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