| 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
|
|
|