OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 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 "chrome/browser/net/pref_proxy_config_service.h" | |
6 | |
7 #include "base/command_line.h" | |
8 #include "base/file_path.h" | |
9 #include "base/message_loop.h" | |
10 #include "chrome/browser/net/chrome_url_request_context.h" | |
11 #include "chrome/browser/prefs/pref_service_mock_builder.h" | |
12 #include "chrome/browser/prefs/proxy_config_dictionary.h" | |
13 #include "chrome/common/chrome_switches.h" | |
14 #include "chrome/common/pref_names.h" | |
15 #include "chrome/test/base/testing_pref_service.h" | |
16 #include "content/test/test_browser_thread.h" | |
17 #include "net/proxy/proxy_config_service_common_unittest.h" | |
18 #include "testing/gmock/include/gmock/gmock.h" | |
19 #include "testing/gtest/include/gtest/gtest.h" | |
20 | |
21 using content::BrowserThread; | |
22 using testing::_; | |
23 using testing::Mock; | |
24 | |
25 namespace { | |
26 | |
27 const char kFixedPacUrl[] = "http://chromium.org/fixed_pac_url"; | |
28 | |
29 // Testing proxy config service that allows us to fire notifications at will. | |
30 class TestProxyConfigService : public net::ProxyConfigService { | |
31 public: | |
32 TestProxyConfigService(const net::ProxyConfig& config, | |
33 ConfigAvailability availability) | |
34 : config_(config), | |
35 availability_(availability) {} | |
36 | |
37 void SetProxyConfig(const net::ProxyConfig config, | |
38 ConfigAvailability availability) { | |
39 config_ = config; | |
40 availability_ = availability; | |
41 FOR_EACH_OBSERVER(net::ProxyConfigService::Observer, observers_, | |
42 OnProxyConfigChanged(config, availability)); | |
43 } | |
44 | |
45 private: | |
46 virtual void AddObserver(net::ProxyConfigService::Observer* observer) { | |
47 observers_.AddObserver(observer); | |
48 } | |
49 | |
50 virtual void RemoveObserver(net::ProxyConfigService::Observer* observer) { | |
51 observers_.RemoveObserver(observer); | |
52 } | |
53 | |
54 virtual net::ProxyConfigService::ConfigAvailability GetLatestProxyConfig( | |
55 net::ProxyConfig* config) { | |
56 *config = config_; | |
57 return availability_; | |
58 } | |
59 | |
60 net::ProxyConfig config_; | |
61 ConfigAvailability availability_; | |
62 ObserverList<net::ProxyConfigService::Observer, true> observers_; | |
63 }; | |
64 | |
65 // A mock observer for capturing callbacks. | |
66 class MockObserver : public net::ProxyConfigService::Observer { | |
67 public: | |
68 MOCK_METHOD2(OnProxyConfigChanged, | |
69 void(const net::ProxyConfig&, | |
70 net::ProxyConfigService::ConfigAvailability)); | |
71 }; | |
72 | |
73 template<typename TESTBASE> | |
74 class PrefProxyConfigServiceTestBase : public TESTBASE { | |
75 protected: | |
76 PrefProxyConfigServiceTestBase() | |
77 : ui_thread_(BrowserThread::UI, &loop_), | |
78 io_thread_(BrowserThread::IO, &loop_) {} | |
79 | |
80 virtual void Init(PrefService* pref_service) { | |
81 ASSERT_TRUE(pref_service); | |
82 PrefProxyConfigService::RegisterPrefs(pref_service); | |
83 fixed_config_.set_pac_url(GURL(kFixedPacUrl)); | |
84 delegate_service_ = | |
85 new TestProxyConfigService(fixed_config_, | |
86 net::ProxyConfigService::CONFIG_VALID); | |
87 proxy_config_tracker_ = new PrefProxyConfigTracker(pref_service); | |
88 proxy_config_service_.reset( | |
89 new PrefProxyConfigService(proxy_config_tracker_.get(), | |
90 delegate_service_)); | |
91 } | |
92 | |
93 virtual void TearDown() { | |
94 proxy_config_tracker_->DetachFromPrefService(); | |
95 loop_.RunAllPending(); | |
96 proxy_config_service_.reset(); | |
97 } | |
98 | |
99 MessageLoop loop_; | |
100 TestProxyConfigService* delegate_service_; // weak | |
101 scoped_ptr<PrefProxyConfigService> proxy_config_service_; | |
102 net::ProxyConfig fixed_config_; | |
103 | |
104 private: | |
105 scoped_refptr<PrefProxyConfigTracker> proxy_config_tracker_; | |
106 content::TestBrowserThread ui_thread_; | |
107 content::TestBrowserThread io_thread_; | |
108 }; | |
109 | |
110 class PrefProxyConfigServiceTest | |
111 : public PrefProxyConfigServiceTestBase<testing::Test> { | |
112 protected: | |
113 virtual void SetUp() { | |
114 pref_service_.reset(new TestingPrefService()); | |
115 Init(pref_service_.get()); | |
116 } | |
117 | |
118 scoped_ptr<TestingPrefService> pref_service_; | |
119 }; | |
120 | |
121 TEST_F(PrefProxyConfigServiceTest, BaseConfiguration) { | |
122 net::ProxyConfig actual_config; | |
123 EXPECT_EQ(net::ProxyConfigService::CONFIG_VALID, | |
124 proxy_config_service_->GetLatestProxyConfig(&actual_config)); | |
125 EXPECT_EQ(GURL(kFixedPacUrl), actual_config.pac_url()); | |
126 } | |
127 | |
128 TEST_F(PrefProxyConfigServiceTest, DynamicPrefOverrides) { | |
129 pref_service_->SetManagedPref( | |
130 prefs::kProxy, | |
131 ProxyConfigDictionary::CreateFixedServers("http://example.com:3128", "")); | |
132 loop_.RunAllPending(); | |
133 | |
134 net::ProxyConfig actual_config; | |
135 EXPECT_EQ(net::ProxyConfigService::CONFIG_VALID, | |
136 proxy_config_service_->GetLatestProxyConfig(&actual_config)); | |
137 EXPECT_FALSE(actual_config.auto_detect()); | |
138 EXPECT_EQ(net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY, | |
139 actual_config.proxy_rules().type); | |
140 EXPECT_EQ(actual_config.proxy_rules().single_proxy, | |
141 net::ProxyServer::FromURI("http://example.com:3128", | |
142 net::ProxyServer::SCHEME_HTTP)); | |
143 | |
144 pref_service_->SetManagedPref(prefs::kProxy, | |
145 ProxyConfigDictionary::CreateAutoDetect()); | |
146 loop_.RunAllPending(); | |
147 | |
148 EXPECT_EQ(net::ProxyConfigService::CONFIG_VALID, | |
149 proxy_config_service_->GetLatestProxyConfig(&actual_config)); | |
150 EXPECT_TRUE(actual_config.auto_detect()); | |
151 } | |
152 | |
153 // Compares proxy configurations, but allows different identifiers. | |
154 MATCHER_P(ProxyConfigMatches, config, "") { | |
155 net::ProxyConfig reference(config); | |
156 reference.set_id(arg.id()); | |
157 return reference.Equals(arg); | |
158 } | |
159 | |
160 TEST_F(PrefProxyConfigServiceTest, Observers) { | |
161 const net::ProxyConfigService::ConfigAvailability CONFIG_VALID = | |
162 net::ProxyConfigService::CONFIG_VALID; | |
163 MockObserver observer; | |
164 proxy_config_service_->AddObserver(&observer); | |
165 | |
166 // Firing the observers in the delegate should trigger a notification. | |
167 net::ProxyConfig config2; | |
168 config2.set_auto_detect(true); | |
169 EXPECT_CALL(observer, OnProxyConfigChanged(ProxyConfigMatches(config2), | |
170 CONFIG_VALID)).Times(1); | |
171 delegate_service_->SetProxyConfig(config2, CONFIG_VALID); | |
172 loop_.RunAllPending(); | |
173 Mock::VerifyAndClearExpectations(&observer); | |
174 | |
175 // Override configuration, this should trigger a notification. | |
176 net::ProxyConfig pref_config; | |
177 pref_config.set_pac_url(GURL(kFixedPacUrl)); | |
178 | |
179 EXPECT_CALL(observer, OnProxyConfigChanged(ProxyConfigMatches(pref_config), | |
180 CONFIG_VALID)).Times(1); | |
181 pref_service_->SetManagedPref( | |
182 prefs::kProxy, | |
183 ProxyConfigDictionary::CreatePacScript(kFixedPacUrl, false)); | |
184 loop_.RunAllPending(); | |
185 Mock::VerifyAndClearExpectations(&observer); | |
186 | |
187 // Since there are pref overrides, delegate changes should be ignored. | |
188 net::ProxyConfig config3; | |
189 config3.proxy_rules().ParseFromString("http=config3:80"); | |
190 EXPECT_CALL(observer, OnProxyConfigChanged(_, _)).Times(0); | |
191 fixed_config_.set_auto_detect(true); | |
192 delegate_service_->SetProxyConfig(config3, CONFIG_VALID); | |
193 loop_.RunAllPending(); | |
194 Mock::VerifyAndClearExpectations(&observer); | |
195 | |
196 // Clear the override should switch back to the fixed configuration. | |
197 EXPECT_CALL(observer, OnProxyConfigChanged(ProxyConfigMatches(config3), | |
198 CONFIG_VALID)).Times(1); | |
199 pref_service_->RemoveManagedPref(prefs::kProxy); | |
200 loop_.RunAllPending(); | |
201 Mock::VerifyAndClearExpectations(&observer); | |
202 | |
203 // Delegate service notifications should show up again. | |
204 net::ProxyConfig config4; | |
205 config4.proxy_rules().ParseFromString("socks:config4"); | |
206 EXPECT_CALL(observer, OnProxyConfigChanged(ProxyConfigMatches(config4), | |
207 CONFIG_VALID)).Times(1); | |
208 delegate_service_->SetProxyConfig(config4, CONFIG_VALID); | |
209 loop_.RunAllPending(); | |
210 Mock::VerifyAndClearExpectations(&observer); | |
211 | |
212 proxy_config_service_->RemoveObserver(&observer); | |
213 } | |
214 | |
215 TEST_F(PrefProxyConfigServiceTest, Fallback) { | |
216 const net::ProxyConfigService::ConfigAvailability CONFIG_VALID = | |
217 net::ProxyConfigService::CONFIG_VALID; | |
218 MockObserver observer; | |
219 net::ProxyConfig actual_config; | |
220 delegate_service_->SetProxyConfig(net::ProxyConfig::CreateDirect(), | |
221 net::ProxyConfigService::CONFIG_UNSET); | |
222 proxy_config_service_->AddObserver(&observer); | |
223 | |
224 // Prepare test data. | |
225 net::ProxyConfig recommended_config = net::ProxyConfig::CreateAutoDetect(); | |
226 net::ProxyConfig user_config = | |
227 net::ProxyConfig::CreateFromCustomPacURL(GURL(kFixedPacUrl)); | |
228 | |
229 // Set a recommended pref. | |
230 EXPECT_CALL(observer, | |
231 OnProxyConfigChanged(ProxyConfigMatches(recommended_config), | |
232 CONFIG_VALID)).Times(1); | |
233 pref_service_->SetRecommendedPref( | |
234 prefs::kProxy, | |
235 ProxyConfigDictionary::CreateAutoDetect()); | |
236 loop_.RunAllPending(); | |
237 Mock::VerifyAndClearExpectations(&observer); | |
238 EXPECT_EQ(CONFIG_VALID, | |
239 proxy_config_service_->GetLatestProxyConfig(&actual_config)); | |
240 EXPECT_TRUE(actual_config.Equals(recommended_config)); | |
241 | |
242 // Override in user prefs. | |
243 EXPECT_CALL(observer, | |
244 OnProxyConfigChanged(ProxyConfigMatches(user_config), | |
245 CONFIG_VALID)).Times(1); | |
246 pref_service_->SetManagedPref( | |
247 prefs::kProxy, | |
248 ProxyConfigDictionary::CreatePacScript(kFixedPacUrl, false)); | |
249 loop_.RunAllPending(); | |
250 Mock::VerifyAndClearExpectations(&observer); | |
251 EXPECT_EQ(CONFIG_VALID, | |
252 proxy_config_service_->GetLatestProxyConfig(&actual_config)); | |
253 EXPECT_TRUE(actual_config.Equals(user_config)); | |
254 | |
255 // Go back to recommended pref. | |
256 EXPECT_CALL(observer, | |
257 OnProxyConfigChanged(ProxyConfigMatches(recommended_config), | |
258 CONFIG_VALID)).Times(1); | |
259 pref_service_->RemoveManagedPref(prefs::kProxy); | |
260 loop_.RunAllPending(); | |
261 Mock::VerifyAndClearExpectations(&observer); | |
262 EXPECT_EQ(CONFIG_VALID, | |
263 proxy_config_service_->GetLatestProxyConfig(&actual_config)); | |
264 EXPECT_TRUE(actual_config.Equals(recommended_config)); | |
265 | |
266 proxy_config_service_->RemoveObserver(&observer); | |
267 } | |
268 | |
269 TEST_F(PrefProxyConfigServiceTest, ExplicitSystemSettings) { | |
270 pref_service_->SetRecommendedPref( | |
271 prefs::kProxy, | |
272 ProxyConfigDictionary::CreateAutoDetect()); | |
273 pref_service_->SetUserPref( | |
274 prefs::kProxy, | |
275 ProxyConfigDictionary::CreateSystem()); | |
276 loop_.RunAllPending(); | |
277 | |
278 // Test if we actually use the system setting, which is |kFixedPacUrl|. | |
279 net::ProxyConfig actual_config; | |
280 EXPECT_EQ(net::ProxyConfigService::CONFIG_VALID, | |
281 proxy_config_service_->GetLatestProxyConfig(&actual_config)); | |
282 EXPECT_EQ(GURL(kFixedPacUrl), actual_config.pac_url()); | |
283 } | |
284 | |
285 // Test parameter object for testing command line proxy configuration. | |
286 struct CommandLineTestParams { | |
287 // Explicit assignment operator, so testing::TestWithParam works with MSVC. | |
288 CommandLineTestParams& operator=(const CommandLineTestParams& other) { | |
289 description = other.description; | |
290 for (unsigned int i = 0; i < arraysize(switches); i++) | |
291 switches[i] = other.switches[i]; | |
292 is_null = other.is_null; | |
293 auto_detect = other.auto_detect; | |
294 pac_url = other.pac_url; | |
295 proxy_rules = other.proxy_rules; | |
296 return *this; | |
297 } | |
298 | |
299 // Short description to identify the test. | |
300 const char* description; | |
301 | |
302 // The command line to build a ProxyConfig from. | |
303 struct SwitchValue { | |
304 const char* name; | |
305 const char* value; | |
306 } switches[2]; | |
307 | |
308 // Expected outputs (fields of the ProxyConfig). | |
309 bool is_null; | |
310 bool auto_detect; | |
311 GURL pac_url; | |
312 net::ProxyRulesExpectation proxy_rules; | |
313 }; | |
314 | |
315 void PrintTo(const CommandLineTestParams& params, std::ostream* os) { | |
316 *os << params.description; | |
317 } | |
318 | |
319 class PrefProxyConfigServiceCommandLineTest | |
320 : public PrefProxyConfigServiceTestBase< | |
321 testing::TestWithParam<CommandLineTestParams> > { | |
322 protected: | |
323 PrefProxyConfigServiceCommandLineTest() | |
324 : command_line_(CommandLine::NO_PROGRAM) {} | |
325 | |
326 virtual void SetUp() { | |
327 for (size_t i = 0; i < arraysize(GetParam().switches); i++) { | |
328 const char* name = GetParam().switches[i].name; | |
329 const char* value = GetParam().switches[i].value; | |
330 if (name && value) | |
331 command_line_.AppendSwitchASCII(name, value); | |
332 else if (name) | |
333 command_line_.AppendSwitch(name); | |
334 } | |
335 pref_service_.reset( | |
336 PrefServiceMockBuilder().WithCommandLine(&command_line_).Create()); | |
337 Init(pref_service_.get()); | |
338 } | |
339 | |
340 private: | |
341 CommandLine command_line_; | |
342 scoped_ptr<PrefService> pref_service_; | |
343 }; | |
344 | |
345 TEST_P(PrefProxyConfigServiceCommandLineTest, CommandLine) { | |
346 net::ProxyConfig config; | |
347 EXPECT_EQ(net::ProxyConfigService::CONFIG_VALID, | |
348 proxy_config_service_->GetLatestProxyConfig(&config)); | |
349 | |
350 if (GetParam().is_null) { | |
351 EXPECT_EQ(GURL(kFixedPacUrl), config.pac_url()); | |
352 } else { | |
353 EXPECT_NE(GURL(kFixedPacUrl), config.pac_url()); | |
354 EXPECT_EQ(GetParam().auto_detect, config.auto_detect()); | |
355 EXPECT_EQ(GetParam().pac_url, config.pac_url()); | |
356 EXPECT_TRUE(GetParam().proxy_rules.Matches(config.proxy_rules())); | |
357 } | |
358 } | |
359 | |
360 static const CommandLineTestParams kCommandLineTestParams[] = { | |
361 { | |
362 "Empty command line", | |
363 // Input | |
364 { }, | |
365 // Expected result | |
366 true, // is_null | |
367 false, // auto_detect | |
368 GURL(), // pac_url | |
369 net::ProxyRulesExpectation::Empty(), | |
370 }, | |
371 { | |
372 "No proxy", | |
373 // Input | |
374 { | |
375 { switches::kNoProxyServer, NULL }, | |
376 }, | |
377 // Expected result | |
378 false, // is_null | |
379 false, // auto_detect | |
380 GURL(), // pac_url | |
381 net::ProxyRulesExpectation::Empty(), | |
382 }, | |
383 { | |
384 "No proxy with extra parameters.", | |
385 // Input | |
386 { | |
387 { switches::kNoProxyServer, NULL }, | |
388 { switches::kProxyServer, "http://proxy:8888" }, | |
389 }, | |
390 // Expected result | |
391 false, // is_null | |
392 false, // auto_detect | |
393 GURL(), // pac_url | |
394 net::ProxyRulesExpectation::Empty(), | |
395 }, | |
396 { | |
397 "Single proxy.", | |
398 // Input | |
399 { | |
400 { switches::kProxyServer, "http://proxy:8888" }, | |
401 }, | |
402 // Expected result | |
403 false, // is_null | |
404 false, // auto_detect | |
405 GURL(), // pac_url | |
406 net::ProxyRulesExpectation::Single( | |
407 "proxy:8888", // single proxy | |
408 ""), // bypass rules | |
409 }, | |
410 { | |
411 "Per scheme proxy.", | |
412 // Input | |
413 { | |
414 { switches::kProxyServer, "http=httpproxy:8888;ftp=ftpproxy:8889" }, | |
415 }, | |
416 // Expected result | |
417 false, // is_null | |
418 false, // auto_detect | |
419 GURL(), // pac_url | |
420 net::ProxyRulesExpectation::PerScheme( | |
421 "httpproxy:8888", // http | |
422 "", // https | |
423 "ftpproxy:8889", // ftp | |
424 ""), // bypass rules | |
425 }, | |
426 { | |
427 "Per scheme proxy with bypass URLs.", | |
428 // Input | |
429 { | |
430 { switches::kProxyServer, "http=httpproxy:8888;ftp=ftpproxy:8889" }, | |
431 { switches::kProxyBypassList, | |
432 ".google.com, foo.com:99, 1.2.3.4:22, 127.0.0.1/8" }, | |
433 }, | |
434 // Expected result | |
435 false, // is_null | |
436 false, // auto_detect | |
437 GURL(), // pac_url | |
438 net::ProxyRulesExpectation::PerScheme( | |
439 "httpproxy:8888", // http | |
440 "", // https | |
441 "ftpproxy:8889", // ftp | |
442 "*.google.com,foo.com:99,1.2.3.4:22,127.0.0.1/8"), | |
443 }, | |
444 { | |
445 "Pac URL", | |
446 // Input | |
447 { | |
448 { switches::kProxyPacUrl, "http://wpad/wpad.dat" }, | |
449 }, | |
450 // Expected result | |
451 false, // is_null | |
452 false, // auto_detect | |
453 GURL("http://wpad/wpad.dat"), // pac_url | |
454 net::ProxyRulesExpectation::Empty(), | |
455 }, | |
456 { | |
457 "Autodetect", | |
458 // Input | |
459 { | |
460 { switches::kProxyAutoDetect, NULL }, | |
461 }, | |
462 // Expected result | |
463 false, // is_null | |
464 true, // auto_detect | |
465 GURL(), // pac_url | |
466 net::ProxyRulesExpectation::Empty(), | |
467 }, | |
468 }; | |
469 | |
470 INSTANTIATE_TEST_CASE_P( | |
471 PrefProxyConfigServiceCommandLineTestInstance, | |
472 PrefProxyConfigServiceCommandLineTest, | |
473 testing::ValuesIn(kCommandLineTestParams)); | |
474 | |
475 } // namespace | |
OLD | NEW |