• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include <map>
6 #include <string>
7 
8 #include "base/bind.h"
9 #include "base/compiler_specific.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/message_loop/message_loop.h"
12 #include "net/proxy/proxy_config.h"
13 #include "net/proxy/proxy_config_service_android.h"
14 #include "net/proxy/proxy_info.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 
17 namespace net {
18 
19 namespace {
20 
21 class TestObserver : public ProxyConfigService::Observer {
22  public:
TestObserver()23   TestObserver() : availability_(ProxyConfigService::CONFIG_UNSET) {}
24 
25   // ProxyConfigService::Observer:
OnProxyConfigChanged(const ProxyConfig & config,ProxyConfigService::ConfigAvailability availability)26   virtual void OnProxyConfigChanged(
27       const ProxyConfig& config,
28       ProxyConfigService::ConfigAvailability availability) OVERRIDE {
29     config_ = config;
30     availability_ = availability;
31   }
32 
availability() const33   ProxyConfigService::ConfigAvailability availability() const {
34     return availability_;
35   }
36 
config() const37   const ProxyConfig& config() const {
38     return config_;
39   }
40 
41  private:
42   ProxyConfig config_;
43   ProxyConfigService::ConfigAvailability availability_;
44 };
45 
46 }  // namespace
47 
48 typedef std::map<std::string, std::string> StringMap;
49 
50 class ProxyConfigServiceAndroidTestBase : public testing::Test {
51  protected:
52   // Note that the current thread's message loop is initialized by the test
53   // suite (see net/test/net_test_suite.cc).
ProxyConfigServiceAndroidTestBase(const StringMap & initial_configuration)54   ProxyConfigServiceAndroidTestBase(const StringMap& initial_configuration)
55       : configuration_(initial_configuration),
56         message_loop_(base::MessageLoop::current()),
57         service_(message_loop_->message_loop_proxy(),
58                  message_loop_->message_loop_proxy(),
59                  base::Bind(&ProxyConfigServiceAndroidTestBase::GetProperty,
60                             base::Unretained(this))) {}
61 
~ProxyConfigServiceAndroidTestBase()62   virtual ~ProxyConfigServiceAndroidTestBase() {}
63 
64   // testing::Test:
SetUp()65   virtual void SetUp() OVERRIDE {
66     message_loop_->RunUntilIdle();
67     service_.AddObserver(&observer_);
68   }
69 
TearDown()70   virtual void TearDown() OVERRIDE {
71     service_.RemoveObserver(&observer_);
72   }
73 
ClearConfiguration()74   void ClearConfiguration() {
75     configuration_.clear();
76   }
77 
AddProperty(const std::string & key,const std::string & value)78   void AddProperty(const std::string& key, const std::string& value) {
79     configuration_[key] = value;
80   }
81 
GetProperty(const std::string & key)82   std::string GetProperty(const std::string& key) {
83     StringMap::const_iterator it = configuration_.find(key);
84     if (it == configuration_.end())
85       return std::string();
86     return it->second;
87   }
88 
ProxySettingsChanged()89   void ProxySettingsChanged() {
90     service_.ProxySettingsChanged();
91     message_loop_->RunUntilIdle();
92   }
93 
TestMapping(const std::string & url,const std::string & expected)94   void TestMapping(const std::string& url, const std::string& expected) {
95     ProxyConfigService::ConfigAvailability availability;
96     ProxyConfig proxy_config;
97     availability = service_.GetLatestProxyConfig(&proxy_config);
98     EXPECT_EQ(ProxyConfigService::CONFIG_VALID, availability);
99     ProxyInfo proxy_info;
100     proxy_config.proxy_rules().Apply(GURL(url), &proxy_info);
101     EXPECT_EQ(expected, proxy_info.ToPacString());
102   }
103 
104   StringMap configuration_;
105   TestObserver observer_;
106   base::MessageLoop* const message_loop_;
107   ProxyConfigServiceAndroid service_;
108 };
109 
110 class ProxyConfigServiceAndroidTest : public ProxyConfigServiceAndroidTestBase {
111  public:
ProxyConfigServiceAndroidTest()112   ProxyConfigServiceAndroidTest()
113       : ProxyConfigServiceAndroidTestBase(StringMap()) {}
114 };
115 
116 class ProxyConfigServiceAndroidWithInitialConfigTest
117     : public ProxyConfigServiceAndroidTestBase {
118  public:
ProxyConfigServiceAndroidWithInitialConfigTest()119   ProxyConfigServiceAndroidWithInitialConfigTest()
120       : ProxyConfigServiceAndroidTestBase(MakeInitialConfiguration()) {}
121 
122  private:
MakeInitialConfiguration()123   StringMap MakeInitialConfiguration() {
124     StringMap initial_configuration;
125     initial_configuration["http.proxyHost"] = "httpproxy.com";
126     initial_configuration["http.proxyPort"] = "8080";
127     return initial_configuration;
128   }
129 };
130 
TEST_F(ProxyConfigServiceAndroidTest,TestChangePropertiesNotification)131 TEST_F(ProxyConfigServiceAndroidTest, TestChangePropertiesNotification) {
132   // Set up a non-empty configuration
133   AddProperty("http.proxyHost", "localhost");
134   ProxySettingsChanged();
135   EXPECT_EQ(ProxyConfigService::CONFIG_VALID, observer_.availability());
136   EXPECT_FALSE(observer_.config().proxy_rules().empty());
137 
138   // Set up an empty configuration
139   ClearConfiguration();
140   ProxySettingsChanged();
141   EXPECT_EQ(ProxyConfigService::CONFIG_VALID, observer_.availability());
142   EXPECT_TRUE(observer_.config().proxy_rules().empty());
143 }
144 
TEST_F(ProxyConfigServiceAndroidWithInitialConfigTest,TestInitialConfig)145 TEST_F(ProxyConfigServiceAndroidWithInitialConfigTest, TestInitialConfig) {
146   // Make sure that the initial config is set.
147   TestMapping("ftp://example.com/", "DIRECT");
148   TestMapping("http://example.com/", "PROXY httpproxy.com:8080");
149 
150   // Override the initial configuration.
151   ClearConfiguration();
152   AddProperty("http.proxyHost", "httpproxy.com");
153   ProxySettingsChanged();
154   TestMapping("http://example.com/", "PROXY httpproxy.com:80");
155 }
156 
157 // !! The following test cases are automatically generated from
158 // !! net/android/tools/proxy_test_cases.py.
159 // !! Please edit that file instead of editing the test cases below and
160 // !! update also the corresponding Java unit tests in
161 // !! AndroidProxySelectorTest.java
162 
TEST_F(ProxyConfigServiceAndroidTest,NoProxy)163 TEST_F(ProxyConfigServiceAndroidTest, NoProxy) {
164   // Test direct mapping when no proxy defined.
165   ProxySettingsChanged();
166   TestMapping("ftp://example.com/", "DIRECT");
167   TestMapping("http://example.com/", "DIRECT");
168   TestMapping("https://example.com/", "DIRECT");
169 }
170 
TEST_F(ProxyConfigServiceAndroidTest,HttpProxyHostAndPort)171 TEST_F(ProxyConfigServiceAndroidTest, HttpProxyHostAndPort) {
172   // Test http.proxyHost and http.proxyPort works.
173   AddProperty("http.proxyHost", "httpproxy.com");
174   AddProperty("http.proxyPort", "8080");
175   ProxySettingsChanged();
176   TestMapping("ftp://example.com/", "DIRECT");
177   TestMapping("http://example.com/", "PROXY httpproxy.com:8080");
178   TestMapping("https://example.com/", "DIRECT");
179 }
180 
TEST_F(ProxyConfigServiceAndroidTest,HttpProxyHostOnly)181 TEST_F(ProxyConfigServiceAndroidTest, HttpProxyHostOnly) {
182   // We should get the default port (80) for proxied hosts.
183   AddProperty("http.proxyHost", "httpproxy.com");
184   ProxySettingsChanged();
185   TestMapping("ftp://example.com/", "DIRECT");
186   TestMapping("http://example.com/", "PROXY httpproxy.com:80");
187   TestMapping("https://example.com/", "DIRECT");
188 }
189 
TEST_F(ProxyConfigServiceAndroidTest,HttpProxyPortOnly)190 TEST_F(ProxyConfigServiceAndroidTest, HttpProxyPortOnly) {
191   // http.proxyPort only should not result in any hosts being proxied.
192   AddProperty("http.proxyPort", "8080");
193   ProxySettingsChanged();
194   TestMapping("ftp://example.com/", "DIRECT");
195   TestMapping("http://example.com/", "DIRECT");
196   TestMapping("https://example.com/", "DIRECT");
197 }
198 
TEST_F(ProxyConfigServiceAndroidTest,HttpNonProxyHosts1)199 TEST_F(ProxyConfigServiceAndroidTest, HttpNonProxyHosts1) {
200   // Test that HTTP non proxy hosts are mapped correctly
201   AddProperty("http.nonProxyHosts", "slashdot.org");
202   AddProperty("http.proxyHost", "httpproxy.com");
203   AddProperty("http.proxyPort", "8080");
204   ProxySettingsChanged();
205   TestMapping("http://example.com/", "PROXY httpproxy.com:8080");
206   TestMapping("http://slashdot.org/", "DIRECT");
207 }
208 
TEST_F(ProxyConfigServiceAndroidTest,HttpNonProxyHosts2)209 TEST_F(ProxyConfigServiceAndroidTest, HttpNonProxyHosts2) {
210   // Test that | pattern works.
211   AddProperty("http.nonProxyHosts", "slashdot.org|freecode.net");
212   AddProperty("http.proxyHost", "httpproxy.com");
213   AddProperty("http.proxyPort", "8080");
214   ProxySettingsChanged();
215   TestMapping("http://example.com/", "PROXY httpproxy.com:8080");
216   TestMapping("http://freecode.net/", "DIRECT");
217   TestMapping("http://slashdot.org/", "DIRECT");
218 }
219 
TEST_F(ProxyConfigServiceAndroidTest,HttpNonProxyHosts3)220 TEST_F(ProxyConfigServiceAndroidTest, HttpNonProxyHosts3) {
221   // Test that * pattern works.
222   AddProperty("http.nonProxyHosts", "*example.com");
223   AddProperty("http.proxyHost", "httpproxy.com");
224   AddProperty("http.proxyPort", "8080");
225   ProxySettingsChanged();
226   TestMapping("http://example.com/", "DIRECT");
227   TestMapping("http://slashdot.org/", "PROXY httpproxy.com:8080");
228   TestMapping("http://www.example.com/", "DIRECT");
229 }
230 
TEST_F(ProxyConfigServiceAndroidTest,FtpNonProxyHosts)231 TEST_F(ProxyConfigServiceAndroidTest, FtpNonProxyHosts) {
232   // Test that FTP non proxy hosts are mapped correctly
233   AddProperty("ftp.nonProxyHosts", "slashdot.org");
234   AddProperty("ftp.proxyHost", "httpproxy.com");
235   AddProperty("ftp.proxyPort", "8080");
236   ProxySettingsChanged();
237   TestMapping("ftp://example.com/", "PROXY httpproxy.com:8080");
238   TestMapping("http://example.com/", "DIRECT");
239 }
240 
TEST_F(ProxyConfigServiceAndroidTest,FtpProxyHostAndPort)241 TEST_F(ProxyConfigServiceAndroidTest, FtpProxyHostAndPort) {
242   // Test ftp.proxyHost and ftp.proxyPort works.
243   AddProperty("ftp.proxyHost", "httpproxy.com");
244   AddProperty("ftp.proxyPort", "8080");
245   ProxySettingsChanged();
246   TestMapping("ftp://example.com/", "PROXY httpproxy.com:8080");
247   TestMapping("http://example.com/", "DIRECT");
248   TestMapping("https://example.com/", "DIRECT");
249 }
250 
TEST_F(ProxyConfigServiceAndroidTest,FtpProxyHostOnly)251 TEST_F(ProxyConfigServiceAndroidTest, FtpProxyHostOnly) {
252   // Test ftp.proxyHost and default port.
253   AddProperty("ftp.proxyHost", "httpproxy.com");
254   ProxySettingsChanged();
255   TestMapping("ftp://example.com/", "PROXY httpproxy.com:80");
256   TestMapping("http://example.com/", "DIRECT");
257   TestMapping("https://example.com/", "DIRECT");
258 }
259 
TEST_F(ProxyConfigServiceAndroidTest,HttpsProxyHostAndPort)260 TEST_F(ProxyConfigServiceAndroidTest, HttpsProxyHostAndPort) {
261   // Test https.proxyHost and https.proxyPort works.
262   AddProperty("https.proxyHost", "httpproxy.com");
263   AddProperty("https.proxyPort", "8080");
264   ProxySettingsChanged();
265   TestMapping("ftp://example.com/", "DIRECT");
266   TestMapping("http://example.com/", "DIRECT");
267   TestMapping("https://example.com/", "PROXY httpproxy.com:8080");
268 }
269 
TEST_F(ProxyConfigServiceAndroidTest,HttpsProxyHostOnly)270 TEST_F(ProxyConfigServiceAndroidTest, HttpsProxyHostOnly) {
271   // Test https.proxyHost and default port.
272   AddProperty("https.proxyHost", "httpproxy.com");
273   ProxySettingsChanged();
274   TestMapping("ftp://example.com/", "DIRECT");
275   TestMapping("http://example.com/", "DIRECT");
276   TestMapping("https://example.com/", "PROXY httpproxy.com:80");
277 }
278 
TEST_F(ProxyConfigServiceAndroidTest,HttpProxyHostIPv6)279 TEST_F(ProxyConfigServiceAndroidTest, HttpProxyHostIPv6) {
280   // Test IPv6 https.proxyHost and default port.
281   AddProperty("http.proxyHost", "a:b:c::d:1");
282   ProxySettingsChanged();
283   TestMapping("ftp://example.com/", "DIRECT");
284   TestMapping("http://example.com/", "PROXY [a:b:c::d:1]:80");
285 }
286 
TEST_F(ProxyConfigServiceAndroidTest,HttpProxyHostAndPortIPv6)287 TEST_F(ProxyConfigServiceAndroidTest, HttpProxyHostAndPortIPv6) {
288   // Test IPv6 http.proxyHost and http.proxyPort works.
289   AddProperty("http.proxyHost", "a:b:c::d:1");
290   AddProperty("http.proxyPort", "8080");
291   ProxySettingsChanged();
292   TestMapping("ftp://example.com/", "DIRECT");
293   TestMapping("http://example.com/", "PROXY [a:b:c::d:1]:8080");
294 }
295 
TEST_F(ProxyConfigServiceAndroidTest,HttpProxyHostAndInvalidPort)296 TEST_F(ProxyConfigServiceAndroidTest, HttpProxyHostAndInvalidPort) {
297   // Test invalid http.proxyPort does not crash.
298   AddProperty("http.proxyHost", "a:b:c::d:1");
299   AddProperty("http.proxyPort", "65536");
300   ProxySettingsChanged();
301   TestMapping("ftp://example.com/", "DIRECT");
302   TestMapping("http://example.com/", "DIRECT");
303 }
304 
TEST_F(ProxyConfigServiceAndroidTest,DefaultProxyExplictPort)305 TEST_F(ProxyConfigServiceAndroidTest, DefaultProxyExplictPort) {
306   // Default http proxy is used if a scheme-specific one is not found.
307   AddProperty("ftp.proxyHost", "httpproxy.com");
308   AddProperty("ftp.proxyPort", "8080");
309   AddProperty("proxyHost", "defaultproxy.com");
310   AddProperty("proxyPort", "8080");
311   ProxySettingsChanged();
312   TestMapping("ftp://example.com/", "PROXY httpproxy.com:8080");
313   TestMapping("http://example.com/", "PROXY defaultproxy.com:8080");
314   TestMapping("https://example.com/", "PROXY defaultproxy.com:8080");
315 }
316 
TEST_F(ProxyConfigServiceAndroidTest,DefaultProxyDefaultPort)317 TEST_F(ProxyConfigServiceAndroidTest, DefaultProxyDefaultPort) {
318   // Check that the default proxy port is as expected.
319   AddProperty("proxyHost", "defaultproxy.com");
320   ProxySettingsChanged();
321   TestMapping("http://example.com/", "PROXY defaultproxy.com:80");
322   TestMapping("https://example.com/", "PROXY defaultproxy.com:80");
323 }
324 
TEST_F(ProxyConfigServiceAndroidTest,FallbackToSocks)325 TEST_F(ProxyConfigServiceAndroidTest, FallbackToSocks) {
326   // SOCKS proxy is used if scheme-specific one is not found.
327   AddProperty("http.proxyHost", "defaultproxy.com");
328   AddProperty("socksProxyHost", "socksproxy.com");
329   ProxySettingsChanged();
330   TestMapping("ftp://example.com", "SOCKS5 socksproxy.com:1080");
331   TestMapping("http://example.com/", "PROXY defaultproxy.com:80");
332   TestMapping("https://example.com/", "SOCKS5 socksproxy.com:1080");
333 }
334 
TEST_F(ProxyConfigServiceAndroidTest,SocksExplicitPort)335 TEST_F(ProxyConfigServiceAndroidTest, SocksExplicitPort) {
336   // SOCKS proxy port is used if specified
337   AddProperty("socksProxyHost", "socksproxy.com");
338   AddProperty("socksProxyPort", "9000");
339   ProxySettingsChanged();
340   TestMapping("http://example.com/", "SOCKS5 socksproxy.com:9000");
341 }
342 
TEST_F(ProxyConfigServiceAndroidTest,HttpProxySupercedesSocks)343 TEST_F(ProxyConfigServiceAndroidTest, HttpProxySupercedesSocks) {
344   // SOCKS proxy is ignored if default HTTP proxy defined.
345   AddProperty("proxyHost", "defaultproxy.com");
346   AddProperty("socksProxyHost", "socksproxy.com");
347   AddProperty("socksProxyPort", "9000");
348   ProxySettingsChanged();
349   TestMapping("http://example.com/", "PROXY defaultproxy.com:80");
350 }
351 
352 }  // namespace net
353