OLD | NEW |
| (Empty) |
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_service.h" | |
6 | |
7 #include <vector> | |
8 | |
9 #include "base/format_macros.h" | |
10 #include "base/logging.h" | |
11 #include "base/strings/string_util.h" | |
12 #include "base/strings/utf_string_conversions.h" | |
13 #include "net/base/load_flags.h" | |
14 #include "net/base/net_errors.h" | |
15 #include "net/base/net_log.h" | |
16 #include "net/base/net_log_unittest.h" | |
17 #include "net/base/network_delegate_impl.h" | |
18 #include "net/base/test_completion_callback.h" | |
19 #include "net/proxy/dhcp_proxy_script_fetcher.h" | |
20 #include "net/proxy/mock_proxy_resolver.h" | |
21 #include "net/proxy/mock_proxy_script_fetcher.h" | |
22 #include "net/proxy/proxy_config_service.h" | |
23 #include "net/proxy/proxy_resolver.h" | |
24 #include "net/proxy/proxy_script_fetcher.h" | |
25 #include "testing/gtest/include/gtest/gtest.h" | |
26 #include "url/gurl.h" | |
27 | |
28 using base::ASCIIToUTF16; | |
29 | |
30 // TODO(eroman): Write a test which exercises | |
31 // ProxyService::SuspendAllPendingRequests(). | |
32 namespace net { | |
33 namespace { | |
34 | |
35 // This polling policy will decide to poll every 1 ms. | |
36 class ImmediatePollPolicy : public ProxyService::PacPollPolicy { | |
37 public: | |
38 ImmediatePollPolicy() {} | |
39 | |
40 Mode GetNextDelay(int error, | |
41 base::TimeDelta current_delay, | |
42 base::TimeDelta* next_delay) const override { | |
43 *next_delay = base::TimeDelta::FromMilliseconds(1); | |
44 return MODE_USE_TIMER; | |
45 } | |
46 | |
47 private: | |
48 DISALLOW_COPY_AND_ASSIGN(ImmediatePollPolicy); | |
49 }; | |
50 | |
51 // This polling policy chooses a fantastically large delay. In other words, it | |
52 // will never trigger a poll | |
53 class NeverPollPolicy : public ProxyService::PacPollPolicy { | |
54 public: | |
55 NeverPollPolicy() {} | |
56 | |
57 Mode GetNextDelay(int error, | |
58 base::TimeDelta current_delay, | |
59 base::TimeDelta* next_delay) const override { | |
60 *next_delay = base::TimeDelta::FromDays(60); | |
61 return MODE_USE_TIMER; | |
62 } | |
63 | |
64 private: | |
65 DISALLOW_COPY_AND_ASSIGN(NeverPollPolicy); | |
66 }; | |
67 | |
68 // This polling policy starts a poll immediately after network activity. | |
69 class ImmediateAfterActivityPollPolicy : public ProxyService::PacPollPolicy { | |
70 public: | |
71 ImmediateAfterActivityPollPolicy() {} | |
72 | |
73 Mode GetNextDelay(int error, | |
74 base::TimeDelta current_delay, | |
75 base::TimeDelta* next_delay) const override { | |
76 *next_delay = base::TimeDelta(); | |
77 return MODE_START_AFTER_ACTIVITY; | |
78 } | |
79 | |
80 private: | |
81 DISALLOW_COPY_AND_ASSIGN(ImmediateAfterActivityPollPolicy); | |
82 }; | |
83 | |
84 // This test fixture is used to partially disable the background polling done by | |
85 // the ProxyService (which it uses to detect whenever its PAC script contents or | |
86 // WPAD results have changed). | |
87 // | |
88 // We disable the feature by setting the poll interval to something really | |
89 // large, so it will never actually be reached even on the slowest bots that run | |
90 // these tests. | |
91 // | |
92 // We disable the polling in order to avoid any timing dependencies in the | |
93 // tests. If the bot were to run the tests very slowly and we hadn't disabled | |
94 // polling, then it might start a background re-try in the middle of our test | |
95 // and confuse our expectations leading to flaky failures. | |
96 // | |
97 // The tests which verify the polling code re-enable the polling behavior but | |
98 // are careful to avoid timing problems. | |
99 class ProxyServiceTest : public testing::Test { | |
100 protected: | |
101 void SetUp() override { | |
102 testing::Test::SetUp(); | |
103 previous_policy_ = | |
104 ProxyService::set_pac_script_poll_policy(&never_poll_policy_); | |
105 } | |
106 | |
107 void TearDown() override { | |
108 // Restore the original policy. | |
109 ProxyService::set_pac_script_poll_policy(previous_policy_); | |
110 testing::Test::TearDown(); | |
111 } | |
112 | |
113 private: | |
114 NeverPollPolicy never_poll_policy_; | |
115 const ProxyService::PacPollPolicy* previous_policy_; | |
116 }; | |
117 | |
118 const char kValidPacScript1[] = "pac-script-v1-FindProxyForURL"; | |
119 const char kValidPacScript2[] = "pac-script-v2-FindProxyForURL"; | |
120 | |
121 class MockProxyConfigService: public ProxyConfigService { | |
122 public: | |
123 explicit MockProxyConfigService(const ProxyConfig& config) | |
124 : availability_(CONFIG_VALID), | |
125 config_(config) { | |
126 } | |
127 | |
128 explicit MockProxyConfigService(const std::string& pac_url) | |
129 : availability_(CONFIG_VALID), | |
130 config_(ProxyConfig::CreateFromCustomPacURL(GURL(pac_url))) { | |
131 } | |
132 | |
133 void AddObserver(Observer* observer) override { | |
134 observers_.AddObserver(observer); | |
135 } | |
136 | |
137 void RemoveObserver(Observer* observer) override { | |
138 observers_.RemoveObserver(observer); | |
139 } | |
140 | |
141 ConfigAvailability GetLatestProxyConfig(ProxyConfig* results) override { | |
142 if (availability_ == CONFIG_VALID) | |
143 *results = config_; | |
144 return availability_; | |
145 } | |
146 | |
147 void SetConfig(const ProxyConfig& config) { | |
148 availability_ = CONFIG_VALID; | |
149 config_ = config; | |
150 FOR_EACH_OBSERVER(Observer, observers_, | |
151 OnProxyConfigChanged(config_, availability_)); | |
152 } | |
153 | |
154 private: | |
155 ConfigAvailability availability_; | |
156 ProxyConfig config_; | |
157 ObserverList<Observer, true> observers_; | |
158 }; | |
159 | |
160 // A test network delegate that exercises the OnResolveProxy callback. | |
161 class TestResolveProxyNetworkDelegate : public NetworkDelegateImpl { | |
162 public: | |
163 TestResolveProxyNetworkDelegate() | |
164 : on_resolve_proxy_called_(false), | |
165 add_proxy_(false), | |
166 remove_proxy_(false), | |
167 proxy_service_(NULL) { | |
168 } | |
169 | |
170 void OnResolveProxy(const GURL& url, | |
171 int load_flags, | |
172 const ProxyService& proxy_service, | |
173 ProxyInfo* result) override { | |
174 on_resolve_proxy_called_ = true; | |
175 proxy_service_ = &proxy_service; | |
176 DCHECK(!add_proxy_ || !remove_proxy_); | |
177 if (add_proxy_) { | |
178 result->UseNamedProxy("delegate_proxy.com"); | |
179 } else if (remove_proxy_) { | |
180 result->UseDirect(); | |
181 } | |
182 } | |
183 | |
184 bool on_resolve_proxy_called() const { | |
185 return on_resolve_proxy_called_; | |
186 } | |
187 | |
188 void set_add_proxy(bool add_proxy) { | |
189 add_proxy_ = add_proxy; | |
190 } | |
191 | |
192 void set_remove_proxy(bool remove_proxy) { | |
193 remove_proxy_ = remove_proxy; | |
194 } | |
195 | |
196 const ProxyService* proxy_service() const { | |
197 return proxy_service_; | |
198 } | |
199 | |
200 private: | |
201 bool on_resolve_proxy_called_; | |
202 bool add_proxy_; | |
203 bool remove_proxy_; | |
204 const ProxyService* proxy_service_; | |
205 }; | |
206 | |
207 // A test network delegate that exercises the OnProxyFallback callback. | |
208 class TestProxyFallbackNetworkDelegate : public NetworkDelegateImpl { | |
209 public: | |
210 TestProxyFallbackNetworkDelegate() | |
211 : on_proxy_fallback_called_(false), | |
212 proxy_fallback_net_error_(OK) { | |
213 } | |
214 | |
215 void OnProxyFallback(const ProxyServer& proxy_server, | |
216 int net_error) override { | |
217 proxy_server_ = proxy_server; | |
218 proxy_fallback_net_error_ = net_error; | |
219 on_proxy_fallback_called_ = true; | |
220 } | |
221 | |
222 bool on_proxy_fallback_called() const { | |
223 return on_proxy_fallback_called_; | |
224 } | |
225 | |
226 const ProxyServer& proxy_server() const { | |
227 return proxy_server_; | |
228 } | |
229 | |
230 int proxy_fallback_net_error() const { | |
231 return proxy_fallback_net_error_; | |
232 } | |
233 | |
234 private: | |
235 bool on_proxy_fallback_called_; | |
236 ProxyServer proxy_server_; | |
237 int proxy_fallback_net_error_; | |
238 }; | |
239 | |
240 } // namespace | |
241 | |
242 TEST_F(ProxyServiceTest, Direct) { | |
243 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; | |
244 ProxyService service(new MockProxyConfigService( | |
245 ProxyConfig::CreateDirect()), resolver, NULL); | |
246 | |
247 GURL url("http://www.google.com/"); | |
248 | |
249 ProxyInfo info; | |
250 TestCompletionCallback callback; | |
251 CapturingBoundNetLog log; | |
252 int rv = service.ResolveProxy( | |
253 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL, | |
254 log.bound()); | |
255 EXPECT_EQ(OK, rv); | |
256 EXPECT_TRUE(resolver->pending_requests().empty()); | |
257 | |
258 EXPECT_TRUE(info.is_direct()); | |
259 EXPECT_TRUE(info.proxy_resolve_start_time().is_null()); | |
260 EXPECT_TRUE(info.proxy_resolve_end_time().is_null()); | |
261 | |
262 // Check the NetLog was filled correctly. | |
263 CapturingNetLog::CapturedEntryList entries; | |
264 log.GetEntries(&entries); | |
265 | |
266 EXPECT_EQ(3u, entries.size()); | |
267 EXPECT_TRUE(LogContainsBeginEvent( | |
268 entries, 0, NetLog::TYPE_PROXY_SERVICE)); | |
269 EXPECT_TRUE(LogContainsEvent( | |
270 entries, 1, NetLog::TYPE_PROXY_SERVICE_RESOLVED_PROXY_LIST, | |
271 NetLog::PHASE_NONE)); | |
272 EXPECT_TRUE(LogContainsEndEvent( | |
273 entries, 2, NetLog::TYPE_PROXY_SERVICE)); | |
274 } | |
275 | |
276 TEST_F(ProxyServiceTest, OnResolveProxyCallbackAddProxy) { | |
277 ProxyConfig config; | |
278 config.proxy_rules().ParseFromString("foopy1:8080"); | |
279 config.set_auto_detect(false); | |
280 config.proxy_rules().bypass_rules.ParseFromString("*.org"); | |
281 | |
282 ProxyService service( | |
283 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL); | |
284 | |
285 GURL url("http://www.google.com/"); | |
286 GURL bypass_url("http://internet.org"); | |
287 | |
288 ProxyInfo info; | |
289 TestCompletionCallback callback; | |
290 CapturingBoundNetLog log; | |
291 | |
292 // First, warm up the ProxyService. | |
293 int rv = service.ResolveProxy( | |
294 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL, | |
295 log.bound()); | |
296 EXPECT_EQ(OK, rv); | |
297 | |
298 // Verify that network delegate is invoked. | |
299 TestResolveProxyNetworkDelegate delegate; | |
300 rv = service.ResolveProxy( | |
301 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, &delegate, | |
302 log.bound()); | |
303 EXPECT_TRUE(delegate.on_resolve_proxy_called()); | |
304 EXPECT_EQ(&service, delegate.proxy_service()); | |
305 | |
306 // Verify that the NetworkDelegate's behavior is stateless across | |
307 // invocations of ResolveProxy. Start by having the callback add a proxy | |
308 // and checking that subsequent requests are not affected. | |
309 delegate.set_add_proxy(true); | |
310 | |
311 // Callback should interpose: | |
312 rv = service.ResolveProxy( | |
313 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, &delegate, | |
314 log.bound()); | |
315 EXPECT_FALSE(info.is_direct()); | |
316 EXPECT_EQ(info.proxy_server().host_port_pair().host(), "delegate_proxy.com"); | |
317 delegate.set_add_proxy(false); | |
318 | |
319 // Check non-bypassed URL: | |
320 rv = service.ResolveProxy( | |
321 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, &delegate, | |
322 log.bound()); | |
323 EXPECT_FALSE(info.is_direct()); | |
324 EXPECT_EQ(info.proxy_server().host_port_pair().host(), "foopy1"); | |
325 | |
326 // Check bypassed URL: | |
327 rv = service.ResolveProxy( | |
328 bypass_url, net::LOAD_NORMAL, &info, callback.callback(), NULL, | |
329 &delegate, log.bound()); | |
330 EXPECT_TRUE(info.is_direct()); | |
331 } | |
332 | |
333 TEST_F(ProxyServiceTest, OnResolveProxyCallbackRemoveProxy) { | |
334 // Same as OnResolveProxyCallbackAddProxy, but verify that the | |
335 // NetworkDelegate's behavior is stateless across invocations after it | |
336 // *removes* a proxy. | |
337 ProxyConfig config; | |
338 config.proxy_rules().ParseFromString("foopy1:8080"); | |
339 config.set_auto_detect(false); | |
340 config.proxy_rules().bypass_rules.ParseFromString("*.org"); | |
341 | |
342 ProxyService service( | |
343 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL); | |
344 | |
345 GURL url("http://www.google.com/"); | |
346 GURL bypass_url("http://internet.org"); | |
347 | |
348 ProxyInfo info; | |
349 TestCompletionCallback callback; | |
350 CapturingBoundNetLog log; | |
351 | |
352 // First, warm up the ProxyService. | |
353 int rv = service.ResolveProxy( | |
354 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL, | |
355 log.bound()); | |
356 EXPECT_EQ(OK, rv); | |
357 | |
358 TestResolveProxyNetworkDelegate delegate; | |
359 delegate.set_remove_proxy(true); | |
360 | |
361 // Callback should interpose: | |
362 rv = service.ResolveProxy( | |
363 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, &delegate, | |
364 log.bound()); | |
365 EXPECT_TRUE(info.is_direct()); | |
366 delegate.set_remove_proxy(false); | |
367 | |
368 // Check non-bypassed URL: | |
369 rv = service.ResolveProxy( | |
370 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, &delegate, | |
371 log.bound()); | |
372 EXPECT_FALSE(info.is_direct()); | |
373 EXPECT_EQ(info.proxy_server().host_port_pair().host(), "foopy1"); | |
374 | |
375 // Check bypassed URL: | |
376 rv = service.ResolveProxy( | |
377 bypass_url, net::LOAD_NORMAL, &info, callback.callback(), NULL, | |
378 &delegate, log.bound()); | |
379 EXPECT_TRUE(info.is_direct()); | |
380 } | |
381 | |
382 TEST_F(ProxyServiceTest, PAC) { | |
383 MockProxyConfigService* config_service = | |
384 new MockProxyConfigService("http://foopy/proxy.pac"); | |
385 | |
386 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; | |
387 | |
388 ProxyService service(config_service, resolver, NULL); | |
389 | |
390 GURL url("http://www.google.com/"); | |
391 | |
392 ProxyInfo info; | |
393 TestCompletionCallback callback; | |
394 ProxyService::PacRequest* request; | |
395 CapturingBoundNetLog log; | |
396 | |
397 int rv = service.ResolveProxy( | |
398 url, net::LOAD_NORMAL, &info, callback.callback(), &request, NULL, | |
399 log.bound()); | |
400 EXPECT_EQ(ERR_IO_PENDING, rv); | |
401 | |
402 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request)); | |
403 | |
404 EXPECT_EQ(GURL("http://foopy/proxy.pac"), | |
405 resolver->pending_set_pac_script_request()->script_data()->url()); | |
406 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
407 | |
408 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
409 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); | |
410 | |
411 // Set the result in proxy resolver. | |
412 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy"); | |
413 resolver->pending_requests()[0]->CompleteNow(OK); | |
414 | |
415 EXPECT_EQ(OK, callback.WaitForResult()); | |
416 EXPECT_FALSE(info.is_direct()); | |
417 EXPECT_EQ("foopy:80", info.proxy_server().ToURI()); | |
418 EXPECT_TRUE(info.did_use_pac_script()); | |
419 | |
420 EXPECT_FALSE(info.proxy_resolve_start_time().is_null()); | |
421 EXPECT_FALSE(info.proxy_resolve_end_time().is_null()); | |
422 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time()); | |
423 | |
424 // Check the NetLog was filled correctly. | |
425 CapturingNetLog::CapturedEntryList entries; | |
426 log.GetEntries(&entries); | |
427 | |
428 EXPECT_EQ(5u, entries.size()); | |
429 EXPECT_TRUE(LogContainsBeginEvent( | |
430 entries, 0, NetLog::TYPE_PROXY_SERVICE)); | |
431 EXPECT_TRUE(LogContainsBeginEvent( | |
432 entries, 1, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC)); | |
433 EXPECT_TRUE(LogContainsEndEvent( | |
434 entries, 2, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC)); | |
435 EXPECT_TRUE(LogContainsEndEvent( | |
436 entries, 4, NetLog::TYPE_PROXY_SERVICE)); | |
437 } | |
438 | |
439 // Test that the proxy resolver does not see the URL's username/password | |
440 // or its reference section. | |
441 TEST_F(ProxyServiceTest, PAC_NoIdentityOrHash) { | |
442 MockProxyConfigService* config_service = | |
443 new MockProxyConfigService("http://foopy/proxy.pac"); | |
444 | |
445 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; | |
446 | |
447 ProxyService service(config_service, resolver, NULL); | |
448 | |
449 GURL url("http://username:password@www.google.com/?ref#hash#hash"); | |
450 | |
451 ProxyInfo info; | |
452 TestCompletionCallback callback; | |
453 int rv = service.ResolveProxy( | |
454 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL, | |
455 BoundNetLog()); | |
456 EXPECT_EQ(ERR_IO_PENDING, rv); | |
457 | |
458 EXPECT_EQ(GURL("http://foopy/proxy.pac"), | |
459 resolver->pending_set_pac_script_request()->script_data()->url()); | |
460 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
461 | |
462 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
463 // The URL should have been simplified, stripping the username/password/hash. | |
464 EXPECT_EQ(GURL("http://www.google.com/?ref"), | |
465 resolver->pending_requests()[0]->url()); | |
466 | |
467 // We end here without ever completing the request -- destruction of | |
468 // ProxyService will cancel the outstanding request. | |
469 } | |
470 | |
471 TEST_F(ProxyServiceTest, PAC_FailoverWithoutDirect) { | |
472 MockProxyConfigService* config_service = | |
473 new MockProxyConfigService("http://foopy/proxy.pac"); | |
474 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; | |
475 | |
476 ProxyService service(config_service, resolver, NULL); | |
477 | |
478 GURL url("http://www.google.com/"); | |
479 | |
480 ProxyInfo info; | |
481 TestCompletionCallback callback1; | |
482 int rv = service.ResolveProxy( | |
483 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, | |
484 BoundNetLog()); | |
485 EXPECT_EQ(ERR_IO_PENDING, rv); | |
486 | |
487 EXPECT_EQ(GURL("http://foopy/proxy.pac"), | |
488 resolver->pending_set_pac_script_request()->script_data()->url()); | |
489 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
490 | |
491 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
492 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); | |
493 | |
494 // Set the result in proxy resolver. | |
495 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy:8080"); | |
496 resolver->pending_requests()[0]->CompleteNow(OK); | |
497 | |
498 EXPECT_EQ(OK, callback1.WaitForResult()); | |
499 EXPECT_FALSE(info.is_direct()); | |
500 EXPECT_EQ("foopy:8080", info.proxy_server().ToURI()); | |
501 EXPECT_TRUE(info.did_use_pac_script()); | |
502 | |
503 EXPECT_FALSE(info.proxy_resolve_start_time().is_null()); | |
504 EXPECT_FALSE(info.proxy_resolve_end_time().is_null()); | |
505 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time()); | |
506 | |
507 // Now, imagine that connecting to foopy:8080 fails: there is nothing | |
508 // left to fallback to, since our proxy list was NOT terminated by | |
509 // DIRECT. | |
510 NetworkDelegateImpl network_delegate; | |
511 TestCompletionCallback callback2; | |
512 ProxyServer expected_proxy_server = info.proxy_server(); | |
513 rv = service.ReconsiderProxyAfterError( | |
514 url, net::LOAD_NORMAL, net::ERR_PROXY_CONNECTION_FAILED, | |
515 &info, callback2.callback(), NULL, &network_delegate, BoundNetLog()); | |
516 // ReconsiderProxyAfterError returns error indicating nothing left. | |
517 EXPECT_EQ(ERR_FAILED, rv); | |
518 EXPECT_TRUE(info.is_empty()); | |
519 } | |
520 | |
521 // Test that if the execution of the PAC script fails (i.e. javascript runtime | |
522 // error), and the PAC settings are non-mandatory, that we fall-back to direct. | |
523 TEST_F(ProxyServiceTest, PAC_RuntimeError) { | |
524 MockProxyConfigService* config_service = | |
525 new MockProxyConfigService("http://foopy/proxy.pac"); | |
526 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; | |
527 | |
528 ProxyService service(config_service, resolver, NULL); | |
529 | |
530 GURL url("http://this-causes-js-error/"); | |
531 | |
532 ProxyInfo info; | |
533 TestCompletionCallback callback1; | |
534 int rv = service.ResolveProxy( | |
535 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, | |
536 BoundNetLog()); | |
537 EXPECT_EQ(ERR_IO_PENDING, rv); | |
538 | |
539 EXPECT_EQ(GURL("http://foopy/proxy.pac"), | |
540 resolver->pending_set_pac_script_request()->script_data()->url()); | |
541 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
542 | |
543 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
544 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); | |
545 | |
546 // Simulate a failure in the PAC executor. | |
547 resolver->pending_requests()[0]->CompleteNow(ERR_PAC_SCRIPT_FAILED); | |
548 | |
549 EXPECT_EQ(OK, callback1.WaitForResult()); | |
550 | |
551 // Since the PAC script was non-mandatory, we should have fallen-back to | |
552 // DIRECT. | |
553 EXPECT_TRUE(info.is_direct()); | |
554 EXPECT_TRUE(info.did_use_pac_script()); | |
555 EXPECT_EQ(1, info.config_id()); | |
556 | |
557 EXPECT_FALSE(info.proxy_resolve_start_time().is_null()); | |
558 EXPECT_FALSE(info.proxy_resolve_end_time().is_null()); | |
559 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time()); | |
560 } | |
561 | |
562 // The proxy list could potentially contain the DIRECT fallback choice | |
563 // in a location other than the very end of the list, and could even | |
564 // specify it multiple times. | |
565 // | |
566 // This is not a typical usage, but we will obey it. | |
567 // (If we wanted to disallow this type of input, the right place to | |
568 // enforce it would be in parsing the PAC result string). | |
569 // | |
570 // This test will use the PAC result string: | |
571 // | |
572 // "DIRECT ; PROXY foobar:10 ; DIRECT ; PROXY foobar:20" | |
573 // | |
574 // For which we expect it to try DIRECT, then foobar:10, then DIRECT again, | |
575 // then foobar:20, and then give up and error. | |
576 // | |
577 // The important check of this test is to make sure that DIRECT is not somehow | |
578 // cached as being a bad proxy. | |
579 TEST_F(ProxyServiceTest, PAC_FailoverAfterDirect) { | |
580 MockProxyConfigService* config_service = | |
581 new MockProxyConfigService("http://foopy/proxy.pac"); | |
582 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; | |
583 | |
584 ProxyService service(config_service, resolver, NULL); | |
585 | |
586 GURL url("http://www.google.com/"); | |
587 | |
588 ProxyInfo info; | |
589 TestCompletionCallback callback1; | |
590 int rv = service.ResolveProxy( | |
591 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, | |
592 BoundNetLog()); | |
593 EXPECT_EQ(ERR_IO_PENDING, rv); | |
594 | |
595 EXPECT_EQ(GURL("http://foopy/proxy.pac"), | |
596 resolver->pending_set_pac_script_request()->script_data()->url()); | |
597 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
598 | |
599 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
600 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); | |
601 | |
602 // Set the result in proxy resolver. | |
603 resolver->pending_requests()[0]->results()->UsePacString( | |
604 "DIRECT ; PROXY foobar:10 ; DIRECT ; PROXY foobar:20"); | |
605 resolver->pending_requests()[0]->CompleteNow(OK); | |
606 | |
607 EXPECT_EQ(OK, callback1.WaitForResult()); | |
608 EXPECT_TRUE(info.is_direct()); | |
609 | |
610 // Fallback 1. | |
611 TestCompletionCallback callback2; | |
612 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, | |
613 net::ERR_PROXY_CONNECTION_FAILED, | |
614 &info, callback2.callback(), NULL, | |
615 NULL, BoundNetLog()); | |
616 EXPECT_EQ(OK, rv); | |
617 EXPECT_FALSE(info.is_direct()); | |
618 EXPECT_EQ("foobar:10", info.proxy_server().ToURI()); | |
619 | |
620 // Fallback 2. | |
621 NetworkDelegateImpl network_delegate; | |
622 ProxyServer expected_proxy_server3 = info.proxy_server(); | |
623 TestCompletionCallback callback3; | |
624 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, | |
625 net::ERR_PROXY_CONNECTION_FAILED, | |
626 &info, callback3.callback(), NULL, | |
627 &network_delegate, BoundNetLog()); | |
628 EXPECT_EQ(OK, rv); | |
629 EXPECT_TRUE(info.is_direct()); | |
630 | |
631 // Fallback 3. | |
632 ProxyServer expected_proxy_server4 = info.proxy_server(); | |
633 TestCompletionCallback callback4; | |
634 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, | |
635 net::ERR_PROXY_CONNECTION_FAILED, | |
636 &info, callback4.callback(), NULL, | |
637 &network_delegate, BoundNetLog()); | |
638 EXPECT_EQ(OK, rv); | |
639 EXPECT_FALSE(info.is_direct()); | |
640 EXPECT_EQ("foobar:20", info.proxy_server().ToURI()); | |
641 | |
642 // Fallback 4 -- Nothing to fall back to! | |
643 ProxyServer expected_proxy_server5 = info.proxy_server(); | |
644 TestCompletionCallback callback5; | |
645 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, | |
646 net::ERR_PROXY_CONNECTION_FAILED, | |
647 &info, callback5.callback(), NULL, | |
648 &network_delegate, BoundNetLog()); | |
649 EXPECT_EQ(ERR_FAILED, rv); | |
650 EXPECT_TRUE(info.is_empty()); | |
651 } | |
652 | |
653 TEST_F(ProxyServiceTest, PAC_ConfigSourcePropagates) { | |
654 // Test whether the ProxyConfigSource set by the ProxyConfigService is applied | |
655 // to ProxyInfo after the proxy is resolved via a PAC script. | |
656 ProxyConfig config = | |
657 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")); | |
658 config.set_source(PROXY_CONFIG_SOURCE_TEST); | |
659 | |
660 MockProxyConfigService* config_service = new MockProxyConfigService(config); | |
661 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; | |
662 ProxyService service(config_service, resolver, NULL); | |
663 | |
664 // Resolve something. | |
665 GURL url("http://www.google.com/"); | |
666 ProxyInfo info; | |
667 TestCompletionCallback callback; | |
668 int rv = service.ResolveProxy( | |
669 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL, | |
670 BoundNetLog()); | |
671 ASSERT_EQ(ERR_IO_PENDING, rv); | |
672 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
673 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
674 | |
675 // Set the result in proxy resolver. | |
676 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy"); | |
677 resolver->pending_requests()[0]->CompleteNow(OK); | |
678 | |
679 EXPECT_EQ(OK, callback.WaitForResult()); | |
680 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source()); | |
681 EXPECT_TRUE(info.did_use_pac_script()); | |
682 | |
683 EXPECT_FALSE(info.proxy_resolve_start_time().is_null()); | |
684 EXPECT_FALSE(info.proxy_resolve_end_time().is_null()); | |
685 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time()); | |
686 } | |
687 | |
688 TEST_F(ProxyServiceTest, ProxyResolverFails) { | |
689 // Test what happens when the ProxyResolver fails. The download and setting | |
690 // of the PAC script have already succeeded, so this corresponds with a | |
691 // javascript runtime error while calling FindProxyForURL(). | |
692 | |
693 MockProxyConfigService* config_service = | |
694 new MockProxyConfigService("http://foopy/proxy.pac"); | |
695 | |
696 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; | |
697 | |
698 ProxyService service(config_service, resolver, NULL); | |
699 | |
700 // Start first resolve request. | |
701 GURL url("http://www.google.com/"); | |
702 ProxyInfo info; | |
703 TestCompletionCallback callback1; | |
704 int rv = service.ResolveProxy( | |
705 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, | |
706 BoundNetLog()); | |
707 EXPECT_EQ(ERR_IO_PENDING, rv); | |
708 | |
709 EXPECT_EQ(GURL("http://foopy/proxy.pac"), | |
710 resolver->pending_set_pac_script_request()->script_data()->url()); | |
711 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
712 | |
713 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
714 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); | |
715 | |
716 // Fail the first resolve request in MockAsyncProxyResolver. | |
717 resolver->pending_requests()[0]->CompleteNow(ERR_FAILED); | |
718 | |
719 // Although the proxy resolver failed the request, ProxyService implicitly | |
720 // falls-back to DIRECT. | |
721 EXPECT_EQ(OK, callback1.WaitForResult()); | |
722 EXPECT_TRUE(info.is_direct()); | |
723 | |
724 // Failed PAC executions still have proxy resolution times. | |
725 EXPECT_FALSE(info.proxy_resolve_start_time().is_null()); | |
726 EXPECT_FALSE(info.proxy_resolve_end_time().is_null()); | |
727 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time()); | |
728 | |
729 // The second resolve request will try to run through the proxy resolver, | |
730 // regardless of whether the first request failed in it. | |
731 TestCompletionCallback callback2; | |
732 rv = service.ResolveProxy( | |
733 url, net::LOAD_NORMAL, &info, callback2.callback(), NULL, NULL, | |
734 BoundNetLog()); | |
735 EXPECT_EQ(ERR_IO_PENDING, rv); | |
736 | |
737 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
738 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); | |
739 | |
740 // This time we will have the resolver succeed (perhaps the PAC script has | |
741 // a dependency on the current time). | |
742 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080"); | |
743 resolver->pending_requests()[0]->CompleteNow(OK); | |
744 | |
745 EXPECT_EQ(OK, callback2.WaitForResult()); | |
746 EXPECT_FALSE(info.is_direct()); | |
747 EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI()); | |
748 } | |
749 | |
750 TEST_F(ProxyServiceTest, ProxyScriptFetcherFailsDownloadingMandatoryPac) { | |
751 // Test what happens when the ProxyScriptResolver fails to download a | |
752 // mandatory PAC script. | |
753 | |
754 ProxyConfig config( | |
755 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"))); | |
756 config.set_pac_mandatory(true); | |
757 | |
758 MockProxyConfigService* config_service = new MockProxyConfigService(config); | |
759 | |
760 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; | |
761 | |
762 ProxyService service(config_service, resolver, NULL); | |
763 | |
764 // Start first resolve request. | |
765 GURL url("http://www.google.com/"); | |
766 ProxyInfo info; | |
767 TestCompletionCallback callback1; | |
768 int rv = service.ResolveProxy( | |
769 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, | |
770 BoundNetLog()); | |
771 EXPECT_EQ(ERR_IO_PENDING, rv); | |
772 | |
773 EXPECT_EQ(GURL("http://foopy/proxy.pac"), | |
774 resolver->pending_set_pac_script_request()->script_data()->url()); | |
775 resolver->pending_set_pac_script_request()->CompleteNow(ERR_FAILED); | |
776 | |
777 ASSERT_EQ(0u, resolver->pending_requests().size()); | |
778 | |
779 // As the proxy resolver failed the request and is configured for a mandatory | |
780 // PAC script, ProxyService must not implicitly fall-back to DIRECT. | |
781 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED, | |
782 callback1.WaitForResult()); | |
783 EXPECT_FALSE(info.is_direct()); | |
784 | |
785 // As the proxy resolver failed the request and is configured for a mandatory | |
786 // PAC script, ProxyService must not implicitly fall-back to DIRECT. | |
787 TestCompletionCallback callback2; | |
788 rv = service.ResolveProxy( | |
789 url, net::LOAD_NORMAL, &info, callback2.callback(), NULL, NULL, | |
790 BoundNetLog()); | |
791 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED, rv); | |
792 EXPECT_FALSE(info.is_direct()); | |
793 } | |
794 | |
795 TEST_F(ProxyServiceTest, ProxyResolverFailsParsingJavaScriptMandatoryPac) { | |
796 // Test what happens when the ProxyResolver fails that is configured to use a | |
797 // mandatory PAC script. The download of the PAC script has already | |
798 // succeeded but the PAC script contains no valid javascript. | |
799 | |
800 ProxyConfig config( | |
801 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"))); | |
802 config.set_pac_mandatory(true); | |
803 | |
804 MockProxyConfigService* config_service = new MockProxyConfigService(config); | |
805 | |
806 MockAsyncProxyResolverExpectsBytes* resolver = | |
807 new MockAsyncProxyResolverExpectsBytes; | |
808 | |
809 ProxyService service(config_service, resolver, NULL); | |
810 | |
811 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; | |
812 DhcpProxyScriptFetcher* dhcp_fetcher = new DoNothingDhcpProxyScriptFetcher(); | |
813 service.SetProxyScriptFetchers(fetcher, dhcp_fetcher); | |
814 | |
815 // Start resolve request. | |
816 GURL url("http://www.google.com/"); | |
817 ProxyInfo info; | |
818 TestCompletionCallback callback; | |
819 int rv = service.ResolveProxy( | |
820 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL, | |
821 BoundNetLog()); | |
822 EXPECT_EQ(ERR_IO_PENDING, rv); | |
823 | |
824 // Check that nothing has been sent to the proxy resolver yet. | |
825 ASSERT_EQ(0u, resolver->pending_requests().size()); | |
826 | |
827 // Downloading the PAC script succeeds. | |
828 EXPECT_TRUE(fetcher->has_pending_request()); | |
829 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); | |
830 fetcher->NotifyFetchCompletion(OK, "invalid-script-contents"); | |
831 | |
832 EXPECT_FALSE(fetcher->has_pending_request()); | |
833 ASSERT_EQ(0u, resolver->pending_requests().size()); | |
834 | |
835 // Since ProxyScriptDecider failed to identify a valid PAC and PAC was | |
836 // mandatory for this configuration, the ProxyService must not implicitly | |
837 // fall-back to DIRECT. | |
838 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED, | |
839 callback.WaitForResult()); | |
840 EXPECT_FALSE(info.is_direct()); | |
841 } | |
842 | |
843 TEST_F(ProxyServiceTest, ProxyResolverFailsInJavaScriptMandatoryPac) { | |
844 // Test what happens when the ProxyResolver fails that is configured to use a | |
845 // mandatory PAC script. The download and setting of the PAC script have | |
846 // already succeeded, so this corresponds with a javascript runtime error | |
847 // while calling FindProxyForURL(). | |
848 | |
849 ProxyConfig config( | |
850 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"))); | |
851 config.set_pac_mandatory(true); | |
852 | |
853 MockProxyConfigService* config_service = new MockProxyConfigService(config); | |
854 | |
855 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; | |
856 | |
857 ProxyService service(config_service, resolver, NULL); | |
858 | |
859 // Start first resolve request. | |
860 GURL url("http://www.google.com/"); | |
861 ProxyInfo info; | |
862 TestCompletionCallback callback1; | |
863 int rv = service.ResolveProxy( | |
864 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, | |
865 BoundNetLog()); | |
866 EXPECT_EQ(ERR_IO_PENDING, rv); | |
867 | |
868 EXPECT_EQ(GURL("http://foopy/proxy.pac"), | |
869 resolver->pending_set_pac_script_request()->script_data()->url()); | |
870 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
871 | |
872 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
873 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); | |
874 | |
875 // Fail the first resolve request in MockAsyncProxyResolver. | |
876 resolver->pending_requests()[0]->CompleteNow(ERR_FAILED); | |
877 | |
878 // As the proxy resolver failed the request and is configured for a mandatory | |
879 // PAC script, ProxyService must not implicitly fall-back to DIRECT. | |
880 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED, | |
881 callback1.WaitForResult()); | |
882 EXPECT_FALSE(info.is_direct()); | |
883 | |
884 // The second resolve request will try to run through the proxy resolver, | |
885 // regardless of whether the first request failed in it. | |
886 TestCompletionCallback callback2; | |
887 rv = service.ResolveProxy( | |
888 url, net::LOAD_NORMAL, &info, callback2.callback(), NULL, NULL, | |
889 BoundNetLog()); | |
890 EXPECT_EQ(ERR_IO_PENDING, rv); | |
891 | |
892 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
893 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); | |
894 | |
895 // This time we will have the resolver succeed (perhaps the PAC script has | |
896 // a dependency on the current time). | |
897 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080"); | |
898 resolver->pending_requests()[0]->CompleteNow(OK); | |
899 | |
900 EXPECT_EQ(OK, callback2.WaitForResult()); | |
901 EXPECT_FALSE(info.is_direct()); | |
902 EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI()); | |
903 } | |
904 | |
905 TEST_F(ProxyServiceTest, ProxyFallback) { | |
906 // Test what happens when we specify multiple proxy servers and some of them | |
907 // are bad. | |
908 | |
909 MockProxyConfigService* config_service = | |
910 new MockProxyConfigService("http://foopy/proxy.pac"); | |
911 | |
912 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; | |
913 | |
914 ProxyService service(config_service, resolver, NULL); | |
915 | |
916 GURL url("http://www.google.com/"); | |
917 | |
918 // Get the proxy information. | |
919 ProxyInfo info; | |
920 TestCompletionCallback callback1; | |
921 int rv = service.ResolveProxy( | |
922 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, | |
923 BoundNetLog()); | |
924 EXPECT_EQ(ERR_IO_PENDING, rv); | |
925 | |
926 EXPECT_EQ(GURL("http://foopy/proxy.pac"), | |
927 resolver->pending_set_pac_script_request()->script_data()->url()); | |
928 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
929 | |
930 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
931 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); | |
932 | |
933 // Set the result in proxy resolver. | |
934 resolver->pending_requests()[0]->results()->UseNamedProxy( | |
935 "foopy1:8080;foopy2:9090"); | |
936 resolver->pending_requests()[0]->CompleteNow(OK); | |
937 | |
938 // The first item is valid. | |
939 EXPECT_EQ(OK, callback1.WaitForResult()); | |
940 EXPECT_FALSE(info.is_direct()); | |
941 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); | |
942 | |
943 EXPECT_FALSE(info.proxy_resolve_start_time().is_null()); | |
944 EXPECT_FALSE(info.proxy_resolve_end_time().is_null()); | |
945 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time()); | |
946 base::TimeTicks proxy_resolve_start_time = info.proxy_resolve_start_time(); | |
947 base::TimeTicks proxy_resolve_end_time = info.proxy_resolve_end_time(); | |
948 | |
949 // Fake an error on the proxy. | |
950 TestCompletionCallback callback2; | |
951 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, | |
952 net::ERR_PROXY_CONNECTION_FAILED, | |
953 &info, callback2.callback(), NULL, | |
954 NULL, BoundNetLog()); | |
955 EXPECT_EQ(OK, rv); | |
956 | |
957 // Proxy times should not have been modified by fallback. | |
958 EXPECT_EQ(proxy_resolve_start_time, info.proxy_resolve_start_time()); | |
959 EXPECT_EQ(proxy_resolve_end_time, info.proxy_resolve_end_time()); | |
960 | |
961 // The second proxy should be specified. | |
962 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); | |
963 // Report back that the second proxy worked. This will globally mark the | |
964 // first proxy as bad. | |
965 TestProxyFallbackNetworkDelegate test_delegate; | |
966 service.ReportSuccess(info, &test_delegate); | |
967 EXPECT_EQ("foopy1:8080", test_delegate.proxy_server().ToURI()); | |
968 EXPECT_EQ(net::ERR_PROXY_CONNECTION_FAILED, | |
969 test_delegate.proxy_fallback_net_error()); | |
970 | |
971 TestCompletionCallback callback3; | |
972 rv = service.ResolveProxy( | |
973 url, net::LOAD_NORMAL, &info, callback3.callback(), NULL, NULL, | |
974 BoundNetLog()); | |
975 EXPECT_EQ(ERR_IO_PENDING, rv); | |
976 | |
977 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
978 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); | |
979 | |
980 // Set the result in proxy resolver -- the second result is already known | |
981 // to be bad, so we will not try to use it initially. | |
982 resolver->pending_requests()[0]->results()->UseNamedProxy( | |
983 "foopy3:7070;foopy1:8080;foopy2:9090"); | |
984 resolver->pending_requests()[0]->CompleteNow(OK); | |
985 | |
986 EXPECT_EQ(OK, callback3.WaitForResult()); | |
987 EXPECT_FALSE(info.is_direct()); | |
988 EXPECT_EQ("foopy3:7070", info.proxy_server().ToURI()); | |
989 | |
990 // Proxy times should have been updated, so get them again. | |
991 EXPECT_LE(proxy_resolve_end_time, info.proxy_resolve_start_time()); | |
992 EXPECT_FALSE(info.proxy_resolve_start_time().is_null()); | |
993 EXPECT_FALSE(info.proxy_resolve_end_time().is_null()); | |
994 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time()); | |
995 proxy_resolve_start_time = info.proxy_resolve_start_time(); | |
996 proxy_resolve_end_time = info.proxy_resolve_end_time(); | |
997 | |
998 // We fake another error. It should now try the third one. | |
999 TestCompletionCallback callback4; | |
1000 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, | |
1001 net::ERR_PROXY_CONNECTION_FAILED, | |
1002 &info, callback4.callback(), NULL, | |
1003 NULL, BoundNetLog()); | |
1004 EXPECT_EQ(OK, rv); | |
1005 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); | |
1006 | |
1007 // We fake another error. At this point we have tried all of the | |
1008 // proxy servers we thought were valid; next we try the proxy server | |
1009 // that was in our bad proxies map (foopy1:8080). | |
1010 TestCompletionCallback callback5; | |
1011 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, | |
1012 net::ERR_PROXY_CONNECTION_FAILED, | |
1013 &info, callback5.callback(), NULL, | |
1014 NULL, BoundNetLog()); | |
1015 EXPECT_EQ(OK, rv); | |
1016 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); | |
1017 | |
1018 // Fake another error, the last proxy is gone, the list should now be empty, | |
1019 // so there is nothing left to try. | |
1020 TestCompletionCallback callback6; | |
1021 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, | |
1022 net::ERR_PROXY_CONNECTION_FAILED, | |
1023 &info, callback6.callback(), NULL, | |
1024 NULL, BoundNetLog()); | |
1025 EXPECT_EQ(ERR_FAILED, rv); | |
1026 EXPECT_FALSE(info.is_direct()); | |
1027 EXPECT_TRUE(info.is_empty()); | |
1028 | |
1029 // Proxy times should not have been modified by fallback. | |
1030 EXPECT_EQ(proxy_resolve_start_time, info.proxy_resolve_start_time()); | |
1031 EXPECT_EQ(proxy_resolve_end_time, info.proxy_resolve_end_time()); | |
1032 | |
1033 // Look up proxies again | |
1034 TestCompletionCallback callback7; | |
1035 rv = service.ResolveProxy(url, net::LOAD_NORMAL, &info, callback7.callback(), | |
1036 NULL, NULL, BoundNetLog()); | |
1037 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1038 | |
1039 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
1040 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); | |
1041 | |
1042 // This time, the first 3 results have been found to be bad, but only the | |
1043 // first proxy has been confirmed ... | |
1044 resolver->pending_requests()[0]->results()->UseNamedProxy( | |
1045 "foopy1:8080;foopy3:7070;foopy2:9090;foopy4:9091"); | |
1046 resolver->pending_requests()[0]->CompleteNow(OK); | |
1047 | |
1048 // ... therefore, we should see the second proxy first. | |
1049 EXPECT_EQ(OK, callback7.WaitForResult()); | |
1050 EXPECT_FALSE(info.is_direct()); | |
1051 EXPECT_EQ("foopy3:7070", info.proxy_server().ToURI()); | |
1052 | |
1053 EXPECT_LE(proxy_resolve_end_time, info.proxy_resolve_start_time()); | |
1054 EXPECT_FALSE(info.proxy_resolve_start_time().is_null()); | |
1055 EXPECT_FALSE(info.proxy_resolve_end_time().is_null()); | |
1056 // TODO(nsylvain): Test that the proxy can be retried after the delay. | |
1057 } | |
1058 | |
1059 // This test is similar to ProxyFallback, but this time we have an explicit | |
1060 // fallback choice to DIRECT. | |
1061 TEST_F(ProxyServiceTest, ProxyFallbackToDirect) { | |
1062 MockProxyConfigService* config_service = | |
1063 new MockProxyConfigService("http://foopy/proxy.pac"); | |
1064 | |
1065 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; | |
1066 | |
1067 ProxyService service(config_service, resolver, NULL); | |
1068 | |
1069 GURL url("http://www.google.com/"); | |
1070 | |
1071 // Get the proxy information. | |
1072 ProxyInfo info; | |
1073 TestCompletionCallback callback1; | |
1074 int rv = service.ResolveProxy( | |
1075 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, | |
1076 BoundNetLog()); | |
1077 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1078 | |
1079 EXPECT_EQ(GURL("http://foopy/proxy.pac"), | |
1080 resolver->pending_set_pac_script_request()->script_data()->url()); | |
1081 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
1082 | |
1083 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
1084 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); | |
1085 | |
1086 // Set the result in proxy resolver. | |
1087 resolver->pending_requests()[0]->results()->UsePacString( | |
1088 "PROXY foopy1:8080; PROXY foopy2:9090; DIRECT"); | |
1089 resolver->pending_requests()[0]->CompleteNow(OK); | |
1090 | |
1091 // Get the first result. | |
1092 EXPECT_EQ(OK, callback1.WaitForResult()); | |
1093 EXPECT_FALSE(info.is_direct()); | |
1094 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); | |
1095 | |
1096 // Fake an error on the proxy. | |
1097 TestCompletionCallback callback2; | |
1098 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, | |
1099 net::ERR_PROXY_CONNECTION_FAILED, | |
1100 &info, callback2.callback(), NULL, | |
1101 NULL, BoundNetLog()); | |
1102 EXPECT_EQ(OK, rv); | |
1103 | |
1104 // Now we get back the second proxy. | |
1105 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); | |
1106 | |
1107 // Fake an error on this proxy as well. | |
1108 TestCompletionCallback callback3; | |
1109 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, | |
1110 net::ERR_PROXY_CONNECTION_FAILED, | |
1111 &info, callback3.callback(), NULL, | |
1112 NULL, BoundNetLog()); | |
1113 EXPECT_EQ(OK, rv); | |
1114 | |
1115 // Finally, we get back DIRECT. | |
1116 EXPECT_TRUE(info.is_direct()); | |
1117 | |
1118 EXPECT_FALSE(info.proxy_resolve_start_time().is_null()); | |
1119 EXPECT_FALSE(info.proxy_resolve_end_time().is_null()); | |
1120 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time()); | |
1121 | |
1122 // Now we tell the proxy service that even DIRECT failed. | |
1123 TestCompletionCallback callback4; | |
1124 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, | |
1125 net::ERR_PROXY_CONNECTION_FAILED, | |
1126 &info, callback4.callback(), NULL, | |
1127 NULL, BoundNetLog()); | |
1128 // There was nothing left to try after DIRECT, so we are out of | |
1129 // choices. | |
1130 EXPECT_EQ(ERR_FAILED, rv); | |
1131 } | |
1132 | |
1133 TEST_F(ProxyServiceTest, ProxyFallback_NewSettings) { | |
1134 // Test proxy failover when new settings are available. | |
1135 | |
1136 MockProxyConfigService* config_service = | |
1137 new MockProxyConfigService("http://foopy/proxy.pac"); | |
1138 | |
1139 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; | |
1140 | |
1141 ProxyService service(config_service, resolver, NULL); | |
1142 | |
1143 GURL url("http://www.google.com/"); | |
1144 | |
1145 // Get the proxy information. | |
1146 ProxyInfo info; | |
1147 TestCompletionCallback callback1; | |
1148 int rv = service.ResolveProxy( | |
1149 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, | |
1150 BoundNetLog()); | |
1151 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1152 | |
1153 EXPECT_EQ(GURL("http://foopy/proxy.pac"), | |
1154 resolver->pending_set_pac_script_request()->script_data()->url()); | |
1155 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
1156 | |
1157 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
1158 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); | |
1159 | |
1160 // Set the result in proxy resolver. | |
1161 resolver->pending_requests()[0]->results()->UseNamedProxy( | |
1162 "foopy1:8080;foopy2:9090"); | |
1163 resolver->pending_requests()[0]->CompleteNow(OK); | |
1164 | |
1165 // The first item is valid. | |
1166 EXPECT_EQ(OK, callback1.WaitForResult()); | |
1167 EXPECT_FALSE(info.is_direct()); | |
1168 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); | |
1169 | |
1170 // Fake an error on the proxy, and also a new configuration on the proxy. | |
1171 config_service->SetConfig( | |
1172 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy-new/proxy.pac"))); | |
1173 | |
1174 TestCompletionCallback callback2; | |
1175 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, | |
1176 net::ERR_PROXY_CONNECTION_FAILED, | |
1177 &info, callback2.callback(), NULL, | |
1178 NULL, BoundNetLog()); | |
1179 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1180 | |
1181 EXPECT_EQ(GURL("http://foopy-new/proxy.pac"), | |
1182 resolver->pending_set_pac_script_request()->script_data()->url()); | |
1183 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
1184 | |
1185 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
1186 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); | |
1187 | |
1188 resolver->pending_requests()[0]->results()->UseNamedProxy( | |
1189 "foopy1:8080;foopy2:9090"); | |
1190 resolver->pending_requests()[0]->CompleteNow(OK); | |
1191 | |
1192 // The first proxy is still there since the configuration changed. | |
1193 EXPECT_EQ(OK, callback2.WaitForResult()); | |
1194 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); | |
1195 | |
1196 // We fake another error. It should now ignore the first one. | |
1197 TestCompletionCallback callback3; | |
1198 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, | |
1199 net::ERR_PROXY_CONNECTION_FAILED, | |
1200 &info, callback3.callback(), NULL, | |
1201 NULL, BoundNetLog()); | |
1202 EXPECT_EQ(OK, rv); | |
1203 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); | |
1204 | |
1205 // We simulate a new configuration. | |
1206 config_service->SetConfig( | |
1207 ProxyConfig::CreateFromCustomPacURL( | |
1208 GURL("http://foopy-new2/proxy.pac"))); | |
1209 | |
1210 // We fake another error. It should go back to the first proxy. | |
1211 TestCompletionCallback callback4; | |
1212 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, | |
1213 net::ERR_PROXY_CONNECTION_FAILED, | |
1214 &info, callback4.callback(), NULL, | |
1215 NULL, BoundNetLog()); | |
1216 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1217 | |
1218 EXPECT_EQ(GURL("http://foopy-new2/proxy.pac"), | |
1219 resolver->pending_set_pac_script_request()->script_data()->url()); | |
1220 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
1221 | |
1222 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
1223 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); | |
1224 | |
1225 resolver->pending_requests()[0]->results()->UseNamedProxy( | |
1226 "foopy1:8080;foopy2:9090"); | |
1227 resolver->pending_requests()[0]->CompleteNow(OK); | |
1228 | |
1229 EXPECT_EQ(OK, callback4.WaitForResult()); | |
1230 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); | |
1231 | |
1232 EXPECT_FALSE(info.proxy_resolve_start_time().is_null()); | |
1233 EXPECT_FALSE(info.proxy_resolve_end_time().is_null()); | |
1234 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time()); | |
1235 } | |
1236 | |
1237 TEST_F(ProxyServiceTest, ProxyFallback_BadConfig) { | |
1238 // Test proxy failover when the configuration is bad. | |
1239 | |
1240 MockProxyConfigService* config_service = | |
1241 new MockProxyConfigService("http://foopy/proxy.pac"); | |
1242 | |
1243 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; | |
1244 | |
1245 ProxyService service(config_service, resolver, NULL); | |
1246 | |
1247 GURL url("http://www.google.com/"); | |
1248 | |
1249 // Get the proxy information. | |
1250 ProxyInfo info; | |
1251 TestCompletionCallback callback1; | |
1252 int rv = service.ResolveProxy( | |
1253 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, | |
1254 BoundNetLog()); | |
1255 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1256 | |
1257 EXPECT_EQ(GURL("http://foopy/proxy.pac"), | |
1258 resolver->pending_set_pac_script_request()->script_data()->url()); | |
1259 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
1260 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
1261 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); | |
1262 | |
1263 resolver->pending_requests()[0]->results()->UseNamedProxy( | |
1264 "foopy1:8080;foopy2:9090"); | |
1265 resolver->pending_requests()[0]->CompleteNow(OK); | |
1266 | |
1267 // The first item is valid. | |
1268 EXPECT_EQ(OK, callback1.WaitForResult()); | |
1269 EXPECT_FALSE(info.is_direct()); | |
1270 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); | |
1271 | |
1272 // Fake a proxy error. | |
1273 TestCompletionCallback callback2; | |
1274 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, | |
1275 net::ERR_PROXY_CONNECTION_FAILED, | |
1276 &info, callback2.callback(), NULL, | |
1277 NULL, BoundNetLog()); | |
1278 EXPECT_EQ(OK, rv); | |
1279 | |
1280 // The first proxy is ignored, and the second one is selected. | |
1281 EXPECT_FALSE(info.is_direct()); | |
1282 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); | |
1283 | |
1284 // Fake a PAC failure. | |
1285 ProxyInfo info2; | |
1286 TestCompletionCallback callback3; | |
1287 rv = service.ResolveProxy( | |
1288 url, net::LOAD_NORMAL, &info2, callback3.callback(), NULL, NULL, | |
1289 BoundNetLog()); | |
1290 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1291 | |
1292 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
1293 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); | |
1294 | |
1295 // This simulates a javascript runtime error in the PAC script. | |
1296 resolver->pending_requests()[0]->CompleteNow(ERR_FAILED); | |
1297 | |
1298 // Although the resolver failed, the ProxyService will implicitly fall-back | |
1299 // to a DIRECT connection. | |
1300 EXPECT_EQ(OK, callback3.WaitForResult()); | |
1301 EXPECT_TRUE(info2.is_direct()); | |
1302 EXPECT_FALSE(info2.is_empty()); | |
1303 | |
1304 // The PAC script will work properly next time and successfully return a | |
1305 // proxy list. Since we have not marked the configuration as bad, it should | |
1306 // "just work" the next time we call it. | |
1307 ProxyInfo info3; | |
1308 TestCompletionCallback callback4; | |
1309 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, | |
1310 net::ERR_PROXY_CONNECTION_FAILED, | |
1311 &info3, callback4.callback(), | |
1312 NULL, NULL, BoundNetLog()); | |
1313 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1314 | |
1315 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
1316 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); | |
1317 | |
1318 resolver->pending_requests()[0]->results()->UseNamedProxy( | |
1319 "foopy1:8080;foopy2:9090"); | |
1320 resolver->pending_requests()[0]->CompleteNow(OK); | |
1321 | |
1322 // The first proxy is not there since the it was added to the bad proxies | |
1323 // list by the earlier ReconsiderProxyAfterError(). | |
1324 EXPECT_EQ(OK, callback4.WaitForResult()); | |
1325 EXPECT_FALSE(info3.is_direct()); | |
1326 EXPECT_EQ("foopy1:8080", info3.proxy_server().ToURI()); | |
1327 | |
1328 EXPECT_FALSE(info.proxy_resolve_start_time().is_null()); | |
1329 EXPECT_FALSE(info.proxy_resolve_end_time().is_null()); | |
1330 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time()); | |
1331 } | |
1332 | |
1333 TEST_F(ProxyServiceTest, ProxyFallback_BadConfigMandatory) { | |
1334 // Test proxy failover when the configuration is bad. | |
1335 | |
1336 ProxyConfig config( | |
1337 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"))); | |
1338 | |
1339 config.set_pac_mandatory(true); | |
1340 MockProxyConfigService* config_service = new MockProxyConfigService(config); | |
1341 | |
1342 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; | |
1343 | |
1344 ProxyService service(config_service, resolver, NULL); | |
1345 | |
1346 GURL url("http://www.google.com/"); | |
1347 | |
1348 // Get the proxy information. | |
1349 ProxyInfo info; | |
1350 TestCompletionCallback callback1; | |
1351 int rv = service.ResolveProxy( | |
1352 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, | |
1353 BoundNetLog()); | |
1354 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1355 | |
1356 EXPECT_EQ(GURL("http://foopy/proxy.pac"), | |
1357 resolver->pending_set_pac_script_request()->script_data()->url()); | |
1358 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
1359 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
1360 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); | |
1361 | |
1362 resolver->pending_requests()[0]->results()->UseNamedProxy( | |
1363 "foopy1:8080;foopy2:9090"); | |
1364 resolver->pending_requests()[0]->CompleteNow(OK); | |
1365 | |
1366 // The first item is valid. | |
1367 EXPECT_EQ(OK, callback1.WaitForResult()); | |
1368 EXPECT_FALSE(info.is_direct()); | |
1369 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); | |
1370 | |
1371 // Fake a proxy error. | |
1372 TestCompletionCallback callback2; | |
1373 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, | |
1374 net::ERR_PROXY_CONNECTION_FAILED, | |
1375 &info, callback2.callback(), NULL, | |
1376 NULL, BoundNetLog()); | |
1377 EXPECT_EQ(OK, rv); | |
1378 | |
1379 // The first proxy is ignored, and the second one is selected. | |
1380 EXPECT_FALSE(info.is_direct()); | |
1381 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); | |
1382 | |
1383 // Fake a PAC failure. | |
1384 ProxyInfo info2; | |
1385 TestCompletionCallback callback3; | |
1386 rv = service.ResolveProxy( | |
1387 url, net::LOAD_NORMAL, &info2, callback3.callback(), NULL, NULL, | |
1388 BoundNetLog()); | |
1389 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1390 | |
1391 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
1392 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); | |
1393 | |
1394 // This simulates a javascript runtime error in the PAC script. | |
1395 resolver->pending_requests()[0]->CompleteNow(ERR_FAILED); | |
1396 | |
1397 // Although the resolver failed, the ProxyService will NOT fall-back | |
1398 // to a DIRECT connection as it is configured as mandatory. | |
1399 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED, | |
1400 callback3.WaitForResult()); | |
1401 EXPECT_FALSE(info2.is_direct()); | |
1402 EXPECT_TRUE(info2.is_empty()); | |
1403 | |
1404 // The PAC script will work properly next time and successfully return a | |
1405 // proxy list. Since we have not marked the configuration as bad, it should | |
1406 // "just work" the next time we call it. | |
1407 ProxyInfo info3; | |
1408 TestCompletionCallback callback4; | |
1409 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, | |
1410 net::ERR_PROXY_CONNECTION_FAILED, | |
1411 &info3, callback4.callback(), | |
1412 NULL, NULL, BoundNetLog()); | |
1413 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1414 | |
1415 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
1416 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); | |
1417 | |
1418 resolver->pending_requests()[0]->results()->UseNamedProxy( | |
1419 "foopy1:8080;foopy2:9090"); | |
1420 resolver->pending_requests()[0]->CompleteNow(OK); | |
1421 | |
1422 // The first proxy is not there since the it was added to the bad proxies | |
1423 // list by the earlier ReconsiderProxyAfterError(). | |
1424 EXPECT_EQ(OK, callback4.WaitForResult()); | |
1425 EXPECT_FALSE(info3.is_direct()); | |
1426 EXPECT_EQ("foopy1:8080", info3.proxy_server().ToURI()); | |
1427 } | |
1428 | |
1429 TEST_F(ProxyServiceTest, ProxyBypassList) { | |
1430 // Test that the proxy bypass rules are consulted. | |
1431 | |
1432 TestCompletionCallback callback[2]; | |
1433 ProxyInfo info[2]; | |
1434 ProxyConfig config; | |
1435 config.proxy_rules().ParseFromString("foopy1:8080;foopy2:9090"); | |
1436 config.set_auto_detect(false); | |
1437 config.proxy_rules().bypass_rules.ParseFromString("*.org"); | |
1438 | |
1439 ProxyService service( | |
1440 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL); | |
1441 | |
1442 int rv; | |
1443 GURL url1("http://www.webkit.org"); | |
1444 GURL url2("http://www.webkit.com"); | |
1445 | |
1446 // Request for a .org domain should bypass proxy. | |
1447 rv = service.ResolveProxy( | |
1448 url1, net::LOAD_NORMAL, &info[0], callback[0].callback(), NULL, NULL, | |
1449 BoundNetLog()); | |
1450 EXPECT_EQ(OK, rv); | |
1451 EXPECT_TRUE(info[0].is_direct()); | |
1452 | |
1453 // Request for a .com domain hits the proxy. | |
1454 rv = service.ResolveProxy( | |
1455 url2, net::LOAD_NORMAL, &info[1], callback[1].callback(), NULL, NULL, | |
1456 BoundNetLog()); | |
1457 EXPECT_EQ(OK, rv); | |
1458 EXPECT_EQ("foopy1:8080", info[1].proxy_server().ToURI()); | |
1459 } | |
1460 | |
1461 | |
1462 TEST_F(ProxyServiceTest, PerProtocolProxyTests) { | |
1463 ProxyConfig config; | |
1464 config.proxy_rules().ParseFromString("http=foopy1:8080;https=foopy2:8080"); | |
1465 config.set_auto_detect(false); | |
1466 { | |
1467 ProxyService service( | |
1468 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL); | |
1469 GURL test_url("http://www.msn.com"); | |
1470 ProxyInfo info; | |
1471 TestCompletionCallback callback; | |
1472 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, | |
1473 callback.callback(), NULL, NULL, | |
1474 BoundNetLog()); | |
1475 EXPECT_EQ(OK, rv); | |
1476 EXPECT_FALSE(info.is_direct()); | |
1477 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); | |
1478 } | |
1479 { | |
1480 ProxyService service( | |
1481 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL); | |
1482 GURL test_url("ftp://ftp.google.com"); | |
1483 ProxyInfo info; | |
1484 TestCompletionCallback callback; | |
1485 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, | |
1486 callback.callback(), NULL, | |
1487 NULL, BoundNetLog()); | |
1488 EXPECT_EQ(OK, rv); | |
1489 EXPECT_TRUE(info.is_direct()); | |
1490 EXPECT_EQ("direct://", info.proxy_server().ToURI()); | |
1491 } | |
1492 { | |
1493 ProxyService service( | |
1494 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL); | |
1495 GURL test_url("https://webbranch.techcu.com"); | |
1496 ProxyInfo info; | |
1497 TestCompletionCallback callback; | |
1498 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, | |
1499 callback.callback(), NULL, | |
1500 NULL, BoundNetLog()); | |
1501 EXPECT_EQ(OK, rv); | |
1502 EXPECT_FALSE(info.is_direct()); | |
1503 EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI()); | |
1504 } | |
1505 { | |
1506 config.proxy_rules().ParseFromString("foopy1:8080"); | |
1507 ProxyService service( | |
1508 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL); | |
1509 GURL test_url("http://www.microsoft.com"); | |
1510 ProxyInfo info; | |
1511 TestCompletionCallback callback; | |
1512 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, | |
1513 callback.callback(), NULL, | |
1514 NULL, BoundNetLog()); | |
1515 EXPECT_EQ(OK, rv); | |
1516 EXPECT_FALSE(info.is_direct()); | |
1517 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); | |
1518 } | |
1519 } | |
1520 | |
1521 TEST_F(ProxyServiceTest, ProxyConfigSourcePropagates) { | |
1522 // Test that the proxy config source is set correctly when resolving proxies | |
1523 // using manual proxy rules. Namely, the config source should only be set if | |
1524 // any of the rules were applied. | |
1525 { | |
1526 ProxyConfig config; | |
1527 config.set_source(PROXY_CONFIG_SOURCE_TEST); | |
1528 config.proxy_rules().ParseFromString("https=foopy2:8080"); | |
1529 ProxyService service( | |
1530 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL); | |
1531 GURL test_url("http://www.google.com"); | |
1532 ProxyInfo info; | |
1533 TestCompletionCallback callback; | |
1534 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, | |
1535 callback.callback(), NULL, | |
1536 NULL, BoundNetLog()); | |
1537 ASSERT_EQ(OK, rv); | |
1538 // Should be SOURCE_TEST, even if there are no HTTP proxies configured. | |
1539 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source()); | |
1540 } | |
1541 { | |
1542 ProxyConfig config; | |
1543 config.set_source(PROXY_CONFIG_SOURCE_TEST); | |
1544 config.proxy_rules().ParseFromString("https=foopy2:8080"); | |
1545 ProxyService service( | |
1546 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL); | |
1547 GURL test_url("https://www.google.com"); | |
1548 ProxyInfo info; | |
1549 TestCompletionCallback callback; | |
1550 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, | |
1551 callback.callback(), NULL, | |
1552 NULL, BoundNetLog()); | |
1553 ASSERT_EQ(OK, rv); | |
1554 // Used the HTTPS proxy. So source should be TEST. | |
1555 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source()); | |
1556 } | |
1557 { | |
1558 ProxyConfig config; | |
1559 config.set_source(PROXY_CONFIG_SOURCE_TEST); | |
1560 ProxyService service( | |
1561 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL); | |
1562 GURL test_url("http://www.google.com"); | |
1563 ProxyInfo info; | |
1564 TestCompletionCallback callback; | |
1565 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, | |
1566 callback.callback(), NULL, | |
1567 NULL, BoundNetLog()); | |
1568 ASSERT_EQ(OK, rv); | |
1569 // ProxyConfig is empty. Source should still be TEST. | |
1570 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source()); | |
1571 } | |
1572 } | |
1573 | |
1574 // If only HTTP and a SOCKS proxy are specified, check if ftp/https queries | |
1575 // fall back to the SOCKS proxy. | |
1576 TEST_F(ProxyServiceTest, DefaultProxyFallbackToSOCKS) { | |
1577 ProxyConfig config; | |
1578 config.proxy_rules().ParseFromString("http=foopy1:8080;socks=foopy2:1080"); | |
1579 config.set_auto_detect(false); | |
1580 EXPECT_EQ(ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, | |
1581 config.proxy_rules().type); | |
1582 | |
1583 { | |
1584 ProxyService service( | |
1585 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL); | |
1586 GURL test_url("http://www.msn.com"); | |
1587 ProxyInfo info; | |
1588 TestCompletionCallback callback; | |
1589 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, | |
1590 callback.callback(), NULL, | |
1591 NULL, BoundNetLog()); | |
1592 EXPECT_EQ(OK, rv); | |
1593 EXPECT_FALSE(info.is_direct()); | |
1594 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); | |
1595 } | |
1596 { | |
1597 ProxyService service( | |
1598 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL); | |
1599 GURL test_url("ftp://ftp.google.com"); | |
1600 ProxyInfo info; | |
1601 TestCompletionCallback callback; | |
1602 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, | |
1603 callback.callback(), NULL, | |
1604 NULL, BoundNetLog()); | |
1605 EXPECT_EQ(OK, rv); | |
1606 EXPECT_FALSE(info.is_direct()); | |
1607 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI()); | |
1608 } | |
1609 { | |
1610 ProxyService service( | |
1611 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL); | |
1612 GURL test_url("https://webbranch.techcu.com"); | |
1613 ProxyInfo info; | |
1614 TestCompletionCallback callback; | |
1615 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, | |
1616 callback.callback(), NULL, | |
1617 NULL, BoundNetLog()); | |
1618 EXPECT_EQ(OK, rv); | |
1619 EXPECT_FALSE(info.is_direct()); | |
1620 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI()); | |
1621 } | |
1622 { | |
1623 ProxyService service( | |
1624 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL); | |
1625 GURL test_url("unknown://www.microsoft.com"); | |
1626 ProxyInfo info; | |
1627 TestCompletionCallback callback; | |
1628 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, | |
1629 callback.callback(), NULL, | |
1630 NULL, BoundNetLog()); | |
1631 EXPECT_EQ(OK, rv); | |
1632 EXPECT_FALSE(info.is_direct()); | |
1633 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI()); | |
1634 } | |
1635 } | |
1636 | |
1637 // Test cancellation of an in-progress request. | |
1638 TEST_F(ProxyServiceTest, CancelInProgressRequest) { | |
1639 MockProxyConfigService* config_service = | |
1640 new MockProxyConfigService("http://foopy/proxy.pac"); | |
1641 | |
1642 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; | |
1643 | |
1644 ProxyService service(config_service, resolver, NULL); | |
1645 | |
1646 // Start 3 requests. | |
1647 | |
1648 ProxyInfo info1; | |
1649 TestCompletionCallback callback1; | |
1650 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL, | |
1651 &info1, callback1.callback(), NULL, NULL, | |
1652 BoundNetLog()); | |
1653 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1654 | |
1655 // Nothing has been sent to the proxy resolver yet, since the proxy | |
1656 // resolver has not been configured yet. | |
1657 ASSERT_EQ(0u, resolver->pending_requests().size()); | |
1658 | |
1659 // Successfully initialize the PAC script. | |
1660 EXPECT_EQ(GURL("http://foopy/proxy.pac"), | |
1661 resolver->pending_set_pac_script_request()->script_data()->url()); | |
1662 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
1663 | |
1664 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
1665 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); | |
1666 | |
1667 ProxyInfo info2; | |
1668 TestCompletionCallback callback2; | |
1669 ProxyService::PacRequest* request2; | |
1670 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2, | |
1671 callback2.callback(), &request2, NULL, | |
1672 BoundNetLog()); | |
1673 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1674 ASSERT_EQ(2u, resolver->pending_requests().size()); | |
1675 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url()); | |
1676 | |
1677 ProxyInfo info3; | |
1678 TestCompletionCallback callback3; | |
1679 rv = service.ResolveProxy(GURL("http://request3"), net::LOAD_NORMAL, &info3, | |
1680 callback3.callback(), NULL, NULL, BoundNetLog()); | |
1681 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1682 ASSERT_EQ(3u, resolver->pending_requests().size()); | |
1683 EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[2]->url()); | |
1684 | |
1685 // Cancel the second request | |
1686 service.CancelPacRequest(request2); | |
1687 | |
1688 ASSERT_EQ(2u, resolver->pending_requests().size()); | |
1689 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); | |
1690 EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[1]->url()); | |
1691 | |
1692 // Complete the two un-cancelled requests. | |
1693 // We complete the last one first, just to mix it up a bit. | |
1694 resolver->pending_requests()[1]->results()->UseNamedProxy("request3:80"); | |
1695 resolver->pending_requests()[1]->CompleteNow(OK); | |
1696 | |
1697 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); | |
1698 resolver->pending_requests()[0]->CompleteNow(OK); | |
1699 | |
1700 // Complete and verify that requests ran as expected. | |
1701 EXPECT_EQ(OK, callback1.WaitForResult()); | |
1702 EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); | |
1703 | |
1704 EXPECT_FALSE(callback2.have_result()); // Cancelled. | |
1705 ASSERT_EQ(1u, resolver->cancelled_requests().size()); | |
1706 EXPECT_EQ(GURL("http://request2"), resolver->cancelled_requests()[0]->url()); | |
1707 | |
1708 EXPECT_EQ(OK, callback3.WaitForResult()); | |
1709 EXPECT_EQ("request3:80", info3.proxy_server().ToURI()); | |
1710 } | |
1711 | |
1712 // Test the initial PAC download for resolver that expects bytes. | |
1713 TEST_F(ProxyServiceTest, InitialPACScriptDownload) { | |
1714 MockProxyConfigService* config_service = | |
1715 new MockProxyConfigService("http://foopy/proxy.pac"); | |
1716 | |
1717 MockAsyncProxyResolverExpectsBytes* resolver = | |
1718 new MockAsyncProxyResolverExpectsBytes; | |
1719 | |
1720 ProxyService service(config_service, resolver, NULL); | |
1721 | |
1722 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; | |
1723 service.SetProxyScriptFetchers(fetcher, | |
1724 new DoNothingDhcpProxyScriptFetcher()); | |
1725 | |
1726 // Start 3 requests. | |
1727 | |
1728 ProxyInfo info1; | |
1729 TestCompletionCallback callback1; | |
1730 ProxyService::PacRequest* request1; | |
1731 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL, | |
1732 &info1, callback1.callback(), &request1, NULL, | |
1733 BoundNetLog()); | |
1734 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1735 | |
1736 // The first request should have triggered download of PAC script. | |
1737 EXPECT_TRUE(fetcher->has_pending_request()); | |
1738 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); | |
1739 | |
1740 ProxyInfo info2; | |
1741 TestCompletionCallback callback2; | |
1742 ProxyService::PacRequest* request2; | |
1743 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2, | |
1744 callback2.callback(), &request2, NULL, | |
1745 BoundNetLog()); | |
1746 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1747 | |
1748 ProxyInfo info3; | |
1749 TestCompletionCallback callback3; | |
1750 ProxyService::PacRequest* request3; | |
1751 rv = service.ResolveProxy(GURL("http://request3"), net::LOAD_NORMAL, &info3, | |
1752 callback3.callback(), &request3, NULL, | |
1753 BoundNetLog()); | |
1754 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1755 | |
1756 // Nothing has been sent to the resolver yet. | |
1757 EXPECT_TRUE(resolver->pending_requests().empty()); | |
1758 | |
1759 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT, | |
1760 service.GetLoadState(request1)); | |
1761 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT, | |
1762 service.GetLoadState(request2)); | |
1763 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT, | |
1764 service.GetLoadState(request3)); | |
1765 | |
1766 // At this point the ProxyService should be waiting for the | |
1767 // ProxyScriptFetcher to invoke its completion callback, notifying it of | |
1768 // PAC script download completion. | |
1769 fetcher->NotifyFetchCompletion(OK, kValidPacScript1); | |
1770 | |
1771 // Now that the PAC script is downloaded, it will have been sent to the proxy | |
1772 // resolver. | |
1773 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1), | |
1774 resolver->pending_set_pac_script_request()->script_data()->utf16()); | |
1775 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
1776 | |
1777 ASSERT_EQ(3u, resolver->pending_requests().size()); | |
1778 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); | |
1779 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url()); | |
1780 EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[2]->url()); | |
1781 | |
1782 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request1)); | |
1783 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request2)); | |
1784 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request3)); | |
1785 | |
1786 // Complete all the requests (in some order). | |
1787 // Note that as we complete requests, they shift up in |pending_requests()|. | |
1788 | |
1789 resolver->pending_requests()[2]->results()->UseNamedProxy("request3:80"); | |
1790 resolver->pending_requests()[2]->CompleteNow(OK); | |
1791 | |
1792 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); | |
1793 resolver->pending_requests()[0]->CompleteNow(OK); | |
1794 | |
1795 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80"); | |
1796 resolver->pending_requests()[0]->CompleteNow(OK); | |
1797 | |
1798 // Complete and verify that requests ran as expected. | |
1799 EXPECT_EQ(OK, callback1.WaitForResult()); | |
1800 EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); | |
1801 EXPECT_FALSE(info1.proxy_resolve_start_time().is_null()); | |
1802 EXPECT_FALSE(info1.proxy_resolve_end_time().is_null()); | |
1803 EXPECT_LE(info1.proxy_resolve_start_time(), info1.proxy_resolve_end_time()); | |
1804 | |
1805 EXPECT_EQ(OK, callback2.WaitForResult()); | |
1806 EXPECT_EQ("request2:80", info2.proxy_server().ToURI()); | |
1807 EXPECT_FALSE(info2.proxy_resolve_start_time().is_null()); | |
1808 EXPECT_FALSE(info2.proxy_resolve_end_time().is_null()); | |
1809 EXPECT_LE(info2.proxy_resolve_start_time(), info2.proxy_resolve_end_time()); | |
1810 | |
1811 EXPECT_EQ(OK, callback3.WaitForResult()); | |
1812 EXPECT_EQ("request3:80", info3.proxy_server().ToURI()); | |
1813 EXPECT_FALSE(info3.proxy_resolve_start_time().is_null()); | |
1814 EXPECT_FALSE(info3.proxy_resolve_end_time().is_null()); | |
1815 EXPECT_LE(info3.proxy_resolve_start_time(), info3.proxy_resolve_end_time()); | |
1816 } | |
1817 | |
1818 // Test changing the ProxyScriptFetcher while PAC download is in progress. | |
1819 TEST_F(ProxyServiceTest, ChangeScriptFetcherWhilePACDownloadInProgress) { | |
1820 MockProxyConfigService* config_service = | |
1821 new MockProxyConfigService("http://foopy/proxy.pac"); | |
1822 | |
1823 MockAsyncProxyResolverExpectsBytes* resolver = | |
1824 new MockAsyncProxyResolverExpectsBytes; | |
1825 | |
1826 ProxyService service(config_service, resolver, NULL); | |
1827 | |
1828 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; | |
1829 service.SetProxyScriptFetchers(fetcher, | |
1830 new DoNothingDhcpProxyScriptFetcher()); | |
1831 | |
1832 // Start 2 requests. | |
1833 | |
1834 ProxyInfo info1; | |
1835 TestCompletionCallback callback1; | |
1836 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL, | |
1837 &info1, callback1.callback(), NULL, NULL, | |
1838 BoundNetLog()); | |
1839 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1840 | |
1841 // The first request should have triggered download of PAC script. | |
1842 EXPECT_TRUE(fetcher->has_pending_request()); | |
1843 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); | |
1844 | |
1845 ProxyInfo info2; | |
1846 TestCompletionCallback callback2; | |
1847 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2, | |
1848 callback2.callback(), NULL, NULL, BoundNetLog()); | |
1849 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1850 | |
1851 // At this point the ProxyService should be waiting for the | |
1852 // ProxyScriptFetcher to invoke its completion callback, notifying it of | |
1853 // PAC script download completion. | |
1854 | |
1855 // We now change out the ProxyService's script fetcher. We should restart | |
1856 // the initialization with the new fetcher. | |
1857 | |
1858 fetcher = new MockProxyScriptFetcher; | |
1859 service.SetProxyScriptFetchers(fetcher, | |
1860 new DoNothingDhcpProxyScriptFetcher()); | |
1861 | |
1862 // Nothing has been sent to the resolver yet. | |
1863 EXPECT_TRUE(resolver->pending_requests().empty()); | |
1864 | |
1865 fetcher->NotifyFetchCompletion(OK, kValidPacScript1); | |
1866 | |
1867 // Now that the PAC script is downloaded, it will have been sent to the proxy | |
1868 // resolver. | |
1869 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1), | |
1870 resolver->pending_set_pac_script_request()->script_data()->utf16()); | |
1871 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
1872 | |
1873 ASSERT_EQ(2u, resolver->pending_requests().size()); | |
1874 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); | |
1875 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url()); | |
1876 } | |
1877 | |
1878 // Test cancellation of a request, while the PAC script is being fetched. | |
1879 TEST_F(ProxyServiceTest, CancelWhilePACFetching) { | |
1880 MockProxyConfigService* config_service = | |
1881 new MockProxyConfigService("http://foopy/proxy.pac"); | |
1882 | |
1883 MockAsyncProxyResolverExpectsBytes* resolver = | |
1884 new MockAsyncProxyResolverExpectsBytes; | |
1885 | |
1886 ProxyService service(config_service, resolver, NULL); | |
1887 | |
1888 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; | |
1889 service.SetProxyScriptFetchers(fetcher, | |
1890 new DoNothingDhcpProxyScriptFetcher()); | |
1891 | |
1892 // Start 3 requests. | |
1893 ProxyInfo info1; | |
1894 TestCompletionCallback callback1; | |
1895 ProxyService::PacRequest* request1; | |
1896 CapturingBoundNetLog log1; | |
1897 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL, | |
1898 &info1, callback1.callback(), &request1, NULL, | |
1899 log1.bound()); | |
1900 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1901 | |
1902 // The first request should have triggered download of PAC script. | |
1903 EXPECT_TRUE(fetcher->has_pending_request()); | |
1904 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); | |
1905 | |
1906 ProxyInfo info2; | |
1907 TestCompletionCallback callback2; | |
1908 ProxyService::PacRequest* request2; | |
1909 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2, | |
1910 callback2.callback(), &request2, NULL, | |
1911 BoundNetLog()); | |
1912 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1913 | |
1914 ProxyInfo info3; | |
1915 TestCompletionCallback callback3; | |
1916 rv = service.ResolveProxy(GURL("http://request3"), net::LOAD_NORMAL, &info3, | |
1917 callback3.callback(), NULL, NULL, BoundNetLog()); | |
1918 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1919 | |
1920 // Nothing has been sent to the resolver yet. | |
1921 EXPECT_TRUE(resolver->pending_requests().empty()); | |
1922 | |
1923 // Cancel the first 2 requests. | |
1924 service.CancelPacRequest(request1); | |
1925 service.CancelPacRequest(request2); | |
1926 | |
1927 // At this point the ProxyService should be waiting for the | |
1928 // ProxyScriptFetcher to invoke its completion callback, notifying it of | |
1929 // PAC script download completion. | |
1930 fetcher->NotifyFetchCompletion(OK, kValidPacScript1); | |
1931 | |
1932 // Now that the PAC script is downloaded, it will have been sent to the | |
1933 // proxy resolver. | |
1934 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1), | |
1935 resolver->pending_set_pac_script_request()->script_data()->utf16()); | |
1936 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
1937 | |
1938 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
1939 EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[0]->url()); | |
1940 | |
1941 // Complete all the requests. | |
1942 resolver->pending_requests()[0]->results()->UseNamedProxy("request3:80"); | |
1943 resolver->pending_requests()[0]->CompleteNow(OK); | |
1944 | |
1945 EXPECT_EQ(OK, callback3.WaitForResult()); | |
1946 EXPECT_EQ("request3:80", info3.proxy_server().ToURI()); | |
1947 | |
1948 EXPECT_TRUE(resolver->cancelled_requests().empty()); | |
1949 | |
1950 EXPECT_FALSE(callback1.have_result()); // Cancelled. | |
1951 EXPECT_FALSE(callback2.have_result()); // Cancelled. | |
1952 | |
1953 CapturingNetLog::CapturedEntryList entries1; | |
1954 log1.GetEntries(&entries1); | |
1955 | |
1956 // Check the NetLog for request 1 (which was cancelled) got filled properly. | |
1957 EXPECT_EQ(4u, entries1.size()); | |
1958 EXPECT_TRUE(LogContainsBeginEvent( | |
1959 entries1, 0, NetLog::TYPE_PROXY_SERVICE)); | |
1960 EXPECT_TRUE(LogContainsBeginEvent( | |
1961 entries1, 1, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC)); | |
1962 // Note that TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC is never completed before | |
1963 // the cancellation occured. | |
1964 EXPECT_TRUE(LogContainsEvent( | |
1965 entries1, 2, NetLog::TYPE_CANCELLED, NetLog::PHASE_NONE)); | |
1966 EXPECT_TRUE(LogContainsEndEvent( | |
1967 entries1, 3, NetLog::TYPE_PROXY_SERVICE)); | |
1968 } | |
1969 | |
1970 // Test that if auto-detect fails, we fall-back to the custom pac. | |
1971 TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomPac) { | |
1972 ProxyConfig config; | |
1973 config.set_auto_detect(true); | |
1974 config.set_pac_url(GURL("http://foopy/proxy.pac")); | |
1975 config.proxy_rules().ParseFromString("http=foopy:80"); // Won't be used. | |
1976 | |
1977 MockProxyConfigService* config_service = new MockProxyConfigService(config); | |
1978 MockAsyncProxyResolverExpectsBytes* resolver = | |
1979 new MockAsyncProxyResolverExpectsBytes; | |
1980 ProxyService service(config_service, resolver, NULL); | |
1981 | |
1982 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; | |
1983 service.SetProxyScriptFetchers(fetcher, | |
1984 new DoNothingDhcpProxyScriptFetcher()); | |
1985 | |
1986 // Start 2 requests. | |
1987 | |
1988 ProxyInfo info1; | |
1989 TestCompletionCallback callback1; | |
1990 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL, | |
1991 &info1, callback1.callback(), NULL, NULL, | |
1992 BoundNetLog()); | |
1993 EXPECT_EQ(ERR_IO_PENDING, rv); | |
1994 | |
1995 ProxyInfo info2; | |
1996 TestCompletionCallback callback2; | |
1997 ProxyService::PacRequest* request2; | |
1998 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2, | |
1999 callback2.callback(), &request2, NULL, | |
2000 BoundNetLog()); | |
2001 EXPECT_EQ(ERR_IO_PENDING, rv); | |
2002 | |
2003 // Check that nothing has been sent to the proxy resolver yet. | |
2004 ASSERT_EQ(0u, resolver->pending_requests().size()); | |
2005 | |
2006 // It should be trying to auto-detect first -- FAIL the autodetect during | |
2007 // the script download. | |
2008 EXPECT_TRUE(fetcher->has_pending_request()); | |
2009 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url()); | |
2010 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string()); | |
2011 | |
2012 // Next it should be trying the custom PAC url. | |
2013 EXPECT_TRUE(fetcher->has_pending_request()); | |
2014 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); | |
2015 fetcher->NotifyFetchCompletion(OK, kValidPacScript1); | |
2016 | |
2017 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1), | |
2018 resolver->pending_set_pac_script_request()->script_data()->utf16()); | |
2019 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
2020 | |
2021 // Now finally, the pending requests should have been sent to the resolver | |
2022 // (which was initialized with custom PAC script). | |
2023 | |
2024 ASSERT_EQ(2u, resolver->pending_requests().size()); | |
2025 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); | |
2026 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url()); | |
2027 | |
2028 // Complete the pending requests. | |
2029 resolver->pending_requests()[1]->results()->UseNamedProxy("request2:80"); | |
2030 resolver->pending_requests()[1]->CompleteNow(OK); | |
2031 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); | |
2032 resolver->pending_requests()[0]->CompleteNow(OK); | |
2033 | |
2034 // Verify that requests ran as expected. | |
2035 EXPECT_EQ(OK, callback1.WaitForResult()); | |
2036 EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); | |
2037 EXPECT_FALSE(info1.proxy_resolve_start_time().is_null()); | |
2038 EXPECT_FALSE(info1.proxy_resolve_end_time().is_null()); | |
2039 EXPECT_LE(info1.proxy_resolve_start_time(), info1.proxy_resolve_end_time()); | |
2040 | |
2041 EXPECT_EQ(OK, callback2.WaitForResult()); | |
2042 EXPECT_EQ("request2:80", info2.proxy_server().ToURI()); | |
2043 EXPECT_FALSE(info2.proxy_resolve_start_time().is_null()); | |
2044 EXPECT_FALSE(info2.proxy_resolve_end_time().is_null()); | |
2045 EXPECT_LE(info2.proxy_resolve_start_time(), info2.proxy_resolve_end_time()); | |
2046 } | |
2047 | |
2048 // This is the same test as FallbackFromAutodetectToCustomPac, except | |
2049 // the auto-detect script fails parsing rather than downloading. | |
2050 TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomPac2) { | |
2051 ProxyConfig config; | |
2052 config.set_auto_detect(true); | |
2053 config.set_pac_url(GURL("http://foopy/proxy.pac")); | |
2054 config.proxy_rules().ParseFromString("http=foopy:80"); // Won't be used. | |
2055 | |
2056 MockProxyConfigService* config_service = new MockProxyConfigService(config); | |
2057 MockAsyncProxyResolverExpectsBytes* resolver = | |
2058 new MockAsyncProxyResolverExpectsBytes; | |
2059 ProxyService service(config_service, resolver, NULL); | |
2060 | |
2061 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; | |
2062 service.SetProxyScriptFetchers(fetcher, | |
2063 new DoNothingDhcpProxyScriptFetcher()); | |
2064 | |
2065 // Start 2 requests. | |
2066 | |
2067 ProxyInfo info1; | |
2068 TestCompletionCallback callback1; | |
2069 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL, | |
2070 &info1, callback1.callback(), NULL, NULL, | |
2071 BoundNetLog()); | |
2072 EXPECT_EQ(ERR_IO_PENDING, rv); | |
2073 | |
2074 ProxyInfo info2; | |
2075 TestCompletionCallback callback2; | |
2076 ProxyService::PacRequest* request2; | |
2077 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2, | |
2078 callback2.callback(), &request2, NULL, | |
2079 BoundNetLog()); | |
2080 EXPECT_EQ(ERR_IO_PENDING, rv); | |
2081 | |
2082 // Check that nothing has been sent to the proxy resolver yet. | |
2083 ASSERT_EQ(0u, resolver->pending_requests().size()); | |
2084 | |
2085 // It should be trying to auto-detect first -- succeed the download. | |
2086 EXPECT_TRUE(fetcher->has_pending_request()); | |
2087 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url()); | |
2088 fetcher->NotifyFetchCompletion(OK, "invalid-script-contents"); | |
2089 | |
2090 // The script contents passed failed basic verification step (since didn't | |
2091 // contain token FindProxyForURL), so it was never passed to the resolver. | |
2092 | |
2093 // Next it should be trying the custom PAC url. | |
2094 EXPECT_TRUE(fetcher->has_pending_request()); | |
2095 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); | |
2096 fetcher->NotifyFetchCompletion(OK, kValidPacScript1); | |
2097 | |
2098 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1), | |
2099 resolver->pending_set_pac_script_request()->script_data()->utf16()); | |
2100 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
2101 | |
2102 // Now finally, the pending requests should have been sent to the resolver | |
2103 // (which was initialized with custom PAC script). | |
2104 | |
2105 ASSERT_EQ(2u, resolver->pending_requests().size()); | |
2106 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); | |
2107 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url()); | |
2108 | |
2109 // Complete the pending requests. | |
2110 resolver->pending_requests()[1]->results()->UseNamedProxy("request2:80"); | |
2111 resolver->pending_requests()[1]->CompleteNow(OK); | |
2112 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); | |
2113 resolver->pending_requests()[0]->CompleteNow(OK); | |
2114 | |
2115 // Verify that requests ran as expected. | |
2116 EXPECT_EQ(OK, callback1.WaitForResult()); | |
2117 EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); | |
2118 | |
2119 EXPECT_EQ(OK, callback2.WaitForResult()); | |
2120 EXPECT_EQ("request2:80", info2.proxy_server().ToURI()); | |
2121 } | |
2122 | |
2123 // Test that if all of auto-detect, a custom PAC script, and manual settings | |
2124 // are given, then we will try them in that order. | |
2125 TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomToManual) { | |
2126 ProxyConfig config; | |
2127 config.set_auto_detect(true); | |
2128 config.set_pac_url(GURL("http://foopy/proxy.pac")); | |
2129 config.proxy_rules().ParseFromString("http=foopy:80"); | |
2130 | |
2131 MockProxyConfigService* config_service = new MockProxyConfigService(config); | |
2132 MockAsyncProxyResolverExpectsBytes* resolver = | |
2133 new MockAsyncProxyResolverExpectsBytes; | |
2134 ProxyService service(config_service, resolver, NULL); | |
2135 | |
2136 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; | |
2137 service.SetProxyScriptFetchers(fetcher, | |
2138 new DoNothingDhcpProxyScriptFetcher()); | |
2139 | |
2140 // Start 2 requests. | |
2141 | |
2142 ProxyInfo info1; | |
2143 TestCompletionCallback callback1; | |
2144 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL, | |
2145 &info1, callback1.callback(), NULL, NULL, | |
2146 BoundNetLog()); | |
2147 EXPECT_EQ(ERR_IO_PENDING, rv); | |
2148 | |
2149 ProxyInfo info2; | |
2150 TestCompletionCallback callback2; | |
2151 ProxyService::PacRequest* request2; | |
2152 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2, | |
2153 callback2.callback(), &request2, NULL, | |
2154 BoundNetLog()); | |
2155 EXPECT_EQ(ERR_IO_PENDING, rv); | |
2156 | |
2157 // Check that nothing has been sent to the proxy resolver yet. | |
2158 ASSERT_EQ(0u, resolver->pending_requests().size()); | |
2159 | |
2160 // It should be trying to auto-detect first -- fail the download. | |
2161 EXPECT_TRUE(fetcher->has_pending_request()); | |
2162 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url()); | |
2163 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string()); | |
2164 | |
2165 // Next it should be trying the custom PAC url -- fail the download. | |
2166 EXPECT_TRUE(fetcher->has_pending_request()); | |
2167 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); | |
2168 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string()); | |
2169 | |
2170 // Since we never managed to initialize a ProxyResolver, nothing should have | |
2171 // been sent to it. | |
2172 ASSERT_EQ(0u, resolver->pending_requests().size()); | |
2173 | |
2174 // Verify that requests ran as expected -- they should have fallen back to | |
2175 // the manual proxy configuration for HTTP urls. | |
2176 EXPECT_EQ(OK, callback1.WaitForResult()); | |
2177 EXPECT_EQ("foopy:80", info1.proxy_server().ToURI()); | |
2178 | |
2179 EXPECT_EQ(OK, callback2.WaitForResult()); | |
2180 EXPECT_EQ("foopy:80", info2.proxy_server().ToURI()); | |
2181 } | |
2182 | |
2183 // Test that the bypass rules are NOT applied when using autodetect. | |
2184 TEST_F(ProxyServiceTest, BypassDoesntApplyToPac) { | |
2185 ProxyConfig config; | |
2186 config.set_auto_detect(true); | |
2187 config.set_pac_url(GURL("http://foopy/proxy.pac")); | |
2188 config.proxy_rules().ParseFromString("http=foopy:80"); // Not used. | |
2189 config.proxy_rules().bypass_rules.ParseFromString("www.google.com"); | |
2190 | |
2191 MockProxyConfigService* config_service = new MockProxyConfigService(config); | |
2192 MockAsyncProxyResolverExpectsBytes* resolver = | |
2193 new MockAsyncProxyResolverExpectsBytes; | |
2194 ProxyService service(config_service, resolver, NULL); | |
2195 | |
2196 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; | |
2197 service.SetProxyScriptFetchers(fetcher, | |
2198 new DoNothingDhcpProxyScriptFetcher()); | |
2199 | |
2200 // Start 1 requests. | |
2201 | |
2202 ProxyInfo info1; | |
2203 TestCompletionCallback callback1; | |
2204 int rv = service.ResolveProxy( | |
2205 GURL("http://www.google.com"), net::LOAD_NORMAL, &info1, | |
2206 callback1.callback(), NULL, NULL, BoundNetLog()); | |
2207 EXPECT_EQ(ERR_IO_PENDING, rv); | |
2208 | |
2209 // Check that nothing has been sent to the proxy resolver yet. | |
2210 ASSERT_EQ(0u, resolver->pending_requests().size()); | |
2211 | |
2212 // It should be trying to auto-detect first -- succeed the download. | |
2213 EXPECT_TRUE(fetcher->has_pending_request()); | |
2214 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url()); | |
2215 fetcher->NotifyFetchCompletion(OK, kValidPacScript1); | |
2216 | |
2217 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1), | |
2218 resolver->pending_set_pac_script_request()->script_data()->utf16()); | |
2219 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
2220 | |
2221 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
2222 EXPECT_EQ(GURL("http://www.google.com"), | |
2223 resolver->pending_requests()[0]->url()); | |
2224 | |
2225 // Complete the pending request. | |
2226 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); | |
2227 resolver->pending_requests()[0]->CompleteNow(OK); | |
2228 | |
2229 // Verify that request ran as expected. | |
2230 EXPECT_EQ(OK, callback1.WaitForResult()); | |
2231 EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); | |
2232 | |
2233 // Start another request, it should pickup the bypass item. | |
2234 ProxyInfo info2; | |
2235 TestCompletionCallback callback2; | |
2236 rv = service.ResolveProxy(GURL("http://www.google.com"), net::LOAD_NORMAL, | |
2237 &info2, callback2.callback(), NULL, NULL, | |
2238 BoundNetLog()); | |
2239 EXPECT_EQ(ERR_IO_PENDING, rv); | |
2240 | |
2241 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
2242 EXPECT_EQ(GURL("http://www.google.com"), | |
2243 resolver->pending_requests()[0]->url()); | |
2244 | |
2245 // Complete the pending request. | |
2246 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80"); | |
2247 resolver->pending_requests()[0]->CompleteNow(OK); | |
2248 | |
2249 EXPECT_EQ(OK, callback2.WaitForResult()); | |
2250 EXPECT_EQ("request2:80", info2.proxy_server().ToURI()); | |
2251 } | |
2252 | |
2253 // Delete the ProxyService while InitProxyResolver has an outstanding | |
2254 // request to the script fetcher. When run under valgrind, should not | |
2255 // have any memory errors (used to be that the ProxyScriptFetcher was | |
2256 // being deleted prior to the InitProxyResolver). | |
2257 TEST_F(ProxyServiceTest, DeleteWhileInitProxyResolverHasOutstandingFetch) { | |
2258 ProxyConfig config = | |
2259 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")); | |
2260 | |
2261 MockProxyConfigService* config_service = new MockProxyConfigService(config); | |
2262 MockAsyncProxyResolverExpectsBytes* resolver = | |
2263 new MockAsyncProxyResolverExpectsBytes; | |
2264 ProxyService service(config_service, resolver, NULL); | |
2265 | |
2266 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; | |
2267 service.SetProxyScriptFetchers(fetcher, | |
2268 new DoNothingDhcpProxyScriptFetcher()); | |
2269 | |
2270 // Start 1 request. | |
2271 | |
2272 ProxyInfo info1; | |
2273 TestCompletionCallback callback1; | |
2274 int rv = service.ResolveProxy(GURL("http://www.google.com"), net::LOAD_NORMAL, | |
2275 &info1, callback1.callback(), NULL, NULL, | |
2276 BoundNetLog()); | |
2277 EXPECT_EQ(ERR_IO_PENDING, rv); | |
2278 | |
2279 // Check that nothing has been sent to the proxy resolver yet. | |
2280 ASSERT_EQ(0u, resolver->pending_requests().size()); | |
2281 | |
2282 // InitProxyResolver should have issued a request to the ProxyScriptFetcher | |
2283 // and be waiting on that to complete. | |
2284 EXPECT_TRUE(fetcher->has_pending_request()); | |
2285 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); | |
2286 } | |
2287 | |
2288 // Delete the ProxyService while InitProxyResolver has an outstanding | |
2289 // request to the proxy resolver. When run under valgrind, should not | |
2290 // have any memory errors (used to be that the ProxyResolver was | |
2291 // being deleted prior to the InitProxyResolver). | |
2292 TEST_F(ProxyServiceTest, DeleteWhileInitProxyResolverHasOutstandingSet) { | |
2293 MockProxyConfigService* config_service = | |
2294 new MockProxyConfigService("http://foopy/proxy.pac"); | |
2295 | |
2296 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; | |
2297 | |
2298 ProxyService service(config_service, resolver, NULL); | |
2299 | |
2300 GURL url("http://www.google.com/"); | |
2301 | |
2302 ProxyInfo info; | |
2303 TestCompletionCallback callback; | |
2304 int rv = service.ResolveProxy( | |
2305 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL, | |
2306 BoundNetLog()); | |
2307 EXPECT_EQ(ERR_IO_PENDING, rv); | |
2308 | |
2309 EXPECT_EQ(GURL("http://foopy/proxy.pac"), | |
2310 resolver->pending_set_pac_script_request()->script_data()->url()); | |
2311 } | |
2312 | |
2313 TEST_F(ProxyServiceTest, ResetProxyConfigService) { | |
2314 ProxyConfig config1; | |
2315 config1.proxy_rules().ParseFromString("foopy1:8080"); | |
2316 config1.set_auto_detect(false); | |
2317 ProxyService service( | |
2318 new MockProxyConfigService(config1), | |
2319 new MockAsyncProxyResolverExpectsBytes, NULL); | |
2320 | |
2321 ProxyInfo info; | |
2322 TestCompletionCallback callback1; | |
2323 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL, | |
2324 &info, callback1.callback(), NULL, NULL, | |
2325 BoundNetLog()); | |
2326 EXPECT_EQ(OK, rv); | |
2327 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); | |
2328 | |
2329 ProxyConfig config2; | |
2330 config2.proxy_rules().ParseFromString("foopy2:8080"); | |
2331 config2.set_auto_detect(false); | |
2332 service.ResetConfigService(new MockProxyConfigService(config2)); | |
2333 TestCompletionCallback callback2; | |
2334 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info, | |
2335 callback2.callback(), NULL, NULL, BoundNetLog()); | |
2336 EXPECT_EQ(OK, rv); | |
2337 EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI()); | |
2338 } | |
2339 | |
2340 // Test that when going from a configuration that required PAC to one | |
2341 // that does NOT, we unset the variable |should_use_proxy_resolver_|. | |
2342 TEST_F(ProxyServiceTest, UpdateConfigFromPACToDirect) { | |
2343 ProxyConfig config = ProxyConfig::CreateAutoDetect(); | |
2344 | |
2345 MockProxyConfigService* config_service = new MockProxyConfigService(config); | |
2346 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; | |
2347 ProxyService service(config_service, resolver, NULL); | |
2348 | |
2349 // Start 1 request. | |
2350 | |
2351 ProxyInfo info1; | |
2352 TestCompletionCallback callback1; | |
2353 int rv = service.ResolveProxy(GURL("http://www.google.com"), net::LOAD_NORMAL, | |
2354 &info1, callback1.callback(), NULL, NULL, | |
2355 BoundNetLog()); | |
2356 EXPECT_EQ(ERR_IO_PENDING, rv); | |
2357 | |
2358 // Check that nothing has been sent to the proxy resolver yet. | |
2359 ASSERT_EQ(0u, resolver->pending_requests().size()); | |
2360 | |
2361 // Successfully set the autodetect script. | |
2362 EXPECT_EQ(ProxyResolverScriptData::TYPE_AUTO_DETECT, | |
2363 resolver->pending_set_pac_script_request()->script_data()->type()); | |
2364 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
2365 | |
2366 // Complete the pending request. | |
2367 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
2368 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); | |
2369 resolver->pending_requests()[0]->CompleteNow(OK); | |
2370 | |
2371 // Verify that request ran as expected. | |
2372 EXPECT_EQ(OK, callback1.WaitForResult()); | |
2373 EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); | |
2374 | |
2375 // Force the ProxyService to pull down a new proxy configuration. | |
2376 // (Even though the configuration isn't old/bad). | |
2377 // | |
2378 // This new configuration no longer has auto_detect set, so | |
2379 // requests should complete synchronously now as direct-connect. | |
2380 config_service->SetConfig(ProxyConfig::CreateDirect()); | |
2381 | |
2382 // Start another request -- the effective configuration has changed. | |
2383 ProxyInfo info2; | |
2384 TestCompletionCallback callback2; | |
2385 rv = service.ResolveProxy(GURL("http://www.google.com"), net::LOAD_NORMAL, | |
2386 &info2, callback2.callback(), NULL, NULL, | |
2387 BoundNetLog()); | |
2388 EXPECT_EQ(OK, rv); | |
2389 | |
2390 EXPECT_TRUE(info2.is_direct()); | |
2391 } | |
2392 | |
2393 TEST_F(ProxyServiceTest, NetworkChangeTriggersPacRefetch) { | |
2394 MockProxyConfigService* config_service = | |
2395 new MockProxyConfigService("http://foopy/proxy.pac"); | |
2396 | |
2397 MockAsyncProxyResolverExpectsBytes* resolver = | |
2398 new MockAsyncProxyResolverExpectsBytes; | |
2399 | |
2400 CapturingNetLog log; | |
2401 | |
2402 ProxyService service(config_service, resolver, &log); | |
2403 | |
2404 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; | |
2405 service.SetProxyScriptFetchers(fetcher, | |
2406 new DoNothingDhcpProxyScriptFetcher()); | |
2407 | |
2408 // Disable the "wait after IP address changes" hack, so this unit-test can | |
2409 // complete quickly. | |
2410 service.set_stall_proxy_auto_config_delay(base::TimeDelta()); | |
2411 | |
2412 // Start 1 request. | |
2413 | |
2414 ProxyInfo info1; | |
2415 TestCompletionCallback callback1; | |
2416 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL, | |
2417 &info1, callback1.callback(), NULL, NULL, | |
2418 BoundNetLog()); | |
2419 EXPECT_EQ(ERR_IO_PENDING, rv); | |
2420 | |
2421 // The first request should have triggered initial download of PAC script. | |
2422 EXPECT_TRUE(fetcher->has_pending_request()); | |
2423 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); | |
2424 | |
2425 // Nothing has been sent to the resolver yet. | |
2426 EXPECT_TRUE(resolver->pending_requests().empty()); | |
2427 | |
2428 // At this point the ProxyService should be waiting for the | |
2429 // ProxyScriptFetcher to invoke its completion callback, notifying it of | |
2430 // PAC script download completion. | |
2431 fetcher->NotifyFetchCompletion(OK, kValidPacScript1); | |
2432 | |
2433 // Now that the PAC script is downloaded, the request will have been sent to | |
2434 // the proxy resolver. | |
2435 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1), | |
2436 resolver->pending_set_pac_script_request()->script_data()->utf16()); | |
2437 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
2438 | |
2439 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
2440 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); | |
2441 | |
2442 // Complete the pending request. | |
2443 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); | |
2444 resolver->pending_requests()[0]->CompleteNow(OK); | |
2445 | |
2446 // Wait for completion callback, and verify that the request ran as expected. | |
2447 EXPECT_EQ(OK, callback1.WaitForResult()); | |
2448 EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); | |
2449 | |
2450 // Now simluate a change in the network. The ProxyConfigService is still | |
2451 // going to return the same PAC URL as before, but this URL needs to be | |
2452 // refetched on the new network. | |
2453 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); | |
2454 base::MessageLoop::current()->RunUntilIdle(); // Notification happens async. | |
2455 | |
2456 // Start a second request. | |
2457 ProxyInfo info2; | |
2458 TestCompletionCallback callback2; | |
2459 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2, | |
2460 callback2.callback(), NULL, NULL, BoundNetLog()); | |
2461 EXPECT_EQ(ERR_IO_PENDING, rv); | |
2462 | |
2463 // This second request should have triggered the re-download of the PAC | |
2464 // script (since we marked the network as having changed). | |
2465 EXPECT_TRUE(fetcher->has_pending_request()); | |
2466 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); | |
2467 | |
2468 // Nothing has been sent to the resolver yet. | |
2469 EXPECT_TRUE(resolver->pending_requests().empty()); | |
2470 | |
2471 // Simulate the PAC script fetch as having completed (this time with | |
2472 // different data). | |
2473 fetcher->NotifyFetchCompletion(OK, kValidPacScript2); | |
2474 | |
2475 // Now that the PAC script is downloaded, the second request will have been | |
2476 // sent to the proxy resolver. | |
2477 EXPECT_EQ(ASCIIToUTF16(kValidPacScript2), | |
2478 resolver->pending_set_pac_script_request()->script_data()->utf16()); | |
2479 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
2480 | |
2481 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
2482 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[0]->url()); | |
2483 | |
2484 // Complete the pending second request. | |
2485 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80"); | |
2486 resolver->pending_requests()[0]->CompleteNow(OK); | |
2487 | |
2488 // Wait for completion callback, and verify that the request ran as expected. | |
2489 EXPECT_EQ(OK, callback2.WaitForResult()); | |
2490 EXPECT_EQ("request2:80", info2.proxy_server().ToURI()); | |
2491 | |
2492 // Check that the expected events were output to the log stream. In particular | |
2493 // PROXY_CONFIG_CHANGED should have only been emitted once (for the initial | |
2494 // setup), and NOT a second time when the IP address changed. | |
2495 CapturingNetLog::CapturedEntryList entries; | |
2496 log.GetEntries(&entries); | |
2497 | |
2498 EXPECT_TRUE(LogContainsEntryWithType(entries, 0, | |
2499 NetLog::TYPE_PROXY_CONFIG_CHANGED)); | |
2500 ASSERT_EQ(9u, entries.size()); | |
2501 for (size_t i = 1; i < entries.size(); ++i) | |
2502 EXPECT_NE(NetLog::TYPE_PROXY_CONFIG_CHANGED, entries[i].type); | |
2503 } | |
2504 | |
2505 // This test verifies that the PAC script specified by the settings is | |
2506 // periodically polled for changes. Specifically, if the initial fetch fails due | |
2507 // to a network error, we will eventually re-configure the service to use the | |
2508 // script once it becomes available. | |
2509 TEST_F(ProxyServiceTest, PACScriptRefetchAfterFailure) { | |
2510 // Change the retry policy to wait a mere 1 ms before retrying, so the test | |
2511 // runs quickly. | |
2512 ImmediatePollPolicy poll_policy; | |
2513 ProxyService::set_pac_script_poll_policy(&poll_policy); | |
2514 | |
2515 MockProxyConfigService* config_service = | |
2516 new MockProxyConfigService("http://foopy/proxy.pac"); | |
2517 | |
2518 MockAsyncProxyResolverExpectsBytes* resolver = | |
2519 new MockAsyncProxyResolverExpectsBytes; | |
2520 | |
2521 ProxyService service(config_service, resolver, NULL); | |
2522 | |
2523 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; | |
2524 service.SetProxyScriptFetchers(fetcher, | |
2525 new DoNothingDhcpProxyScriptFetcher()); | |
2526 | |
2527 // Start 1 request. | |
2528 | |
2529 ProxyInfo info1; | |
2530 TestCompletionCallback callback1; | |
2531 int rv = service.ResolveProxy( | |
2532 GURL("http://request1"), net::LOAD_NORMAL, &info1, callback1.callback(), | |
2533 NULL, NULL, BoundNetLog()); | |
2534 EXPECT_EQ(ERR_IO_PENDING, rv); | |
2535 | |
2536 // The first request should have triggered initial download of PAC script. | |
2537 EXPECT_TRUE(fetcher->has_pending_request()); | |
2538 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); | |
2539 | |
2540 // Nothing has been sent to the resolver yet. | |
2541 EXPECT_TRUE(resolver->pending_requests().empty()); | |
2542 | |
2543 // At this point the ProxyService should be waiting for the | |
2544 // ProxyScriptFetcher to invoke its completion callback, notifying it of | |
2545 // PAC script download completion. | |
2546 // | |
2547 // We simulate a failed download attempt, the proxy service should now | |
2548 // fall-back to DIRECT connections. | |
2549 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string()); | |
2550 | |
2551 ASSERT_TRUE(resolver->pending_requests().empty()); | |
2552 | |
2553 // Wait for completion callback, and verify it used DIRECT. | |
2554 EXPECT_EQ(OK, callback1.WaitForResult()); | |
2555 EXPECT_TRUE(info1.is_direct()); | |
2556 | |
2557 // At this point we have initialized the proxy service using a PAC script, | |
2558 // however it failed and fell-back to DIRECT. | |
2559 // | |
2560 // A background task to periodically re-check the PAC script for validity will | |
2561 // have been started. We will now wait for the next download attempt to start. | |
2562 // | |
2563 // Note that we shouldn't have to wait long here, since our test enables a | |
2564 // special unit-test mode. | |
2565 fetcher->WaitUntilFetch(); | |
2566 | |
2567 ASSERT_TRUE(resolver->pending_requests().empty()); | |
2568 | |
2569 // Make sure that our background checker is trying to download the expected | |
2570 // PAC script (same one as before). This time we will simulate a successful | |
2571 // download of the script. | |
2572 EXPECT_TRUE(fetcher->has_pending_request()); | |
2573 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); | |
2574 fetcher->NotifyFetchCompletion(OK, kValidPacScript1); | |
2575 | |
2576 base::MessageLoop::current()->RunUntilIdle(); | |
2577 | |
2578 // Now that the PAC script is downloaded, it should be used to initialize the | |
2579 // ProxyResolver. Simulate a successful parse. | |
2580 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1), | |
2581 resolver->pending_set_pac_script_request()->script_data()->utf16()); | |
2582 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
2583 | |
2584 // At this point the ProxyService should have re-configured itself to use the | |
2585 // PAC script (thereby recovering from the initial fetch failure). We will | |
2586 // verify that the next Resolve request uses the resolver rather than | |
2587 // DIRECT. | |
2588 | |
2589 // Start a second request. | |
2590 ProxyInfo info2; | |
2591 TestCompletionCallback callback2; | |
2592 rv = service.ResolveProxy( | |
2593 GURL("http://request2"), net::LOAD_NORMAL, &info2, callback2.callback(), | |
2594 NULL, NULL, BoundNetLog()); | |
2595 EXPECT_EQ(ERR_IO_PENDING, rv); | |
2596 | |
2597 // Check that it was sent to the resolver. | |
2598 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
2599 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[0]->url()); | |
2600 | |
2601 // Complete the pending second request. | |
2602 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80"); | |
2603 resolver->pending_requests()[0]->CompleteNow(OK); | |
2604 | |
2605 // Wait for completion callback, and verify that the request ran as expected. | |
2606 EXPECT_EQ(OK, callback2.WaitForResult()); | |
2607 EXPECT_EQ("request2:80", info2.proxy_server().ToURI()); | |
2608 } | |
2609 | |
2610 // This test verifies that the PAC script specified by the settings is | |
2611 // periodically polled for changes. Specifically, if the initial fetch succeeds, | |
2612 // however at a later time its *contents* change, we will eventually | |
2613 // re-configure the service to use the new script. | |
2614 TEST_F(ProxyServiceTest, PACScriptRefetchAfterContentChange) { | |
2615 // Change the retry policy to wait a mere 1 ms before retrying, so the test | |
2616 // runs quickly. | |
2617 ImmediatePollPolicy poll_policy; | |
2618 ProxyService::set_pac_script_poll_policy(&poll_policy); | |
2619 | |
2620 MockProxyConfigService* config_service = | |
2621 new MockProxyConfigService("http://foopy/proxy.pac"); | |
2622 | |
2623 MockAsyncProxyResolverExpectsBytes* resolver = | |
2624 new MockAsyncProxyResolverExpectsBytes; | |
2625 | |
2626 ProxyService service(config_service, resolver, NULL); | |
2627 | |
2628 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; | |
2629 service.SetProxyScriptFetchers(fetcher, | |
2630 new DoNothingDhcpProxyScriptFetcher()); | |
2631 | |
2632 // Start 1 request. | |
2633 | |
2634 ProxyInfo info1; | |
2635 TestCompletionCallback callback1; | |
2636 int rv = service.ResolveProxy( | |
2637 GURL("http://request1"), net::LOAD_NORMAL, &info1, callback1.callback(), | |
2638 NULL, NULL, BoundNetLog()); | |
2639 EXPECT_EQ(ERR_IO_PENDING, rv); | |
2640 | |
2641 // The first request should have triggered initial download of PAC script. | |
2642 EXPECT_TRUE(fetcher->has_pending_request()); | |
2643 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); | |
2644 | |
2645 // Nothing has been sent to the resolver yet. | |
2646 EXPECT_TRUE(resolver->pending_requests().empty()); | |
2647 | |
2648 // At this point the ProxyService should be waiting for the | |
2649 // ProxyScriptFetcher to invoke its completion callback, notifying it of | |
2650 // PAC script download completion. | |
2651 fetcher->NotifyFetchCompletion(OK, kValidPacScript1); | |
2652 | |
2653 // Now that the PAC script is downloaded, the request will have been sent to | |
2654 // the proxy resolver. | |
2655 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1), | |
2656 resolver->pending_set_pac_script_request()->script_data()->utf16()); | |
2657 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
2658 | |
2659 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
2660 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); | |
2661 | |
2662 // Complete the pending request. | |
2663 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); | |
2664 resolver->pending_requests()[0]->CompleteNow(OK); | |
2665 | |
2666 // Wait for completion callback, and verify that the request ran as expected. | |
2667 EXPECT_EQ(OK, callback1.WaitForResult()); | |
2668 EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); | |
2669 | |
2670 // At this point we have initialized the proxy service using a PAC script. | |
2671 // | |
2672 // A background task to periodically re-check the PAC script for validity will | |
2673 // have been started. We will now wait for the next download attempt to start. | |
2674 // | |
2675 // Note that we shouldn't have to wait long here, since our test enables a | |
2676 // special unit-test mode. | |
2677 fetcher->WaitUntilFetch(); | |
2678 | |
2679 ASSERT_TRUE(resolver->pending_requests().empty()); | |
2680 | |
2681 // Make sure that our background checker is trying to download the expected | |
2682 // PAC script (same one as before). This time we will simulate a successful | |
2683 // download of a DIFFERENT script. | |
2684 EXPECT_TRUE(fetcher->has_pending_request()); | |
2685 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); | |
2686 fetcher->NotifyFetchCompletion(OK, kValidPacScript2); | |
2687 | |
2688 base::MessageLoop::current()->RunUntilIdle(); | |
2689 | |
2690 // Now that the PAC script is downloaded, it should be used to initialize the | |
2691 // ProxyResolver. Simulate a successful parse. | |
2692 EXPECT_EQ(ASCIIToUTF16(kValidPacScript2), | |
2693 resolver->pending_set_pac_script_request()->script_data()->utf16()); | |
2694 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
2695 | |
2696 // At this point the ProxyService should have re-configured itself to use the | |
2697 // new PAC script. | |
2698 | |
2699 // Start a second request. | |
2700 ProxyInfo info2; | |
2701 TestCompletionCallback callback2; | |
2702 rv = service.ResolveProxy( | |
2703 GURL("http://request2"), net::LOAD_NORMAL, &info2, callback2.callback(), | |
2704 NULL, NULL, BoundNetLog()); | |
2705 EXPECT_EQ(ERR_IO_PENDING, rv); | |
2706 | |
2707 // Check that it was sent to the resolver. | |
2708 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
2709 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[0]->url()); | |
2710 | |
2711 // Complete the pending second request. | |
2712 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80"); | |
2713 resolver->pending_requests()[0]->CompleteNow(OK); | |
2714 | |
2715 // Wait for completion callback, and verify that the request ran as expected. | |
2716 EXPECT_EQ(OK, callback2.WaitForResult()); | |
2717 EXPECT_EQ("request2:80", info2.proxy_server().ToURI()); | |
2718 } | |
2719 | |
2720 // This test verifies that the PAC script specified by the settings is | |
2721 // periodically polled for changes. Specifically, if the initial fetch succeeds | |
2722 // and so does the next poll, however the contents of the downloaded script | |
2723 // have NOT changed, then we do not bother to re-initialize the proxy resolver. | |
2724 TEST_F(ProxyServiceTest, PACScriptRefetchAfterContentUnchanged) { | |
2725 // Change the retry policy to wait a mere 1 ms before retrying, so the test | |
2726 // runs quickly. | |
2727 ImmediatePollPolicy poll_policy; | |
2728 ProxyService::set_pac_script_poll_policy(&poll_policy); | |
2729 | |
2730 MockProxyConfigService* config_service = | |
2731 new MockProxyConfigService("http://foopy/proxy.pac"); | |
2732 | |
2733 MockAsyncProxyResolverExpectsBytes* resolver = | |
2734 new MockAsyncProxyResolverExpectsBytes; | |
2735 | |
2736 ProxyService service(config_service, resolver, NULL); | |
2737 | |
2738 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; | |
2739 service.SetProxyScriptFetchers(fetcher, | |
2740 new DoNothingDhcpProxyScriptFetcher()); | |
2741 | |
2742 // Start 1 request. | |
2743 | |
2744 ProxyInfo info1; | |
2745 TestCompletionCallback callback1; | |
2746 int rv = service.ResolveProxy( | |
2747 GURL("http://request1"), net::LOAD_NORMAL, &info1, callback1.callback(), | |
2748 NULL, NULL, BoundNetLog()); | |
2749 EXPECT_EQ(ERR_IO_PENDING, rv); | |
2750 | |
2751 // The first request should have triggered initial download of PAC script. | |
2752 EXPECT_TRUE(fetcher->has_pending_request()); | |
2753 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); | |
2754 | |
2755 // Nothing has been sent to the resolver yet. | |
2756 EXPECT_TRUE(resolver->pending_requests().empty()); | |
2757 | |
2758 // At this point the ProxyService should be waiting for the | |
2759 // ProxyScriptFetcher to invoke its completion callback, notifying it of | |
2760 // PAC script download completion. | |
2761 fetcher->NotifyFetchCompletion(OK, kValidPacScript1); | |
2762 | |
2763 // Now that the PAC script is downloaded, the request will have been sent to | |
2764 // the proxy resolver. | |
2765 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1), | |
2766 resolver->pending_set_pac_script_request()->script_data()->utf16()); | |
2767 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
2768 | |
2769 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
2770 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); | |
2771 | |
2772 // Complete the pending request. | |
2773 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); | |
2774 resolver->pending_requests()[0]->CompleteNow(OK); | |
2775 | |
2776 // Wait for completion callback, and verify that the request ran as expected. | |
2777 EXPECT_EQ(OK, callback1.WaitForResult()); | |
2778 EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); | |
2779 | |
2780 // At this point we have initialized the proxy service using a PAC script. | |
2781 // | |
2782 // A background task to periodically re-check the PAC script for validity will | |
2783 // have been started. We will now wait for the next download attempt to start. | |
2784 // | |
2785 // Note that we shouldn't have to wait long here, since our test enables a | |
2786 // special unit-test mode. | |
2787 fetcher->WaitUntilFetch(); | |
2788 | |
2789 ASSERT_TRUE(resolver->pending_requests().empty()); | |
2790 | |
2791 // Make sure that our background checker is trying to download the expected | |
2792 // PAC script (same one as before). We will simulate the same response as | |
2793 // last time (i.e. the script is unchanged). | |
2794 EXPECT_TRUE(fetcher->has_pending_request()); | |
2795 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); | |
2796 fetcher->NotifyFetchCompletion(OK, kValidPacScript1); | |
2797 | |
2798 base::MessageLoop::current()->RunUntilIdle(); | |
2799 | |
2800 ASSERT_FALSE(resolver->has_pending_set_pac_script_request()); | |
2801 | |
2802 // At this point the ProxyService is still running the same PAC script as | |
2803 // before. | |
2804 | |
2805 // Start a second request. | |
2806 ProxyInfo info2; | |
2807 TestCompletionCallback callback2; | |
2808 rv = service.ResolveProxy( | |
2809 GURL("http://request2"), net::LOAD_NORMAL, &info2, callback2.callback(), | |
2810 NULL, NULL, BoundNetLog()); | |
2811 EXPECT_EQ(ERR_IO_PENDING, rv); | |
2812 | |
2813 // Check that it was sent to the resolver. | |
2814 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
2815 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[0]->url()); | |
2816 | |
2817 // Complete the pending second request. | |
2818 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80"); | |
2819 resolver->pending_requests()[0]->CompleteNow(OK); | |
2820 | |
2821 // Wait for completion callback, and verify that the request ran as expected. | |
2822 EXPECT_EQ(OK, callback2.WaitForResult()); | |
2823 EXPECT_EQ("request2:80", info2.proxy_server().ToURI()); | |
2824 } | |
2825 | |
2826 // This test verifies that the PAC script specified by the settings is | |
2827 // periodically polled for changes. Specifically, if the initial fetch succeeds, | |
2828 // however at a later time it starts to fail, we should re-configure the | |
2829 // ProxyService to stop using that PAC script. | |
2830 TEST_F(ProxyServiceTest, PACScriptRefetchAfterSuccess) { | |
2831 // Change the retry policy to wait a mere 1 ms before retrying, so the test | |
2832 // runs quickly. | |
2833 ImmediatePollPolicy poll_policy; | |
2834 ProxyService::set_pac_script_poll_policy(&poll_policy); | |
2835 | |
2836 MockProxyConfigService* config_service = | |
2837 new MockProxyConfigService("http://foopy/proxy.pac"); | |
2838 | |
2839 MockAsyncProxyResolverExpectsBytes* resolver = | |
2840 new MockAsyncProxyResolverExpectsBytes; | |
2841 | |
2842 ProxyService service(config_service, resolver, NULL); | |
2843 | |
2844 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; | |
2845 service.SetProxyScriptFetchers(fetcher, | |
2846 new DoNothingDhcpProxyScriptFetcher()); | |
2847 | |
2848 // Start 1 request. | |
2849 | |
2850 ProxyInfo info1; | |
2851 TestCompletionCallback callback1; | |
2852 int rv = service.ResolveProxy( | |
2853 GURL("http://request1"), net::LOAD_NORMAL, &info1, callback1.callback(), | |
2854 NULL, NULL, BoundNetLog()); | |
2855 EXPECT_EQ(ERR_IO_PENDING, rv); | |
2856 | |
2857 // The first request should have triggered initial download of PAC script. | |
2858 EXPECT_TRUE(fetcher->has_pending_request()); | |
2859 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); | |
2860 | |
2861 // Nothing has been sent to the resolver yet. | |
2862 EXPECT_TRUE(resolver->pending_requests().empty()); | |
2863 | |
2864 // At this point the ProxyService should be waiting for the | |
2865 // ProxyScriptFetcher to invoke its completion callback, notifying it of | |
2866 // PAC script download completion. | |
2867 fetcher->NotifyFetchCompletion(OK, kValidPacScript1); | |
2868 | |
2869 // Now that the PAC script is downloaded, the request will have been sent to | |
2870 // the proxy resolver. | |
2871 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1), | |
2872 resolver->pending_set_pac_script_request()->script_data()->utf16()); | |
2873 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
2874 | |
2875 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
2876 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); | |
2877 | |
2878 // Complete the pending request. | |
2879 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); | |
2880 resolver->pending_requests()[0]->CompleteNow(OK); | |
2881 | |
2882 // Wait for completion callback, and verify that the request ran as expected. | |
2883 EXPECT_EQ(OK, callback1.WaitForResult()); | |
2884 EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); | |
2885 | |
2886 // At this point we have initialized the proxy service using a PAC script. | |
2887 // | |
2888 // A background task to periodically re-check the PAC script for validity will | |
2889 // have been started. We will now wait for the next download attempt to start. | |
2890 // | |
2891 // Note that we shouldn't have to wait long here, since our test enables a | |
2892 // special unit-test mode. | |
2893 fetcher->WaitUntilFetch(); | |
2894 | |
2895 ASSERT_TRUE(resolver->pending_requests().empty()); | |
2896 | |
2897 // Make sure that our background checker is trying to download the expected | |
2898 // PAC script (same one as before). This time we will simulate a failure | |
2899 // to download the script. | |
2900 EXPECT_TRUE(fetcher->has_pending_request()); | |
2901 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); | |
2902 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string()); | |
2903 | |
2904 base::MessageLoop::current()->RunUntilIdle(); | |
2905 | |
2906 // At this point the ProxyService should have re-configured itself to use | |
2907 // DIRECT connections rather than the given proxy resolver. | |
2908 | |
2909 // Start a second request. | |
2910 ProxyInfo info2; | |
2911 TestCompletionCallback callback2; | |
2912 rv = service.ResolveProxy( | |
2913 GURL("http://request2"), net::LOAD_NORMAL, &info2, callback2.callback(), | |
2914 NULL, NULL, BoundNetLog()); | |
2915 EXPECT_EQ(OK, rv); | |
2916 EXPECT_TRUE(info2.is_direct()); | |
2917 } | |
2918 | |
2919 // Tests that the code which decides at what times to poll the PAC | |
2920 // script follows the expected policy. | |
2921 TEST_F(ProxyServiceTest, PACScriptPollingPolicy) { | |
2922 // Retrieve the internal polling policy implementation used by ProxyService. | |
2923 scoped_ptr<ProxyService::PacPollPolicy> policy = | |
2924 ProxyService::CreateDefaultPacPollPolicy(); | |
2925 | |
2926 int error; | |
2927 ProxyService::PacPollPolicy::Mode mode; | |
2928 const base::TimeDelta initial_delay = base::TimeDelta::FromMilliseconds(-1); | |
2929 base::TimeDelta delay = initial_delay; | |
2930 | |
2931 // -------------------------------------------------- | |
2932 // Test the poll sequence in response to a failure. | |
2933 // -------------------------------------------------- | |
2934 error = ERR_NAME_NOT_RESOLVED; | |
2935 | |
2936 // Poll #0 | |
2937 mode = policy->GetNextDelay(error, initial_delay, &delay); | |
2938 EXPECT_EQ(8, delay.InSeconds()); | |
2939 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_USE_TIMER, mode); | |
2940 | |
2941 // Poll #1 | |
2942 mode = policy->GetNextDelay(error, delay, &delay); | |
2943 EXPECT_EQ(32, delay.InSeconds()); | |
2944 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode); | |
2945 | |
2946 // Poll #2 | |
2947 mode = policy->GetNextDelay(error, delay, &delay); | |
2948 EXPECT_EQ(120, delay.InSeconds()); | |
2949 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode); | |
2950 | |
2951 // Poll #3 | |
2952 mode = policy->GetNextDelay(error, delay, &delay); | |
2953 EXPECT_EQ(14400, delay.InSeconds()); | |
2954 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode); | |
2955 | |
2956 // Poll #4 | |
2957 mode = policy->GetNextDelay(error, delay, &delay); | |
2958 EXPECT_EQ(14400, delay.InSeconds()); | |
2959 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode); | |
2960 | |
2961 // -------------------------------------------------- | |
2962 // Test the poll sequence in response to a success. | |
2963 // -------------------------------------------------- | |
2964 error = OK; | |
2965 | |
2966 // Poll #0 | |
2967 mode = policy->GetNextDelay(error, initial_delay, &delay); | |
2968 EXPECT_EQ(43200, delay.InSeconds()); | |
2969 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode); | |
2970 | |
2971 // Poll #1 | |
2972 mode = policy->GetNextDelay(error, delay, &delay); | |
2973 EXPECT_EQ(43200, delay.InSeconds()); | |
2974 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode); | |
2975 | |
2976 // Poll #2 | |
2977 mode = policy->GetNextDelay(error, delay, &delay); | |
2978 EXPECT_EQ(43200, delay.InSeconds()); | |
2979 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode); | |
2980 } | |
2981 | |
2982 // This tests the polling of the PAC script. Specifically, it tests that | |
2983 // polling occurs in response to user activity. | |
2984 TEST_F(ProxyServiceTest, PACScriptRefetchAfterActivity) { | |
2985 ImmediateAfterActivityPollPolicy poll_policy; | |
2986 ProxyService::set_pac_script_poll_policy(&poll_policy); | |
2987 | |
2988 MockProxyConfigService* config_service = | |
2989 new MockProxyConfigService("http://foopy/proxy.pac"); | |
2990 | |
2991 MockAsyncProxyResolverExpectsBytes* resolver = | |
2992 new MockAsyncProxyResolverExpectsBytes; | |
2993 | |
2994 ProxyService service(config_service, resolver, NULL); | |
2995 | |
2996 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; | |
2997 service.SetProxyScriptFetchers(fetcher, | |
2998 new DoNothingDhcpProxyScriptFetcher()); | |
2999 | |
3000 // Start 1 request. | |
3001 | |
3002 ProxyInfo info1; | |
3003 TestCompletionCallback callback1; | |
3004 int rv = service.ResolveProxy( | |
3005 GURL("http://request1"), net::LOAD_NORMAL, &info1, callback1.callback(), | |
3006 NULL, NULL, BoundNetLog()); | |
3007 EXPECT_EQ(ERR_IO_PENDING, rv); | |
3008 | |
3009 // The first request should have triggered initial download of PAC script. | |
3010 EXPECT_TRUE(fetcher->has_pending_request()); | |
3011 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); | |
3012 | |
3013 // Nothing has been sent to the resolver yet. | |
3014 EXPECT_TRUE(resolver->pending_requests().empty()); | |
3015 | |
3016 // At this point the ProxyService should be waiting for the | |
3017 // ProxyScriptFetcher to invoke its completion callback, notifying it of | |
3018 // PAC script download completion. | |
3019 fetcher->NotifyFetchCompletion(OK, kValidPacScript1); | |
3020 | |
3021 // Now that the PAC script is downloaded, the request will have been sent to | |
3022 // the proxy resolver. | |
3023 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1), | |
3024 resolver->pending_set_pac_script_request()->script_data()->utf16()); | |
3025 resolver->pending_set_pac_script_request()->CompleteNow(OK); | |
3026 | |
3027 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
3028 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); | |
3029 | |
3030 // Complete the pending request. | |
3031 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); | |
3032 resolver->pending_requests()[0]->CompleteNow(OK); | |
3033 | |
3034 // Wait for completion callback, and verify that the request ran as expected. | |
3035 EXPECT_EQ(OK, callback1.WaitForResult()); | |
3036 EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); | |
3037 | |
3038 // At this point we have initialized the proxy service using a PAC script. | |
3039 // Our PAC poller is set to update ONLY in response to network activity, | |
3040 // (i.e. another call to ResolveProxy()). | |
3041 | |
3042 ASSERT_FALSE(fetcher->has_pending_request()); | |
3043 ASSERT_TRUE(resolver->pending_requests().empty()); | |
3044 | |
3045 // Start a second request. | |
3046 ProxyInfo info2; | |
3047 TestCompletionCallback callback2; | |
3048 rv = service.ResolveProxy( | |
3049 GURL("http://request2"), net::LOAD_NORMAL, &info2, callback2.callback(), | |
3050 NULL, NULL, BoundNetLog()); | |
3051 EXPECT_EQ(ERR_IO_PENDING, rv); | |
3052 | |
3053 // This request should have sent work to the resolver; complete it. | |
3054 ASSERT_EQ(1u, resolver->pending_requests().size()); | |
3055 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[0]->url()); | |
3056 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80"); | |
3057 resolver->pending_requests()[0]->CompleteNow(OK); | |
3058 | |
3059 EXPECT_EQ(OK, callback2.WaitForResult()); | |
3060 EXPECT_EQ("request2:80", info2.proxy_server().ToURI()); | |
3061 | |
3062 // In response to getting that resolve request, the poller should have | |
3063 // started the next poll, and made it as far as to request the download. | |
3064 | |
3065 EXPECT_TRUE(fetcher->has_pending_request()); | |
3066 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); | |
3067 | |
3068 // This time we will fail the download, to simulate a PAC script change. | |
3069 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string()); | |
3070 | |
3071 // Drain the message loop, so ProxyService is notified of the change | |
3072 // and has a chance to re-configure itself. | |
3073 base::MessageLoop::current()->RunUntilIdle(); | |
3074 | |
3075 // Start a third request -- this time we expect to get a direct connection | |
3076 // since the PAC script poller experienced a failure. | |
3077 ProxyInfo info3; | |
3078 TestCompletionCallback callback3; | |
3079 rv = service.ResolveProxy( | |
3080 GURL("http://request3"), net::LOAD_NORMAL, &info3, callback3.callback(), | |
3081 NULL, NULL, BoundNetLog()); | |
3082 EXPECT_EQ(OK, rv); | |
3083 EXPECT_TRUE(info3.is_direct()); | |
3084 } | |
3085 | |
3086 // Test that the synchronous resolution fails when a PAC script is active. | |
3087 TEST_F(ProxyServiceTest, SynchronousWithPAC) { | |
3088 MockProxyConfigService* config_service = | |
3089 new MockProxyConfigService("http://foopy/proxy.pac"); | |
3090 | |
3091 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver(); | |
3092 | |
3093 ProxyService service(config_service, resolver, NULL); | |
3094 | |
3095 GURL url("http://www.google.com/"); | |
3096 | |
3097 ProxyInfo info; | |
3098 info.UseDirect(); | |
3099 CapturingBoundNetLog log; | |
3100 | |
3101 bool synchronous_success = service.TryResolveProxySynchronously( | |
3102 url, net::LOAD_NORMAL, &info, NULL, log.bound()); | |
3103 EXPECT_FALSE(synchronous_success); | |
3104 | |
3105 // No request should have been queued. | |
3106 EXPECT_EQ(0u, resolver->pending_requests().size()); | |
3107 | |
3108 // |info| should not have been modified. | |
3109 EXPECT_TRUE(info.is_direct()); | |
3110 } | |
3111 | |
3112 // Test that synchronous results are returned correctly if a fixed proxy | |
3113 // configuration is active. | |
3114 TEST_F(ProxyServiceTest, SynchronousWithFixedConfiguration) { | |
3115 ProxyConfig config; | |
3116 config.proxy_rules().ParseFromString("foopy1:8080"); | |
3117 config.set_auto_detect(false); | |
3118 | |
3119 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver(); | |
3120 | |
3121 ProxyService service(new MockProxyConfigService(config), resolver, NULL); | |
3122 | |
3123 GURL url("http://www.google.com/"); | |
3124 | |
3125 ProxyInfo info; | |
3126 CapturingBoundNetLog log; | |
3127 | |
3128 bool synchronous_success = service.TryResolveProxySynchronously( | |
3129 url, net::LOAD_NORMAL, &info, NULL, log.bound()); | |
3130 EXPECT_TRUE(synchronous_success); | |
3131 EXPECT_FALSE(info.is_direct()); | |
3132 EXPECT_EQ("foopy1", info.proxy_server().host_port_pair().host()); | |
3133 | |
3134 // No request should have been queued. | |
3135 EXPECT_EQ(0u, resolver->pending_requests().size()); | |
3136 } | |
3137 | |
3138 } // namespace net | |
OLD | NEW |