Browse Source

Merge pull request #13625 from electron/proxy_resolver_oop

fix: use mojo v8 proxy resolver with a utility process
Cheng Zhao 6 years ago
parent
commit
17297d85f8

+ 4 - 57
atom/browser/api/atom_api_session.cc

@@ -29,7 +29,6 @@
 #include "base/guid.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
-#include "base/threading/thread_task_runner_handle.h"
 #include "brightray/browser/media/media_device_id_salt.h"
 #include "brightray/browser/net/devtools_network_conditions.h"
 #include "brightray/browser/net/devtools_network_controller_handle.h"
@@ -47,7 +46,6 @@
 #include "net/http/http_auth_handler_factory.h"
 #include "net/http/http_auth_preferences.h"
 #include "net/proxy/proxy_config_service_fixed.h"
-#include "net/proxy/proxy_service.h"
 #include "net/url_request/static_http_user_agent_settings.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
@@ -232,59 +230,6 @@ const char kPersistPrefix[] = "persist:";
 // Referenced session objects.
 std::map<uint32_t, v8::Global<v8::Object>> g_sessions;
 
-class ResolveProxyHelper {
- public:
-  ResolveProxyHelper(AtomBrowserContext* browser_context,
-                     const GURL& url,
-                     const Session::ResolveProxyCallback& callback)
-      : callback_(callback),
-        original_thread_(base::ThreadTaskRunnerHandle::Get()) {
-    scoped_refptr<net::URLRequestContextGetter> context_getter =
-        browser_context->url_request_context_getter();
-    context_getter->GetNetworkTaskRunner()->PostTask(
-        FROM_HERE,
-        base::Bind(&ResolveProxyHelper::ResolveProxy,
-                   base::Unretained(this), context_getter, url));
-  }
-
-  void OnResolveProxyCompleted(int result) {
-    std::string proxy;
-    if (result == net::OK)
-      proxy = proxy_info_.ToPacString();
-    original_thread_->PostTask(FROM_HERE,
-                               base::Bind(callback_, proxy));
-    delete this;
-  }
-
- private:
-  void ResolveProxy(scoped_refptr<net::URLRequestContextGetter> context_getter,
-                    const GURL& url) {
-    DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-
-    net::ProxyService* proxy_service =
-        context_getter->GetURLRequestContext()->proxy_service();
-    net::CompletionCallback completion_callback =
-        base::Bind(&ResolveProxyHelper::OnResolveProxyCompleted,
-                   base::Unretained(this));
-
-    // Start the request.
-    int result = proxy_service->ResolveProxy(
-        url, "GET", &proxy_info_, completion_callback, &pac_req_, nullptr,
-        net::NetLogWithSource());
-
-    // Completed synchronously.
-    if (result != net::ERR_IO_PENDING)
-      completion_callback.Run(result);
-  }
-
-  Session::ResolveProxyCallback callback_;
-  net::ProxyInfo proxy_info_;
-  net::ProxyService::PacRequest* pac_req_;
-  scoped_refptr<base::SingleThreadTaskRunner> original_thread_;
-
-  DISALLOW_COPY_AND_ASSIGN(ResolveProxyHelper);
-};
-
 // Runs the callback in UI thread.
 void RunCallbackInUI(const base::Callback<void()>& callback) {
   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
@@ -490,8 +435,10 @@ void Session::OnDownloadCreated(content::DownloadManager* manager,
   }
 }
 
