diff options
author | eroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-26 23:51:28 +0000 |
---|---|---|
committer | eroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-26 23:51:28 +0000 |
commit | 21f20c8940b8b9f06b04ff142716201a2530f0a3 (patch) | |
tree | d68fcccc003b0c7edb4ce7620f2270fb608d4022 | |
parent | 13d54f79c040c2e6beeed94e096d1fcf2b0f7101 (diff) | |
download | chromium_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.h | 6 | ||||
-rw-r--r-- | net/data/proxy_resolver_v8_unittest/bindings.js | 9 | ||||
-rw-r--r-- | net/data/proxy_resolver_v8_unittest/dns_fail.js | 27 | ||||
-rw-r--r-- | net/proxy/proxy_resolver_js_bindings.cc | 50 | ||||
-rw-r--r-- | net/proxy/proxy_resolver_js_bindings.h | 12 | ||||
-rw-r--r-- | net/proxy/proxy_resolver_js_bindings_unittest.cc | 120 | ||||
-rw-r--r-- | net/proxy/proxy_resolver_script.h | 10 | ||||
-rw-r--r-- | net/proxy/proxy_resolver_v8.cc | 108 | ||||
-rw-r--r-- | net/proxy/proxy_resolver_v8_unittest.cc | 41 |
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 |