Browse Source

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
Robo 6 years ago
parent
commit
6c20c6e668

+ 20 - 2
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<AtomBrowserContext*>(browser_context)->GetNetworkContext();
+
+  if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+    return NetworkContextServiceFactory::GetForContext(browser_context)
+        ->CreateNetworkContext();
+  } else {
+    return static_cast<AtomBrowserContext*>(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);
 }

+ 1 - 0
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<service_manager::Manifest> GetServiceManifestOverlay(
       base::StringPiece name) override;

+ 48 - 11
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<ProxyConfigMonitor>(prefs_.get());
-  io_handle_ = new URLRequestContextGetter::Handle(weak_factory_.GetWeakPtr());
+  if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+    proxy_config_monitor_ = std::make_unique<ProxyConfigMonitor>(prefs_.get());
+    io_handle_ =
+        new URLRequestContextGetter::Handle(weak_factory_.GetWeakPtr());
+  }
+
   cookie_change_notifier_ = std::make_unique<CookieChangeNotifier>(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() {

+ 2 - 0
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<content::ResourceContext> resource_context_;
   std::unique_ptr<CookieChangeNotifier> cookie_change_notifier_;
   std::unique_ptr<PrefService> prefs_;
   std::unique_ptr<AtomDownloadManagerDelegate> download_manager_delegate_;

+ 10 - 7
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<SystemNetworkContextManager>();
+  if (!SystemNetworkContextManager::GetInstance())
+    SystemNetworkContextManager::CreateInstance(local_state_.get());
 
   net_log_ = std::make_unique<net_log::ChromeNetLog>();
   // 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<IOThread>(
-      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() {

+ 0 - 1
atom/browser/browser_process_impl.h

@@ -122,7 +122,6 @@ class BrowserProcessImpl : public BrowserProcess {
   std::unique_ptr<PrefService> local_state_;
   std::unique_ptr<IOThread> io_thread_;
   std::unique_ptr<net_log::ChromeNetLog> net_log_;
-  std::unique_ptr<SystemNetworkContextManager> system_network_context_manager_;
   std::string locale_;
 
   DISALLOW_COPY_AND_ASSIGN(BrowserProcessImpl);

+ 24 - 19
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<network::URLRequestContextBuilderMojo> builder =
-      std::make_unique<network::URLRequestContextBuilderMojo>();
+  if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+    std::unique_ptr<network::URLRequestContextBuilderMojo> builder =
+        std::make_unique<network::URLRequestContextBuilderMojo>();
 
-  auto cert_verifier = std::make_unique<net::CachingCertVerifier>(
-      std::make_unique<net::MultiThreadedCertVerifier>(
-          net::CertVerifyProc::CreateDefault()));
-  builder->SetCertVerifier(std::move(cert_verifier));
+    auto cert_verifier = std::make_unique<net::CachingCertVerifier>(
+        std::make_unique<net::MultiThreadedCertVerifier>(
+            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();

+ 94 - 0
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<AtomBrowserContext*>(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

+ 41 - 0
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_

+ 34 - 0
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<NetworkContextService*>(
+      GetInstance()->GetServiceForBrowserContext(browser_context, true));
+}
+
+NetworkContextServiceFactory* NetworkContextServiceFactory::GetInstance() {
+  return base::Singleton<NetworkContextServiceFactory>::get();
+}
+
+NetworkContextServiceFactory::NetworkContextServiceFactory()
+    : BrowserContextKeyedServiceFactory(
+          "ElectronNetworkContextService",
+          BrowserContextDependencyManager::GetInstance()) {}
+
+NetworkContextServiceFactory::~NetworkContextServiceFactory() {}
+
+KeyedService* NetworkContextServiceFactory::BuildServiceInstanceFor(
+    content::BrowserContext* context) const {
+  return new NetworkContextService(static_cast<AtomBrowserContext*>(context));
+}
+
+}  // namespace atom

+ 48 - 0
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();
+  ~NetworkContextServiceFactory() override;
+
+  // BrowserContextKeyedServiceFactory implementation:
+  KeyedService* BuildServiceInstanceFor(
+      content::BrowserContext* context) const override;
+};
+
+}  // namespace atom
+
+#endif  // ATOM_BROWSER_NET_NETWORK_CONTEXT_SERVICE_FACTORY_H_

+ 32 - 10
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<SystemNetworkContextManager>::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<network::SharedURLLoaderFactoryInfo> Clone() override {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
     return std::make_unique<network::CrossThreadSharedURLLoaderFactoryInfo>(
         this);
@@ -102,6 +103,7 @@ class SystemNetworkContextManager::URLLoaderFactoryForSystem
   friend class base::RefCounted<URLLoaderFactoryForSystem>;
   ~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);
 }
 

+ 13 - 3
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();

+ 4 - 13
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<AtomBrowserContext> 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<ResourceContext> resource_context) {
+    std::unique_ptr<content::ResourceContext> resource_context) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   // todo(brenca): remove once C70 lands

+ 3 - 2
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<ResourceContext>);
+  void NotifyContextShuttingDown(std::unique_ptr<content::ResourceContext>);
 
   AtomURLRequestJobFactory* job_factory() const {
     return top_job_factory_.get();
@@ -69,7 +70,7 @@ class URLRequestContextGetter : public net::URLRequestContextGetter {
     void LazyInitialize();
 
     scoped_refptr<URLRequestContextGetter> main_request_context_getter_;
-    std::unique_ptr<ResourceContext> resource_context_;
+    std::unique_ptr<content::ResourceContext> resource_context_;
     base::WeakPtr<AtomBrowserContext> browser_context_;
     // This is a NetworkContext interface that uses URLRequestContextGetter
     // NetworkContext, ownership is passed to StoragePartition when

+ 78 - 90
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,63 +145,82 @@ 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<InspectableWebContentsImpl> bindings,
-                 int stream_id);
-  ~ResponseWriter() override;
+  NetworkResourceLoader(int stream_id,
+                        InspectableWebContentsImpl* bindings,
+                        std::unique_ptr<network::SimpleURLLoader> 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<InspectableWebContentsImpl> bindings_;
-  int stream_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(ResponseWriter);
-};
+  void OnResponseStarted(const GURL& final_url,
+                         const network::ResourceResponseHead& response_head) {
+    response_headers_ = response_head.headers;
+  }
 
-ResponseWriter::ResponseWriter(
-    base::WeakPtr<InspectableWebContentsImpl> bindings,
-    int stream_id)
-    : bindings_(bindings), stream_id_(stream_id) {}
+  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);
 
