123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876 |
- // 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 "atom/browser/api/atom_api_session.h"
- #include <map>
- #include <string>
- #include <vector>
- #include "atom/browser/api/atom_api_cookies.h"
- #include "atom/browser/api/atom_api_download_item.h"
- #include "atom/browser/api/atom_api_protocol.h"
- #include "atom/browser/api/atom_api_web_request.h"
- #include "atom/browser/atom_browser_context.h"
- #include "atom/browser/atom_browser_main_parts.h"
- #include "atom/browser/atom_permission_manager.h"
- #include "atom/browser/browser.h"
- #include "atom/browser/net/atom_cert_verifier.h"
- #include "atom/browser/session_preferences.h"
- #include "atom/common/native_mate_converters/callback.h"
- #include "atom/common/native_mate_converters/content_converter.h"
- #include "atom/common/native_mate_converters/file_path_converter.h"
- #include "atom/common/native_mate_converters/gurl_converter.h"
- #include "atom/common/native_mate_converters/net_converter.h"
- #include "atom/common/native_mate_converters/value_converter.h"
- #include "atom/common/node_includes.h"
- #include "base/files/file_path.h"
- #include "base/guid.h"
- #include "base/strings/string_number_conversions.h"
- #include "base/strings/string_util.h"
- #include "base/threading/thread_task_runner_handle.h"
- #include "brightray/browser/media/media_device_id_salt.h"
- #include "chrome/browser/browser_process.h"
- #include "chrome/common/pref_names.h"
- #include "components/prefs/pref_service.h"
- #include "content/common/devtools/devtools_network_conditions.h"
- #include "content/common/devtools/devtools_network_controller.h"
- #include "content/public/browser/browser_thread.h"
- #include "content/public/browser/download_manager_delegate.h"
- #include "content/public/browser/storage_partition.h"
- #include "native_mate/dictionary.h"
- #include "native_mate/object_template_builder.h"
- #include "net/base/load_flags.h"
- #include "net/disk_cache/disk_cache.h"
- #include "net/dns/host_cache.h"
- #include "net/http/http_auth_handler_factory.h"
- #include "net/http/http_auth_preferences.h"
- #include "net/proxy/proxy_config_service_fixed.h"
- #include "net/proxy/proxy_service.h"
- #include "net/url_request/static_http_user_agent_settings.h"
- #include "net/url_request/url_request_context.h"
- #include "net/url_request/url_request_context_getter.h"
- #include "ui/base/l10n/l10n_util.h"
- using atom::api::Cookies;
- using content::BrowserThread;
- using content::StoragePartition;
- namespace {
- struct ClearStorageDataOptions {
- GURL origin;
- uint32_t storage_types = StoragePartition::REMOVE_DATA_MASK_ALL;
- uint32_t quota_types = StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL;
- };
- struct ClearAuthCacheOptions {
- std::string type;
- GURL origin;
- std::string realm;
- base::string16 username;
- base::string16 password;
- net::HttpAuth::Scheme auth_scheme;
- };
- uint32_t GetStorageMask(const std::vector<std::string>& storage_types) {
- uint32_t storage_mask = 0;
- for (const auto& it : storage_types) {
- auto type = base::ToLowerASCII(it);
- if (type == "appcache")
- storage_mask |= StoragePartition::REMOVE_DATA_MASK_APPCACHE;
- else if (type == "cookies")
- storage_mask |= StoragePartition::REMOVE_DATA_MASK_COOKIES;
- else if (type == "filesystem")
- storage_mask |= StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS;
- else if (type == "indexdb")
- storage_mask |= StoragePartition::REMOVE_DATA_MASK_INDEXEDDB;
- else if (type == "localstorage")
- storage_mask |= StoragePartition::REMOVE_DATA_MASK_LOCAL_STORAGE;
- else if (type == "shadercache")
- storage_mask |= StoragePartition::REMOVE_DATA_MASK_SHADER_CACHE;
- else if (type == "websql")
- storage_mask |= StoragePartition::REMOVE_DATA_MASK_WEBSQL;
- else if (type == "serviceworkers")
- storage_mask |= StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS;
- else if (type == "cachestorage")
- storage_mask |= StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE;
- }
- 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 == "persistent")
- quota_mask |= StoragePartition::QUOTA_MANAGED_STORAGE_MASK_PERSISTENT;
- else if (type == "syncable")
- quota_mask |= StoragePartition::QUOTA_MANAGED_STORAGE_MASK_SYNCABLE;
- }
- return quota_mask;
- }
- net::HttpAuth::Scheme GetAuthSchemeFromString(const std::string& scheme) {
- if (scheme == "basic")
- return net::HttpAuth::AUTH_SCHEME_BASIC;
- if (scheme == "digest")
- return net::HttpAuth::AUTH_SCHEME_DIGEST;
- if (scheme == "ntlm")
- return net::HttpAuth::AUTH_SCHEME_NTLM;
- if (scheme == "negotiate")
- return net::HttpAuth::AUTH_SCHEME_NEGOTIATE;
- return net::HttpAuth::AUTH_SCHEME_MAX;
- }
- void SetUserAgentInIO(scoped_refptr<net::URLRequestContextGetter> getter,
- const std::string& accept_lang,
- const std::string& user_agent) {
- getter->GetURLRequestContext()->set_http_user_agent_settings(
- new net::StaticHttpUserAgentSettings(
- net::HttpUtil::GenerateAcceptLanguageHeader(accept_lang),
- user_agent));
- }
- } // namespace
- namespace mate {
- template <>
- struct Converter<ClearStorageDataOptions> {
- static bool FromV8(v8::Isolate* isolate,
- v8::Local<v8::Value> val,
- ClearStorageDataOptions* out) {
- mate::Dictionary options;
- if (!ConvertFromV8(isolate, val, &options))
- return false;
- options.Get("origin", &out->origin);
- std::vector<std::string> types;
- if (options.Get("storages", &types))
- out->storage_types = GetStorageMask(types);
- if (options.Get("quotas", &types))
- out->quota_types = GetQuotaMask(types);
- return true;
- }
- };
- template <>
- struct Converter<ClearAuthCacheOptions> {
- static bool FromV8(v8::Isolate* isolate,
- v8::Local<v8::Value> val,
- ClearAuthCacheOptions* out) {
- mate::Dictionary options;
- if (!ConvertFromV8(isolate, val, &options))
- return false;
- options.Get("type", &out->type);
- options.Get("origin", &out->origin);
- options.Get("realm", &out->realm);
- options.Get("username", &out->username);
- options.Get("password", &out->password);
- std::string scheme;
- if (options.Get("scheme", &scheme))
- out->auth_scheme = GetAuthSchemeFromString(scheme);
- return true;
- }
- };
- template <>
- struct Converter<net::ProxyConfig> {
- static bool FromV8(v8::Isolate* isolate,
- v8::Local<v8::Value> val,
- net::ProxyConfig* out) {
- std::string proxy_rules, proxy_bypass_rules;
- GURL pac_url;
- mate::Dictionary options;
- // Fallback to previous API when passed String.
- // https://git.io/vuhjj
- if (ConvertFromV8(isolate, val, &proxy_rules)) {
- pac_url = GURL(proxy_rules); // Assume it is PAC script if it is URL.
- } else if (ConvertFromV8(isolate, val, &options)) {
- options.Get("pacScript", &pac_url);
- options.Get("proxyRules", &proxy_rules);
- options.Get("proxyBypassRules", &proxy_bypass_rules);
- } else {
- return false;
- }
- // pacScript takes precedence over proxyRules.
- if (!pac_url.is_empty() && pac_url.is_valid()) {
- out->set_pac_url(pac_url);
- } else {
- out->proxy_rules().ParseFromString(proxy_rules);
- out->proxy_rules().bypass_rules.ParseFromString(proxy_bypass_rules);
- }
- return true;
- }
- };
- template <>
- struct Converter<atom::VerifyRequestParams> {
- static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
- atom::VerifyRequestParams val) {
- mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
- dict.Set("hostname", val.hostname);
- dict.Set("certificate", val.certificate);
- dict.Set("verificationResult", val.default_result);
- dict.Set("errorCode", val.error_code);
- return dict.GetHandle();
- }
- };
- } // namespace mate
- namespace atom {
- namespace api {
- namespace {
- const char kPersistPrefix[] = "persist:";
- // Referenced session objects.
- std::map<uint32_t, v8::Global<v8::Object>> g_sessions;
- class ResolveProxyHelper {
- public:
- ResolveProxyHelper(AtomBrowserContext* browser_context,
- const GURL& url,
- const Session::ResolveProxyCallback& callback)
- : callback_(callback),
- original_thread_(base::ThreadTaskRunnerHandle::Get()) {
- scoped_refptr<net::URLRequestContextGetter> context_getter =
- browser_context->url_request_context_getter();
- context_getter->GetNetworkTaskRunner()->PostTask(
- FROM_HERE, base::BindOnce(&ResolveProxyHelper::ResolveProxy,
- base::Unretained(this), context_getter, url));
- }
- void OnResolveProxyCompleted(int result) {
- std::string proxy;
- if (result == net::OK)
- proxy = proxy_info_.ToPacString();
- original_thread_->PostTask(FROM_HERE, base::BindOnce(callback_, proxy));
- delete this;
- }
- private:
- void ResolveProxy(scoped_refptr<net::URLRequestContextGetter> context_getter,
- const GURL& url) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
- net::ProxyService* proxy_service =
- context_getter->GetURLRequestContext()->proxy_service();
- net::CompletionCallback completion_callback = base::Bind(
- &ResolveProxyHelper::OnResolveProxyCompleted, base::Unretained(this));
- // Start the request.
- int result = proxy_service->ResolveProxy(url, "GET", &proxy_info_,
- completion_callback, &pac_req_,
- nullptr, net::NetLogWithSource());
- // Completed synchronously.
- if (result != net::ERR_IO_PENDING)
- completion_callback.Run(result);
- }
- Session::ResolveProxyCallback callback_;
- net::ProxyInfo proxy_info_;
- net::ProxyService::PacRequest* pac_req_;
- scoped_refptr<base::SingleThreadTaskRunner> original_thread_;
- DISALLOW_COPY_AND_ASSIGN(ResolveProxyHelper);
- };
- // Runs the callback in UI thread.
- void RunCallbackInUI(const base::Callback<void()>& callback) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
- }
- template <typename... T>
- void RunCallbackInUI(const base::Callback<void(T...)>& callback, T... result) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::BindOnce(callback, result...));
- }
- // Callback of HttpCache::GetBackend.
- void OnGetBackend(disk_cache::Backend** backend_ptr,
- Session::CacheAction action,
- const net::CompletionCallback& callback,
- int result) {
- if (result != net::OK) {
- RunCallbackInUI(callback, result);
- } else if (backend_ptr && *backend_ptr) {
- if (action == Session::CacheAction::CLEAR) {
- (*backend_ptr)
- ->DoomAllEntries(base::Bind(&RunCallbackInUI<int>, callback));
- } else if (action == Session::CacheAction::STATS) {
- base::StringPairs stats;
- (*backend_ptr)->GetStats(&stats);
- for (const auto& stat : stats) {
- if (stat.first == "Current size") {
- int current_size;
- base::StringToInt(stat.second, ¤t_size);
- RunCallbackInUI(callback, current_size);
- break;
- }
- }
- }
- } else {
- RunCallbackInUI<int>(callback, net::ERR_FAILED);
- }
- }
- void DoCacheActionInIO(
- const scoped_refptr<net::URLRequestContextGetter>& context_getter,
- Session::CacheAction action,
- const net::CompletionCallback& callback) {
- auto* request_context = context_getter->GetURLRequestContext();
- auto* http_cache = request_context->http_transaction_factory()->GetCache();
- if (!http_cache)
- RunCallbackInUI<int>(callback, net::ERR_FAILED);
- // Call GetBackend and make the backend's ptr accessable in OnGetBackend.
- using BackendPtr = disk_cache::Backend*;
- auto** backend_ptr = new BackendPtr(nullptr);
- net::CompletionCallback on_get_backend =
- base::Bind(&OnGetBackend, base::Owned(backend_ptr), action, callback);
- int rv = http_cache->GetBackend(backend_ptr, on_get_backend);
- if (rv != net::ERR_IO_PENDING)
- on_get_backend.Run(net::OK);
- }
- void SetProxyInIO(scoped_refptr<net::URLRequestContextGetter> getter,
- const net::ProxyConfig& config,
- const base::Closure& callback) {
- auto* proxy_service = getter->GetURLRequestContext()->proxy_service();
- proxy_service->ResetConfigService(
- base::WrapUnique(new net::ProxyConfigServiceFixed(config)));
- // Refetches and applies the new pac script if provided.
- proxy_service->ForceReloadProxyConfig();
- RunCallbackInUI(callback);
- }
- void SetCertVerifyProcInIO(
- const scoped_refptr<net::URLRequestContextGetter>& context_getter,
- const AtomCertVerifier::VerifyProc& proc) {
- auto* request_context = context_getter->GetURLRequestContext();
- static_cast<AtomCertVerifier*>(request_context->cert_verifier())
- ->SetVerifyProc(proc);
- }
- void ClearHostResolverCacheInIO(
- const scoped_refptr<net::URLRequestContextGetter>& context_getter,
- const base::Closure& callback) {
- auto* request_context = context_getter->GetURLRequestContext();
- auto* cache = request_context->host_resolver()->GetHostCache();
- if (cache) {
- cache->clear();
- DCHECK_EQ(0u, cache->size());
- if (!callback.is_null())
- RunCallbackInUI(callback);
- }
- }
- void ClearAuthCacheInIO(
- const scoped_refptr<net::URLRequestContextGetter>& context_getter,
- const ClearAuthCacheOptions& options,
- const base::Closure& callback) {
- auto* request_context = context_getter->GetURLRequestContext();
- auto* network_session =
- request_context->http_transaction_factory()->GetSession();
- if (network_session) {
- if (options.type == "password") {
- auto* auth_cache = network_session->http_auth_cache();
- if (!options.origin.is_empty()) {
- auth_cache->Remove(
- options.origin, options.realm, options.auth_scheme,
- net::AuthCredentials(options.username, options.password));
- } else {
- auth_cache->ClearEntriesAddedWithin(base::TimeDelta::Max());
- }
- } else if (options.type == "clientCertificate") {
- auto* client_auth_cache = network_session->ssl_client_auth_cache();
- client_auth_cache->Remove(net::HostPortPair::FromURL(options.origin));
- }
- network_session->CloseAllConnections();
- }
- if (!callback.is_null())
- RunCallbackInUI(callback);
- }
- void AllowNTLMCredentialsForDomainsInIO(
- const scoped_refptr<net::URLRequestContextGetter>& context_getter,
- const std::string& domains) {
- auto* request_context = context_getter->GetURLRequestContext();
- auto* auth_handler = request_context->http_auth_handler_factory();
- if (auth_handler) {
- auto* auth_preferences = const_cast<net::HttpAuthPreferences*>(
- auth_handler->http_auth_preferences());
- if (auth_preferences)
- auth_preferences->set_server_whitelist(domains);
- }
- }
- void OnClearStorageDataDone(const base::Closure& callback) {
- if (!callback.is_null())
- callback.Run();
- }
- 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::GenerateGUID(), id, path, path, url_chain, GURL(), GURL(), GURL(),
- GURL(), mime_type, mime_type, start_time, base::Time(), etag,
- last_modified, offset, length, std::string(),
- content::DownloadItem::INTERRUPTED,
- content::DownloadDangerType::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
- content::DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT, false, base::Time(),
- false, std::vector<content::DownloadItem::ReceivedSlice>());
- }
- void SetDevToolsNetworkEmulationClientIdInIO(
- brightray::URLRequestContextGetter* url_request_context_getter,
- const std::string& client_id) {
- if (!url_request_context_getter)
- return;
- net::URLRequestContext* context =
- url_request_context_getter->GetURLRequestContext();
- AtomNetworkDelegate* network_delegate =
- static_cast<AtomNetworkDelegate*>(context->network_delegate());
- network_delegate->SetDevToolsNetworkEmulationClientId(client_id);
- }
- // Clear protocol handlers in IO thread.
- void ClearJobFactoryInIO(
- scoped_refptr<brightray::URLRequestContextGetter> request_context_getter) {
- auto* job_factory = static_cast<AtomURLRequestJobFactory*>(
- request_context_getter->job_factory());
- if (job_factory)
- job_factory->Clear();
- }
- void DestroyGlobalHandle(v8::Isolate* isolate,
- const v8::Global<v8::Value>& global_handle) {
- v8::Locker locker(isolate);
- v8::HandleScope handle_scope(isolate);
- if (!global_handle.IsEmpty()) {
- v8::Local<v8::Value> local_handle = global_handle.Get(isolate);
- if (local_handle->IsObject()) {
- v8::Local<v8::Object> object = local_handle->ToObject();
- void* ptr = object->GetAlignedPointerFromInternalField(0);
- if (!ptr)
- return;
- delete static_cast<mate::WrappableBase*>(ptr);
- object->SetAlignedPointerInInternalField(0, nullptr);
- }
- }
- }
- } // namespace
- Session::Session(v8::Isolate* isolate, AtomBrowserContext* browser_context)
- : devtools_network_emulation_client_id_(base::GenerateGUID()),
- browser_context_(browser_context) {
- // Observe DownloadManager to get download notifications.
- content::BrowserContext::GetDownloadManager(browser_context)
- ->AddObserver(this);
- new SessionPreferences(browser_context);
- Init(isolate);
- AttachAsUserData(browser_context);
- }
- Session::~Session() {
- auto* getter = browser_context_->GetRequestContext();
- content::BrowserThread::PostTask(
- content::BrowserThread::IO, FROM_HERE,
- base::BindOnce(ClearJobFactoryInIO, base::RetainedRef(getter)));
- content::BrowserContext::GetDownloadManager(browser_context())
- ->RemoveObserver(this);
- DestroyGlobalHandle(isolate(), cookies_);
- DestroyGlobalHandle(isolate(), web_request_);
- DestroyGlobalHandle(isolate(), protocol_);
- g_sessions.erase(weak_map_id());
- }
- void Session::OnDownloadCreated(content::DownloadManager* manager,
- content::DownloadItem* item) {
- if (item->IsSavePackageDownload())
- return;
- v8::Locker locker(isolate());
- v8::HandleScope handle_scope(isolate());
- auto handle = DownloadItem::Create(isolate(), item);
- if (item->GetState() == content::DownloadItem::INTERRUPTED)
- handle->SetSavePath(item->GetTargetFilePath());
- bool prevent_default = Emit("will-download", handle, item->GetWebContents());
- if (prevent_default) {
- item->Cancel(true);
- item->Remove();
- }
- }
- void Session::ResolveProxy(const GURL& url, ResolveProxyCallback callback) {
- new ResolveProxyHelper(browser_context(), url, callback);
- }
- template <Session::CacheAction action>
- void Session::DoCacheAction(const net::CompletionCallback& callback) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&DoCacheActionInIO,
- WrapRefCounted(browser_context_->GetRequestContext()),
- action, callback));
- }
- void Session::ClearStorageData(mate::Arguments* args) {
- // clearStorageData([options, callback])
- ClearStorageDataOptions options;
- base::Closure callback;
- args->GetNext(&options);
- args->GetNext(&callback);
- auto* storage_partition =
- content::BrowserContext::GetStoragePartition(browser_context(), nullptr);
- if (options.storage_types & StoragePartition::REMOVE_DATA_MASK_COOKIES) {
- // Reset media device id salt when cookies are cleared.
- // https://w3c.github.io/mediacapture-main/#dom-mediadeviceinfo-deviceid
- brightray::MediaDeviceIDSalt::Reset(browser_context()->prefs());
- }
- storage_partition->ClearData(
- options.storage_types, options.quota_types, options.origin,
- content::StoragePartition::OriginMatcherFunction(), base::Time(),
- base::Time::Max(), base::Bind(&OnClearStorageDataDone, callback));
- }
- void Session::FlushStorageData() {
- auto* storage_partition =
- content::BrowserContext::GetStoragePartition(browser_context(), nullptr);
- storage_partition->Flush();
- }
- void Session::SetProxy(const net::ProxyConfig& config,
- const base::Closure& callback) {
- auto* getter = browser_context_->GetRequestContext();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&SetProxyInIO, base::RetainedRef(getter), config,
- callback));
- }
- void Session::SetDownloadPath(const base::FilePath& path) {
- browser_context_->prefs()->SetFilePath(prefs::kDownloadDefaultDirectory,
- path);
- }
- void Session::EnableNetworkEmulation(const mate::Dictionary& options) {
- std::unique_ptr<content::DevToolsNetworkConditions> conditions;
- bool offline = false;
- double latency = 0.0, download_throughput = 0.0, upload_throughput = 0.0;
- if (options.Get("offline", &offline) && offline) {
- conditions.reset(new content::DevToolsNetworkConditions(offline));
- } else {
- options.Get("latency", &latency);
- options.Get("downloadThroughput", &download_throughput);
- options.Get("uploadThroughput", &upload_throughput);
- conditions.reset(new content::DevToolsNetworkConditions(
- false, latency, download_throughput, upload_throughput));
- }
- content::DevToolsNetworkController::SetNetworkState(
- devtools_network_emulation_client_id_, std::move(conditions));
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(
- &SetDevToolsNetworkEmulationClientIdInIO,
- base::RetainedRef(browser_context_->url_request_context_getter()),
- devtools_network_emulation_client_id_));
- }
- void Session::DisableNetworkEmulation() {
- auto conditions = std::make_unique<content::DevToolsNetworkConditions>();
- content::DevToolsNetworkController::SetNetworkState(
- devtools_network_emulation_client_id_, std::move(conditions));
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(
- &SetDevToolsNetworkEmulationClientIdInIO,
- base::RetainedRef(browser_context_->url_request_context_getter()),
- std::string()));
- }
- void Session::SetCertVerifyProc(v8::Local<v8::Value> val,
- mate::Arguments* args) {
- AtomCertVerifier::VerifyProc proc;
- if (!(val->IsNull() || mate::ConvertFromV8(args->isolate(), val, &proc))) {
- args->ThrowError("Must pass null or function");
- return;
- }
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&SetCertVerifyProcInIO,
- WrapRefCounted(browser_context_->GetRequestContext()),
- proc));
- }
- void Session::SetPermissionRequestHandler(v8::Local<v8::Value> val,
- mate::Arguments* args) {
- AtomPermissionManager::RequestHandler handler;
- if (!(val->IsNull() || mate::ConvertFromV8(args->isolate(), val, &handler))) {
- args->ThrowError("Must pass null or function");
- return;
- }
- auto* permission_manager = static_cast<AtomPermissionManager*>(
- browser_context()->GetPermissionManager());
- permission_manager->SetPermissionRequestHandler(handler);
- }
- void Session::ClearHostResolverCache(mate::Arguments* args) {
- base::Closure callback;
- args->GetNext(&callback);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&ClearHostResolverCacheInIO,
- WrapRefCounted(browser_context_->GetRequestContext()),
- callback));
- }
- void Session::ClearAuthCache(mate::Arguments* args) {
- ClearAuthCacheOptions options;
- if (!args->GetNext(&options)) {
- args->ThrowError("Must specify options object");
- return;
- }
- base::Closure callback;
- args->GetNext(&callback);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&ClearAuthCacheInIO,
- WrapRefCounted(browser_context_->GetRequestContext()),
- options, callback));
- }
- void Session::AllowNTLMCredentialsForDomains(const std::string& domains) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&AllowNTLMCredentialsForDomainsInIO,
- WrapRefCounted(browser_context_->GetRequestContext()),
- domains));
- }
- void Session::SetUserAgent(const std::string& user_agent,
- mate::Arguments* args) {
- browser_context_->SetUserAgent(user_agent);
- std::string accept_lang = g_browser_process->GetApplicationLocale();
- args->GetNext(&accept_lang);
- scoped_refptr<brightray::URLRequestContextGetter> getter(
- browser_context_->GetRequestContext());
- getter->GetNetworkTaskRunner()->PostTask(
- FROM_HERE,
- base::BindOnce(&SetUserAgentInIO, getter, accept_lang, user_agent));
- }
- std::string Session::GetUserAgent() {
- return browser_context_->GetUserAgent();
- }
- void Session::GetBlobData(const std::string& uuid,
- const AtomBlobReader::CompletionCallback& callback) {
- if (callback.is_null())
- return;
- AtomBlobReader* blob_reader = browser_context()->GetBlobReader();
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::BindOnce(&AtomBlobReader::StartReading,
- base::Unretained(blob_reader), uuid, callback));
- }
- void Session::CreateInterruptedDownload(const mate::Dictionary& options) {
- int64_t offset = 0, length = 0;
- double start_time = 0.0;
- 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(mate::StringToV8(
- isolate(), "Must pass non-empty path, urlChain and length.")));
- return;
- }
- if (offset >= length) {
- isolate()->ThrowException(v8::Exception::Error(mate::StringToV8(
- isolate(), "Must pass an offset value less than length.")));
- return;
- }
- auto* download_manager =
- content::BrowserContext::GetDownloadManager(browser_context());
- download_manager->GetDelegate()->GetNextId(base::Bind(
- &DownloadIdCallback, download_manager, path, url_chain, mime_type, offset,
- length, last_modified, etag, base::Time::FromDoubleT(start_time)));
- }
- void Session::SetPreloads(
- const std::vector<base::FilePath::StringType>& preloads) {
- auto* prefs = SessionPreferences::FromBrowserContext(browser_context());
- DCHECK(prefs);
- prefs->set_preloads(preloads);
- }
- std::vector<base::FilePath::StringType> Session::GetPreloads() const {
- auto* prefs = SessionPreferences::FromBrowserContext(browser_context());
- DCHECK(prefs);
- return prefs->preloads();
- }
- v8::Local<v8::Value> Session::Cookies(v8::Isolate* isolate) {
- if (cookies_.IsEmpty()) {
- auto handle = Cookies::Create(isolate, browser_context());
- cookies_.Reset(isolate, handle.ToV8());
- }
- return v8::Local<v8::Value>::New(isolate, cookies_);
- }
- v8::Local<v8::Value> Session::Protocol(v8::Isolate* isolate) {
- if (protocol_.IsEmpty()) {
- auto handle = atom::api::Protocol::Create(isolate, browser_context());
- protocol_.Reset(isolate, handle.ToV8());
- }
- return v8::Local<v8::Value>::New(isolate, protocol_);
- }
- v8::Local<v8::Value> Session::WebRequest(v8::Isolate* isolate) {
- if (web_request_.IsEmpty()) {
- auto handle = atom::api::WebRequest::Create(isolate, browser_context());
- web_request_.Reset(isolate, handle.ToV8());
- }
- return v8::Local<v8::Value>::New(isolate, web_request_);
- }
- // static
- mate::Handle<Session> Session::CreateFrom(v8::Isolate* isolate,
- AtomBrowserContext* browser_context) {
- auto* existing = TrackableObject::FromWrappedClass(isolate, browser_context);
- if (existing)
- return mate::CreateHandle(isolate, static_cast<Session*>(existing));
- auto handle =
- mate::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.
- g_sessions[handle->weak_map_id()] =
- v8::Global<v8::Object>(isolate, handle.ToV8());
- return handle;
- }
- // static
- mate::Handle<Session> Session::FromPartition(
- v8::Isolate* isolate,
- const std::string& partition,
- const base::DictionaryValue& options) {
- scoped_refptr<AtomBrowserContext> browser_context;
- if (partition.empty()) {
- browser_context = AtomBrowserContext::From("", false, options);
- } else if (base::StartsWith(partition, kPersistPrefix,
- base::CompareCase::SENSITIVE)) {
- std::string name = partition.substr(8);
- browser_context = AtomBrowserContext::From(name, false, options);
- } else {
- browser_context = AtomBrowserContext::From(partition, true, options);
- }
- return CreateFrom(isolate, browser_context.get());
- }
- // static
- void Session::BuildPrototype(v8::Isolate* isolate,
- v8::Local<v8::FunctionTemplate> prototype) {
- prototype->SetClassName(mate::StringToV8(isolate, "Session"));
- mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
- .MakeDestroyable()
- .SetMethod("resolveProxy", &Session::ResolveProxy)
- .SetMethod("getCacheSize", &Session::DoCacheAction<CacheAction::STATS>)
- .SetMethod("clearCache", &Session::DoCacheAction<CacheAction::CLEAR>)
- .SetMethod("clearStorageData", &Session::ClearStorageData)
- .SetMethod("flushStorageData", &Session::FlushStorageData)
- .SetMethod("setProxy", &Session::SetProxy)
- .SetMethod("setDownloadPath", &Session::SetDownloadPath)
- .SetMethod("enableNetworkEmulation", &Session::EnableNetworkEmulation)
- .SetMethod("disableNetworkEmulation", &Session::DisableNetworkEmulation)
- .SetMethod("setCertificateVerifyProc", &Session::SetCertVerifyProc)
- .SetMethod("setPermissionRequestHandler",
- &Session::SetPermissionRequestHandler)
- .SetMethod("clearHostResolverCache", &Session::ClearHostResolverCache)
- .SetMethod("clearAuthCache", &Session::ClearAuthCache)
- .SetMethod("allowNTLMCredentialsForDomains",
- &Session::AllowNTLMCredentialsForDomains)
- .SetMethod("setUserAgent", &Session::SetUserAgent)
- .SetMethod("getUserAgent", &Session::GetUserAgent)
- .SetMethod("getBlobData", &Session::GetBlobData)
- .SetMethod("createInterruptedDownload",
- &Session::CreateInterruptedDownload)
- .SetMethod("setPreloads", &Session::SetPreloads)
- .SetMethod("getPreloads", &Session::GetPreloads)
- .SetProperty("cookies", &Session::Cookies)
- .SetProperty("protocol", &Session::Protocol)
- .SetProperty("webRequest", &Session::WebRequest);
- }
- } // namespace api
- } // namespace atom
- namespace {
- using atom::api::Session;
- v8::Local<v8::Value> FromPartition(const std::string& partition,
- mate::Arguments* args) {
- if (!atom::Browser::Get()->is_ready()) {
- args->ThrowError("Session can only be received when app is ready");
- return v8::Null(args->isolate());
- }
- base::DictionaryValue options;
- args->GetNext(&options);
- return Session::FromPartition(args->isolate(), partition, options).ToV8();
- }
- void Initialize(v8::Local<v8::Object> exports,
- v8::Local<v8::Value> unused,
- v8::Local<v8::Context> context,
- void* priv) {
- v8::Isolate* isolate = context->GetIsolate();
- mate::Dictionary dict(isolate, exports);
- dict.Set("Session", Session::GetConstructor(isolate)->GetFunction());
- dict.Set("Cookies", Cookies::GetConstructor(isolate)->GetFunction());
- dict.SetMethod("fromPartition", &FromPartition);
- }
- } // namespace
- NODE_BUILTIN_MODULE_CONTEXT_AWARE(atom_browser_session, Initialize)
|