• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/proxy_resolution/proxy_config_service_android.h"
6 
7 #include <map>
8 #include <memory>
9 #include <string>
10 
11 #include "base/compiler_specific.h"
12 #include "base/functional/bind.h"
13 #include "base/functional/callback_helpers.h"
14 #include "base/run_loop.h"
15 #include "base/task/single_thread_task_runner.h"
16 #include "net/proxy_resolution/proxy_config_with_annotation.h"
17 #include "net/proxy_resolution/proxy_info.h"
18 #include "net/test/test_with_task_environment.h"
19 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 
22 // Must come after all headers that specialize FromJniType() / ToJniType().
23 #include "net/android/net_tests_jni/AndroidProxyConfigServiceTestUtil_jni.h"
24 
25 namespace net {
26 
27 namespace {
28 
29 class TestObserver : public ProxyConfigService::Observer {
30  public:
TestObserver()31   TestObserver() : availability_(ProxyConfigService::CONFIG_UNSET) {}
32 
33   // ProxyConfigService::Observer:
OnProxyConfigChanged(const ProxyConfigWithAnnotation & config,ProxyConfigService::ConfigAvailability availability)34   void OnProxyConfigChanged(
35       const ProxyConfigWithAnnotation& config,
36       ProxyConfigService::ConfigAvailability availability) override {
37     config_ = config;
38     availability_ = availability;
39   }
40 
availability() const41   ProxyConfigService::ConfigAvailability availability() const {
42     return availability_;
43   }
44 
config() const45   const ProxyConfigWithAnnotation& config() const { return config_; }
46 
47  private:
48   ProxyConfigWithAnnotation config_;
49   ProxyConfigService::ConfigAvailability availability_;
50 };
51 
52 // Helper class that simply prepares Java's Looper on construction.
53 class JavaLooperPreparer {
54  public:
JavaLooperPreparer()55   JavaLooperPreparer() {
56     Java_AndroidProxyConfigServiceTestUtil_prepareLooper(
57         base::android::AttachCurrentThread());
58   }
59 };
60 
61 }  // namespace
62 
63 typedef std::map<std::string, std::string> StringMap;
64 
65 class ProxyConfigServiceAndroidTestBase : public TestWithTaskEnvironment {
66  protected:
67   // Note that the current thread's message loop is initialized by the test
68   // suite (see net/test/net_test_suite.cc).
ProxyConfigServiceAndroidTestBase(const StringMap & initial_configuration)69   explicit ProxyConfigServiceAndroidTestBase(
70       const StringMap& initial_configuration)
71       : configuration_(initial_configuration),
72         service_(
73             base::SingleThreadTaskRunner::GetCurrentDefault(),
74             base::SingleThreadTaskRunner::GetCurrentDefault(),
75             base::BindRepeating(&ProxyConfigServiceAndroidTestBase::GetProperty,
76                                 base::Unretained(this))) {}
77 
78   ~ProxyConfigServiceAndroidTestBase() override = default;
79 
80   // testing::Test:
SetUp()81   void SetUp() override {
82     base::RunLoop().RunUntilIdle();
83     service_.AddObserver(&observer_);
84   }
85 
TearDown()86   void TearDown() override { service_.RemoveObserver(&observer_); }
87 
ClearConfiguration()88   void ClearConfiguration() {
89     configuration_.clear();
90   }
91 
AddProperty(const std::string & key,const std::string & value)92   void AddProperty(const std::string& key, const std::string& value) {
93     configuration_[key] = value;
94   }
95 
GetProperty(const std::string & key)96   std::string GetProperty(const std::string& key) {
97     StringMap::const_iterator it = configuration_.find(key);
98     if (it == configuration_.end())
99       return std::string();
100     return it->second;
101   }
102 
ProxySettingsChangedTo(const std::string & host,int port,const std::string & pac_url,const std::vector<std::string> & exclusion_list)103   void ProxySettingsChangedTo(const std::string& host,
104                               int port,
105                               const std::string& pac_url,
106                               const std::vector<std::string>& exclusion_list) {
107     service_.ProxySettingsChangedTo(host, port, pac_url, exclusion_list);
108     base::RunLoop().RunUntilIdle();
109   }
110 
ProxySettingsChanged()111   void ProxySettingsChanged() {
112     service_.ProxySettingsChanged();
113     base::RunLoop().RunUntilIdle();
114   }
115 
TestMapping(const std::string & url,const std::string & expected)116   void TestMapping(const std::string& url, const std::string& expected) {
117     ProxyConfigService::ConfigAvailability availability;
118     ProxyConfigWithAnnotation proxy_config;
119     availability = service_.GetLatestProxyConfig(&proxy_config);
120     EXPECT_EQ(ProxyConfigService::CONFIG_VALID, availability);
121     ProxyInfo proxy_info;
122     proxy_config.value().proxy_rules().Apply(GURL(url), &proxy_info);
123     EXPECT_EQ(expected, proxy_info.ToDebugString());
124   }
125 
SetProxyOverride(const ProxyConfigServiceAndroid::ProxyOverrideRule & rule,const std::vector<std::string> & bypass_rules,const bool reverse_bypass,base::OnceClosure callback)126   void SetProxyOverride(
127       const ProxyConfigServiceAndroid::ProxyOverrideRule& rule,
128       const std::vector<std::string>& bypass_rules,
129       const bool reverse_bypass,
130       base::OnceClosure callback) {
131     std::vector<ProxyConfigServiceAndroid::ProxyOverrideRule> rules;
132     rules.push_back(rule);
133     SetProxyOverride(rules, bypass_rules, reverse_bypass, std::move(callback));
134   }
135 
SetProxyOverride(const std::vector<ProxyConfigServiceAndroid::ProxyOverrideRule> & rules,const std::vector<std::string> & bypass_rules,const bool reverse_bypass,base::OnceClosure callback)136   void SetProxyOverride(
137       const std::vector<ProxyConfigServiceAndroid::ProxyOverrideRule>& rules,
138       const std::vector<std::string>& bypass_rules,
139       const bool reverse_bypass,
140       base::OnceClosure callback) {
141     service_.SetProxyOverride(rules, bypass_rules, reverse_bypass,
142                               std::move(callback));
143     base::RunLoop().RunUntilIdle();
144   }
145 
ClearProxyOverride(base::OnceClosure callback)146   void ClearProxyOverride(base::OnceClosure callback) {
147     service_.ClearProxyOverride(std::move(callback));
148     base::RunLoop().RunUntilIdle();
149   }
150 
151   StringMap configuration_;
152   TestObserver observer_;
153   // |java_looper_preparer_| appears before |service_| so that Java's Looper is
154   // prepared before constructing |service_| as it creates a ProxyChangeListener
155   // which requires a Looper.
156   JavaLooperPreparer java_looper_preparer_;
157   ProxyConfigServiceAndroid service_;
158 };
159 
160 class ProxyConfigServiceAndroidTest : public ProxyConfigServiceAndroidTestBase {
161  public:
ProxyConfigServiceAndroidTest()162   ProxyConfigServiceAndroidTest()
163       : ProxyConfigServiceAndroidTestBase(StringMap()) {}
164 };
165 
166 class ProxyConfigServiceAndroidWithInitialConfigTest
167     : public ProxyConfigServiceAndroidTestBase {
168  public:
ProxyConfigServiceAndroidWithInitialConfigTest()169   ProxyConfigServiceAndroidWithInitialConfigTest()
170       : ProxyConfigServiceAndroidTestBase(MakeInitialConfiguration()) {}
171 
172  private:
MakeInitialConfiguration()173   StringMap MakeInitialConfiguration() {
174     StringMap initial_configuration;
175     initial_configuration["http.proxyHost"] = "httpproxy.com";
176     initial_configuration["http.proxyPort"] = "8080";
177     return initial_configuration;
178   }
179 };
180 
TEST_F(ProxyConfigServiceAndroidTest,TestChangePropertiesNotification)181 TEST_F(ProxyConfigServiceAndroidTest, TestChangePropertiesNotification) {
182   // Set up a non-empty configuration
183   AddProperty("http.proxyHost", "localhost");
184   ProxySettingsChanged();
185   EXPECT_EQ(ProxyConfigService::CONFIG_VALID, observer_.availability());
186   EXPECT_FALSE(observer_.config().value().proxy_rules().empty());
187 
188   // Set up an empty configuration
189   ClearConfiguration();
190   ProxySettingsChanged();
191   EXPECT_EQ(ProxyConfigService::CONFIG_VALID, observer_.availability());
192   EXPECT_TRUE(observer_.config().value().proxy_rules().empty());
193 }
194 
TEST_F(ProxyConfigServiceAndroidWithInitialConfigTest,TestInitialConfig)195 TEST_F(ProxyConfigServiceAndroidWithInitialConfigTest, TestInitialConfig) {
196   // Make sure that the initial config is set.
197   TestMapping("ftp://example.com/", "DIRECT");
198   TestMapping("http://example.com/", "PROXY httpproxy.com:8080");
199 
200   // Override the initial configuration.
201   ClearConfiguration();
202   AddProperty("http.proxyHost", "httpproxy.com");
203   ProxySettingsChanged();
204   TestMapping("http://example.com/", "PROXY httpproxy.com:80");
205 }
206 
TEST_F(ProxyConfigServiceAndroidTest,TestClearProxy)207 TEST_F(ProxyConfigServiceAndroidTest, TestClearProxy) {
208   AddProperty("http.proxyHost", "httpproxy.com");
209   ProxySettingsChanged();
210   TestMapping("http://example.com/", "PROXY httpproxy.com:80");
211 
212   // These values are used in ProxyChangeListener.java to indicate a direct
213   // proxy connection.
214   ProxySettingsChangedTo("", 0, "", {});
215   TestMapping("http://example.com/", "DIRECT");
216 }
217 
218 struct ProxyCallback {
ProxyCallbacknet::ProxyCallback219   ProxyCallback()
220       : callback(base::BindOnce(&ProxyCallback::Call, base::Unretained(this))) {
221   }
222 
Callnet::ProxyCallback223   void Call() { called = true; }
224 
225   bool called = false;
226   base::OnceClosure callback;
227 };
228 
TEST_F(ProxyConfigServiceAndroidTest,TestProxyOverrideCallback)229 TEST_F(ProxyConfigServiceAndroidTest, TestProxyOverrideCallback) {
230   ProxyCallback proxyCallback;
231   ASSERT_FALSE(proxyCallback.called);
232   ClearProxyOverride(std::move(proxyCallback.callback));
233   base::RunLoop().RunUntilIdle();
234   EXPECT_TRUE(proxyCallback.called);
235 }
236 
TEST_F(ProxyConfigServiceAndroidTest,TestProxyOverrideSchemes)237 TEST_F(ProxyConfigServiceAndroidTest, TestProxyOverrideSchemes) {
238   std::vector<std::string> bypass_rules;
239 
240   // Check that webview uses the default proxy
241   TestMapping("http://example.com/", "DIRECT");
242   TestMapping("https://example.com/", "DIRECT");
243   TestMapping("ftp://example.com/", "DIRECT");
244 
245   SetProxyOverride({"*", "httpoverrideproxy.com:200"}, bypass_rules, false,
246                    base::DoNothing());
247   TestMapping("http://example.com/", "PROXY httpoverrideproxy.com:200");
248   TestMapping("https://example.com/", "PROXY httpoverrideproxy.com:200");
249   TestMapping("ftp://example.com/", "PROXY httpoverrideproxy.com:200");
250 
251   // Check that webview uses the custom proxy only for https
252   SetProxyOverride({"https", "httpoverrideproxy.com:200"}, bypass_rules, false,
253                    base::DoNothing());
254   TestMapping("http://example.com/", "DIRECT");
255   TestMapping("https://example.com/", "PROXY httpoverrideproxy.com:200");
256   TestMapping("ftp://example.com/", "DIRECT");
257 
258   // Check that webview uses the default proxy
259   ClearProxyOverride(base::DoNothing());
260   TestMapping("http://example.com/", "DIRECT");
261   TestMapping("https://example.com/", "DIRECT");
262   TestMapping("ftp://example.com/", "DIRECT");
263 }
264 
TEST_F(ProxyConfigServiceAndroidTest,TestProxyOverridePorts)265 TEST_F(ProxyConfigServiceAndroidTest, TestProxyOverridePorts) {
266   std::vector<std::string> bypass_rules;
267 
268   // Check that webview uses the default proxy
269   TestMapping("http://example.com/", "DIRECT");
270   TestMapping("https://example.com/", "DIRECT");
271   TestMapping("ftp://example.com/", "DIRECT");
272 
273   // Check that webview uses port 80 for http proxies
274   SetProxyOverride({"*", "httpoverrideproxy.com"}, bypass_rules, false,
275                    base::DoNothing());
276   TestMapping("http://example.com:444", "PROXY httpoverrideproxy.com:80");
277   TestMapping("https://example.com:2222", "PROXY httpoverrideproxy.com:80");
278   TestMapping("ftp://example.com:15", "PROXY httpoverrideproxy.com:80");
279 
280   // Check that webview uses port 443 for https proxies
281   SetProxyOverride({"*", "https://httpoverrideproxy.com"}, bypass_rules, false,
282                    base::DoNothing());
283   TestMapping("http://example.com:8080", "HTTPS httpoverrideproxy.com:443");
284   TestMapping("https://example.com:1111", "HTTPS httpoverrideproxy.com:443");
285   TestMapping("ftp://example.com:752", "HTTPS httpoverrideproxy.com:443");
286 
287   // Check that webview uses custom port
288   SetProxyOverride({"*", "https://httpoverrideproxy.com:777"}, bypass_rules,
289                    false, base::DoNothing());
290   TestMapping("http://example.com:8080", "HTTPS httpoverrideproxy.com:777");
291   TestMapping("https://example.com:1111", "HTTPS httpoverrideproxy.com:777");
292   TestMapping("ftp://example.com:752", "HTTPS httpoverrideproxy.com:777");
293 
294   ClearProxyOverride(base::DoNothing());
295 }
296 
TEST_F(ProxyConfigServiceAndroidTest,TestProxyOverrideMultipleRules)297 TEST_F(ProxyConfigServiceAndroidTest, TestProxyOverrideMultipleRules) {
298   std::vector<std::string> bypass_rules;
299 
300   // Multiple rules with schemes are valid
301   std::vector<ProxyConfigServiceAndroid::ProxyOverrideRule> rules;
302   rules.emplace_back("http", "httpoverrideproxy.com");
303   rules.emplace_back("https", "https://httpoverrideproxy.com");
304   SetProxyOverride(rules, bypass_rules, false, base::DoNothing());
305   TestMapping("https://example.com/", "HTTPS httpoverrideproxy.com:443");
306   TestMapping("http://example.com/", "PROXY httpoverrideproxy.com:80");
307 
308   // Rules with and without scheme can be combined
309   rules.clear();
310   rules.emplace_back("http", "overrideproxy1.com");
311   rules.emplace_back("*", "overrideproxy2.com");
312   SetProxyOverride(rules, bypass_rules, false, base::DoNothing());
313   TestMapping("https://example.com/", "PROXY overrideproxy2.com:80");
314   TestMapping("http://example.com/", "PROXY overrideproxy1.com:80");
315 
316   ClearProxyOverride(base::DoNothing());
317 }
318 
TEST_F(ProxyConfigServiceAndroidTest,TestProxyOverrideListOfRules)319 TEST_F(ProxyConfigServiceAndroidTest, TestProxyOverrideListOfRules) {
320   std::vector<std::string> bypass_rules;
321 
322   std::vector<ProxyConfigServiceAndroid::ProxyOverrideRule> rules;
323   rules.emplace_back("http", "httpproxy1");
324   rules.emplace_back("*", "socks5://fallback1");
325   rules.emplace_back("http", "httpproxy2");
326   rules.emplace_back("*", "fallback2");
327   rules.emplace_back("*", "direct://");
328   SetProxyOverride(rules, bypass_rules, false, base::DoNothing());
329 
330   TestMapping("http://example.com", "PROXY httpproxy1:80;PROXY httpproxy2:80");
331   TestMapping("https://example.com",
332               "SOCKS5 fallback1:1080;PROXY fallback2:80;DIRECT");
333 }
334 
TEST_F(ProxyConfigServiceAndroidTest,TestOverrideAndProxy)335 TEST_F(ProxyConfigServiceAndroidTest, TestOverrideAndProxy) {
336   std::vector<std::string> bypass_rules;
337   bypass_rules.push_back("www.excluded.com");
338 
339   // Check that webview uses the default proxy
340   TestMapping("http://example.com/", "DIRECT");
341 
342   // Check that webview uses the custom proxy
343   SetProxyOverride({"*", "httpoverrideproxy.com:200"}, bypass_rules, false,
344                    base::DoNothing());
345   TestMapping("http://example.com/", "PROXY httpoverrideproxy.com:200");
346 
347   // Check that webview continues to use the custom proxy
348   AddProperty("http.proxyHost", "httpsomeproxy.com");
349   ProxySettingsChanged();
350   TestMapping("http://example.com/", "PROXY httpoverrideproxy.com:200");
351   TestMapping("http://www.excluded.com/", "DIRECT");
352 
353   // Check that webview uses the non default proxy
354   ClearProxyOverride(base::DoNothing());
355   TestMapping("http://example.com/", "PROXY httpsomeproxy.com:80");
356 }
357 
TEST_F(ProxyConfigServiceAndroidTest,TestProxyAndOverride)358 TEST_F(ProxyConfigServiceAndroidTest, TestProxyAndOverride) {
359   std::vector<std::string> bypass_rules;
360 
361   // Check that webview uses the default proxy
362   TestMapping("http://example.com/", "DIRECT");
363 
364   // Check that webview uses the non default proxy
365   AddProperty("http.proxyHost", "httpsomeproxy.com");
366   ProxySettingsChanged();
367   TestMapping("http://example.com/", "PROXY httpsomeproxy.com:80");
368 
369   // Check that webview uses the custom proxy
370   SetProxyOverride({"*", "httpoverrideproxy.com:200"}, bypass_rules, false,
371                    base::DoNothing());
372   TestMapping("http://example.com/", "PROXY httpoverrideproxy.com:200");
373 
374   // Check that webview uses the non default proxy
375   ClearProxyOverride(base::DoNothing());
376   TestMapping("http://example.com/", "PROXY httpsomeproxy.com:80");
377 }
378 
TEST_F(ProxyConfigServiceAndroidTest,TestOverrideThenProxy)379 TEST_F(ProxyConfigServiceAndroidTest, TestOverrideThenProxy) {
380   std::vector<std::string> bypass_rules;
381 
382   // Check that webview uses the default proxy
383   TestMapping("http://example.com/", "DIRECT");
384 
385   // Check that webview uses the custom proxy
386   SetProxyOverride({"*", "httpoverrideproxy.com:200"}, bypass_rules, false,
387                    base::DoNothing());
388   TestMapping("http://example.com/", "PROXY httpoverrideproxy.com:200");
389 
390   // Check that webview uses the default proxy
391   ClearProxyOverride(base::DoNothing());
392   TestMapping("http://example.com/", "DIRECT");
393 
394   // Check that webview uses the non default proxy
395   AddProperty("http.proxyHost", "httpsomeproxy.com");
396   ProxySettingsChanged();
397   TestMapping("http://example.com/", "PROXY httpsomeproxy.com:80");
398 }
399 
TEST_F(ProxyConfigServiceAndroidTest,TestClearOverride)400 TEST_F(ProxyConfigServiceAndroidTest, TestClearOverride) {
401   std::vector<std::string> bypass_rules;
402 
403   // Check that webview uses the default proxy
404   TestMapping("http://example.com/", "DIRECT");
405 
406   // Check that webview uses the default proxy
407   ClearProxyOverride(base::DoNothing());
408   TestMapping("http://example.com/", "DIRECT");
409 }
410 
TEST_F(ProxyConfigServiceAndroidTest,TestProxyAndClearOverride)411 TEST_F(ProxyConfigServiceAndroidTest, TestProxyAndClearOverride) {
412   std::vector<std::string> bypass_rules;
413 
414   // Check that webview uses the non default proxy
415   AddProperty("http.proxyHost", "httpsomeproxy.com");
416   ProxySettingsChanged();
417   TestMapping("http://example.com/", "PROXY httpsomeproxy.com:80");
418 
419   // Check that webview uses the non default proxy
420   ClearProxyOverride(base::DoNothing());
421   TestMapping("http://example.com/", "PROXY httpsomeproxy.com:80");
422 }
423 
TEST_F(ProxyConfigServiceAndroidTest,TestOverrideBypassRules)424 TEST_F(ProxyConfigServiceAndroidTest, TestOverrideBypassRules) {
425   std::vector<std::string> bypass_rules;
426   bypass_rules.push_back("excluded.com");
427 
428   // Check that webview uses the default proxy
429   TestMapping("http://excluded.com/", "DIRECT");
430   TestMapping("http://example.com/", "DIRECT");
431 
432   // Check that webview handles the bypass rules correctly
433   SetProxyOverride({"*", "httpoverrideproxy.com:200"}, bypass_rules, false,
434                    base::DoNothing());
435   TestMapping("http://excluded.com/", "DIRECT");
436   TestMapping("http://example.com/", "PROXY httpoverrideproxy.com:200");
437 
438   // Check that webview uses the default proxy
439   ClearProxyOverride(base::DoNothing());
440   TestMapping("http://excluded.com/", "DIRECT");
441   TestMapping("http://example.com/", "DIRECT");
442 }
443 
TEST_F(ProxyConfigServiceAndroidTest,TestOverrideToDirect)444 TEST_F(ProxyConfigServiceAndroidTest, TestOverrideToDirect) {
445   std::vector<std::string> bypass_rules;
446 
447   // Check that webview uses the non default proxy
448   AddProperty("http.proxyHost", "httpsomeproxy.com");
449   ProxySettingsChanged();
450   TestMapping("http://example.com/", "PROXY httpsomeproxy.com:80");
451 
452   // Check that webview uses no proxy
453   TestMapping("http://example.com/", "PROXY httpsomeproxy.com:80");
454   SetProxyOverride({"*", "direct://"}, bypass_rules, false, base::DoNothing());
455   TestMapping("http://example.com/", "DIRECT");
456 
457   ClearProxyOverride(base::DoNothing());
458 }
459 
TEST_F(ProxyConfigServiceAndroidTest,TestReverseBypass)460 TEST_F(ProxyConfigServiceAndroidTest, TestReverseBypass) {
461   std::vector<std::string> bypass_rules;
462 
463   // Check that webview uses the default proxy
464   TestMapping("http://example.com/", "DIRECT");
465   TestMapping("http://other.com/", "DIRECT");
466 
467   // Use a reverse bypass list, that is, WebView will only apply the proxy
468   // settings to URLs in the bypass list
469   bypass_rules.push_back("http://example.com");
470   SetProxyOverride({"*", "httpoverrideproxy.com:200"}, bypass_rules, true,
471                    base::DoNothing());
472 
473   // Check that URLs in the bypass list use the proxy
474   TestMapping("http://example.com/", "PROXY httpoverrideproxy.com:200");
475   TestMapping("http://other.com/", "DIRECT");
476 }
477 
478 // !! The following test cases are automatically generated from
479 // !! net/android/tools/proxy_test_cases.py.
480 // !! Please edit that file instead of editing the test cases below and
481 // !! update also the corresponding Java unit tests in
482 // !! AndroidProxySelectorTest.java
483 
TEST_F(ProxyConfigServiceAndroidTest,NoProxy)484 TEST_F(ProxyConfigServiceAndroidTest, NoProxy) {
485   // Test direct mapping when no proxy defined.
486   ProxySettingsChanged();
487   TestMapping("ftp://example.com/", "DIRECT");
488   TestMapping("http://example.com/", "DIRECT");
489   TestMapping("https://example.com/", "DIRECT");
490 }
491 
TEST_F(ProxyConfigServiceAndroidTest,HttpProxyHostAndPort)492 TEST_F(ProxyConfigServiceAndroidTest, HttpProxyHostAndPort) {
493   // Test http.proxyHost and http.proxyPort works.
494   AddProperty("http.proxyHost", "httpproxy.com");
495   AddProperty("http.proxyPort", "8080");
496   ProxySettingsChanged();
497   TestMapping("ftp://example.com/", "DIRECT");
498   TestMapping("http://example.com/", "PROXY httpproxy.com:8080");
499   TestMapping("https://example.com/", "DIRECT");
500 }
501 
TEST_F(ProxyConfigServiceAndroidTest,HttpProxyHostOnly)502 TEST_F(ProxyConfigServiceAndroidTest, HttpProxyHostOnly) {
503   // We should get the default port (80) for proxied hosts.
504   AddProperty("http.proxyHost", "httpproxy.com");
505   ProxySettingsChanged();
506   TestMapping("ftp://example.com/", "DIRECT");
507   TestMapping("http://example.com/", "PROXY httpproxy.com:80");
508   TestMapping("https://example.com/", "DIRECT");
509 }
510 
TEST_F(ProxyConfigServiceAndroidTest,HttpProxyPortOnly)511 TEST_F(ProxyConfigServiceAndroidTest, HttpProxyPortOnly) {
512   // http.proxyPort only should not result in any hosts being proxied.
513   AddProperty("http.proxyPort", "8080");
514   ProxySettingsChanged();
515   TestMapping("ftp://example.com/", "DIRECT");
516   TestMapping("http://example.com/", "DIRECT");
517   TestMapping("https://example.com/", "DIRECT");
518 }
519 
TEST_F(ProxyConfigServiceAndroidTest,HttpNonProxyHosts1)520 TEST_F(ProxyConfigServiceAndroidTest, HttpNonProxyHosts1) {
521   // Test that HTTP non proxy hosts are mapped correctly
522   AddProperty("http.nonProxyHosts", "slashdot.org");
523   AddProperty("http.proxyHost", "httpproxy.com");
524   AddProperty("http.proxyPort", "8080");
525   ProxySettingsChanged();
526   TestMapping("http://example.com/", "PROXY httpproxy.com:8080");
527   TestMapping("http://slashdot.org/", "DIRECT");
528 }
529 
TEST_F(ProxyConfigServiceAndroidTest,HttpNonProxyHosts2)530 TEST_F(ProxyConfigServiceAndroidTest, HttpNonProxyHosts2) {
531   // Test that | pattern works.
532   AddProperty("http.nonProxyHosts", "slashdot.org|freecode.net");
533   AddProperty("http.proxyHost", "httpproxy.com");
534   AddProperty("http.proxyPort", "8080");
535   ProxySettingsChanged();
536   TestMapping("http://example.com/", "PROXY httpproxy.com:8080");
537   TestMapping("http://freecode.net/", "DIRECT");
538   TestMapping("http://slashdot.org/", "DIRECT");
539 }
540 
TEST_F(ProxyConfigServiceAndroidTest,HttpNonProxyHosts3)541 TEST_F(ProxyConfigServiceAndroidTest, HttpNonProxyHosts3) {
542   // Test that * pattern works.
543   AddProperty("http.nonProxyHosts", "*example.com");
544   AddProperty("http.proxyHost", "httpproxy.com");
545   AddProperty("http.proxyPort", "8080");
546   ProxySettingsChanged();
547   TestMapping("http://example.com/", "DIRECT");
548   TestMapping("http://slashdot.org/", "PROXY httpproxy.com:8080");
549   TestMapping("http://www.example.com/", "DIRECT");
550 }
551 
TEST_F(ProxyConfigServiceAndroidTest,FtpNonProxyHosts)552 TEST_F(ProxyConfigServiceAndroidTest, FtpNonProxyHosts) {
553   // Test that FTP non proxy hosts are mapped correctly
554   AddProperty("ftp.nonProxyHosts", "slashdot.org");
555   AddProperty("ftp.proxyHost", "httpproxy.com");
556   AddProperty("ftp.proxyPort", "8080");
557   ProxySettingsChanged();
558   TestMapping("ftp://example.com/", "PROXY httpproxy.com:8080");
559   TestMapping("http://example.com/", "DIRECT");
560 }
561 
TEST_F(ProxyConfigServiceAndroidTest,FtpProxyHostAndPort)562 TEST_F(ProxyConfigServiceAndroidTest, FtpProxyHostAndPort) {
563   // Test ftp.proxyHost and ftp.proxyPort works.
564   AddProperty("ftp.proxyHost", "httpproxy.com");
565   AddProperty("ftp.proxyPort", "8080");
566   ProxySettingsChanged();
567   TestMapping("ftp://example.com/", "PROXY httpproxy.com:8080");
568   TestMapping("http://example.com/", "DIRECT");
569   TestMapping("https://example.com/", "DIRECT");
570 }
571 
TEST_F(ProxyConfigServiceAndroidTest,FtpProxyHostOnly)572 TEST_F(ProxyConfigServiceAndroidTest, FtpProxyHostOnly) {
573   // Test ftp.proxyHost and default port.
574   AddProperty("ftp.proxyHost", "httpproxy.com");
575   ProxySettingsChanged();
576   TestMapping("ftp://example.com/", "PROXY httpproxy.com:80");
577   TestMapping("http://example.com/", "DIRECT");
578   TestMapping("https://example.com/", "DIRECT");
579 }
580 
TEST_F(ProxyConfigServiceAndroidTest,HttpsProxyHostAndPort)581 TEST_F(ProxyConfigServiceAndroidTest, HttpsProxyHostAndPort) {
582   // Test https.proxyHost and https.proxyPort works.
583   AddProperty("https.proxyHost", "httpproxy.com");
584   AddProperty("https.proxyPort", "8080");
585   ProxySettingsChanged();
586   TestMapping("ftp://example.com/", "DIRECT");
587   TestMapping("http://example.com/", "DIRECT");
588   TestMapping("https://example.com/", "PROXY httpproxy.com:8080");
589 }
590 
TEST_F(ProxyConfigServiceAndroidTest,HttpsProxyHostOnly)591 TEST_F(ProxyConfigServiceAndroidTest, HttpsProxyHostOnly) {
592   // Test https.proxyHost and default port.
593   AddProperty("https.proxyHost", "httpproxy.com");
594   ProxySettingsChanged();
595   TestMapping("ftp://example.com/", "DIRECT");
596   TestMapping("http://example.com/", "DIRECT");
597   TestMapping("https://example.com/", "PROXY httpproxy.com:80");
598 }
599 
TEST_F(ProxyConfigServiceAndroidTest,HttpProxyHostIPv6)600 TEST_F(ProxyConfigServiceAndroidTest, HttpProxyHostIPv6) {
601   // Test IPv6 https.proxyHost and default port.
602   AddProperty("http.proxyHost", "a:b:c::d:1");
603   ProxySettingsChanged();
604   TestMapping("ftp://example.com/", "DIRECT");
605   TestMapping("http://example.com/", "PROXY [a:b:c::d:1]:80");
606 }
607 
TEST_F(ProxyConfigServiceAndroidTest,HttpProxyHostAndPortIPv6)608 TEST_F(ProxyConfigServiceAndroidTest, HttpProxyHostAndPortIPv6) {
609   // Test IPv6 http.proxyHost and http.proxyPort works.
610   AddProperty("http.proxyHost", "a:b:c::d:1");
611   AddProperty("http.proxyPort", "8080");
612   ProxySettingsChanged();
613   TestMapping("ftp://example.com/", "DIRECT");
614   TestMapping("http://example.com/", "PROXY [a:b:c::d:1]:8080");
615 }
616 
TEST_F(ProxyConfigServiceAndroidTest,HttpProxyHostAndInvalidPort)617 TEST_F(ProxyConfigServiceAndroidTest, HttpProxyHostAndInvalidPort) {
618   // Test invalid http.proxyPort does not crash.
619   AddProperty("http.proxyHost", "a:b:c::d:1");
620   AddProperty("http.proxyPort", "65536");
621   ProxySettingsChanged();
622   TestMapping("ftp://example.com/", "DIRECT");
623   TestMapping("http://example.com/", "DIRECT");
624 }
625 
TEST_F(ProxyConfigServiceAndroidTest,DefaultProxyExplictPort)626 TEST_F(ProxyConfigServiceAndroidTest, DefaultProxyExplictPort) {
627   // Default http proxy is used if a scheme-specific one is not found.
628   AddProperty("ftp.proxyHost", "httpproxy.com");
629   AddProperty("ftp.proxyPort", "8080");
630   AddProperty("proxyHost", "defaultproxy.com");
631   AddProperty("proxyPort", "8080");
632   ProxySettingsChanged();
633   TestMapping("ftp://example.com/", "PROXY httpproxy.com:8080");
634   TestMapping("http://example.com/", "PROXY defaultproxy.com:8080");
635   TestMapping("https://example.com/", "PROXY defaultproxy.com:8080");
636 }
637 
TEST_F(ProxyConfigServiceAndroidTest,DefaultProxyDefaultPort)638 TEST_F(ProxyConfigServiceAndroidTest, DefaultProxyDefaultPort) {
639   // Check that the default proxy port is as expected.
640   AddProperty("proxyHost", "defaultproxy.com");
641   ProxySettingsChanged();
642   TestMapping("http://example.com/", "PROXY defaultproxy.com:80");
643   TestMapping("https://example.com/", "PROXY defaultproxy.com:80");
644 }
645 
TEST_F(ProxyConfigServiceAndroidTest,FallbackToSocks)646 TEST_F(ProxyConfigServiceAndroidTest, FallbackToSocks) {
647   // SOCKS proxy is used if scheme-specific one is not found.
648   AddProperty("http.proxyHost", "defaultproxy.com");
649   AddProperty("socksProxyHost", "socksproxy.com");
650   ProxySettingsChanged();
651   TestMapping("ftp://example.com", "SOCKS5 socksproxy.com:1080");
652   TestMapping("http://example.com/", "PROXY defaultproxy.com:80");
653   TestMapping("https://example.com/", "SOCKS5 socksproxy.com:1080");
654 }
655 
TEST_F(ProxyConfigServiceAndroidTest,SocksExplicitPort)656 TEST_F(ProxyConfigServiceAndroidTest, SocksExplicitPort) {
657   // SOCKS proxy port is used if specified
658   AddProperty("socksProxyHost", "socksproxy.com");
659   AddProperty("socksProxyPort", "9000");
660   ProxySettingsChanged();
661   TestMapping("http://example.com/", "SOCKS5 socksproxy.com:9000");
662 }
663 
TEST_F(ProxyConfigServiceAndroidTest,HttpProxySupercedesSocks)664 TEST_F(ProxyConfigServiceAndroidTest, HttpProxySupercedesSocks) {
665   // SOCKS proxy is ignored if default HTTP proxy defined.
666   AddProperty("proxyHost", "defaultproxy.com");
667   AddProperty("socksProxyHost", "socksproxy.com");
668   AddProperty("socksProxyPort", "9000");
669   ProxySettingsChanged();
670   TestMapping("http://example.com/", "PROXY defaultproxy.com:80");
671 }
672 
673 }  // namespace net
674