123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869 |
- // 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/electron_api_session.h"
- #include <algorithm>
- #include <memory>
- #include <set>
- #include <string>
- #include <utility>
- #include <vector>
- #include "base/command_line.h"
- #include "base/containers/fixed_flat_map.h"
- #include "base/files/file_enumerator.h"
- #include "base/files/file_path.h"
- #include "base/files/file_util.h"
- #include "base/scoped_observation.h"
- #include "base/strings/string_util.h"
- #include "base/uuid.h"
- #include "chrome/browser/browser_process.h"
- #include "chrome/browser/predictors/preconnect_manager.h"
- #include "chrome/common/chrome_switches.h"
- #include "chrome/common/pref_names.h"
- #include "components/download/public/common/download_danger_type.h"
- #include "components/download/public/common/download_url_parameters.h"
- #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 "components/proxy_config/proxy_prefs.h"
- #include "content/browser/code_cache/generated_code_cache_context.h" // nogncheck
- #include "content/public/browser/browser_task_traits.h"
- #include "content/public/browser/browser_thread.h"
- #include "content/public/browser/browsing_data_filter_builder.h"
- #include "content/public/browser/browsing_data_remover.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 "gin/arguments.h"
- #include "gin/converter.h"
- #include "gin/handle.h"
- #include "mojo/public/cpp/bindings/pending_remote.h"
- #include "mojo/public/cpp/bindings/self_owned_receiver.h"
- #include "net/base/completion_repeating_callback.h"
- #include "net/base/load_flags.h"
- #include "net/base/network_anonymization_key.h"
- #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
- #include "net/http/http_auth_handler_factory.h"
- #include "net/http/http_auth_preferences.h"
- #include "net/http/http_cache.h"
- #include "net/http/http_util.h"
- #include "services/network/network_service.h"
- #include "services/network/public/cpp/features.h"
- #include "services/network/public/cpp/request_destination.h"
- #include "services/network/public/mojom/clear_data_filter.mojom.h"
- #include "shell/browser/api/electron_api_app.h"
- #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"
- #include "shell/browser/api/electron_api_service_worker_context.h"
- #include "shell/browser/api/electron_api_web_frame_main.h"
- #include "shell/browser/api/electron_api_web_request.h"
- #include "shell/browser/browser.h"
- #include "shell/browser/electron_browser_context.h"
- #include "shell/browser/electron_browser_main_parts.h"
- #include "shell/browser/electron_permission_manager.h"
- #include "shell/browser/javascript_environment.h"
- #include "shell/browser/media/media_device_id_salt.h"
- #include "shell/browser/net/cert_verifier_client.h"
- #include "shell/browser/net/resolve_host_function.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/media_converter.h"
- #include "shell/common/gin_converters/net_converter.h"
- #include "shell/common/gin_converters/time_converter.h"
- #include "shell/common/gin_converters/usb_protected_classes_converter.h"
- #include "shell/common/gin_converters/value_converter.h"
- #include "shell/common/gin_helper/dictionary.h"
- #include "shell/common/gin_helper/error_thrower.h"
- #include "shell/common/gin_helper/object_template_builder.h"
- #include "shell/common/gin_helper/promise.h"
- #include "shell/common/node_includes.h"
- #include "shell/common/node_util.h"
- #include "shell/common/options_switches.h"
- #include "third_party/abseil-cpp/absl/strings/str_format.h"
- #include "third_party/blink/public/common/storage_key/storage_key.h"
- #include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h"
- #include "ui/base/l10n/l10n_util.h"
- #include "url/origin.h"
- #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
- #include "shell/browser/api/electron_api_extensions.h"
- #endif
- #if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
- #include "chrome/browser/spellchecker/spellcheck_factory.h" // nogncheck
- #include "chrome/browser/spellchecker/spellcheck_service.h" // nogncheck
- #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::BrowsingDataFilterBuilder;
- using content::BrowsingDataRemover;
- using content::StoragePartition;
- namespace {
- struct ClearStorageDataOptions {
- blink::StorageKey storage_key;
- uint32_t storage_types = StoragePartition::REMOVE_DATA_MASK_ALL;
- uint32_t quota_types = StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL;
- };
- uint32_t GetStorageMask(const std::vector<std::string>& storage_types) {
- static constexpr auto Lookup =
- base::MakeFixedFlatMap<std::string_view, uint32_t>(
- {{"cookies", StoragePartition::REMOVE_DATA_MASK_COOKIES},
- {"filesystem", StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS},
- {"indexdb", StoragePartition::REMOVE_DATA_MASK_INDEXEDDB},
- {"localstorage", StoragePartition::REMOVE_DATA_MASK_LOCAL_STORAGE},
- {"shadercache", StoragePartition::REMOVE_DATA_MASK_SHADER_CACHE},
- {"serviceworkers",
- StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS},
- {"cachestorage", StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE}});
- uint32_t storage_mask = 0;
- for (const auto& it : storage_types) {
- auto type = base::ToLowerASCII(it);
- if (Lookup.contains(type))
- storage_mask |= Lookup.at(type);
- }
- return storage_mask;
- }
- uint32_t GetQuotaMask(const std::vector<std::string>& quota_types) {
- uint32_t quota_mask = 0;
- for (const auto& it : quota_types) {
- auto type = base::ToLowerASCII(it);
- if (type == "temporary")
- quota_mask |= StoragePartition::QUOTA_MANAGED_STORAGE_MASK_TEMPORARY;
- else if (type == "syncable")
- quota_mask |= StoragePartition::QUOTA_MANAGED_STORAGE_MASK_SYNCABLE;
- }
- return quota_mask;
- }
- constexpr BrowsingDataRemover::DataType kClearDataTypeAll =
- ~0ULL & ~BrowsingDataRemover::DATA_TYPE_AVOID_CLOSING_CONNECTIONS;
- constexpr BrowsingDataRemover::OriginType kClearOriginTypeAll =
- BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB |
- BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB;
- constexpr auto kDataTypeLookup =
- base::MakeFixedFlatMap<std::string_view, BrowsingDataRemover::DataType>({
- {"backgroundFetch", BrowsingDataRemover::DATA_TYPE_BACKGROUND_FETCH},
- {"cache", BrowsingDataRemover::DATA_TYPE_CACHE |
- BrowsingDataRemover::DATA_TYPE_CACHE_STORAGE},
- {"cookies", BrowsingDataRemover::DATA_TYPE_COOKIES},
- {"downloads", BrowsingDataRemover::DATA_TYPE_DOWNLOADS},
- {"fileSystems", BrowsingDataRemover::DATA_TYPE_FILE_SYSTEMS},
- {"indexedDB", BrowsingDataRemover::DATA_TYPE_INDEXED_DB},
- {"localStorage", BrowsingDataRemover::DATA_TYPE_LOCAL_STORAGE},
- {"serviceWorkers", BrowsingDataRemover::DATA_TYPE_SERVICE_WORKERS},
- });
- BrowsingDataRemover::DataType GetDataTypeMask(
- const std::vector<std::string>& data_types) {
- BrowsingDataRemover::DataType mask = 0u;
- for (const auto& type : data_types) {
- if (kDataTypeLookup.contains(type)) {
- mask |= kDataTypeLookup.at(type);
- }
- }
- return mask;
- }
- std::vector<std::string> GetDataTypesFromMask(
- BrowsingDataRemover::DataType mask) {
- std::vector<std::string> results;
- for (const auto [type, flag] : kDataTypeLookup) {
- if (mask & flag) {
- results.emplace_back(type);
- }
- }
- return results;
- }
- // Represents a task to clear browsing data for the `clearData` API method.
- //
- // This type manages its own lifetime, deleting itself once the task finishes
- // completely.
- class ClearDataTask {
- public:
- // Starts running a task. This function will return before the task is
- // finished, but will resolve or reject the |promise| when it finishes.
- static void Run(
- BrowsingDataRemover* remover,
- gin_helper::Promise<void> promise,
- BrowsingDataRemover::DataType data_type_mask,
- std::vector<url::Origin> origins,
- BrowsingDataFilterBuilder::Mode filter_mode,
- BrowsingDataFilterBuilder::OriginMatchingMode origin_matching_mode) {
- std::shared_ptr<ClearDataTask> task(new ClearDataTask(std::move(promise)));
- // This method counts as an operation. This is important so we can call
- // `OnOperationFinished` at the end of this method as a fallback if all the
- // other operations finished while this method was still executing
- task->operations_running_ = 1;
- // Cookies are scoped more broadly than other types of data, so if we are
- // filtering then we need to do it at the registrable domain level
- if (!origins.empty() &&
- data_type_mask & BrowsingDataRemover::DATA_TYPE_COOKIES) {
- data_type_mask &= ~BrowsingDataRemover::DATA_TYPE_COOKIES;
- auto cookies_filter_builder =
- BrowsingDataFilterBuilder::Create(filter_mode);
- for (const url::Origin& origin : origins) {
- std::string domain = GetDomainAndRegistry(
- origin,
- net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
- if (domain.empty()) {
- domain = origin.host();
- }
- cookies_filter_builder->AddRegisterableDomain(domain);
- }
- StartOperation(task, remover, BrowsingDataRemover::DATA_TYPE_COOKIES,
- std::move(cookies_filter_builder));
- }
- // If cookies aren't the only data type and weren't handled above, then we
- // can start an operation that is scoped to origins
- if (data_type_mask) {
- auto filter_builder =
- BrowsingDataFilterBuilder::Create(filter_mode, origin_matching_mode);
- for (auto const& origin : origins) {
- filter_builder->AddOrigin(origin);
- }
- StartOperation(task, remover, data_type_mask, std::move(filter_builder));
- }
- // This static method counts as an operation.
- task->OnOperationFinished(std::nullopt);
- }
- private:
- // An individual |content::BrowsingDataRemover::Remove...| operation as part
- // of a full |ClearDataTask|. This class manages its own lifetime, cleaning
- // itself up after the operation completes and notifies the task of the
- // result.
- class ClearDataOperation : private BrowsingDataRemover::Observer {
- public:
- static void Run(std::shared_ptr<ClearDataTask> task,
- BrowsingDataRemover* remover,
- BrowsingDataRemover::DataType data_type_mask,
- std::unique_ptr<BrowsingDataFilterBuilder> filter_builder) {
- auto* operation = new ClearDataOperation(task, remover);
- remover->RemoveWithFilterAndReply(base::Time::Min(), base::Time::Max(),
- data_type_mask, kClearOriginTypeAll,
- std::move(filter_builder), operation);
- }
- // BrowsingDataRemover::Observer:
- void OnBrowsingDataRemoverDone(
- BrowsingDataRemover::DataType failed_data_types) override {
- task_->OnOperationFinished(failed_data_types);
- delete this;
- }
- private:
- ClearDataOperation(std::shared_ptr<ClearDataTask> task,
- BrowsingDataRemover* remover)
- : task_(task) {
- observation_.Observe(remover);
- }
- std::shared_ptr<ClearDataTask> task_;
- base::ScopedObservation<BrowsingDataRemover, BrowsingDataRemover::Observer>
- observation_{this};
- };
- explicit ClearDataTask(gin_helper::Promise<void> promise)
- : promise_(std::move(promise)) {}
- static void StartOperation(
- std::shared_ptr<ClearDataTask> task,
- BrowsingDataRemover* remover,
- BrowsingDataRemover::DataType data_type_mask,
- std::unique_ptr<BrowsingDataFilterBuilder> filter_builder) {
- // Track this operation
- task->operations_running_ += 1;
- ClearDataOperation::Run(task, remover, data_type_mask,
- std::move(filter_builder));
- }
- void OnOperationFinished(
- std::optional<BrowsingDataRemover::DataType> failed_data_types) {
- DCHECK_GT(operations_running_, 0);
- operations_running_ -= 1;
- if (failed_data_types.has_value()) {
- failed_data_types_ |= failed_data_types.value();
- }
- // If this is the last operation, then the task is finished
- if (operations_running_ == 0) {
- OnTaskFinished();
- }
- }
- void OnTaskFinished() {
- if (failed_data_types_ == 0ULL) {
- promise_.Resolve();
- } else {
- v8::Isolate* isolate = promise_.isolate();
- v8::Local<v8::Value> failed_data_types_array =
- gin::ConvertToV8(isolate, GetDataTypesFromMask(failed_data_types_));
- // Create a rich error object with extra detail about what data types
- // failed
- auto error = v8::Exception::Error(
- gin::StringToV8(isolate, "Failed to clear data"));
- error.As<v8::Object>()
- ->Set(promise_.GetContext(),
- gin::StringToV8(isolate, "failedDataTypes"),
- failed_data_types_array)
- .Check();
- promise_.Reject(error);
- }
- }
- int operations_running_ = 0;
- BrowsingDataRemover::DataType failed_data_types_ = 0ULL;
- gin_helper::Promise<void> promise_;
- };
- base::Value::Dict createProxyConfig(ProxyPrefs::ProxyMode proxy_mode,
- std::string const& pac_url,
- std::string const& proxy_server,
- std::string const& bypass_list) {
- if (proxy_mode == ProxyPrefs::MODE_DIRECT) {
- return ProxyConfigDictionary::CreateDirect();
- }
- if (proxy_mode == ProxyPrefs::MODE_SYSTEM) {
- return ProxyConfigDictionary::CreateSystem();
- }
- if (proxy_mode == ProxyPrefs::MODE_AUTO_DETECT) {
- return ProxyConfigDictionary::CreateAutoDetect();
- }
- if (proxy_mode == ProxyPrefs::MODE_PAC_SCRIPT) {
- const bool pac_mandatory = true;
- return ProxyConfigDictionary::CreatePacScript(pac_url, pac_mandatory);
- }
- return ProxyConfigDictionary::CreateFixedServers(proxy_server, bypass_list);
- }
- } // namespace
- namespace gin {
- 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;
- if (GURL storage_origin; options.Get("origin", &storage_origin))
- out->storage_key = blink::StorageKey::CreateFirstParty(
- url::Origin::Create(storage_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;
- }
- };
- bool SSLProtocolVersionFromString(const std::string& version_str,
- network::mojom::SSLVersion* version) {
- 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;
- }
- 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;
- }
- };
- 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;
- }
- if (options.Has("disabledCipherSuites") &&
- !options.Get("disabledCipherSuites", &(*out)->disabled_cipher_suites)) {
- return false;
- }
- std::ranges::sort((*out)->disabled_cipher_suites);
- // TODO(nornagon): also support other SSLConfig properties?
- return true;
- }
- };
- } // namespace gin
- namespace electron::api {
- namespace {
- const char kPersistPrefix[] = "persist:";
- 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) {
- download_manager->CreateDownloadItem(
- base::Uuid::GenerateRandomV4().AsLowercaseString(), id, path, path,
- url_chain, GURL(),
- content::StoragePartitionConfig::CreateDefault(
- download_manager->GetBrowserContext()),
- GURL(), GURL(), std::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>());
- }
- #if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
- 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
- }
- };
- #endif // BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
- struct UserDataLink : base::SupportsUserData::Data {
- explicit UserDataLink(base::WeakPtr<Session> session_in)
- : session{std::move(session_in)} {}
- base::WeakPtr<Session> session;
- };
- const void* kElectronApiSessionKey = &kElectronApiSessionKey;
- } // namespace
- gin::WrapperInfo Session::kWrapperInfo = {gin::kEmbedderNativeGin};
- Session::Session(v8::Isolate* isolate, ElectronBrowserContext* browser_context)
- : isolate_(isolate),
- network_emulation_token_(base::UnguessableToken::Create()),
- browser_context_{
- raw_ref<ElectronBrowserContext>::from_ptr(browser_context)} {
- // Observe DownloadManager to get download notifications.
- browser_context->GetDownloadManager()->AddObserver(this);
- SessionPreferences::CreateForBrowserContext(browser_context);
- protocol_.Reset(isolate, Protocol::Create(isolate, browser_context).ToV8());
- browser_context->SetUserData(
- kElectronApiSessionKey,
- std::make_unique<UserDataLink>(weak_factory_.GetWeakPtr()));
- #if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
- if (auto* service =
- SpellcheckServiceFactory::GetForContext(browser_context)) {
- service->SetHunspellObserver(this);
- }
- #endif
- }
- Session::~Session() {
- browser_context()->GetDownloadManager()->RemoveObserver(this);
- #if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
- if (auto* service =
- SpellcheckServiceFactory::GetForContext(browser_context())) {
- service->SetHunspellObserver(nullptr);
- }
- #endif
- }
- void Session::OnDownloadCreated(content::DownloadManager* manager,
- download::DownloadItem* item) {
- if (item->IsSavePackageDownload())
- return;
- v8::HandleScope handle_scope(isolate_);
- auto handle = DownloadItem::FromOrCreate(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();
- }
- }
- #if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
- 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);
- }
- #endif
- v8::Local<v8::Promise> Session::ResolveProxy(gin::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;
- }
- v8::Local<v8::Promise> Session::ResolveHost(
- std::string host,
- std::optional<network::mojom::ResolveHostParametersPtr> params) {
- gin_helper::Promise<gin_helper::Dictionary> promise(isolate_);
- v8::Local<v8::Promise> handle = promise.GetHandle();
- auto fn = base::MakeRefCounted<ResolveHostFunction>(
- browser_context(), std::move(host),
- params ? std::move(params.value()) : nullptr,
- base::BindOnce(
- [](gin_helper::Promise<gin_helper::Dictionary> promise,
- int64_t net_error, const std::optional<net::AddressList>& addrs) {
- if (net_error < 0) {
- promise.RejectWithErrorMessage(net::ErrorToString(net_error));
- } else {
- DCHECK(addrs.has_value() && !addrs->empty());
- v8::HandleScope handle_scope(promise.isolate());
- auto dict =
- gin_helper::Dictionary::CreateEmpty(promise.isolate());
- dict.Set("endpoints", addrs->endpoints());
- promise.Resolve(dict);
- }
- },
- std::move(promise)));
- fn->Run();
- return handle;
- }
- v8::Local<v8::Promise> Session::GetCacheSize() {
- gin_helper::Promise<int64_t> promise(isolate_);
- auto handle = promise.GetHandle();
- browser_context_->GetDefaultStoragePartition()
- ->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() {
- gin_helper::Promise<void> promise(isolate_);
- auto handle = promise.GetHandle();
- browser_context_->GetDefaultStoragePartition()
- ->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::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 = browser_context()->GetStoragePartition(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.storage_key,
- base::Time(), base::Time::Max(),
- base::BindOnce(gin_helper::Promise<void>::ResolvePromise,
- std::move(promise)));
- return handle;
- }
- void Session::FlushStorageData() {
- auto* storage_partition = browser_context()->GetStoragePartition(nullptr);
- storage_partition->Flush();
- }
- v8::Local<v8::Promise> Session::SetProxy(gin::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 mode, proxy_rules, bypass_list, pac_url;
- options.Get("pacScript", &pac_url);
- options.Get("proxyRules", &proxy_rules);
- options.Get("proxyBypassRules", &bypass_list);
- 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;
- }
- }
- browser_context_->in_memory_pref_store()->SetValue(
- proxy_config::prefs::kProxy,
- base::Value{
- createProxyConfig(proxy_mode, pac_url, proxy_rules, bypass_list)},
- WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
- base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
- FROM_HERE, base::BindOnce(gin_helper::Promise<void>::ResolvePromise,
- std::move(promise)));
- return handle;
- }
- v8::Local<v8::Promise> Session::ForceReloadProxyConfig() {
- gin_helper::Promise<void> promise(isolate_);
- auto handle = promise.GetHandle();
- browser_context_->GetDefaultStoragePartition()
- ->GetNetworkContext()
- ->ForceReloadProxyConfig(base::BindOnce(
- gin_helper::Promise<void>::ResolvePromise, std::move(promise)));
- return handle;
- }
- void Session::SetDownloadPath(const base::FilePath& path) {
- browser_context_->prefs()->SetFilePath(prefs::kDownloadDefaultDirectory,
- path);
- }
- 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::Milliseconds(latency);
- }
- auto* network_context =
- browser_context_->GetDefaultStoragePartition()->GetNetworkContext();
- network_context->SetNetworkConditions(network_emulation_token_,
- std::move(conditions));
- }
- void Session::DisableNetworkEmulation() {
- auto* network_context =
- browser_context_->GetDefaultStoragePartition()->GetNetworkContext();
- network_context->SetNetworkConditions(
- network_emulation_token_, network::mojom::NetworkConditions::New());
- }
- void Session::SetCertVerifyProc(v8::Local<v8::Value> val,
- gin::Arguments* args) {
- CertVerifierClient::CertVerifyProc proc;
- if (!(val->IsNull() || gin::ConvertFromV8(args->isolate(), val, &proc))) {
- args->ThrowTypeError("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());
- }
- browser_context_->GetDefaultStoragePartition()
- ->GetNetworkContext()
- ->SetCertVerifierClient(std::move(cert_verifier_client_remote));
- }
- void Session::SetPermissionRequestHandler(v8::Local<v8::Value> val,
- gin::Arguments* args) {
- auto* permission_manager = static_cast<ElectronPermissionManager*>(
- browser_context()->GetPermissionControllerDelegate());
- if (val->IsNull()) {
- permission_manager->SetPermissionRequestHandler(
- ElectronPermissionManager::RequestHandler());
- return;
- }
- auto handler = std::make_unique<ElectronPermissionManager::RequestHandler>();
- if (!gin::ConvertFromV8(args->isolate(), val, handler.get())) {
- args->ThrowTypeError("Must pass null or function");
- return;
- }
- permission_manager->SetPermissionRequestHandler(base::BindRepeating(
- [](ElectronPermissionManager::RequestHandler* handler,
- content::WebContents* web_contents,
- blink::PermissionType permission_type,
- ElectronPermissionManager::StatusCallback callback,
- const base::Value& details) {
- handler->Run(web_contents, permission_type, std::move(callback),
- details);
- },
- base::Owned(std::move(handler))));
- }
- void Session::SetPermissionCheckHandler(v8::Local<v8::Value> val,
- gin::Arguments* args) {
- ElectronPermissionManager::CheckHandler handler;
- if (!(val->IsNull() || gin::ConvertFromV8(args->isolate(), val, &handler))) {
- args->ThrowTypeError("Must pass null or function");
- return;
- }
- auto* permission_manager = static_cast<ElectronPermissionManager*>(
- browser_context()->GetPermissionControllerDelegate());
- permission_manager->SetPermissionCheckHandler(handler);
- }
- void Session::SetDisplayMediaRequestHandler(v8::Isolate* isolate,
- v8::Local<v8::Value> val) {
- if (val->IsNull()) {
- browser_context_->SetDisplayMediaRequestHandler(
- DisplayMediaRequestHandler());
- return;
- }
- DisplayMediaRequestHandler handler;
- if (!gin::ConvertFromV8(isolate, val, &handler)) {
- gin_helper::ErrorThrower(isolate).ThrowTypeError(
- "Display media request handler must be null or a function");
- return;
- }
- browser_context_->SetDisplayMediaRequestHandler(handler);
- }
- void Session::SetDevicePermissionHandler(v8::Local<v8::Value> val,
- gin::Arguments* args) {
- ElectronPermissionManager::DeviceCheckHandler handler;
- if (!(val->IsNull() || gin::ConvertFromV8(args->isolate(), val, &handler))) {
- args->ThrowTypeError("Must pass null or function");
- return;
- }
- auto* permission_manager = static_cast<ElectronPermissionManager*>(
- browser_context()->GetPermissionControllerDelegate());
- permission_manager->SetDevicePermissionHandler(handler);
- }
- void Session::SetUSBProtectedClassesHandler(v8::Local<v8::Value> val,
- gin::Arguments* args) {
- ElectronPermissionManager::ProtectedUSBHandler handler;
- if (!(val->IsNull() || gin::ConvertFromV8(args->isolate(), val, &handler))) {
- args->ThrowTypeError("Must pass null or function");
- return;
- }
- auto* permission_manager = static_cast<ElectronPermissionManager*>(
- browser_context()->GetPermissionControllerDelegate());
- permission_manager->SetProtectedUSBHandler(handler);
- }
- void Session::SetBluetoothPairingHandler(v8::Local<v8::Value> val,
- gin::Arguments* args) {
- ElectronPermissionManager::BluetoothPairingHandler handler;
- if (!(val->IsNull() || gin::ConvertFromV8(args->isolate(), val, &handler))) {
- args->ThrowTypeError("Must pass null or function");
- return;
- }
- auto* permission_manager = static_cast<ElectronPermissionManager*>(
- browser_context()->GetPermissionControllerDelegate());
- permission_manager->SetBluetoothPairingHandler(handler);
- }
- v8::Local<v8::Promise> Session::ClearHostResolverCache(gin::Arguments* args) {
- v8::Isolate* isolate = args->isolate();
- gin_helper::Promise<void> promise(isolate);
- v8::Local<v8::Promise> handle = promise.GetHandle();
- browser_context_->GetDefaultStoragePartition()
- ->GetNetworkContext()
- ->ClearHostCache(nullptr,
- base::BindOnce(gin_helper::Promise<void>::ResolvePromise,
- std::move(promise)));
- return handle;
- }
- v8::Local<v8::Promise> Session::ClearAuthCache() {
- gin_helper::Promise<void> promise(isolate_);
- v8::Local<v8::Promise> handle = promise.GetHandle();
- browser_context_->GetDefaultStoragePartition()
- ->GetNetworkContext()
- ->ClearHttpAuthCache(
- base::Time(), base::Time::Max(),
- nullptr /*mojom::ClearDataFilterPtr*/,
- base::BindOnce(gin_helper::Promise<void>::ResolvePromise,
- std::move(promise)));
- return handle;
- }
- void Session::AllowNTLMCredentialsForDomains(const std::string& domains) {
- auto* command_line = base::CommandLine::ForCurrentProcess();
- network::mojom::HttpAuthDynamicParamsPtr auth_dynamic_params =
- network::mojom::HttpAuthDynamicParams::New();
- auth_dynamic_params->server_allowlist = domains;
- auth_dynamic_params->enable_negotiate_port =
- command_line->HasSwitch(electron::switches::kEnableAuthNegotiatePort);
- auth_dynamic_params->ntlm_v2_enabled =
- !command_line->HasSwitch(electron::switches::kDisableNTLMv2);
- content::GetNetworkService()->ConfigureHttpAuthPrefs(
- std::move(auth_dynamic_params));
- }
- void Session::SetUserAgent(const std::string& user_agent,
- gin::Arguments* args) {
- browser_context_->SetUserAgent(user_agent);
- auto* network_context =
- browser_context_->GetDefaultStoragePartition()->GetNetworkContext();
- network_context->SetUserAgent(user_agent);
- std::string accept_lang;
- if (args->GetNext(&accept_lang)) {
- network_context->SetAcceptLanguage(
- net::HttpUtil::GenerateAcceptLanguageHeader(accept_lang));
- }
- }
- std::string Session::GetUserAgent() {
- return browser_context_->GetUserAgent();
- }
- void Session::SetSSLConfig(network::mojom::SSLConfigPtr config) {
- browser_context_->SetSSLConfig(std::move(config));
- }
- bool Session::IsPersistent() {
- return !browser_context_->IsOffTheRecord();
- }
- 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, gin::Arguments* args) {
- std::map<std::string, std::string> headers;
- gin_helper::Dictionary options;
- if (args->GetNext(&options)) {
- if (options.Has("headers") && !options.Get("headers", &headers)) {
- args->ThrowTypeError("Invalid value for headers - must be an object");
- return;
- }
- }
- auto download_params = std::make_unique<download::DownloadUrlParameters>(
- url, MISSING_TRAFFIC_ANNOTATION);
- for (const auto& [name, value] : headers) {
- download_params->add_request_header(name, value);
- }
- auto* download_manager = browser_context()->GetDownloadManager();
- 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().InSecondsFSinceUnixEpoch();
- 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);
- if (path.empty() || url_chain.empty() || length == 0) {
- isolate_->ThrowException(v8::Exception::Error(gin::StringToV8(
- isolate_, "Must pass non-empty path, urlChain and length.")));
- return;
- }
- if (offset >= length) {
- isolate_->ThrowException(v8::Exception::Error(gin::StringToV8(
- isolate_, "Must pass an offset value less than length.")));
- return;
- }
- auto* download_manager = browser_context()->GetDownloadManager();
- download_manager->GetNextId(base::BindRepeating(
- &DownloadIdCallback, download_manager, path, url_chain, mime_type, offset,
- length, last_modified, etag,
- base::Time::FromSecondsSinceUnixEpoch(start_time)));
- }
- std::string Session::RegisterPreloadScript(
- gin_helper::ErrorThrower thrower,
- const PreloadScript& new_preload_script) {
- auto* prefs = SessionPreferences::FromBrowserContext(browser_context());
- DCHECK(prefs);
- auto& preload_scripts = prefs->preload_scripts();
- auto it = std::find_if(preload_scripts.begin(), preload_scripts.end(),
- [&new_preload_script](const PreloadScript& script) {
- return script.id == new_preload_script.id;
- });
- if (it != preload_scripts.end()) {
- thrower.ThrowError(base::StringPrintf(
- "Cannot register preload script with existing ID '%s'",
- new_preload_script.id.c_str()));
- return "";
- }
- if (!new_preload_script.file_path.IsAbsolute()) {
- // Deprecated preload scripts logged error without throwing.
- if (new_preload_script.deprecated) {
- LOG(ERROR) << "preload script must have absolute path: "
- << new_preload_script.file_path;
- } else {
- thrower.ThrowError(
- base::StringPrintf("Preload script must have absolute path: %s",
- new_preload_script.file_path.value().c_str()));
- return "";
- }
- }
- preload_scripts.push_back(new_preload_script);
- return new_preload_script.id;
- }
- void Session::UnregisterPreloadScript(gin_helper::ErrorThrower thrower,
- const std::string& script_id) {
- auto* prefs = SessionPreferences::FromBrowserContext(browser_context());
- DCHECK(prefs);
- auto& preload_scripts = prefs->preload_scripts();
- // Find the preload script by its ID
- auto it = std::find_if(preload_scripts.begin(), preload_scripts.end(),
- [&script_id](const PreloadScript& script) {
- return script.id == script_id;
- });
- // If the script is found, erase it from the vector
- if (it != preload_scripts.end()) {
- preload_scripts.erase(it);
- return;
- }
- // If the script is not found, throw an error
- thrower.ThrowError(base::StringPrintf(
- "Cannot unregister preload script with non-existing ID '%s'",
- script_id.c_str()));
- }
- std::vector<PreloadScript> Session::GetPreloadScripts() const {
- auto* prefs = SessionPreferences::FromBrowserContext(browser_context());
- DCHECK(prefs);
- return prefs->preload_scripts();
- }
- /**
- * Exposes the network service's ClearSharedDictionaryCacheForIsolationKey
- * method, allowing clearing the Shared Dictionary cache for a given isolation
- * key. Details about the feature available at
- * https://developer.chrome.com/blog/shared-dictionary-compression
- */
- v8::Local<v8::Promise> Session::ClearSharedDictionaryCacheForIsolationKey(
- const gin_helper::Dictionary& options) {
- gin_helper::Promise<void> promise(isolate_);
- auto handle = promise.GetHandle();
- GURL frame_origin_url, top_frame_site_url;
- if (!options.Get("frameOrigin", &frame_origin_url) ||
- !options.Get("topFrameSite", &top_frame_site_url)) {
- promise.RejectWithErrorMessage(
- "Must provide frameOrigin and topFrameSite strings to "
- "`clearSharedDictionaryCacheForIsolationKey`");
- return handle;
- }
- if (!frame_origin_url.is_valid() || !top_frame_site_url.is_valid()) {
- promise.RejectWithErrorMessage(
- "Invalid URLs provided for frameOrigin or topFrameSite");
- return handle;
- }
- url::Origin frame_origin = url::Origin::Create(frame_origin_url);
- net::SchemefulSite top_frame_site(top_frame_site_url);
- net::SharedDictionaryIsolationKey isolation_key(frame_origin, top_frame_site);
- browser_context_->GetDefaultStoragePartition()
- ->GetNetworkContext()
- ->ClearSharedDictionaryCacheForIsolationKey(
- isolation_key,
- base::BindOnce(gin_helper::Promise<void>::ResolvePromise,
- std::move(promise)));
- return handle;
- }
- /**
- * Exposes the network service's ClearSharedDictionaryCache
- * method, allowing clearing the Shared Dictionary cache.
- * https://developer.chrome.com/blog/shared-dictionary-compression
- */
- v8::Local<v8::Promise> Session::ClearSharedDictionaryCache() {
- gin_helper::Promise<void> promise(isolate_);
- auto handle = promise.GetHandle();
- browser_context_->GetDefaultStoragePartition()
- ->GetNetworkContext()
- ->ClearSharedDictionaryCache(
- base::Time(), base::Time::Max(),
- nullptr /*mojom::ClearDataFilterPtr*/,
- base::BindOnce(gin_helper::Promise<void>::ResolvePromise,
- std::move(promise)));
- return handle;
- }
- /**
- * Exposes the network service's GetSharedDictionaryInfo method, allowing
- * inspection of Shared Dictionary information. Details about the feature
- * available at https://developer.chrome.com/blog/shared-dictionary-compression
- */
- v8::Local<v8::Promise> Session::GetSharedDictionaryInfo(
- const gin_helper::Dictionary& options) {
- gin_helper::Promise<std::vector<gin_helper::Dictionary>> promise(isolate_);
- auto handle = promise.GetHandle();
- GURL frame_origin_url, top_frame_site_url;
- if (!options.Get("frameOrigin", &frame_origin_url) ||
- !options.Get("topFrameSite", &top_frame_site_url)) {
- promise.RejectWithErrorMessage(
- "Must provide frameOrigin and topFrameSite strings");
- return handle;
- }
- if (!frame_origin_url.is_valid() || !top_frame_site_url.is_valid()) {
- promise.RejectWithErrorMessage(
- "Invalid URLs provided for frameOrigin or topFrameSite");
- return handle;
- }
- url::Origin frame_origin = url::Origin::Create(frame_origin_url);
- net::SchemefulSite top_frame_site(top_frame_site_url);
- net::SharedDictionaryIsolationKey isolation_key(frame_origin, top_frame_site);
- browser_context_->GetDefaultStoragePartition()
- ->GetNetworkContext()
- ->GetSharedDictionaryInfo(
- isolation_key,
- base::BindOnce(
- [](gin_helper::Promise<std::vector<gin_helper::Dictionary>>
- promise,
- std::vector<network::mojom::SharedDictionaryInfoPtr> info) {
- v8::Isolate* isolate = promise.isolate();
- v8::HandleScope handle_scope(isolate);
- std::vector<gin_helper::Dictionary> result;
- result.reserve(info.size());
- for (const auto& item : info) {
- gin_helper::Dictionary dict =
- gin_helper::Dictionary::CreateEmpty(isolate);
- dict.Set("match", item->match);
- // Convert RequestDestination enum values to strings
- std::vector<std::string> destinations;
- for (const auto& dest : item->match_dest) {
- destinations.push_back(
- network::RequestDestinationToString(dest));
- }
- dict.Set("matchDestinations", destinations);
- dict.Set("id", item->id);
- dict.Set("dictionaryUrl", item->dictionary_url.spec());
- dict.Set("lastFetchTime", item->last_fetch_time);
- dict.Set("responseTime", item->response_time);
- dict.Set("expirationDuration",
- item->expiration.InMillisecondsF());
- dict.Set("lastUsedTime", item->last_used_time);
- dict.Set("size", item->size);
- dict.Set("hash", net::HashValue(item->hash).ToString());
- result.push_back(dict);
- }
- promise.Resolve(result);
- },
- std::move(promise)));
- return handle;
- }
- /**
- * Exposes the network service's GetSharedDictionaryUsageInfo method, allowing
- * inspection of Shared Dictionary information. Details about the feature
- * available at https://developer.chrome.com/blog/shared-dictionary-compression
- */
- v8::Local<v8::Promise> Session::GetSharedDictionaryUsageInfo() {
- gin_helper::Promise<std::vector<gin_helper::Dictionary>> promise(isolate_);
- auto handle = promise.GetHandle();
- browser_context_->GetDefaultStoragePartition()
- ->GetNetworkContext()
- ->GetSharedDictionaryUsageInfo(base::BindOnce(
- [](gin_helper::Promise<std::vector<gin_helper::Dictionary>> promise,
- const std::vector<net::SharedDictionaryUsageInfo>& info) {
- v8::Isolate* isolate = promise.isolate();
- v8::HandleScope handle_scope(isolate);
- std::vector<gin_helper::Dictionary> result;
- result.reserve(info.size());
- for (const auto& item : info) {
- gin_helper::Dictionary dict =
- gin_helper::Dictionary::CreateEmpty(isolate);
- dict.Set("frameOrigin",
- item.isolation_key.frame_origin().Serialize());
- dict.Set("topFrameSite",
- item.isolation_key.top_frame_site().Serialize());
- dict.Set("totalSizeBytes", item.total_size_bytes);
- result.push_back(dict);
- }
- promise.Resolve(result);
- },
- std::move(promise)));
- return handle;
- }
- 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 cookies_.Get(isolate);
- }
- v8::Local<v8::Value> Session::Extensions(v8::Isolate* isolate) {
- #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
- if (extensions_.IsEmpty()) {
- v8::Local<v8::Value> handle;
- handle = Extensions::Create(isolate, browser_context()).ToV8();
- extensions_.Reset(isolate, handle);
- }
- #endif
- return extensions_.Get(isolate);
- }
- v8::Local<v8::Value> Session::Protocol(v8::Isolate* isolate) {
- return protocol_.Get(isolate);
- }
- 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);
- }
- return service_worker_context_.Get(isolate);
- }
- 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());
- }
- return web_request_.Get(isolate);
- }
- v8::Local<v8::Value> Session::NetLog(v8::Isolate* isolate) {
- if (net_log_.IsEmpty()) {
- auto handle = NetLog::Create(isolate, browser_context());
- net_log_.Reset(isolate, handle.ToV8());
- }
- return net_log_.Get(isolate);
- }
- static void StartPreconnectOnUI(ElectronBrowserContext* browser_context,
- const GURL& url,
- int num_sockets_to_preconnect) {
- url::Origin origin = url::Origin::Create(url);
- std::vector<predictors::PreconnectRequest> requests = {
- {url::Origin::Create(url), num_sockets_to_preconnect,
- net::NetworkAnonymizationKey::CreateSameSite(
- net::SchemefulSite(origin))}};
- browser_context->GetPreconnectManager()->Start(url, requests);
- }
- void Session::Preconnect(const gin_helper::Dictionary& options,
- gin::Arguments* args) {
- GURL url;
- if (!options.Get("url", &url) || !url.is_valid()) {
- args->ThrowTypeError(
- "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->ThrowTypeError(
- absl::StrFormat("numSocketsToPreconnect is outside range [%d,%d]",
- kMinSocketsToPreconnect, kMaxSocketsToPreconnect));
- return;
- }
- }
- DCHECK_GT(num_sockets_to_preconnect, 0);
- content::GetUIThreadTaskRunner({})->PostTask(
- FROM_HERE,
- base::BindOnce(&StartPreconnectOnUI, base::Unretained(browser_context()),
- url, num_sockets_to_preconnect));
- }
- v8::Local<v8::Promise> Session::CloseAllConnections() {
- gin_helper::Promise<void> promise(isolate_);
- auto handle = promise.GetHandle();
- browser_context_->GetDefaultStoragePartition()
- ->GetNetworkContext()
- ->CloseAllConnections(base::BindOnce(
- gin_helper::Promise<void>::ResolvePromise, std::move(promise)));
- return handle;
- }
- v8::Local<v8::Value> Session::GetPath(v8::Isolate* isolate) {
- if (browser_context_->IsOffTheRecord()) {
- return v8::Null(isolate);
- }
- return gin::ConvertToV8(isolate, browser_context_->GetPath());
- }
- void Session::SetCodeCachePath(gin::Arguments* args) {
- base::FilePath code_cache_path;
- auto* storage_partition = browser_context_->GetDefaultStoragePartition();
- auto* code_cache_context = storage_partition->GetGeneratedCodeCacheContext();
- if (code_cache_context) {
- if (!args->GetNext(&code_cache_path) || !code_cache_path.IsAbsolute()) {
- args->ThrowTypeError(
- "Absolute path must be provided to store code cache.");
- return;
- }
- code_cache_context->Initialize(
- code_cache_path, 0 /* allows disk_cache to choose the size */);
- }
- }
- v8::Local<v8::Promise> Session::ClearCodeCaches(
- const gin_helper::Dictionary& options) {
- auto* isolate = JavascriptEnvironment::GetIsolate();
- gin_helper::Promise<void> promise(isolate);
- v8::Local<v8::Promise> handle = promise.GetHandle();
- std::set<GURL> url_list;
- base::RepeatingCallback<bool(const GURL&)> url_matcher = base::NullCallback();
- if (options.Get("urls", &url_list) && !url_list.empty()) {
- url_matcher = base::BindRepeating(
- [](const std::set<GURL>& url_list, const GURL& url) {
- return url_list.contains(url);
- },
- url_list);
- }
- browser_context_->GetDefaultStoragePartition()->ClearCodeCaches(
- base::Time(), base::Time::Max(), url_matcher,
- base::BindOnce(gin_helper::Promise<void>::ResolvePromise,
- std::move(promise)));
- return handle;
- }
- v8::Local<v8::Value> Session::ClearData(gin_helper::ErrorThrower thrower,
- gin::Arguments* args) {
- auto* isolate = JavascriptEnvironment::GetIsolate();
- BrowsingDataRemover::DataType data_type_mask = kClearDataTypeAll;
- std::vector<url::Origin> origins;
- BrowsingDataFilterBuilder::OriginMatchingMode origin_matching_mode =
- BrowsingDataFilterBuilder::OriginMatchingMode::kThirdPartiesIncluded;
- BrowsingDataFilterBuilder::Mode filter_mode =
- BrowsingDataFilterBuilder::Mode::kPreserve;
- if (gin_helper::Dictionary options; args->GetNext(&options)) {
- if (std::vector<std::string> data_types;
- options.Get("dataTypes", &data_types)) {
- data_type_mask = GetDataTypeMask(data_types);
- }
- if (bool avoid_closing_connections;
- options.Get("avoidClosingConnections", &avoid_closing_connections) &&
- avoid_closing_connections) {
- data_type_mask |=
- BrowsingDataRemover::DATA_TYPE_AVOID_CLOSING_CONNECTIONS;
- }
- std::vector<GURL> origin_urls;
- {
- bool has_origins_key = options.Get("origins", &origin_urls);
- std::vector<GURL> exclude_origin_urls;
- bool has_exclude_origins_key =
- options.Get("excludeOrigins", &exclude_origin_urls);
- if (has_origins_key && has_exclude_origins_key) {
- thrower.ThrowError(
- "Cannot provide both 'origins' and 'excludeOrigins'");
- return v8::Undefined(isolate);
- }
- if (has_origins_key) {
- filter_mode = BrowsingDataFilterBuilder::Mode::kDelete;
- } else if (has_exclude_origins_key) {
- origin_urls = std::move(exclude_origin_urls);
- }
- }
- if (!origin_urls.empty()) {
- origins.reserve(origin_urls.size());
- for (const GURL& origin_url : origin_urls) {
- auto origin = url::Origin::Create(origin_url);
- // Opaque origins cannot be used with this API
- if (origin.opaque()) {
- thrower.ThrowError(
- absl::StrFormat("Invalid origin: '%s'",
- origin_url.possibly_invalid_spec().c_str()));
- return v8::Undefined(isolate);
- }
- origins.push_back(std::move(origin));
- }
- }
- if (std::string origin_matching_mode_string;
- options.Get("originMatchingMode", &origin_matching_mode_string)) {
- if (origin_matching_mode_string == "third-parties-included") {
- origin_matching_mode = BrowsingDataFilterBuilder::OriginMatchingMode::
- kThirdPartiesIncluded;
- } else if (origin_matching_mode_string == "origin-in-all-contexts") {
- origin_matching_mode =
- BrowsingDataFilterBuilder::OriginMatchingMode::kOriginInAllContexts;
- }
- }
- }
- gin_helper::Promise<void> promise(isolate);
- v8::Local<v8::Promise> promise_handle = promise.GetHandle();
- BrowsingDataRemover* remover = browser_context_->GetBrowsingDataRemover();
- ClearDataTask::Run(remover, std::move(promise), data_type_mask,
- std::move(origins), filter_mode, origin_matching_mode);
- return promise_handle;
- }
- #if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
- base::Value Session::GetSpellCheckerLanguages() {
- return browser_context_->prefs()
- ->GetValue(spellcheck::prefs::kSpellCheckDictionaries)
- .Clone();
- }
- void Session::SetSpellCheckerLanguages(
- gin_helper::ErrorThrower thrower,
- const std::vector<std::string>& languages) {
- #if !BUILDFLAG(IS_MAC)
- base::Value::List 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.Append(code);
- }
- browser_context_->prefs()->Set(spellcheck::prefs::kSpellCheckDictionaries,
- base::Value(std::move(language_codes)));
- // Enable spellcheck if > 0 languages, disable if no languages set
- browser_context_->prefs()->SetBoolean(spellcheck::prefs::kSpellCheckEnable,
- !languages.empty());
- #endif
- }
- void SetSpellCheckerDictionaryDownloadURL(gin_helper::ErrorThrower thrower,
- const GURL& url) {
- #if !BUILDFLAG(IS_MAC)
- if (!url.is_valid()) {
- thrower.ThrowError(
- "The URL you provided to setSpellCheckerDictionaryDownloadURL is not a "
- "valid URL");
- return;
- }
- SpellcheckHunspellDictionary::SetBaseDownloadURL(url);
- #endif
- }
- v8::Local<v8::Promise> Session::ListWordsInSpellCheckerDictionary() {
- gin_helper::Promise<std::set<std::string>> promise(isolate_);
- v8::Local<v8::Promise> handle = promise.GetHandle();
- SpellcheckService* spellcheck =
- SpellcheckServiceFactory::GetForContext(browser_context());
- if (!spellcheck) {
- promise.RejectWithErrorMessage(
- "Spellcheck in unexpected state: failed to load custom dictionary.");
- return handle;
- }
- 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;
- }
- bool Session::AddWordToSpellCheckerDictionary(const std::string& word) {
- // 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;
- SpellcheckService* service =
- SpellcheckServiceFactory::GetForContext(browser_context());
- if (!service)
- return false;
- #if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
- if (spellcheck::UseBrowserSpellChecker()) {
- spellcheck_platform::AddWord(service->platform_spell_checker(),
- base::UTF8ToUTF16(word));
- }
- #endif
- return service->GetCustomDictionary()->AddWord(word);
- }
- bool Session::RemoveWordFromSpellCheckerDictionary(const std::string& word) {
- // 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;
- SpellcheckService* service =
- SpellcheckServiceFactory::GetForContext(browser_context());
- 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);
- }
- void Session::SetSpellCheckerEnabled(bool b) {
- browser_context_->prefs()->SetBoolean(spellcheck::prefs::kSpellCheckEnable,
- b);
- }
- bool Session::IsSpellCheckerEnabled() const {
- return browser_context_->prefs()->GetBoolean(
- spellcheck::prefs::kSpellCheckEnable);
- }
- #endif // BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
- // static
- Session* Session::FromBrowserContext(content::BrowserContext* context) {
- auto* data =
- static_cast<UserDataLink*>(context->GetUserData(kElectronApiSessionKey));
- return data ? data->session.get() : nullptr;
- }
- // static
- gin::Handle<Session> Session::CreateFrom(
- v8::Isolate* isolate,
- ElectronBrowserContext* browser_context) {
- Session* existing = FromBrowserContext(browser_context);
- if (existing)
- return gin::CreateHandle(isolate, existing);
- auto handle =
- gin::CreateHandle(isolate, new Session(isolate, browser_context));
- // The Sessions should never be garbage collected, since the common pattern is
- // to use partition strings, instead of using the Session object directly.
- handle->Pin(isolate);
- v8::TryCatch try_catch(isolate);
- gin_helper::CallMethod(isolate, handle.get(), "_init");
- if (try_catch.HasCaught()) {
- node::errors::TriggerUncaughtException(isolate, try_catch);
- }
- App::Get()->EmitWithoutEvent("session-created", handle);
- return handle;
- }
- // static
- gin::Handle<Session> Session::FromPartition(v8::Isolate* isolate,
- const std::string& partition,
- base::Value::Dict options) {
- ElectronBrowserContext* browser_context;
- if (partition.empty()) {
- browser_context =
- ElectronBrowserContext::From("", false, std::move(options));
- } else if (partition.starts_with(kPersistPrefix)) {
- std::string name = partition.substr(8);
- browser_context =
- ElectronBrowserContext::From(name, false, std::move(options));
- } else {
- browser_context =
- ElectronBrowserContext::From(partition, true, std::move(options));
- }
- return CreateFrom(isolate, browser_context);
- }
- // static
- std::optional<gin::Handle<Session>> Session::FromPath(
- v8::Isolate* isolate,
- const base::FilePath& path,
- base::Value::Dict options) {
- ElectronBrowserContext* browser_context;
- if (path.empty()) {
- gin_helper::Promise<v8::Local<v8::Value>> promise(isolate);
- promise.RejectWithErrorMessage("An empty path was specified");
- return std::nullopt;
- }
- if (!path.IsAbsolute()) {
- gin_helper::Promise<v8::Local<v8::Value>> promise(isolate);
- promise.RejectWithErrorMessage("An absolute path was not provided");
- return std::nullopt;
- }
- browser_context =
- ElectronBrowserContext::FromPath(std::move(path), std::move(options));
- return CreateFrom(isolate, browser_context);
- }
- // static
- gin::Handle<Session> Session::New() {
- gin_helper::ErrorThrower(JavascriptEnvironment::GetIsolate())
- .ThrowError("Session objects cannot be created with 'new'");
- return {};
- }
- void Session::FillObjectTemplate(v8::Isolate* isolate,
- v8::Local<v8::ObjectTemplate> templ) {
- gin::ObjectTemplateBuilder(isolate, GetClassName(), templ)
- .SetMethod("resolveHost", &Session::ResolveHost)
- .SetMethod("resolveProxy", &Session::ResolveProxy)
- .SetMethod("getCacheSize", &Session::GetCacheSize)
- .SetMethod("clearCache", &Session::ClearCache)
- .SetMethod("clearStorageData", &Session::ClearStorageData)
- .SetMethod("flushStorageData", &Session::FlushStorageData)
- .SetMethod("setProxy", &Session::SetProxy)
- .SetMethod("forceReloadProxyConfig", &Session::ForceReloadProxyConfig)
- .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("_setDisplayMediaRequestHandler",
- &Session::SetDisplayMediaRequestHandler)
- .SetMethod("setDevicePermissionHandler",
- &Session::SetDevicePermissionHandler)
- .SetMethod("setUSBProtectedClassesHandler",
- &Session::SetUSBProtectedClassesHandler)
- .SetMethod("setBluetoothPairingHandler",
- &Session::SetBluetoothPairingHandler)
- .SetMethod("clearHostResolverCache", &Session::ClearHostResolverCache)
- .SetMethod("clearAuthCache", &Session::ClearAuthCache)
- .SetMethod("allowNTLMCredentialsForDomains",
- &Session::AllowNTLMCredentialsForDomains)
- .SetMethod("isPersistent", &Session::IsPersistent)
- .SetMethod("setUserAgent", &Session::SetUserAgent)
- .SetMethod("getUserAgent", &Session::GetUserAgent)
- .SetMethod("setSSLConfig", &Session::SetSSLConfig)
- .SetMethod("getBlobData", &Session::GetBlobData)
- .SetMethod("downloadURL", &Session::DownloadURL)
- .SetMethod("createInterruptedDownload",
- &Session::CreateInterruptedDownload)
- .SetMethod("registerPreloadScript", &Session::RegisterPreloadScript)
- .SetMethod("unregisterPreloadScript", &Session::UnregisterPreloadScript)
- .SetMethod("getPreloadScripts", &Session::GetPreloadScripts)
- .SetMethod("getSharedDictionaryUsageInfo",
- &Session::GetSharedDictionaryUsageInfo)
- .SetMethod("getSharedDictionaryInfo", &Session::GetSharedDictionaryInfo)
- .SetMethod("clearSharedDictionaryCache",
- &Session::ClearSharedDictionaryCache)
- .SetMethod("clearSharedDictionaryCacheForIsolationKey",
- &Session::ClearSharedDictionaryCacheForIsolationKey)
- #if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
- .SetMethod("getSpellCheckerLanguages", &Session::GetSpellCheckerLanguages)
- .SetMethod("setSpellCheckerLanguages", &Session::SetSpellCheckerLanguages)
- .SetProperty("availableSpellCheckerLanguages",
- &spellcheck::SpellCheckLanguages)
- .SetMethod("setSpellCheckerDictionaryDownloadURL",
- &SetSpellCheckerDictionaryDownloadURL)
- .SetMethod("listWordsInSpellCheckerDictionary",
- &Session::ListWordsInSpellCheckerDictionary)
- .SetMethod("addWordToSpellCheckerDictionary",
- &Session::AddWordToSpellCheckerDictionary)
- .SetMethod("removeWordFromSpellCheckerDictionary",
- &Session::RemoveWordFromSpellCheckerDictionary)
- .SetMethod("setSpellCheckerEnabled", &Session::SetSpellCheckerEnabled)
- .SetMethod("isSpellCheckerEnabled", &Session::IsSpellCheckerEnabled)
- .SetProperty("spellCheckerEnabled", &Session::IsSpellCheckerEnabled,
- &Session::SetSpellCheckerEnabled)
- #endif
- .SetMethod("preconnect", &Session::Preconnect)
- .SetMethod("closeAllConnections", &Session::CloseAllConnections)
- .SetMethod("getStoragePath", &Session::GetPath)
- .SetMethod("setCodeCachePath", &Session::SetCodeCachePath)
- .SetMethod("clearCodeCaches", &Session::ClearCodeCaches)
- .SetMethod("clearData", &Session::ClearData)
- .SetProperty("cookies", &Session::Cookies)
- .SetProperty("extensions", &Session::Extensions)
- .SetProperty("netLog", &Session::NetLog)
- .SetProperty("protocol", &Session::Protocol)
- .SetProperty("serviceWorkers", &Session::ServiceWorkerContext)
- .SetProperty("webRequest", &Session::WebRequest)
- .SetProperty("storagePath", &Session::GetPath)
- .Build();
- }
- const char* Session::GetTypeName() {
- return GetClassName();
- }
- void Session::WillBeDestroyed() {
- ClearWeak();
- }
- } // namespace electron::api
- namespace {
- using electron::api::Session;
- v8::Local<v8::Value> FromPartition(const std::string& partition,
- gin::Arguments* args) {
- if (!electron::Browser::Get()->is_ready()) {
- args->ThrowTypeError("Session can only be received when app is ready");
- return v8::Null(args->isolate());
- }
- base::Value::Dict options;
- args->GetNext(&options);
- return Session::FromPartition(args->isolate(), partition, std::move(options))
- .ToV8();
- }
- v8::Local<v8::Value> FromPath(const base::FilePath& path,
- gin::Arguments* args) {
- if (!electron::Browser::Get()->is_ready()) {
- args->ThrowTypeError("Session can only be received when app is ready");
- return v8::Null(args->isolate());
- }
- base::Value::Dict options;
- args->GetNext(&options);
- std::optional<gin::Handle<Session>> session_handle =
- Session::FromPath(args->isolate(), path, std::move(options));
- if (session_handle)
- return session_handle.value().ToV8();
- else
- return v8::Null(args->isolate());
- }
- void Initialize(v8::Local<v8::Object> exports,
- v8::Local<v8::Value> unused,
- v8::Local<v8::Context> context,
- void* priv) {
- v8::Isolate* isolate = context->GetIsolate();
- gin_helper::Dictionary dict(isolate, exports);
- dict.Set("Session", Session::GetConstructor(context));
- dict.SetMethod("fromPartition", &FromPartition);
- dict.SetMethod("fromPath", &FromPath);
- }
- } // namespace
- NODE_LINKED_BINDING_CONTEXT_AWARE(electron_browser_session, Initialize)
|