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