Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(363)

Unified Diff: net/proxy/proxy_resolver_v8.cc

Issue 118100: Avoid doing concurrent DNS resolves of the same hostname (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Get compiling on mac Created 11 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/proxy/proxy_resolver_v8.cc
===================================================================
--- net/proxy/proxy_resolver_v8.cc (revision 18213)
+++ net/proxy/proxy_resolver_v8.cc (working copy)
@@ -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 @@
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 @@
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 @@
}
private:
- HostResolver host_resolver_;
+ scoped_refptr<SyncHostResolverBridge> host_resolver_;
};
} // namespace
@@ -106,7 +177,7 @@
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 @@
}
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 @@
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

Powered by Google App Engine
This is Rietveld 408576698