From 1c0bb06d4aed758c018b39a7b56f1cff5b81a7fe Mon Sep 17 00:00:00 2001 From: Robo Date: Tue, 14 Aug 2018 03:52:45 +0530 Subject: [PATCH] [WIP] refactor: (Part I) make the ownership of URLRequestContextGetter more clear (#13956) * refactor: desttroy URLRequestContextGetter on IO thread * Accepts a factory class that can customize the creation of URLRequestContext * Use a separate request context for media which is derived from the default * Notify URLRequestContextGetter observers and cleanup on IO thread * Move most of brightray net/ classes into atom net/ * refactor: remove refs to URLRequestContextGetter on shutdown * refactor: remove brigtray switches.{cc|h} * refactor: remove brightray network_delegate.{cc|h} * refactor: make AtomURLRequestJobFactory the top level factory. * Allows to use the default handler from content/ for http{s}, ws{s} schemes. * Removes the storage of job factory in URLRequestContextGetter. --- atom/browser/api/atom_api_cookies.cc | 3 +- atom/browser/api/atom_api_cookies.h | 3 + atom/browser/api/atom_api_protocol.cc | 12 +- atom/browser/api/atom_api_protocol.h | 15 +- atom/browser/api/atom_api_session.cc | 31 +- atom/browser/api/atom_api_web_request.cc | 2 +- atom/browser/atom_browser_context.cc | 132 +----- atom/browser/atom_browser_context.h | 28 +- atom/browser/net/atom_network_delegate.cc | 128 +++-- atom/browser/net/atom_network_delegate.h | 46 +- atom/browser/net/atom_url_request.cc | 8 +- .../net/atom_url_request_job_factory.cc | 69 +-- .../net/atom_url_request_job_factory.h | 27 +- atom/browser/net/http_protocol_handler.cc | 22 - atom/browser/net/http_protocol_handler.h | 30 -- atom/browser/net/js_asker.h | 1 - atom/browser/net/request_context_factory.cc | 375 +++++++++++++++ atom/browser/net/request_context_factory.h | 86 ++++ atom/browser/net/url_request_fetch_job.cc | 11 +- atom/browser/net/url_request_fetch_job.h | 5 +- atom/common/options_switches.cc | 54 ++- atom/common/options_switches.h | 13 +- brightray/browser/browser_context.cc | 52 +-- brightray/browser/browser_context.h | 17 +- .../browser/inspectable_web_contents_impl.cc | 2 +- .../net/url_request_context_getter_factory.h | 29 ++ brightray/browser/network_delegate.cc | 161 ------- brightray/browser/network_delegate.h | 88 ---- .../browser/url_request_context_getter.cc | 440 +++++------------- .../browser/url_request_context_getter.h | 123 ++--- brightray/common/switches.cc | 58 --- brightray/common/switches.h | 26 -- brightray/filenames.gypi | 5 +- filenames.gypi | 4 +- 34 files changed, 985 insertions(+), 1121 deletions(-) delete mode 100644 atom/browser/net/http_protocol_handler.cc delete mode 100644 atom/browser/net/http_protocol_handler.h create mode 100644 atom/browser/net/request_context_factory.cc create mode 100644 atom/browser/net/request_context_factory.h create mode 100644 brightray/browser/net/url_request_context_getter_factory.h delete mode 100644 brightray/browser/network_delegate.cc delete mode 100644 brightray/browser/network_delegate.h delete mode 100644 brightray/common/switches.cc delete mode 100644 brightray/common/switches.h diff --git a/atom/browser/api/atom_api_cookies.cc b/atom/browser/api/atom_api_cookies.cc index dafb003465d9..82fe84ef5d0d 100644 --- a/atom/browser/api/atom_api_cookies.cc +++ b/atom/browser/api/atom_api_cookies.cc @@ -253,9 +253,8 @@ void SetCookieOnIO(scoped_refptr getter, Cookies::Cookies(v8::Isolate* isolate, AtomBrowserContext* browser_context) : browser_context_(browser_context) { Init(isolate); - auto subscription = browser_context->RegisterCookieChangeCallback( + cookie_change_subscription_ = browser_context->RegisterCookieChangeCallback( base::Bind(&Cookies::OnCookieChanged, base::Unretained(this))); - browser_context->set_cookie_change_subscription(std::move(subscription)); } Cookies::~Cookies() {} diff --git a/atom/browser/api/atom_api_cookies.h b/atom/browser/api/atom_api_cookies.h index 403e22623302..fdd5c7cb9455 100644 --- a/atom/browser/api/atom_api_cookies.h +++ b/atom/browser/api/atom_api_cookies.h @@ -10,6 +10,7 @@ #include "atom/browser/api/trackable_object.h" #include "atom/browser/net/cookie_details.h" #include "base/callback.h" +#include "base/callback_list.h" #include "native_mate/handle.h" #include "net/cookies/canonical_cookie.h" @@ -59,6 +60,8 @@ class Cookies : public mate::TrackableObject { void OnCookieChanged(const CookieDetails*); private: + std::unique_ptr::Subscription> + cookie_change_subscription_; scoped_refptr browser_context_; DISALLOW_COPY_AND_ASSIGN(Cookies); diff --git a/atom/browser/api/atom_api_protocol.cc b/atom/browser/api/atom_api_protocol.cc index 5e1f991ad8dc..537911ef12a9 100644 --- a/atom/browser/api/atom_api_protocol.cc +++ b/atom/browser/api/atom_api_protocol.cc @@ -95,8 +95,8 @@ void Protocol::UnregisterProtocol(const std::string& scheme, Protocol::ProtocolError Protocol::UnregisterProtocolInIO( scoped_refptr request_context_getter, const std::string& scheme) { - auto* job_factory = static_cast( - request_context_getter->job_factory()); + auto* job_factory = static_cast( + request_context_getter->GetURLRequestContext()->job_factory()); if (!job_factory->HasProtocolHandler(scheme)) return PROTOCOL_NOT_REGISTERED; job_factory->SetProtocolHandler(scheme, nullptr); @@ -117,7 +117,9 @@ void Protocol::IsProtocolHandled(const std::string& scheme, bool Protocol::IsProtocolHandledInIO( scoped_refptr request_context_getter, const std::string& scheme) { - return request_context_getter->job_factory()->IsHandledProtocol(scheme); + return request_context_getter->GetURLRequestContext() + ->job_factory() + ->IsHandledProtocol(scheme); } void Protocol::UninterceptProtocol(const std::string& scheme, @@ -136,8 +138,8 @@ void Protocol::UninterceptProtocol(const std::string& scheme, Protocol::ProtocolError Protocol::UninterceptProtocolInIO( scoped_refptr request_context_getter, const std::string& scheme) { - return static_cast( - request_context_getter->job_factory()) + return static_cast( + request_context_getter->GetURLRequestContext()->job_factory()) ->UninterceptProtocol(scheme) ? PROTOCOL_OK : PROTOCOL_NOT_INTERCEPTED; diff --git a/atom/browser/api/atom_api_protocol.h b/atom/browser/api/atom_api_protocol.h index ab5e34872c6e..1eca6b47b827 100644 --- a/atom/browser/api/atom_api_protocol.h +++ b/atom/browser/api/atom_api_protocol.h @@ -78,13 +78,13 @@ class Protocol : public mate::TrackableObject { net::URLRequest* request, net::NetworkDelegate* network_delegate) const override { RequestJob* request_job = new RequestJob(request, network_delegate); - request_job->SetHandlerInfo(isolate_, request_context_.get(), handler_); + request_job->SetHandlerInfo(isolate_, request_context_, handler_); return request_job; } private: v8::Isolate* isolate_; - scoped_refptr request_context_; + net::URLRequestContextGetter* request_context_; Protocol::Handler handler_; DISALLOW_COPY_AND_ASSIGN(CustomProtocolHandler); @@ -113,8 +113,8 @@ class Protocol : public mate::TrackableObject { v8::Isolate* isolate, const std::string& scheme, const Handler& handler) { - auto* job_factory = static_cast( - request_context_getter->job_factory()); + auto* job_factory = static_cast( + request_context_getter->GetURLRequestContext()->job_factory()); if (job_factory->IsHandledProtocol(scheme)) return PROTOCOL_REGISTERED; auto protocol_handler = std::make_unique>( @@ -158,13 +158,10 @@ class Protocol : public mate::TrackableObject { v8::Isolate* isolate, const std::string& scheme, const Handler& handler) { - auto* job_factory = static_cast( - request_context_getter->job_factory()); + auto* job_factory = static_cast( + request_context_getter->GetURLRequestContext()->job_factory()); if (!job_factory->IsHandledProtocol(scheme)) return PROTOCOL_NOT_REGISTERED; - // It is possible a protocol is handled but can not be intercepted. - if (!job_factory->HasProtocolHandler(scheme)) - return PROTOCOL_FAIL; auto protocol_handler = std::make_unique>( isolate, request_context_getter.get(), handler); if (!job_factory->InterceptProtocol(scheme, std::move(protocol_handler))) diff --git a/atom/browser/api/atom_api_session.cc b/atom/browser/api/atom_api_session.cc index 2ca8ae0e26dd..e11655eb0ce0 100644 --- a/atom/browser/api/atom_api_session.cc +++ b/atom/browser/api/atom_api_session.cc @@ -46,6 +46,8 @@ #include "net/dns/host_cache.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_transaction_factory.h" #include "net/proxy_resolution/proxy_config_service_fixed.h" #include "net/proxy_resolution/proxy_service.h" #include "net/url_request/static_http_user_agent_settings.h" @@ -244,7 +246,7 @@ class ResolveProxyHelper { : callback_(callback), original_thread_(base::ThreadTaskRunnerHandle::Get()) { scoped_refptr context_getter = - browser_context->url_request_context_getter(); + browser_context->GetRequestContext(); context_getter->GetNetworkTaskRunner()->PostTask( FROM_HERE, base::BindOnce(&ResolveProxyHelper::ResolveProxy, base::Unretained(this), context_getter, url)); @@ -453,15 +455,6 @@ void SetDevToolsNetworkEmulationClientIdInIO( network_delegate->SetDevToolsNetworkEmulationClientId(client_id); } -// Clear protocol handlers in IO thread. -void ClearJobFactoryInIO( - scoped_refptr request_context_getter) { - auto* job_factory = static_cast( - request_context_getter->job_factory()); - if (job_factory) - job_factory->Clear(); -} - void DestroyGlobalHandle(v8::Isolate* isolate, const v8::Global& global_handle) { v8::Locker locker(isolate); @@ -495,10 +488,6 @@ Session::Session(v8::Isolate* isolate, AtomBrowserContext* 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_); @@ -597,10 +586,9 @@ void Session::EnableNetworkEmulation(const mate::Dictionary& options) { 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_)); + base::BindOnce(&SetDevToolsNetworkEmulationClientIdInIO, + base::RetainedRef(browser_context_->GetRequestContext()), + devtools_network_emulation_client_id_)); } void Session::DisableNetworkEmulation() { @@ -609,10 +597,9 @@ void Session::DisableNetworkEmulation() { 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())); + base::BindOnce(&SetDevToolsNetworkEmulationClientIdInIO, + base::RetainedRef(browser_context_->GetRequestContext()), + std::string())); } void Session::SetCertVerifyProc(v8::Local val, diff --git a/atom/browser/api/atom_api_web_request.cc b/atom/browser/api/atom_api_web_request.cc index ac265fb168ae..c088196f8331 100644 --- a/atom/browser/api/atom_api_web_request.cc +++ b/atom/browser/api/atom_api_web_request.cc @@ -95,7 +95,7 @@ void WebRequest::SetListener(Method method, Event type, mate::Arguments* args) { } brightray::URLRequestContextGetter* url_request_context_getter = - browser_context_->url_request_context_getter(); + browser_context_->GetRequestContext(); if (!url_request_context_getter) return; BrowserThread::PostTask( diff --git a/atom/browser/atom_browser_context.cc b/atom/browser/atom_browser_context.cc index e3dbfedc0c2d..899179d04092 100644 --- a/atom/browser/atom_browser_context.cc +++ b/atom/browser/atom_browser_context.cc @@ -6,42 +6,23 @@ #include "atom/browser/api/atom_api_protocol.h" #include "atom/browser/atom_blob_reader.h" -#include "atom/browser/atom_browser_main_parts.h" #include "atom/browser/atom_download_manager_delegate.h" #include "atom/browser/atom_permission_manager.h" #include "atom/browser/browser.h" -#include "atom/browser/net/about_protocol_handler.h" -#include "atom/browser/net/asar/asar_protocol_handler.h" -#include "atom/browser/net/atom_cert_verifier.h" -#include "atom/browser/net/atom_network_delegate.h" -#include "atom/browser/net/atom_url_request_job_factory.h" -#include "atom/browser/net/cookie_details.h" -#include "atom/browser/net/http_protocol_handler.h" +#include "atom/browser/net/request_context_factory.h" #include "atom/browser/web_view_manager.h" #include "atom/common/atom_version.h" #include "atom/common/chrome_version.h" -#include "atom/common/options_switches.h" #include "base/command_line.h" #include "base/files/file_path.h" -#include "base/memory/ptr_util.h" #include "base/path_service.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" -#include "base/task_scheduler/post_task.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/pref_names.h" #include "components/prefs/pref_registry_simple.h" #include "content/browser/blob_storage/chrome_blob_storage_context.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/storage_partition.h" -#include "content/public/common/url_constants.h" #include "content/public/common/user_agent.h" -#include "net/ftp/ftp_network_layer.h" -#include "net/url_request/data_protocol_handler.h" -#include "net/url_request/ftp_protocol_handler.h" -#include "net/url_request/url_request_context.h" -#include "net/url_request/url_request_intercepting_job_factory.h" -#include "url/url_constants.h" using content::BrowserThread; @@ -49,14 +30,6 @@ namespace atom { namespace { -class NoCacheBackend : public net::HttpCache::BackendFactory { - int CreateBackend(net::NetLog* net_log, - std::unique_ptr* backend, - const net::CompletionCallback& callback) override { - return net::ERR_FAILED; - } -}; - std::string RemoveWhitespace(const std::string& str) { std::string trimmed; if (base::RemoveChars(str, " ", &trimmed)) @@ -65,6 +38,14 @@ std::string RemoveWhitespace(const std::string& str) { return str; } +std::vector GetCookieableSchemes() { + std::vector default_schemes = {"http", "https", "ws", "wss"}; + const auto& standard_schemes = atom::api::GetStandardSchemes(); + default_schemes.insert(default_schemes.end(), standard_schemes.begin(), + standard_schemes.end()); + return default_schemes; +} + } // namespace AtomBrowserContext::AtomBrowserContext(const std::string& partition, @@ -105,68 +86,10 @@ AtomBrowserContext::RegisterCookieChangeCallback( return cookie_change_sub_list_.Add(cb); } -std::unique_ptr -AtomBrowserContext::CreateNetworkDelegate() { - return std::make_unique(); -} - -std::string AtomBrowserContext::GetUserAgent() { +std::string AtomBrowserContext::GetUserAgent() const { return user_agent_; } -std::unique_ptr -AtomBrowserContext::CreateURLRequestJobFactory( - content::ProtocolHandlerMap* protocol_handlers) { - std::unique_ptr job_factory( - new AtomURLRequestJobFactory); - - for (auto& it : *protocol_handlers) { - job_factory->SetProtocolHandler(it.first, - base::WrapUnique(it.second.release())); - } - protocol_handlers->clear(); - - job_factory->SetProtocolHandler(url::kAboutScheme, - base::WrapUnique(new AboutProtocolHandler)); - job_factory->SetProtocolHandler( - url::kDataScheme, base::WrapUnique(new net::DataProtocolHandler)); - job_factory->SetProtocolHandler( - url::kFileScheme, - base::WrapUnique( - new asar::AsarProtocolHandler(base::CreateTaskRunnerWithTraits( - {base::MayBlock(), base::TaskPriority::USER_VISIBLE, - base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})))); - job_factory->SetProtocolHandler( - url::kHttpScheme, - base::WrapUnique(new HttpProtocolHandler(url::kHttpScheme))); - job_factory->SetProtocolHandler( - url::kHttpsScheme, - base::WrapUnique(new HttpProtocolHandler(url::kHttpsScheme))); - job_factory->SetProtocolHandler( - url::kWsScheme, - base::WrapUnique(new HttpProtocolHandler(url::kWsScheme))); - job_factory->SetProtocolHandler( - url::kWssScheme, - base::WrapUnique(new HttpProtocolHandler(url::kWssScheme))); - - auto* host_resolver = - url_request_context_getter()->GetURLRequestContext()->host_resolver(); - job_factory->SetProtocolHandler( - url::kFtpScheme, net::FtpProtocolHandler::Create(host_resolver)); - - return std::move(job_factory); -} - -net::HttpCache::BackendFactory* -AtomBrowserContext::CreateHttpCacheBackendFactory( - const base::FilePath& base_path) { - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - if (!use_cache_ || command_line->HasSwitch(switches::kDisableHttpCache)) - return new NoCacheBackend; - else - return brightray::BrowserContext::CreateHttpCacheBackendFactory(base_path); -} - content::DownloadManagerDelegate* AtomBrowserContext::GetDownloadManagerDelegate() { if (!download_manager_delegate_.get()) { @@ -189,26 +112,6 @@ content::PermissionManager* AtomBrowserContext::GetPermissionManager() { return permission_manager_.get(); } -std::unique_ptr AtomBrowserContext::CreateCertVerifier( - brightray::RequireCTDelegate* ct_delegate) { - return base::WrapUnique(new AtomCertVerifier(ct_delegate)); -} - -std::vector AtomBrowserContext::GetCookieableSchemes() { - auto default_schemes = brightray::BrowserContext::GetCookieableSchemes(); - const auto& standard_schemes = atom::api::GetStandardSchemes(); - default_schemes.insert(default_schemes.end(), standard_schemes.begin(), - standard_schemes.end()); - return default_schemes; -} - -void AtomBrowserContext::NotifyCookieChange(const net::CanonicalCookie& cookie, - bool removed, - net::CookieChangeCause cause) { - CookieDetails cookie_details(&cookie, removed, cause); - cookie_change_sub_list_.Notify(&cookie_details); -} - void AtomBrowserContext::RegisterPrefs(PrefRegistrySimple* pref_registry) { pref_registry->RegisterFilePathPref(prefs::kSelectFileLastDirectory, base::FilePath()); @@ -219,6 +122,16 @@ void AtomBrowserContext::RegisterPrefs(PrefRegistrySimple* pref_registry) { pref_registry->RegisterDictionaryPref(prefs::kDevToolsFileSystemPaths); } +brightray::URLRequestContextGetterFactory* +AtomBrowserContext::GetFactoryForMainRequestContext( + content::ProtocolHandlerMap* protocol_handlers, + content::URLRequestInterceptorScopedVector request_interceptors) { + return new AtomMainRequestContextFactory( + GetPath(), IsOffTheRecord(), use_cache_, user_agent_, + GetCookieableSchemes(), protocol_handlers, + std::move(request_interceptors), this); +} + AtomBlobReader* AtomBrowserContext::GetBlobReader() { if (!blob_reader_.get()) { content::ChromeBlobStorageContext* blob_context = @@ -228,6 +141,11 @@ AtomBlobReader* AtomBrowserContext::GetBlobReader() { return blob_reader_.get(); } +void AtomBrowserContext::NotifyCookieChange( + const CookieDetails* cookie_details) { + cookie_change_sub_list_.Notify(cookie_details); +} + // static scoped_refptr AtomBrowserContext::From( const std::string& partition, diff --git a/atom/browser/atom_browser_context.h b/atom/browser/atom_browser_context.h index b60a4e682b0a..935e0ecf1f81 100644 --- a/atom/browser/atom_browser_context.h +++ b/atom/browser/atom_browser_context.h @@ -15,7 +15,6 @@ namespace atom { class AtomBlobReader; class AtomDownloadManagerDelegate; -class AtomNetworkDelegate; class AtomPermissionManager; class WebViewManager; struct CookieDetails; @@ -31,25 +30,12 @@ class AtomBrowserContext : public brightray::BrowserContext { const base::DictionaryValue& options = base::DictionaryValue()); void SetUserAgent(const std::string& user_agent); + std::string GetUserAgent() const; // Register callbacks that needs to notified on any cookie store changes. std::unique_ptr::Subscription> RegisterCookieChangeCallback( const base::Callback& cb); - // brightray::URLRequestContextGetter::Delegate: - std::unique_ptr CreateNetworkDelegate() override; - std::string GetUserAgent() override; - std::unique_ptr CreateURLRequestJobFactory( - content::ProtocolHandlerMap* protocol_handlers) override; - net::HttpCache::BackendFactory* CreateHttpCacheBackendFactory( - const base::FilePath& base_path) override; - std::unique_ptr CreateCertVerifier( - brightray::RequireCTDelegate* ct_delegate) override; - std::vector GetCookieableSchemes() override; - void NotifyCookieChange(const net::CanonicalCookie& cookie, - bool removed, - net::CookieChangeCause cause) override; - // content::BrowserContext: content::DownloadManagerDelegate* GetDownloadManagerDelegate() override; content::BrowserPluginGuestManager* GetGuestManager() override; @@ -57,15 +43,13 @@ class AtomBrowserContext : public brightray::BrowserContext { // brightray::BrowserContext: void RegisterPrefs(PrefRegistrySimple* pref_registry) override; + brightray::URLRequestContextGetterFactory* GetFactoryForMainRequestContext( + content::ProtocolHandlerMap* protocol_handlers, + content::URLRequestInterceptorScopedVector request_interceptors) override; AtomBlobReader* GetBlobReader(); - void set_cookie_change_subscription( - std::unique_ptr< - base::CallbackList::Subscription> - subscription) { - cookie_change_subscription_.swap(subscription); - } + void NotifyCookieChange(const CookieDetails* cookie_details); protected: AtomBrowserContext(const std::string& partition, @@ -82,8 +66,6 @@ class AtomBrowserContext : public brightray::BrowserContext { bool use_cache_; base::CallbackList cookie_change_sub_list_; - std::unique_ptr::Subscription> - cookie_change_subscription_; DISALLOW_COPY_AND_ASSIGN(AtomBrowserContext); }; diff --git a/atom/browser/net/atom_network_delegate.cc b/atom/browser/net/atom_network_delegate.cc index c2bbc29051d3..85dd2e190ab0 100644 --- a/atom/browser/net/atom_network_delegate.cc +++ b/atom/browser/net/atom_network_delegate.cc @@ -8,10 +8,14 @@ #include "atom/browser/api/atom_api_web_contents.h" #include "atom/common/native_mate_converters/net_converter.h" +#include "atom/common/options_switches.h" +#include "base/command_line.h" #include "base/stl_util.h" #include "base/strings/string_util.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_frame_host.h" +#include "net/base/load_flags.h" +#include "net/base/net_errors.h" #include "net/url_request/url_request.h" #include "services/network/throttling/throttling_network_transaction.h" @@ -232,7 +236,15 @@ AtomNetworkDelegate::ResponseListenerInfo::ResponseListenerInfo( AtomNetworkDelegate::ResponseListenerInfo::ResponseListenerInfo() = default; AtomNetworkDelegate::ResponseListenerInfo::~ResponseListenerInfo() = default; -AtomNetworkDelegate::AtomNetworkDelegate() {} +AtomNetworkDelegate::AtomNetworkDelegate() { + auto* command_line = base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kIgnoreConnectionsLimit)) { + std::string value = + command_line->GetSwitchValueASCII(switches::kIgnoreConnectionsLimit); + ignore_connections_limit_domains_ = base::SplitString( + value, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + } +} AtomNetworkDelegate::~AtomNetworkDelegate() {} @@ -263,9 +275,17 @@ int AtomNetworkDelegate::OnBeforeURLRequest( net::URLRequest* request, const net::CompletionCallback& callback, GURL* new_url) { - if (!base::ContainsKey(response_listeners_, kOnBeforeRequest)) - return brightray::NetworkDelegate::OnBeforeURLRequest(request, callback, - new_url); + if (!base::ContainsKey(response_listeners_, kOnBeforeRequest)) { + for (const auto& domain : ignore_connections_limit_domains_) { + if (request->url().DomainIs(domain)) { + // Allow unlimited concurrent connections. + request->SetPriority(net::MAXIMUM_PRIORITY); + request->SetLoadFlags(request->load_flags() | net::LOAD_IGNORE_LIMITS); + break; + } + } + return net::OK; + } return HandleResponseEvent(kOnBeforeRequest, request, callback, new_url); } @@ -279,8 +299,7 @@ int AtomNetworkDelegate::OnBeforeStartTransaction( kDevToolsEmulateNetworkConditionsClientId, client_id_); if (!base::ContainsKey(response_listeners_, kOnBeforeSendHeaders)) - return brightray::NetworkDelegate::OnBeforeStartTransaction( - request, callback, headers); + return net::OK; return HandleResponseEvent(kOnBeforeSendHeaders, request, callback, headers, *headers); @@ -289,10 +308,8 @@ int AtomNetworkDelegate::OnBeforeStartTransaction( void AtomNetworkDelegate::OnStartTransaction( net::URLRequest* request, const net::HttpRequestHeaders& headers) { - if (!base::ContainsKey(simple_listeners_, kOnSendHeaders)) { - brightray::NetworkDelegate::OnStartTransaction(request, headers); + if (!base::ContainsKey(simple_listeners_, kOnSendHeaders)) return; - } HandleSimpleEvent(kOnSendHeaders, request, headers); } @@ -304,8 +321,7 @@ int AtomNetworkDelegate::OnHeadersReceived( scoped_refptr* override, GURL* allowed) { if (!base::ContainsKey(response_listeners_, kOnHeadersReceived)) - return brightray::NetworkDelegate::OnHeadersReceived( - request, callback, original, override, allowed); + return net::OK; return HandleResponseEvent( kOnHeadersReceived, request, callback, @@ -314,10 +330,8 @@ int AtomNetworkDelegate::OnHeadersReceived( void AtomNetworkDelegate::OnBeforeRedirect(net::URLRequest* request, const GURL& new_location) { - if (!base::ContainsKey(simple_listeners_, kOnBeforeRedirect)) { - brightray::NetworkDelegate::OnBeforeRedirect(request, new_location); + if (!base::ContainsKey(simple_listeners_, kOnBeforeRedirect)) return; - } HandleSimpleEvent(kOnBeforeRedirect, request, new_location, request->response_headers(), request->GetSocketAddress(), @@ -326,10 +340,8 @@ void AtomNetworkDelegate::OnBeforeRedirect(net::URLRequest* request, void AtomNetworkDelegate::OnResponseStarted(net::URLRequest* request, int net_error) { - if (!base::ContainsKey(simple_listeners_, kOnResponseStarted)) { - brightray::NetworkDelegate::OnResponseStarted(request, net_error); + if (!base::ContainsKey(simple_listeners_, kOnResponseStarted)) return; - } if (request->status().status() != net::URLRequestStatus::SUCCESS) return; @@ -347,18 +359,17 @@ void AtomNetworkDelegate::OnCompleted(net::URLRequest* request, bool started) { // Error event. OnErrorOccurred(request, started); return; - } else if (request->response_headers() && - net::HttpResponseHeaders::IsRedirectResponseCode( - request->response_headers()->response_code())) { + } + + if (request->response_headers() && + net::HttpResponseHeaders::IsRedirectResponseCode( + request->response_headers()->response_code())) { // Redirect event. - brightray::NetworkDelegate::OnCompleted(request, started); return; } - if (!base::ContainsKey(simple_listeners_, kOnCompleted)) { - brightray::NetworkDelegate::OnCompleted(request, started); + if (!base::ContainsKey(simple_listeners_, kOnCompleted)) return; - } HandleSimpleEvent(kOnCompleted, request, request->response_headers(), request->was_cached()); @@ -368,12 +379,75 @@ void AtomNetworkDelegate::OnURLRequestDestroyed(net::URLRequest* request) { callbacks_.erase(request->identifier()); } +net::NetworkDelegate::AuthRequiredResponse AtomNetworkDelegate::OnAuthRequired( + net::URLRequest* request, + const net::AuthChallengeInfo& auth_info, + const AuthCallback& callback, + net::AuthCredentials* credentials) { + return AUTH_REQUIRED_RESPONSE_NO_ACTION; +} + +bool AtomNetworkDelegate::OnCanGetCookies(const net::URLRequest& request, + const net::CookieList& cookie_list) { + return true; +} + +bool AtomNetworkDelegate::OnCanSetCookie( + const net::URLRequest& request, + const net::CanonicalCookie& cookie_line, + net::CookieOptions* options) { + return true; +} + +bool AtomNetworkDelegate::OnCanAccessFile( + const net::URLRequest& request, + const base::FilePath& original_path, + const base::FilePath& absolute_path) const { + return true; +} + +bool AtomNetworkDelegate::OnCanEnablePrivacyMode( + const GURL& url, + const GURL& first_party_for_cookies) const { + return false; +} + +bool AtomNetworkDelegate::OnAreExperimentalCookieFeaturesEnabled() const { + return true; +} + +bool AtomNetworkDelegate::OnCancelURLRequestWithPolicyViolatingReferrerHeader( + const net::URLRequest& request, + const GURL& target_url, + const GURL& referrer_url) const { + return false; +} + +// TODO(deepak1556) : Enable after hooking into the reporting service +// https://crbug.com/704259 +bool AtomNetworkDelegate::OnCanQueueReportingReport( + const url::Origin& origin) const { + return false; +} + +void AtomNetworkDelegate::OnCanSendReportingReports( + std::set origins, + base::OnceCallback)> result_callback) const {} + +bool AtomNetworkDelegate::OnCanSetReportingClient(const url::Origin& origin, + const GURL& endpoint) const { + return false; +} + +bool AtomNetworkDelegate::OnCanUseReportingClient(const url::Origin& origin, + const GURL& endpoint) const { + return false; +} + void AtomNetworkDelegate::OnErrorOccurred(net::URLRequest* request, bool started) { - if (!base::ContainsKey(simple_listeners_, kOnErrorOccurred)) { - brightray::NetworkDelegate::OnCompleted(request, started); + if (!base::ContainsKey(simple_listeners_, kOnErrorOccurred)) return; - } HandleSimpleEvent(kOnErrorOccurred, request, request->was_cached(), request->status()); diff --git a/atom/browser/net/atom_network_delegate.h b/atom/browser/net/atom_network_delegate.h index 9288b70cb422..32f16b40ab29 100644 --- a/atom/browser/net/atom_network_delegate.h +++ b/atom/browser/net/atom_network_delegate.h @@ -8,14 +8,14 @@ #include #include #include +#include #include "base/callback.h" #include "base/synchronization/lock.h" #include "base/values.h" -#include "brightray/browser/network_delegate.h" #include "content/public/browser/resource_request_info.h" #include "extensions/common/url_pattern.h" -#include "net/base/net_errors.h" +#include "net/base/network_delegate.h" #include "net/http/http_request_headers.h" #include "net/http/http_response_headers.h" @@ -27,7 +27,7 @@ using URLPatterns = std::set; const char* ResourceTypeToString(content::ResourceType type); -class AtomNetworkDelegate : public brightray::NetworkDelegate { +class AtomNetworkDelegate : public net::NetworkDelegate { public: using ResponseCallback = base::Callback; using SimpleListener = base::Callback; @@ -86,6 +86,10 @@ class AtomNetworkDelegate : public brightray::NetworkDelegate { int OnBeforeStartTransaction(net::URLRequest* request, const net::CompletionCallback& callback, net::HttpRequestHeaders* headers) override; + void OnBeforeSendHeaders(net::URLRequest* request, + const net::ProxyInfo& proxy_info, + const net::ProxyRetryInfoMap& proxy_retry_info, + net::HttpRequestHeaders* headers) override {} void OnStartTransaction(net::URLRequest* request, const net::HttpRequestHeaders& headers) override; int OnHeadersReceived( @@ -97,8 +101,43 @@ class AtomNetworkDelegate : public brightray::NetworkDelegate { void OnBeforeRedirect(net::URLRequest* request, const GURL& new_location) override; void OnResponseStarted(net::URLRequest* request, int net_error) override; + void OnNetworkBytesReceived(net::URLRequest* request, + int64_t bytes_read) override {} + void OnNetworkBytesSent(net::URLRequest* request, + int64_t bytes_sent) override {} void OnCompleted(net::URLRequest* request, bool started) override; void OnURLRequestDestroyed(net::URLRequest* request) override; + void OnPACScriptError(int line_number, const base::string16& error) override { + } + AuthRequiredResponse OnAuthRequired( + net::URLRequest* request, + const net::AuthChallengeInfo& auth_info, + const AuthCallback& callback, + net::AuthCredentials* credentials) override; + bool OnCanGetCookies(const net::URLRequest& request, + const net::CookieList& cookie_list) override; + bool OnCanSetCookie(const net::URLRequest& request, + const net::CanonicalCookie& cookie_line, + net::CookieOptions* options) override; + bool OnCanAccessFile(const net::URLRequest& request, + const base::FilePath& original_path, + const base::FilePath& absolute_path) const override; + bool OnCanEnablePrivacyMode( + const GURL& url, + const GURL& first_party_for_cookies) const override; + bool OnAreExperimentalCookieFeaturesEnabled() const override; + bool OnCancelURLRequestWithPolicyViolatingReferrerHeader( + const net::URLRequest& request, + const GURL& target_url, + const GURL& referrer_url) const override; + bool OnCanQueueReportingReport(const url::Origin& origin) const override; + void OnCanSendReportingReports(std::set origins, + base::OnceCallback)> + result_callback) const override; + bool OnCanSetReportingClient(const url::Origin& origin, + const GURL& endpoint) const override; + bool OnCanUseReportingClient(const url::Origin& origin, + const GURL& endpoint) const override; private: void OnErrorOccurred(net::URLRequest* request, bool started); @@ -127,6 +166,7 @@ class AtomNetworkDelegate : public brightray::NetworkDelegate { std::map simple_listeners_; std::map response_listeners_; std::map callbacks_; + std::vector ignore_connections_limit_domains_; // Client id for devtools network emulation. std::string client_id_; diff --git a/atom/browser/net/atom_url_request.cc b/atom/browser/net/atom_url_request.cc index 8c0fbc4987bd..4ec9d9aa973e 100644 --- a/atom/browser/net/atom_url_request.cc +++ b/atom/browser/net/atom_url_request.cc @@ -4,7 +4,9 @@ // found in the LICENSE file. #include "atom/browser/net/atom_url_request.h" + #include + #include "atom/browser/api/atom_api_url_request.h" #include "atom/browser/atom_browser_context.h" #include "atom/browser/net/atom_url_request_job_factory.h" @@ -70,11 +72,7 @@ scoped_refptr AtomURLRequest::Create( return nullptr; } scoped_refptr request_context_getter( - browser_context->url_request_context_getter()); - DCHECK(request_context_getter); - if (!request_context_getter) { - return nullptr; - } + browser_context->GetRequestContext()); scoped_refptr atom_url_request(new AtomURLRequest(delegate)); if (content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, diff --git a/atom/browser/net/atom_url_request_job_factory.cc b/atom/browser/net/atom_url_request_job_factory.cc index 7047f7a6f7f8..9d50cd545177 100644 --- a/atom/browser/net/atom_url_request_job_factory.cc +++ b/atom/browser/net/atom_url_request_job_factory.cc @@ -33,9 +33,14 @@ AtomURLRequestJobFactory::~AtomURLRequestJobFactory() { Clear(); } +void AtomURLRequestJobFactory::Chain( + std::unique_ptr job_factory) { + job_factory_ = std::move(job_factory); +} + bool AtomURLRequestJobFactory::SetProtocolHandler( const std::string& scheme, - std::unique_ptr protocol_handler) { + std::unique_ptr protocol_handler) const { if (!protocol_handler) { auto it = protocol_handler_map_.find(scheme); if (it == protocol_handler_map_.end()) @@ -54,41 +59,41 @@ bool AtomURLRequestJobFactory::SetProtocolHandler( bool AtomURLRequestJobFactory::InterceptProtocol( const std::string& scheme, - std::unique_ptr protocol_handler) { - if (!base::ContainsKey(protocol_handler_map_, scheme) || + std::unique_ptr protocol_handler) const { + if (!IsHandledProtocol(scheme) || base::ContainsKey(original_protocols_, scheme)) return false; - ProtocolHandler* original_protocol_handler = protocol_handler_map_[scheme]; + auto it = protocol_handler_map_.find(scheme); + if (it != protocol_handler_map_.end()) { + original_protocols_[scheme].reset(it->second); + } else { + original_protocols_[scheme] = nullptr; + } protocol_handler_map_[scheme] = protocol_handler.release(); - original_protocols_[scheme].reset(original_protocol_handler); return true; } -bool AtomURLRequestJobFactory::UninterceptProtocol(const std::string& scheme) { +bool AtomURLRequestJobFactory::UninterceptProtocol( + const std::string& scheme) const { auto it = original_protocols_.find(scheme); if (it == original_protocols_.end()) return false; - protocol_handler_map_[scheme] = it->second.release(); + + if (it->second) { + protocol_handler_map_[scheme] = it->second.release(); + } else { + protocol_handler_map_.erase(scheme); + } original_protocols_.erase(it); return true; } -ProtocolHandler* AtomURLRequestJobFactory::GetProtocolHandler( - const std::string& scheme) const { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - auto it = protocol_handler_map_.find(scheme); - if (it == protocol_handler_map_.end()) - return nullptr; - return it->second; -} - bool AtomURLRequestJobFactory::HasProtocolHandler( const std::string& scheme) const { return base::ContainsKey(protocol_handler_map_, scheme); } -void AtomURLRequestJobFactory::Clear() { +void AtomURLRequestJobFactory::Clear() const { for (auto& it : protocol_handler_map_) delete it.second; protocol_handler_map_.clear(); @@ -101,33 +106,42 @@ net::URLRequestJob* AtomURLRequestJobFactory::MaybeCreateJobWithProtocolHandler( net::NetworkDelegate* network_delegate) const { DCHECK_CURRENTLY_ON(BrowserThread::IO); - auto it = protocol_handler_map_.find(scheme); - if (it == protocol_handler_map_.end()) - return nullptr; + // Check if some interceptors like service worker are interested in + // handling the request. + auto* job = job_factory_->MaybeCreateJobWithProtocolHandler(scheme, request, + network_delegate); + if (job) + return job; + if (request->GetUserData(DisableProtocolInterceptFlagKey())) return nullptr; - return it->second->MaybeCreateJob(request, network_delegate); + + auto it = protocol_handler_map_.find(scheme); + if (it != protocol_handler_map_.end()) + return it->second->MaybeCreateJob(request, network_delegate); + + return nullptr; } net::URLRequestJob* AtomURLRequestJobFactory::MaybeInterceptRedirect( net::URLRequest* request, net::NetworkDelegate* network_delegate, const GURL& location) const { - return nullptr; + return job_factory_->MaybeInterceptRedirect(request, network_delegate, + location); } net::URLRequestJob* AtomURLRequestJobFactory::MaybeInterceptResponse( net::URLRequest* request, net::NetworkDelegate* network_delegate) const { - return nullptr; + return job_factory_->MaybeInterceptResponse(request, network_delegate); } bool AtomURLRequestJobFactory::IsHandledProtocol( const std::string& scheme) const { DCHECK_CURRENTLY_ON(BrowserThread::IO); - return HasProtocolHandler(scheme) || - net::URLRequest::IsHandledProtocol(scheme); + return HasProtocolHandler(scheme) || job_factory_->IsHandledProtocol(scheme); } bool AtomURLRequestJobFactory::IsSafeRedirectTarget( @@ -136,7 +150,8 @@ bool AtomURLRequestJobFactory::IsSafeRedirectTarget( // We handle error cases. return true; } - return IsHandledProtocol(location.scheme()); + return HasProtocolHandler(location.spec()) || + job_factory_->IsSafeRedirectTarget(location); } } // namespace atom diff --git a/atom/browser/net/atom_url_request_job_factory.h b/atom/browser/net/atom_url_request_job_factory.h index c0e26568fdea..1af3f8fca274 100644 --- a/atom/browser/net/atom_url_request_job_factory.h +++ b/atom/browser/net/atom_url_request_job_factory.h @@ -23,25 +23,28 @@ class AtomURLRequestJobFactory : public net::URLRequestJobFactory { AtomURLRequestJobFactory(); ~AtomURLRequestJobFactory() override; + // Requests are forwarded to the chained job factory if + // this class decides to not handle them. + void Chain(std::unique_ptr job_factory); + // Sets the ProtocolHandler for a scheme. Returns true on success, false on // failure (a ProtocolHandler already exists for |scheme|). On success, // URLRequestJobFactory takes ownership of |protocol_handler|. - bool SetProtocolHandler(const std::string& scheme, - std::unique_ptr protocol_handler); + bool SetProtocolHandler( + const std::string& scheme, + std::unique_ptr protocol_handler) const; // Intercepts the ProtocolHandler for a scheme. - bool InterceptProtocol(const std::string& scheme, - std::unique_ptr protocol_handler); - bool UninterceptProtocol(const std::string& scheme); - - // Returns the protocol handler registered with scheme. - ProtocolHandler* GetProtocolHandler(const std::string& scheme) const; + bool InterceptProtocol( + const std::string& scheme, + std::unique_ptr protocol_handler) const; + bool UninterceptProtocol(const std::string& scheme) const; // Whether the protocol handler is registered by the job factory. bool HasProtocolHandler(const std::string& scheme) const; // Clear all protocol handlers. - void Clear(); + void Clear() const; // URLRequestJobFactory implementation net::URLRequestJob* MaybeCreateJobWithProtocolHandler( @@ -61,13 +64,15 @@ class AtomURLRequestJobFactory : public net::URLRequestJobFactory { private: using ProtocolHandlerMap = std::map; - ProtocolHandlerMap protocol_handler_map_; + mutable ProtocolHandlerMap protocol_handler_map_; // Map that stores the original protocols of schemes. using OriginalProtocolsMap = std::unordered_map>; // Can only be accessed in IO thread. - OriginalProtocolsMap original_protocols_; + mutable OriginalProtocolsMap original_protocols_; + + std::unique_ptr job_factory_; DISALLOW_COPY_AND_ASSIGN(AtomURLRequestJobFactory); }; diff --git a/atom/browser/net/http_protocol_handler.cc b/atom/browser/net/http_protocol_handler.cc deleted file mode 100644 index 7c5cc365b74b..000000000000 --- a/atom/browser/net/http_protocol_handler.cc +++ /dev/null @@ -1,22 +0,0 @@ -// 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/net/http_protocol_handler.h" - -#include "net/url_request/url_request_http_job.h" - -namespace atom { - -HttpProtocolHandler::HttpProtocolHandler(const std::string& scheme) - : scheme_(scheme) {} - -HttpProtocolHandler::~HttpProtocolHandler() {} - -net::URLRequestJob* HttpProtocolHandler::MaybeCreateJob( - net::URLRequest* request, - net::NetworkDelegate* network_delegate) const { - return net::URLRequestHttpJob::Factory(request, network_delegate, scheme_); -} - -} // namespace atom diff --git a/atom/browser/net/http_protocol_handler.h b/atom/browser/net/http_protocol_handler.h deleted file mode 100644 index 39e1ff2ad29b..000000000000 --- a/atom/browser/net/http_protocol_handler.h +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2015 GitHub, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#ifndef ATOM_BROWSER_NET_HTTP_PROTOCOL_HANDLER_H_ -#define ATOM_BROWSER_NET_HTTP_PROTOCOL_HANDLER_H_ - -#include - -#include "net/url_request/url_request_job_factory.h" - -namespace atom { - -class HttpProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler { - public: - explicit HttpProtocolHandler(const std::string&); - ~HttpProtocolHandler() override; - - // net::URLRequestJobFactory::ProtocolHandler: - net::URLRequestJob* MaybeCreateJob( - net::URLRequest* request, - net::NetworkDelegate* network_delegate) const override; - - private: - std::string scheme_; -}; - -} // namespace atom - -#endif // ATOM_BROWSER_NET_HTTP_PROTOCOL_HANDLER_H_ diff --git a/atom/browser/net/js_asker.h b/atom/browser/net/js_asker.h index 45e2da9b8220..f4f43eac2d46 100644 --- a/atom/browser/net/js_asker.h +++ b/atom/browser/net/js_asker.h @@ -7,7 +7,6 @@ #include "atom/common/native_mate_converters/net_converter.h" #include "base/callback.h" -#include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/values.h" #include "content/public/browser/browser_thread.h" diff --git a/atom/browser/net/request_context_factory.cc b/atom/browser/net/request_context_factory.cc new file mode 100644 index 000000000000..db6dd15c8b57 --- /dev/null +++ b/atom/browser/net/request_context_factory.cc @@ -0,0 +1,375 @@ +// Copyright (c) 2018 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/net/request_context_factory.h" + +#include + +#include "atom/browser/atom_browser_context.h" +#include "atom/browser/net/about_protocol_handler.h" +#include "atom/browser/net/asar/asar_protocol_handler.h" +#include "atom/browser/net/atom_cert_verifier.h" +#include "atom/browser/net/atom_network_delegate.h" +#include "atom/browser/net/atom_url_request_job_factory.h" +#include "atom/browser/net/cookie_details.h" +#include "atom/common/options_switches.h" +#include "base/command_line.h" +#include "base/memory/ptr_util.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" +#include "base/task_scheduler/post_task.h" +#include "brightray/browser/browser_client.h" +#include "brightray/browser/net/require_ct_delegate.h" +#include "brightray/browser/net/url_request_context_getter_factory.h" +#include "brightray/browser/net_log.h" +#include "components/network_session_configurator/common/network_switches.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/cookie_store_factory.h" +#include "content/public/browser/devtools_network_transaction_factory.h" +#include "content/public/browser/resource_context.h" +#include "net/base/host_mapping_rules.h" +#include "net/cert/cert_verifier.h" +#include "net/cert/ct_known_logs.h" +#include "net/cert/ct_log_verifier.h" +#include "net/cert/ct_policy_enforcer.h" +#include "net/cert/multi_log_ct_verifier.h" +#include "net/cookies/cookie_monster.h" +#include "net/cookies/cookie_store.h" +#include "net/dns/mapped_host_resolver.h" +#include "net/ftp/ftp_network_layer.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_server_properties_impl.h" +#include "net/http/transport_security_state.h" +#include "net/proxy_resolution/dhcp_pac_file_fetcher_factory.h" +#include "net/proxy_resolution/pac_file_fetcher_impl.h" +#include "net/proxy_resolution/proxy_config.h" +#include "net/proxy_resolution/proxy_config_service.h" +#include "net/proxy_resolution/proxy_service.h" +#include "net/ssl/channel_id_service.h" +#include "net/ssl/default_channel_id_store.h" +#include "net/ssl/ssl_config_service_defaults.h" +#include "net/url_request/data_protocol_handler.h" +#include "net/url_request/file_protocol_handler.h" +#include "net/url_request/ftp_protocol_handler.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_builder.h" +#include "net/url_request/url_request_context_storage.h" +#include "net/url_request/url_request_intercepting_job_factory.h" +#include "net/url_request/url_request_job_factory_impl.h" +#include "services/network/public/cpp/network_switches.h" + +using content::BrowserThread; + +namespace atom { + +namespace { + +class NoCacheBackend : public net::HttpCache::BackendFactory { + int CreateBackend(net::NetLog* net_log, + std::unique_ptr* backend, + const net::CompletionCallback& callback) override { + return net::ERR_FAILED; + } +}; + +net::HttpCache::BackendFactory* CreateHttpCacheBackendFactory( + bool use_cache, + const base::FilePath& base_path) { + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + if (!use_cache || + command_line->HasSwitch(atom::switches::kDisableHttpCache)) { + return new NoCacheBackend; + } else { + int max_size = 0; + base::StringToInt( + command_line->GetSwitchValueASCII(atom::switches::kDiskCacheSize), + &max_size); + base::FilePath cache_path = base_path.Append(FILE_PATH_LITERAL("Cache")); + return new net::HttpCache::DefaultBackend( + net::DISK_CACHE, net::CACHE_BACKEND_DEFAULT, cache_path, max_size); + } +} + +std::unique_ptr CreateURLRequestJobFactory( + content::ProtocolHandlerMap* protocol_handlers, + content::URLRequestInterceptorScopedVector request_interceptors, + net::HostResolver* host_resolver) { + std::unique_ptr job_factory( + new AtomURLRequestJobFactory); + + for (auto& it : *protocol_handlers) { + job_factory->SetProtocolHandler(it.first, + base::WrapUnique(it.second.release())); + } + protocol_handlers->clear(); + + job_factory->SetProtocolHandler(url::kAboutScheme, + base::WrapUnique(new AboutProtocolHandler)); + job_factory->SetProtocolHandler( + url::kDataScheme, base::WrapUnique(new net::DataProtocolHandler)); + job_factory->SetProtocolHandler( + url::kFileScheme, + base::WrapUnique( + new asar::AsarProtocolHandler(base::CreateTaskRunnerWithTraits( + {base::MayBlock(), base::TaskPriority::USER_VISIBLE, + base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})))); + job_factory->SetProtocolHandler( + url::kFtpScheme, net::FtpProtocolHandler::Create(host_resolver)); + + // Set up interceptors in the reverse order. + std::unique_ptr top_job_factory = + std::make_unique(); + if (!request_interceptors.empty()) { + for (auto it = request_interceptors.rbegin(); + it != request_interceptors.rend(); ++it) { + top_job_factory.reset(new net::URLRequestInterceptingJobFactory( + std::move(top_job_factory), std::move(*it))); + } + request_interceptors.clear(); + } + + job_factory->Chain(std::move(top_job_factory)); + return std::move(job_factory); +} + +} // namespace + +AtomMainRequestContextFactory::AtomMainRequestContextFactory( + const base::FilePath& path, + bool in_memory, + bool use_cache, + std::string user_agent, + std::vector cookieable_schemes, + content::ProtocolHandlerMap* protocol_handlers, + content::URLRequestInterceptorScopedVector request_interceptors, + AtomBrowserContext* browser_context) + : base_path_(path), + in_memory_(in_memory), + use_cache_(use_cache), + user_agent_(user_agent), + cookieable_schemes_(cookieable_schemes), + request_interceptors_(std::move(request_interceptors)), + browser_context_(browser_context), + weak_ptr_factory_(this) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + if (protocol_handlers) + std::swap(protocol_handlers_, *protocol_handlers); + + net_log_ = static_cast( + brightray::BrowserClient::Get()->GetNetLog()); + + // We must create the proxy config service on the UI loop on Linux because it + // must synchronously run on the glib message loop. This will be passed to + // the URLRequestContextStorage on the IO thread in GetURLRequestContext(). + proxy_config_service_ = + net::ProxyResolutionService::CreateSystemProxyConfigService( + BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)); +} + +AtomMainRequestContextFactory::~AtomMainRequestContextFactory() {} + +void AtomMainRequestContextFactory::OnCookieChanged( + const net::CanonicalCookie& cookie, + net::CookieChangeCause cause) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::BindOnce(&AtomMainRequestContextFactory::NotifyCookieChange, + weak_ptr_factory_.GetWeakPtr(), cookie, cause)); +} + +void AtomMainRequestContextFactory::NotifyCookieChange( + const net::CanonicalCookie& cookie, + net::CookieChangeCause cause) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + CookieDetails cookie_details( + &cookie, !(cause == net::CookieChangeCause::INSERTED), cause); + + if (browser_context_) + browser_context_->NotifyCookieChange(&cookie_details); +} + +net::URLRequestContext* AtomMainRequestContextFactory::Create() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + auto& command_line = *base::CommandLine::ForCurrentProcess(); + url_request_context_.reset(new net::URLRequestContext); + + ct_delegate_.reset(new brightray::RequireCTDelegate); + + // --log-net-log + if (net_log_) { + net_log_->StartLogging(); + url_request_context_->set_net_log(net_log_); + } + + storage_.reset(new net::URLRequestContextStorage(url_request_context_.get())); + + storage_->set_network_delegate(std::make_unique()); + + auto cookie_path = in_memory_ + ? base::FilePath() + : base_path_.Append(FILE_PATH_LITERAL("Cookies")); + std::unique_ptr cookie_store = content::CreateCookieStore( + content::CookieStoreConfig(cookie_path, false, false, nullptr)); + storage_->set_cookie_store(std::move(cookie_store)); + + // Set custom schemes that can accept cookies. + net::CookieMonster* cookie_monster = + static_cast(url_request_context_->cookie_store()); + cookie_monster->SetCookieableSchemes(cookieable_schemes_); + // Cookie store will outlive notifier by order of declaration + // in the header. + cookie_change_sub_ = url_request_context_->cookie_store() + ->GetChangeDispatcher() + .AddCallbackForAllChanges(base::Bind( + &AtomMainRequestContextFactory::OnCookieChanged, + base::Unretained(this))); + + storage_->set_channel_id_service(std::make_unique( + new net::DefaultChannelIDStore(nullptr))); + + storage_->set_http_user_agent_settings( + base::WrapUnique(new net::StaticHttpUserAgentSettings( + net::HttpUtil::GenerateAcceptLanguageHeader( + brightray::BrowserClient::Get()->GetApplicationLocale()), + user_agent_))); + + std::unique_ptr host_resolver( + net::HostResolver::CreateDefaultResolver(nullptr)); + + // --host-resolver-rules + if (command_line.HasSwitch(network::switches::kHostResolverRules)) { + std::unique_ptr remapped_resolver( + new net::MappedHostResolver(std::move(host_resolver))); + remapped_resolver->SetRulesFromString(command_line.GetSwitchValueASCII( + network::switches::kHostResolverRules)); + host_resolver = std::move(remapped_resolver); + } + + // --proxy-server + if (command_line.HasSwitch(switches::kNoProxyServer)) { + storage_->set_proxy_resolution_service( + net::ProxyResolutionService::CreateDirect()); + } else if (command_line.HasSwitch(switches::kProxyServer)) { + net::ProxyConfig proxy_config; + proxy_config.proxy_rules().ParseFromString( + command_line.GetSwitchValueASCII(switches::kProxyServer)); + proxy_config.proxy_rules().bypass_rules.ParseFromString( + command_line.GetSwitchValueASCII(switches::kProxyBypassList)); + storage_->set_proxy_resolution_service( + net::ProxyResolutionService::CreateFixed(proxy_config)); + } else if (command_line.HasSwitch(switches::kProxyPacUrl)) { + auto proxy_config = net::ProxyConfig::CreateFromCustomPacURL( + GURL(command_line.GetSwitchValueASCII(switches::kProxyPacUrl))); + proxy_config.set_pac_mandatory(true); + storage_->set_proxy_resolution_service( + net::ProxyResolutionService::CreateFixed(proxy_config)); + } else { + storage_->set_proxy_resolution_service( + net::ProxyResolutionService::CreateUsingSystemProxyResolver( + std::move(proxy_config_service_), net_log_)); + } + + std::vector schemes; + schemes.push_back(std::string("basic")); + schemes.push_back(std::string("digest")); + schemes.push_back(std::string("ntlm")); + schemes.push_back(std::string("negotiate")); +#if defined(OS_POSIX) + http_auth_preferences_.reset( + new net::HttpAuthPreferences(schemes, std::string())); +#else + http_auth_preferences_.reset(new net::HttpAuthPreferences(schemes)); +#endif + + // --auth-server-whitelist + if (command_line.HasSwitch(switches::kAuthServerWhitelist)) { + http_auth_preferences_->SetServerWhitelist( + command_line.GetSwitchValueASCII(switches::kAuthServerWhitelist)); + } + + // --auth-negotiate-delegate-whitelist + if (command_line.HasSwitch(switches::kAuthNegotiateDelegateWhitelist)) { + http_auth_preferences_->SetDelegateWhitelist( + command_line.GetSwitchValueASCII( + switches::kAuthNegotiateDelegateWhitelist)); + } + + auto auth_handler_factory = net::HttpAuthHandlerRegistryFactory::Create( + http_auth_preferences_.get(), host_resolver.get()); + + std::unique_ptr transport_security_state = + std::make_unique(); + transport_security_state->SetRequireCTDelegate(ct_delegate_.get()); + storage_->set_transport_security_state(std::move(transport_security_state)); + storage_->set_cert_verifier( + std::make_unique(ct_delegate_.get())); + storage_->set_ssl_config_service(new net::SSLConfigServiceDefaults); + storage_->set_http_auth_handler_factory(std::move(auth_handler_factory)); + std::unique_ptr server_properties( + new net::HttpServerPropertiesImpl); + storage_->set_http_server_properties(std::move(server_properties)); + + std::unique_ptr ct_verifier = + std::make_unique(); + ct_verifier->AddLogs(net::ct::CreateLogVerifiersForKnownLogs()); + storage_->set_cert_transparency_verifier(std::move(ct_verifier)); + storage_->set_ct_policy_enforcer(std::make_unique()); + + net::HttpNetworkSession::Params network_session_params; + network_session_params.ignore_certificate_errors = false; + + // --disable-http2 + if (command_line.HasSwitch(switches::kDisableHttp2)) + network_session_params.enable_http2 = false; + + // --ignore-certificate-errors + if (command_line.HasSwitch(::switches::kIgnoreCertificateErrors)) + network_session_params.ignore_certificate_errors = true; + + // --host-rules + if (command_line.HasSwitch(switches::kHostRules)) { + host_mapping_rules_.reset(new net::HostMappingRules); + host_mapping_rules_->SetRulesFromString( + command_line.GetSwitchValueASCII(switches::kHostRules)); + network_session_params.host_mapping_rules = *host_mapping_rules_.get(); + } + + // Give |storage_| ownership at the end in case it's |mapped_host_resolver|. + storage_->set_host_resolver(std::move(host_resolver)); + + net::HttpNetworkSession::Context network_session_context; + net::URLRequestContextBuilder::SetHttpNetworkSessionComponents( + url_request_context_.get(), &network_session_context); + http_network_session_.reset(new net::HttpNetworkSession( + network_session_params, network_session_context)); + + std::unique_ptr backend; + if (in_memory_) { + backend = net::HttpCache::DefaultBackend::InMemory(0); + } else { + backend.reset(CreateHttpCacheBackendFactory(use_cache_, base_path_)); + } + + storage_->set_http_transaction_factory(std::make_unique( + content::CreateDevToolsNetworkTransactionFactory( + http_network_session_.get()), + std::move(backend), false)); + + std::unique_ptr job_factory = + CreateURLRequestJobFactory(&protocol_handlers_, + std::move(request_interceptors_), + url_request_context_->host_resolver()); + storage_->set_job_factory(std::move(job_factory)); + + return url_request_context_.get(); +} + +} // namespace atom diff --git a/atom/browser/net/request_context_factory.h b/atom/browser/net/request_context_factory.h new file mode 100644 index 000000000000..b3c553b99c62 --- /dev/null +++ b/atom/browser/net/request_context_factory.h @@ -0,0 +1,86 @@ +// Copyright (c) 2018 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_NET_REQUEST_CONTEXT_FACTORY_H_ +#define ATOM_BROWSER_NET_REQUEST_CONTEXT_FACTORY_H_ + +#include +#include + +#include "base/files/file_path.h" +#include "brightray/browser/net/url_request_context_getter_factory.h" +#include "content/public/browser/browser_context.h" +#include "net/cookies/cookie_change_dispatcher.h" + +namespace net { +class HostMappingRules; +class HttpAuthPreferences; +class HttpNetworkSession; +class ProxyConfigService; +class URLRequestContextStorage; +} // namespace net + +namespace brightray { +class NetLog; +class RequireCTDelegate; +} // namespace brightray + +namespace atom { + +class AtomBrowserContext; +struct CookieDetails; + +class AtomMainRequestContextFactory + : public brightray::URLRequestContextGetterFactory { + public: + AtomMainRequestContextFactory( + const base::FilePath& path, + bool in_memory, + bool use_cache, + std::string user_agent, + std::vector cookieable_schemes, + content::ProtocolHandlerMap* protocol_handlers, + content::URLRequestInterceptorScopedVector request_interceptors, + AtomBrowserContext* browser_context); + ~AtomMainRequestContextFactory() override; + + // URLRequestContextGetterFactory: + net::URLRequestContext* Create() override; + + private: + // Notify cookie changes on the UI thread. + void NotifyCookieChange(const net::CanonicalCookie& cookie, + net::CookieChangeCause cause); + // net::CookieChangeDispatcher::CookieChangedCallback implementation. + // Called on the IO thread. + void OnCookieChanged(const net::CanonicalCookie& cookie, + net::CookieChangeCause cause); + + base::FilePath base_path_; + bool in_memory_; + bool use_cache_; + std::string user_agent_; + std::vector cookieable_schemes_; + content::ProtocolHandlerMap protocol_handlers_; + content::URLRequestInterceptorScopedVector request_interceptors_; + brightray::NetLog* net_log_; + AtomBrowserContext* browser_context_; + + std::unique_ptr proxy_config_service_; + std::unique_ptr ct_delegate_; + std::unique_ptr host_mapping_rules_; + std::unique_ptr http_auth_preferences_; + std::unique_ptr http_network_session_; + std::unique_ptr storage_; + std::unique_ptr cookie_change_sub_; + std::unique_ptr url_request_context_; + + base::WeakPtrFactory weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(AtomMainRequestContextFactory); +}; + +} // namespace atom + +#endif // ATOM_BROWSER_NET_REQUEST_CONTEXT_FACTORY_H_ diff --git a/atom/browser/net/url_request_fetch_job.cc b/atom/browser/net/url_request_fetch_job.cc index 09f7277ab659..36b434ca833f 100644 --- a/atom/browser/net/url_request_fetch_job.cc +++ b/atom/browser/net/url_request_fetch_job.cc @@ -93,16 +93,13 @@ void URLRequestFetchJob::BeforeStartInUI(v8::Isolate* isolate, if (options.Get("session", &val)) { if (val->IsNull()) { // We have to create the URLRequestContextGetter on UI thread. - url_request_context_getter_ = new brightray::URLRequestContextGetter( - this, nullptr, base::FilePath(), true, - BrowserThread::GetTaskRunnerForThread(BrowserThread::IO), nullptr, - content::URLRequestInterceptorScopedVector()); + url_request_context_getter_ = + new brightray::URLRequestContextGetter(nullptr, nullptr); } else { mate::Handle session; if (mate::ConvertFromV8(isolate, val, &session) && !session.IsEmpty()) { AtomBrowserContext* browser_context = session->browser_context(); - url_request_context_getter_ = - browser_context->url_request_context_getter(); + url_request_context_getter_ = browser_context->GetRequestContext(); } } } @@ -167,6 +164,8 @@ void URLRequestFetchJob::StartAsync(std::unique_ptr options) { request()->extra_request_headers().ToString()); fetcher_->Start(); + + url_request_context_getter_ = nullptr; } void URLRequestFetchJob::HeadersCompleted() { diff --git a/atom/browser/net/url_request_fetch_job.h b/atom/browser/net/url_request_fetch_job.h index d952074b2097..6d50edd4dc54 100644 --- a/atom/browser/net/url_request_fetch_job.h +++ b/atom/browser/net/url_request_fetch_job.h @@ -8,16 +8,15 @@ #include #include "atom/browser/net/js_asker.h" -#include "brightray/browser/url_request_context_getter.h" #include "content/browser/streams/stream.h" #include "content/browser/streams/stream_read_observer.h" #include "net/url_request/url_fetcher_delegate.h" +#include "net/url_request/url_request_context_getter.h" namespace atom { class URLRequestFetchJob : public JsAsker, - public net::URLFetcherDelegate, - public brightray::URLRequestContextGetter::Delegate { + public net::URLFetcherDelegate { public: URLRequestFetchJob(net::URLRequest*, net::NetworkDelegate*); ~URLRequestFetchJob() override; diff --git a/atom/common/options_switches.cc b/atom/common/options_switches.cc index 17a8800d24f5..5cbe79aba250 100644 --- a/atom/common/options_switches.cc +++ b/atom/common/options_switches.cc @@ -170,9 +170,6 @@ const char kPpapiFlashPath[] = "ppapi-flash-path"; // Ppapi Flash version. const char kPpapiFlashVersion[] = "ppapi-flash-version"; -// Disable HTTP cache. -const char kDisableHttpCache[] = "disable-http-cache"; - // The list of standard schemes. const char kStandardSchemes[] = "standard-schemes"; @@ -210,6 +207,57 @@ const char kWidevineCdmPath[] = "widevine-cdm-path"; // Widevine CDM version. const char kWidevineCdmVersion[] = "widevine-cdm-version"; +// Comma-separated list of rules that control how hostnames are mapped. +// +// For example: +// "MAP * 127.0.0.1" --> Forces all hostnames to be mapped to 127.0.0.1 +// "MAP *.google.com proxy" --> Forces all google.com subdomains to be +// resolved to "proxy". +// "MAP test.com [::1]:77 --> Forces "test.com" to resolve to IPv6 loopback. +// Will also force the port of the resulting +// socket address to be 77. +// "MAP * baz, EXCLUDE www.google.com" --> Remaps everything to "baz", +// except for "www.google.com". +// +// These mappings apply to the endpoint host in a net::URLRequest (the TCP +// connect and host resolver in a direct connection, and the CONNECT in an http +// proxy connection, and the endpoint host in a SOCKS proxy connection). +const char kHostRules[] = "host-rules"; + +// Don't use a proxy server, always make direct connections. Overrides any +// other proxy server flags that are passed. +const char kNoProxyServer[] = "no-proxy-server"; + +// Uses a specified proxy server, overrides system settings. This switch only +// affects HTTP and HTTPS requests. +const char kProxyServer[] = "proxy-server"; + +// Bypass specified proxy for the given semi-colon-separated list of hosts. This +// flag has an effect only when --proxy-server is set. +const char kProxyBypassList[] = "proxy-bypass-list"; + +// Uses the pac script at the given URL. +const char kProxyPacUrl[] = "proxy-pac-url"; + +// Disable HTTP/2 and SPDY/3.1 protocols. +const char kDisableHttp2[] = "disable-http2"; + +// Disable HTTP cache. +const char kDisableHttpCache[] = "disable-http-cache"; + +// Whitelist containing servers for which Integrated Authentication is enabled. +const char kAuthServerWhitelist[] = "auth-server-whitelist"; + +// Whitelist containing servers for which Kerberos delegation is allowed. +const char kAuthNegotiateDelegateWhitelist[] = + "auth-negotiate-delegate-whitelist"; + +// Forces the maximum disk space to be used by the disk cache, in bytes. +const char kDiskCacheSize[] = "disk-cache-size"; + +// Ignore the limit of 6 connections per host. +const char kIgnoreConnectionsLimit[] = "ignore-connections-limit"; + } // namespace switches } // namespace atom diff --git a/atom/common/options_switches.h b/atom/common/options_switches.h index 387b11d8d657..a255134dbd90 100644 --- a/atom/common/options_switches.h +++ b/atom/common/options_switches.h @@ -86,7 +86,6 @@ extern const char kEnableMixedSandbox[]; extern const char kEnablePlugins[]; extern const char kPpapiFlashPath[]; extern const char kPpapiFlashVersion[]; -extern const char kDisableHttpCache[]; extern const char kStandardSchemes[]; extern const char kRegisterServiceWorkerSchemes[]; extern const char kSecureSchemes[]; @@ -109,6 +108,18 @@ extern const char kWebviewTag[]; extern const char kWidevineCdmPath[]; extern const char kWidevineCdmVersion[]; +extern const char kHostRules[]; +extern const char kNoProxyServer[]; +extern const char kProxyServer[]; +extern const char kProxyBypassList[]; +extern const char kProxyPacUrl[]; +extern const char kDisableHttp2[]; +extern const char kDisableHttpCache[]; +extern const char kAuthServerWhitelist[]; +extern const char kAuthNegotiateDelegateWhitelist[]; +extern const char kDiskCacheSize[]; +extern const char kIgnoreConnectionsLimit[]; + } // namespace switches } // namespace atom diff --git a/brightray/browser/browser_context.cc b/brightray/browser/browser_context.cc index 6123937cb564..b12300ed7d83 100644 --- a/brightray/browser/browser_context.cc +++ b/brightray/browser/browser_context.cc @@ -11,7 +11,6 @@ #include "brightray/browser/brightray_paths.h" #include "brightray/browser/browser_client.h" #include "brightray/browser/inspectable_web_contents_impl.h" -#include "brightray/browser/network_delegate.h" #include "brightray/browser/special_storage_policy.h" #include "brightray/browser/zoom_level_delegate.h" #include "brightray/common/application_info.h" @@ -20,7 +19,6 @@ #include "components/prefs/pref_service.h" #include "components/prefs/pref_service_factory.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/resource_context.h" #include "content/public/browser/storage_partition.h" #include "net/base/escape.h" @@ -37,26 +35,6 @@ std::string MakePartitionName(const std::string& input) { } // namespace -class BrowserContext::ResourceContext : public content::ResourceContext { - public: - ResourceContext() : getter_(nullptr) {} - - void set_url_request_context_getter(URLRequestContextGetter* getter) { - getter_ = getter; - } - - private: - net::HostResolver* GetHostResolver() override { - return getter_->host_resolver(); - } - - net::URLRequestContext* GetRequestContext() override { - return getter_->GetURLRequestContext(); - } - - URLRequestContextGetter* getter_; -}; - // static BrowserContext::BrowserContextMap BrowserContext::browser_context_map_; @@ -72,7 +50,6 @@ scoped_refptr BrowserContext::Get(const std::string& partition, BrowserContext::BrowserContext(const std::string& partition, bool in_memory) : in_memory_(in_memory), - resource_context_(new ResourceContext), storage_policy_(new SpecialStoragePolicy), weak_factory_(this) { if (!PathService::Get(DIR_USER_DATA, &path_)) { @@ -88,6 +65,8 @@ BrowserContext::BrowserContext(const std::string& partition, bool in_memory) content::BrowserContext::Initialize(this, path_); + io_handle_ = new URLRequestContextGetter::Handle(GetWeakPtr()); + browser_context_map_[PartitionKey(partition, in_memory)] = GetWeakPtr(); } @@ -95,14 +74,7 @@ BrowserContext::~BrowserContext() { DCHECK_CURRENTLY_ON(BrowserThread::UI); NotifyWillBeDestroyed(this); ShutdownStoragePartitions(); - if (BrowserThread::IsMessageLoopValid(BrowserThread::IO)) { - BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, - resource_context_.release()); - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::BindOnce(&URLRequestContextGetter::NotifyContextShutdownOnIO, - base::RetainedRef(url_request_getter_))); - } + io_handle_->ShutdownOnUIThread(); } void BrowserContext::InitPrefs() { @@ -135,17 +107,9 @@ URLRequestContextGetter* BrowserContext::GetRequestContext() { net::URLRequestContextGetter* BrowserContext::CreateRequestContext( content::ProtocolHandlerMap* protocol_handlers, content::URLRequestInterceptorScopedVector protocol_interceptors) { - DCHECK(!url_request_getter_.get()); - url_request_getter_ = new URLRequestContextGetter( - this, static_cast(BrowserClient::Get()->GetNetLog()), GetPath(), - in_memory_, BrowserThread::GetTaskRunnerForThread(BrowserThread::IO), + auto* factory = GetFactoryForMainRequestContext( protocol_handlers, std::move(protocol_interceptors)); - resource_context_->set_url_request_context_getter(url_request_getter_.get()); - return url_request_getter_.get(); -} - -std::unique_ptr BrowserContext::CreateNetworkDelegate() { - return std::make_unique(); + return io_handle_->CreateMainRequestContextGetter(factory).get(); } std::string BrowserContext::GetMediaDeviceIDSalt() { @@ -171,7 +135,7 @@ bool BrowserContext::IsOffTheRecord() const { } content::ResourceContext* BrowserContext::GetResourceContext() { - return resource_context_.get(); + return io_handle_->GetResourceContext(); } content::DownloadManagerDelegate* BrowserContext::GetDownloadManagerDelegate() { @@ -214,17 +178,19 @@ BrowserContext::CreateRequestContextForStoragePartition( bool in_memory, content::ProtocolHandlerMap* protocol_handlers, content::URLRequestInterceptorScopedVector request_interceptors) { + NOTREACHED(); return nullptr; } net::URLRequestContextGetter* BrowserContext::CreateMediaRequestContext() { - return url_request_getter_.get(); + return io_handle_->GetMediaRequestContextGetter().get(); } net::URLRequestContextGetter* BrowserContext::CreateMediaRequestContextForStoragePartition( const base::FilePath& partition_path, bool in_memory) { + NOTREACHED(); return nullptr; } diff --git a/brightray/browser/browser_context.h b/brightray/browser/browser_context.h index 8f3de784cfe2..8ceecd27e388 100644 --- a/brightray/browser/browser_context.h +++ b/brightray/browser/browser_context.h @@ -24,8 +24,7 @@ class SpecialStoragePolicy; namespace brightray { class BrowserContext : public base::RefCounted, - public content::BrowserContext, - public brightray::URLRequestContextGetter::Delegate { + public content::BrowserContext { public: // Get the BrowserContext according to its |partition| and |in_memory|, // empty pointer when be returned when there is no matching BrowserContext. @@ -67,10 +66,6 @@ class BrowserContext : public base::RefCounted, bool in_memory) override; std::string GetMediaDeviceIDSalt() override; - URLRequestContextGetter* url_request_context_getter() const { - return url_request_getter_.get(); - } - void InitPrefs(); PrefService* prefs() { return prefs_.get(); } @@ -80,15 +75,14 @@ class BrowserContext : public base::RefCounted, // Subclasses should override this to register custom preferences. virtual void RegisterPrefs(PrefRegistrySimple* pref_registry) {} - - // URLRequestContextGetter::Delegate: - std::unique_ptr CreateNetworkDelegate() override; + virtual URLRequestContextGetterFactory* GetFactoryForMainRequestContext( + content::ProtocolHandlerMap* protocol_handlers, + content::URLRequestInterceptorScopedVector request_interceptors) = 0; base::FilePath GetPath() const override; private: friend class base::RefCounted; - class ResourceContext; void RegisterInternalPrefs(PrefRegistrySimple* pref_registry); @@ -117,11 +111,10 @@ class BrowserContext : public base::RefCounted, base::FilePath path_; bool in_memory_; - std::unique_ptr resource_context_; - scoped_refptr url_request_getter_; scoped_refptr storage_policy_; std::unique_ptr prefs_; std::unique_ptr media_device_id_salt_; + URLRequestContextGetter::Handle* io_handle_; base::WeakPtrFactory weak_factory_; diff --git a/brightray/browser/inspectable_web_contents_impl.cc b/brightray/browser/inspectable_web_contents_impl.cc index 426df497c60b..6784180a7f6b 100644 --- a/brightray/browser/inspectable_web_contents_impl.cc +++ b/brightray/browser/inspectable_web_contents_impl.cc @@ -472,7 +472,7 @@ void InspectableWebContentsImpl::LoadNetworkResource( net::URLFetcher* fetcher = (net::URLFetcher::Create(gurl, net::URLFetcher::GET, this)).release(); pending_requests_[fetcher] = callback; - fetcher->SetRequestContext(browser_context->url_request_context_getter()); + fetcher->SetRequestContext(browser_context->GetRequestContext()); fetcher->SetExtraRequestHeaders(headers); fetcher->SaveResponseWithWriter( std::unique_ptr( diff --git a/brightray/browser/net/url_request_context_getter_factory.h b/brightray/browser/net/url_request_context_getter_factory.h new file mode 100644 index 000000000000..9043c6f9ec51 --- /dev/null +++ b/brightray/browser/net/url_request_context_getter_factory.h @@ -0,0 +1,29 @@ +// Copyright (c) 2018 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef BRIGHTRAY_BROWSER_NET_URL_REQUEST_CONTEXT_GETTER_FACTORY_H_ +#define BRIGHTRAY_BROWSER_NET_URL_REQUEST_CONTEXT_GETTER_FACTORY_H_ + +#include "base/macros.h" + +namespace net { +class URLRequestContext; +} // namespace net + +namespace brightray { + +class URLRequestContextGetterFactory { + public: + URLRequestContextGetterFactory() {} + virtual ~URLRequestContextGetterFactory() {} + + virtual net::URLRequestContext* Create() = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(URLRequestContextGetterFactory); +}; + +} // namespace brightray + +#endif // BRIGHTRAY_BROWSER_NET_URL_REQUEST_CONTEXT_GETTER_FACTORY_H_ diff --git a/brightray/browser/network_delegate.cc b/brightray/browser/network_delegate.cc deleted file mode 100644 index 32981cb8b8d5..000000000000 --- a/brightray/browser/network_delegate.cc +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE-CHROMIUM file. - -#include "brightray/browser/network_delegate.h" - -#include -#include - -#include "base/command_line.h" -#include "base/strings/string_split.h" -#include "net/base/load_flags.h" -#include "net/base/net_errors.h" -#include "net/url_request/url_request.h" - -namespace brightray { - -namespace { - -// Ignore the limit of 6 connections per host. -const char kIgnoreConnectionsLimit[] = "ignore-connections-limit"; - -} // namespace - -NetworkDelegate::NetworkDelegate() { - auto* command_line = base::CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch(kIgnoreConnectionsLimit)) { - std::string value = - command_line->GetSwitchValueASCII(kIgnoreConnectionsLimit); - ignore_connections_limit_domains_ = base::SplitString( - value, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); - } -} - -NetworkDelegate::~NetworkDelegate() {} - -int NetworkDelegate::OnBeforeURLRequest(net::URLRequest* request, - const net::CompletionCallback& callback, - GURL* new_url) { - for (const auto& domain : ignore_connections_limit_domains_) { - if (request->url().DomainIs(domain)) { - // Allow unlimited concurrent connections. - request->SetPriority(net::MAXIMUM_PRIORITY); - request->SetLoadFlags(request->load_flags() | net::LOAD_IGNORE_LIMITS); - break; - } - } - - return net::OK; -} - -int NetworkDelegate::OnBeforeStartTransaction( - net::URLRequest* request, - const net::CompletionCallback& callback, - net::HttpRequestHeaders* headers) { - return net::OK; -} - -void NetworkDelegate::OnStartTransaction( - net::URLRequest* request, - const net::HttpRequestHeaders& headers) {} - -void NetworkDelegate::OnBeforeSendHeaders( - net::URLRequest* request, - const net::ProxyInfo& proxy_info, - const net::ProxyRetryInfoMap& proxy_retry_info, - net::HttpRequestHeaders* headers) {} - -int NetworkDelegate::OnHeadersReceived( - net::URLRequest* request, - const net::CompletionCallback& callback, - const net::HttpResponseHeaders* original_response_headers, - scoped_refptr* override_response_headers, - GURL* allowed_unsafe_redirect_url) { - return net::OK; -} - -void NetworkDelegate::OnBeforeRedirect(net::URLRequest* request, - const GURL& new_location) {} - -void NetworkDelegate::OnResponseStarted(net::URLRequest* request, - int net_error) {} - -void NetworkDelegate::OnNetworkBytesReceived(net::URLRequest* request, - int64_t bytes_read) {} - -void NetworkDelegate::OnNetworkBytesSent(net::URLRequest* request, - int64_t bytes_sent) {} - -void NetworkDelegate::OnCompleted(net::URLRequest* request, bool started) {} - -void NetworkDelegate::OnURLRequestDestroyed(net::URLRequest* request) {} - -void NetworkDelegate::OnPACScriptError(int line_number, - const base::string16& error) {} - -NetworkDelegate::AuthRequiredResponse NetworkDelegate::OnAuthRequired( - net::URLRequest* request, - const net::AuthChallengeInfo& auth_info, - const AuthCallback& callback, - net::AuthCredentials* credentials) { - return AUTH_REQUIRED_RESPONSE_NO_ACTION; -} - -bool NetworkDelegate::OnCanGetCookies(const net::URLRequest& request, - const net::CookieList& cookie_list) { - return true; -} - -bool NetworkDelegate::OnCanSetCookie(const net::URLRequest& request, - const net::CanonicalCookie& cookie_line, - net::CookieOptions* options) { - return true; -} - -bool NetworkDelegate::OnCanAccessFile( - const net::URLRequest& request, - const base::FilePath& original_path, - const base::FilePath& absolute_path) const { - return true; -} - -bool NetworkDelegate::OnCanEnablePrivacyMode( - const GURL& url, - const GURL& first_party_for_cookies) const { - return false; -} - -bool NetworkDelegate::OnAreExperimentalCookieFeaturesEnabled() const { - return true; -} - -bool NetworkDelegate::OnCancelURLRequestWithPolicyViolatingReferrerHeader( - const net::URLRequest& request, - const GURL& target_url, - const GURL& referrer_url) const { - return false; -} - -// TODO(deepak1556) : Enable after hooking into the reporting service -// https://crbug.com/704259 -bool NetworkDelegate::OnCanQueueReportingReport( - const url::Origin& origin) const { - return false; -} - -void NetworkDelegate::OnCanSendReportingReports( - std::set origins, - base::OnceCallback)> result_callback) const {} - -bool NetworkDelegate::OnCanSetReportingClient(const url::Origin& origin, - const GURL& endpoint) const { - return false; -} - -bool NetworkDelegate::OnCanUseReportingClient(const url::Origin& origin, - const GURL& endpoint) const { - return false; -} - -} // namespace brightray diff --git a/brightray/browser/network_delegate.h b/brightray/browser/network_delegate.h deleted file mode 100644 index 77625e5c86b1..000000000000 --- a/brightray/browser/network_delegate.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE-CHROMIUM file. - -#ifndef BRIGHTRAY_BROWSER_NETWORK_DELEGATE_H_ -#define BRIGHTRAY_BROWSER_NETWORK_DELEGATE_H_ - -#include -#include -#include - -#include "net/base/network_delegate.h" - -namespace brightray { - -class NetworkDelegate : public net::NetworkDelegate { - public: - NetworkDelegate(); - ~NetworkDelegate() override; - - protected: - int OnBeforeURLRequest(net::URLRequest* request, - const net::CompletionCallback& callback, - GURL* new_url) override; - int OnBeforeStartTransaction(net::URLRequest* request, - const net::CompletionCallback& callback, - net::HttpRequestHeaders* headers) override; - void OnBeforeSendHeaders(net::URLRequest* request, - const net::ProxyInfo& proxy_info, - const net::ProxyRetryInfoMap& proxy_retry_info, - net::HttpRequestHeaders* headers) override; - void OnStartTransaction(net::URLRequest* request, - const net::HttpRequestHeaders& headers) override; - int OnHeadersReceived( - net::URLRequest* request, - const net::CompletionCallback& callback, - const net::HttpResponseHeaders* original_response_headers, - scoped_refptr* override_response_headers, - GURL* allowed_unsafe_redirect_url) override; - void OnBeforeRedirect(net::URLRequest* request, - const GURL& new_location) override; - void OnResponseStarted(net::URLRequest* request, int net_error) override; - void OnNetworkBytesReceived(net::URLRequest* request, - int64_t bytes_read) override; - void OnNetworkBytesSent(net::URLRequest* request, - int64_t bytes_sent) override; - void OnCompleted(net::URLRequest* request, bool started) override; - void OnURLRequestDestroyed(net::URLRequest* request) override; - void OnPACScriptError(int line_number, const base::string16& error) override; - AuthRequiredResponse OnAuthRequired( - net::URLRequest* request, - const net::AuthChallengeInfo& auth_info, - const AuthCallback& callback, - net::AuthCredentials* credentials) override; - bool OnCanGetCookies(const net::URLRequest& request, - const net::CookieList& cookie_list) override; - bool OnCanSetCookie(const net::URLRequest& request, - const net::CanonicalCookie& cookie_line, - net::CookieOptions* options) override; - bool OnCanAccessFile(const net::URLRequest& request, - const base::FilePath& original_path, - const base::FilePath& absolute_path) const override; - bool OnCanEnablePrivacyMode( - const GURL& url, - const GURL& first_party_for_cookies) const override; - bool OnAreExperimentalCookieFeaturesEnabled() const override; - bool OnCancelURLRequestWithPolicyViolatingReferrerHeader( - const net::URLRequest& request, - const GURL& target_url, - const GURL& referrer_url) const override; - bool OnCanQueueReportingReport(const url::Origin& origin) const override; - void OnCanSendReportingReports(std::set origins, - base::OnceCallback)> - result_callback) const override; - bool OnCanSetReportingClient(const url::Origin& origin, - const GURL& endpoint) const override; - bool OnCanUseReportingClient(const url::Origin& origin, - const GURL& endpoint) const override; - - private: - std::vector ignore_connections_limit_domains_; - - DISALLOW_COPY_AND_ASSIGN(NetworkDelegate); -}; - -} // namespace brightray - -#endif // BRIGHTRAY_BROWSER_NETWORK_DELEGATE_H_ diff --git a/brightray/browser/url_request_context_getter.cc b/brightray/browser/url_request_context_getter.cc index 68041972af79..172ec585ff85 100644 --- a/brightray/browser/url_request_context_getter.cc +++ b/brightray/browser/url_request_context_getter.cc @@ -4,381 +4,151 @@ #include "brightray/browser/url_request_context_getter.h" -#include +#include -#include "base/command_line.h" -#include "base/memory/ptr_util.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" #include "base/task_scheduler/post_task.h" -#include "brightray/browser/browser_client.h" -#include "brightray/browser/net/require_ct_delegate.h" -#include "brightray/browser/net_log.h" -#include "brightray/browser/network_delegate.h" -#include "brightray/common/switches.h" -#include "components/network_session_configurator/common/network_switches.h" +#include "brightray/browser/browser_context.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/cookie_store_factory.h" -#include "content/public/browser/devtools_network_transaction_factory.h" -#include "net/base/host_mapping_rules.h" -#include "net/cert/cert_verifier.h" -#include "net/cert/ct_known_logs.h" -#include "net/cert/ct_log_verifier.h" -#include "net/cert/ct_policy_enforcer.h" -#include "net/cert/multi_log_ct_verifier.h" -#include "net/cookies/cookie_monster.h" -#include "net/cookies/cookie_store.h" -#include "net/dns/mapped_host_resolver.h" -#include "net/http/http_auth_filter.h" -#include "net/http/http_auth_handler_factory.h" -#include "net/http/http_auth_preferences.h" -#include "net/http/http_server_properties_impl.h" -#include "net/log/net_log.h" -#include "net/proxy_resolution/dhcp_pac_file_fetcher_factory.h" -#include "net/proxy_resolution/pac_file_fetcher_impl.h" -#include "net/proxy_resolution/proxy_config.h" -#include "net/proxy_resolution/proxy_config_service.h" -#include "net/proxy_resolution/proxy_service.h" -#include "net/ssl/channel_id_service.h" -#include "net/ssl/default_channel_id_store.h" -#include "net/ssl/ssl_config_service_defaults.h" -#include "net/url_request/data_protocol_handler.h" -#include "net/url_request/file_protocol_handler.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_builder.h" -#include "net/url_request/url_request_context_storage.h" -#include "net/url_request/url_request_intercepting_job_factory.h" -#include "net/url_request/url_request_job_factory_impl.h" -#include "services/network/public/cpp/network_switches.h" -#include "storage/browser/quota/special_storage_policy.h" -#include "url/url_constants.h" using content::BrowserThread; namespace brightray { -std::string URLRequestContextGetter::Delegate::GetUserAgent() { - return base::EmptyString(); -} +class ResourceContext : public content::ResourceContext { + public: + ResourceContext() = default; + ~ResourceContext() override = default; -std::unique_ptr -URLRequestContextGetter::Delegate::CreateNetworkDelegate() { - return nullptr; -} - -std::unique_ptr -URLRequestContextGetter::Delegate::CreateURLRequestJobFactory( - content::ProtocolHandlerMap* protocol_handlers) { - std::unique_ptr job_factory( - new net::URLRequestJobFactoryImpl); - - for (auto& it : *protocol_handlers) { - job_factory->SetProtocolHandler(it.first, - base::WrapUnique(it.second.release())); + net::HostResolver* GetHostResolver() override { + if (request_context_) + return request_context_->host_resolver(); + return nullptr; } - protocol_handlers->clear(); - job_factory->SetProtocolHandler( - url::kDataScheme, base::WrapUnique(new net::DataProtocolHandler)); - job_factory->SetProtocolHandler( - url::kFileScheme, - base::WrapUnique( - new net::FileProtocolHandler(base::CreateTaskRunnerWithTraits( - {base::MayBlock(), base::TaskPriority::USER_VISIBLE, - base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})))); + net::URLRequestContext* GetRequestContext() override { + return request_context_; + } - return std::move(job_factory); + private: + friend class URLRequestContextGetter; + + net::URLRequestContext* request_context_; + + DISALLOW_COPY_AND_ASSIGN(ResourceContext); +}; + +namespace { + +// For safe shutdown, must be called before +// URLRequestContextGetter::Handle is destroyed. +void NotifyContextGettersOfShutdownOnIO( + std::unique_ptr>> + getters) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + for (auto& context_getter : *getters) + context_getter->NotifyContextShuttingDown(); } -net::HttpCache::BackendFactory* -URLRequestContextGetter::Delegate::CreateHttpCacheBackendFactory( - const base::FilePath& base_path) { - auto* command_line = base::CommandLine::ForCurrentProcess(); - int max_size = 0; - base::StringToInt(command_line->GetSwitchValueASCII(switches::kDiskCacheSize), - &max_size); +} // namespace - base::FilePath cache_path = base_path.Append(FILE_PATH_LITERAL("Cache")); - return new net::HttpCache::DefaultBackend( - net::DISK_CACHE, net::CACHE_BACKEND_DEFAULT, cache_path, max_size); +URLRequestContextGetter::Handle::Handle( + base::WeakPtr browser_context) + : resource_context_(new ResourceContext), + browser_context_(browser_context), + initialized_(false) {} + +URLRequestContextGetter::Handle::~Handle() {} + +content::ResourceContext* URLRequestContextGetter::Handle::GetResourceContext() + const { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + LazyInitialize(); + return resource_context_.get(); } -std::unique_ptr -URLRequestContextGetter::Delegate::CreateCertVerifier( - RequireCTDelegate* ct_delegate) { - return net::CertVerifier::CreateDefault(); +scoped_refptr +URLRequestContextGetter::Handle::CreateMainRequestContextGetter( + URLRequestContextGetterFactory* factory) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(!main_request_context_getter_.get()); + main_request_context_getter_ = + new URLRequestContextGetter(factory, resource_context_.get()); + return main_request_context_getter_; } -net::SSLConfigService* -URLRequestContextGetter::Delegate::CreateSSLConfigService() { - return new net::SSLConfigServiceDefaults; +scoped_refptr +URLRequestContextGetter::Handle::GetMediaRequestContextGetter() const { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + return main_request_context_getter_; } -std::vector -URLRequestContextGetter::Delegate::GetCookieableSchemes() { - return {"http", "https", "ws", "wss"}; +void URLRequestContextGetter::Handle::LazyInitialize() const { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (initialized_) + return; + + initialized_ = true; + content::BrowserContext::EnsureResourceContextInitialized( + browser_context_.get()); +} + +void URLRequestContextGetter::Handle::ShutdownOnUIThread() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + auto context_getters = + std::make_unique>>(); + if (media_request_context_getter_.get()) + context_getters->push_back(media_request_context_getter_); + if (main_request_context_getter_.get()) + context_getters->push_back(main_request_context_getter_); + if (!context_getters->empty()) { + if (BrowserThread::IsThreadInitialized(BrowserThread::IO)) { + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::BindOnce(&NotifyContextGettersOfShutdownOnIO, + std::move(context_getters))); + } + } + + if (!BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, this)) + delete this; } URLRequestContextGetter::URLRequestContextGetter( - Delegate* delegate, - NetLog* net_log, - const base::FilePath& base_path, - bool in_memory, - scoped_refptr io_task_runner, - content::ProtocolHandlerMap* protocol_handlers, - content::URLRequestInterceptorScopedVector protocol_interceptors) - : delegate_(delegate), - net_log_(net_log), - base_path_(base_path), - in_memory_(in_memory), - io_task_runner_(io_task_runner), - protocol_interceptors_(std::move(protocol_interceptors)), - job_factory_(nullptr), + URLRequestContextGetterFactory* factory, + ResourceContext* resource_context) + : factory_(factory), + resource_context_(resource_context), + url_request_context_(nullptr), context_shutting_down_(false) { // Must first be created on the UI thread. DCHECK_CURRENTLY_ON(BrowserThread::UI); - - if (protocol_handlers) - std::swap(protocol_handlers_, *protocol_handlers); - - if (delegate_) - user_agent_ = delegate_->GetUserAgent(); - - // We must create the proxy config service on the UI loop on Linux because it - // must synchronously run on the glib message loop. This will be passed to - // the URLRequestContextStorage on the IO thread in GetURLRequestContext(). - proxy_config_service_ = - net::ProxyResolutionService::CreateSystemProxyConfigService( - io_task_runner_); } -URLRequestContextGetter::~URLRequestContextGetter() {} +URLRequestContextGetter::~URLRequestContextGetter() { + DCHECK(!factory_.get()); + DCHECK(!url_request_context_); +} + +void URLRequestContextGetter::NotifyContextShuttingDown() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); -void URLRequestContextGetter::NotifyContextShutdownOnIO() { context_shutting_down_ = true; - cookie_change_sub_.reset(); - http_network_session_.reset(); - http_auth_preferences_.reset(); - host_mapping_rules_.reset(); - url_request_context_.reset(); - storage_.reset(); - ct_delegate_.reset(); + url_request_context_ = nullptr; net::URLRequestContextGetter::NotifyContextShuttingDown(); -} - -void URLRequestContextGetter::OnCookieChanged( - const net::CanonicalCookie& cookie, - net::CookieChangeCause cause) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - - if (!delegate_ || context_shutting_down_) - return; - - content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, - base::BindOnce(&Delegate::NotifyCookieChange, base::Unretained(delegate_), - cookie, !(cause == net::CookieChangeCause::INSERTED), - cause)); -} - -net::HostResolver* URLRequestContextGetter::host_resolver() { - return url_request_context_->host_resolver(); + factory_.reset(); } net::URLRequestContext* URLRequestContextGetter::GetURLRequestContext() { DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (context_shutting_down_) - return nullptr; - - if (!url_request_context_.get()) { - ct_delegate_.reset(new RequireCTDelegate); - auto& command_line = *base::CommandLine::ForCurrentProcess(); - url_request_context_.reset(new net::URLRequestContext); - - // --log-net-log - if (net_log_) { - net_log_->StartLogging(); - url_request_context_->set_net_log(net_log_); + if (factory_.get() && !url_request_context_ && !context_shutting_down_) { + url_request_context_ = factory_->Create(); + if (resource_context_) { + resource_context_->request_context_ = url_request_context_; } - - storage_.reset( - new net::URLRequestContextStorage(url_request_context_.get())); - - storage_->set_network_delegate(delegate_->CreateNetworkDelegate()); - - auto cookie_path = in_memory_ - ? base::FilePath() - : base_path_.Append(FILE_PATH_LITERAL("Cookies")); - std::unique_ptr cookie_store = - content::CreateCookieStore(content::CookieStoreConfig( - cookie_path, false, false, nullptr)); - storage_->set_cookie_store(std::move(cookie_store)); - - // Set custom schemes that can accept cookies. - net::CookieMonster* cookie_monster = - static_cast(url_request_context_->cookie_store()); - cookie_monster->SetCookieableSchemes(delegate_->GetCookieableSchemes()); - // Cookie store will outlive notifier by order of declaration - // in the header. - cookie_change_sub_ = - url_request_context_->cookie_store() - ->GetChangeDispatcher() - .AddCallbackForAllChanges( - base::Bind(&URLRequestContextGetter::OnCookieChanged, this)); - - storage_->set_channel_id_service(std::make_unique( - new net::DefaultChannelIDStore(nullptr))); - - storage_->set_http_user_agent_settings( - base::WrapUnique(new net::StaticHttpUserAgentSettings( - net::HttpUtil::GenerateAcceptLanguageHeader( - BrowserClient::Get()->GetApplicationLocale()), - user_agent_))); - - std::unique_ptr host_resolver( - net::HostResolver::CreateDefaultResolver(nullptr)); - - // --host-resolver-rules - if (command_line.HasSwitch(network::switches::kHostResolverRules)) { - std::unique_ptr remapped_resolver( - new net::MappedHostResolver(std::move(host_resolver))); - remapped_resolver->SetRulesFromString(command_line.GetSwitchValueASCII( - network::switches::kHostResolverRules)); - host_resolver = std::move(remapped_resolver); - } - - // --proxy-server - if (command_line.HasSwitch(switches::kNoProxyServer)) { - storage_->set_proxy_resolution_service( - net::ProxyResolutionService::CreateDirect()); - } else if (command_line.HasSwitch(switches::kProxyServer)) { - net::ProxyConfig proxy_config; - proxy_config.proxy_rules().ParseFromString( - command_line.GetSwitchValueASCII(switches::kProxyServer)); - proxy_config.proxy_rules().bypass_rules.ParseFromString( - command_line.GetSwitchValueASCII(switches::kProxyBypassList)); - storage_->set_proxy_resolution_service( - net::ProxyResolutionService::CreateFixed(proxy_config)); - } else if (command_line.HasSwitch(switches::kProxyPacUrl)) { - auto proxy_config = net::ProxyConfig::CreateFromCustomPacURL( - GURL(command_line.GetSwitchValueASCII(switches::kProxyPacUrl))); - proxy_config.set_pac_mandatory(true); - storage_->set_proxy_resolution_service( - net::ProxyResolutionService::CreateFixed(proxy_config)); - } else { - storage_->set_proxy_resolution_service( - net::ProxyResolutionService::CreateUsingSystemProxyResolver( - std::move(proxy_config_service_), net_log_)); - } - - std::vector schemes; - schemes.push_back(std::string("basic")); - schemes.push_back(std::string("digest")); - schemes.push_back(std::string("ntlm")); - schemes.push_back(std::string("negotiate")); -#if defined(OS_POSIX) - http_auth_preferences_.reset( - new net::HttpAuthPreferences(schemes, std::string())); -#else - http_auth_preferences_.reset(new net::HttpAuthPreferences(schemes)); -#endif - - // --auth-server-whitelist - if (command_line.HasSwitch(switches::kAuthServerWhitelist)) { - http_auth_preferences_->SetServerWhitelist( - command_line.GetSwitchValueASCII(switches::kAuthServerWhitelist)); - } - - // --auth-negotiate-delegate-whitelist - if (command_line.HasSwitch(switches::kAuthNegotiateDelegateWhitelist)) { - http_auth_preferences_->SetDelegateWhitelist( - command_line.GetSwitchValueASCII( - switches::kAuthNegotiateDelegateWhitelist)); - } - - auto auth_handler_factory = net::HttpAuthHandlerRegistryFactory::Create( - http_auth_preferences_.get(), host_resolver.get()); - - std::unique_ptr transport_security_state = - base::WrapUnique(new net::TransportSecurityState); - transport_security_state->SetRequireCTDelegate(ct_delegate_.get()); - storage_->set_transport_security_state(std::move(transport_security_state)); - storage_->set_cert_verifier( - delegate_->CreateCertVerifier(ct_delegate_.get())); - storage_->set_ssl_config_service(delegate_->CreateSSLConfigService()); - storage_->set_http_auth_handler_factory(std::move(auth_handler_factory)); - std::unique_ptr server_properties( - new net::HttpServerPropertiesImpl); - storage_->set_http_server_properties(std::move(server_properties)); - - std::unique_ptr ct_verifier = - std::make_unique(); - ct_verifier->AddLogs(net::ct::CreateLogVerifiersForKnownLogs()); - storage_->set_cert_transparency_verifier(std::move(ct_verifier)); - storage_->set_ct_policy_enforcer(std::make_unique()); - - net::HttpNetworkSession::Params network_session_params; - network_session_params.ignore_certificate_errors = false; - - // --disable-http2 - if (command_line.HasSwitch(switches::kDisableHttp2)) - network_session_params.enable_http2 = false; - - // --ignore-certificate-errors - if (command_line.HasSwitch(::switches::kIgnoreCertificateErrors)) - network_session_params.ignore_certificate_errors = true; - - // --host-rules - if (command_line.HasSwitch(switches::kHostRules)) { - host_mapping_rules_.reset(new net::HostMappingRules); - host_mapping_rules_->SetRulesFromString( - command_line.GetSwitchValueASCII(switches::kHostRules)); - network_session_params.host_mapping_rules = *host_mapping_rules_.get(); - } - - // Give |storage_| ownership at the end in case it's |mapped_host_resolver|. - storage_->set_host_resolver(std::move(host_resolver)); - - net::HttpNetworkSession::Context network_session_context; - net::URLRequestContextBuilder::SetHttpNetworkSessionComponents( - url_request_context_.get(), &network_session_context); - http_network_session_.reset(new net::HttpNetworkSession( - network_session_params, network_session_context)); - - std::unique_ptr backend; - if (in_memory_) { - backend = net::HttpCache::DefaultBackend::InMemory(0); - } else { - backend.reset(delegate_->CreateHttpCacheBackendFactory(base_path_)); - } - - storage_->set_http_transaction_factory(std::make_unique( - content::CreateDevToolsNetworkTransactionFactory( - http_network_session_.get()), - std::move(backend), false)); - - std::unique_ptr job_factory = - delegate_->CreateURLRequestJobFactory(&protocol_handlers_); - job_factory_ = job_factory.get(); - - // Set up interceptors in the reverse order. - std::unique_ptr top_job_factory = - std::move(job_factory); - if (!protocol_interceptors_.empty()) { - for (auto it = protocol_interceptors_.rbegin(); - it != protocol_interceptors_.rend(); ++it) { - top_job_factory.reset(new net::URLRequestInterceptingJobFactory( - std::move(top_job_factory), std::move(*it))); - } - protocol_interceptors_.clear(); - } - - storage_->set_job_factory(std::move(top_job_factory)); } - return url_request_context_.get(); + return url_request_context_; } scoped_refptr diff --git a/brightray/browser/url_request_context_getter.h b/brightray/browser/url_request_context_getter.h index b990d479a06c..a3d37cada1e9 100644 --- a/brightray/browser/url_request_context_getter.h +++ b/brightray/browser/url_request_context_getter.h @@ -5,16 +5,8 @@ #ifndef BRIGHTRAY_BROWSER_URL_REQUEST_CONTEXT_GETTER_H_ #define BRIGHTRAY_BROWSER_URL_REQUEST_CONTEXT_GETTER_H_ -#include -#include - -#include "base/files/file_path.h" -#include "content/public/browser/browser_context.h" -#include "content/public/browser/content_browser_client.h" -#include "net/cookies/cookie_change_dispatcher.h" -#include "net/http/http_cache.h" -#include "net/http/transport_security_state.h" -#include "net/http/url_security_manager.h" +#include "brightray/browser/net/url_request_context_getter_factory.h" +#include "content/public/browser/resource_context.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_getter.h" @@ -22,99 +14,64 @@ #include "base/debug/leak_tracker.h" #endif -namespace base { -class MessageLoop; -} - -namespace net { -class HostMappingRules; -class HostResolver; -class HttpAuthPreferences; -class NetworkDelegate; -class ProxyConfigService; -class URLRequestContextStorage; -class URLRequestJobFactory; -} // namespace net - namespace brightray { -class RequireCTDelegate; -class NetLog; +class BrowserContext; +class ResourceContext; class URLRequestContextGetter : public net::URLRequestContextGetter { public: - class Delegate { - public: - Delegate() {} - virtual ~Delegate() {} - - virtual std::unique_ptr CreateNetworkDelegate(); - virtual std::string GetUserAgent(); - virtual std::unique_ptr - CreateURLRequestJobFactory(content::ProtocolHandlerMap* protocol_handlers); - virtual net::HttpCache::BackendFactory* CreateHttpCacheBackendFactory( - const base::FilePath& base_path); - virtual std::unique_ptr CreateCertVerifier( - RequireCTDelegate* ct_delegate); - virtual net::SSLConfigService* CreateSSLConfigService(); - virtual std::vector GetCookieableSchemes(); - virtual void NotifyCookieChange(const net::CanonicalCookie& cookie, - bool removed, - net::CookieChangeCause cause) {} - }; - - URLRequestContextGetter( - Delegate* delegate, - NetLog* net_log, - const base::FilePath& base_path, - bool in_memory, - scoped_refptr io_task_runner, - content::ProtocolHandlerMap* protocol_handlers, - content::URLRequestInterceptorScopedVector protocol_interceptors); - - // net::CookieChangeDispatcher::CookieChangedCallback implementation. - void OnCookieChanged(const net::CanonicalCookie& cookie, - net::CookieChangeCause cause); + URLRequestContextGetter(URLRequestContextGetterFactory* factory, + ResourceContext* resource_context); // net::URLRequestContextGetter: net::URLRequestContext* GetURLRequestContext() override; scoped_refptr GetNetworkTaskRunner() const override; - net::HostResolver* host_resolver(); - net::URLRequestJobFactory* job_factory() const { return job_factory_; } - - void NotifyContextShutdownOnIO(); + // Discard reference to URLRequestContext and inform observers to + // shutdown. Must be called only on IO thread. + void NotifyContextShuttingDown(); private: + friend class BrowserContext; + + // Responsible for destroying URLRequestContextGetter + // on the IO thread. + class Handle { + public: + explicit Handle(base::WeakPtr browser_context); + ~Handle(); + + scoped_refptr CreateMainRequestContextGetter( + URLRequestContextGetterFactory* factory); + content::ResourceContext* GetResourceContext() const; + scoped_refptr GetMediaRequestContextGetter() const; + + void ShutdownOnUIThread(); + + private: + void LazyInitialize() const; + + scoped_refptr main_request_context_getter_; + scoped_refptr media_request_context_getter_; + std::unique_ptr resource_context_; + base::WeakPtr browser_context_; + mutable bool initialized_; + + DISALLOW_COPY_AND_ASSIGN(Handle); + }; + ~URLRequestContextGetter() override; - Delegate* delegate_; - - NetLog* net_log_; - base::FilePath base_path_; - bool in_memory_; - scoped_refptr io_task_runner_; - - std::string user_agent_; - #if DCHECK_IS_ON() base::debug::LeakTracker leak_tracker_; #endif - std::unique_ptr ct_delegate_; - std::unique_ptr proxy_config_service_; - std::unique_ptr storage_; - std::unique_ptr url_request_context_; - std::unique_ptr host_mapping_rules_; - std::unique_ptr http_auth_preferences_; - std::unique_ptr http_network_session_; - std::unique_ptr cookie_change_sub_; - content::ProtocolHandlerMap protocol_handlers_; - content::URLRequestInterceptorScopedVector protocol_interceptors_; - - net::URLRequestJobFactory* job_factory_; // weak ref + std::unique_ptr factory_; + ResourceContext* resource_context_; + net::URLRequestContext* url_request_context_; bool context_shutting_down_; DISALLOW_COPY_AND_ASSIGN(URLRequestContextGetter); diff --git a/brightray/common/switches.cc b/brightray/common/switches.cc deleted file mode 100644 index 9985f9f15e0b..000000000000 --- a/brightray/common/switches.cc +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2016 GitHub, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#include "brightray/common/switches.h" - -namespace brightray { - -namespace switches { - -// Comma-separated list of rules that control how hostnames are mapped. -// -// For example: -// "MAP * 127.0.0.1" --> Forces all hostnames to be mapped to 127.0.0.1 -// "MAP *.google.com proxy" --> Forces all google.com subdomains to be -// resolved to "proxy". -// "MAP test.com [::1]:77 --> Forces "test.com" to resolve to IPv6 loopback. -// Will also force the port of the resulting -// socket address to be 77. -// "MAP * baz, EXCLUDE www.google.com" --> Remaps everything to "baz", -// except for "www.google.com". -// -// These mappings apply to the endpoint host in a net::URLRequest (the TCP -// connect and host resolver in a direct connection, and the CONNECT in an http -// proxy connection, and the endpoint host in a SOCKS proxy connection). -const char kHostRules[] = "host-rules"; - -// Don't use a proxy server, always make direct connections. Overrides any -// other proxy server flags that are passed. -const char kNoProxyServer[] = "no-proxy-server"; - -// Uses a specified proxy server, overrides system settings. This switch only -// affects HTTP and HTTPS requests. -const char kProxyServer[] = "proxy-server"; - -// Bypass specified proxy for the given semi-colon-separated list of hosts. This -// flag has an effect only when --proxy-server is set. -const char kProxyBypassList[] = "proxy-bypass-list"; - -// Uses the pac script at the given URL. -const char kProxyPacUrl[] = "proxy-pac-url"; - -// Disable HTTP/2 and SPDY/3.1 protocols. -const char kDisableHttp2[] = "disable-http2"; - -// Whitelist containing servers for which Integrated Authentication is enabled. -const char kAuthServerWhitelist[] = "auth-server-whitelist"; - -// Whitelist containing servers for which Kerberos delegation is allowed. -const char kAuthNegotiateDelegateWhitelist[] = - "auth-negotiate-delegate-whitelist"; - -// Forces the maximum disk space to be used by the disk cache, in bytes. -const char kDiskCacheSize[] = "disk-cache-size"; - -} // namespace switches - -} // namespace brightray diff --git a/brightray/common/switches.h b/brightray/common/switches.h deleted file mode 100644 index 6262f5f962ca..000000000000 --- a/brightray/common/switches.h +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) 2016 GitHub, Inc. -// Use of this source code is governed by the MIT license that can be -// found in the LICENSE file. - -#ifndef BRIGHTRAY_COMMON_SWITCHES_H_ -#define BRIGHTRAY_COMMON_SWITCHES_H_ - -namespace brightray { - -namespace switches { - -extern const char kHostRules[]; -extern const char kNoProxyServer[]; -extern const char kProxyServer[]; -extern const char kProxyBypassList[]; -extern const char kProxyPacUrl[]; -extern const char kDisableHttp2[]; -extern const char kAuthServerWhitelist[]; -extern const char kAuthNegotiateDelegateWhitelist[]; -extern const char kDiskCacheSize[]; - -} // namespace switches - -} // namespace brightray - -#endif // BRIGHTRAY_COMMON_SWITCHES_H_ diff --git a/brightray/filenames.gypi b/brightray/filenames.gypi index 0d79b5faf74f..47fb5e8accd7 100644 --- a/brightray/filenames.gypi +++ b/brightray/filenames.gypi @@ -49,10 +49,9 @@ 'browser/media/media_stream_devices_controller.h', 'browser/net/require_ct_delegate.cc', 'browser/net/require_ct_delegate.h', + 'browser/net/url_request_context_getter_factory.h', 'browser/net_log.cc', 'browser/net_log.h', - 'browser/network_delegate.cc', - 'browser/network_delegate.h', 'browser/notification_delegate.h', 'browser/notification_presenter.cc', 'browser/notification_presenter.h', @@ -104,8 +103,6 @@ 'common/main_delegate.cc', 'common/main_delegate.h', 'common/main_delegate_mac.mm', - 'common/switches.cc', - 'common/switches.h', 'common/platform_util_linux.cc', 'common/platform_util.h', ], diff --git a/filenames.gypi b/filenames.gypi index 2215cb4f6d89..78af9908b3a4 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -288,10 +288,10 @@ 'atom/browser/net/atom_url_request.h', 'atom/browser/net/atom_url_request_job_factory.cc', 'atom/browser/net/atom_url_request_job_factory.h', - 'atom/browser/net/http_protocol_handler.cc', - 'atom/browser/net/http_protocol_handler.h', 'atom/browser/net/js_asker.cc', 'atom/browser/net/js_asker.h', + 'atom/browser/net/request_context_factory.cc', + 'atom/browser/net/request_context_factory.h', 'atom/browser/net/url_request_about_job.cc', 'atom/browser/net/url_request_about_job.h', 'atom/browser/net/url_request_async_asar_job.cc',