-ResponseWriter::~ResponseWriter() {}
+    bindings_->CallClientFunction("DevToolsAPI.streamWrite", &id, &chunkValue,
+                                  &encodedValue);
+    std::move(resume).Run();
+  }
 
-int ResponseWriter::Initialize(net::CompletionOnceCallback callback) {
-  return net::OK;
-}
+  void OnComplete(bool success) override {
+    base::DictionaryValue response;
+    response.SetInteger("statusCode", response_headers_
+                                          ? response_headers_->response_code()
+                                          : 200);
 
-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;
+    auto headers = std::make_unique<base::DictionaryValue>();
+    size_t iterator = 0;
+    std::string name;
+    std::string value;
+    while (response_headers_ &&
+           response_headers_->EnumerateHeaderLines(&iterator, &name, &value))
+      headers->SetString(name, value);
 
-  base::Value* id = new base::Value(stream_id_);
-  base::Value* chunk_value = new base::Value(chunk);
+    response.Set("headers", std::move(headers));
+    callback_.Run(&response);
 
-  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;
-}
+    bindings_->loaders_.erase(bindings_->loaders_.find(this));
+  }
 
-int ResponseWriter::Finish(int net_error,
-                           net::CompletionOnceCallback callback) {
-  return net::OK;
-}
+  void OnRetry(base::OnceClosure start_retry) override {}
 
-}  // namespace
+  const int stream_id_;
+  InspectableWebContentsImpl* const bindings_;
+  std::unique_ptr<network::SimpleURLLoader> loader_;
+  DispatchCallback callback_;
+  scoped_refptr<net::HttpResponseHeaders> response_headers_;
+};
 
 // Implemented separately on each platform.
 InspectableWebContentsView* CreateInspectableContentsView(
@@ -495,19 +514,19 @@ void InspectableWebContentsImpl::LoadNetworkResource(
     return;
   }
 
-  auto* browser_context = GetDevToolsWebContents()->GetBrowserContext();
+  auto resource_request = std::make_unique<network::ResourceRequest>();
+  resource_request->url = gurl;
+  resource_request->headers.AddHeadersFromString(headers);
+
+  auto* partition = content::BrowserContext::GetDefaultStoragePartition(
+      GetDevToolsWebContents()->GetBrowserContext());
+  auto factory = partition->GetURLLoaderFactoryForBrowserProcess();
 
-  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<net::URLFetcherResponseWriter>(
-          new ResponseWriter(weak_factory_.GetWeakPtr(), stream_id)));
-  fetcher->Start();
+  auto simple_url_loader = network::SimpleURLLoader::Create(
+      std::move(resource_request), NO_TRAFFIC_ANNOTATION_YET);
+  auto resource_loader = std::make_unique<NetworkResourceLoader>(
+      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<base::DictionaryValue>();
-
-    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);

+ 7 - 8
atom/browser/ui/inspectable_web_contents_impl.h

@@ -8,10 +8,12 @@
 
 #include <map>
 #include <memory>
+#include <set>
 #include <string>
 #include <vector>
 
 #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<content::FileSelectListener> 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<const net::URLFetcher*, DispatchCallback>;
-  PendingRequestsMap pending_requests_;
   InspectableWebContentsDelegate* delegate_;  // weak references.
 
   PrefService* pref_service_;  // weak reference.
@@ -231,6 +226,10 @@ class InspectableWebContentsImpl
   bool is_guest_;
   std::unique_ptr<InspectableWebContentsView> view_;
 
+  class NetworkResourceLoader;
+  std::set<std::unique_ptr<NetworkResourceLoader>, base::UniquePtrComparator>
+      loaders_;
+
   using ExtensionsAPIs = std::map<std::string, std::string>;
   ExtensionsAPIs extensions_api_;
 

+ 4 - 0
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",