-void Session::ResolveProxy(const GURL& url, ResolveProxyCallback callback) {
-  new ResolveProxyHelper(browser_context(), url, callback);
+void Session::ResolveProxy(
+    const GURL& url,
+    const ResolveProxyHelper::ResolveProxyCallback& callback) {
+  browser_context_->GetResolveProxyHelper()->ResolveProxy(url, callback);
 }
 
 template<Session::CacheAction action>

+ 3 - 3
atom/browser/api/atom_api_session.h

@@ -10,6 +10,7 @@
 
 #include "atom/browser/api/trackable_object.h"
 #include "atom/browser/atom_blob_reader.h"
+#include "atom/browser/net/resolve_proxy_helper.h"
 #include "base/values.h"
 #include "content/public/browser/download_manager.h"
 #include "native_mate/handle.h"
@@ -39,8 +40,6 @@ namespace api {
 class Session: public mate::TrackableObject<Session>,
                public content::DownloadManager::Observer {
  public:
-  using ResolveProxyCallback = base::Callback<void(std::string)>;
-
   enum class CacheAction {
     CLEAR,
     STATS,
@@ -62,7 +61,8 @@ class Session: public mate::TrackableObject<Session>,
                              v8::Local<v8::FunctionTemplate> prototype);
 
   // Methods.
-  void ResolveProxy(const GURL& url, ResolveProxyCallback callback);
+  void ResolveProxy(const GURL& url,
+                    const ResolveProxyHelper::ResolveProxyCallback& callback);
   template<CacheAction action>
   void DoCacheAction(const net::CompletionCallback& callback);
   void ClearStorageData(mate::Arguments* args);

+ 0 - 1
atom/browser/atom_browser_client.cc

@@ -448,7 +448,6 @@ void AtomBrowserClient::SiteInstanceDeleting(
 
 brightray::BrowserMainParts* AtomBrowserClient::OverrideCreateBrowserMainParts(
     const content::MainFunctionParams&) {
-  v8::V8::Initialize();  // Init V8 before creating main parts.
   return new AtomBrowserMainParts;
 }
 

+ 9 - 0
atom/browser/atom_browser_context.cc

@@ -16,6 +16,7 @@
 #include "atom/browser/net/atom_network_delegate.h"
 #include "atom/browser/net/atom_url_request_job_factory.h"
 #include "atom/browser/net/http_protocol_handler.h"
+#include "atom/browser/net/resolve_proxy_helper.h"
 #include "atom/browser/web_view_manager.h"
 #include "atom/common/atom_version.h"
 #include "atom/common/chrome_version.h"
@@ -226,6 +227,14 @@ AtomBlobReader* AtomBrowserContext::GetBlobReader() {
   return blob_reader_.get();
 }
 
+ResolveProxyHelper* AtomBrowserContext::GetResolveProxyHelper() {
+  if (!resolve_proxy_helper_.get()) {
+    resolve_proxy_helper_ =
+        base::MakeRefCounted<ResolveProxyHelper>(url_request_context_getter());
+  }
+  return resolve_proxy_helper_.get();
+}
+
 // static
 scoped_refptr<AtomBrowserContext> AtomBrowserContext::From(
     const std::string& partition, bool in_memory,

+ 4 - 0
atom/browser/atom_browser_context.h

@@ -18,6 +18,7 @@ class AtomBlobReader;
 class AtomDownloadManagerDelegate;
 class AtomNetworkDelegate;
 class AtomPermissionManager;
+class ResolveProxyHelper;
 class WebViewManager;
 
 class AtomBrowserContext : public brightray::BrowserContext {
@@ -51,6 +52,8 @@ class AtomBrowserContext : public brightray::BrowserContext {
   // brightray::BrowserContext:
   void RegisterPrefs(PrefRegistrySimple* pref_registry) override;
 
+  ResolveProxyHelper* GetResolveProxyHelper();
+
   AtomBlobReader* GetBlobReader();
   AtomCookieDelegate* cookie_delegate() const {
     return cookie_delegate_.get();
@@ -62,6 +65,7 @@ class AtomBrowserContext : public brightray::BrowserContext {
   ~AtomBrowserContext() override;
 
  private:
+  scoped_refptr<ResolveProxyHelper> resolve_proxy_helper_;
   std::unique_ptr<AtomDownloadManagerDelegate> download_manager_delegate_;
   std::unique_ptr<WebViewManager> guest_manager_;
   std::unique_ptr<AtomPermissionManager> permission_manager_;

+ 85 - 0
atom/browser/net/resolve_proxy_helper.cc

@@ -0,0 +1,85 @@
+// 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/resolve_proxy_helper.h"
+
+#include "base/threading/thread_task_runner_handle.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_context_getter.h"
+
+namespace atom {
+
+ResolveProxyHelper::ResolveProxyHelper(net::URLRequestContextGetter* getter)
+    : context_getter_(getter),
+      original_thread_(base::ThreadTaskRunnerHandle::Get()) {}
+
+ResolveProxyHelper::~ResolveProxyHelper() {
+  // Clear all pending requests if the ProxyService is still alive.
+  pending_requests_.clear();
+}
+
+void ResolveProxyHelper::ResolveProxy(const GURL& url,
+                                      const ResolveProxyCallback& callback) {
+  // Enqueue the pending request.
+  pending_requests_.push_back(PendingRequest(url, callback));
+
+  // If nothing is in progress, start.
+  if (pending_requests_.size() == 1)
+    StartPendingRequest();
+}
+
+void ResolveProxyHelper::SendProxyResult(const std::string& proxy) {
+  CHECK(!pending_requests_.empty());
+
+  const auto& completed_request = pending_requests_.front();
+  if (!completed_request.callback.is_null())
+    completed_request.callback.Run(proxy);
+
+  // Clear the current (completed) request.
+  pending_requests_.pop_front();
+
+  // Start the next request.
+  if (!pending_requests_.empty())
+    StartPendingRequest();
+}
+
+void ResolveProxyHelper::StartPendingRequest() {
+  auto& request = pending_requests_.front();
+  context_getter_->GetNetworkTaskRunner()->PostTask(
+      FROM_HERE,
+      base::BindOnce(&ResolveProxyHelper::StartPendingRequestInIO,
+                     base::Unretained(this), request.url, request.pac_req));
+}
+
+void ResolveProxyHelper::OnResolveProxyCompleted(int result) {
+  std::string proxy;
+  if (result == net::OK)
+    proxy = proxy_info_.ToPacString();
+
+  original_thread_->PostTask(
+      FROM_HERE, base::BindOnce(&ResolveProxyHelper::SendProxyResult,
+                                base::Unretained(this), proxy));
+}
+
+void ResolveProxyHelper::StartPendingRequestInIO(
+    const GURL& url,
+    net::ProxyService::PacRequest* pac_req) {
+  // Verify the request wasn't started yet.
+  DCHECK(nullptr == pac_req);
+
+  auto proxy_service = context_getter_->GetURLRequestContext()->proxy_service();
+
+  // Start the request.
+  int result = proxy_service->ResolveProxy(
+      url, std::string(), &proxy_info_,
+      base::Bind(&ResolveProxyHelper::OnResolveProxyCompleted,
+                 base::Unretained(this)),
+      &pac_req, nullptr, net::NetLogWithSource());
+
+  // Completed synchronously.
+  if (result != net::ERR_IO_PENDING)
+    OnResolveProxyCompleted(result);
+}
+
+}  // namespace atom

+ 59 - 0
atom/browser/net/resolve_proxy_helper.h

@@ -0,0 +1,59 @@
+// 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_RESOLVE_PROXY_HELPER_H_
+#define ATOM_BROWSER_NET_RESOLVE_PROXY_HELPER_H_
+
+#include <deque>
+#include <string>
+
+#include "base/memory/ref_counted.h"
+#include "net/proxy/proxy_service.h"
+#include "url/gurl.h"
+
+namespace net {
+class URLRequestContextGetter;
+}
+
+namespace atom {
+
+class ResolveProxyHelper
+    : public base::RefCountedThreadSafe<ResolveProxyHelper> {
+ public:
+  using ResolveProxyCallback = base::Callback<void(std::string)>;
+  explicit ResolveProxyHelper(net::URLRequestContextGetter* getter);
+
+  void ResolveProxy(const GURL& url, const ResolveProxyCallback& callback);
+
+ private:
+  friend class base::RefCountedThreadSafe<ResolveProxyHelper>;
+  struct PendingRequest {
+   public:
+    PendingRequest(const GURL& url, const ResolveProxyCallback& callback)
+        : url(url), callback(callback), pac_req(nullptr) {}
+
+    GURL url;
+    ResolveProxyCallback callback;
+    net::ProxyService::PacRequest* pac_req;
+  };
+
+  ~ResolveProxyHelper();
+
+  void StartPendingRequest();
+  void StartPendingRequestInIO(const GURL& request,
+                               net::ProxyService::PacRequest* pac_req);
+  void SendProxyResult(const std::string& proxy);
+  void OnResolveProxyCompleted(int result);
+
+  net::ProxyInfo proxy_info_;
+  std::deque<PendingRequest> pending_requests_;
+  scoped_refptr<net::URLRequestContextGetter> context_getter_;
+  scoped_refptr<base::SingleThreadTaskRunner> original_thread_;
+
+  DISALLOW_COPY_AND_ASSIGN(ResolveProxyHelper);
+};
+
+}  // namespace atom
+
+#endif  // ATOM_BROWSER_NET_RESOLVE_PROXY_HELPER_H_

+ 34 - 0
atom/utility/atom_content_utility_client.cc

@@ -4,6 +4,13 @@
 
 #include "atom/utility/atom_content_utility_client.h"
 
+#include "content/public/common/service_manager_connection.h"
+#include "content/public/common/simple_connection_filter.h"
+#include "content/public/utility/utility_thread.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "net/proxy/mojo_proxy_resolver_factory_impl.h"
+#include "services/service_manager/public/cpp/binder_registry.h"
+
 #if defined(OS_WIN)
 #include "base/memory/ptr_util.h"
 #include "chrome/utility/printing_handler_win.h"
@@ -11,6 +18,16 @@
 
 namespace atom {
 
+namespace {
+
+void CreateProxyResolverFactory(
+    net::interfaces::ProxyResolverFactoryRequest request) {
+  mojo::MakeStrongBinding(base::MakeUnique<net::MojoProxyResolverFactoryImpl>(),
+                          std::move(request));
+}
+
+}  // namespace
+
 AtomContentUtilityClient::AtomContentUtilityClient() {
 #if defined(OS_WIN)
   handlers_.push_back(base::MakeUnique<printing::PrintingHandlerWin>());
@@ -20,6 +37,23 @@ AtomContentUtilityClient::AtomContentUtilityClient() {
 AtomContentUtilityClient::~AtomContentUtilityClient() {
 }
 
+void AtomContentUtilityClient::UtilityThreadStarted() {
+  content::ServiceManagerConnection* connection =
+      content::ChildThread::Get()->GetServiceManagerConnection();
+
+  // NOTE: Some utility process instances are not connected to the Service
+  // Manager. Nothing left to do in that case.
+  if (!connection)
+    return;
+
+  auto registry = base::MakeUnique<service_manager::BinderRegistry>();
+  registry->AddInterface<net::interfaces::ProxyResolverFactory>(
+      base::Bind(CreateProxyResolverFactory),
+      base::ThreadTaskRunnerHandle::Get());
+  connection->AddConnectionFilter(
+      base::MakeUnique<content::SimpleConnectionFilter>(std::move(registry)));
+}
+
 bool AtomContentUtilityClient::OnMessageReceived(
     const IPC::Message& message) {
 #if defined(OS_WIN)

+ 1 - 0
atom/utility/atom_content_utility_client.h

@@ -20,6 +20,7 @@ class AtomContentUtilityClient : public content::ContentUtilityClient {
   AtomContentUtilityClient();
   ~AtomContentUtilityClient() override;
 
+  void UtilityThreadStarted() override;
   bool OnMessageReceived(const IPC::Message& message) override;
 
  private:

+ 6 - 0
brightray/brightray.gyp

@@ -116,6 +116,8 @@
                   '<(libchromiumcontent_dir)/libcommon.a',
                   # services/device/wake_lock/power_save_blocker/
                   '<(libchromiumcontent_dir)/libpower_save_blocker.a',
+                  # net/proxy/mojo_*
+                  '<(libchromiumcontent_dir)/libnet_proxy_service.a',
                   # Friends of libpdf.a:
                   # On Linux we have to use "--whole-archive" to include
                   # all symbols, otherwise there will be plenty of
@@ -200,6 +202,8 @@
                   '<(libchromiumcontent_dir)/libcommon.a',
                   # services/device/wake_lock/power_save_blocker/
                   '<(libchromiumcontent_dir)/libpower_save_blocker.a',
+                  # net/proxy/mojo_*
+                  '<(libchromiumcontent_dir)/libnet_proxy_service.a',
                   # Friends of libpdf.a:
                   '<(libchromiumcontent_dir)/libpdf.a',
                   '<(libchromiumcontent_dir)/libppapi_cpp_objects.a',
@@ -310,6 +314,8 @@
                   '<(libchromiumcontent_dir)/common.lib',
                   # services/device/wake_lock/power_save_blocker/
                   '<(libchromiumcontent_dir)/power_save_blocker.lib',
+                  # net/proxy/mojo_*
+                  '<(libchromiumcontent_dir)/net_proxy_service.lib',
                   # Friends of pdf.lib:
                   '<(libchromiumcontent_dir)/pdf.lib',
                   '<(libchromiumcontent_dir)/ppapi_cpp_objects.lib',

+ 117 - 0
brightray/browser/net/chrome_mojo_proxy_resolver_factory.cc

@@ -0,0 +1,117 @@
+// Copyright 2015 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 file.
+
+#include "brightray/browser/net/chrome_mojo_proxy_resolver_factory.h"
+
+#include <utility>
+
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/memory/singleton.h"
+#include "base/single_thread_task_runner.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/utility_process_host.h"
+#include "content/public/browser/utility_process_host_client.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
+
+namespace {
+const int kUtilityProcessIdleTimeoutSeconds = 5;
+}
+
+// static
+ChromeMojoProxyResolverFactory* ChromeMojoProxyResolverFactory::GetInstance() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+  return base::Singleton<
+      ChromeMojoProxyResolverFactory,
+      base::LeakySingletonTraits<ChromeMojoProxyResolverFactory>>::get();
+}
+
+ChromeMojoProxyResolverFactory::ChromeMojoProxyResolverFactory() {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+}
+
+ChromeMojoProxyResolverFactory::~ChromeMojoProxyResolverFactory() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+}
+
+std::unique_ptr<base::ScopedClosureRunner>
+ChromeMojoProxyResolverFactory::CreateResolver(
+    const std::string& pac_script,
+    mojo::InterfaceRequest<net::interfaces::ProxyResolver> req,
+    net::interfaces::ProxyResolverFactoryRequestClientPtr client) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  if (!resolver_factory_)
+    CreateFactory();
+
+  if (!resolver_factory_) {
+    // If factory creation failed, close |req|'s message pipe, which should
+    // cause a connection error.
+    req = nullptr;
+    return nullptr;
+  }
+  idle_timer_.Stop();
+  num_proxy_resolvers_++;
+  resolver_factory_->CreateResolver(pac_script, std::move(req),
+                                    std::move(client));
+  return base::MakeUnique<base::ScopedClosureRunner>(
+      base::Bind(&ChromeMojoProxyResolverFactory::OnResolverDestroyed,
+                 base::Unretained(this)));
+}
+
+void ChromeMojoProxyResolverFactory::CreateFactory() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(!resolver_factory_);
+  DCHECK(!weak_utility_process_host_);
+
+  DVLOG(1) << "Attempting to create utility process for proxy resolver";
+  content::UtilityProcessHost* utility_process_host =
+      content::UtilityProcessHost::Create(
+          scoped_refptr<content::UtilityProcessHostClient>(),
+          base::ThreadTaskRunnerHandle::Get());
+  utility_process_host->SetName(base::ASCIIToUTF16("Electron Proxy Resolver"));
+  bool process_started = utility_process_host->Start();
+  if (process_started) {
+    BindInterface(utility_process_host, &resolver_factory_);
+    weak_utility_process_host_ = utility_process_host->AsWeakPtr();
+  } else {
+    LOG(ERROR) << "Unable to connect to utility process";
+    return;
+  }
+
+  resolver_factory_.set_connection_error_handler(base::Bind(
+      &ChromeMojoProxyResolverFactory::DestroyFactory, base::Unretained(this)));
+}
+
+void ChromeMojoProxyResolverFactory::DestroyFactory() {
+  resolver_factory_.reset();
+  delete weak_utility_process_host_.get();
+  weak_utility_process_host_.reset();
+}
+
+void ChromeMojoProxyResolverFactory::OnResolverDestroyed() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_GT(num_proxy_resolvers_, 0u);
+  if (--num_proxy_resolvers_ == 0) {
+    // When all proxy resolvers have been destroyed, the proxy resolver factory
+    // is no longer needed. However, new proxy resolvers may be created
+    // shortly after being destroyed (e.g. due to a network change).
+    //
+    // On desktop, where a utility process is used, if the utility process is
+    // shut down immediately, this would cause unnecessary process churn, so
+    // wait for an idle timeout before shutting down the proxy resolver utility
+    // process.
+    idle_timer_.Start(
+        FROM_HERE,
+        base::TimeDelta::FromSeconds(kUtilityProcessIdleTimeoutSeconds), this,
+        &ChromeMojoProxyResolverFactory::OnIdleTimeout);
+  }
+}
+
+void ChromeMojoProxyResolverFactory::OnIdleTimeout() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_EQ(num_proxy_resolvers_, 0u);
+  DestroyFactory();
+}

+ 73 - 0
brightray/browser/net/chrome_mojo_proxy_resolver_factory.h

@@ -0,0 +1,73 @@
+// Copyright 2015 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 file.
+
+#ifndef BRIGHTRAY_BROWSER_NET_CHROME_MOJO_PROXY_RESOLVER_FACTORY_H_
+#define BRIGHTRAY_BROWSER_NET_CHROME_MOJO_PROXY_RESOLVER_FACTORY_H_
+
+#include <stddef.h>
+#include <string>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
+#include "base/timer/timer.h"
+#include "net/proxy/mojo_proxy_resolver_factory.h"
+
+namespace content {
+class UtilityProcessHost;
+}
+
+namespace base {
+template <typename Type>
+struct DefaultSingletonTraits;
+}  // namespace base
+
+// A factory used to create connections to Mojo proxy resolver services.  On
+// Android, the proxy resolvers will run in the browser process, and on other
+// platforms, they'll all be run in the same utility process. Utility process
+// crashes are detected and the utility process is automatically restarted.
+class ChromeMojoProxyResolverFactory : public net::MojoProxyResolverFactory {
+ public:
+  static ChromeMojoProxyResolverFactory* GetInstance();
+
+  // Overridden from net::MojoProxyResolverFactory:
+  std::unique_ptr<base::ScopedClosureRunner> CreateResolver(
+      const std::string& pac_script,
+      mojo::InterfaceRequest<net::interfaces::ProxyResolver> req,
+      net::interfaces::ProxyResolverFactoryRequestClientPtr client) override;
+
+ private:
+  friend struct base::DefaultSingletonTraits<ChromeMojoProxyResolverFactory>;
+  ChromeMojoProxyResolverFactory();
+  ~ChromeMojoProxyResolverFactory() override;
+
+  // Creates the proxy resolver factory. On desktop, creates a new utility
+  // process before creating it out of process. On Android, creates it on the
+  // current thread.
+  void CreateFactory();
+
+  // Destroys |resolver_factory_|.
+  void DestroyFactory();
+
+  // Invoked each time a proxy resolver is destroyed.
+  void OnResolverDestroyed();
+
+  // Invoked once an idle timeout has elapsed after all proxy resolvers are
+  // destroyed.
+  void OnIdleTimeout();
+
+  net::interfaces::ProxyResolverFactoryPtr resolver_factory_;
+
+  base::WeakPtr<content::UtilityProcessHost> weak_utility_process_host_;
+
+  size_t num_proxy_resolvers_ = 0;
+
+  base::OneShotTimer idle_timer_;
+
+  base::ThreadChecker thread_checker_;
+
+  DISALLOW_COPY_AND_ASSIGN(ChromeMojoProxyResolverFactory);
+};
+
+#endif  // BRIGHTRAY_BROWSER_NET_CHROME_MOJO_PROXY_RESOLVER_FACTORY_H_

+ 8 - 9
brightray/browser/url_request_context_getter.cc

@@ -13,6 +13,7 @@
 #include "base/threading/sequenced_worker_pool.h"
 #include "base/threading/worker_pool.h"
 #include "brightray/browser/browser_client.h"
+#include "brightray/browser/net/chrome_mojo_proxy_resolver_factory.h"
 #include "brightray/browser/net/devtools_network_controller_handle.h"
 #include "brightray/browser/net/devtools_network_transaction_factory.h"
 #include "brightray/browser/net/require_ct_delegate.h"
@@ -41,7 +42,7 @@
 #include "net/proxy/proxy_config_service.h"
 #include "net/proxy/proxy_script_fetcher_impl.h"
 #include "net/proxy/proxy_service.h"
-#include "net/proxy/proxy_service_v8.h"
+#include "net/proxy/proxy_service_mojo.h"
 #include "net/ssl/channel_id_service.h"
 #include "net/ssl/default_channel_id_store.h"
 #include "net/ssl/ssl_config_service_defaults.h"
@@ -229,14 +230,12 @@ net::URLRequestContext* URLRequestContextGetter::GetURLRequestContext() {
       storage_->set_proxy_service(net::ProxyService::CreateFixed(
           proxy_config));
     } else {
-      storage_->set_proxy_service(
-          net::CreateProxyServiceUsingV8ProxyResolver(
-              std::move(proxy_config_service_),
-              new net::ProxyScriptFetcherImpl(url_request_context_.get()),
-              dhcp_factory.Create(url_request_context_.get()),
-              host_resolver.get(),
-              nullptr,
-              url_request_context_->network_delegate()));
+      storage_->set_proxy_service(net::CreateProxyServiceUsingMojoFactory(
+          ChromeMojoProxyResolverFactory::GetInstance(),
+          std::move(proxy_config_service_),
+          new net::ProxyScriptFetcherImpl(url_request_context_.get()),
+          dhcp_factory.Create(url_request_context_.get()), host_resolver.get(),
+          nullptr, url_request_context_->network_delegate()));
     }
 
     std::vector<std::string> schemes;

+ 2 - 0
brightray/filenames.gypi

@@ -63,6 +63,8 @@
       'browser/net/devtools_network_transaction.h',
       'browser/net/devtools_network_upload_data_stream.cc',
       'browser/net/devtools_network_upload_data_stream.h',
+      'browser/net/chrome_mojo_proxy_resolver_factory.cc',
+      'browser/net/chrome_mojo_proxy_resolver_factory.h',
       'browser/net/require_ct_delegate.cc',
       'browser/net/require_ct_delegate.h',
       'browser/net_log.cc',

+ 2 - 0
filenames.gypi

@@ -274,6 +274,8 @@
       'atom/browser/net/http_protocol_handler.h',
       'atom/browser/net/js_asker.cc',
       'atom/browser/net/js_asker.h',
+      'atom/browser/net/resolve_proxy_helper.cc',
+      'atom/browser/net/resolve_proxy_helper.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',

+ 1 - 1
vendor/libchromiumcontent

@@ -1 +1 @@
-Subproject commit 7878d313798820d1539364ecb87da61e14d834d6
+Subproject commit 0f50f5e3b3fff53d53f72eb39293e01083480311