summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-26 23:51:28 +0000
committereroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-26 23:51:28 +0000
commit21f20c8940b8b9f06b04ff142716201a2530f0a3 (patch)
treed68fcccc003b0c7edb4ce7620f2270fb608d4022
parent13d54f79c040c2e6beeed94e096d1fcf2b0f7101 (diff)
downloadchromium_src-21f20c8940b8b9f06b04ff142716201a2530f0a3.zip
chromium_src-21f20c8940b8b9f06b04ff142716201a2530f0a3.tar.gz
chromium_src-21f20c8940b8b9f06b04ff142716201a2530f0a3.tar.bz2
Add three of the six extensions to PAC that Internet Explorer supports.
The following descriptions were taken from <http://blogs.msdn.com/wndp/articles/IPV6_PAC_Extensions_v0_9.aspx> ---------------------------- * myIpAddressEx(): Returns a semi-colon delimited string containing all IP addresses for localhost (IPv6 and/or IPv4), or an empty string if unable to resolve localhost to an IP address. * dnsResolveEx(host): Returns semi-colon delimited string containing IPv6 and IPv4 addresses or an empty string if host is not resolvable. * isResolvableEx(): Returns TRUE if the host is resolvable to a IPv4 or IPv6 address, FALSE otherwise. ---------------------------- These differ from the vanilla PAC functions in the following ways: * myIpAddressEx() returns all the addrsses for localhost (including IPv6 ones), whereas myIpAddress() only returns the first IPv4 one. * On failure, myIpAddress() returns "127.0.0.1" whereas on failure myIpAddressEx() returns empty string. * dnsResolveEx() returns a list of addresses (including IPV6 ones), whereas dnsResolve() only returns the first IPv4 address. * On failure, dnsResolve() returns |null|, whereas on failure dnsResolveEx() returns empty string. BUG=25407 TEST=ProxyResolverV8Test.DNSResolutionFailure, ProxyResolverJSBindingsTest.RestrictAddressFamily, ProxyResolverJSBindingsTest.ExFunctionsReturnList Review URL: http://codereview.chromium.org/333006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@30127 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--net/base/load_log_event_type_list.h6
-rw-r--r--net/data/proxy_resolver_v8_unittest/bindings.js9
-rw-r--r--net/data/proxy_resolver_v8_unittest/dns_fail.js27
-rw-r--r--net/proxy/proxy_resolver_js_bindings.cc50
-rw-r--r--net/proxy/proxy_resolver_js_bindings.h12
-rw-r--r--net/proxy/proxy_resolver_js_bindings_unittest.cc120
-rw-r--r--net/proxy/proxy_resolver_script.h10
-rw-r--r--net/proxy/proxy_resolver_v8.cc108
-rw-r--r--net/proxy/proxy_resolver_v8_unittest.cc41
9 files changed, 363 insertions, 20 deletions
diff --git a/net/base/load_log_event_type_list.h b/net/base/load_log_event_type_list.h
index cd01931..3639003 100644
--- a/net/base/load_log_event_type_list.h
+++ b/net/base/load_log_event_type_list.h
@@ -67,9 +67,15 @@ EVENT_TYPE(PROXY_SERVICE_WAITING_FOR_INIT_PAC)
// Measures the time taken to execute the "myIpAddress()" javascript binding.
EVENT_TYPE(PROXY_RESOLVER_V8_MY_IP_ADDRESS)
+// Measures the time taken to execute the "myIpAddressEx()" javascript binding.
+EVENT_TYPE(PROXY_RESOLVER_V8_MY_IP_ADDRESS_EX)
+
// Measures the time taken to execute the "dnsResolve()" javascript binding.
EVENT_TYPE(PROXY_RESOLVER_V8_DNS_RESOLVE)
+// Measures the time taken to execute the "dnsResolveEx()" javascript binding.
+EVENT_TYPE(PROXY_RESOLVER_V8_DNS_RESOLVE_EX)
+
// ------------------------------------------------------------------------
// ClientSocketPoolBase::ConnectJob
// ------------------------------------------------------------------------
diff --git a/net/data/proxy_resolver_v8_unittest/bindings.js b/net/data/proxy_resolver_v8_unittest/bindings.js
index 0e748c1..3026569 100644
--- a/net/data/proxy_resolver_v8_unittest/bindings.js
+++ b/net/data/proxy_resolver_v8_unittest/bindings.js
@@ -35,10 +35,17 @@ function FindProxyForURL(url, host) {
alert(e);
}
- // Call myIpAddress() with wonky arguments
+ // Call myIpAddress() with wonky arguments
myIpAddress(null);
myIpAddress(null, null);
+ // Call myIpAddressEx() correctly (no arguments).
+ myIpAddressEx();
+
+ // Call dnsResolveEx() (note that isResolvableEx() implicity calls it.)
+ isResolvableEx("is_resolvable");
+ dnsResolveEx("foobar");
+
return "DIRECT";
}
diff --git a/net/data/proxy_resolver_v8_unittest/dns_fail.js b/net/data/proxy_resolver_v8_unittest/dns_fail.js
new file mode 100644
index 0000000..c71bcc3
--- /dev/null
+++ b/net/data/proxy_resolver_v8_unittest/dns_fail.js
@@ -0,0 +1,27 @@
+// This script should be run in an environment where all DNS resolution are
+// failing. It tests that functions return the expected values.
+//
+// Returns "PROXY success:80" on success.
+function FindProxyForURL(url, host) {
+ try {
+ expectEq("127.0.0.1", myIpAddress());
+ expectEq("", myIpAddressEx());
+
+ expectEq(null, dnsResolve("not-found"));
+ expectEq("", dnsResolveEx("not-found"));
+
+ expectEq(false, isResolvable("not-found"));
+ expectEq(false, isResolvableEx("not-found"));
+
+ return "PROXY success:80";
+ } catch(e) {
+ alert(e);
+ return "PROXY failed:80";
+ }
+}
+
+function expectEq(expected, actual) {
+ if (expected != actual)
+ throw "Expected " + expected + " but was " + actual;
+}
+
diff --git a/net/proxy/proxy_resolver_js_bindings.cc b/net/proxy/proxy_resolver_js_bindings.cc
index f9ea5ae..077e5c6 100644
--- a/net/proxy/proxy_resolver_js_bindings.cc
+++ b/net/proxy/proxy_resolver_js_bindings.cc
@@ -2,6 +2,14 @@
// source code is governed by a BSD-style license that can be found in the
// LICENSE file.
+#include "build/build_config.h"
+
+#if defined(OS_WIN)
+#include <ws2tcpip.h>
+#else
+#include <netdb.h>
+#endif
+
#include "net/proxy/proxy_resolver_js_bindings.h"
#include "base/compiler_specific.h"
@@ -97,21 +105,24 @@ class DefaultJSBindings : public ProxyResolverJSBindings {
}
// Handler for "myIpAddress()". Returns empty string on failure.
+ // TODO(eroman): Perhaps enumerate the interfaces directly, using
+ // getifaddrs().
virtual std::string MyIpAddress() {
// DnsResolve("") returns "", so no need to check for failure.
return DnsResolve(GetHostName());
}
+ // Handler for "myIpAddressEx()". Returns empty string on failure.
+ virtual std::string MyIpAddressEx() {
+ return DnsResolveEx(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.
- // Disable IPv6 results. We do this because Internet Explorer does it --
- // consequently a lot of existing PAC scripts assume they will only get
+ // Disable IPv6 results. We do this because the PAC specification isn't
+ // really IPv6 friendly, and Internet Explorer also restricts to IPv4.
+ // Consequently a lot of existing PAC scripts assume they will only get
// IPv4 results, and will misbehave if they get an IPv6 result.
// See http://crbug.com/24641 for more details.
net::AddressList address_list;
@@ -130,6 +141,31 @@ class DefaultJSBindings : public ProxyResolverJSBindings {
return net::NetAddressToString(address_list.head());
}
+ // Handler for "dnsResolveEx(host)". Returns empty string on failure.
+ virtual std::string DnsResolveEx(const std::string& host) {
+ // Do a sync resolve of the hostname.
+ net::AddressList address_list;
+ int result = host_resolver_->Resolve(host,
+ ADDRESS_FAMILY_UNSPECIFIED,
+ &address_list);
+
+ if (result != OK)
+ return std::string(); // Failed.
+
+ // Stringify all of the addresses in the address list, separated
+ // by semicolons.
+ std::string address_list_str;
+ const struct addrinfo* current_address = address_list.head();
+ while (current_address) {
+ if (!address_list_str.empty())
+ address_list_str += ";";
+ address_list_str += net::NetAddressToString(current_address);
+ current_address = current_address->ai_next;
+ }
+
+ return address_list_str;
+ }
+
// 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)
diff --git a/net/proxy/proxy_resolver_js_bindings.h b/net/proxy/proxy_resolver_js_bindings.h
index 6eff69d..03ad61a 100644
--- a/net/proxy/proxy_resolver_js_bindings.h
+++ b/net/proxy/proxy_resolver_js_bindings.h
@@ -24,9 +24,21 @@ class ProxyResolverJSBindings {
// Handler for "myIpAddress()". Returns empty string on failure.
virtual std::string MyIpAddress() = 0;
+ // Handler for "myIpAddressEx()". Returns empty string on failure.
+ //
+ // This is a Microsoft extension to PAC for IPv6, see:
+ // http://blogs.msdn.com/wndp/articles/IPV6_PAC_Extensions_v0_9.aspx
+ virtual std::string MyIpAddressEx() = 0;
+
// Handler for "dnsResolve(host)". Returns empty string on failure.
virtual std::string DnsResolve(const std::string& host) = 0;
+ // Handler for "dnsResolveEx(host)". Returns empty string on failure.
+ //
+ // This is a Microsoft extension to PAC for IPv6, see:
+ // http://blogs.msdn.com/wndp/articles/IPV6_PAC_Extensions_v0_9.aspx
+ virtual std::string DnsResolveEx(const std::string& host) = 0;
+
// Handler for when an error is encountered. |line_number| may be -1
// if a line number is not applicable to this error.
virtual void OnError(int line_number, const std::string& error) = 0;
diff --git a/net/proxy/proxy_resolver_js_bindings_unittest.cc b/net/proxy/proxy_resolver_js_bindings_unittest.cc
index b84c829..4e0f6a6 100644
--- a/net/proxy/proxy_resolver_js_bindings_unittest.cc
+++ b/net/proxy/proxy_resolver_js_bindings_unittest.cc
@@ -2,7 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "build/build_config.h"
+
+#if defined(OS_WIN)
+#include <ws2tcpip.h>
+#else
+#include <netdb.h>
+#endif
+
#include "base/scoped_ptr.h"
+#include "net/base/address_list.h"
#include "net/base/mock_host_resolver.h"
#include "net/base/net_errors.h"
#include "net/base/net_util.h"
@@ -12,6 +21,67 @@
namespace net {
namespace {
+// This is a HostResolver that synchronously resolves all hosts to the
+// following address list of length 3:
+// 192.168.1.1
+// 172.22.34.1
+// 200.100.1.2
+class MockHostResolverWithMultipleResults : public HostResolver {
+ public:
+ // HostResolver methods:
+ virtual int Resolve(const RequestInfo& info,
+ AddressList* addresses,
+ CompletionCallback* callback,
+ RequestHandle* out_req,
+ LoadLog* load_log) {
+ // Build up the result list (in reverse).
+ AddressList temp_list = ResolveIPLiteral("200.100.1.2");
+ temp_list = PrependAddressToList("172.22.34.1", temp_list);
+ temp_list = PrependAddressToList("192.168.1.1", temp_list);
+ *addresses = temp_list;
+ return OK;
+ }
+ virtual void CancelRequest(RequestHandle req) {}
+ virtual void AddObserver(Observer* observer) {}
+ virtual void RemoveObserver(Observer* observer) {}
+ virtual HostCache* GetHostCache() { return NULL; }
+ virtual void Shutdown() {}
+
+ private:
+ // Resolves an IP literal to an address list.
+ AddressList ResolveIPLiteral(const char* ip_literal) {
+ AddressList result;
+ int rv = SystemHostResolverProc(ip_literal,
+ ADDRESS_FAMILY_UNSPECIFIED,
+ &result);
+ EXPECT_EQ(OK, rv);
+ EXPECT_EQ(NULL, result.head()->ai_next);
+ return result;
+ }
+
+ // Builds an AddressList that is |ip_literal| + |address_list|.
+ // |orig_list| must not be empty.
+ AddressList PrependAddressToList(const char* ip_literal,
+ const AddressList& orig_list) {
+ // Build an addrinfo for |ip_literal|.
+ AddressList result = ResolveIPLiteral(ip_literal);
+
+ struct addrinfo* result_head = const_cast<struct addrinfo*>(result.head());
+
+ // Temporarily append |orig_list| to |result|.
+ result_head->ai_next = const_cast<struct addrinfo*>(orig_list.head());
+
+ // Make a copy of the concatenated list.
+ AddressList concatenated;
+ concatenated.Copy(result.head());
+
+ // Restore |result| (so it is freed properly).
+ result_head->ai_next = NULL;
+
+ return concatenated;
+ }
+};
+
TEST(ProxyResolverJSBindingsTest, DnsResolve) {
scoped_refptr<MockHostResolver> host_resolver(new MockHostResolver);
@@ -21,6 +91,7 @@ TEST(ProxyResolverJSBindingsTest, DnsResolve) {
// Empty string is not considered a valid host (even though on some systems
// requesting this will resolve to localhost).
+ host_resolver->rules()->AddSimulatedFailure("");
EXPECT_EQ("", bindings->DnsResolve(""));
// Should call through to the HostResolver.
@@ -48,10 +119,19 @@ TEST(ProxyResolverJSBindingsTest, MyIpAddress) {
EXPECT_EQ("127.0.0.1", my_ip_address);
}
-// Tests that myIpAddress() and dnsResolve() pass the flag
-// ADDRESS_FAMILY_IPV4 to the host resolver, as we don't want them
-// to return IPv6 results.
-TEST(ProxyResolverJSBindingsTest, DontUseIPv6) {
+// Tests that the regular PAC functions restrict results to IPv4,
+// but that the Microsoft extensions to PAC do not. We test this
+// by seeing whether ADDRESS_FAMILY_IPV4 or ADDRESS_FAMILY_UNSPECIFIED
+// was passed into to the host resolver.
+//
+// Restricted to IPv4 address family:
+// myIpAddress()
+// dnsResolve()
+//
+// Unrestricted address family:
+// myIpAddressEx()
+// dnsResolveEx()
+TEST(ProxyResolverJSBindingsTest, RestrictAddressFamily) {
scoped_refptr<MockHostResolver> host_resolver(new MockHostResolver);
// Get a hold of a DefaultJSBindings* (it is a hidden impl class).
@@ -67,7 +147,9 @@ TEST(ProxyResolverJSBindingsTest, DontUseIPv6) {
host_resolver->rules()->AddRuleForAddressFamily(
"*", ADDRESS_FAMILY_IPV4, "192.168.1.2");
host_resolver->rules()->AddRuleForAddressFamily(
- "*", ADDRESS_FAMILY_UNSPECIFIED, "192.168.2.1");
+ "foo", ADDRESS_FAMILY_UNSPECIFIED, "192.168.2.1");
+ host_resolver->rules()->AddRuleForAddressFamily(
+ "*", ADDRESS_FAMILY_UNSPECIFIED, "192.168.2.2");
// Verify that our mock setups works as expected, and we get different results
// depending if the address family was IPV4_ONLY or not.
@@ -81,9 +163,31 @@ TEST(ProxyResolverJSBindingsTest, DontUseIPv6) {
EXPECT_EQ("192.168.1.1", NetAddressToString(address_list.head()));
// Now the actual test.
- EXPECT_EQ("192.168.1.2", bindings->MyIpAddress());
- EXPECT_EQ("192.168.1.1", bindings->DnsResolve("foo"));
- EXPECT_EQ("192.168.1.2", bindings->DnsResolve("foo2"));
+ EXPECT_EQ("192.168.1.2", bindings->MyIpAddress()); // IPv4 restricted.
+ EXPECT_EQ("192.168.1.1", bindings->DnsResolve("foo")); // IPv4 restricted.
+ EXPECT_EQ("192.168.1.2", bindings->DnsResolve("foo2")); // IPv4 restricted.
+
+ EXPECT_EQ("192.168.2.2", bindings->MyIpAddressEx()); // Unrestricted.
+ EXPECT_EQ("192.168.2.1", bindings->DnsResolveEx("foo")); // Unrestricted.
+ EXPECT_EQ("192.168.2.2", bindings->DnsResolveEx("foo2")); // Unrestricted.
+}
+
+// Test that myIpAddressEx() and dnsResolveEx() both return a semi-colon
+// separated list of addresses (as opposed to the non-Ex versions which
+// just return the first result).
+TEST(ProxyResolverJSBindingsTest, ExFunctionsReturnList) {
+ scoped_refptr<HostResolver> host_resolver(
+ new MockHostResolverWithMultipleResults);
+
+ // Get a hold of a DefaultJSBindings* (it is a hidden impl class).
+ scoped_ptr<ProxyResolverJSBindings> bindings(
+ ProxyResolverJSBindings::CreateDefault(host_resolver, NULL));
+
+ EXPECT_EQ("192.168.1.1;172.22.34.1;200.100.1.2",
+ bindings->MyIpAddressEx());
+
+ EXPECT_EQ("192.168.1.1;172.22.34.1;200.100.1.2",
+ bindings->DnsResolveEx("FOO"));
}
} // namespace
diff --git a/net/proxy/proxy_resolver_script.h b/net/proxy/proxy_resolver_script.h
index be592e4..a872cba 100644
--- a/net/proxy/proxy_resolver_script.h
+++ b/net/proxy/proxy_resolver_script.h
@@ -263,6 +263,14 @@
" date.setSeconds(date.getUTCSeconds());\n" \
" }\n" \
" return ((date1 <= date) && (date <= date2));\n" \
- "}\n" \
+ "}\n"
+
+// This is a Microsoft extension to PAC for IPv6, see:
+// http://blogs.msdn.com/wndp/articles/IPV6_PAC_Extensions_v0_9.aspx
+#define PROXY_RESOLVER_SCRIPT_EX \
+ "function isResolvableEx(host) {\n" \
+ " var ipList = dnsResolveEx(host);\n" \
+ " return (ipList != '');\n" \
+ "}\n"
#endif // NET_PROXY_PROXY_RESOLVER_SCRIPT_H_
diff --git a/net/proxy/proxy_resolver_v8.cc b/net/proxy/proxy_resolver_v8.cc
index 7fd00bd..4db6bc3 100644
--- a/net/proxy/proxy_resolver_v8.cc
+++ b/net/proxy/proxy_resolver_v8.cc
@@ -14,6 +14,51 @@
#include "net/proxy/proxy_resolver_script.h"
#include "v8/include/v8.h"
+// Notes on the javascript environment:
+//
+// For the majority of the PAC utility functions, we use the same code
+// as Firefox. See the javascript library that proxy_resolver_scipt.h
+// pulls in.
+//
+// In addition, we implement a subset of Microsoft's extensions to PAC.
+// TODO(eroman): Implement the rest.
+//
+// - myIpAddressEx()
+// - dnsResolveEx()
+// - isResolvableEx()
+//
+// It is worth noting that the original PAC specification does not describe
+// the return values on failure. Consequently, there are compatibility
+// differences between browsers on what to return on failure, which are
+// illustrated below:
+//
+// ----------------+-------------+-------------------+--------------
+// | Firefox3 | InternetExplorer8 | --> Us <---
+// ----------------+-------------+-------------------+--------------
+// myIpAddress() | "127.0.0.1" | ??? | "127.0.0.1"
+// dnsResolve() | null | false | null
+// myIpAddressEx() | N/A | "" | ""
+// dnsResolveEx() | N/A | "" | ""
+// ----------------+-------------+-------------------+--------------
+//
+// TODO(eroman): The cell above reading ??? means I didn't test it.
+//
+// Another difference is in how dnsResolve() and myIpAddress() are
+// implemented -- whether they should restrict to IPv4 results, or
+// include both IPv4 and IPv6. The following table illustrates the
+// differences:
+//
+// -----------------+-------------+-------------------+--------------
+// | Firefox3 | InternetExplorer8 | --> Us <---
+// -----------------+-------------+-------------------+--------------
+// myIpAddress() | IPv4/IPv6 | IPv4 | IPv4
+// dnsResolve() | IPv4/IPv6 | IPv4 | IPv4
+// isResolvable() | IPv4/IPv6 | IPv4 | IPv4
+// myIpAddressEx() | N/A | IPv4/IPv6 | IPv4/IPv6
+// dnsResolveEx() | N/A | IPv4/IPv6 | IPv4/IPv6
+// isResolvableEx() | N/A | IPv4/IPv6 | IPv4/IPv6
+// -----------------+-------------+-------------------+--------------
+
namespace net {
namespace {
@@ -128,13 +173,28 @@ class ProxyResolverV8::Context {
global_template->Set(v8::String::New("dnsResolve"),
dns_resolve_template);
+ // Microsoft's PAC extensions (incomplete):
+
+ v8::Local<v8::FunctionTemplate> dns_resolve_ex_template =
+ v8::FunctionTemplate::New(&DnsResolveExCallback, v8_this_);
+ global_template->Set(v8::String::New("dnsResolveEx"),
+ dns_resolve_ex_template);
+
+ v8::Local<v8::FunctionTemplate> my_ip_address_ex_template =
+ v8::FunctionTemplate::New(&MyIpAddressExCallback, v8_this_);
+ global_template->Set(v8::String::New("myIpAddressEx"),
+ my_ip_address_ex_template);
+
v8_context_ = v8::Context::New(NULL, global_template);
v8::Context::Scope ctx(v8_context_);
// Add the PAC utility functions to the environment.
// (This script should never fail, as it is a string literal!)
- int rv = RunScript(PROXY_RESOLVER_SCRIPT, kPacUtilityResourceName);
+ // Note that the two string literals are concatenated.
+ int rv = RunScript(PROXY_RESOLVER_SCRIPT
+ PROXY_RESOLVER_SCRIPT_EX,
+ kPacUtilityResourceName);
if (rv != OK) {
NOTREACHED();
return rv;
@@ -248,6 +308,25 @@ class ProxyResolverV8::Context {
return StdStringToV8String(result);
}
+ // V8 callback for when "myIpAddressEx()" is invoked by the PAC script.
+ static v8::Handle<v8::Value> MyIpAddressExCallback(
+ const v8::Arguments& args) {
+ Context* context =
+ static_cast<Context*>(v8::External::Cast(*args.Data())->Value());
+
+ LoadLog::BeginEvent(context->current_request_load_log_,
+ LoadLog::TYPE_PROXY_RESOLVER_V8_MY_IP_ADDRESS_EX);
+
+ // We shouldn't be called with any arguments, but will not complain if
+ // we are.
+ std::string result = context->js_bindings_->MyIpAddressEx();
+
+ LoadLog::EndEvent(context->current_request_load_log_,
+ LoadLog::TYPE_PROXY_RESOLVER_V8_MY_IP_ADDRESS_EX);
+
+ return StdStringToV8String(result);
+ }
+
// V8 callback for when "dnsResolve()" is invoked by the PAC script.
static v8::Handle<v8::Value> DnsResolveCallback(const v8::Arguments& args) {
Context* context =
@@ -270,10 +349,35 @@ class ProxyResolverV8::Context {
LoadLog::EndEvent(context->current_request_load_log_,
LoadLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE);
- // DoDnsResolve() returns empty string on failure.
+ // DnsResolve() returns empty string on failure.
return result.empty() ? v8::Null() : StdStringToV8String(result);
}
+ // V8 callback for when "dnsResolveEx()" is invoked by the PAC script.
+ static v8::Handle<v8::Value> DnsResolveExCallback(const v8::Arguments& args) {
+ Context* context =
+ static_cast<Context*>(v8::External::Cast(*args.Data())->Value());
+
+ // We need at least one argument.
+ std::string host;
+ if (args.Length() == 0) {
+ host = "undefined";
+ } else {
+ if (!V8ObjectToString(args[0], &host))
+ return v8::Undefined();
+ }
+
+ LoadLog::BeginEvent(context->current_request_load_log_,
+ LoadLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE_EX);
+
+ std::string result = context->js_bindings_->DnsResolveEx(host);
+
+ LoadLog::EndEvent(context->current_request_load_log_,
+ LoadLog::TYPE_PROXY_RESOLVER_V8_DNS_RESOLVE_EX);
+
+ return StdStringToV8String(result);
+ }
+
ProxyResolverJSBindings* js_bindings_;
LoadLog* current_request_load_log_;
v8::Persistent<v8::External> v8_this_;
diff --git a/net/proxy/proxy_resolver_v8_unittest.cc b/net/proxy/proxy_resolver_v8_unittest.cc
index c172093..550426a 100644
--- a/net/proxy/proxy_resolver_v8_unittest.cc
+++ b/net/proxy/proxy_resolver_v8_unittest.cc
@@ -21,7 +21,7 @@ namespace {
// list, for later verification.
class MockJSBindings : public ProxyResolverJSBindings {
public:
- MockJSBindings() : my_ip_address_count(0) {}
+ MockJSBindings() : my_ip_address_count(0), my_ip_address_ex_count(0) {}
virtual void Alert(const std::string& message) {
LOG(INFO) << "PAC-alert: " << message; // Helpful when debugging.
@@ -33,11 +33,21 @@ class MockJSBindings : public ProxyResolverJSBindings {
return my_ip_address_result;
}
+ virtual std::string MyIpAddressEx() {
+ my_ip_address_ex_count++;
+ return my_ip_address_ex_result;
+ }
+
virtual std::string DnsResolve(const std::string& host) {
dns_resolves.push_back(host);
return dns_resolve_result;
}
+ virtual std::string DnsResolveEx(const std::string& host) {
+ dns_resolves_ex.push_back(host);
+ return dns_resolve_ex_result;
+ }
+
virtual void OnError(int line_number, const std::string& message) {
// Helpful when debugging.
LOG(INFO) << "PAC-error: [" << line_number << "] " << message;
@@ -48,14 +58,18 @@ class MockJSBindings : public ProxyResolverJSBindings {
// Mock values to return.
std::string my_ip_address_result;
+ std::string my_ip_address_ex_result;
std::string dns_resolve_result;
+ std::string dns_resolve_ex_result;
// Inputs we got called with.
std::vector<std::string> alerts;
std::vector<std::string> errors;
std::vector<int> errors_line_number;
std::vector<std::string> dns_resolves;
+ std::vector<std::string> dns_resolves_ex;
int my_ip_address_count;
+ int my_ip_address_ex_count;
};
// This is the same as ProxyResolverV8, but it uses mock bindings in place of
@@ -391,6 +405,14 @@ TEST(ProxyResolverV8Test, V8Bindings) {
// MyIpAddress was called two times.
EXPECT_EQ(2, bindings->my_ip_address_count);
+
+ // MyIpAddressEx was called once.
+ EXPECT_EQ(1, bindings->my_ip_address_ex_count);
+
+ // DnsResolveEx was called 2 times.
+ ASSERT_EQ(2U, bindings->dns_resolves_ex.size());
+ EXPECT_EQ("is_resolvable", bindings->dns_resolves_ex[0]);
+ EXPECT_EQ("foobar", bindings->dns_resolves_ex[1]);
}
// Test that calls to the myIpAddress() and dnsResolve() bindings get
@@ -464,5 +486,22 @@ TEST(ProxyResolverV8Test, EndsWithStatementNoNewline) {
EXPECT_EQ("success:3", proxy_info.proxy_server().ToURI());
}
+// Test the return values from myIpAddress(), myIpAddressEx(), dnsResolve(),
+// dnsResolveEx(), isResolvable(), isResolvableEx(), when the the binding
+// returns empty string (failure). This simulates the return values from
+// those functions when the underlying DNS resolution fails.
+TEST(ProxyResolverV8Test, DNSResolutionFailure) {
+ ProxyResolverV8WithMockBindings resolver;
+ int result = resolver.SetPacScriptFromDisk("dns_fail.js");
+ EXPECT_EQ(OK, result);
+
+ ProxyInfo proxy_info;
+ result = resolver.GetProxyForURL(kQueryUrl, &proxy_info, NULL, NULL, NULL);
+
+ EXPECT_EQ(OK, result);
+ EXPECT_FALSE(proxy_info.is_direct());
+ EXPECT_EQ("success:80", proxy_info.proxy_server().ToURI());
+}
+
} // namespace
} // namespace net