Index: net/proxy/proxy_service_unittest.cc |
diff --git a/net/proxy/proxy_service_unittest.cc b/net/proxy/proxy_service_unittest.cc |
index a0db685aaba34234fca5ac5a7afcf567a214b7eb..34a0c5d51350633e524e639571a64745bf8c7baf 100644 |
--- a/net/proxy/proxy_service_unittest.cc |
+++ b/net/proxy/proxy_service_unittest.cc |
@@ -3480,4 +3480,224 @@ TEST_F(ProxyServiceTest, SynchronousWithFixedConfiguration) { |
EXPECT_EQ(0u, factory->pending_requests().size()); |
} |
+// Helper class to exercise URL sanitization using the different policies. This |
+// works by submitted URLs to the ProxyService. In turn the ProxyService |
+// sanitizes the URL and then passes it along to the ProxyResolver. This helper |
+// returns the URL seen by the ProxyResolver. |
+class SanitizeUrlHelper { |
+ public: |
+ SanitizeUrlHelper() { |
+ std::unique_ptr<MockProxyConfigService> config_service( |
+ new MockProxyConfigService("http://foopy/proxy.pac")); |
+ |
+ factory = new MockAsyncProxyResolverFactory(false); |
+ |
+ service_.reset(new ProxyService(std::move(config_service), |
+ base::WrapUnique(factory), nullptr)); |
+ |
+ // Do an initial request to initialize the service (configure the PAC |
+ // script). |
+ GURL url("http://example.com"); |
+ |
+ ProxyInfo info; |
+ TestCompletionCallback callback; |
+ int rv = service_->ResolveProxy(url, std::string(), LOAD_NORMAL, &info, |
+ callback.callback(), nullptr, nullptr, |
+ BoundNetLog()); |
+ EXPECT_EQ(ERR_IO_PENDING, rv); |
+ |
+ // First step is to download the PAC script. |
+ EXPECT_EQ(GURL("http://foopy/proxy.pac"), |
+ factory->pending_requests()[0]->script_data()->url()); |
+ factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver); |
+ |
+ EXPECT_EQ(1u, resolver.pending_requests().size()); |
+ EXPECT_EQ(url, resolver.pending_requests()[0]->url()); |
+ |
+ // Complete the request. |
+ resolver.pending_requests()[0]->results()->UsePacString("DIRECT"); |
+ resolver.pending_requests()[0]->CompleteNow(OK); |
+ EXPECT_EQ(OK, callback.WaitForResult()); |
+ EXPECT_TRUE(info.is_direct()); |
+ } |
+ |
+ // Changes the URL sanitization policy for the underlying ProxyService. This |
+ // will affect subsequent calls to SanitizeUrl. |
+ void SetSanitizeUrlPolicy(ProxyService::SanitizeUrlPolicy policy) { |
+ service_->set_sanitize_url_policy(policy); |
+ } |
+ |
+ // Makes a proxy resolution request through the ProxyService, and returns the |
+ // URL that was submitted to the Proxy Resolver. |
+ GURL SanitizeUrl(const GURL& raw_url) { |
+ // Issue a request and see what URL is sent to the proxy resolver. |
+ ProxyInfo info; |
+ TestCompletionCallback callback; |
+ int rv = service_->ResolveProxy(raw_url, std::string(), LOAD_NORMAL, &info, |
+ callback.callback(), nullptr, nullptr, |
+ BoundNetLog()); |
+ EXPECT_EQ(ERR_IO_PENDING, rv); |
+ |
+ EXPECT_EQ(1u, resolver.pending_requests().size()); |
+ |
+ GURL sanitized_url = resolver.pending_requests()[0]->url(); |
+ |
+ // Complete the request. |
+ resolver.pending_requests()[0]->results()->UsePacString("DIRECT"); |
+ resolver.pending_requests()[0]->CompleteNow(OK); |
+ EXPECT_EQ(OK, callback.WaitForResult()); |
+ EXPECT_TRUE(info.is_direct()); |
+ |
+ return sanitized_url; |
+ } |
+ |
+ // Changes the ProxyService's URL sanitization policy and then sanitizes |
+ // |raw_url|. |
+ GURL SanitizeUrl(const GURL& raw_url, |
+ ProxyService::SanitizeUrlPolicy policy) { |
+ service_->set_sanitize_url_policy(policy); |
+ return SanitizeUrl(raw_url); |
+ } |
+ |
+ private: |
+ MockAsyncProxyResolver resolver; |
+ MockAsyncProxyResolverFactory* factory; |
+ std::unique_ptr<ProxyService> service_; |
+}; |
+ |
+TEST_F(ProxyServiceTest, SanitizeUrlDefaultsToSafe) { |
+ SanitizeUrlHelper helper; |
+ |
+ // Without changing the URL sanitization policy, the default should be to |
+ // strip https:// URLs. |
+ EXPECT_EQ(GURL("https://example.com/"), |
+ helper.SanitizeUrl( |
+ GURL("https://foo:bar@example.com/foo/bar/baz?hello#sigh"))); |
+} |
+ |
+// Tests URL sanitization with input URLs that have a // non-cryptographic |
+// scheme (i.e. http://). The sanitized result is consistent regardless of the |
+// stripping mode selected. |
+TEST_F(ProxyServiceTest, SanitizeUrlForPacScriptNonCryptographic) { |
+ const struct { |
+ const char* raw_url; |
+ const char* sanitized_url; |
+ } kTests[] = { |
+ // Embedded identity is stripped. |
+ { |
+ "http://foo:bar@example.com/", "http://example.com/", |
+ }, |
+ { |
+ "ftp://foo:bar@example.com/", "ftp://example.com/", |
+ }, |
+ { |
+ "ftp://example.com/some/path/here", |
+ "ftp://example.com/some/path/here", |
+ }, |
+ // Reference fragment is stripped. |
+ { |
+ "http://example.com/blah#hello", "http://example.com/blah", |
+ }, |
+ // Query parameters are NOT stripped. |
+ { |
+ "http://example.com/foo/bar/baz?hello", |
+ "http://example.com/foo/bar/baz?hello", |
+ }, |
+ // Fragment is stripped, but path and query are left intact. |
+ { |
+ "http://foo:bar@example.com/foo/bar/baz?hello#sigh", |
+ "http://example.com/foo/bar/baz?hello", |
+ }, |
+ // Port numbers are not affected. |
+ { |
+ "http://example.com:88/hi", "http://example.com:88/hi", |
+ }, |
+ }; |
+ |
+ SanitizeUrlHelper helper; |
+ |
+ for (const auto& test : kTests) { |
+ // The result of SanitizeUrlForPacScript() is the same regardless of the |
+ // second parameter (sanitization mode), since the input URLs do not use a |
+ // cryptographic scheme. |
+ GURL raw_url(test.raw_url); |
+ ASSERT_TRUE(raw_url.is_valid()); |
+ EXPECT_FALSE(raw_url.SchemeIsCryptographic()); |
+ |
+ EXPECT_EQ( |
+ GURL(test.sanitized_url), |
+ helper.SanitizeUrl(raw_url, ProxyService::SanitizeUrlPolicy::UNSAFE)); |
+ |
+ EXPECT_EQ( |
+ GURL(test.sanitized_url), |
+ helper.SanitizeUrl(raw_url, ProxyService::SanitizeUrlPolicy::SAFE)); |
+ } |
+} |
+ |
+// Tests URL sanitization using input URLs that have a cryptographic schemes |
+// (i.e. https://). The sanitized result differs depending on the sanitization |
+// mode chosen. |
+TEST_F(ProxyServiceTest, SanitizeUrlForPacScriptCryptographic) { |
+ const struct { |
+ // Input URL. |
+ const char* raw_url; |
+ |
+ // Output URL when stripping of cryptographic URLs is disabled. |
+ const char* sanitized_url_unstripped; |
+ |
+ // Output URL when stripping of cryptographic URLs is enabled. |
+ const char* sanitized_url; |
+ } kTests[] = { |
+ // Embedded identity is always stripped. |
+ { |
+ "https://foo:bar@example.com/", "https://example.com/", |
+ "https://example.com/", |
+ }, |
+ // Fragments are always stripped, but stripping path is conditional on the |
+ // mode. |
+ { |
+ "https://example.com/blah#hello", "https://example.com/blah", |
+ "https://example.com/", |
+ }, |
+ // Stripping the query is conditional on the mode. |
+ { |
+ "https://example.com/?hello", "https://example.com/?hello", |
+ "https://example.com/", |
+ }, |
+ // The embedded identity and fragment is always stripped, however path and |
+ // query are conditional on the stripping mode. |
+ { |
+ "https://foo:bar@example.com/foo/bar/baz?hello#sigh", |
+ "https://example.com/foo/bar/baz?hello", "https://example.com/", |
+ }, |
+ // The URL's port should not be stripped. |
+ { |
+ "https://example.com:88/hi", "https://example.com:88/hi", |
+ "https://example.com:88/", |
+ }, |
+ // Try a wss:// URL, to make sure it also strips (is is also a |
+ // cryptographic URL). |
+ { |
+ "wss://example.com:88/hi", "wss://example.com:88/hi", |
+ "wss://example.com:88/", |
+ }, |
+ }; |
+ |
+ SanitizeUrlHelper helper; |
+ |
+ for (const auto& test : kTests) { |
+ GURL raw_url(test.raw_url); |
+ ASSERT_TRUE(raw_url.is_valid()); |
+ EXPECT_TRUE(raw_url.SchemeIsCryptographic()); |
+ |
+ EXPECT_EQ( |
+ GURL(test.sanitized_url_unstripped), |
+ helper.SanitizeUrl(raw_url, ProxyService::SanitizeUrlPolicy::UNSAFE)); |
+ |
+ EXPECT_EQ( |
+ GURL(test.sanitized_url), |
+ helper.SanitizeUrl(raw_url, ProxyService::SanitizeUrlPolicy::SAFE)); |
+ } |
+} |
+ |
} // namespace net |