From 6c20c6e66875ad889a9611a64f95346fc3c94367 Mon Sep 17 00:00:00 2001 From: Robo Date: Tue, 26 Mar 2019 06:40:48 +0530 Subject: [PATCH] refactor: Enable network service (Part 1) (#17431) * Convert InspectableWebContentsImpl::LoadNetworkResource to SimpleURLLoader https://bugs.chromium.org/p/chromium/issues/detail?id=721408 * Plumb creation of network context with the service --- atom/browser/atom_browser_client.cc | 22 ++- atom/browser/atom_browser_client.h | 1 + atom/browser/atom_browser_context.cc | 59 ++++-- atom/browser/atom_browser_context.h | 2 + atom/browser/browser_process_impl.cc | 17 +- atom/browser/browser_process_impl.h | 1 - atom/browser/io_thread.cc | 43 +++-- atom/browser/net/network_context_service.cc | 94 +++++++++ atom/browser/net/network_context_service.h | 41 ++++ .../net/network_context_service_factory.cc | 34 ++++ .../net/network_context_service_factory.h | 48 +++++ .../net/system_network_context_manager.cc | 42 +++- .../net/system_network_context_manager.h | 16 +- .../browser/net/url_request_context_getter.cc | 17 +- atom/browser/net/url_request_context_getter.h | 5 +- .../ui/inspectable_web_contents_impl.cc | 180 ++++++++---------- .../ui/inspectable_web_contents_impl.h | 15 +- filenames.gni | 4 + 18 files changed, 469 insertions(+), 172 deletions(-) create mode 100644 atom/browser/net/network_context_service.cc create mode 100644 atom/browser/net/network_context_service.h create mode 100644 atom/browser/net/network_context_service_factory.cc create mode 100644 atom/browser/net/network_context_service_factory.h diff --git a/atom/browser/atom_browser_client.cc b/atom/browser/atom_browser_client.cc index e1f5f28a08..64c1e522d0 100644 --- a/atom/browser/atom_browser_client.cc +++ b/atom/browser/atom_browser_client.cc @@ -26,6 +26,8 @@ #include "atom/browser/io_thread.h" #include "atom/browser/media/media_capture_devices_dispatcher.h" #include "atom/browser/native_window.h" +#include "atom/browser/net/network_context_service.h" +#include "atom/browser/net/network_context_service_factory.h" #include "atom/browser/notifications/notification_presenter.h" #include "atom/browser/notifications/platform_notification_service.h" #include "atom/browser/session_preferences.h" @@ -72,6 +74,7 @@ #include "ppapi/host/ppapi_host.h" #include "printing/buildflags/buildflags.h" #include "services/device/public/cpp/geolocation/location_provider.h" +#include "services/network/public/cpp/features.h" #include "services/network/public/cpp/resource_request_body.h" #include "services/proxy_resolver/public/mojom/proxy_resolver.mojom.h" #include "ui/base/l10n/l10n_util.h" @@ -686,7 +689,20 @@ network::mojom::NetworkContextPtr AtomBrowserClient::CreateNetworkContext( const base::FilePath& /*relative_partition_path*/) { if (!browser_context) return nullptr; - return static_cast(browser_context)->GetNetworkContext(); + + if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { + return NetworkContextServiceFactory::GetForContext(browser_context) + ->CreateNetworkContext(); + } else { + return static_cast(browser_context) + ->GetNetworkContext(); + } +} + +network::mojom::NetworkContext* AtomBrowserClient::GetSystemNetworkContext() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(g_browser_process->system_network_context_manager()); + return g_browser_process->system_network_context_manager()->GetContext(); } void AtomBrowserClient::RegisterOutOfProcessServices( @@ -872,8 +888,10 @@ AtomBrowserClient::GetSystemSharedURLLoaderFactory() { void AtomBrowserClient::OnNetworkServiceCreated( network::mojom::NetworkService* network_service) { - if (!g_browser_process) + if (!g_browser_process || + !base::FeatureList::IsEnabled(network::features::kNetworkService)) return; + g_browser_process->system_network_context_manager()->OnNetworkServiceCreated( network_service); } diff --git a/atom/browser/atom_browser_client.h b/atom/browser/atom_browser_client.h index 65a0aba20d..0adafc31ed 100644 --- a/atom/browser/atom_browser_client.h +++ b/atom/browser/atom_browser_client.h @@ -137,6 +137,7 @@ class AtomBrowserClient : public content::ContentBrowserClient, content::BrowserContext* browser_context, bool in_memory, const base::FilePath& relative_partition_path) override; + network::mojom::NetworkContext* GetSystemNetworkContext() override; void RegisterOutOfProcessServices(OutOfProcessServiceMap* services) override; base::Optional GetServiceManifestOverlay( base::StringPiece name) override; diff --git a/atom/browser/atom_browser_context.cc b/atom/browser/atom_browser_context.cc index 99c274ecd7..186cdaf5c4 100644 --- a/atom/browser/atom_browser_context.cc +++ b/atom/browser/atom_browser_context.cc @@ -40,6 +40,7 @@ #include "content/public/browser/browser_thread.h" #include "content/public/browser/storage_partition.h" #include "net/base/escape.h" +#include "services/network/public/cpp/features.h" using content::BrowserThread; @@ -92,8 +93,12 @@ AtomBrowserContext::AtomBrowserContext(const std::string& partition, // Initialize Pref Registry. InitPrefs(); - proxy_config_monitor_ = std::make_unique(prefs_.get()); - io_handle_ = new URLRequestContextGetter::Handle(weak_factory_.GetWeakPtr()); + if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) { + proxy_config_monitor_ = std::make_unique(prefs_.get()); + io_handle_ = + new URLRequestContextGetter::Handle(weak_factory_.GetWeakPtr()); + } + cookie_change_notifier_ = std::make_unique(this); BrowserContextDependencyManager::GetInstance()->MarkBrowserContextLive(this); @@ -103,7 +108,13 @@ AtomBrowserContext::~AtomBrowserContext() { DCHECK_CURRENTLY_ON(BrowserThread::UI); NotifyWillBeDestroyed(this); ShutdownStoragePartitions(); - io_handle_->ShutdownOnUIThread(); + + BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, + std::move(resource_context_)); + + if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) + io_handle_->ShutdownOnUIThread(); + // Notify any keyed services of browser context destruction. BrowserContextDependencyManager::GetInstance()->DestroyBrowserContextServices( this); @@ -145,22 +156,42 @@ void AtomBrowserContext::SetUserAgent(const std::string& user_agent) { net::URLRequestContextGetter* AtomBrowserContext::CreateRequestContext( content::ProtocolHandlerMap* protocol_handlers, content::URLRequestInterceptorScopedVector protocol_interceptors) { - return io_handle_ - ->CreateMainRequestContextGetter(protocol_handlers, - std::move(protocol_interceptors)) - .get(); + if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) { + return io_handle_ + ->CreateMainRequestContextGetter(protocol_handlers, + std::move(protocol_interceptors)) + .get(); + } else { + NOTREACHED(); + return nullptr; + } } net::URLRequestContextGetter* AtomBrowserContext::CreateMediaRequestContext() { - return io_handle_->GetMainRequestContextGetter().get(); + if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) { + return io_handle_->GetMainRequestContextGetter().get(); + } else { + NOTREACHED(); + return nullptr; + } } net::URLRequestContextGetter* AtomBrowserContext::GetRequestContext() { - return GetDefaultStoragePartition(this)->GetURLRequestContext(); + if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) { + return GetDefaultStoragePartition(this)->GetURLRequestContext(); + } else { + NOTREACHED(); + return nullptr; + } } network::mojom::NetworkContextPtr AtomBrowserContext::GetNetworkContext() { - return io_handle_->GetNetworkContext(); + if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) { + return io_handle_->GetNetworkContext(); + } else { + NOTREACHED(); + return nullptr; + } } base::FilePath AtomBrowserContext::GetPath() const { @@ -180,7 +211,13 @@ int AtomBrowserContext::GetMaxCacheSize() const { } content::ResourceContext* AtomBrowserContext::GetResourceContext() { - return io_handle_->GetResourceContext(); + if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) { + return io_handle_->GetResourceContext(); + } else { + if (!resource_context_) + resource_context_.reset(new content::ResourceContext); + return resource_context_.get(); + } } std::string AtomBrowserContext::GetMediaDeviceIDSalt() { diff --git a/atom/browser/atom_browser_context.h b/atom/browser/atom_browser_context.h index 0a370377d3..9376640850 100644 --- a/atom/browser/atom_browser_context.h +++ b/atom/browser/atom_browser_context.h @@ -16,6 +16,7 @@ #include "base/memory/weak_ptr.h" #include "chrome/browser/net/proxy_config_monitor.h" #include "content/public/browser/browser_context.h" +#include "content/public/browser/resource_context.h" class PrefRegistrySimple; class PrefService; @@ -148,6 +149,7 @@ class AtomBrowserContext URLRequestContextGetter::Handle* io_handle_; ValueMapPrefStore* in_memory_pref_store_; + std::unique_ptr resource_context_; std::unique_ptr cookie_change_notifier_; std::unique_ptr prefs_; std::unique_ptr download_manager_delegate_; diff --git a/atom/browser/browser_process_impl.cc b/atom/browser/browser_process_impl.cc index 56fb4df360..092eb6b5c2 100644 --- a/atom/browser/browser_process_impl.cc +++ b/atom/browser/browser_process_impl.cc @@ -95,8 +95,8 @@ void BrowserProcessImpl::PreCreateThreads( // Must be created before the IOThread. // Once IOThread class is no longer needed, // this can be created on first use. - system_network_context_manager_ = - std::make_unique(); + if (!SystemNetworkContextManager::GetInstance()) + SystemNetworkContextManager::CreateInstance(local_state_.get()); net_log_ = std::make_unique(); // start net log trace if --log-net-log is passed in the command line. @@ -110,11 +110,11 @@ void BrowserProcessImpl::PreCreateThreads( } } // Initialize net log file exporter. - system_network_context_manager_->GetNetExportFileWriter()->Initialize(); + system_network_context_manager()->GetNetExportFileWriter()->Initialize(); // Manage global state of net and other IO thread related. io_thread_ = std::make_unique( - net_log_.get(), system_network_context_manager_.get()); + net_log_.get(), SystemNetworkContextManager::GetInstance()); } void BrowserProcessImpl::PostDestroyThreads() { @@ -122,8 +122,11 @@ void BrowserProcessImpl::PostDestroyThreads() { } void BrowserProcessImpl::PostMainMessageLoopRun() { + if (local_state_) + local_state_->CommitPendingWrite(); + // This expects to be destroyed before the task scheduler is torn down. - system_network_context_manager_.reset(); + SystemNetworkContextManager::DeleteInstance(); } bool BrowserProcessImpl::IsShuttingDown() { @@ -189,8 +192,8 @@ IOThread* BrowserProcessImpl::io_thread() { SystemNetworkContextManager* BrowserProcessImpl::system_network_context_manager() { - DCHECK(system_network_context_manager_.get()); - return system_network_context_manager_.get(); + DCHECK(SystemNetworkContextManager::GetInstance()); + return SystemNetworkContextManager::GetInstance(); } network::NetworkQualityTracker* BrowserProcessImpl::network_quality_tracker() { diff --git a/atom/browser/browser_process_impl.h b/atom/browser/browser_process_impl.h index d24e7c79e4..f3e4018b0e 100644 --- a/atom/browser/browser_process_impl.h +++ b/atom/browser/browser_process_impl.h @@ -122,7 +122,6 @@ class BrowserProcessImpl : public BrowserProcess { std::unique_ptr local_state_; std::unique_ptr io_thread_; std::unique_ptr net_log_; - std::unique_ptr system_network_context_manager_; std::string locale_; DISALLOW_COPY_AND_ASSIGN(BrowserProcessImpl); diff --git a/atom/browser/io_thread.cc b/atom/browser/io_thread.cc index 72a6da8882..45fe3db3e4 100644 --- a/atom/browser/io_thread.cc +++ b/atom/browser/io_thread.cc @@ -16,6 +16,7 @@ #include "net/proxy_resolution/proxy_resolution_service.h" #include "net/url_request/url_request_context.h" #include "services/network/network_service.h" +#include "services/network/public/cpp/features.h" #include "services/network/url_request_context_builder_mojo.h" using content::BrowserThread; @@ -35,31 +36,35 @@ IOThread::~IOThread() { } void IOThread::Init() { - std::unique_ptr builder = - std::make_unique(); + if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) { + std::unique_ptr builder = + std::make_unique(); - auto cert_verifier = std::make_unique( - std::make_unique( - net::CertVerifyProc::CreateDefault())); - builder->SetCertVerifier(std::move(cert_verifier)); + auto cert_verifier = std::make_unique( + std::make_unique( + net::CertVerifyProc::CreateDefault())); + builder->SetCertVerifier(std::move(cert_verifier)); - // Create the network service, so that shared host resolver - // gets created which is required to set the auth preferences below. - network::NetworkService* network_service = content::GetNetworkServiceImpl(); - network_service->SetUpHttpAuth(std::move(http_auth_static_params_)); - network_service->ConfigureHttpAuthPrefs(std::move(http_auth_dynamic_params_)); + // Create the network service, so that shared host resolver + // gets created which is required to set the auth preferences below. + network::NetworkService* network_service = content::GetNetworkServiceImpl(); + network_service->SetUpHttpAuth(std::move(http_auth_static_params_)); + network_service->ConfigureHttpAuthPrefs( + std::move(http_auth_dynamic_params_)); - system_network_context_ = - network_service - ->CreateNetworkContextWithBuilder(std::move(network_context_request_), - std::move(network_context_params_), - std::move(builder), - &system_request_context_) - .release(); + system_network_context_ = + network_service + ->CreateNetworkContextWithBuilder( + std::move(network_context_request_), + std::move(network_context_params_), std::move(builder), + &system_request_context_) + .release(); + } } void IOThread::CleanUp() { - system_request_context_->proxy_resolution_service()->OnShutdown(); + if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) + system_request_context_->proxy_resolution_service()->OnShutdown(); if (net_log_) net_log_->ShutDownBeforeTaskScheduler(); diff --git a/atom/browser/net/network_context_service.cc b/atom/browser/net/network_context_service.cc new file mode 100644 index 0000000000..d070828a1b --- /dev/null +++ b/atom/browser/net/network_context_service.cc @@ -0,0 +1,94 @@ +// Copyright (c) 2019 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/network_context_service.h" + +#include "atom/browser/atom_browser_client.h" +#include "atom/browser/browser_process_impl.h" +#include "atom/browser/net/system_network_context_manager.h" +#include "chrome/common/chrome_constants.h" +#include "content/public/browser/network_service_instance.h" +#include "services/network/network_service.h" + +namespace atom { + +NetworkContextService::NetworkContextService(content::BrowserContext* context) + : browser_context_(static_cast(context)), + proxy_config_monitor_(browser_context_->prefs()) {} + +NetworkContextService::~NetworkContextService() = default; + +network::mojom::NetworkContextPtr +NetworkContextService::CreateNetworkContext() { + network::mojom::NetworkContextPtr network_context; + + content::GetNetworkService()->CreateNetworkContext( + MakeRequest(&network_context), + CreateNetworkContextParams(browser_context_->IsOffTheRecord(), + browser_context_->GetPath())); + + return network_context; +} + +network::mojom::NetworkContextParamsPtr +NetworkContextService::CreateNetworkContextParams(bool in_memory, + const base::FilePath& path) { + network::mojom::NetworkContextParamsPtr network_context_params = + g_browser_process->system_network_context_manager() + ->CreateDefaultNetworkContextParams(); + + network_context_params->user_agent = browser_context_->GetUserAgent(); + + network_context_params->accept_language = + net::HttpUtil::GenerateAcceptLanguageHeader( + AtomBrowserClient::Get()->GetApplicationLocale()); + + // Enable the HTTP cache. + network_context_params->http_cache_enabled = + browser_context_->CanUseHttpCache(); + + network_context_params->cookie_manager_params = + network::mojom::CookieManagerParams::New(); + + // Configure on-disk storage for persistent sessions. + if (!in_memory) { + // Configure the HTTP cache path and size. + network_context_params->http_cache_path = + path.Append(chrome::kCacheDirname); + network_context_params->http_cache_max_size = + browser_context_->GetMaxCacheSize(); + + // Currently this just contains HttpServerProperties + network_context_params->http_server_properties_path = + path.Append(chrome::kNetworkPersistentStateFilename); + + // Configure persistent cookie path. + network_context_params->cookie_path = path.Append(chrome::kCookieFilename); + + network_context_params->restore_old_session_cookies = false; + network_context_params->persist_session_cookies = false; + + // TODO(deepak1556): Matches the existing behavior https://git.io/fxHMl, + // enable encryption as a followup. + network_context_params->enable_encrypted_cookies = false; + + network_context_params->transport_security_persister_path = path; + } + +#if !BUILDFLAG(DISABLE_FTP_SUPPORT) + network_context_params->enable_ftp_url_support = true; +#endif // !BUILDFLAG(DISABLE_FTP_SUPPORT) + + // Needed for PAC scripts that use data URLs. + network_context_params->enable_data_url_support = true; + + proxy_config_monitor_.AddToNetworkContextParams(network_context_params.get()); + + BrowserProcessImpl::ApplyProxyModeFromCommandLine( + browser_context_->in_memory_pref_store()); + + return network_context_params; +} + +} // namespace atom diff --git a/atom/browser/net/network_context_service.h b/atom/browser/net/network_context_service.h new file mode 100644 index 0000000000..6dd2c4922b --- /dev/null +++ b/atom/browser/net/network_context_service.h @@ -0,0 +1,41 @@ +// Copyright (c) 2019 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_NETWORK_CONTEXT_SERVICE_H_ +#define ATOM_BROWSER_NET_NETWORK_CONTEXT_SERVICE_H_ + +#include "atom/browser/atom_browser_context.h" +#include "base/files/file_path.h" +#include "chrome/browser/net/proxy_config_monitor.h" +#include "components/keyed_service/core/keyed_service.h" +#include "services/network/public/mojom/network_context.mojom.h" + +namespace atom { + +// KeyedService that initializes and provides access to the NetworkContexts for +// a BrowserContext. +class NetworkContextService : public KeyedService { + public: + explicit NetworkContextService(content::BrowserContext* context); + ~NetworkContextService() override; + + NetworkContextService(const NetworkContextService&) = delete; + NetworkContextService& operator=(const NetworkContextService&) = delete; + + // Creates a NetworkContext for the BrowserContext. + network::mojom::NetworkContextPtr CreateNetworkContext(); + + private: + // Creates parameters for the NetworkContext. + network::mojom::NetworkContextParamsPtr CreateNetworkContextParams( + bool in_memory, + const base::FilePath& path); + + AtomBrowserContext* browser_context_; + ProxyConfigMonitor proxy_config_monitor_; +}; + +} // namespace atom + +#endif // ATOM_BROWSER_NET_NETWORK_CONTEXT_SERVICE_H_ diff --git a/atom/browser/net/network_context_service_factory.cc b/atom/browser/net/network_context_service_factory.cc new file mode 100644 index 0000000000..eb1e55bcda --- /dev/null +++ b/atom/browser/net/network_context_service_factory.cc @@ -0,0 +1,34 @@ +// Copyright (c) 2019 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/network_context_service_factory.h" + +#include "atom/browser/net/network_context_service.h" +#include "components/keyed_service/content/browser_context_dependency_manager.h" + +namespace atom { + +NetworkContextService* NetworkContextServiceFactory::GetForContext( + content::BrowserContext* browser_context) { + return static_cast( + GetInstance()->GetServiceForBrowserContext(browser_context, true)); +} + +NetworkContextServiceFactory* NetworkContextServiceFactory::GetInstance() { + return base::Singleton::get(); +} + +NetworkContextServiceFactory::NetworkContextServiceFactory() + : BrowserContextKeyedServiceFactory( + "ElectronNetworkContextService", + BrowserContextDependencyManager::GetInstance()) {} + +NetworkContextServiceFactory::~NetworkContextServiceFactory() {} + +KeyedService* NetworkContextServiceFactory::BuildServiceInstanceFor( + content::BrowserContext* context) const { + return new NetworkContextService(static_cast(context)); +} + +} // namespace atom diff --git a/atom/browser/net/network_context_service_factory.h b/atom/browser/net/network_context_service_factory.h new file mode 100644 index 0000000000..07a92a2009 --- /dev/null +++ b/atom/browser/net/network_context_service_factory.h @@ -0,0 +1,48 @@ +// Copyright (c) 2019 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_NETWORK_CONTEXT_SERVICE_FACTORY_H_ +#define ATOM_BROWSER_NET_NETWORK_CONTEXT_SERVICE_FACTORY_H_ + +#include "base/memory/singleton.h" +#include "components/keyed_service/content/browser_context_keyed_service_factory.h" + +class KeyedService; + +namespace contenet { +class BrowserContext; +} + +namespace atom { + +class NetworkContextService; + +class NetworkContextServiceFactory : public BrowserContextKeyedServiceFactory { + public: + // Returns the NetworkContextService that supports NetworkContexts for + // |browser_context|. + static NetworkContextService* GetForContext( + content::BrowserContext* browser_context); + + // Returns the NetworkContextServiceFactory singleton. + static NetworkContextServiceFactory* GetInstance(); + + NetworkContextServiceFactory(const NetworkContextServiceFactory&) = delete; + NetworkContextServiceFactory& operator=(const NetworkContextServiceFactory&) = + delete; + + private: + friend struct base::DefaultSingletonTraits; + + NetworkContextServiceFactory(); + ~NetworkContextServiceFactory() override; + + // BrowserContextKeyedServiceFactory implementation: + KeyedService* BuildServiceInstanceFor( + content::BrowserContext* context) const override; +}; + +} // namespace atom + +#endif // ATOM_BROWSER_NET_NETWORK_CONTEXT_SERVICE_FACTORY_H_ diff --git a/atom/browser/net/system_network_context_manager.cc b/atom/browser/net/system_network_context_manager.cc index 964376afbb..f9d1a12679 100644 --- a/atom/browser/net/system_network_context_manager.cc +++ b/atom/browser/net/system_network_context_manager.cc @@ -11,7 +11,6 @@ #include "atom/common/application_info.h" #include "atom/common/options_switches.h" #include "base/command_line.h" -#include "base/lazy_instance.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/net/chrome_mojo_proxy_resolver_factory.h" #include "components/net_log/net_export_file_writer.h" @@ -27,11 +26,11 @@ #include "services/network/public/cpp/shared_url_loader_factory.h" #include "url/gurl.h" -base::LazyInstance::Leaky - g_system_network_context_manager = LAZY_INSTANCE_INITIALIZER; - namespace { +// The global instance of the SystemNetworkContextmanager. +SystemNetworkContextManager* g_system_network_context_manager = nullptr; + network::mojom::HttpAuthStaticParamsPtr CreateHttpAuthStaticParams() { network::mojom::HttpAuthStaticParamsPtr auth_static_params = network::mojom::HttpAuthStaticParams::New(); @@ -63,10 +62,11 @@ class SystemNetworkContextManager::URLLoaderFactoryForSystem : public network::SharedURLLoaderFactory { public: explicit URLLoaderFactoryForSystem(SystemNetworkContextManager* manager) - : manager_(manager) {} + : manager_(manager) { + DETACH_FROM_SEQUENCE(sequence_checker_); + } // mojom::URLLoaderFactory implementation: - void CreateLoaderAndStart(network::mojom::URLLoaderRequest request, int32_t routing_id, int32_t request_id, @@ -75,7 +75,7 @@ class SystemNetworkContextManager::URLLoaderFactoryForSystem network::mojom::URLLoaderClientPtr client, const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) override { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!manager_) return; manager_->GetURLLoaderFactory()->CreateLoaderAndStart( @@ -91,6 +91,7 @@ class SystemNetworkContextManager::URLLoaderFactoryForSystem // SharedURLLoaderFactory implementation: std::unique_ptr Clone() override { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CURRENTLY_ON(content::BrowserThread::UI); return std::make_unique( this); @@ -102,6 +103,7 @@ class SystemNetworkContextManager::URLLoaderFactoryForSystem friend class base::RefCounted; ~URLLoaderFactoryForSystem() override {} + SEQUENCE_CHECKER(sequence_checker_); SystemNetworkContextManager* manager_; DISALLOW_COPY_AND_ASSIGN(URLLoaderFactoryForSystem); @@ -157,7 +159,6 @@ SystemNetworkContextManager::GetNetExportFileWriter() { return net_export_file_writer_.get(); } -// static network::mojom::NetworkContextParamsPtr SystemNetworkContextManager::CreateDefaultNetworkContextParams() { network::mojom::NetworkContextParamsPtr network_context_params = @@ -191,8 +192,29 @@ void SystemNetworkContextManager::SetUp( *http_auth_dynamic_params = CreateHttpAuthDynamicParams(); } -SystemNetworkContextManager::SystemNetworkContextManager() - : proxy_config_monitor_(g_browser_process->local_state()) { +// static +SystemNetworkContextManager* SystemNetworkContextManager::CreateInstance( + PrefService* pref_service) { + DCHECK(!g_system_network_context_manager); + g_system_network_context_manager = + new SystemNetworkContextManager(pref_service); + return g_system_network_context_manager; +} + +// static +SystemNetworkContextManager* SystemNetworkContextManager::GetInstance() { + return g_system_network_context_manager; +} + +// static +void SystemNetworkContextManager::DeleteInstance() { + DCHECK(g_system_network_context_manager); + delete g_system_network_context_manager; +} + +SystemNetworkContextManager::SystemNetworkContextManager( + PrefService* pref_service) + : proxy_config_monitor_(pref_service) { shared_url_loader_factory_ = new URLLoaderFactoryForSystem(this); } diff --git a/atom/browser/net/system_network_context_manager.h b/atom/browser/net/system_network_context_manager.h index 2462dd4454..7967d60ae8 100644 --- a/atom/browser/net/system_network_context_manager.h +++ b/atom/browser/net/system_network_context_manager.h @@ -40,12 +40,20 @@ class NetExportFileWriter; // using the actual network service. class SystemNetworkContextManager { public: - SystemNetworkContextManager(); ~SystemNetworkContextManager(); + // Creates the global instance of SystemNetworkContextManager. If an + // instance already exists, this will cause a DCHECK failure. + static SystemNetworkContextManager* CreateInstance(PrefService* pref_service); + + // Gets the global SystemNetworkContextManager instance. + static SystemNetworkContextManager* GetInstance(); + + // Destroys the global SystemNetworkContextManager instance. + static void DeleteInstance(); + // Returns default set of parameters for configuring the network service. - static network::mojom::NetworkContextParamsPtr - CreateDefaultNetworkContextParams(); + network::mojom::NetworkContextParamsPtr CreateDefaultNetworkContextParams(); // Initializes |network_context_params| as needed to set up a system // NetworkContext. If the network service is disabled, @@ -85,6 +93,8 @@ class SystemNetworkContextManager { private: class URLLoaderFactoryForSystem; + explicit SystemNetworkContextManager(PrefService* pref_service); + // Creates parameters for the NetworkContext. May only be called once, since // it initializes some class members. network::mojom::NetworkContextParamsPtr CreateNetworkContextParams(); diff --git a/atom/browser/net/url_request_context_getter.cc b/atom/browser/net/url_request_context_getter.cc index 6454f42a1c..d36b1cc9ef 100644 --- a/atom/browser/net/url_request_context_getter.cc +++ b/atom/browser/net/url_request_context_getter.cc @@ -31,7 +31,6 @@ #include "content/public/browser/browser_thread.h" #include "content/public/browser/devtools_network_transaction_factory.h" #include "content/public/browser/network_service_instance.h" -#include "content/public/browser/resource_context.h" #include "net/base/host_mapping_rules.h" #include "net/cert/multi_log_ct_verifier.h" #include "net/cookies/cookie_monster.h" @@ -102,18 +101,9 @@ void SetupAtomURLRequestJobFactory( } // namespace -class ResourceContext : public content::ResourceContext { - public: - ResourceContext() = default; - ~ResourceContext() override = default; - - private: - DISALLOW_COPY_AND_ASSIGN(ResourceContext); -}; - URLRequestContextGetter::Handle::Handle( base::WeakPtr browser_context) - : resource_context_(new ResourceContext), + : resource_context_(new content::ResourceContext), browser_context_(browser_context), initialized_(false) {} @@ -154,7 +144,8 @@ URLRequestContextGetter::Handle::GetNetworkContext() { network::mojom::NetworkContextParamsPtr URLRequestContextGetter::Handle::CreateNetworkContextParams() { network::mojom::NetworkContextParamsPtr network_context_params = - SystemNetworkContextManager::CreateDefaultNetworkContextParams(); + SystemNetworkContextManager::GetInstance() + ->CreateDefaultNetworkContextParams(); network_context_params->user_agent = browser_context_->GetUserAgent(); @@ -250,7 +241,7 @@ URLRequestContextGetter::~URLRequestContextGetter() { } void URLRequestContextGetter::NotifyContextShuttingDown( - std::unique_ptr resource_context) { + std::unique_ptr resource_context) { DCHECK_CURRENTLY_ON(BrowserThread::IO); // todo(brenca): remove once C70 lands diff --git a/atom/browser/net/url_request_context_getter.h b/atom/browser/net/url_request_context_getter.h index fa30feb447..c4ec7159dc 100644 --- a/atom/browser/net/url_request_context_getter.h +++ b/atom/browser/net/url_request_context_getter.h @@ -11,6 +11,7 @@ #include "base/files/file_path.h" #include "content/public/browser/browser_context.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" #include "services/network/public/mojom/network_service.mojom.h" @@ -36,7 +37,7 @@ class URLRequestContextGetter : public net::URLRequestContextGetter { // Discard reference to URLRequestContext and inform observers to // shutdown. Must be called only on IO thread. - void NotifyContextShuttingDown(std::unique_ptr); + void NotifyContextShuttingDown(std::unique_ptr); AtomURLRequestJobFactory* job_factory() const { return top_job_factory_.get(); @@ -69,7 +70,7 @@ class URLRequestContextGetter : public net::URLRequestContextGetter { void LazyInitialize(); scoped_refptr main_request_context_getter_; - std::unique_ptr resource_context_; + std::unique_ptr resource_context_; base::WeakPtr browser_context_; // This is a NetworkContext interface that uses URLRequestContextGetter // NetworkContext, ownership is passed to StoragePartition when diff --git a/atom/browser/ui/inspectable_web_contents_impl.cc b/atom/browser/ui/inspectable_web_contents_impl.cc index f8f9fce56d..cdea0da456 100644 --- a/atom/browser/ui/inspectable_web_contents_impl.cc +++ b/atom/browser/ui/inspectable_web_contents_impl.cc @@ -12,6 +12,7 @@ #include "atom/browser/ui/inspectable_web_contents_view.h" #include "atom/browser/ui/inspectable_web_contents_view_delegate.h" #include "atom/common/platform_util.h" +#include "base/base64.h" #include "base/guid.h" #include "base/json/json_reader.h" #include "base/json/json_writer.h" @@ -37,10 +38,9 @@ #include "content/public/browser/storage_partition.h" #include "content/public/common/user_agent.h" #include "ipc/ipc_channel.h" -#include "net/base/io_buffer.h" #include "net/http/http_response_headers.h" -#include "net/url_request/url_fetcher.h" -#include "net/url_request/url_fetcher_response_writer.h" +#include "services/network/public/cpp/simple_url_loader.h" +#include "services/network/public/cpp/simple_url_loader_stream_consumer.h" #include "ui/display/display.h" #include "ui/display/screen.h" @@ -145,64 +145,83 @@ GURL GetDevToolsURL(bool can_dock) { return GURL(url_string); } -// ResponseWriter ------------------------------------------------------------- +} // namespace -class ResponseWriter : public net::URLFetcherResponseWriter { +class InspectableWebContentsImpl::NetworkResourceLoader + : public network::SimpleURLLoaderStreamConsumer { public: - ResponseWriter(base::WeakPtr bindings, - int stream_id); - ~ResponseWriter() override; + NetworkResourceLoader(int stream_id, + InspectableWebContentsImpl* bindings, + std::unique_ptr loader, + network::mojom::URLLoaderFactory* url_loader_factory, + const DispatchCallback& callback) + : stream_id_(stream_id), + bindings_(bindings), + loader_(std::move(loader)), + callback_(callback) { + loader_->SetOnResponseStartedCallback(base::BindOnce( + &NetworkResourceLoader::OnResponseStarted, base::Unretained(this))); + loader_->DownloadAsStream(url_loader_factory, this); + } - // URLFetcherResponseWriter overrides: - int Initialize(net::CompletionOnceCallback callback) override; - int Write(net::IOBuffer* buffer, - int num_bytes, - net::CompletionOnceCallback callback) override; - int Finish(int net_error, net::CompletionOnceCallback callback) override; + NetworkResourceLoader(const NetworkResourceLoader&) = delete; + NetworkResourceLoader& operator=(const NetworkResourceLoader&) = delete; private: - base::WeakPtr bindings_; - int stream_id_; + void OnResponseStarted(const GURL& final_url, + const network::ResourceResponseHead& response_head) { + response_headers_ = response_head.headers; + } - DISALLOW_COPY_AND_ASSIGN(ResponseWriter); + void OnDataReceived(base::StringPiece chunk, + base::OnceClosure resume) override { + base::Value chunkValue; + + bool encoded = !base::IsStringUTF8(chunk); + if (encoded) { + std::string encoded_string; + base::Base64Encode(chunk, &encoded_string); + chunkValue = base::Value(std::move(encoded_string)); + } else { + chunkValue = base::Value(chunk); + } + base::Value id(stream_id_); + base::Value encodedValue(encoded); + + bindings_->CallClientFunction("DevToolsAPI.streamWrite", &id, &chunkValue, + &encodedValue); + std::move(resume).Run(); + } + + void OnComplete(bool success) override { + base::DictionaryValue response; + response.SetInteger("statusCode", response_headers_ + ? response_headers_->response_code() + : 200); + + auto headers = std::make_unique(); + size_t iterator = 0; + std::string name; + std::string value; + while (response_headers_ && + response_headers_->EnumerateHeaderLines(&iterator, &name, &value)) + headers->SetString(name, value); + + response.Set("headers", std::move(headers)); + callback_.Run(&response); + + bindings_->loaders_.erase(bindings_->loaders_.find(this)); + } + + void OnRetry(base::OnceClosure start_retry) override {} + + const int stream_id_; + InspectableWebContentsImpl* const bindings_; + std::unique_ptr loader_; + DispatchCallback callback_; + scoped_refptr response_headers_; }; -ResponseWriter::ResponseWriter( - base::WeakPtr bindings, - int stream_id) - : bindings_(bindings), stream_id_(stream_id) {} - -ResponseWriter::~ResponseWriter() {} - -int ResponseWriter::Initialize(net::CompletionOnceCallback callback) { - return net::OK; -} - -int ResponseWriter::Write(net::IOBuffer* buffer, - int num_bytes, - net::CompletionOnceCallback callback) { - std::string chunk = std::string(buffer->data(), num_bytes); - if (!base::IsStringUTF8(chunk)) - return num_bytes; - - base::Value* id = new base::Value(stream_id_); - base::Value* chunk_value = new base::Value(chunk); - - base::PostTaskWithTraits( - FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&InspectableWebContentsImpl::CallClientFunction, bindings_, - "DevToolsAPI.streamWrite", base::Owned(id), - base::Owned(chunk_value), nullptr)); - return num_bytes; -} - -int ResponseWriter::Finish(int net_error, - net::CompletionOnceCallback callback) { - return net::OK; -} - -} // namespace - // Implemented separately on each platform. InspectableWebContentsView* CreateInspectableContentsView( InspectableWebContentsImpl* inspectable_web_contents_impl); @@ -495,19 +514,19 @@ void InspectableWebContentsImpl::LoadNetworkResource( return; } - auto* browser_context = GetDevToolsWebContents()->GetBrowserContext(); + auto resource_request = std::make_unique(); + resource_request->url = gurl; + resource_request->headers.AddHeadersFromString(headers); - net::URLFetcher* fetcher = - (net::URLFetcher::Create(gurl, net::URLFetcher::GET, this)).release(); - pending_requests_[fetcher] = callback; - fetcher->SetRequestContext( - content::BrowserContext::GetDefaultStoragePartition(browser_context) - ->GetURLRequestContext()); - fetcher->SetExtraRequestHeaders(headers); - fetcher->SaveResponseWithWriter( - std::unique_ptr( - new ResponseWriter(weak_factory_.GetWeakPtr(), stream_id))); - fetcher->Start(); + auto* partition = content::BrowserContext::GetDefaultStoragePartition( + GetDevToolsWebContents()->GetBrowserContext()); + auto factory = partition->GetURLLoaderFactoryForBrowserProcess(); + + auto simple_url_loader = network::SimpleURLLoader::Create( + std::move(resource_request), NO_TRAFFIC_ANNOTATION_YET); + auto resource_loader = std::make_unique( + stream_id, this, std::move(simple_url_loader), factory.get(), callback); + loaders_.insert(std::move(resource_loader)); } void InspectableWebContentsImpl::SetIsDocked(const DispatchCallback& callback, @@ -752,9 +771,6 @@ void InspectableWebContentsImpl::WebContentsDestroyed() { Detach(); embedder_message_dispatcher_.reset(); - for (const auto& pair : pending_requests_) - delete pair.first; - if (view_ && view_->GetDelegate()) view_->GetDelegate()->DevToolsClosed(); } @@ -874,34 +890,6 @@ void InspectableWebContentsImpl::DidFinishNavigation( frame->ExecuteJavaScriptForTests(base::UTF8ToUTF16(script)); } -void InspectableWebContentsImpl::OnURLFetchComplete( - const net::URLFetcher* source) { - DCHECK(source); - auto it = pending_requests_.find(source); - DCHECK(it != pending_requests_.end()); - - base::DictionaryValue response; - - net::HttpResponseHeaders* rh = source->GetResponseHeaders(); - response.SetInteger("statusCode", rh ? rh->response_code() : 200); - - { - auto headers = std::make_unique(); - - size_t iterator = 0; - std::string name; - std::string value; - while (rh && rh->EnumerateHeaderLines(&iterator, &name, &value)) - headers->SetString(name, value); - - response.Set("headers", std::move(headers)); - } - - it->second.Run(&response); - pending_requests_.erase(it); - delete source; -} - void InspectableWebContentsImpl::SendMessageAck(int request_id, const base::Value* arg) { base::Value id_value(request_id); diff --git a/atom/browser/ui/inspectable_web_contents_impl.h b/atom/browser/ui/inspectable_web_contents_impl.h index f60a19f2fd..f3a9451f4d 100644 --- a/atom/browser/ui/inspectable_web_contents_impl.h +++ b/atom/browser/ui/inspectable_web_contents_impl.h @@ -8,10 +8,12 @@ #include #include +#include #include #include #include "atom/browser/ui/inspectable_web_contents.h" +#include "base/containers/unique_ptr_adapters.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/devtools/devtools_contents_resizing_strategy.h" #include "chrome/browser/devtools/devtools_embedder_message_dispatcher.h" @@ -19,7 +21,6 @@ #include "content/public/browser/devtools_frontend_host.h" #include "content/public/browser/web_contents_delegate.h" #include "content/public/browser/web_contents_observer.h" -#include "net/url_request/url_fetcher_delegate.h" #include "ui/gfx/geometry/rect.h" class PrefService; @@ -35,8 +36,7 @@ class InspectableWebContentsImpl public content::DevToolsAgentHostClient, public content::WebContentsObserver, public content::WebContentsDelegate, - public DevToolsEmbedderMessageDispatcher::Delegate, - public net::URLFetcherDelegate { + public DevToolsEmbedderMessageDispatcher::Delegate { public: static void RegisterPrefs(PrefRegistrySimple* pref_registry); @@ -197,9 +197,6 @@ class InspectableWebContentsImpl std::unique_ptr listener, const base::FilePath& path) override; - // net::URLFetcherDelegate: - void OnURLFetchComplete(const net::URLFetcher* source) override; - void SendMessageAck(int request_id, const base::Value* arg1); bool frontend_loaded_; @@ -214,8 +211,6 @@ class InspectableWebContentsImpl std::string dock_state_; bool activate_ = true; - using PendingRequestsMap = std::map; - PendingRequestsMap pending_requests_; InspectableWebContentsDelegate* delegate_; // weak references. PrefService* pref_service_; // weak reference. @@ -231,6 +226,10 @@ class InspectableWebContentsImpl bool is_guest_; std::unique_ptr view_; + class NetworkResourceLoader; + std::set, base::UniquePtrComparator> + loaders_; + using ExtensionsAPIs = std::map; ExtensionsAPIs extensions_api_; diff --git a/filenames.gni b/filenames.gni index 0ff0374a05..bff034ba1e 100644 --- a/filenames.gni +++ b/filenames.gni @@ -325,6 +325,10 @@ filenames = { "atom/browser/net/http_protocol_handler.h", "atom/browser/net/js_asker.cc", "atom/browser/net/js_asker.h", + "atom/browser/net/network_context_service_factory.cc", + "atom/browser/net/network_context_service_factory.h", + "atom/browser/net/network_context_service.cc", + "atom/browser/net/network_context_service.h", "atom/browser/net/require_ct_delegate.cc", "atom/browser/net/require_ct_delegate.h", "atom/browser/net/resolve_proxy_helper.cc",