• 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 "net/proxy/proxy_config.h"
6 #include "net/proxy/proxy_config_service_common_unittest.h"
7 #include "net/proxy/proxy_info.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9 
10 namespace net {
11 namespace {
12 
ExpectProxyServerEquals(const char * expectation,const ProxyList & proxy_servers)13 void ExpectProxyServerEquals(const char* expectation,
14                              const ProxyList& proxy_servers) {
15   if (expectation == NULL) {
16     EXPECT_TRUE(proxy_servers.IsEmpty());
17   } else {
18     EXPECT_EQ(expectation, proxy_servers.ToPacString());
19   }
20 }
21 
TEST(ProxyConfigTest,Equals)22 TEST(ProxyConfigTest, Equals) {
23   // Test |ProxyConfig::auto_detect|.
24 
25   ProxyConfig config1;
26   config1.set_auto_detect(true);
27 
28   ProxyConfig config2;
29   config2.set_auto_detect(false);
30 
31   EXPECT_FALSE(config1.Equals(config2));
32   EXPECT_FALSE(config2.Equals(config1));
33 
34   config2.set_auto_detect(true);
35 
36   EXPECT_TRUE(config1.Equals(config2));
37   EXPECT_TRUE(config2.Equals(config1));
38 
39   // Test |ProxyConfig::pac_url|.
40 
41   config2.set_pac_url(GURL("http://wpad/wpad.dat"));
42 
43   EXPECT_FALSE(config1.Equals(config2));
44   EXPECT_FALSE(config2.Equals(config1));
45 
46   config1.set_pac_url(GURL("http://wpad/wpad.dat"));
47 
48   EXPECT_TRUE(config1.Equals(config2));
49   EXPECT_TRUE(config2.Equals(config1));
50 
51   // Test |ProxyConfig::proxy_rules|.
52 
53   config2.proxy_rules().type = ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY;
54   config2.proxy_rules().single_proxies.SetSingleProxyServer(
55       ProxyServer::FromURI("myproxy:80", ProxyServer::SCHEME_HTTP));
56 
57   EXPECT_FALSE(config1.Equals(config2));
58   EXPECT_FALSE(config2.Equals(config1));
59 
60   config1.proxy_rules().type = ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY;
61   config1.proxy_rules().single_proxies.SetSingleProxyServer(
62       ProxyServer::FromURI("myproxy:100", ProxyServer::SCHEME_HTTP));
63 
64   EXPECT_FALSE(config1.Equals(config2));
65   EXPECT_FALSE(config2.Equals(config1));
66 
67   config1.proxy_rules().single_proxies.SetSingleProxyServer(
68       ProxyServer::FromURI("myproxy", ProxyServer::SCHEME_HTTP));
69 
70   EXPECT_TRUE(config1.Equals(config2));
71   EXPECT_TRUE(config2.Equals(config1));
72 
73   // Test |ProxyConfig::bypass_rules|.
74 
75   config2.proxy_rules().bypass_rules.AddRuleFromString("*.google.com");
76 
77   EXPECT_FALSE(config1.Equals(config2));
78   EXPECT_FALSE(config2.Equals(config1));
79 
80   config1.proxy_rules().bypass_rules.AddRuleFromString("*.google.com");
81 
82   EXPECT_TRUE(config1.Equals(config2));
83   EXPECT_TRUE(config2.Equals(config1));
84 
85   // Test |ProxyConfig::proxy_rules.reverse_bypass|.
86 
87   config2.proxy_rules().reverse_bypass = true;
88 
89   EXPECT_FALSE(config1.Equals(config2));
90   EXPECT_FALSE(config2.Equals(config1));
91 
92   config1.proxy_rules().reverse_bypass = true;
93 
94   EXPECT_TRUE(config1.Equals(config2));
95   EXPECT_TRUE(config2.Equals(config1));
96 }
97 
TEST(ProxyConfigTest,ParseProxyRules)98 TEST(ProxyConfigTest, ParseProxyRules) {
99   const struct {
100     const char* proxy_rules;
101 
102     ProxyConfig::ProxyRules::Type type;
103     // These will be PAC-stle strings, eg 'PROXY foo.com'
104     const char* single_proxy;
105     const char* proxy_for_http;
106     const char* proxy_for_https;
107     const char* proxy_for_ftp;
108     const char* fallback_proxy;
109   } tests[] = {
110     // One HTTP proxy for all schemes.
111     {
112       "myproxy:80",
113 
114       ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY,
115       "PROXY myproxy:80",
116       NULL,
117       NULL,
118       NULL,
119       NULL,
120     },
121 
122     // Multiple HTTP proxies for all schemes.
123     {
124       "myproxy:80,https://myotherproxy",
125 
126       ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY,
127       "PROXY myproxy:80;HTTPS myotherproxy:443",
128       NULL,
129       NULL,
130       NULL,
131       NULL,
132     },
133 
134     // Only specify a proxy server for "http://" urls.
135     {
136       "http=myproxy:80",
137 
138       ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
139       NULL,
140       "PROXY myproxy:80",
141       NULL,
142       NULL,
143       NULL,
144     },
145 
146     // Specify an HTTP proxy for "ftp://" and a SOCKS proxy for "https://" urls.
147     {
148       "ftp=ftp-proxy ; https=socks4://foopy",
149 
150       ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
151       NULL,
152       NULL,
153       "SOCKS foopy:1080",
154       "PROXY ftp-proxy:80",
155       NULL,
156     },
157 
158     // Give a scheme-specific proxy as well as a non-scheme specific.
159     // The first entry "foopy" takes precedance marking this list as
160     // TYPE_SINGLE_PROXY.
161     {
162       "foopy ; ftp=ftp-proxy",
163 
164       ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY,
165       "PROXY foopy:80",
166       NULL,
167       NULL,
168       NULL,
169       NULL,
170     },
171 
172     // Give a scheme-specific proxy as well as a non-scheme specific.
173     // The first entry "ftp=ftp-proxy" takes precedance marking this list as
174     // TYPE_PROXY_PER_SCHEME.
175     {
176       "ftp=ftp-proxy ; foopy",
177 
178       ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
179       NULL,
180       NULL,
181       NULL,
182       "PROXY ftp-proxy:80",
183       NULL,
184     },
185 
186     // Include a list of entries for a single scheme.
187     {
188       "ftp=ftp1,ftp2,ftp3",
189 
190       ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
191       NULL,
192       NULL,
193       NULL,
194       "PROXY ftp1:80;PROXY ftp2:80;PROXY ftp3:80",
195       NULL,
196     },
197 
198     // Include multiple entries for the same scheme -- they accumulate.
199     {
200       "http=http1,http2; http=http3",
201 
202       ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
203       NULL,
204       "PROXY http1:80;PROXY http2:80;PROXY http3:80",
205       NULL,
206       NULL,
207       NULL,
208     },
209 
210     // Include lists of entries for multiple schemes.
211     {
212       "ftp=ftp1,ftp2,ftp3 ; http=http1,http2; ",
213 
214       ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
215       NULL,
216       "PROXY http1:80;PROXY http2:80",
217       NULL,
218       "PROXY ftp1:80;PROXY ftp2:80;PROXY ftp3:80",
219       NULL,
220     },
221 
222     // Include non-default proxy schemes.
223     {
224       "http=https://secure_proxy; ftp=socks4://socks_proxy; https=socks://foo",
225 
226       ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
227       NULL,
228       "HTTPS secure_proxy:443",
229       "SOCKS5 foo:1080",
230       "SOCKS socks_proxy:1080",
231       NULL,
232     },
233 
234     // Only SOCKS proxy present, others being blank.
235     {
236       "socks=foopy",
237 
238       ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
239       NULL,
240       NULL,
241       NULL,
242       NULL,
243       "SOCKS foopy:1080",
244       },
245 
246     // SOCKS proxy present along with other proxies too
247     {
248       "http=httpproxy ; https=httpsproxy ; ftp=ftpproxy ; socks=foopy ",
249 
250       ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
251       NULL,
252       "PROXY httpproxy:80",
253       "PROXY httpsproxy:80",
254       "PROXY ftpproxy:80",
255       "SOCKS foopy:1080",
256     },
257 
258     // SOCKS proxy (with modifier) present along with some proxies
259     // (FTP being blank)
260     {
261       "http=httpproxy ; https=httpsproxy ; socks=socks5://foopy ",
262 
263       ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
264       NULL,
265       "PROXY httpproxy:80",
266       "PROXY httpsproxy:80",
267       NULL,
268       "SOCKS5 foopy:1080",
269       },
270 
271     // Include unsupported schemes -- they are discarded.
272     {
273       "crazy=foopy ; foo=bar ; https=myhttpsproxy",
274 
275       ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
276       NULL,
277       NULL,
278       "PROXY myhttpsproxy:80",
279       NULL,
280       NULL,
281     },
282 
283     // direct:// as first option for a scheme.
284     {
285       "http=direct://,myhttpproxy; https=direct://",
286 
287       ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
288       NULL,
289       "DIRECT;PROXY myhttpproxy:80",
290       "DIRECT",
291       NULL,
292       NULL,
293     },
294 
295     // direct:// as a second option for a scheme.
296     {
297       "http=myhttpproxy,direct://",
298 
299       ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
300       NULL,
301       "PROXY myhttpproxy:80;DIRECT",
302       NULL,
303       NULL,
304       NULL,
305     },
306 
307   };
308 
309   ProxyConfig config;
310 
311   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
312     config.proxy_rules().ParseFromString(tests[i].proxy_rules);
313 
314     EXPECT_EQ(tests[i].type, config.proxy_rules().type);
315     ExpectProxyServerEquals(tests[i].single_proxy,
316                             config.proxy_rules().single_proxies);
317     ExpectProxyServerEquals(tests[i].proxy_for_http,
318                             config.proxy_rules().proxies_for_http);
319     ExpectProxyServerEquals(tests[i].proxy_for_https,
320                             config.proxy_rules().proxies_for_https);
321     ExpectProxyServerEquals(tests[i].proxy_for_ftp,
322                             config.proxy_rules().proxies_for_ftp);
323     ExpectProxyServerEquals(tests[i].fallback_proxy,
324                             config.proxy_rules().fallback_proxies);
325   }
326 }
327 
TEST(ProxyConfigTest,ProxyRulesSetBypassFlag)328 TEST(ProxyConfigTest, ProxyRulesSetBypassFlag) {
329   // Test whether the did_bypass_proxy() flag is set in proxy info correctly.
330   ProxyConfig::ProxyRules rules;
331   ProxyInfo  result;
332 
333   rules.ParseFromString("http=httpproxy:80");
334   rules.bypass_rules.AddRuleFromString(".com");
335 
336   rules.Apply(GURL("http://example.com"), &result);
337   EXPECT_TRUE(result.is_direct_only());
338   EXPECT_TRUE(result.did_bypass_proxy());
339 
340   rules.Apply(GURL("http://example.org"), &result);
341   EXPECT_FALSE(result.is_direct());
342   EXPECT_FALSE(result.did_bypass_proxy());
343 
344   // Try with reversed bypass rules.
345   rules.reverse_bypass = true;
346 
347   rules.Apply(GURL("http://example.org"), &result);
348   EXPECT_TRUE(result.is_direct_only());
349   EXPECT_TRUE(result.did_bypass_proxy());
350 
351   rules.Apply(GURL("http://example.com"), &result);
352   EXPECT_FALSE(result.is_direct());
353   EXPECT_FALSE(result.did_bypass_proxy());
354 }
355 
356 static const char kWsUrl[] = "ws://example.com/echo";
357 static const char kWssUrl[] = "wss://example.com/echo";
358 
359 class ProxyConfigWebSocketTest : public ::testing::Test {
360  protected:
ParseFromString(const std::string & rules)361   void ParseFromString(const std::string& rules) {
362     rules_.ParseFromString(rules);
363   }
Apply(const GURL & gurl)364   void Apply(const GURL& gurl) { rules_.Apply(gurl, &info_); }
ToPacString() const365   std::string ToPacString() const { return info_.ToPacString(); }
366 
WsUrl()367   static GURL WsUrl() { return GURL(kWsUrl); }
WssUrl()368   static GURL WssUrl() { return GURL(kWssUrl); }
369 
370   ProxyConfig::ProxyRules rules_;
371   ProxyInfo info_;
372 };
373 
374 // If a single proxy is set for all protocols, WebSocket uses it.
TEST_F(ProxyConfigWebSocketTest,UsesProxy)375 TEST_F(ProxyConfigWebSocketTest, UsesProxy) {
376   ParseFromString("proxy:3128");
377   Apply(WsUrl());
378   EXPECT_EQ("PROXY proxy:3128", ToPacString());
379 }
380 
381 // See RFC6455 Section 4.1. item 3, "_Proxy Usage_".
TEST_F(ProxyConfigWebSocketTest,PrefersSocks)382 TEST_F(ProxyConfigWebSocketTest, PrefersSocks) {
383   ParseFromString(
384       "http=proxy:3128 ; https=sslproxy:3128 ; socks=socksproxy:1080");
385   Apply(WsUrl());
386   EXPECT_EQ("SOCKS socksproxy:1080", ToPacString());
387 }
388 
TEST_F(ProxyConfigWebSocketTest,PrefersHttpsToHttp)389 TEST_F(ProxyConfigWebSocketTest, PrefersHttpsToHttp) {
390   ParseFromString("http=proxy:3128 ; https=sslproxy:3128");
391   Apply(WssUrl());
392   EXPECT_EQ("PROXY sslproxy:3128", ToPacString());
393 }
394 
TEST_F(ProxyConfigWebSocketTest,PrefersHttpsEvenForWs)395 TEST_F(ProxyConfigWebSocketTest, PrefersHttpsEvenForWs) {
396   ParseFromString("http=proxy:3128 ; https=sslproxy:3128");
397   Apply(WsUrl());
398   EXPECT_EQ("PROXY sslproxy:3128", ToPacString());
399 }
400 
TEST_F(ProxyConfigWebSocketTest,PrefersHttpToDirect)401 TEST_F(ProxyConfigWebSocketTest, PrefersHttpToDirect) {
402   ParseFromString("http=proxy:3128");
403   Apply(WssUrl());
404   EXPECT_EQ("PROXY proxy:3128", ToPacString());
405 }
406 
TEST_F(ProxyConfigWebSocketTest,IgnoresFtpProxy)407 TEST_F(ProxyConfigWebSocketTest, IgnoresFtpProxy) {
408   ParseFromString("ftp=ftpproxy:3128");
409   Apply(WssUrl());
410   EXPECT_EQ("DIRECT", ToPacString());
411 }
412 
TEST_F(ProxyConfigWebSocketTest,ObeysBypassRules)413 TEST_F(ProxyConfigWebSocketTest, ObeysBypassRules) {
414   ParseFromString("http=proxy:3128 ; https=sslproxy:3128");
415   rules_.bypass_rules.AddRuleFromString(".chromium.org");
416   Apply(GURL("wss://codereview.chromium.org/feed"));
417   EXPECT_EQ("DIRECT", ToPacString());
418 }
419 
TEST_F(ProxyConfigWebSocketTest,ObeysLocalBypass)420 TEST_F(ProxyConfigWebSocketTest, ObeysLocalBypass) {
421   ParseFromString("http=proxy:3128 ; https=sslproxy:3128");
422   rules_.bypass_rules.AddRuleFromString("<local>");
423   Apply(GURL("ws://localhost/feed"));
424   EXPECT_EQ("DIRECT", ToPacString());
425 }
426 
427 }  // namespace
428 }  // namespace net
429