2015-06-16 09:23:29 +00:00
|
|
|
// Copyright (c) 2015 GitHub, Inc.
|
|
|
|
// Use of this source code is governed by the MIT license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
2020-02-04 20:19:40 +00:00
|
|
|
#include "shell/browser/api/electron_api_session.h"
|
2015-06-16 09:23:29 +00:00
|
|
|
|
2019-08-26 16:47:32 +00:00
|
|
|
#include <algorithm>
|
2016-08-01 11:11:17 +00:00
|
|
|
#include <map>
|
2018-09-13 00:25:56 +00:00
|
|
|
#include <memory>
|
2020-02-10 22:08:53 +00:00
|
|
|
#include <set>
|
2015-06-24 03:59:11 +00:00
|
|
|
#include <string>
|
2018-09-13 00:25:56 +00:00
|
|
|
#include <utility>
|
2015-07-13 22:13:17 +00:00
|
|
|
#include <vector>
|
2015-06-24 03:59:11 +00:00
|
|
|
|
2019-12-19 13:53:49 +00:00
|
|
|
#include "base/command_line.h"
|
2015-07-26 08:30:02 +00:00
|
|
|
#include "base/files/file_path.h"
|
2016-04-18 04:59:15 +00:00
|
|
|
#include "base/guid.h"
|
2016-01-14 09:31:54 +00:00
|
|
|
#include "base/strings/string_number_conversions.h"
|
2015-07-02 14:12:18 +00:00
|
|
|
#include "base/strings/string_util.h"
|
2019-01-12 01:00:43 +00:00
|
|
|
#include "base/task/post_task.h"
|
2018-01-02 12:03:46 +00:00
|
|
|
#include "chrome/browser/browser_process.h"
|
2020-09-23 20:22:10 +00:00
|
|
|
#include "chrome/common/chrome_switches.h"
|
2015-07-26 08:30:02 +00:00
|
|
|
#include "chrome/common/pref_names.h"
|
2018-04-10 15:58:49 +00:00
|
|
|
#include "components/download/public/common/download_danger_type.h"
|
2019-08-29 03:27:20 +00:00
|
|
|
#include "components/download/public/common/download_url_parameters.h"
|
2016-08-26 22:30:02 +00:00
|
|
|
#include "components/prefs/pref_service.h"
|
2018-10-04 18:08:56 +00:00
|
|
|
#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"
|
2020-10-27 06:50:06 +00:00
|
|
|
#include "components/proxy_config/proxy_prefs.h"
|
2019-01-12 01:00:43 +00:00
|
|
|
#include "content/public/browser/browser_task_traits.h"
|
2015-06-25 08:43:01 +00:00
|
|
|
#include "content/public/browser/browser_thread.h"
|
2018-04-10 15:29:26 +00:00
|
|
|
#include "content/public/browser/download_item_utils.h"
|
2016-11-18 10:43:43 +00:00
|
|
|
#include "content/public/browser/download_manager_delegate.h"
|
2019-05-29 23:43:06 +00:00
|
|
|
#include "content/public/browser/network_service_instance.h"
|
2015-06-25 08:43:01 +00:00
|
|
|
#include "content/public/browser/storage_partition.h"
|
2020-05-19 17:18:12 +00:00
|
|
|
#include "gin/arguments.h"
|
2019-09-18 19:58:00 +00:00
|
|
|
#include "mojo/public/cpp/bindings/pending_remote.h"
|
|
|
|
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
|
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"
|
2016-05-23 05:29:55 +00:00
|
|
|
#include "net/http/http_auth_handler_factory.h"
|
|
|
|
#include "net/http/http_auth_preferences.h"
|
2018-10-04 18:08:56 +00:00
|
|
|
#include "net/http/http_cache.h"
|
2020-06-04 11:05:37 +00:00
|
|
|
#include "net/http/http_util.h"
|
2019-06-28 22:22:23 +00:00
|
|
|
#include "services/network/network_service.h"
|
2019-04-23 21:39:21 +00:00
|
|
|
#include "services/network/public/cpp/features.h"
|
2020-05-19 17:18:12 +00:00
|
|
|
#include "shell/browser/api/electron_api_app.h"
|
2020-02-04 20:19:40 +00:00
|
|
|
#include "shell/browser/api/electron_api_cookies.h"
|
|
|
|
#include "shell/browser/api/electron_api_data_pipe_holder.h"
|
|
|
|
#include "shell/browser/api/electron_api_download_item.h"
|
|
|
|
#include "shell/browser/api/electron_api_net_log.h"
|
|
|
|
#include "shell/browser/api/electron_api_protocol.h"
|
2020-02-20 23:19:06 +00:00
|
|
|
#include "shell/browser/api/electron_api_service_worker_context.h"
|
2020-02-04 20:19:40 +00:00
|
|
|
#include "shell/browser/api/electron_api_web_request.h"
|
2019-06-19 20:46:59 +00:00
|
|
|
#include "shell/browser/browser.h"
|
2020-02-04 20:19:40 +00:00
|
|
|
#include "shell/browser/electron_browser_context.h"
|
|
|
|
#include "shell/browser/electron_browser_main_parts.h"
|
|
|
|
#include "shell/browser/electron_permission_manager.h"
|
2020-06-22 16:35:24 +00:00
|
|
|
#include "shell/browser/javascript_environment.h"
|
2019-06-19 20:46:59 +00:00
|
|
|
#include "shell/browser/media/media_device_id_salt.h"
|
2019-08-07 15:04:09 +00:00
|
|
|
#include "shell/browser/net/cert_verifier_client.h"
|
2019-06-19 20:46:59 +00:00
|
|
|
#include "shell/browser/session_preferences.h"
|
2019-10-25 13:03:28 +00:00
|
|
|
#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"
|
2019-10-31 07:56:00 +00:00
|
|
|
#include "shell/common/gin_converters/value_converter.h"
|
2019-10-25 13:03:28 +00:00
|
|
|
#include "shell/common/gin_helper/dictionary.h"
|
|
|
|
#include "shell/common/gin_helper/object_template_builder.h"
|
2019-06-19 20:46:59 +00:00
|
|
|
#include "shell/common/node_includes.h"
|
|
|
|
#include "shell/common/options_switches.h"
|
2020-02-03 22:01:10 +00:00
|
|
|
#include "shell/common/process_util.h"
|
2016-06-22 06:57:51 +00:00
|
|
|
#include "ui/base/l10n/l10n_util.h"
|
2015-06-16 09:23:29 +00:00
|
|
|
|
2019-07-24 23:01:08 +00:00
|
|
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
2020-01-13 22:56:28 +00:00
|
|
|
#include "extensions/browser/extension_registry.h"
|
2020-02-03 22:01:10 +00:00
|
|
|
#include "shell/browser/extensions/electron_extension_system.h"
|
2020-01-13 22:56:28 +00:00
|
|
|
#include "shell/common/gin_converters/extension_converter.h"
|
2019-07-24 23:01:08 +00:00
|
|
|
#endif
|
|
|
|
|
2019-10-31 20:11:51 +00:00
|
|
|
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
|
2019-11-30 22:17:46 +00:00
|
|
|
#include "chrome/browser/spellchecker/spellcheck_factory.h" // nogncheck
|
|
|
|
#include "chrome/browser/spellchecker/spellcheck_service.h" // nogncheck
|
2019-10-31 20:11:51 +00:00
|
|
|
#include "components/spellcheck/browser/pref_names.h"
|
|
|
|
#include "components/spellcheck/common/spellcheck_common.h"
|
2019-11-26 21:16:43 +00:00
|
|
|
|
|
|
|
#if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
|
|
|
|
#include "components/spellcheck/browser/spellcheck_platform.h"
|
|
|
|
#include "components/spellcheck/common/spellcheck_features.h"
|
|
|
|
#endif
|
2019-10-31 20:11:51 +00:00
|
|
|
#endif
|
|
|
|
|
2015-07-02 14:12:18 +00:00
|
|
|
using content::BrowserThread;
|
|
|
|
using content::StoragePartition;
|
|
|
|
|
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(
|
2019-12-11 00:22:35 +00:00
|
|
|
const url::Origin& origin,
|
2019-11-05 23:41:20 +00:00
|
|
|
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
|
|
|
|
|
2015-07-02 14:12:18 +00:00
|
|
|
namespace {
|
|
|
|
|
2015-07-13 22:13:17 +00:00
|
|
|
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;
|
2015-07-13 22:13:17 +00:00
|
|
|
};
|
2015-07-02 14:12:18 +00:00
|
|
|
|
2016-03-08 04:40:10 +00:00
|
|
|
uint32_t GetStorageMask(const std::vector<std::string>& storage_types) {
|
|
|
|
uint32_t storage_mask = 0;
|
2015-07-13 22:13:17 +00:00
|
|
|
for (const auto& it : storage_types) {
|
2015-12-07 11:56:23 +00:00
|
|
|
auto type = base::ToLowerASCII(it);
|
2015-07-13 22:13:17 +00:00
|
|
|
if (type == "appcache")
|
2015-07-02 14:12:18 +00:00
|
|
|
storage_mask |= StoragePartition::REMOVE_DATA_MASK_APPCACHE;
|
2015-07-13 22:13:17 +00:00
|
|
|
else if (type == "cookies")
|
2015-07-02 14:12:18 +00:00
|
|
|
storage_mask |= StoragePartition::REMOVE_DATA_MASK_COOKIES;
|
2015-07-13 22:13:17 +00:00
|
|
|
else if (type == "filesystem")
|
2015-07-02 14:12:18 +00:00
|
|
|
storage_mask |= StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS;
|
2015-07-13 22:13:17 +00:00
|
|
|
else if (type == "indexdb")
|
2015-07-02 14:12:18 +00:00
|
|
|
storage_mask |= StoragePartition::REMOVE_DATA_MASK_INDEXEDDB;
|
2015-07-13 22:13:17 +00:00
|
|
|
else if (type == "localstorage")
|
2015-07-02 14:12:18 +00:00
|
|
|
storage_mask |= StoragePartition::REMOVE_DATA_MASK_LOCAL_STORAGE;
|
2015-07-13 22:13:17 +00:00
|
|
|
else if (type == "shadercache")
|
2015-07-02 14:12:18 +00:00
|
|
|
storage_mask |= StoragePartition::REMOVE_DATA_MASK_SHADER_CACHE;
|
2015-07-13 22:13:17 +00:00
|
|
|
else if (type == "websql")
|
2015-07-02 14:12:18 +00:00
|
|
|
storage_mask |= StoragePartition::REMOVE_DATA_MASK_WEBSQL;
|
2015-07-13 22:13:17 +00:00
|
|
|
else if (type == "serviceworkers")
|
2015-07-02 14:12:18 +00:00
|
|
|
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;
|
2015-07-02 14:12:18 +00:00
|
|
|
}
|
|
|
|
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;
|
2015-07-13 22:13:17 +00:00
|
|
|
for (const auto& it : quota_types) {
|
2015-12-07 11:56:23 +00:00
|
|
|
auto type = base::ToLowerASCII(it);
|
2015-07-13 22:13:17 +00:00
|
|
|
if (type == "temporary")
|
2015-07-02 14:12:18 +00:00
|
|
|
quota_mask |= StoragePartition::QUOTA_MANAGED_STORAGE_MASK_TEMPORARY;
|
2015-07-13 22:13:17 +00:00
|
|
|
else if (type == "persistent")
|
2015-07-02 14:12:18 +00:00
|
|
|
quota_mask |= StoragePartition::QUOTA_MANAGED_STORAGE_MASK_PERSISTENT;
|
2015-07-13 22:13:17 +00:00
|
|
|
else if (type == "syncable")
|
|
|
|
quota_mask |= StoragePartition::QUOTA_MANAGED_STORAGE_MASK_SYNCABLE;
|
2015-07-02 14:12:18 +00:00
|
|
|
}
|
|
|
|
return quota_mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
2019-10-25 13:03:28 +00:00
|
|
|
namespace gin {
|
2015-07-13 22:13:17 +00:00
|
|
|
|
2018-04-18 01:55:30 +00:00
|
|
|
template <>
|
2015-07-13 22:13:17 +00:00
|
|
|
struct Converter<ClearStorageDataOptions> {
|
|
|
|
static bool FromV8(v8::Isolate* isolate,
|
|
|
|
v8::Local<v8::Value> val,
|
|
|
|
ClearStorageDataOptions* out) {
|
2019-10-25 13:03:28 +00:00
|
|
|
gin_helper::Dictionary options;
|
2015-07-13 22:13:17 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-09-23 20:22:10 +00:00
|
|
|
bool SSLProtocolVersionFromString(const std::string& version_str,
|
|
|
|
network::mojom::SSLVersion* version) {
|
|
|
|
if (version_str == switches::kSSLVersionTLSv1) {
|
|
|
|
*version = network::mojom::SSLVersion::kTLS1;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (version_str == switches::kSSLVersionTLSv11) {
|
|
|
|
*version = network::mojom::SSLVersion::kTLS11;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (version_str == switches::kSSLVersionTLSv12) {
|
|
|
|
*version = network::mojom::SSLVersion::kTLS12;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (version_str == switches::kSSLVersionTLSv13) {
|
|
|
|
*version = network::mojom::SSLVersion::kTLS13;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-10-21 18:03:59 +00:00
|
|
|
template <>
|
|
|
|
struct Converter<uint16_t> {
|
|
|
|
static bool FromV8(v8::Isolate* isolate,
|
|
|
|
v8::Local<v8::Value> val,
|
|
|
|
uint16_t* out) {
|
|
|
|
auto maybe = val->IntegerValue(isolate->GetCurrentContext());
|
|
|
|
if (maybe.IsNothing())
|
|
|
|
return false;
|
|
|
|
*out = maybe.FromJust();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-09-23 20:22:10 +00:00
|
|
|
template <>
|
|
|
|
struct Converter<network::mojom::SSLConfigPtr> {
|
|
|
|
static bool FromV8(v8::Isolate* isolate,
|
|
|
|
v8::Local<v8::Value> val,
|
|
|
|
network::mojom::SSLConfigPtr* out) {
|
|
|
|
gin_helper::Dictionary options;
|
|
|
|
if (!ConvertFromV8(isolate, val, &options))
|
|
|
|
return false;
|
|
|
|
*out = network::mojom::SSLConfig::New();
|
|
|
|
std::string version_min_str;
|
|
|
|
if (options.Get("minVersion", &version_min_str)) {
|
|
|
|
if (!SSLProtocolVersionFromString(version_min_str, &(*out)->version_min))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
std::string version_max_str;
|
|
|
|
if (options.Get("maxVersion", &version_max_str)) {
|
|
|
|
if (!SSLProtocolVersionFromString(version_max_str,
|
|
|
|
&(*out)->version_max) ||
|
|
|
|
(*out)->version_max < network::mojom::SSLVersion::kTLS12)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-10-21 18:03:59 +00:00
|
|
|
if (options.Has("disabledCipherSuites") &&
|
|
|
|
!options.Get("disabledCipherSuites", &(*out)->disabled_cipher_suites)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
std::sort((*out)->disabled_cipher_suites.begin(),
|
|
|
|
(*out)->disabled_cipher_suites.end());
|
|
|
|
|
|
|
|
// TODO(nornagon): also support other SSLConfig properties?
|
2020-09-23 20:22:10 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-10-25 13:03:28 +00:00
|
|
|
} // namespace gin
|
2015-07-13 22:13:17 +00:00
|
|
|
|
2019-06-19 21:23:04 +00:00
|
|
|
namespace electron {
|
2015-06-16 09:23:29 +00:00
|
|
|
|
|
|
|
namespace api {
|
|
|
|
|
2015-06-24 03:59:11 +00:00
|
|
|
namespace {
|
|
|
|
|
2016-07-12 12:01:49 +00:00
|
|
|
const char kPersistPrefix[] = "persist:";
|
|
|
|
|
2016-11-18 10:43:43 +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(
|
2016-11-18 10:43:43 +00:00
|
|
|
base::GenerateGUID(), id, path, path, url_chain, GURL(), GURL(), GURL(),
|
2019-05-13 21:24:39 +00:00
|
|
|
GURL(), base::nullopt, mime_type, mime_type, start_time, base::Time(),
|
|
|
|
etag, last_modified, offset, length, std::string(),
|
2018-04-10 15:29:26 +00:00
|
|
|
download::DownloadItem::INTERRUPTED,
|
2018-04-10 15:58:49 +00:00
|
|
|
download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
|
2018-04-10 16:08:50 +00:00
|
|
|
download::DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT, false, base::Time(),
|
2018-04-10 15:29:26 +00:00
|
|
|
false, std::vector<download::DownloadItem::ReceivedSlice>());
|
2016-11-18 10:43:43 +00:00
|
|
|
}
|
|
|
|
|
2020-03-10 09:39:40 +00:00
|
|
|
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
|
2020-02-10 22:08:53 +00:00
|
|
|
class DictionaryObserver final : public SpellcheckCustomDictionary::Observer {
|
|
|
|
private:
|
|
|
|
std::unique_ptr<gin_helper::Promise<std::set<std::string>>> promise_;
|
|
|
|
base::WeakPtr<SpellcheckService> spellcheck_;
|
|
|
|
|
|
|
|
public:
|
|
|
|
DictionaryObserver(gin_helper::Promise<std::set<std::string>> promise,
|
|
|
|
base::WeakPtr<SpellcheckService> spellcheck)
|
|
|
|
: spellcheck_(spellcheck) {
|
|
|
|
promise_ = std::make_unique<gin_helper::Promise<std::set<std::string>>>(
|
|
|
|
std::move(promise));
|
|
|
|
if (spellcheck_)
|
|
|
|
spellcheck_->GetCustomDictionary()->AddObserver(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
~DictionaryObserver() {
|
|
|
|
if (spellcheck_)
|
|
|
|
spellcheck_->GetCustomDictionary()->RemoveObserver(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OnCustomDictionaryLoaded() override {
|
|
|
|
if (spellcheck_) {
|
|
|
|
promise_->Resolve(spellcheck_->GetCustomDictionary()->GetWords());
|
|
|
|
} else {
|
|
|
|
promise_->RejectWithErrorMessage(
|
|
|
|
"Spellcheck in unexpected state: failed to load custom dictionary.");
|
|
|
|
}
|
|
|
|
delete this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void OnCustomDictionaryChanged(
|
|
|
|
const SpellcheckCustomDictionary::Change& dictionary_change) override {
|
|
|
|
// noop
|
|
|
|
}
|
|
|
|
};
|
2020-03-10 09:39:40 +00:00
|
|
|
#endif // BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
|
2020-02-10 22:08:53 +00:00
|
|
|
|
2020-05-19 17:18:12 +00:00
|
|
|
struct UserDataLink : base::SupportsUserData::Data {
|
|
|
|
explicit UserDataLink(Session* ses) : session(ses) {}
|
|
|
|
|
|
|
|
Session* session;
|
|
|
|
};
|
|
|
|
|
|
|
|
const void* kElectronApiSessionKey = &kElectronApiSessionKey;
|
|
|
|
|
2015-06-24 03:59:11 +00:00
|
|
|
} // namespace
|
|
|
|
|
2020-05-19 17:18:12 +00:00
|
|
|
gin::WrapperInfo Session::kWrapperInfo = {gin::kEmbedderNativeGin};
|
|
|
|
|
2020-02-04 20:19:40 +00:00
|
|
|
Session::Session(v8::Isolate* isolate, ElectronBrowserContext* browser_context)
|
2018-10-02 18:08:10 +00:00
|
|
|
: network_emulation_token_(base::UnguessableToken::Create()),
|
2016-04-18 04:59:15 +00:00
|
|
|
browser_context_(browser_context) {
|
2016-09-21 23:24:03 +00:00
|
|
|
// 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
|
|
|
|
2017-12-05 06:59:15 +00:00
|
|
|
new SessionPreferences(browser_context);
|
|
|
|
|
2019-11-07 23:35:12 +00:00
|
|
|
protocol_.Reset(isolate, Protocol::Create(isolate, browser_context).ToV8());
|
|
|
|
|
2020-05-19 17:18:12 +00:00
|
|
|
browser_context->SetUserData(kElectronApiSessionKey,
|
|
|
|
std::make_unique<UserDataLink>(this));
|
2020-03-05 19:58:19 +00:00
|
|
|
|
2020-03-10 09:39:40 +00:00
|
|
|
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
|
2020-03-05 19:58:19 +00:00
|
|
|
SpellcheckService* service =
|
2020-08-17 20:21:53 +00:00
|
|
|
SpellcheckServiceFactory::GetForContext(browser_context_);
|
2020-03-05 19:58:19 +00:00
|
|
|
if (service) {
|
|
|
|
service->SetHunspellObserver(this);
|
|
|
|
}
|
2020-03-10 09:39:40 +00:00
|
|
|
#endif
|
2020-09-23 19:29:08 +00:00
|
|
|
|
|
|
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
|
|
|
extensions::ExtensionRegistry::Get(browser_context)->AddObserver(this);
|
|
|
|
#endif
|
2015-06-16 09:23:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Session::~Session() {
|
2018-04-18 01:55:30 +00:00
|
|
|
content::BrowserContext::GetDownloadManager(browser_context())
|
|
|
|
->RemoveObserver(this);
|
2020-03-05 19:58:19 +00:00
|
|
|
|
2020-03-10 09:39:40 +00:00
|
|
|
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
|
2020-03-05 19:58:19 +00:00
|
|
|
SpellcheckService* service =
|
2020-08-17 20:21:53 +00:00
|
|
|
SpellcheckServiceFactory::GetForContext(browser_context_);
|
2020-03-05 19:58:19 +00:00
|
|
|
if (service) {
|
|
|
|
service->SetHunspellObserver(nullptr);
|
|
|
|
}
|
2020-03-10 09:39:40 +00:00
|
|
|
#endif
|
2020-09-23 19:29:08 +00:00
|
|
|
|
|
|
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
|
|
|
extensions::ExtensionRegistry::Get(browser_context())->RemoveObserver(this);
|
|
|
|
#endif
|
2015-08-30 18:52:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Session::OnDownloadCreated(content::DownloadManager* manager,
|
2018-04-10 15:29:26 +00:00
|
|
|
download::DownloadItem* item) {
|
2016-04-27 14:59:39 +00:00
|
|
|
if (item->IsSavePackageDownload())
|
2015-10-14 04:41:31 +00:00
|
|
|
return;
|
2016-04-25 01:17:54 +00:00
|
|
|
|
2020-06-22 16:35:24 +00:00
|
|
|
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
2020-05-19 17:18:12 +00:00
|
|
|
v8::Locker locker(isolate);
|
|
|
|
v8::HandleScope handle_scope(isolate);
|
|
|
|
auto handle = DownloadItem::FromOrCreate(isolate, item);
|
2018-04-10 15:29:26 +00:00
|
|
|
if (item->GetState() == download::DownloadItem::INTERRUPTED)
|
2016-11-18 10:43:43 +00:00
|
|
|
handle->SetSavePath(item->GetTargetFilePath());
|
2018-04-10 15:29:26 +00:00
|
|
|
content::WebContents* web_contents =
|
|
|
|
content::DownloadItemUtils::GetWebContents(item);
|
|
|
|
bool prevent_default = Emit("will-download", handle, web_contents);
|
2015-08-30 18:52:01 +00:00
|
|
|
if (prevent_default) {
|
|
|
|
item->Cancel(true);
|
|
|
|
item->Remove();
|
|
|
|
}
|
2015-06-16 09:23:29 +00:00
|
|
|
}
|
|
|
|
|
2020-03-10 09:39:40 +00:00
|
|
|
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
|
2020-03-05 19:58:19 +00:00
|
|
|
void Session::OnHunspellDictionaryInitialized(const std::string& language) {
|
|
|
|
Emit("spellcheck-dictionary-initialized", language);
|
|
|
|
}
|
|
|
|
void Session::OnHunspellDictionaryDownloadBegin(const std::string& language) {
|
|
|
|
Emit("spellcheck-dictionary-download-begin", language);
|
|
|
|
}
|
|
|
|
void Session::OnHunspellDictionaryDownloadSuccess(const std::string& language) {
|
|
|
|
Emit("spellcheck-dictionary-download-success", language);
|
|
|
|
}
|
|
|
|
void Session::OnHunspellDictionaryDownloadFailure(const std::string& language) {
|
|
|
|
Emit("spellcheck-dictionary-download-failure", language);
|
|
|
|
}
|
2020-03-10 09:39:40 +00:00
|
|
|
#endif
|
2020-03-05 19:58:19 +00:00
|
|
|
|
2020-05-19 17:18:12 +00:00
|
|
|
v8::Local<v8::Promise> Session::ResolveProxy(gin::Arguments* args) {
|
2019-03-08 20:51:12 +00:00
|
|
|
v8::Isolate* isolate = args->isolate();
|
2019-11-01 06:10:32 +00:00
|
|
|
gin_helper::Promise<std::string> promise(isolate);
|
2019-03-08 20:51:12 +00:00
|
|
|
v8::Local<v8::Promise> handle = promise.GetHandle();
|
|
|
|
|
|
|
|
GURL url;
|
|
|
|
args->GetNext(&url);
|
|
|
|
|
|
|
|
browser_context_->GetResolveProxyHelper()->ResolveProxy(
|
2019-11-01 06:10:32 +00:00
|
|
|
url, base::BindOnce(gin_helper::Promise<std::string>::ResolvePromise,
|
2019-05-01 20:45:08 +00:00
|
|
|
std::move(promise)));
|
2019-03-08 20:51:12 +00:00
|
|
|
|
|
|
|
return handle;
|
2015-06-24 03:59:11 +00:00
|
|
|
}
|
|
|
|
|
2019-04-30 22:09:17 +00:00
|
|
|
v8::Local<v8::Promise> Session::GetCacheSize() {
|
2020-06-22 16:35:24 +00:00
|
|
|
auto* isolate = JavascriptEnvironment::GetIsolate();
|
2019-11-01 06:10:32 +00:00
|
|
|
gin_helper::Promise<int64_t> promise(isolate);
|
2019-04-30 22:09:17 +00:00
|
|
|
auto handle = promise.GetHandle();
|
2019-03-08 22:42:03 +00:00
|
|
|
|
2020-08-17 20:21:53 +00:00
|
|
|
content::BrowserContext::GetDefaultStoragePartition(browser_context_)
|
2019-04-30 22:09:17 +00:00
|
|
|
->GetNetworkContext()
|
2019-08-23 00:03:28 +00:00
|
|
|
->ComputeHttpCacheSize(
|
|
|
|
base::Time(), base::Time::Max(),
|
|
|
|
base::BindOnce(
|
2019-11-01 06:10:32 +00:00
|
|
|
[](gin_helper::Promise<int64_t> promise, bool is_upper_bound,
|
2019-08-23 00:03:28 +00:00
|
|
|
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)));
|
2019-04-30 22:09:17 +00:00
|
|
|
|
|
|
|
return handle;
|
|
|
|
}
|
|
|
|
|
|
|
|
v8::Local<v8::Promise> Session::ClearCache() {
|
2020-06-22 16:35:24 +00:00
|
|
|
auto* isolate = JavascriptEnvironment::GetIsolate();
|
2019-11-01 06:10:32 +00:00
|
|
|
gin_helper::Promise<void> promise(isolate);
|
2019-04-30 22:09:17 +00:00
|
|
|
auto handle = promise.GetHandle();
|
|
|
|
|
2020-08-17 20:21:53 +00:00
|
|
|
content::BrowserContext::GetDefaultStoragePartition(browser_context_)
|
2019-04-30 22:09:17 +00:00
|
|
|
->GetNetworkContext()
|
|
|
|
->ClearHttpCache(base::Time(), base::Time::Max(), nullptr,
|
2019-11-01 06:10:32 +00:00
|
|
|
base::BindOnce(gin_helper::Promise<void>::ResolvePromise,
|
2019-04-30 22:09:17 +00:00
|
|
|
std::move(promise)));
|
2019-03-08 22:42:03 +00:00
|
|
|
|
|
|
|
return handle;
|
2015-07-02 14:12:18 +00:00
|
|
|
}
|
|
|
|
|
2020-05-19 17:18:12 +00:00
|
|
|
v8::Local<v8::Promise> Session::ClearStorageData(gin::Arguments* args) {
|
2019-03-08 17:02:30 +00:00
|
|
|
v8::Isolate* isolate = args->isolate();
|
2019-11-01 06:10:32 +00:00
|
|
|
gin_helper::Promise<void> promise(isolate);
|
2019-03-08 17:02:30 +00:00
|
|
|
v8::Local<v8::Promise> handle = promise.GetHandle();
|
|
|
|
|
2015-07-13 22:13:17 +00:00
|
|
|
ClearStorageDataOptions options;
|
|
|
|
args->GetNext(&options);
|
|
|
|
|
2018-04-17 22:41:47 +00:00
|
|
|
auto* storage_partition =
|
2015-09-05 14:39:48 +00:00
|
|
|
content::BrowserContext::GetStoragePartition(browser_context(), nullptr);
|
2016-12-03 11:14:33 +00:00
|
|
|
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
|
2018-10-19 18:51:43 +00:00
|
|
|
MediaDeviceIDSalt::Reset(browser_context()->prefs());
|
2016-12-03 11:14:33 +00:00
|
|
|
}
|
2019-03-08 17:02:30 +00:00
|
|
|
|
|
|
|
storage_partition->ClearData(
|
|
|
|
options.storage_types, options.quota_types, options.origin, base::Time(),
|
|
|
|
base::Time::Max(),
|
2019-11-01 06:10:32 +00:00
|
|
|
base::BindOnce(gin_helper::Promise<void>::ResolvePromise,
|
2019-08-23 00:03:28 +00:00
|
|
|
std::move(promise)));
|
2019-03-08 17:02:30 +00:00
|
|
|
return handle;
|
2015-07-02 14:12:18 +00:00
|
|
|
}
|
|
|
|
|
2016-01-12 15:28:12 +00:00
|
|
|
void Session::FlushStorageData() {
|
2018-04-17 22:41:47 +00:00
|
|
|
auto* storage_partition =
|
2016-01-12 15:28:12 +00:00
|
|
|
content::BrowserContext::GetStoragePartition(browser_context(), nullptr);
|
|
|
|
storage_partition->Flush();
|
|
|
|
}
|
|
|
|
|
2020-05-19 17:18:12 +00:00
|
|
|
v8::Local<v8::Promise> Session::SetProxy(gin::Arguments* args) {
|
2019-03-08 20:51:12 +00:00
|
|
|
v8::Isolate* isolate = args->isolate();
|
2019-11-01 06:10:32 +00:00
|
|
|
gin_helper::Promise<void> promise(isolate);
|
2019-03-08 20:51:12 +00:00
|
|
|
v8::Local<v8::Promise> handle = promise.GetHandle();
|
|
|
|
|
2019-10-25 13:03:28 +00:00
|
|
|
gin_helper::Dictionary options;
|
2019-03-08 20:51:12 +00:00
|
|
|
args->GetNext(&options);
|
|
|
|
|
2018-10-04 18:08:56 +00:00
|
|
|
if (!browser_context_->in_memory_pref_store()) {
|
2019-03-08 20:51:12 +00:00
|
|
|
promise.Resolve();
|
|
|
|
return handle;
|
2018-10-04 18:08:56 +00:00
|
|
|
}
|
|
|
|
|
2020-10-27 06:50:06 +00:00
|
|
|
std::string mode, proxy_rules, bypass_list, pac_url;
|
2018-10-04 18:08:56 +00:00
|
|
|
|
|
|
|
options.Get("pacScript", &pac_url);
|
|
|
|
options.Get("proxyRules", &proxy_rules);
|
|
|
|
options.Get("proxyBypassRules", &bypass_list);
|
|
|
|
|
2020-10-27 06:50:06 +00:00
|
|
|
ProxyPrefs::ProxyMode proxy_mode = ProxyPrefs::MODE_FIXED_SERVERS;
|
|
|
|
if (!options.Get("mode", &mode)) {
|
|
|
|
// pacScript takes precedence over proxyRules.
|
|
|
|
if (!pac_url.empty()) {
|
|
|
|
proxy_mode = ProxyPrefs::MODE_PAC_SCRIPT;
|
|
|
|
} else {
|
|
|
|
proxy_mode = ProxyPrefs::MODE_FIXED_SERVERS;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!ProxyPrefs::StringToProxyMode(mode, &proxy_mode)) {
|
|
|
|
promise.RejectWithErrorMessage(
|
|
|
|
"Invalid mode, must be one of direct, auto_detect, pac_script, "
|
|
|
|
"fixed_servers or system");
|
|
|
|
return handle;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<base::Value> proxy_config;
|
|
|
|
if (proxy_mode == ProxyPrefs::MODE_DIRECT) {
|
|
|
|
proxy_config =
|
|
|
|
std::make_unique<base::Value>(ProxyConfigDictionary::CreateDirect());
|
|
|
|
} else if (proxy_mode == ProxyPrefs::MODE_SYSTEM) {
|
|
|
|
proxy_config =
|
|
|
|
std::make_unique<base::Value>(ProxyConfigDictionary::CreateSystem());
|
|
|
|
} else if (proxy_mode == ProxyPrefs::MODE_AUTO_DETECT) {
|
|
|
|
proxy_config = std::make_unique<base::Value>(
|
|
|
|
ProxyConfigDictionary::CreateAutoDetect());
|
|
|
|
} else if (proxy_mode == ProxyPrefs::MODE_PAC_SCRIPT) {
|
|
|
|
proxy_config =
|
2018-10-25 16:48:25 +00:00
|
|
|
std::make_unique<base::Value>(ProxyConfigDictionary::CreatePacScript(
|
2020-10-27 06:50:06 +00:00
|
|
|
pac_url, true /* pac_mandatory */));
|
2018-10-04 18:08:56 +00:00
|
|
|
} else {
|
2020-10-27 06:50:06 +00:00
|
|
|
proxy_config = std::make_unique<base::Value>(
|
|
|
|
ProxyConfigDictionary::CreateFixedServers(proxy_rules, bypass_list));
|
2018-10-04 18:08:56 +00:00
|
|
|
}
|
2020-10-27 06:50:06 +00:00
|
|
|
browser_context_->in_memory_pref_store()->SetValue(
|
|
|
|
proxy_config::prefs::kProxy, std::move(proxy_config),
|
|
|
|
WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
|
2018-10-04 18:08:56 +00:00
|
|
|
|
2019-03-08 20:51:12 +00:00
|
|
|
base::ThreadTaskRunnerHandle::Get()->PostTask(
|
2019-11-01 06:10:32 +00:00
|
|
|
FROM_HERE, base::BindOnce(gin_helper::Promise<void>::ResolvePromise,
|
2019-08-23 00:03:28 +00:00
|
|
|
std::move(promise)));
|
2019-03-08 20:51:12 +00:00
|
|
|
|
|
|
|
return handle;
|
2015-07-16 14:36:48 +00:00
|
|
|
}
|
|
|
|
|
2020-10-27 06:50:06 +00:00
|
|
|
v8::Local<v8::Promise> Session::ForceReloadProxyConfig() {
|
|
|
|
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
|
|
|
gin_helper::Promise<void> promise(isolate);
|
|
|
|
auto handle = promise.GetHandle();
|
|
|
|
|
|
|
|
content::BrowserContext::GetDefaultStoragePartition(browser_context_)
|
|
|
|
->GetNetworkContext()
|
|
|
|
->ForceReloadProxyConfig(base::BindOnce(
|
|
|
|
gin_helper::Promise<void>::ResolvePromise, std::move(promise)));
|
|
|
|
|
|
|
|
return handle;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2019-10-25 13:03:28 +00:00
|
|
|
void Session::EnableNetworkEmulation(const gin_helper::Dictionary& options) {
|
2018-10-02 18:08:10 +00:00
|
|
|
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);
|
2015-09-27 13:19:52 +00:00
|
|
|
}
|
|
|
|
|
2020-08-17 20:21:53 +00:00
|
|
|
auto* network_context =
|
|
|
|
content::BrowserContext::GetDefaultStoragePartition(browser_context_)
|
|
|
|
->GetNetworkContext();
|
2018-10-02 18:08:10 +00:00
|
|
|
network_context->SetNetworkConditions(network_emulation_token_,
|
|
|
|
std::move(conditions));
|
2015-09-27 13:19:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Session::DisableNetworkEmulation() {
|
2020-08-17 20:21:53 +00:00
|
|
|
auto* network_context =
|
|
|
|
content::BrowserContext::GetDefaultStoragePartition(browser_context_)
|
|
|
|
->GetNetworkContext();
|
2018-10-02 18:08:10 +00:00
|
|
|
network_context->SetNetworkConditions(
|
|
|
|
network_emulation_token_, network::mojom::NetworkConditions::New());
|
2015-09-27 13:19:52 +00:00
|
|
|
}
|
|
|
|
|
2015-11-18 03:45:15 +00:00
|
|
|
void Session::SetCertVerifyProc(v8::Local<v8::Value> val,
|
2020-05-19 17:18:12 +00:00
|
|
|
gin::Arguments* args) {
|
2019-08-07 15:04:09 +00:00
|
|
|
CertVerifierClient::CertVerifyProc proc;
|
2019-10-25 13:03:28 +00:00
|
|
|
if (!(val->IsNull() || gin::ConvertFromV8(args->isolate(), val, &proc))) {
|
2020-05-19 17:18:12 +00:00
|
|
|
args->ThrowTypeError("Must pass null or function");
|
2015-11-18 03:17:08 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-09-18 19:58:00 +00:00
|
|
|
mojo::PendingRemote<network::mojom::CertVerifierClient>
|
|
|
|
cert_verifier_client_remote;
|
2019-08-02 23:56:46 +00:00
|
|
|
if (proc) {
|
2019-09-18 19:58:00 +00:00
|
|
|
mojo::MakeSelfOwnedReceiver(
|
|
|
|
std::make_unique<CertVerifierClient>(proc),
|
|
|
|
cert_verifier_client_remote.InitWithNewPipeAndPassReceiver());
|
2019-06-28 22:22:23 +00:00
|
|
|
}
|
2020-08-17 20:21:53 +00:00
|
|
|
content::BrowserContext::GetDefaultStoragePartition(browser_context_)
|
2019-08-02 23:56:46 +00:00
|
|
|
->GetNetworkContext()
|
2019-09-18 19:58:00 +00:00
|
|
|
->SetCertVerifierClient(std::move(cert_verifier_client_remote));
|
2019-08-02 23:56:46 +00:00
|
|
|
|
|
|
|
// This causes the cert verifier cache to be cleared.
|
|
|
|
content::GetNetworkService()->OnCertDBChanged();
|
2015-11-18 03:17:08 +00:00
|
|
|
}
|
|
|
|
|
2016-01-31 21:35:34 +00:00
|
|
|
void Session::SetPermissionRequestHandler(v8::Local<v8::Value> val,
|
2020-05-19 17:18:12 +00:00
|
|
|
gin::Arguments* args) {
|
2020-02-04 20:19:40 +00:00
|
|
|
auto* permission_manager = static_cast<ElectronPermissionManager*>(
|
2019-05-03 21:20:43 +00:00
|
|
|
browser_context()->GetPermissionControllerDelegate());
|
|
|
|
if (val->IsNull()) {
|
|
|
|
permission_manager->SetPermissionRequestHandler(
|
2020-02-04 20:19:40 +00:00
|
|
|
ElectronPermissionManager::RequestHandler());
|
2019-05-03 21:20:43 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-02-04 20:19:40 +00:00
|
|
|
auto handler = std::make_unique<ElectronPermissionManager::RequestHandler>();
|
2019-10-25 13:03:28 +00:00
|
|
|
if (!gin::ConvertFromV8(args->isolate(), val, handler.get())) {
|
2020-05-19 17:18:12 +00:00
|
|
|
args->ThrowTypeError("Must pass null or function");
|
2016-01-31 21:35:34 +00:00
|
|
|
return;
|
|
|
|
}
|
2019-05-03 18:30:48 +00:00
|
|
|
permission_manager->SetPermissionRequestHandler(base::BindRepeating(
|
2020-02-04 20:19:40 +00:00
|
|
|
[](ElectronPermissionManager::RequestHandler* handler,
|
2019-06-13 18:11:43 +00:00
|
|
|
content::WebContents* web_contents,
|
2019-05-03 18:30:48 +00:00
|
|
|
content::PermissionType permission_type,
|
2020-02-04 20:19:40 +00:00
|
|
|
ElectronPermissionManager::StatusCallback callback,
|
2019-06-13 18:11:43 +00:00
|
|
|
const base::Value& details) {
|
2019-05-03 21:20:43 +00:00
|
|
|
handler->Run(web_contents, permission_type,
|
|
|
|
base::AdaptCallbackForRepeating(std::move(callback)),
|
|
|
|
details);
|
2019-05-03 18:30:48 +00:00
|
|
|
},
|
2019-05-03 21:20:43 +00:00
|
|
|
base::Owned(std::move(handler))));
|
2016-01-31 21:35:34 +00:00
|
|
|
}
|
|
|
|
|
2018-08-28 14:05:08 +00:00
|
|
|
void Session::SetPermissionCheckHandler(v8::Local<v8::Value> val,
|
2020-05-19 17:18:12 +00:00
|
|
|
gin::Arguments* args) {
|
2020-02-04 20:19:40 +00:00
|
|
|
ElectronPermissionManager::CheckHandler handler;
|
2019-10-25 13:03:28 +00:00
|
|
|
if (!(val->IsNull() || gin::ConvertFromV8(args->isolate(), val, &handler))) {
|
2020-05-19 17:18:12 +00:00
|
|
|
args->ThrowTypeError("Must pass null or function");
|
2018-08-28 14:05:08 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-02-04 20:19:40 +00:00
|
|
|
auto* permission_manager = static_cast<ElectronPermissionManager*>(
|
2018-10-02 21:53:10 +00:00
|
|
|
browser_context()->GetPermissionControllerDelegate());
|
2018-08-28 14:05:08 +00:00
|
|
|
permission_manager->SetPermissionCheckHandler(handler);
|
|
|
|
}
|
|
|
|
|
2020-05-19 17:18:12 +00:00
|
|
|
v8::Local<v8::Promise> Session::ClearHostResolverCache(gin::Arguments* args) {
|
2019-03-08 18:26:17 +00:00
|
|
|
v8::Isolate* isolate = args->isolate();
|
2019-11-01 06:10:32 +00:00
|
|
|
gin_helper::Promise<void> promise(isolate);
|
2019-03-08 18:26:17 +00:00
|
|
|
v8::Local<v8::Promise> handle = promise.GetHandle();
|
2016-02-01 13:33:23 +00:00
|
|
|
|
2020-08-17 20:21:53 +00:00
|
|
|
content::BrowserContext::GetDefaultStoragePartition(browser_context_)
|
2019-04-25 17:51:48 +00:00
|
|
|
->GetNetworkContext()
|
2019-05-03 21:30:25 +00:00
|
|
|
->ClearHostCache(nullptr,
|
2019-11-01 06:10:32 +00:00
|
|
|
base::BindOnce(gin_helper::Promise<void>::ResolvePromise,
|
2019-05-03 21:30:25 +00:00
|
|
|
std::move(promise)));
|
2019-04-25 17:51:48 +00:00
|
|
|
|
2019-03-08 18:26:17 +00:00
|
|
|
return handle;
|
2016-02-01 13:33:23 +00:00
|
|
|
}
|
|
|
|
|
2019-05-03 21:30:25 +00:00
|
|
|
v8::Local<v8::Promise> Session::ClearAuthCache() {
|
2020-06-22 16:35:24 +00:00
|
|
|
auto* isolate = JavascriptEnvironment::GetIsolate();
|
2019-11-01 06:10:32 +00:00
|
|
|
gin_helper::Promise<void> promise(isolate);
|
2019-03-09 02:41:42 +00:00
|
|
|
v8::Local<v8::Promise> handle = promise.GetHandle();
|
|
|
|
|
2020-08-17 20:21:53 +00:00
|
|
|
content::BrowserContext::GetDefaultStoragePartition(browser_context_)
|
2019-05-03 21:30:25 +00:00
|
|
|
->GetNetworkContext()
|
2019-08-23 00:03:28 +00:00
|
|
|
->ClearHttpAuthCache(
|
2020-09-21 08:00:36 +00:00
|
|
|
base::Time(), base::Time::Max(),
|
2019-11-01 06:10:32 +00:00
|
|
|
base::BindOnce(gin_helper::Promise<void>::ResolvePromise,
|
2019-08-23 00:03:28 +00:00
|
|
|
std::move(promise)));
|
2016-11-30 16:35:15 +00:00
|
|
|
|
2019-03-09 02:41:42 +00:00
|
|
|
return handle;
|
2016-11-30 16:35:15 +00:00
|
|
|
}
|
|
|
|
|
2016-05-23 05:29:55 +00:00
|
|
|
void Session::AllowNTLMCredentialsForDomains(const std::string& domains) {
|
2020-06-02 19:58:00 +00:00
|
|
|
auto* command_line = base::CommandLine::ForCurrentProcess();
|
2019-08-07 15:04:09 +00:00
|
|
|
network::mojom::HttpAuthDynamicParamsPtr auth_dynamic_params =
|
|
|
|
network::mojom::HttpAuthDynamicParams::New();
|
|
|
|
auth_dynamic_params->server_allowlist = domains;
|
2019-12-19 13:53:49 +00:00
|
|
|
auth_dynamic_params->enable_negotiate_port =
|
2020-06-02 19:58:00 +00:00
|
|
|
command_line->HasSwitch(electron::switches::kEnableAuthNegotiatePort);
|
|
|
|
auth_dynamic_params->ntlm_v2_enabled =
|
|
|
|
!command_line->HasSwitch(electron::switches::kDisableNTLMv2);
|
2019-08-07 15:04:09 +00:00
|
|
|
content::GetNetworkService()->ConfigureHttpAuthPrefs(
|
|
|
|
std::move(auth_dynamic_params));
|
2016-05-23 05:29:55 +00:00
|
|
|
}
|
|
|
|
|
2016-06-22 06:57:51 +00:00
|
|
|
void Session::SetUserAgent(const std::string& user_agent,
|
2020-05-19 17:18:12 +00:00
|
|
|
gin::Arguments* args) {
|
2019-08-29 06:50:14 +00:00
|
|
|
browser_context_->SetUserAgent(user_agent);
|
2020-08-17 20:21:53 +00:00
|
|
|
auto* network_context =
|
|
|
|
content::BrowserContext::GetDefaultStoragePartition(browser_context_)
|
|
|
|
->GetNetworkContext();
|
2020-06-04 11:05:37 +00:00
|
|
|
network_context->SetUserAgent(user_agent);
|
|
|
|
|
|
|
|
std::string accept_lang;
|
|
|
|
if (args->GetNext(&accept_lang)) {
|
|
|
|
network_context->SetAcceptLanguage(
|
|
|
|
net::HttpUtil::GenerateAcceptLanguageHeader(accept_lang));
|
|
|
|
}
|
2016-06-22 06:57:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string Session::GetUserAgent() {
|
|
|
|
return browser_context_->GetUserAgent();
|
|
|
|
}
|
|
|
|
|
2020-09-23 20:22:10 +00:00
|
|
|
void Session::SetSSLConfig(network::mojom::SSLConfigPtr config) {
|
|
|
|
browser_context_->SetSSLConfig(std::move(config));
|
|
|
|
}
|
|
|
|
|
2020-03-11 07:02:22 +00:00
|
|
|
bool Session::IsPersistent() {
|
|
|
|
return !browser_context_->IsOffTheRecord();
|
|
|
|
}
|
|
|
|
|
2019-03-14 15:11:01 +00:00
|
|
|
v8::Local<v8::Promise> Session::GetBlobData(v8::Isolate* isolate,
|
|
|
|
const std::string& uuid) {
|
2019-09-03 22:54:14 +00:00
|
|
|
gin::Handle<DataPipeHolder> holder = DataPipeHolder::From(isolate, uuid);
|
|
|
|
if (holder.IsEmpty()) {
|
2019-11-01 06:10:32 +00:00
|
|
|
gin_helper::Promise<v8::Local<v8::Value>> promise(isolate);
|
2019-09-03 22:54:14 +00:00
|
|
|
promise.RejectWithErrorMessage("Could not get blob data handle");
|
|
|
|
return promise.GetHandle();
|
|
|
|
}
|
2016-08-23 05:57:43 +00:00
|
|
|
|
2019-09-03 22:54:14 +00:00
|
|
|
return holder->ReadAll(isolate);
|
2016-08-23 00:39:06 +00:00
|
|
|
}
|
|
|
|
|
2019-08-29 03:27:20 +00:00
|
|
|
void Session::DownloadURL(const GURL& url) {
|
|
|
|
auto* download_manager =
|
|
|
|
content::BrowserContext::GetDownloadManager(browser_context());
|
|
|
|
auto download_params = std::make_unique<download::DownloadUrlParameters>(
|
2020-03-11 11:15:07 +00:00
|
|
|
url, MISSING_TRAFFIC_ANNOTATION);
|
2019-08-29 03:27:20 +00:00
|
|
|
download_manager->DownloadUrl(std::move(download_params));
|
|
|
|
}
|
|
|
|
|
2019-10-25 13:03:28 +00:00
|
|
|
void Session::CreateInterruptedDownload(const gin_helper::Dictionary& options) {
|
2016-11-18 10:43:43 +00:00
|
|
|
int64_t offset = 0, length = 0;
|
2019-09-21 14:51:28 +00:00
|
|
|
double start_time = base::Time::Now().ToDoubleT();
|
2016-11-18 10:43:43 +00:00
|
|
|
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);
|
2020-06-22 16:35:24 +00:00
|
|
|
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
2016-12-07 07:28:53 +00:00
|
|
|
if (path.empty() || url_chain.empty() || length == 0) {
|
2020-05-19 17:18:12 +00:00
|
|
|
isolate->ThrowException(v8::Exception::Error(gin::StringToV8(
|
|
|
|
isolate, "Must pass non-empty path, urlChain and length.")));
|
2016-11-18 10:43:43 +00:00
|
|
|
return;
|
2016-12-07 07:28:53 +00:00
|
|
|
}
|
|
|
|
if (offset >= length) {
|
2020-05-19 17:18:12 +00:00
|
|
|
isolate->ThrowException(v8::Exception::Error(gin::StringToV8(
|
|
|
|
isolate, "Must pass an offset value less than length.")));
|
2016-12-07 07:28:53 +00:00
|
|
|
return;
|
|
|
|
}
|
2018-04-17 22:41:47 +00:00
|
|
|
auto* download_manager =
|
2016-11-18 10:43:43 +00:00
|
|
|
content::BrowserContext::GetDownloadManager(browser_context());
|
2020-04-03 00:22:46 +00:00
|
|
|
download_manager->GetNextId(base::BindRepeating(
|
2016-11-18 10:43:43 +00:00
|
|
|
&DownloadIdCallback, download_manager, path, url_chain, mime_type, offset,
|
|
|
|
length, last_modified, etag, base::Time::FromDoubleT(start_time)));
|
|
|
|
}
|
|
|
|
|
2017-12-05 06:59:15 +00:00
|
|
|
void Session::SetPreloads(
|
|
|
|
const std::vector<base::FilePath::StringType>& preloads) {
|
|
|
|
auto* prefs = SessionPreferences::FromBrowserContext(browser_context());
|
|
|
|
DCHECK(prefs);
|
|
|
|
prefs->set_preloads(preloads);
|
2017-09-16 15:05:49 +00:00
|
|
|
}
|
2017-12-05 02:50:06 +00:00
|
|
|
|
|
|
|
std::vector<base::FilePath::StringType> Session::GetPreloads() const {
|
2017-12-05 06:59:15 +00:00
|
|
|
auto* prefs = SessionPreferences::FromBrowserContext(browser_context());
|
|
|
|
DCHECK(prefs);
|
|
|
|
return prefs->preloads();
|
2017-09-16 15:05:49 +00:00
|
|
|
}
|
|
|
|
|
2019-07-24 23:01:08 +00:00
|
|
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
2020-01-13 22:56:28 +00:00
|
|
|
v8::Local<v8::Promise> Session::LoadExtension(
|
|
|
|
const base::FilePath& extension_path) {
|
2020-06-22 16:35:24 +00:00
|
|
|
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
2020-05-19 17:18:12 +00:00
|
|
|
gin_helper::Promise<const extensions::Extension*> promise(isolate);
|
2020-01-13 22:56:28 +00:00
|
|
|
v8::Local<v8::Promise> handle = promise.GetHandle();
|
2020-08-21 03:47:10 +00:00
|
|
|
|
|
|
|
if (!extension_path.IsAbsolute()) {
|
|
|
|
promise.RejectWithErrorMessage(
|
|
|
|
"The path to the extension in 'loadExtension' must be absolute");
|
|
|
|
return handle;
|
|
|
|
}
|
|
|
|
|
2020-02-10 16:28:03 +00:00
|
|
|
if (browser_context()->IsOffTheRecord()) {
|
|
|
|
promise.RejectWithErrorMessage(
|
|
|
|
"Extensions cannot be loaded in a temporary session");
|
|
|
|
return handle;
|
|
|
|
}
|
2020-01-13 22:56:28 +00:00
|
|
|
|
2020-02-03 22:01:10 +00:00
|
|
|
auto* extension_system = static_cast<extensions::ElectronExtensionSystem*>(
|
2020-01-13 22:56:28 +00:00
|
|
|
extensions::ExtensionSystem::Get(browser_context()));
|
2020-01-21 17:43:18 +00:00
|
|
|
extension_system->LoadExtension(
|
|
|
|
extension_path,
|
|
|
|
base::BindOnce(
|
|
|
|
[](gin_helper::Promise<const extensions::Extension*> promise,
|
2020-02-03 22:01:10 +00:00
|
|
|
const extensions::Extension* extension,
|
|
|
|
const std::string& error_msg) {
|
2020-01-21 17:43:18 +00:00
|
|
|
if (extension) {
|
2020-02-03 22:01:10 +00:00
|
|
|
if (!error_msg.empty()) {
|
|
|
|
node::Environment* env =
|
|
|
|
node::Environment::GetCurrent(v8::Isolate::GetCurrent());
|
|
|
|
EmitWarning(env, error_msg, "ExtensionLoadWarning");
|
|
|
|
}
|
2020-01-21 17:43:18 +00:00
|
|
|
promise.Resolve(extension);
|
|
|
|
} else {
|
2020-02-03 22:01:10 +00:00
|
|
|
promise.RejectWithErrorMessage(error_msg);
|
2020-01-21 17:43:18 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
std::move(promise)));
|
2020-01-13 22:56:28 +00:00
|
|
|
|
|
|
|
return handle;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Session::RemoveExtension(const std::string& extension_id) {
|
2020-02-03 22:01:10 +00:00
|
|
|
auto* extension_system = static_cast<extensions::ElectronExtensionSystem*>(
|
2019-07-24 23:01:08 +00:00
|
|
|
extensions::ExtensionSystem::Get(browser_context()));
|
2020-01-13 22:56:28 +00:00
|
|
|
extension_system->RemoveExtension(extension_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
v8::Local<v8::Value> Session::GetExtension(const std::string& extension_id) {
|
|
|
|
auto* registry = extensions::ExtensionRegistry::Get(browser_context());
|
|
|
|
const extensions::Extension* extension =
|
|
|
|
registry->GetInstalledExtension(extension_id);
|
2020-06-22 16:35:24 +00:00
|
|
|
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
2020-01-13 22:56:28 +00:00
|
|
|
if (extension) {
|
2020-05-19 17:18:12 +00:00
|
|
|
return gin::ConvertToV8(isolate, extension);
|
2020-01-13 22:56:28 +00:00
|
|
|
} else {
|
2020-05-19 17:18:12 +00:00
|
|
|
return v8::Null(isolate);
|
2020-01-13 22:56:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
v8::Local<v8::Value> Session::GetAllExtensions() {
|
|
|
|
auto* registry = extensions::ExtensionRegistry::Get(browser_context());
|
|
|
|
auto installed_extensions = registry->GenerateInstalledExtensionsSet();
|
|
|
|
std::vector<const extensions::Extension*> extensions_vector;
|
|
|
|
for (const auto& extension : *installed_extensions) {
|
2020-02-13 00:39:12 +00:00
|
|
|
if (extension->location() != extensions::Manifest::COMPONENT)
|
|
|
|
extensions_vector.emplace_back(extension.get());
|
2020-01-13 22:56:28 +00:00
|
|
|
}
|
2020-05-19 17:18:12 +00:00
|
|
|
return gin::ConvertToV8(v8::Isolate::GetCurrent(), extensions_vector);
|
2019-07-24 23:01:08 +00:00
|
|
|
}
|
2020-09-23 19:29:08 +00:00
|
|
|
|
|
|
|
void Session::OnExtensionLoaded(content::BrowserContext* browser_context,
|
|
|
|
const extensions::Extension* extension) {
|
|
|
|
Emit("extension-loaded", extension);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Session::OnExtensionUnloaded(content::BrowserContext* browser_context,
|
|
|
|
const extensions::Extension* extension,
|
|
|
|
extensions::UnloadedExtensionReason reason) {
|
|
|
|
Emit("extension-unloaded", extension);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Session::OnExtensionReady(content::BrowserContext* browser_context,
|
|
|
|
const extensions::Extension* extension) {
|
|
|
|
Emit("extension-ready", extension);
|
|
|
|
}
|
2019-07-24 23:01:08 +00:00
|
|
|
#endif
|
|
|
|
|
2015-06-16 09:23:29 +00:00
|
|
|
v8::Local<v8::Value> Session::Cookies(v8::Isolate* isolate) {
|
|
|
|
if (cookies_.IsEmpty()) {
|
2016-09-21 23:24:03 +00:00
|
|
|
auto handle = Cookies::Create(isolate, browser_context());
|
2015-06-16 09:23:29 +00:00
|
|
|
cookies_.Reset(isolate, handle.ToV8());
|
|
|
|
}
|
2020-03-26 17:34:32 +00:00
|
|
|
return cookies_.Get(isolate);
|
2015-06-16 09:23:29 +00:00
|
|
|
}
|
|
|
|
|
2016-06-08 14:31:27 +00:00
|
|
|
v8::Local<v8::Value> Session::Protocol(v8::Isolate* isolate) {
|
2020-03-26 17:34:32 +00:00
|
|
|
return protocol_.Get(isolate);
|
2016-06-08 14:31:27 +00:00
|
|
|
}
|
|
|
|
|
2020-02-20 23:19:06 +00:00
|
|
|
v8::Local<v8::Value> Session::ServiceWorkerContext(v8::Isolate* isolate) {
|
|
|
|
if (service_worker_context_.IsEmpty()) {
|
|
|
|
v8::Local<v8::Value> handle;
|
|
|
|
handle = ServiceWorkerContext::Create(isolate, browser_context()).ToV8();
|
|
|
|
service_worker_context_.Reset(isolate, handle);
|
|
|
|
}
|
2020-03-26 17:34:32 +00:00
|
|
|
return service_worker_context_.Get(isolate);
|
2020-02-20 23:19:06 +00:00
|
|
|
}
|
|
|
|
|
2015-12-01 04:52:22 +00:00
|
|
|
v8::Local<v8::Value> Session::WebRequest(v8::Isolate* isolate) {
|
|
|
|
if (web_request_.IsEmpty()) {
|
2019-10-24 00:51:06 +00:00
|
|
|
auto handle = WebRequest::Create(isolate, browser_context());
|
2019-08-11 04:24:51 +00:00
|
|
|
web_request_.Reset(isolate, handle.ToV8());
|
2015-12-01 04:52:22 +00:00
|
|
|
}
|
2020-03-26 17:34:32 +00:00
|
|
|
return web_request_.Get(isolate);
|
2015-12-01 04:52:22 +00:00
|
|
|
}
|
|
|
|
|
2018-10-04 18:08:56 +00:00
|
|
|
v8::Local<v8::Value> Session::NetLog(v8::Isolate* isolate) {
|
|
|
|
if (net_log_.IsEmpty()) {
|
2020-03-26 17:34:32 +00:00
|
|
|
auto handle = NetLog::Create(isolate, browser_context());
|
2018-10-04 18:08:56 +00:00
|
|
|
net_log_.Reset(isolate, handle.ToV8());
|
|
|
|
}
|
2020-03-26 17:34:32 +00:00
|
|
|
return net_log_.Get(isolate);
|
2018-10-04 18:08:56 +00:00
|
|
|
}
|
|
|
|
|
2020-08-17 20:21:53 +00:00
|
|
|
static void StartPreconnectOnUI(ElectronBrowserContext* browser_context,
|
|
|
|
const GURL& url,
|
|
|
|
int num_sockets_to_preconnect) {
|
2019-08-26 16:47:32 +00:00
|
|
|
std::vector<predictors::PreconnectRequest> requests = {
|
2019-12-11 00:22:35 +00:00
|
|
|
{url::Origin::Create(url), num_sockets_to_preconnect,
|
|
|
|
net::NetworkIsolationKey()}};
|
2019-08-26 16:47:32 +00:00
|
|
|
browser_context->GetPreconnectManager()->Start(url, requests);
|
|
|
|
}
|
|
|
|
|
2019-10-25 13:03:28 +00:00
|
|
|
void Session::Preconnect(const gin_helper::Dictionary& options,
|
2020-05-19 17:18:12 +00:00
|
|
|
gin::Arguments* args) {
|
2019-08-26 16:47:32 +00:00
|
|
|
GURL url;
|
|
|
|
if (!options.Get("url", &url) || !url.is_valid()) {
|
2020-05-19 17:18:12 +00:00
|
|
|
args->ThrowTypeError(
|
|
|
|
"Must pass non-empty valid url to session.preconnect.");
|
2019-08-26 16:47:32 +00:00
|
|
|
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) {
|
2020-05-19 17:18:12 +00:00
|
|
|
args->ThrowTypeError(
|
2019-08-26 16:47:32 +00:00
|
|
|
base::StringPrintf("numSocketsToPreconnect is outside range [%d,%d]",
|
|
|
|
kMinSocketsToPreconnect, kMaxSocketsToPreconnect));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DCHECK_GT(num_sockets_to_preconnect, 0);
|
2019-09-18 19:58:00 +00:00
|
|
|
base::PostTask(
|
2019-08-26 16:47:32 +00:00
|
|
|
FROM_HERE, {content::BrowserThread::UI},
|
2020-08-17 20:21:53 +00:00
|
|
|
base::BindOnce(&StartPreconnectOnUI, base::Unretained(browser_context_),
|
2019-08-26 16:47:32 +00:00
|
|
|
url, num_sockets_to_preconnect));
|
|
|
|
}
|
|
|
|
|
2020-10-08 16:45:36 +00:00
|
|
|
v8::Local<v8::Promise> Session::CloseAllConnections() {
|
|
|
|
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
|
|
|
gin_helper::Promise<void> promise(isolate);
|
|
|
|
auto handle = promise.GetHandle();
|
|
|
|
|
|
|
|
content::BrowserContext::GetDefaultStoragePartition(browser_context_)
|
|
|
|
->GetNetworkContext()
|
|
|
|
->CloseAllConnections(base::BindOnce(
|
|
|
|
gin_helper::Promise<void>::ResolvePromise, std::move(promise)));
|
|
|
|
|
|
|
|
return handle;
|
|
|
|
}
|
|
|
|
|
2019-10-31 20:11:51 +00:00
|
|
|
#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);
|
2020-10-23 07:34:19 +00:00
|
|
|
// Enable spellcheck if > 0 languages, disable if no languages set
|
|
|
|
browser_context_->prefs()->SetBoolean(spellcheck::prefs::kSpellCheckEnable,
|
|
|
|
!languages.empty());
|
2019-10-31 20:11:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2020-02-25 22:57:28 +00:00
|
|
|
SpellcheckHunspellDictionary::SetBaseDownloadURL(url);
|
2019-10-31 20:11:51 +00:00
|
|
|
}
|
2019-11-26 21:16:43 +00:00
|
|
|
|
2020-02-10 22:08:53 +00:00
|
|
|
v8::Local<v8::Promise> Session::ListWordsInSpellCheckerDictionary() {
|
2020-06-22 16:35:24 +00:00
|
|
|
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
2020-05-19 17:18:12 +00:00
|
|
|
gin_helper::Promise<std::set<std::string>> promise(isolate);
|
2020-02-10 22:08:53 +00:00
|
|
|
v8::Local<v8::Promise> handle = promise.GetHandle();
|
|
|
|
|
|
|
|
SpellcheckService* spellcheck =
|
2020-08-17 20:21:53 +00:00
|
|
|
SpellcheckServiceFactory::GetForContext(browser_context_);
|
2020-02-10 22:08:53 +00:00
|
|
|
|
2020-10-22 17:53:42 +00:00
|
|
|
if (!spellcheck) {
|
2020-02-10 22:08:53 +00:00
|
|
|
promise.RejectWithErrorMessage(
|
|
|
|
"Spellcheck in unexpected state: failed to load custom dictionary.");
|
2020-10-22 17:53:42 +00:00
|
|
|
return handle;
|
|
|
|
}
|
2020-02-10 22:08:53 +00:00
|
|
|
|
|
|
|
if (spellcheck->GetCustomDictionary()->IsLoaded()) {
|
|
|
|
promise.Resolve(spellcheck->GetCustomDictionary()->GetWords());
|
|
|
|
} else {
|
|
|
|
new DictionaryObserver(std::move(promise), spellcheck->GetWeakPtr());
|
|
|
|
// Dictionary loads by default asynchronously,
|
|
|
|
// call the load function anyways just to be sure.
|
|
|
|
spellcheck->GetCustomDictionary()->Load();
|
|
|
|
}
|
|
|
|
|
|
|
|
return handle;
|
|
|
|
}
|
|
|
|
|
2019-11-26 21:16:43 +00:00
|
|
|
bool Session::AddWordToSpellCheckerDictionary(const std::string& word) {
|
2020-03-10 07:45:43 +00:00
|
|
|
// don't let in-memory sessions add spellchecker words
|
|
|
|
// because files will persist unintentionally
|
|
|
|
bool is_in_memory = browser_context_->IsOffTheRecord();
|
|
|
|
if (is_in_memory)
|
|
|
|
return false;
|
|
|
|
|
2020-02-06 07:05:30 +00:00
|
|
|
SpellcheckService* service =
|
2020-08-17 20:21:53 +00:00
|
|
|
SpellcheckServiceFactory::GetForContext(browser_context_);
|
2020-02-06 07:05:30 +00:00
|
|
|
if (!service)
|
|
|
|
return false;
|
|
|
|
|
2019-11-26 21:16:43 +00:00
|
|
|
#if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
|
|
|
|
if (spellcheck::UseBrowserSpellChecker()) {
|
2020-02-06 07:05:30 +00:00
|
|
|
spellcheck_platform::AddWord(service->platform_spell_checker(),
|
|
|
|
base::UTF8ToUTF16(word));
|
2019-11-26 21:16:43 +00:00
|
|
|
}
|
|
|
|
#endif
|
2020-02-06 07:05:30 +00:00
|
|
|
return service->GetCustomDictionary()->AddWord(word);
|
2019-11-26 21:16:43 +00:00
|
|
|
}
|
2020-02-10 22:07:25 +00:00
|
|
|
|
|
|
|
bool Session::RemoveWordFromSpellCheckerDictionary(const std::string& word) {
|
2020-03-10 07:45:43 +00:00
|
|
|
// don't let in-memory sessions remove spellchecker words
|
|
|
|
// because files will persist unintentionally
|
|
|
|
bool is_in_memory = browser_context_->IsOffTheRecord();
|
|
|
|
if (is_in_memory)
|
|
|
|
return false;
|
|
|
|
|
2020-02-10 22:07:25 +00:00
|
|
|
SpellcheckService* service =
|
2020-08-17 20:21:53 +00:00
|
|
|
SpellcheckServiceFactory::GetForContext(browser_context_);
|
2020-02-10 22:07:25 +00:00
|
|
|
if (!service)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
#if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
|
|
|
|
if (spellcheck::UseBrowserSpellChecker()) {
|
|
|
|
spellcheck_platform::RemoveWord(service->platform_spell_checker(),
|
|
|
|
base::UTF8ToUTF16(word));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return service->GetCustomDictionary()->RemoveWord(word);
|
|
|
|
}
|
2020-03-10 09:39:40 +00:00
|
|
|
#endif // BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
|
2019-10-31 20:11:51 +00:00
|
|
|
|
2020-05-19 17:18:12 +00:00
|
|
|
// static
|
|
|
|
Session* Session::FromBrowserContext(content::BrowserContext* context) {
|
2020-10-26 18:56:31 +00:00
|
|
|
auto* data =
|
2020-05-19 17:18:12 +00:00
|
|
|
static_cast<UserDataLink*>(context->GetUserData(kElectronApiSessionKey));
|
|
|
|
return data ? data->session : nullptr;
|
|
|
|
}
|
|
|
|
|
2015-06-16 09:23:29 +00:00
|
|
|
// static
|
2020-02-04 20:19:40 +00:00
|
|
|
gin::Handle<Session> Session::CreateFrom(
|
|
|
|
v8::Isolate* isolate,
|
|
|
|
ElectronBrowserContext* browser_context) {
|
2020-05-19 17:18:12 +00:00
|
|
|
Session* existing = FromBrowserContext(browser_context);
|
2015-06-24 07:37:04 +00:00
|
|
|
if (existing)
|
2020-05-19 17:18:12 +00:00
|
|
|
return gin::CreateHandle(isolate, existing);
|
2015-06-24 07:37:04 +00:00
|
|
|
|
2018-04-18 01:55:30 +00:00
|
|
|
auto handle =
|
2019-10-25 13:03:28 +00:00
|
|
|
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.
|
2020-05-19 17:18:12 +00:00
|
|
|
handle->Pin(isolate);
|
|
|
|
|
|
|
|
App::Get()->EmitCustomEvent("session-created",
|
|
|
|
handle.ToV8().As<v8::Object>());
|
2016-08-01 11:11:17 +00:00
|
|
|
|
2015-09-01 10:02:14 +00:00
|
|
|
return handle;
|
|
|
|
}
|
|
|
|
|
2015-09-05 14:39:48 +00:00
|
|
|
// static
|
2019-10-30 05:30:59 +00:00
|
|
|
gin::Handle<Session> Session::FromPartition(v8::Isolate* isolate,
|
|
|
|
const std::string& partition,
|
|
|
|
base::DictionaryValue options) {
|
2020-08-17 20:21:53 +00:00
|
|
|
ElectronBrowserContext* browser_context;
|
2016-07-12 12:01:49 +00:00
|
|
|
if (partition.empty()) {
|
2020-02-04 20:19:40 +00:00
|
|
|
browser_context =
|
|
|
|
ElectronBrowserContext::From("", false, std::move(options));
|
2016-07-12 12:01:49 +00:00
|
|
|
} else if (base::StartsWith(partition, kPersistPrefix,
|
|
|
|
base::CompareCase::SENSITIVE)) {
|
|
|
|
std::string name = partition.substr(8);
|
2020-02-04 20:19:40 +00:00
|
|
|
browser_context =
|
|
|
|
ElectronBrowserContext::From(name, false, std::move(options));
|
2016-07-12 12:01:49 +00:00
|
|
|
} else {
|
2019-10-30 05:30:59 +00:00
|
|
|
browser_context =
|
2020-02-04 20:19:40 +00:00
|
|
|
ElectronBrowserContext::From(partition, true, std::move(options));
|
2016-07-12 12:01:49 +00:00
|
|
|
}
|
2020-08-17 20:21:53 +00:00
|
|
|
return CreateFrom(isolate, browser_context);
|
2015-09-05 14:39:48 +00:00
|
|
|
}
|
|
|
|
|
2020-05-19 17:18:12 +00:00
|
|
|
gin::ObjectTemplateBuilder Session::GetObjectTemplateBuilder(
|
|
|
|
v8::Isolate* isolate) {
|
|
|
|
return gin_helper::EventEmitterMixin<Session>::GetObjectTemplateBuilder(
|
|
|
|
isolate)
|
2015-12-03 08:04:46 +00:00
|
|
|
.SetMethod("resolveProxy", &Session::ResolveProxy)
|
2019-04-30 22:09:17 +00:00
|
|
|
.SetMethod("getCacheSize", &Session::GetCacheSize)
|
|
|
|
.SetMethod("clearCache", &Session::ClearCache)
|
2015-12-03 08:04:46 +00:00
|
|
|
.SetMethod("clearStorageData", &Session::ClearStorageData)
|
2016-01-12 15:28:12 +00:00
|
|
|
.SetMethod("flushStorageData", &Session::FlushStorageData)
|
2015-12-03 08:04:46 +00:00
|
|
|
.SetMethod("setProxy", &Session::SetProxy)
|
2020-10-27 06:50:06 +00:00
|
|
|
.SetMethod("forceReloadProxyConfig", &Session::ForceReloadProxyConfig)
|
2015-12-03 08:04:46 +00:00
|
|
|
.SetMethod("setDownloadPath", &Session::SetDownloadPath)
|
|
|
|
.SetMethod("enableNetworkEmulation", &Session::EnableNetworkEmulation)
|
|
|
|
.SetMethod("disableNetworkEmulation", &Session::DisableNetworkEmulation)
|
2018-05-23 20:51:28 +00:00
|
|
|
.SetMethod("setCertificateVerifyProc", &Session::SetCertVerifyProc)
|
2016-01-31 21:35:34 +00:00
|
|
|
.SetMethod("setPermissionRequestHandler",
|
|
|
|
&Session::SetPermissionRequestHandler)
|
2018-08-28 14:05:08 +00:00
|
|
|
.SetMethod("setPermissionCheckHandler",
|
|
|
|
&Session::SetPermissionCheckHandler)
|
2016-02-01 13:33:23 +00:00
|
|
|
.SetMethod("clearHostResolverCache", &Session::ClearHostResolverCache)
|
2016-11-30 16:35:15 +00:00
|
|
|
.SetMethod("clearAuthCache", &Session::ClearAuthCache)
|
2016-05-23 05:29:55 +00:00
|
|
|
.SetMethod("allowNTLMCredentialsForDomains",
|
|
|
|
&Session::AllowNTLMCredentialsForDomains)
|
2020-03-11 07:02:22 +00:00
|
|
|
.SetMethod("isPersistent", &Session::IsPersistent)
|
2016-06-22 06:57:51 +00:00
|
|
|
.SetMethod("setUserAgent", &Session::SetUserAgent)
|
|
|
|
.SetMethod("getUserAgent", &Session::GetUserAgent)
|
2020-09-23 20:22:10 +00:00
|
|
|
.SetMethod("setSSLConfig", &Session::SetSSLConfig)
|
2016-08-23 05:57:43 +00:00
|
|
|
.SetMethod("getBlobData", &Session::GetBlobData)
|
2019-08-29 03:27:20 +00:00
|
|
|
.SetMethod("downloadURL", &Session::DownloadURL)
|
2016-11-18 10:43:43 +00:00
|
|
|
.SetMethod("createInterruptedDownload",
|
|
|
|
&Session::CreateInterruptedDownload)
|
2017-12-05 06:59:15 +00:00
|
|
|
.SetMethod("setPreloads", &Session::SetPreloads)
|
2017-09-16 15:05:49 +00:00
|
|
|
.SetMethod("getPreloads", &Session::GetPreloads)
|
2019-07-24 23:01:08 +00:00
|
|
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
2020-01-13 22:56:28 +00:00
|
|
|
.SetMethod("loadExtension", &Session::LoadExtension)
|
|
|
|
.SetMethod("removeExtension", &Session::RemoveExtension)
|
|
|
|
.SetMethod("getExtension", &Session::GetExtension)
|
|
|
|
.SetMethod("getAllExtensions", &Session::GetAllExtensions)
|
2019-10-31 20:11:51 +00:00
|
|
|
#endif
|
|
|
|
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
|
|
|
|
.SetMethod("getSpellCheckerLanguages", &Session::GetSpellCheckerLanguages)
|
|
|
|
.SetMethod("setSpellCheckerLanguages", &Session::SetSpellCheckerLanguages)
|
|
|
|
.SetProperty("availableSpellCheckerLanguages",
|
|
|
|
&spellcheck::SpellCheckLanguages)
|
|
|
|
.SetMethod("setSpellCheckerDictionaryDownloadURL",
|
|
|
|
&SetSpellCheckerDictionaryDownloadURL)
|
2020-02-10 22:08:53 +00:00
|
|
|
.SetMethod("listWordsInSpellCheckerDictionary",
|
|
|
|
&Session::ListWordsInSpellCheckerDictionary)
|
2019-11-26 21:16:43 +00:00
|
|
|
.SetMethod("addWordToSpellCheckerDictionary",
|
|
|
|
&Session::AddWordToSpellCheckerDictionary)
|
2020-02-10 22:07:25 +00:00
|
|
|
.SetMethod("removeWordFromSpellCheckerDictionary",
|
|
|
|
&Session::RemoveWordFromSpellCheckerDictionary)
|
2019-07-24 23:01:08 +00:00
|
|
|
#endif
|
2019-08-26 16:47:32 +00:00
|
|
|
.SetMethod("preconnect", &Session::Preconnect)
|
2020-10-08 16:45:36 +00:00
|
|
|
.SetMethod("closeAllConnections", &Session::CloseAllConnections)
|
2015-12-01 04:52:22 +00:00
|
|
|
.SetProperty("cookies", &Session::Cookies)
|
2018-10-04 18:08:56 +00:00
|
|
|
.SetProperty("netLog", &Session::NetLog)
|
2016-06-08 14:31:27 +00:00
|
|
|
.SetProperty("protocol", &Session::Protocol)
|
2020-02-20 23:19:06 +00:00
|
|
|
.SetProperty("serviceWorkers", &Session::ServiceWorkerContext)
|
2015-12-01 04:52:22 +00:00
|
|
|
.SetProperty("webRequest", &Session::WebRequest);
|
2015-12-03 08:04:46 +00:00
|
|
|
}
|
|
|
|
|
2020-05-19 17:18:12 +00:00
|
|
|
const char* Session::GetTypeName() {
|
|
|
|
return "Session";
|
|
|
|
}
|
|
|
|
|
2015-06-16 09:23:29 +00:00
|
|
|
} // namespace api
|
|
|
|
|
2019-06-19 21:23:04 +00:00
|
|
|
} // namespace electron
|
2015-09-01 10:02:14 +00:00
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
2019-06-19 21:23:04 +00:00
|
|
|
using electron::api::Cookies;
|
2019-10-24 00:51:06 +00:00
|
|
|
using electron::api::Protocol;
|
2020-02-20 23:19:06 +00:00
|
|
|
using electron::api::ServiceWorkerContext;
|
2019-06-19 21:23:04 +00:00
|
|
|
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,
|
2020-05-19 17:18:12 +00:00
|
|
|
gin::Arguments* args) {
|
2019-06-19 21:23:04 +00:00
|
|
|
if (!electron::Browser::Get()->is_ready()) {
|
2020-05-19 17:18:12 +00:00
|
|
|
args->ThrowTypeError("Session can only be received when app is ready");
|
2016-07-12 11:21:59 +00:00
|
|
|
return v8::Null(args->isolate());
|
|
|
|
}
|
2016-07-12 12:53:19 +00:00
|
|
|
base::DictionaryValue options;
|
|
|
|
args->GetNext(&options);
|
2019-10-30 05:30:59 +00:00
|
|
|
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();
|
2019-10-25 13:03:28 +00:00
|
|
|
gin_helper::Dictionary dict(isolate, exports);
|
2016-07-12 11:21:59 +00:00
|
|
|
dict.SetMethod("fromPartition", &FromPartition);
|
2015-09-01 10:02:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
2020-02-14 11:25:39 +00:00
|
|
|
NODE_LINKED_MODULE_CONTEXT_AWARE(electron_browser_session, Initialize)
|