summaryrefslogtreecommitdiffstats
path: root/net/proxy/proxy_resolver_js_bindings.cc
diff options
context:
space:
mode:
Diffstat (limited to 'net/proxy/proxy_resolver_js_bindings.cc')
-rw-r--r--net/proxy/proxy_resolver_js_bindings.cc143
1 files changed, 143 insertions, 0 deletions
diff --git a/net/proxy/proxy_resolver_js_bindings.cc b/net/proxy/proxy_resolver_js_bindings.cc
new file mode 100644
index 0000000..6787b1b
--- /dev/null
+++ b/net/proxy/proxy_resolver_js_bindings.cc
@@ -0,0 +1,143 @@
+// Copyright (c) 2009 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 "net/proxy/proxy_resolver_js_bindings.h"
+
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/waitable_event.h"
+#include "net/base/address_list.h"
+#include "net/base/host_resolver.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_util.h"
+
+namespace net {
+namespace {
+
+// 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) {
+ // Port number doesn't matter.
+ HostResolver::RequestInfo info(hostname, 80);
+
+ // Hack for tests -- run synchronously on current thread.
+ if (!host_resolver_loop_)
+ return host_resolver_->Resolve(info, addresses, NULL, NULL);
+
+ // Otherwise start an async resolve on the resolver's thread.
+ host_resolver_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
+ &SyncHostResolverBridge::StartResolve, info, 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 HostResolver::RequestInfo& info,
+ net::AddressList* addresses) {
+ DCHECK_EQ(host_resolver_loop_, MessageLoop::current());
+ int error = host_resolver_->Resolve(info, 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();
+ }
+
+ scoped_refptr<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_;
+};
+
+// ProxyResolverJSBindings implementation.
+class DefaultJSBindings : public ProxyResolverJSBindings {
+ 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;
+ }
+
+ // Handler for "myIpAddress()". Returns empty string on failure.
+ virtual std::string MyIpAddress() {
+ // DnsResolve("") returns "", so no need to check for failure.
+ return DnsResolve(GetHostName());
+ }
+
+ // Handler for "dnsResolve(host)". Returns empty string on failure.
+ virtual std::string DnsResolve(const std::string& host) {
+ // TODO(eroman): Should this return our IP address, or fail, or
+ // simply be unspecified (works differently on windows and mac os x).
+ if (host.empty())
+ return std::string();
+
+ // Do a sync resolve of the hostname.
+ net::AddressList address_list;
+ int result = host_resolver_->Resolve(host, &address_list);
+
+ if (result != OK)
+ return std::string(); // Failed.
+
+ if (!address_list.head())
+ return std::string();
+
+ // There may be multiple results; we will just use the first one.
+ // This returns empty string on failure.
+ return net::NetAddressToString(address_list.head());
+ }
+
+ // Handler for when an error is encountered. |line_number| may be -1.
+ virtual void OnError(int line_number, const std::string& message) {
+ if (line_number == -1)
+ LOG(INFO) << "PAC-error: " << message;
+ else
+ LOG(INFO) << "PAC-error: " << "line: " << line_number << ": " << message;
+ }
+
+ private:
+ scoped_refptr<SyncHostResolverBridge> host_resolver_;
+};
+
+} // namespace
+
+// static
+ProxyResolverJSBindings* ProxyResolverJSBindings::CreateDefault(
+ HostResolver* host_resolver, MessageLoop* host_resolver_loop) {
+ return new DefaultJSBindings(host_resolver, host_resolver_loop);
+}
+
+} // namespace net