| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/compiler_specific.h" | 5 #include "base/compiler_specific.h" |
| 6 #include "base/file_util.h" | 6 #include "base/file_util.h" |
| 7 #include "base/path_service.h" | 7 #include "base/path_service.h" |
| 8 #include "base/strings/string_util.h" | 8 #include "base/strings/string_util.h" |
| 9 #include "base/strings/stringprintf.h" | 9 #include "base/strings/stringprintf.h" |
| 10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
| 11 #include "net/base/net_errors.h" | 11 #include "net/base/net_errors.h" |
| 12 #include "net/base/net_log_unittest.h" | 12 #include "net/base/net_log_unittest.h" |
| 13 #include "net/proxy/proxy_info.h" | 13 #include "net/proxy/proxy_info.h" |
| 14 #include "net/proxy/proxy_resolver_v8.h" | 14 #include "net/proxy/proxy_resolver_v8.h" |
| 15 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
| 16 #include "url/gurl.h" | 16 #include "url/gurl.h" |
| 17 | 17 |
| 18 namespace net { | 18 namespace net { |
| 19 namespace { | 19 namespace { |
| 20 | 20 |
| 21 // Javascript bindings for ProxyResolverV8, which returns mock values. | 21 // Javascript bindings for ProxyResolverV8, which returns mock values. |
| 22 // Each time one of the bindings is called into, we push the input into a | 22 // Each time one of the bindings is called into, we push the input into a |
| 23 // list, for later verification. | 23 // list, for later verification. |
| 24 class MockJSBindings : public ProxyResolverV8::JSBindings { | 24 class MockJSBindings : public ProxyResolverV8::JSBindings { |
| 25 public: | 25 public: |
| 26 MockJSBindings() : my_ip_address_count(0), my_ip_address_ex_count(0), | 26 MockJSBindings() |
| 27 should_terminate(false) {} | 27 : my_ip_address_count(0), |
| 28 my_ip_address_ex_count(0), |
| 29 should_terminate(false) {} |
| 28 | 30 |
| 29 virtual void Alert(const base::string16& message) OVERRIDE { | 31 virtual void Alert(const base::string16& message) OVERRIDE { |
| 30 VLOG(1) << "PAC-alert: " << message; // Helpful when debugging. | 32 VLOG(1) << "PAC-alert: " << message; // Helpful when debugging. |
| 31 alerts.push_back(base::UTF16ToUTF8(message)); | 33 alerts.push_back(base::UTF16ToUTF8(message)); |
| 32 } | 34 } |
| 33 | 35 |
| 34 virtual bool ResolveDns(const std::string& host, | 36 virtual bool ResolveDns(const std::string& host, |
| 35 ResolveDnsOperation op, | 37 ResolveDnsOperation op, |
| 36 std::string* output, | 38 std::string* output, |
| 37 bool* terminate) OVERRIDE { | 39 bool* terminate) OVERRIDE { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 | 93 |
| 92 // Whether ResolveDns() should terminate script execution. | 94 // Whether ResolveDns() should terminate script execution. |
| 93 bool should_terminate; | 95 bool should_terminate; |
| 94 }; | 96 }; |
| 95 | 97 |
| 96 // This is the same as ProxyResolverV8, but it uses mock bindings in place of | 98 // This is the same as ProxyResolverV8, but it uses mock bindings in place of |
| 97 // the default bindings, and has a helper function to load PAC scripts from | 99 // the default bindings, and has a helper function to load PAC scripts from |
| 98 // disk. | 100 // disk. |
| 99 class ProxyResolverV8WithMockBindings : public ProxyResolverV8 { | 101 class ProxyResolverV8WithMockBindings : public ProxyResolverV8 { |
| 100 public: | 102 public: |
| 101 ProxyResolverV8WithMockBindings() { | 103 ProxyResolverV8WithMockBindings() { set_js_bindings(&mock_js_bindings_); } |
| 102 set_js_bindings(&mock_js_bindings_); | |
| 103 } | |
| 104 | 104 |
| 105 virtual ~ProxyResolverV8WithMockBindings() { | 105 virtual ~ProxyResolverV8WithMockBindings() {} |
| 106 } | |
| 107 | 106 |
| 108 MockJSBindings* mock_js_bindings() { | 107 MockJSBindings* mock_js_bindings() { return &mock_js_bindings_; } |
| 109 return &mock_js_bindings_; | |
| 110 } | |
| 111 | 108 |
| 112 // Initialize with the PAC script data at |filename|. | 109 // Initialize with the PAC script data at |filename|. |
| 113 int SetPacScriptFromDisk(const char* filename) { | 110 int SetPacScriptFromDisk(const char* filename) { |
| 114 base::FilePath path; | 111 base::FilePath path; |
| 115 PathService::Get(base::DIR_SOURCE_ROOT, &path); | 112 PathService::Get(base::DIR_SOURCE_ROOT, &path); |
| 116 path = path.AppendASCII("net"); | 113 path = path.AppendASCII("net"); |
| 117 path = path.AppendASCII("data"); | 114 path = path.AppendASCII("data"); |
| 118 path = path.AppendASCII("proxy_resolver_v8_unittest"); | 115 path = path.AppendASCII("proxy_resolver_v8_unittest"); |
| 119 path = path.AppendASCII(filename); | 116 path = path.AppendASCII(filename); |
| 120 | 117 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 TEST(ProxyResolverV8Test, Basic) { | 179 TEST(ProxyResolverV8Test, Basic) { |
| 183 ProxyResolverV8WithMockBindings resolver; | 180 ProxyResolverV8WithMockBindings resolver; |
| 184 int result = resolver.SetPacScriptFromDisk("passthrough.js"); | 181 int result = resolver.SetPacScriptFromDisk("passthrough.js"); |
| 185 EXPECT_EQ(OK, result); | 182 EXPECT_EQ(OK, result); |
| 186 | 183 |
| 187 // The "FindProxyForURL" of this PAC script simply concatenates all of the | 184 // The "FindProxyForURL" of this PAC script simply concatenates all of the |
| 188 // arguments into a pseudo-host. The purpose of this test is to verify that | 185 // arguments into a pseudo-host. The purpose of this test is to verify that |
| 189 // the correct arguments are being passed to FindProxyForURL(). | 186 // the correct arguments are being passed to FindProxyForURL(). |
| 190 { | 187 { |
| 191 ProxyInfo proxy_info; | 188 ProxyInfo proxy_info; |
| 192 result = resolver.GetProxyForURL(GURL("http://query.com/path"), &proxy_info, | 189 result = resolver.GetProxyForURL(GURL("http://query.com/path"), |
| 193 CompletionCallback(), NULL, BoundNetLog()); | 190 &proxy_info, |
| 191 CompletionCallback(), |
| 192 NULL, |
| 193 BoundNetLog()); |
| 194 EXPECT_EQ(OK, result); | 194 EXPECT_EQ(OK, result); |
| 195 EXPECT_EQ("http.query.com.path.query.com:80", | 195 EXPECT_EQ("http.query.com.path.query.com:80", |
| 196 proxy_info.proxy_server().ToURI()); | 196 proxy_info.proxy_server().ToURI()); |
| 197 } | 197 } |
| 198 { | 198 { |
| 199 ProxyInfo proxy_info; | 199 ProxyInfo proxy_info; |
| 200 int result = resolver.GetProxyForURL( | 200 int result = resolver.GetProxyForURL(GURL("ftp://query.com:90/path"), |
| 201 GURL("ftp://query.com:90/path"), &proxy_info, CompletionCallback(), | 201 &proxy_info, |
| 202 NULL, BoundNetLog()); | 202 CompletionCallback(), |
| 203 NULL, |
| 204 BoundNetLog()); |
| 203 EXPECT_EQ(OK, result); | 205 EXPECT_EQ(OK, result); |
| 204 // Note that FindProxyForURL(url, host) does not expect |host| to contain | 206 // Note that FindProxyForURL(url, host) does not expect |host| to contain |
| 205 // the port number. | 207 // the port number. |
| 206 EXPECT_EQ("ftp.query.com.90.path.query.com:80", | 208 EXPECT_EQ("ftp.query.com.90.path.query.com:80", |
| 207 proxy_info.proxy_server().ToURI()); | 209 proxy_info.proxy_server().ToURI()); |
| 208 | 210 |
| 209 EXPECT_EQ(0U, resolver.mock_js_bindings()->alerts.size()); | 211 EXPECT_EQ(0U, resolver.mock_js_bindings()->alerts.size()); |
| 210 EXPECT_EQ(0U, resolver.mock_js_bindings()->errors.size()); | 212 EXPECT_EQ(0U, resolver.mock_js_bindings()->errors.size()); |
| 211 } | 213 } |
| 212 } | 214 } |
| 213 | 215 |
| 214 TEST(ProxyResolverV8Test, BadReturnType) { | 216 TEST(ProxyResolverV8Test, BadReturnType) { |
| 215 // These are the filenames of PAC scripts which each return a non-string | 217 // These are the filenames of PAC scripts which each return a non-string |
| 216 // types for FindProxyForURL(). They should all fail with | 218 // types for FindProxyForURL(). They should all fail with |
| 217 // ERR_PAC_SCRIPT_FAILED. | 219 // ERR_PAC_SCRIPT_FAILED. |
| 218 static const char* const filenames[] = { | 220 static const char* const filenames[] = { |
| 219 "return_undefined.js", | 221 "return_undefined.js", "return_integer.js", "return_function.js", |
| 220 "return_integer.js", | |
| 221 "return_function.js", | |
| 222 "return_object.js", | 222 "return_object.js", |
| 223 // TODO(eroman): Should 'null' be considered equivalent to "DIRECT" ? | 223 // TODO(eroman): Should 'null' be considered equivalent to "DIRECT" ? |
| 224 "return_null.js" | 224 "return_null.js"}; |
| 225 }; | |
| 226 | 225 |
| 227 for (size_t i = 0; i < arraysize(filenames); ++i) { | 226 for (size_t i = 0; i < arraysize(filenames); ++i) { |
| 228 ProxyResolverV8WithMockBindings resolver; | 227 ProxyResolverV8WithMockBindings resolver; |
| 229 int result = resolver.SetPacScriptFromDisk(filenames[i]); | 228 int result = resolver.SetPacScriptFromDisk(filenames[i]); |
| 230 EXPECT_EQ(OK, result); | 229 EXPECT_EQ(OK, result); |
| 231 | 230 |
| 232 ProxyInfo proxy_info; | 231 ProxyInfo proxy_info; |
| 233 result = resolver.GetProxyForURL( | 232 result = resolver.GetProxyForURL( |
| 234 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog()); | 233 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog()); |
| 235 | 234 |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 377 // Initialize it. | 376 // Initialize it. |
| 378 result = resolver.SetPacScriptFromDisk("direct.js"); | 377 result = resolver.SetPacScriptFromDisk("direct.js"); |
| 379 EXPECT_EQ(OK, result); | 378 EXPECT_EQ(OK, result); |
| 380 | 379 |
| 381 // Resolve should now succeed. | 380 // Resolve should now succeed. |
| 382 result = resolver.GetProxyForURL( | 381 result = resolver.GetProxyForURL( |
| 383 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog()); | 382 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog()); |
| 384 EXPECT_EQ(OK, result); | 383 EXPECT_EQ(OK, result); |
| 385 | 384 |
| 386 // Clear it, by initializing with an empty string. | 385 // Clear it, by initializing with an empty string. |
| 387 resolver.SetPacScript( | 386 resolver.SetPacScript(ProxyResolverScriptData::FromUTF16(base::string16()), |
| 388 ProxyResolverScriptData::FromUTF16(base::string16()), | 387 CompletionCallback()); |
| 389 CompletionCallback()); | |
| 390 | 388 |
| 391 // Resolve should fail again now. | 389 // Resolve should fail again now. |
| 392 result = resolver.GetProxyForURL( | 390 result = resolver.GetProxyForURL( |
| 393 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog()); | 391 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog()); |
| 394 EXPECT_EQ(ERR_FAILED, result); | 392 EXPECT_EQ(ERR_FAILED, result); |
| 395 | 393 |
| 396 // Load a good script once more. | 394 // Load a good script once more. |
| 397 result = resolver.SetPacScriptFromDisk("direct.js"); | 395 result = resolver.SetPacScriptFromDisk("direct.js"); |
| 398 EXPECT_EQ(OK, result); | 396 EXPECT_EQ(OK, result); |
| 399 result = resolver.GetProxyForURL( | 397 result = resolver.GetProxyForURL( |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 EXPECT_FALSE(proxy_info.is_direct()); | 491 EXPECT_FALSE(proxy_info.is_direct()); |
| 494 EXPECT_EQ("success:80", proxy_info.proxy_server().ToURI()); | 492 EXPECT_EQ("success:80", proxy_info.proxy_server().ToURI()); |
| 495 } | 493 } |
| 496 | 494 |
| 497 // Try loading a PAC script that ends with a statement and has no terminal | 495 // Try loading a PAC script that ends with a statement and has no terminal |
| 498 // newline. This should not cause problems with the PAC utility functions | 496 // newline. This should not cause problems with the PAC utility functions |
| 499 // that we add to the script's environment. | 497 // that we add to the script's environment. |
| 500 // http://crbug.com/22864 | 498 // http://crbug.com/22864 |
| 501 TEST(ProxyResolverV8Test, EndsWithStatementNoNewline) { | 499 TEST(ProxyResolverV8Test, EndsWithStatementNoNewline) { |
| 502 ProxyResolverV8WithMockBindings resolver; | 500 ProxyResolverV8WithMockBindings resolver; |
| 503 int result = resolver.SetPacScriptFromDisk( | 501 int result = |
| 504 "ends_with_statement_no_semicolon.js"); | 502 resolver.SetPacScriptFromDisk("ends_with_statement_no_semicolon.js"); |
| 505 EXPECT_EQ(OK, result); | 503 EXPECT_EQ(OK, result); |
| 506 | 504 |
| 507 ProxyInfo proxy_info; | 505 ProxyInfo proxy_info; |
| 508 result = resolver.GetProxyForURL( | 506 result = resolver.GetProxyForURL( |
| 509 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog()); | 507 kQueryUrl, &proxy_info, CompletionCallback(), NULL, BoundNetLog()); |
| 510 | 508 |
| 511 EXPECT_EQ(OK, result); | 509 EXPECT_EQ(OK, result); |
| 512 EXPECT_FALSE(proxy_info.is_direct()); | 510 EXPECT_FALSE(proxy_info.is_direct()); |
| 513 EXPECT_EQ("success:3", proxy_info.proxy_server().ToURI()); | 511 EXPECT_EQ("success:3", proxy_info.proxy_server().ToURI()); |
| 514 } | 512 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 558 // Test that when resolving a URL which contains an IPv6 string literal, the | 556 // Test that when resolving a URL which contains an IPv6 string literal, the |
| 559 // brackets are removed from the host before passing it down to the PAC script. | 557 // brackets are removed from the host before passing it down to the PAC script. |
| 560 // If we don't do this, then subsequent calls to dnsResolveEx(host) will be | 558 // If we don't do this, then subsequent calls to dnsResolveEx(host) will be |
| 561 // doomed to fail since it won't correspond with a valid name. | 559 // doomed to fail since it won't correspond with a valid name. |
| 562 TEST(ProxyResolverV8Test, IPv6HostnamesNotBracketed) { | 560 TEST(ProxyResolverV8Test, IPv6HostnamesNotBracketed) { |
| 563 ProxyResolverV8WithMockBindings resolver; | 561 ProxyResolverV8WithMockBindings resolver; |
| 564 int result = resolver.SetPacScriptFromDisk("resolve_host.js"); | 562 int result = resolver.SetPacScriptFromDisk("resolve_host.js"); |
| 565 EXPECT_EQ(OK, result); | 563 EXPECT_EQ(OK, result); |
| 566 | 564 |
| 567 ProxyInfo proxy_info; | 565 ProxyInfo proxy_info; |
| 568 result = resolver.GetProxyForURL( | 566 result = resolver.GetProxyForURL(GURL("http://[abcd::efff]:99/watsupdawg"), |
| 569 GURL("http://[abcd::efff]:99/watsupdawg"), &proxy_info, | 567 &proxy_info, |
| 570 CompletionCallback(), NULL, BoundNetLog()); | 568 CompletionCallback(), |
| 569 NULL, |
| 570 BoundNetLog()); |
| 571 | 571 |
| 572 EXPECT_EQ(OK, result); | 572 EXPECT_EQ(OK, result); |
| 573 EXPECT_TRUE(proxy_info.is_direct()); | 573 EXPECT_TRUE(proxy_info.is_direct()); |
| 574 | 574 |
| 575 // We called dnsResolveEx() exactly once, by passing through the "host" | 575 // We called dnsResolveEx() exactly once, by passing through the "host" |
| 576 // argument to FindProxyForURL(). The brackets should have been stripped. | 576 // argument to FindProxyForURL(). The brackets should have been stripped. |
| 577 ASSERT_EQ(1U, resolver.mock_js_bindings()->dns_resolves_ex.size()); | 577 ASSERT_EQ(1U, resolver.mock_js_bindings()->dns_resolves_ex.size()); |
| 578 EXPECT_EQ("abcd::efff", resolver.mock_js_bindings()->dns_resolves_ex[0]); | 578 EXPECT_EQ("abcd::efff", resolver.mock_js_bindings()->dns_resolves_ex[0]); |
| 579 } | 579 } |
| 580 | 580 |
| 581 // Test that terminating a script within DnsResolve() leads to eventual | 581 // Test that terminating a script within DnsResolve() leads to eventual |
| 582 // termination of the script. Also test that repeatedly calling terminate is | 582 // termination of the script. Also test that repeatedly calling terminate is |
| 583 // safe, and running the script again after termination still works. | 583 // safe, and running the script again after termination still works. |
| 584 TEST(ProxyResolverV8Test, Terminate) { | 584 TEST(ProxyResolverV8Test, Terminate) { |
| 585 ProxyResolverV8WithMockBindings resolver; | 585 ProxyResolverV8WithMockBindings resolver; |
| 586 int result = resolver.SetPacScriptFromDisk("terminate.js"); | 586 int result = resolver.SetPacScriptFromDisk("terminate.js"); |
| 587 EXPECT_EQ(OK, result); | 587 EXPECT_EQ(OK, result); |
| 588 | 588 |
| 589 MockJSBindings* bindings = resolver.mock_js_bindings(); | 589 MockJSBindings* bindings = resolver.mock_js_bindings(); |
| 590 | 590 |
| 591 // Terminate script execution upon reaching dnsResolve(). Note that | 591 // Terminate script execution upon reaching dnsResolve(). Note that |
| 592 // termination may not take effect right away (so the subsequent dnsResolve() | 592 // termination may not take effect right away (so the subsequent dnsResolve() |
| 593 // and alert() may be run). | 593 // and alert() may be run). |
| 594 bindings->should_terminate = true; | 594 bindings->should_terminate = true; |
| 595 | 595 |
| 596 ProxyInfo proxy_info; | 596 ProxyInfo proxy_info; |
| 597 result = resolver.GetProxyForURL( | 597 result = resolver.GetProxyForURL(GURL("http://hang/"), |
| 598 GURL("http://hang/"), &proxy_info, | 598 &proxy_info, |
| 599 CompletionCallback(), NULL, BoundNetLog()); | 599 CompletionCallback(), |
| 600 NULL, |
| 601 BoundNetLog()); |
| 600 | 602 |
| 601 // The script execution was terminated. | 603 // The script execution was terminated. |
| 602 EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, result); | 604 EXPECT_EQ(ERR_PAC_SCRIPT_FAILED, result); |
| 603 | 605 |
| 604 EXPECT_EQ(1U, resolver.mock_js_bindings()->dns_resolves.size()); | 606 EXPECT_EQ(1U, resolver.mock_js_bindings()->dns_resolves.size()); |
| 605 EXPECT_GE(2U, resolver.mock_js_bindings()->dns_resolves_ex.size()); | 607 EXPECT_GE(2U, resolver.mock_js_bindings()->dns_resolves_ex.size()); |
| 606 EXPECT_GE(1U, bindings->alerts.size()); | 608 EXPECT_GE(1U, bindings->alerts.size()); |
| 607 | 609 |
| 608 EXPECT_EQ(1U, bindings->errors.size()); | 610 EXPECT_EQ(1U, bindings->errors.size()); |
| 609 | 611 |
| 610 // Termination shows up as an uncaught exception without any message. | 612 // Termination shows up as an uncaught exception without any message. |
| 611 EXPECT_EQ("", bindings->errors[0]); | 613 EXPECT_EQ("", bindings->errors[0]); |
| 612 | 614 |
| 613 bindings->errors.clear(); | 615 bindings->errors.clear(); |
| 614 | 616 |
| 615 // Try running the script again, this time with a different input which won't | 617 // Try running the script again, this time with a different input which won't |
| 616 // cause a termination+hang. | 618 // cause a termination+hang. |
| 617 result = resolver.GetProxyForURL( | 619 result = resolver.GetProxyForURL(GURL("http://kittens/"), |
| 618 GURL("http://kittens/"), &proxy_info, | 620 &proxy_info, |
| 619 CompletionCallback(), NULL, BoundNetLog()); | 621 CompletionCallback(), |
| 622 NULL, |
| 623 BoundNetLog()); |
| 620 | 624 |
| 621 EXPECT_EQ(OK, result); | 625 EXPECT_EQ(OK, result); |
| 622 EXPECT_EQ(0u, bindings->errors.size()); | 626 EXPECT_EQ(0u, bindings->errors.size()); |
| 623 EXPECT_EQ("kittens:88", proxy_info.proxy_server().ToURI()); | 627 EXPECT_EQ("kittens:88", proxy_info.proxy_server().ToURI()); |
| 624 } | 628 } |
| 625 | 629 |
| 626 } // namespace | 630 } // namespace |
| 627 } // namespace net | 631 } // namespace net |
| OLD | NEW |