electron/shell/browser/api/atom_api_session.cc

861 lines
32 KiB
C++
Raw Normal View History

// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "shell/browser/api/atom_api_session.h"
#include <algorithm>
2016-08-01 11:11:17 +00:00
#include <map>
#include <memory>
2015-06-24 03:59:11 +00:00
#include <string>
#include <utility>
#include <vector>
2015-06-24 03:59:11 +00:00
2015-07-26 08:30:02 +00:00
#include "base/files/file_path.h"
#include "base/guid.h"
2016-01-14 09:31:54 +00:00
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/task/post_task.h"
#include "chrome/browser/browser_process.h"
2015-07-26 08:30:02 +00:00
#include "chrome/common/pref_names.h"
#include "components/download/public/common/download_danger_type.h"
#include "components/download/public/common/download_url_parameters.h"
2016-08-26 22:30:02 +00:00
#include "components/prefs/pref_service.h"
#include "components/prefs/value_map_pref_store.h"
#include "components/proxy_config/proxy_config_dictionary.h"
#include "components/proxy_config/proxy_config_pref_names.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_item_utils.h"
#include "content/public/browser/download_manager_delegate.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/storage_partition.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
chore: bump chromium to 1e9f9a24aa12 (master) (#17880) * chore: bump chromium in DEPS to 1e9f9a24aa12bea9cf194a82a7e249bd1242ec4f * chore: update patches * Make WebContents' theme color a base::Optional<SkColor> https://chromium-review.googlesource.com/c/chromium/src/+/1540022 * update autofill patch for incorrect header includes * Move Shell messages to web_test and rename to BlinkTest. https://chromium-review.googlesource.com/c/chromium/src/+/1525181 * Make PlatformNotificationServiceImpl a KeyedService. https://chromium-review.googlesource.com/c/chromium/src/+/1336150 * Move MediaPlayerId to its own file. https://chromium-review.googlesource.com/c/chromium/src/+/1547057 * Remove net/base/completion_callback.h, which is no longer used https://chromium-review.googlesource.com/c/chromium/src/+/1552821 * AW NS: support file scheme cookies https://chromium-review.googlesource.com/c/chromium/src/+/1533486 * Remove SecurityInfo and adapt remaining consumers https://chromium-review.googlesource.com/c/chromium/src/+/1509455 * Remove deprecated type-specific number to string conversion functions https://chromium-review.googlesource.com/c/chromium/src/+/1545881 * DevTools: Adding new performance histograms for launch of top 4 tools https://chromium-review.googlesource.com/c/chromium/src/+/1506388 * Update include paths for //base/hash/hash.h https://chromium-review.googlesource.com/c/chromium/src/+/1544630 * build: Disable ensure_gn_version gclient hook for mac CI checkout * update patches * use maybe version of v8::String::NewFromTwoByte * bump appveyor image version * fix mac ci hopefully * Convert enum to enum class for MenuAnchorPosition https://chromium-review.googlesource.com/c/chromium/src/+/1530508 * use maybe version of ToObject * RenderViewHost::GetProcess is no longer const * Unrefcount AuthChallengeInfo https://chromium-review.googlesource.com/c/chromium/src/+/1550631 * MenuButtonController takes Button rather than MenuButton https://chromium-review.googlesource.com/c/chromium/src/+/1500935 * add //ui/views_bridge_mac to deps to fix link error * forward declare views::Button in atom::MenuDelegate * more v8 patches * base/{=> hash}/md5.h https://chromium-review.googlesource.com/c/chromium/src/+/1535124 * gfx::{PlatformFontWin => win}::* https://chromium-review.googlesource.com/c/chromium/src/+/1534178 * fix v8 patches * [base] Rename TaskScheduler to ThreadPool https://chromium-review.googlesource.com/c/chromium/src/+/1561552 * use internal_config_base for bytecode_builtins_list_generator avoids windows link errors * FIXME: temporarily disable v8/breakpad integration * FIXME: temporarily disable prevent-will-redirect test * FIXME: disable neon on aarch64 pending crbug.com/953815 * update to account for WebCursor refactor https://chromium-review.googlesource.com/c/chromium/src/+/1562755 * enable stack dumping on appveyor * Revert "FIXME: disable neon on aarch64 pending crbug.com/953815" This reverts commit 57f082026be3d83069f2a2814684abf4dc9e7b53. * fix: remove const qualifiers to match upstream * fix: remove const qualifiers to match upstream in cc files as well * don't throw an error when testing if an object is an object * use non-deprecated Buffer constructor * Remove net::CookieSameSite::DEFAULT_MODE enum value https://chromium-review.googlesource.com/c/chromium/src/+/1567955 * depend on modded dbus-native to work around buffer deprecation https://github.com/sidorares/dbus-native/pull/262 * revert clang roll to fix arm build on linux * fixup! depend on modded dbus-native to work around buffer deprecation need more coffee * update coffee-script * robustify verify-mksnapshot w.r.t. command-line parameters * Revert "robustify verify-mksnapshot w.r.t. command-line parameters" This reverts commit a49af01411f684f6025528d604895c3696e0bc57. * fix mksnapshot by matching args * update patches * TMP: enable rdp on appveyor * Changed ContentBrowserClient::CreateQuotaPermissionContext() to return scoped_refptr. https://chromium-review.googlesource.com/c/chromium/src/+/1569376 * Make content::ResourceType an enum class. https://chromium-review.googlesource.com/c/chromium/src/+/1569345 * fixup! Make content::ResourceType an enum class. * turn off rdp * use net::CompletionRepeatingCallback instead of base::Callback<void(int)> * remove disable_ensure_gn_version_gclient_hook.patch * copy repeating callback instead of std::move * fix lint * add completion_repeating_callback.h include
2019-04-20 17:20:37 +00:00
#include "net/base/completion_repeating_callback.h"
2015-06-24 03:59:11 +00:00
#include "net/base/load_flags.h"
#include "net/http/http_auth_handler_factory.h"
#include "net/http/http_auth_preferences.h"
#include "net/http/http_cache.h"
#include "services/network/network_service.h"
#include "services/network/public/cpp/features.h"
#include "shell/browser/api/atom_api_cookies.h"
#include "shell/browser/api/atom_api_data_pipe_holder.h"
#include "shell/browser/api/atom_api_download_item.h"
#include "shell/browser/api/atom_api_net_log.h"
#include "shell/browser/api/atom_api_protocol.h"
#include "shell/browser/api/atom_api_web_request.h"
#include "shell/browser/atom_browser_context.h"
#include "shell/browser/atom_browser_main_parts.h"
#include "shell/browser/atom_permission_manager.h"
#include "shell/browser/browser.h"
#include "shell/browser/media/media_device_id_salt.h"
#include "shell/browser/net/cert_verifier_client.h"
#include "shell/browser/session_preferences.h"
#include "shell/common/gin_converters/callback_converter.h"
#include "shell/common/gin_converters/content_converter.h"
#include "shell/common/gin_converters/file_path_converter.h"
#include "shell/common/gin_converters/gurl_converter.h"
#include "shell/common/gin_converters/net_converter.h"
#include "shell/common/gin_converters/value_converter.h"
#include "shell/common/gin_helper/dictionary.h"
#include "shell/common/gin_helper/object_template_builder.h"
#include "shell/common/node_includes.h"
#include "shell/common/options_switches.h"
#include "ui/base/l10n/l10n_util.h"
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
#include "shell/browser/extensions/atom_extension_system.h"
#endif
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
#include "chrome/browser/spellchecker/spellcheck_factory.h"
#include "chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h"
#include "chrome/browser/spellchecker/spellcheck_service.h"
#include "components/spellcheck/browser/pref_names.h"
#include "components/spellcheck/common/spellcheck_common.h"
#if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
#include "components/spellcheck/browser/spellcheck_platform.h"
#include "components/spellcheck/common/spellcheck_features.h"
#endif
#endif
using content::BrowserThread;
using content::StoragePartition;
chore: bump chromium to f30828899e4cd7161f6dc6507023f (master) (#20824) * chore: bump chromium in DEPS to 0476932294da8809a19189b9f54cee11d50cc512 * update chromium patches (#20838) * chore: bump chromium in DEPS to 838863f5ec9e8a12132a10bb47be8382ad9756a7 * IsRendererTransferNeededForNavigation went away https://chromium-review.googlesource.com/c/chromium/src/+/1867031 * [arraybuffer] Move the ArrayBuffer implementation from wtf to core https://chromium-review.googlesource.com/c/chromium/src/+/1875731 * URLLoaderRequest new mojo types * context menu enums moved around https://chromium-review.googlesource.com/c/chromium/src/+/1872004 https://chromium-review.googlesource.com/c/chromium/src/+/1876088 https://chromium-review.googlesource.com/c/chromium/src/+/1866520 * chore: bump chromium in DEPS to dc9525d251bf30828899e4cd7161f6dc6507023f * update chromium patches * [WIP] Convert network hints IPC to Mojo https://chromium-review.googlesource.com/c/chromium/src/+/1881967 * jumbo build is no longer supported https://chromium-review.googlesource.com/c/chromium/src/+/1881967 * fix disable-color-correct-rendering * [FIXME] fix printing patch compiles but prob doesn't work * explicitly include ax_enums https://chromium-review.googlesource.com/c/chromium/src/+/1759821 * fixup! [WIP] Convert network hints IPC to Mojo * fix base::span * fix AsarURLLoader to not double-std::move * fix debug build * fix msstl patch * lint * more fix msstl * mooooore fix msstl * fix compile * update backport_fix_msstl_compat_in_ui_events.patch * update msstl compat patch * don't try to build chrome's prefetch predictor * build: fix compilation on windows * Fixup patches for MAS build * Free up disk space for mac debug builds * fix: apply custom site instance only for main frame * Fixup from rebase * Try not generating symbols for mac debug builds * Remove double entry of patch * FIx compile errors * Trigger CI * Set symbol_level to 1 for mac debug builds
2019-11-05 23:41:20 +00:00
namespace predictors {
// NOTE(nornagon): this is copied from
// //chrome/browser/predictors/resource_prefetch_predictor.cc we don't need
// anything in that file other than this constructor. Without it we get a link
// error. Probably upstream the constructor should be moved to
// preconnect_manager.cc.
PreconnectRequest::PreconnectRequest(
const GURL& origin,
int num_sockets,
const net::NetworkIsolationKey& network_isolation_key)
: origin(origin),
num_sockets(num_sockets),
network_isolation_key(network_isolation_key) {
DCHECK_GE(num_sockets, 0);
}
} // namespace predictors
namespace {
struct ClearStorageDataOptions {
GURL origin;
2016-03-08 04:40:10 +00:00
uint32_t storage_types = StoragePartition::REMOVE_DATA_MASK_ALL;
uint32_t quota_types = StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL;
};
2016-03-08 04:40:10 +00:00
uint32_t GetStorageMask(const std::vector<std::string>& storage_types) {
uint32_t storage_mask = 0;
for (const auto& it : storage_types) {
2015-12-07 11:56:23 +00:00
auto type = base::ToLowerASCII(it);
if (type == "appcache")
storage_mask |= StoragePartition::REMOVE_DATA_MASK_APPCACHE;
else if (type == "cookies")
storage_mask |= StoragePartition::REMOVE_DATA_MASK_COOKIES;
else if (type == "filesystem")
storage_mask |= StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS;
else if (type == "indexdb")
storage_mask |= StoragePartition::REMOVE_DATA_MASK_INDEXEDDB;
else if (type == "localstorage")
storage_mask |= StoragePartition::REMOVE_DATA_MASK_LOCAL_STORAGE;
else if (type == "shadercache")
storage_mask |= StoragePartition::REMOVE_DATA_MASK_SHADER_CACHE;
else if (type == "websql")
storage_mask |= StoragePartition::REMOVE_DATA_MASK_WEBSQL;
else if (type == "serviceworkers")
storage_mask |= StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS;
2018-04-13 17:03:16 +00:00
else if (type == "cachestorage")
storage_mask |= StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE;
}
return storage_mask;
}
2016-03-08 04:40:10 +00:00
uint32_t GetQuotaMask(const std::vector<std::string>& quota_types) {
uint32_t quota_mask = 0;
for (const auto& it : quota_types) {
2015-12-07 11:56:23 +00:00
auto type = base::ToLowerASCII(it);
if (type == "temporary")
quota_mask |= StoragePartition::QUOTA_MANAGED_STORAGE_MASK_TEMPORARY;
else if (type == "persistent")
quota_mask |= StoragePartition::QUOTA_MANAGED_STORAGE_MASK_PERSISTENT;
else if (type == "syncable")
quota_mask |= StoragePartition::QUOTA_MANAGED_STORAGE_MASK_SYNCABLE;
}
return quota_mask;
}
} // namespace
namespace gin {
2018-04-18 01:55:30 +00:00
template <>
struct Converter<ClearStorageDataOptions> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
ClearStorageDataOptions* out) {
gin_helper::Dictionary options;
if (!ConvertFromV8(isolate, val, &options))
return false;
options.Get("origin", &out->origin);
std::vector<std::string> types;
if (options.Get("storages", &types))
out->storage_types = GetStorageMask(types);
if (options.Get("quotas", &types))
out->quota_types = GetQuotaMask(types);
return true;
}
};
} // namespace gin
namespace electron {
namespace api {
2015-06-24 03:59:11 +00:00
namespace {
const char kPersistPrefix[] = "persist:";
2016-08-01 11:11:17 +00:00
// Referenced session objects.
std::map<uint32_t, v8::Global<v8::Value>> g_sessions;
2016-08-01 11:11:17 +00:00
void DownloadIdCallback(content::DownloadManager* download_manager,
const base::FilePath& path,
const std::vector<GURL>& url_chain,
const std::string& mime_type,
int64_t offset,
int64_t length,
const std::string& last_modified,
const std::string& etag,
const base::Time& start_time,
uint32_t id) {
2016-11-24 15:16:39 +00:00
download_manager->CreateDownloadItem(
base::GenerateGUID(), id, path, path, url_chain, GURL(), GURL(), GURL(),
GURL(), base::nullopt, mime_type, mime_type, start_time, base::Time(),
etag, last_modified, offset, length, std::string(),
download::DownloadItem::INTERRUPTED,
download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
download::DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT, false, base::Time(),
false, std::vector<download::DownloadItem::ReceivedSlice>());
}
void DestroyGlobalHandle(v8::Isolate* isolate,
const v8::Global<v8::Value>& global_handle) {
v8::Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
if (!global_handle.IsEmpty()) {
v8::Local<v8::Value> local_handle = global_handle.Get(isolate);
chore: bump chromium to 1e9f9a24aa12 (master) (#17880) * chore: bump chromium in DEPS to 1e9f9a24aa12bea9cf194a82a7e249bd1242ec4f * chore: update patches * Make WebContents' theme color a base::Optional<SkColor> https://chromium-review.googlesource.com/c/chromium/src/+/1540022 * update autofill patch for incorrect header includes * Move Shell messages to web_test and rename to BlinkTest. https://chromium-review.googlesource.com/c/chromium/src/+/1525181 * Make PlatformNotificationServiceImpl a KeyedService. https://chromium-review.googlesource.com/c/chromium/src/+/1336150 * Move MediaPlayerId to its own file. https://chromium-review.googlesource.com/c/chromium/src/+/1547057 * Remove net/base/completion_callback.h, which is no longer used https://chromium-review.googlesource.com/c/chromium/src/+/1552821 * AW NS: support file scheme cookies https://chromium-review.googlesource.com/c/chromium/src/+/1533486 * Remove SecurityInfo and adapt remaining consumers https://chromium-review.googlesource.com/c/chromium/src/+/1509455 * Remove deprecated type-specific number to string conversion functions https://chromium-review.googlesource.com/c/chromium/src/+/1545881 * DevTools: Adding new performance histograms for launch of top 4 tools https://chromium-review.googlesource.com/c/chromium/src/+/1506388 * Update include paths for //base/hash/hash.h https://chromium-review.googlesource.com/c/chromium/src/+/1544630 * build: Disable ensure_gn_version gclient hook for mac CI checkout * update patches * use maybe version of v8::String::NewFromTwoByte * bump appveyor image version * fix mac ci hopefully * Convert enum to enum class for MenuAnchorPosition https://chromium-review.googlesource.com/c/chromium/src/+/1530508 * use maybe version of ToObject * RenderViewHost::GetProcess is no longer const * Unrefcount AuthChallengeInfo https://chromium-review.googlesource.com/c/chromium/src/+/1550631 * MenuButtonController takes Button rather than MenuButton https://chromium-review.googlesource.com/c/chromium/src/+/1500935 * add //ui/views_bridge_mac to deps to fix link error * forward declare views::Button in atom::MenuDelegate * more v8 patches * base/{=> hash}/md5.h https://chromium-review.googlesource.com/c/chromium/src/+/1535124 * gfx::{PlatformFontWin => win}::* https://chromium-review.googlesource.com/c/chromium/src/+/1534178 * fix v8 patches * [base] Rename TaskScheduler to ThreadPool https://chromium-review.googlesource.com/c/chromium/src/+/1561552 * use internal_config_base for bytecode_builtins_list_generator avoids windows link errors * FIXME: temporarily disable v8/breakpad integration * FIXME: temporarily disable prevent-will-redirect test * FIXME: disable neon on aarch64 pending crbug.com/953815 * update to account for WebCursor refactor https://chromium-review.googlesource.com/c/chromium/src/+/1562755 * enable stack dumping on appveyor * Revert "FIXME: disable neon on aarch64 pending crbug.com/953815" This reverts commit 57f082026be3d83069f2a2814684abf4dc9e7b53. * fix: remove const qualifiers to match upstream * fix: remove const qualifiers to match upstream in cc files as well * don't throw an error when testing if an object is an object * use non-deprecated Buffer constructor * Remove net::CookieSameSite::DEFAULT_MODE enum value https://chromium-review.googlesource.com/c/chromium/src/+/1567955 * depend on modded dbus-native to work around buffer deprecation https://github.com/sidorares/dbus-native/pull/262 * revert clang roll to fix arm build on linux * fixup! depend on modded dbus-native to work around buffer deprecation need more coffee * update coffee-script * robustify verify-mksnapshot w.r.t. command-line parameters * Revert "robustify verify-mksnapshot w.r.t. command-line parameters" This reverts commit a49af01411f684f6025528d604895c3696e0bc57. * fix mksnapshot by matching args * update patches * TMP: enable rdp on appveyor * Changed ContentBrowserClient::CreateQuotaPermissionContext() to return scoped_refptr. https://chromium-review.googlesource.com/c/chromium/src/+/1569376 * Make content::ResourceType an enum class. https://chromium-review.googlesource.com/c/chromium/src/+/1569345 * fixup! Make content::ResourceType an enum class. * turn off rdp * use net::CompletionRepeatingCallback instead of base::Callback<void(int)> * remove disable_ensure_gn_version_gclient_hook.patch * copy repeating callback instead of std::move * fix lint * add completion_repeating_callback.h include
2019-04-20 17:20:37 +00:00
v8::Local<v8::Object> object;
if (local_handle->IsObject() &&
local_handle->ToObject(isolate->GetCurrentContext()).ToLocal(&object)) {
void* ptr = object->GetAlignedPointerFromInternalField(0);
if (!ptr)
return;
delete static_cast<mate::WrappableBase*>(ptr);
object->SetAlignedPointerInInternalField(0, nullptr);
}
}
}
2015-06-24 03:59:11 +00:00
} // namespace
2016-04-25 01:17:54 +00:00
Session::Session(v8::Isolate* isolate, AtomBrowserContext* browser_context)
: network_emulation_token_(base::UnguessableToken::Create()),
browser_context_(browser_context) {
// Observe DownloadManager to get download notifications.
2018-04-18 01:55:30 +00:00
content::BrowserContext::GetDownloadManager(browser_context)
->AddObserver(this);
2016-04-25 01:17:54 +00:00
new SessionPreferences(browser_context);
protocol_.Reset(isolate, Protocol::Create(isolate, browser_context).ToV8());
2016-04-25 01:17:54 +00:00
Init(isolate);
AttachAsUserData(browser_context);
}
Session::~Session() {
2018-04-18 01:55:30 +00:00
content::BrowserContext::GetDownloadManager(browser_context())
->RemoveObserver(this);
// TODO(zcbenz): Now since URLRequestContextGetter is gone, is this still
// needed?
// Refs https://github.com/electron/electron/pull/12305.
DestroyGlobalHandle(isolate(), cookies_);
DestroyGlobalHandle(isolate(), protocol_);
DestroyGlobalHandle(isolate(), net_log_);
2016-08-01 11:11:17 +00:00
g_sessions.erase(weak_map_id());
}
void Session::OnDownloadCreated(content::DownloadManager* manager,
download::DownloadItem* item) {
if (item->IsSavePackageDownload())
2015-10-14 04:41:31 +00:00
return;
2016-04-25 01:17:54 +00:00
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
auto handle = DownloadItem::Create(isolate(), item);
if (item->GetState() == download::DownloadItem::INTERRUPTED)
handle->SetSavePath(item->GetTargetFilePath());
content::WebContents* web_contents =
content::DownloadItemUtils::GetWebContents(item);
bool prevent_default = Emit("will-download", handle, web_contents);
if (prevent_default) {
item->Cancel(true);
item->Remove();
}
}
v8::Local<v8::Promise> Session::ResolveProxy(gin_helper::Arguments* args) {
v8::Isolate* isolate = args->isolate();
gin_helper::Promise<std::string> promise(isolate);
v8::Local<v8::Promise> handle = promise.GetHandle();
GURL url;
args->GetNext(&url);
browser_context_->GetResolveProxyHelper()->ResolveProxy(
url, base::BindOnce(gin_helper::Promise<std::string>::ResolvePromise,
std::move(promise)));
return handle;
2015-06-24 03:59:11 +00:00
}
v8::Local<v8::Promise> Session::GetCacheSize() {
auto* isolate = v8::Isolate::GetCurrent();
gin_helper::Promise<int64_t> promise(isolate);
auto handle = promise.GetHandle();
content::BrowserContext::GetDefaultStoragePartition(browser_context_.get())
->GetNetworkContext()
->ComputeHttpCacheSize(
base::Time(), base::Time::Max(),
base::BindOnce(
[](gin_helper::Promise<int64_t> promise, bool is_upper_bound,
int64_t size_or_error) {
if (size_or_error < 0) {
promise.RejectWithErrorMessage(
net::ErrorToString(size_or_error));
} else {
promise.Resolve(size_or_error);
}
},
std::move(promise)));
return handle;
}
v8::Local<v8::Promise> Session::ClearCache() {
auto* isolate = v8::Isolate::GetCurrent();
gin_helper::Promise<void> promise(isolate);
auto handle = promise.GetHandle();
content::BrowserContext::GetDefaultStoragePartition(browser_context_.get())
->GetNetworkContext()
->ClearHttpCache(base::Time(), base::Time::Max(), nullptr,
base::BindOnce(gin_helper::Promise<void>::ResolvePromise,
std::move(promise)));
return handle;
}
v8::Local<v8::Promise> Session::ClearStorageData(gin_helper::Arguments* args) {
v8::Isolate* isolate = args->isolate();
gin_helper::Promise<void> promise(isolate);
v8::Local<v8::Promise> handle = promise.GetHandle();
ClearStorageDataOptions options;
args->GetNext(&options);
auto* storage_partition =
content::BrowserContext::GetStoragePartition(browser_context(), nullptr);
if (options.storage_types & StoragePartition::REMOVE_DATA_MASK_COOKIES) {
// Reset media device id salt when cookies are cleared.
// https://w3c.github.io/mediacapture-main/#dom-mediadeviceinfo-deviceid
MediaDeviceIDSalt::Reset(browser_context()->prefs());
}
storage_partition->ClearData(
options.storage_types, options.quota_types, options.origin, base::Time(),
base::Time::Max(),
base::BindOnce(gin_helper::Promise<void>::ResolvePromise,
std::move(promise)));
return handle;
}
2016-01-12 15:28:12 +00:00
void Session::FlushStorageData() {
auto* storage_partition =
2016-01-12 15:28:12 +00:00
content::BrowserContext::GetStoragePartition(browser_context(), nullptr);
storage_partition->Flush();
}
v8::Local<v8::Promise> Session::SetProxy(gin_helper::Arguments* args) {
v8::Isolate* isolate = args->isolate();
gin_helper::Promise<void> promise(isolate);
v8::Local<v8::Promise> handle = promise.GetHandle();
gin_helper::Dictionary options;
args->GetNext(&options);
if (!browser_context_->in_memory_pref_store()) {
promise.Resolve();
return handle;
}
std::string proxy_rules, bypass_list, pac_url;
options.Get("pacScript", &pac_url);
options.Get("proxyRules", &proxy_rules);
options.Get("proxyBypassRules", &bypass_list);
// pacScript takes precedence over proxyRules.
if (!pac_url.empty()) {
browser_context_->in_memory_pref_store()->SetValue(
proxy_config::prefs::kProxy,
std::make_unique<base::Value>(ProxyConfigDictionary::CreatePacScript(
pac_url, true /* pac_mandatory */)),
WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
} else {
browser_context_->in_memory_pref_store()->SetValue(
proxy_config::prefs::kProxy,
std::make_unique<base::Value>(ProxyConfigDictionary::CreateFixedServers(
proxy_rules, bypass_list)),
WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
}
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(gin_helper::Promise<void>::ResolvePromise,
std::move(promise)));
return handle;
2015-07-16 14:36:48 +00:00
}
2015-07-30 02:38:04 +00:00
void Session::SetDownloadPath(const base::FilePath& path) {
2018-04-18 01:55:30 +00:00
browser_context_->prefs()->SetFilePath(prefs::kDownloadDefaultDirectory,
path);
2015-07-26 08:30:02 +00:00
}
void Session::EnableNetworkEmulation(const gin_helper::Dictionary& options) {
auto conditions = network::mojom::NetworkConditions::New();
options.Get("offline", &conditions->offline);
options.Get("downloadThroughput", &conditions->download_throughput);
options.Get("uploadThroughput", &conditions->upload_throughput);
double latency = 0.0;
if (options.Get("latency", &latency) && latency) {
conditions->latency = base::TimeDelta::FromMillisecondsD(latency);
}
auto* network_context = content::BrowserContext::GetDefaultStoragePartition(
browser_context_.get())
->GetNetworkContext();
network_context->SetNetworkConditions(network_emulation_token_,
std::move(conditions));
}
void Session::DisableNetworkEmulation() {
auto* network_context = content::BrowserContext::GetDefaultStoragePartition(
browser_context_.get())
->GetNetworkContext();
network_context->SetNetworkConditions(
network_emulation_token_, network::mojom::NetworkConditions::New());
}
2015-11-18 03:45:15 +00:00
void Session::SetCertVerifyProc(v8::Local<v8::Value> val,
gin_helper::Arguments* args) {
CertVerifierClient::CertVerifyProc proc;
if (!(val->IsNull() || gin::ConvertFromV8(args->isolate(), val, &proc))) {
2015-11-18 03:17:08 +00:00
args->ThrowError("Must pass null or function");
return;
}
mojo::PendingRemote<network::mojom::CertVerifierClient>
cert_verifier_client_remote;
if (proc) {
mojo::MakeSelfOwnedReceiver(
std::make_unique<CertVerifierClient>(proc),
cert_verifier_client_remote.InitWithNewPipeAndPassReceiver());
}
content::BrowserContext::GetDefaultStoragePartition(browser_context_.get())
->GetNetworkContext()
->SetCertVerifierClient(std::move(cert_verifier_client_remote));
// This causes the cert verifier cache to be cleared.
content::GetNetworkService()->OnCertDBChanged();
2015-11-18 03:17:08 +00:00
}
void Session::SetPermissionRequestHandler(v8::Local<v8::Value> val,
gin_helper::Arguments* args) {
auto* permission_manager = static_cast<AtomPermissionManager*>(
browser_context()->GetPermissionControllerDelegate());
if (val->IsNull()) {
permission_manager->SetPermissionRequestHandler(
AtomPermissionManager::RequestHandler());
return;
}
auto handler = std::make_unique<AtomPermissionManager::RequestHandler>();
if (!gin::ConvertFromV8(args->isolate(), val, handler.get())) {
args->ThrowError("Must pass null or function");
return;
}
permission_manager->SetPermissionRequestHandler(base::BindRepeating(
[](AtomPermissionManager::RequestHandler* handler,
content::WebContents* web_contents,
content::PermissionType permission_type,
AtomPermissionManager::StatusCallback callback,
const base::Value& details) {
handler->Run(web_contents, permission_type,
base::AdaptCallbackForRepeating(std::move(callback)),
details);
},
base::Owned(std::move(handler))));
}
void Session::SetPermissionCheckHandler(v8::Local<v8::Value> val,
gin_helper::Arguments* args) {
AtomPermissionManager::CheckHandler handler;
if (!(val->IsNull() || gin::ConvertFromV8(args->isolate(), val, &handler))) {
args->ThrowError("Must pass null or function");
return;
}
auto* permission_manager = static_cast<AtomPermissionManager*>(
browser_context()->GetPermissionControllerDelegate());
permission_manager->SetPermissionCheckHandler(handler);
}
v8::Local<v8::Promise> Session::ClearHostResolverCache(
gin_helper::Arguments* args) {
v8::Isolate* isolate = args->isolate();
gin_helper::Promise<void> promise(isolate);
v8::Local<v8::Promise> handle = promise.GetHandle();
content::BrowserContext::GetDefaultStoragePartition(browser_context_.get())
->GetNetworkContext()
->ClearHostCache(nullptr,
base::BindOnce(gin_helper::Promise<void>::ResolvePromise,
std::move(promise)));
return handle;
}
v8::Local<v8::Promise> Session::ClearAuthCache() {
auto* isolate = v8::Isolate::GetCurrent();
gin_helper::Promise<void> promise(isolate);
v8::Local<v8::Promise> handle = promise.GetHandle();
content::BrowserContext::GetDefaultStoragePartition(browser_context_.get())
->GetNetworkContext()
->ClearHttpAuthCache(
base::Time(),
base::BindOnce(gin_helper::Promise<void>::ResolvePromise,
std::move(promise)));
2016-11-30 16:35:15 +00:00
return handle;
2016-11-30 16:35:15 +00:00
}
void Session::AllowNTLMCredentialsForDomains(const std::string& domains) {
network::mojom::HttpAuthDynamicParamsPtr auth_dynamic_params =
network::mojom::HttpAuthDynamicParams::New();
auth_dynamic_params->server_allowlist = domains;
content::GetNetworkService()->ConfigureHttpAuthPrefs(
std::move(auth_dynamic_params));
}
void Session::SetUserAgent(const std::string& user_agent,
gin_helper::Arguments* args) {
browser_context_->SetUserAgent(user_agent);
content::BrowserContext::GetDefaultStoragePartition(browser_context_.get())
->GetNetworkContext()
->SetUserAgent(user_agent);
}
std::string Session::GetUserAgent() {
return browser_context_->GetUserAgent();
}
v8::Local<v8::Promise> Session::GetBlobData(v8::Isolate* isolate,
const std::string& uuid) {
gin::Handle<DataPipeHolder> holder = DataPipeHolder::From(isolate, uuid);
if (holder.IsEmpty()) {
gin_helper::Promise<v8::Local<v8::Value>> promise(isolate);
promise.RejectWithErrorMessage("Could not get blob data handle");
return promise.GetHandle();
}
return holder->ReadAll(isolate);
}
void Session::DownloadURL(const GURL& url) {
auto* download_manager =
content::BrowserContext::GetDownloadManager(browser_context());
auto download_params = std::make_unique<download::DownloadUrlParameters>(
url, MISSING_TRAFFIC_ANNOTATION);
download_manager->DownloadUrl(std::move(download_params));
}
void Session::CreateInterruptedDownload(const gin_helper::Dictionary& options) {
int64_t offset = 0, length = 0;
double start_time = base::Time::Now().ToDoubleT();
std::string mime_type, last_modified, etag;
base::FilePath path;
std::vector<GURL> url_chain;
options.Get("path", &path);
options.Get("urlChain", &url_chain);
options.Get("mimeType", &mime_type);
options.Get("offset", &offset);
options.Get("length", &length);
options.Get("lastModified", &last_modified);
options.Get("eTag", &etag);
options.Get("startTime", &start_time);
2016-12-07 07:28:53 +00:00
if (path.empty() || url_chain.empty() || length == 0) {
isolate()->ThrowException(v8::Exception::Error(gin::StringToV8(
2016-12-07 07:28:53 +00:00
isolate(), "Must pass non-empty path, urlChain and length.")));
return;
2016-12-07 07:28:53 +00:00
}
if (offset >= length) {
isolate()->ThrowException(v8::Exception::Error(gin::StringToV8(
2016-12-07 07:28:53 +00:00
isolate(), "Must pass an offset value less than length.")));
return;
}
auto* download_manager =
content::BrowserContext::GetDownloadManager(browser_context());
download_manager->GetDelegate()->GetNextId(base::BindRepeating(
&DownloadIdCallback, download_manager, path, url_chain, mime_type, offset,
length, last_modified, etag, base::Time::FromDoubleT(start_time)));
}
void Session::SetPreloads(
const std::vector<base::FilePath::StringType>& preloads) {
auto* prefs = SessionPreferences::FromBrowserContext(browser_context());
DCHECK(prefs);
prefs->set_preloads(preloads);
}
2017-12-05 02:50:06 +00:00
std::vector<base::FilePath::StringType> Session::GetPreloads() const {
auto* prefs = SessionPreferences::FromBrowserContext(browser_context());
DCHECK(prefs);
return prefs->preloads();
}
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
void Session::LoadChromeExtension(const base::FilePath extension_path) {
auto* extension_system = static_cast<extensions::AtomExtensionSystem*>(
extensions::ExtensionSystem::Get(browser_context()));
extension_system->LoadExtension(extension_path);
}
#endif
v8::Local<v8::Value> Session::Cookies(v8::Isolate* isolate) {
if (cookies_.IsEmpty()) {
auto handle = Cookies::Create(isolate, browser_context());
cookies_.Reset(isolate, handle.ToV8());
}
return v8::Local<v8::Value>::New(isolate, cookies_);
}
v8::Local<v8::Value> Session::Protocol(v8::Isolate* isolate) {
return v8::Local<v8::Value>::New(isolate, protocol_);
}
2015-12-01 04:52:22 +00:00
v8::Local<v8::Value> Session::WebRequest(v8::Isolate* isolate) {
if (web_request_.IsEmpty()) {
auto handle = WebRequest::Create(isolate, browser_context());
web_request_.Reset(isolate, handle.ToV8());
2015-12-01 04:52:22 +00:00
}
return v8::Local<v8::Value>::New(isolate, web_request_);
}
v8::Local<v8::Value> Session::NetLog(v8::Isolate* isolate) {
if (net_log_.IsEmpty()) {
auto handle = electron::api::NetLog::Create(isolate, browser_context());
net_log_.Reset(isolate, handle.ToV8());
}
return v8::Local<v8::Value>::New(isolate, net_log_);
}
static void StartPreconnectOnUI(
scoped_refptr<AtomBrowserContext> browser_context,
const GURL& url,
int num_sockets_to_preconnect) {
std::vector<predictors::PreconnectRequest> requests = {
{url.GetOrigin(), num_sockets_to_preconnect, net::NetworkIsolationKey()}};
browser_context->GetPreconnectManager()->Start(url, requests);
}
void Session::Preconnect(const gin_helper::Dictionary& options,
gin_helper::Arguments* args) {
GURL url;
if (!options.Get("url", &url) || !url.is_valid()) {
args->ThrowError("Must pass non-empty valid url to session.preconnect.");
return;
}
int num_sockets_to_preconnect = 1;
if (options.Get("numSockets", &num_sockets_to_preconnect)) {
const int kMinSocketsToPreconnect = 1;
const int kMaxSocketsToPreconnect = 6;
if (num_sockets_to_preconnect < kMinSocketsToPreconnect ||
num_sockets_to_preconnect > kMaxSocketsToPreconnect) {
args->ThrowError(
base::StringPrintf("numSocketsToPreconnect is outside range [%d,%d]",
kMinSocketsToPreconnect, kMaxSocketsToPreconnect));
return;
}
}
DCHECK_GT(num_sockets_to_preconnect, 0);
base::PostTask(
FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(&StartPreconnectOnUI, base::RetainedRef(browser_context_),
url, num_sockets_to_preconnect));
}
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
base::Value Session::GetSpellCheckerLanguages() {
return browser_context_->prefs()
->Get(spellcheck::prefs::kSpellCheckDictionaries)
->Clone();
}
void Session::SetSpellCheckerLanguages(
gin_helper::ErrorThrower thrower,
const std::vector<std::string>& languages) {
base::ListValue language_codes;
for (const std::string& lang : languages) {
std::string code = spellcheck::GetCorrespondingSpellCheckLanguage(lang);
if (code.empty()) {
thrower.ThrowError("Invalid language code provided: \"" + lang +
"\" is not a valid language code");
return;
}
language_codes.AppendString(code);
}
browser_context_->prefs()->Set(spellcheck::prefs::kSpellCheckDictionaries,
language_codes);
}
void SetSpellCheckerDictionaryDownloadURL(gin_helper::ErrorThrower thrower,
const GURL& url) {
if (!url.is_valid()) {
thrower.ThrowError(
"The URL you provided to setSpellCheckerDictionaryDownloadURL is not a "
"valid URL");
return;
}
SpellcheckHunspellDictionary::SetDownloadURLForTesting(url);
}
bool Session::AddWordToSpellCheckerDictionary(const std::string& word) {
#if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
if (spellcheck::UseBrowserSpellChecker()) {
spellcheck_platform::AddWord(base::UTF8ToUTF16(word));
}
#endif
SpellcheckService* spellcheck =
SpellcheckServiceFactory::GetForContext(browser_context_.get());
if (!spellcheck)
return false;
return spellcheck->GetCustomDictionary()->AddWord(word);
}
#endif
// static
gin::Handle<Session> Session::CreateFrom(v8::Isolate* isolate,
AtomBrowserContext* browser_context) {
auto* existing = TrackableObject::FromWrappedClass(isolate, browser_context);
2015-06-24 07:37:04 +00:00
if (existing)
return gin::CreateHandle(isolate, static_cast<Session*>(existing));
2015-06-24 07:37:04 +00:00
2018-04-18 01:55:30 +00:00
auto handle =
gin::CreateHandle(isolate, new Session(isolate, browser_context));
2016-08-01 11:11:17 +00:00
// The Sessions should never be garbage collected, since the common pattern is
// to use partition strings, instead of using the Session object directly.
g_sessions[handle->weak_map_id()] =
v8::Global<v8::Value>(isolate, handle.ToV8());
2016-08-01 11:11:17 +00:00
2015-09-01 10:02:14 +00:00
return handle;
}
// static
gin::Handle<Session> Session::FromPartition(v8::Isolate* isolate,
const std::string& partition,
base::DictionaryValue options) {
scoped_refptr<AtomBrowserContext> browser_context;
if (partition.empty()) {
browser_context = AtomBrowserContext::From("", false, std::move(options));
} else if (base::StartsWith(partition, kPersistPrefix,
base::CompareCase::SENSITIVE)) {
std::string name = partition.substr(8);
browser_context = AtomBrowserContext::From(name, false, std::move(options));
} else {
browser_context =
AtomBrowserContext::From(partition, true, std::move(options));
}
return CreateFrom(isolate, browser_context.get());
}
// static
void Session::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(gin::StringToV8(isolate, "Session"));
gin_helper::Destroyable::MakeDestroyable(isolate, prototype);
gin_helper::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.SetMethod("resolveProxy", &Session::ResolveProxy)
.SetMethod("getCacheSize", &Session::GetCacheSize)
.SetMethod("clearCache", &Session::ClearCache)
.SetMethod("clearStorageData", &Session::ClearStorageData)
2016-01-12 15:28:12 +00:00
.SetMethod("flushStorageData", &Session::FlushStorageData)
.SetMethod("setProxy", &Session::SetProxy)
.SetMethod("setDownloadPath", &Session::SetDownloadPath)
.SetMethod("enableNetworkEmulation", &Session::EnableNetworkEmulation)
.SetMethod("disableNetworkEmulation", &Session::DisableNetworkEmulation)
.SetMethod("setCertificateVerifyProc", &Session::SetCertVerifyProc)
.SetMethod("setPermissionRequestHandler",
&Session::SetPermissionRequestHandler)
.SetMethod("setPermissionCheckHandler",
&Session::SetPermissionCheckHandler)
.SetMethod("clearHostResolverCache", &Session::ClearHostResolverCache)
2016-11-30 16:35:15 +00:00
.SetMethod("clearAuthCache", &Session::ClearAuthCache)
.SetMethod("allowNTLMCredentialsForDomains",
&Session::AllowNTLMCredentialsForDomains)
.SetMethod("setUserAgent", &Session::SetUserAgent)
.SetMethod("getUserAgent", &Session::GetUserAgent)
.SetMethod("getBlobData", &Session::GetBlobData)
.SetMethod("downloadURL", &Session::DownloadURL)
.SetMethod("createInterruptedDownload",
&Session::CreateInterruptedDownload)
.SetMethod("setPreloads", &Session::SetPreloads)
.SetMethod("getPreloads", &Session::GetPreloads)
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
.SetMethod("loadChromeExtension", &Session::LoadChromeExtension)
#endif
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
.SetMethod("getSpellCheckerLanguages", &Session::GetSpellCheckerLanguages)
.SetMethod("setSpellCheckerLanguages", &Session::SetSpellCheckerLanguages)
.SetProperty("availableSpellCheckerLanguages",
&spellcheck::SpellCheckLanguages)
.SetMethod("setSpellCheckerDictionaryDownloadURL",
&SetSpellCheckerDictionaryDownloadURL)
.SetMethod("addWordToSpellCheckerDictionary",
&Session::AddWordToSpellCheckerDictionary)
#endif
.SetMethod("preconnect", &Session::Preconnect)
2015-12-01 04:52:22 +00:00
.SetProperty("cookies", &Session::Cookies)
.SetProperty("netLog", &Session::NetLog)
.SetProperty("protocol", &Session::Protocol)
2015-12-01 04:52:22 +00:00
.SetProperty("webRequest", &Session::WebRequest);
}
} // namespace api
} // namespace electron
2015-09-01 10:02:14 +00:00
namespace {
using electron::api::Cookies;
using electron::api::NetLog;
using electron::api::Protocol;
using electron::api::Session;
2016-08-02 11:38:35 +00:00
2018-04-18 01:55:30 +00:00
v8::Local<v8::Value> FromPartition(const std::string& partition,
gin_helper::Arguments* args) {
if (!electron::Browser::Get()->is_ready()) {
2016-07-12 11:21:59 +00:00
args->ThrowError("Session can only be received when app is ready");
return v8::Null(args->isolate());
}
2016-07-12 12:53:19 +00:00
base::DictionaryValue options;
args->GetNext(&options);
return Session::FromPartition(args->isolate(), partition, std::move(options))
.ToV8();
2016-07-12 11:21:59 +00:00
}
2018-04-18 01:55:30 +00:00
void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
2015-09-01 10:02:14 +00:00
v8::Isolate* isolate = context->GetIsolate();
gin_helper::Dictionary dict(isolate, exports);
dict.Set(
"Session",
Session::GetConstructor(isolate)->GetFunction(context).ToLocalChecked());
dict.Set(
"Cookies",
Cookies::GetConstructor(isolate)->GetFunction(context).ToLocalChecked());
dict.Set(
"NetLog",
NetLog::GetConstructor(isolate)->GetFunction(context).ToLocalChecked());
dict.Set(
"Protocol",
Protocol::GetConstructor(isolate)->GetFunction(context).ToLocalChecked());
2016-07-12 11:21:59 +00:00
dict.SetMethod("fromPartition", &FromPartition);
2015-09-01 10:02:14 +00:00
}
} // namespace
NODE_LINKED_MODULE_CONTEXT_AWARE(atom_browser_session, Initialize)