diff options
author | ericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-12 00:49:38 +0000 |
---|---|---|
committer | ericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-12 00:49:38 +0000 |
commit | 8a00f00ab5d68ffcc998fd04d2ca343af7cdf190 (patch) | |
tree | fd464ba49db4271c76c1cf8f769a22120ad631af /net/proxy/proxy_resolver_v8.cc | |
parent | 77ae132c1bfdd986228b6f1c0d8c63baa441afdf (diff) | |
download | chromium_src-8a00f00ab5d68ffcc998fd04d2ca343af7cdf190.zip chromium_src-8a00f00ab5d68ffcc998fd04d2ca343af7cdf190.tar.gz chromium_src-8a00f00ab5d68ffcc998fd04d2ca343af7cdf190.tar.bz2 |
* Avoid doing concurrent DNS resolves of the same hostname in HostResolver.
* Add a 1 minute cache for host resolves.
* Refactor HostResolver to handle multiple requests.
* Make HostResolver a dependency of URLRequestContext. operate the HostResolver
in async mode for proxy resolver (bridging to IO thread).
TEST=unittests
BUG=13163
Review URL: http://codereview.chromium.org/118100
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18236 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/proxy/proxy_resolver_v8.cc')
-rw-r--r-- | net/proxy/proxy_resolver_v8.cc | 95 |
1 files changed, 82 insertions, 13 deletions
diff --git a/net/proxy/proxy_resolver_v8.cc b/net/proxy/proxy_resolver_v8.cc index a5d1c76..38e0a83 100644 --- a/net/proxy/proxy_resolver_v8.cc +++ b/net/proxy/proxy_resolver_v8.cc @@ -4,7 +4,10 @@ #include "net/proxy/proxy_resolver_v8.h" +#include "base/compiler_specific.h" #include "base/logging.h" +#include "base/message_loop.h" +#include "base/waitable_event.h" #include "base/string_util.h" #include "googleurl/src/gurl.h" #include "net/base/address_list.h" @@ -50,9 +53,78 @@ bool V8ObjectToString(v8::Handle<v8::Value> object, std::string* result) { return true; } +// Wrapper around HostResolver to give a sync API while running the resolve +// in async mode on |host_resolver_loop|. If |host_resolver_loop| is NULL, +// runs sync on the current thread (this mode is just used by testing). +class SyncHostResolverBridge + : public base::RefCountedThreadSafe<SyncHostResolverBridge> { + public: + SyncHostResolverBridge(HostResolver* host_resolver, + MessageLoop* host_resolver_loop) + : host_resolver_(host_resolver), + host_resolver_loop_(host_resolver_loop), + event_(false, false), + ALLOW_THIS_IN_INITIALIZER_LIST( + callback_(this, &SyncHostResolverBridge::OnResolveCompletion)) { + } + + // Run the resolve on host_resolver_loop, and wait for result. + int Resolve(const std::string& hostname, net::AddressList* addresses) { + int kPort = 80; // Doesn't matter. + + // Hack for tests -- run synchronously on current thread. + if (!host_resolver_loop_) + return host_resolver_->Resolve(hostname, kPort, addresses, NULL, NULL); + + // Otherwise start an async resolve on the resolver's thread. + host_resolver_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, + &SyncHostResolverBridge::StartResolve, hostname, kPort, addresses)); + + // Wait for the resolve to complete in the resolver's thread. + event_.Wait(); + return err_; + } + + private: + // Called on host_resolver_loop_. + void StartResolve(const std::string& hostname, + int port, + net::AddressList* addresses) { + DCHECK_EQ(host_resolver_loop_, MessageLoop::current()); + int error = host_resolver_->Resolve( + hostname, port, addresses, &callback_, NULL); + if (error != ERR_IO_PENDING) + OnResolveCompletion(error); // Completed synchronously. + } + + // Called on host_resolver_loop_. + void OnResolveCompletion(int result) { + DCHECK_EQ(host_resolver_loop_, MessageLoop::current()); + err_ = result; + event_.Signal(); + } + + HostResolver* host_resolver_; + MessageLoop* host_resolver_loop_; + + // Event to notify completion of resolve request. + base::WaitableEvent event_; + + // Callback for when the resolve completes on host_resolver_loop_. + net::CompletionCallbackImpl<SyncHostResolverBridge> callback_; + + // The result from the result request (set by in host_resolver_loop_). + int err_; +}; + // JSBIndings implementation. class DefaultJSBindings : public ProxyResolverV8::JSBindings { public: + DefaultJSBindings(HostResolver* host_resolver, + MessageLoop* host_resolver_loop) + : host_resolver_(new SyncHostResolverBridge( + host_resolver, host_resolver_loop)) {} + // Handler for "alert(message)". virtual void Alert(const std::string& message) { LOG(INFO) << "PAC-alert: " << message; @@ -71,10 +143,9 @@ class DefaultJSBindings : public ProxyResolverV8::JSBindings { if (host.empty()) return std::string(); - // Try to resolve synchronously. + // Do a sync resolve of the hostname. net::AddressList address_list; - const int kPort = 80; // Doesn't matter what this is. - int result = host_resolver_.Resolve(host, kPort, &address_list, NULL); + int result = host_resolver_->Resolve(host, &address_list); if (result != OK) return std::string(); // Failed. @@ -96,7 +167,7 @@ class DefaultJSBindings : public ProxyResolverV8::JSBindings { } private: - HostResolver host_resolver_; + scoped_refptr<SyncHostResolverBridge> host_resolver_; }; } // namespace @@ -106,7 +177,7 @@ class DefaultJSBindings : public ProxyResolverV8::JSBindings { class ProxyResolverV8::Context { public: Context(JSBindings* js_bindings, const std::string& pac_data) - : js_bindings_(js_bindings) { + : js_bindings_(js_bindings) { DCHECK(js_bindings != NULL); InitV8(pac_data); } @@ -266,20 +337,12 @@ class ProxyResolverV8::Context { } JSBindings* js_bindings_; - HostResolver host_resolver_; v8::Persistent<v8::External> v8_this_; v8::Persistent<v8::Context> v8_context_; }; // ProxyResolverV8 ------------------------------------------------------------ -// the |false| argument to ProxyResolver means the ProxyService will handle -// downloading of the PAC script, and notify changes through SetPacScript(). -ProxyResolverV8::ProxyResolverV8() - : ProxyResolver(false /*does_fetch*/), - js_bindings_(new DefaultJSBindings()) { -} - ProxyResolverV8::ProxyResolverV8( ProxyResolverV8::JSBindings* custom_js_bindings) : ProxyResolver(false), js_bindings_(custom_js_bindings) { @@ -305,4 +368,10 @@ void ProxyResolverV8::SetPacScript(const std::string& data) { context_.reset(new Context(js_bindings_.get(), data)); } +// static +ProxyResolverV8::JSBindings* ProxyResolverV8::CreateDefaultBindings( + HostResolver* host_resolver, MessageLoop* host_resolver_loop) { + return new DefaultJSBindings(host_resolver, host_resolver_loop); +} + } // namespace net |