Browse Source

REVIEW: create proxy helper per browser context

deepak1556 6 years ago
parent
commit
d6d2a46821

+ 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);

+ 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

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

@@ -0,0 +1,58 @@
+// 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 "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_

+ 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',