Make GetSecurityLevel available from the java ToolbarModel.
[chromium-blink-merge.git] / net / proxy / proxy_service_unittest.cc
blob12f9af21a1fd05c38c9f17254d57298e7387b54b
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.
5 #include "net/proxy/proxy_service.h"
7 #include <vector>
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.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"
28 using base::ASCIIToUTF16;
30 // TODO(eroman): Write a test which exercises
31 // ProxyService::SuspendAllPendingRequests().
32 namespace net {
33 namespace {
35 // This polling policy will decide to poll every 1 ms.
36 class ImmediatePollPolicy : public ProxyService::PacPollPolicy {
37 public:
38 ImmediatePollPolicy() {}
40 virtual Mode GetNextDelay(int error, base::TimeDelta current_delay,
41 base::TimeDelta* next_delay) const override {
42 *next_delay = base::TimeDelta::FromMilliseconds(1);
43 return MODE_USE_TIMER;
46 private:
47 DISALLOW_COPY_AND_ASSIGN(ImmediatePollPolicy);
50 // This polling policy chooses a fantastically large delay. In other words, it
51 // will never trigger a poll
52 class NeverPollPolicy : public ProxyService::PacPollPolicy {
53 public:
54 NeverPollPolicy() {}
56 virtual Mode GetNextDelay(int error, base::TimeDelta current_delay,
57 base::TimeDelta* next_delay) const override {
58 *next_delay = base::TimeDelta::FromDays(60);
59 return MODE_USE_TIMER;
62 private:
63 DISALLOW_COPY_AND_ASSIGN(NeverPollPolicy);
66 // This polling policy starts a poll immediately after network activity.
67 class ImmediateAfterActivityPollPolicy : public ProxyService::PacPollPolicy {
68 public:
69 ImmediateAfterActivityPollPolicy() {}
71 virtual Mode GetNextDelay(int error, base::TimeDelta current_delay,
72 base::TimeDelta* next_delay) const override {
73 *next_delay = base::TimeDelta();
74 return MODE_START_AFTER_ACTIVITY;
77 private:
78 DISALLOW_COPY_AND_ASSIGN(ImmediateAfterActivityPollPolicy);
81 // This test fixture is used to partially disable the background polling done by
82 // the ProxyService (which it uses to detect whenever its PAC script contents or
83 // WPAD results have changed).
85 // We disable the feature by setting the poll interval to something really
86 // large, so it will never actually be reached even on the slowest bots that run
87 // these tests.
89 // We disable the polling in order to avoid any timing dependencies in the
90 // tests. If the bot were to run the tests very slowly and we hadn't disabled
91 // polling, then it might start a background re-try in the middle of our test
92 // and confuse our expectations leading to flaky failures.
94 // The tests which verify the polling code re-enable the polling behavior but
95 // are careful to avoid timing problems.
96 class ProxyServiceTest : public testing::Test {
97 protected:
98 virtual void SetUp() override {
99 testing::Test::SetUp();
100 previous_policy_ =
101 ProxyService::set_pac_script_poll_policy(&never_poll_policy_);
104 virtual void TearDown() override {
105 // Restore the original policy.
106 ProxyService::set_pac_script_poll_policy(previous_policy_);
107 testing::Test::TearDown();
110 private:
111 NeverPollPolicy never_poll_policy_;
112 const ProxyService::PacPollPolicy* previous_policy_;
115 const char kValidPacScript1[] = "pac-script-v1-FindProxyForURL";
116 const char kValidPacScript2[] = "pac-script-v2-FindProxyForURL";
118 class MockProxyConfigService: public ProxyConfigService {
119 public:
120 explicit MockProxyConfigService(const ProxyConfig& config)
121 : availability_(CONFIG_VALID),
122 config_(config) {
125 explicit MockProxyConfigService(const std::string& pac_url)
126 : availability_(CONFIG_VALID),
127 config_(ProxyConfig::CreateFromCustomPacURL(GURL(pac_url))) {
130 virtual void AddObserver(Observer* observer) override {
131 observers_.AddObserver(observer);
134 virtual void RemoveObserver(Observer* observer) override {
135 observers_.RemoveObserver(observer);
138 virtual ConfigAvailability GetLatestProxyConfig(ProxyConfig* results)
139 override {
140 if (availability_ == CONFIG_VALID)
141 *results = config_;
142 return availability_;
145 void SetConfig(const ProxyConfig& config) {
146 availability_ = CONFIG_VALID;
147 config_ = config;
148 FOR_EACH_OBSERVER(Observer, observers_,
149 OnProxyConfigChanged(config_, availability_));
152 private:
153 ConfigAvailability availability_;
154 ProxyConfig config_;
155 ObserverList<Observer, true> observers_;
158 // A test network delegate that exercises the OnResolveProxy callback.
159 class TestResolveProxyNetworkDelegate : public NetworkDelegate {
160 public:
161 TestResolveProxyNetworkDelegate()
162 : on_resolve_proxy_called_(false),
163 add_proxy_(false),
164 remove_proxy_(false),
165 proxy_service_(NULL) {
168 virtual void OnResolveProxy(const GURL& url,
169 int load_flags,
170 const ProxyService& proxy_service,
171 ProxyInfo* result) override {
172 on_resolve_proxy_called_ = true;
173 proxy_service_ = &proxy_service;
174 DCHECK(!add_proxy_ || !remove_proxy_);
175 if (add_proxy_) {
176 result->UseNamedProxy("delegate_proxy.com");
177 } else if (remove_proxy_) {
178 result->UseDirect();
182 bool on_resolve_proxy_called() const {
183 return on_resolve_proxy_called_;
186 void set_add_proxy(bool add_proxy) {
187 add_proxy_ = add_proxy;
190 void set_remove_proxy(bool remove_proxy) {
191 remove_proxy_ = remove_proxy;
194 const ProxyService* proxy_service() const {
195 return proxy_service_;
198 private:
199 bool on_resolve_proxy_called_;
200 bool add_proxy_;
201 bool remove_proxy_;
202 const ProxyService* proxy_service_;
205 // A test network delegate that exercises the OnProxyFallback callback.
206 class TestProxyFallbackNetworkDelegate : public NetworkDelegate {
207 public:
208 TestProxyFallbackNetworkDelegate()
209 : on_proxy_fallback_called_(false),
210 proxy_fallback_net_error_(OK) {
213 virtual void OnProxyFallback(const ProxyServer& proxy_server,
214 int net_error) override {
215 proxy_server_ = proxy_server;
216 proxy_fallback_net_error_ = net_error;
217 on_proxy_fallback_called_ = true;
220 bool on_proxy_fallback_called() const {
221 return on_proxy_fallback_called_;
224 const ProxyServer& proxy_server() const {
225 return proxy_server_;
228 int proxy_fallback_net_error() const {
229 return proxy_fallback_net_error_;
232 private:
233 bool on_proxy_fallback_called_;
234 ProxyServer proxy_server_;
235 int proxy_fallback_net_error_;
238 } // namespace
240 TEST_F(ProxyServiceTest, Direct) {
241 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
242 ProxyService service(new MockProxyConfigService(
243 ProxyConfig::CreateDirect()), resolver, NULL);
245 GURL url("http://www.google.com/");
247 ProxyInfo info;
248 TestCompletionCallback callback;
249 CapturingBoundNetLog log;
250 int rv = service.ResolveProxy(
251 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL,
252 log.bound());
253 EXPECT_EQ(OK, rv);
254 EXPECT_TRUE(resolver->pending_requests().empty());
256 EXPECT_TRUE(info.is_direct());
257 EXPECT_TRUE(info.proxy_resolve_start_time().is_null());
258 EXPECT_TRUE(info.proxy_resolve_end_time().is_null());
260 // Check the NetLog was filled correctly.
261 CapturingNetLog::CapturedEntryList entries;
262 log.GetEntries(&entries);
264 EXPECT_EQ(3u, entries.size());
265 EXPECT_TRUE(LogContainsBeginEvent(
266 entries, 0, NetLog::TYPE_PROXY_SERVICE));
267 EXPECT_TRUE(LogContainsEvent(
268 entries, 1, NetLog::TYPE_PROXY_SERVICE_RESOLVED_PROXY_LIST,
269 NetLog::PHASE_NONE));
270 EXPECT_TRUE(LogContainsEndEvent(
271 entries, 2, NetLog::TYPE_PROXY_SERVICE));
274 TEST_F(ProxyServiceTest, OnResolveProxyCallbackAddProxy) {
275 ProxyConfig config;
276 config.proxy_rules().ParseFromString("foopy1:8080");
277 config.set_auto_detect(false);
278 config.proxy_rules().bypass_rules.ParseFromString("*.org");
280 ProxyService service(
281 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
283 GURL url("http://www.google.com/");
284 GURL bypass_url("http://internet.org");
286 ProxyInfo info;
287 TestCompletionCallback callback;
288 CapturingBoundNetLog log;
290 // First, warm up the ProxyService.
291 int rv = service.ResolveProxy(
292 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL,
293 log.bound());
294 EXPECT_EQ(OK, rv);
296 // Verify that network delegate is invoked.
297 TestResolveProxyNetworkDelegate delegate;
298 rv = service.ResolveProxy(
299 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, &delegate,
300 log.bound());
301 EXPECT_TRUE(delegate.on_resolve_proxy_called());
302 EXPECT_EQ(&service, delegate.proxy_service());
304 // Verify that the NetworkDelegate's behavior is stateless across
305 // invocations of ResolveProxy. Start by having the callback add a proxy
306 // and checking that subsequent requests are not affected.
307 delegate.set_add_proxy(true);
309 // Callback should interpose:
310 rv = service.ResolveProxy(
311 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, &delegate,
312 log.bound());
313 EXPECT_FALSE(info.is_direct());
314 EXPECT_EQ(info.proxy_server().host_port_pair().host(), "delegate_proxy.com");
315 delegate.set_add_proxy(false);
317 // Check non-bypassed URL:
318 rv = service.ResolveProxy(
319 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, &delegate,
320 log.bound());
321 EXPECT_FALSE(info.is_direct());
322 EXPECT_EQ(info.proxy_server().host_port_pair().host(), "foopy1");
324 // Check bypassed URL:
325 rv = service.ResolveProxy(
326 bypass_url, net::LOAD_NORMAL, &info, callback.callback(), NULL,
327 &delegate, log.bound());
328 EXPECT_TRUE(info.is_direct());
331 TEST_F(ProxyServiceTest, OnResolveProxyCallbackRemoveProxy) {
332 // Same as OnResolveProxyCallbackAddProxy, but verify that the
333 // NetworkDelegate's behavior is stateless across invocations after it
334 // *removes* a proxy.
335 ProxyConfig config;
336 config.proxy_rules().ParseFromString("foopy1:8080");
337 config.set_auto_detect(false);
338 config.proxy_rules().bypass_rules.ParseFromString("*.org");
340 ProxyService service(
341 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
343 GURL url("http://www.google.com/");
344 GURL bypass_url("http://internet.org");
346 ProxyInfo info;
347 TestCompletionCallback callback;
348 CapturingBoundNetLog log;
350 // First, warm up the ProxyService.
351 int rv = service.ResolveProxy(
352 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL,
353 log.bound());
354 EXPECT_EQ(OK, rv);
356 TestResolveProxyNetworkDelegate delegate;
357 delegate.set_remove_proxy(true);
359 // Callback should interpose:
360 rv = service.ResolveProxy(
361 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, &delegate,
362 log.bound());
363 EXPECT_TRUE(info.is_direct());
364 delegate.set_remove_proxy(false);
366 // Check non-bypassed URL:
367 rv = service.ResolveProxy(
368 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, &delegate,
369 log.bound());
370 EXPECT_FALSE(info.is_direct());
371 EXPECT_EQ(info.proxy_server().host_port_pair().host(), "foopy1");
373 // Check bypassed URL:
374 rv = service.ResolveProxy(
375 bypass_url, net::LOAD_NORMAL, &info, callback.callback(), NULL,
376 &delegate, log.bound());
377 EXPECT_TRUE(info.is_direct());
380 TEST_F(ProxyServiceTest, PAC) {
381 MockProxyConfigService* config_service =
382 new MockProxyConfigService("http://foopy/proxy.pac");
384 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
386 ProxyService service(config_service, resolver, NULL);
388 GURL url("http://www.google.com/");
390 ProxyInfo info;
391 TestCompletionCallback callback;
392 ProxyService::PacRequest* request;
393 CapturingBoundNetLog log;
395 int rv = service.ResolveProxy(
396 url, net::LOAD_NORMAL, &info, callback.callback(), &request, NULL,
397 log.bound());
398 EXPECT_EQ(ERR_IO_PENDING, rv);
400 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request));
402 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
403 resolver->pending_set_pac_script_request()->script_data()->url());
404 resolver->pending_set_pac_script_request()->CompleteNow(OK);
406 ASSERT_EQ(1u, resolver->pending_requests().size());
407 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
409 // Set the result in proxy resolver.
410 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy");
411 resolver->pending_requests()[0]->CompleteNow(OK);
413 EXPECT_EQ(OK, callback.WaitForResult());
414 EXPECT_FALSE(info.is_direct());
415 EXPECT_EQ("foopy:80", info.proxy_server().ToURI());
416 EXPECT_TRUE(info.did_use_pac_script());
418 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
419 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
420 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
422 // Check the NetLog was filled correctly.
423 CapturingNetLog::CapturedEntryList entries;
424 log.GetEntries(&entries);
426 EXPECT_EQ(5u, entries.size());
427 EXPECT_TRUE(LogContainsBeginEvent(
428 entries, 0, NetLog::TYPE_PROXY_SERVICE));
429 EXPECT_TRUE(LogContainsBeginEvent(
430 entries, 1, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
431 EXPECT_TRUE(LogContainsEndEvent(
432 entries, 2, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
433 EXPECT_TRUE(LogContainsEndEvent(
434 entries, 4, NetLog::TYPE_PROXY_SERVICE));
437 // Test that the proxy resolver does not see the URL's username/password
438 // or its reference section.
439 TEST_F(ProxyServiceTest, PAC_NoIdentityOrHash) {
440 MockProxyConfigService* config_service =
441 new MockProxyConfigService("http://foopy/proxy.pac");
443 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
445 ProxyService service(config_service, resolver, NULL);
447 GURL url("http://username:password@www.google.com/?ref#hash#hash");
449 ProxyInfo info;
450 TestCompletionCallback callback;
451 int rv = service.ResolveProxy(
452 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL,
453 BoundNetLog());
454 EXPECT_EQ(ERR_IO_PENDING, rv);
456 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
457 resolver->pending_set_pac_script_request()->script_data()->url());
458 resolver->pending_set_pac_script_request()->CompleteNow(OK);
460 ASSERT_EQ(1u, resolver->pending_requests().size());
461 // The URL should have been simplified, stripping the username/password/hash.
462 EXPECT_EQ(GURL("http://www.google.com/?ref"),
463 resolver->pending_requests()[0]->url());
465 // We end here without ever completing the request -- destruction of
466 // ProxyService will cancel the outstanding request.
469 TEST_F(ProxyServiceTest, PAC_FailoverWithoutDirect) {
470 MockProxyConfigService* config_service =
471 new MockProxyConfigService("http://foopy/proxy.pac");
472 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
474 ProxyService service(config_service, resolver, NULL);
476 GURL url("http://www.google.com/");
478 ProxyInfo info;
479 TestCompletionCallback callback1;
480 int rv = service.ResolveProxy(
481 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL,
482 BoundNetLog());
483 EXPECT_EQ(ERR_IO_PENDING, rv);
485 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
486 resolver->pending_set_pac_script_request()->script_data()->url());
487 resolver->pending_set_pac_script_request()->CompleteNow(OK);
489 ASSERT_EQ(1u, resolver->pending_requests().size());
490 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
492 // Set the result in proxy resolver.
493 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy:8080");
494 resolver->pending_requests()[0]->CompleteNow(OK);
496 EXPECT_EQ(OK, callback1.WaitForResult());
497 EXPECT_FALSE(info.is_direct());
498 EXPECT_EQ("foopy:8080", info.proxy_server().ToURI());
499 EXPECT_TRUE(info.did_use_pac_script());
501 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
502 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
503 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
505 // Now, imagine that connecting to foopy:8080 fails: there is nothing
506 // left to fallback to, since our proxy list was NOT terminated by
507 // DIRECT.
508 NetworkDelegate network_delegate;
509 TestCompletionCallback callback2;
510 ProxyServer expected_proxy_server = info.proxy_server();
511 rv = service.ReconsiderProxyAfterError(
512 url, net::LOAD_NORMAL, net::ERR_PROXY_CONNECTION_FAILED,
513 &info, callback2.callback(), NULL, &network_delegate, BoundNetLog());
514 // ReconsiderProxyAfterError returns error indicating nothing left.
515 EXPECT_EQ(ERR_FAILED, rv);
516 EXPECT_TRUE(info.is_empty());
519 // Test that if the execution of the PAC script fails (i.e. javascript runtime
520 // error), and the PAC settings are non-mandatory, that we fall-back to direct.
521 TEST_F(ProxyServiceTest, PAC_RuntimeError) {
522 MockProxyConfigService* config_service =
523 new MockProxyConfigService("http://foopy/proxy.pac");
524 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
526 ProxyService service(config_service, resolver, NULL);
528 GURL url("http://this-causes-js-error/");
530 ProxyInfo info;
531 TestCompletionCallback callback1;
532 int rv = service.ResolveProxy(
533 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL,
534 BoundNetLog());
535 EXPECT_EQ(ERR_IO_PENDING, rv);
537 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
538 resolver->pending_set_pac_script_request()->script_data()->url());
539 resolver->pending_set_pac_script_request()->CompleteNow(OK);
541 ASSERT_EQ(1u, resolver->pending_requests().size());
542 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
544 // Simulate a failure in the PAC executor.
545 resolver->pending_requests()[0]->CompleteNow(ERR_PAC_SCRIPT_FAILED);
547 EXPECT_EQ(OK, callback1.WaitForResult());
549 // Since the PAC script was non-mandatory, we should have fallen-back to
550 // DIRECT.
551 EXPECT_TRUE(info.is_direct());
552 EXPECT_TRUE(info.did_use_pac_script());
553 EXPECT_EQ(1, info.config_id());
555 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
556 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
557 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
560 // The proxy list could potentially contain the DIRECT fallback choice
561 // in a location other than the very end of the list, and could even
562 // specify it multiple times.
564 // This is not a typical usage, but we will obey it.
565 // (If we wanted to disallow this type of input, the right place to
566 // enforce it would be in parsing the PAC result string).
568 // This test will use the PAC result string:
570 // "DIRECT ; PROXY foobar:10 ; DIRECT ; PROXY foobar:20"
572 // For which we expect it to try DIRECT, then foobar:10, then DIRECT again,
573 // then foobar:20, and then give up and error.
575 // The important check of this test is to make sure that DIRECT is not somehow
576 // cached as being a bad proxy.
577 TEST_F(ProxyServiceTest, PAC_FailoverAfterDirect) {
578 MockProxyConfigService* config_service =
579 new MockProxyConfigService("http://foopy/proxy.pac");
580 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
582 ProxyService service(config_service, resolver, NULL);
584 GURL url("http://www.google.com/");
586 ProxyInfo info;
587 TestCompletionCallback callback1;
588 int rv = service.ResolveProxy(
589 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL,
590 BoundNetLog());
591 EXPECT_EQ(ERR_IO_PENDING, rv);
593 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
594 resolver->pending_set_pac_script_request()->script_data()->url());
595 resolver->pending_set_pac_script_request()->CompleteNow(OK);
597 ASSERT_EQ(1u, resolver->pending_requests().size());
598 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
600 // Set the result in proxy resolver.
601 resolver->pending_requests()[0]->results()->UsePacString(
602 "DIRECT ; PROXY foobar:10 ; DIRECT ; PROXY foobar:20");
603 resolver->pending_requests()[0]->CompleteNow(OK);
605 EXPECT_EQ(OK, callback1.WaitForResult());
606 EXPECT_TRUE(info.is_direct());
608 // Fallback 1.
609 TestCompletionCallback callback2;
610 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
611 net::ERR_PROXY_CONNECTION_FAILED,
612 &info, callback2.callback(), NULL,
613 NULL, BoundNetLog());
614 EXPECT_EQ(OK, rv);
615 EXPECT_FALSE(info.is_direct());
616 EXPECT_EQ("foobar:10", info.proxy_server().ToURI());
618 // Fallback 2.
619 NetworkDelegate network_delegate;
620 ProxyServer expected_proxy_server3 = info.proxy_server();
621 TestCompletionCallback callback3;
622 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
623 net::ERR_PROXY_CONNECTION_FAILED,
624 &info, callback3.callback(), NULL,
625 &network_delegate, BoundNetLog());
626 EXPECT_EQ(OK, rv);
627 EXPECT_TRUE(info.is_direct());
629 // Fallback 3.
630 ProxyServer expected_proxy_server4 = info.proxy_server();
631 TestCompletionCallback callback4;
632 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
633 net::ERR_PROXY_CONNECTION_FAILED,
634 &info, callback4.callback(), NULL,
635 &network_delegate, BoundNetLog());
636 EXPECT_EQ(OK, rv);
637 EXPECT_FALSE(info.is_direct());
638 EXPECT_EQ("foobar:20", info.proxy_server().ToURI());
640 // Fallback 4 -- Nothing to fall back to!
641 ProxyServer expected_proxy_server5 = info.proxy_server();
642 TestCompletionCallback callback5;
643 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
644 net::ERR_PROXY_CONNECTION_FAILED,
645 &info, callback5.callback(), NULL,
646 &network_delegate, BoundNetLog());
647 EXPECT_EQ(ERR_FAILED, rv);
648 EXPECT_TRUE(info.is_empty());
651 TEST_F(ProxyServiceTest, PAC_ConfigSourcePropagates) {
652 // Test whether the ProxyConfigSource set by the ProxyConfigService is applied
653 // to ProxyInfo after the proxy is resolved via a PAC script.
654 ProxyConfig config =
655 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"));
656 config.set_source(PROXY_CONFIG_SOURCE_TEST);
658 MockProxyConfigService* config_service = new MockProxyConfigService(config);
659 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
660 ProxyService service(config_service, resolver, NULL);
662 // Resolve something.
663 GURL url("http://www.google.com/");
664 ProxyInfo info;
665 TestCompletionCallback callback;
666 int rv = service.ResolveProxy(
667 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL,
668 BoundNetLog());
669 ASSERT_EQ(ERR_IO_PENDING, rv);
670 resolver->pending_set_pac_script_request()->CompleteNow(OK);
671 ASSERT_EQ(1u, resolver->pending_requests().size());
673 // Set the result in proxy resolver.
674 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy");
675 resolver->pending_requests()[0]->CompleteNow(OK);
677 EXPECT_EQ(OK, callback.WaitForResult());
678 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
679 EXPECT_TRUE(info.did_use_pac_script());
681 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
682 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
683 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
686 TEST_F(ProxyServiceTest, ProxyResolverFails) {
687 // Test what happens when the ProxyResolver fails. The download and setting
688 // of the PAC script have already succeeded, so this corresponds with a
689 // javascript runtime error while calling FindProxyForURL().
691 MockProxyConfigService* config_service =
692 new MockProxyConfigService("http://foopy/proxy.pac");
694 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
696 ProxyService service(config_service, resolver, NULL);
698 // Start first resolve request.
699 GURL url("http://www.google.com/");
700 ProxyInfo info;
701 TestCompletionCallback callback1;
702 int rv = service.ResolveProxy(
703 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL,
704 BoundNetLog());
705 EXPECT_EQ(ERR_IO_PENDING, rv);
707 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
708 resolver->pending_set_pac_script_request()->script_data()->url());
709 resolver->pending_set_pac_script_request()->CompleteNow(OK);
711 ASSERT_EQ(1u, resolver->pending_requests().size());
712 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
714 // Fail the first resolve request in MockAsyncProxyResolver.
715 resolver->pending_requests()[0]->CompleteNow(ERR_FAILED);
717 // Although the proxy resolver failed the request, ProxyService implicitly
718 // falls-back to DIRECT.
719 EXPECT_EQ(OK, callback1.WaitForResult());
720 EXPECT_TRUE(info.is_direct());
722 // Failed PAC executions still have proxy resolution times.
723 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
724 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
725 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
727 // The second resolve request will try to run through the proxy resolver,
728 // regardless of whether the first request failed in it.
729 TestCompletionCallback callback2;
730 rv = service.ResolveProxy(
731 url, net::LOAD_NORMAL, &info, callback2.callback(), NULL, NULL,
732 BoundNetLog());
733 EXPECT_EQ(ERR_IO_PENDING, rv);
735 ASSERT_EQ(1u, resolver->pending_requests().size());
736 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
738 // This time we will have the resolver succeed (perhaps the PAC script has
739 // a dependency on the current time).
740 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080");
741 resolver->pending_requests()[0]->CompleteNow(OK);
743 EXPECT_EQ(OK, callback2.WaitForResult());
744 EXPECT_FALSE(info.is_direct());
745 EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI());
748 TEST_F(ProxyServiceTest, ProxyScriptFetcherFailsDownloadingMandatoryPac) {
749 // Test what happens when the ProxyScriptResolver fails to download a
750 // mandatory PAC script.
752 ProxyConfig config(
753 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
754 config.set_pac_mandatory(true);
756 MockProxyConfigService* config_service = new MockProxyConfigService(config);
758 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
760 ProxyService service(config_service, resolver, NULL);
762 // Start first resolve request.
763 GURL url("http://www.google.com/");
764 ProxyInfo info;
765 TestCompletionCallback callback1;
766 int rv = service.ResolveProxy(
767 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL,
768 BoundNetLog());
769 EXPECT_EQ(ERR_IO_PENDING, rv);
771 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
772 resolver->pending_set_pac_script_request()->script_data()->url());
773 resolver->pending_set_pac_script_request()->CompleteNow(ERR_FAILED);
775 ASSERT_EQ(0u, resolver->pending_requests().size());
777 // As the proxy resolver failed the request and is configured for a mandatory
778 // PAC script, ProxyService must not implicitly fall-back to DIRECT.
779 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
780 callback1.WaitForResult());
781 EXPECT_FALSE(info.is_direct());
783 // As the proxy resolver failed the request and is configured for a mandatory
784 // PAC script, ProxyService must not implicitly fall-back to DIRECT.
785 TestCompletionCallback callback2;
786 rv = service.ResolveProxy(
787 url, net::LOAD_NORMAL, &info, callback2.callback(), NULL, NULL,
788 BoundNetLog());
789 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED, rv);
790 EXPECT_FALSE(info.is_direct());
793 TEST_F(ProxyServiceTest, ProxyResolverFailsParsingJavaScriptMandatoryPac) {
794 // Test what happens when the ProxyResolver fails that is configured to use a
795 // mandatory PAC script. The download of the PAC script has already
796 // succeeded but the PAC script contains no valid javascript.
798 ProxyConfig config(
799 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
800 config.set_pac_mandatory(true);
802 MockProxyConfigService* config_service = new MockProxyConfigService(config);
804 MockAsyncProxyResolverExpectsBytes* resolver =
805 new MockAsyncProxyResolverExpectsBytes;
807 ProxyService service(config_service, resolver, NULL);
809 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
810 DhcpProxyScriptFetcher* dhcp_fetcher = new DoNothingDhcpProxyScriptFetcher();
811 service.SetProxyScriptFetchers(fetcher, dhcp_fetcher);
813 // Start resolve request.
814 GURL url("http://www.google.com/");
815 ProxyInfo info;
816 TestCompletionCallback callback;
817 int rv = service.ResolveProxy(
818 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL,
819 BoundNetLog());
820 EXPECT_EQ(ERR_IO_PENDING, rv);
822 // Check that nothing has been sent to the proxy resolver yet.
823 ASSERT_EQ(0u, resolver->pending_requests().size());
825 // Downloading the PAC script succeeds.
826 EXPECT_TRUE(fetcher->has_pending_request());
827 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
828 fetcher->NotifyFetchCompletion(OK, "invalid-script-contents");
830 EXPECT_FALSE(fetcher->has_pending_request());
831 ASSERT_EQ(0u, resolver->pending_requests().size());
833 // Since ProxyScriptDecider failed to identify a valid PAC and PAC was
834 // mandatory for this configuration, the ProxyService must not implicitly
835 // fall-back to DIRECT.
836 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
837 callback.WaitForResult());
838 EXPECT_FALSE(info.is_direct());
841 TEST_F(ProxyServiceTest, ProxyResolverFailsInJavaScriptMandatoryPac) {
842 // Test what happens when the ProxyResolver fails that is configured to use a
843 // mandatory PAC script. The download and setting of the PAC script have
844 // already succeeded, so this corresponds with a javascript runtime error
845 // while calling FindProxyForURL().
847 ProxyConfig config(
848 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
849 config.set_pac_mandatory(true);
851 MockProxyConfigService* config_service = new MockProxyConfigService(config);
853 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
855 ProxyService service(config_service, resolver, NULL);
857 // Start first resolve request.
858 GURL url("http://www.google.com/");
859 ProxyInfo info;
860 TestCompletionCallback callback1;
861 int rv = service.ResolveProxy(
862 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL,
863 BoundNetLog());
864 EXPECT_EQ(ERR_IO_PENDING, rv);
866 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
867 resolver->pending_set_pac_script_request()->script_data()->url());
868 resolver->pending_set_pac_script_request()->CompleteNow(OK);
870 ASSERT_EQ(1u, resolver->pending_requests().size());
871 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
873 // Fail the first resolve request in MockAsyncProxyResolver.
874 resolver->pending_requests()[0]->CompleteNow(ERR_FAILED);
876 // As the proxy resolver failed the request and is configured for a mandatory
877 // PAC script, ProxyService must not implicitly fall-back to DIRECT.
878 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
879 callback1.WaitForResult());
880 EXPECT_FALSE(info.is_direct());
882 // The second resolve request will try to run through the proxy resolver,
883 // regardless of whether the first request failed in it.
884 TestCompletionCallback callback2;
885 rv = service.ResolveProxy(
886 url, net::LOAD_NORMAL, &info, callback2.callback(), NULL, NULL,
887 BoundNetLog());
888 EXPECT_EQ(ERR_IO_PENDING, rv);
890 ASSERT_EQ(1u, resolver->pending_requests().size());
891 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
893 // This time we will have the resolver succeed (perhaps the PAC script has
894 // a dependency on the current time).
895 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080");
896 resolver->pending_requests()[0]->CompleteNow(OK);
898 EXPECT_EQ(OK, callback2.WaitForResult());
899 EXPECT_FALSE(info.is_direct());
900 EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI());
903 TEST_F(ProxyServiceTest, ProxyFallback) {
904 // Test what happens when we specify multiple proxy servers and some of them
905 // are bad.
907 MockProxyConfigService* config_service =
908 new MockProxyConfigService("http://foopy/proxy.pac");
910 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
912 ProxyService service(config_service, resolver, NULL);
914 GURL url("http://www.google.com/");
916 // Get the proxy information.
917 ProxyInfo info;
918 TestCompletionCallback callback1;
919 int rv = service.ResolveProxy(
920 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL,
921 BoundNetLog());
922 EXPECT_EQ(ERR_IO_PENDING, rv);
924 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
925 resolver->pending_set_pac_script_request()->script_data()->url());
926 resolver->pending_set_pac_script_request()->CompleteNow(OK);
928 ASSERT_EQ(1u, resolver->pending_requests().size());
929 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
931 // Set the result in proxy resolver.
932 resolver->pending_requests()[0]->results()->UseNamedProxy(
933 "foopy1:8080;foopy2:9090");
934 resolver->pending_requests()[0]->CompleteNow(OK);
936 // The first item is valid.
937 EXPECT_EQ(OK, callback1.WaitForResult());
938 EXPECT_FALSE(info.is_direct());
939 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
941 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
942 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
943 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
944 base::TimeTicks proxy_resolve_start_time = info.proxy_resolve_start_time();
945 base::TimeTicks proxy_resolve_end_time = info.proxy_resolve_end_time();
947 // Fake an error on the proxy.
948 TestCompletionCallback callback2;
949 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
950 net::ERR_PROXY_CONNECTION_FAILED,
951 &info, callback2.callback(), NULL,
952 NULL, BoundNetLog());
953 EXPECT_EQ(OK, rv);
955 // Proxy times should not have been modified by fallback.
956 EXPECT_EQ(proxy_resolve_start_time, info.proxy_resolve_start_time());
957 EXPECT_EQ(proxy_resolve_end_time, info.proxy_resolve_end_time());
959 // The second proxy should be specified.
960 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
961 // Report back that the second proxy worked. This will globally mark the
962 // first proxy as bad.
963 TestProxyFallbackNetworkDelegate test_delegate;
964 service.ReportSuccess(info, &test_delegate);
965 EXPECT_EQ("foopy1:8080", test_delegate.proxy_server().ToURI());
966 EXPECT_EQ(net::ERR_PROXY_CONNECTION_FAILED,
967 test_delegate.proxy_fallback_net_error());
969 TestCompletionCallback callback3;
970 rv = service.ResolveProxy(
971 url, net::LOAD_NORMAL, &info, callback3.callback(), NULL, NULL,
972 BoundNetLog());
973 EXPECT_EQ(ERR_IO_PENDING, rv);
975 ASSERT_EQ(1u, resolver->pending_requests().size());
976 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
978 // Set the result in proxy resolver -- the second result is already known
979 // to be bad, so we will not try to use it initially.
980 resolver->pending_requests()[0]->results()->UseNamedProxy(
981 "foopy3:7070;foopy1:8080;foopy2:9090");
982 resolver->pending_requests()[0]->CompleteNow(OK);
984 EXPECT_EQ(OK, callback3.WaitForResult());
985 EXPECT_FALSE(info.is_direct());
986 EXPECT_EQ("foopy3:7070", info.proxy_server().ToURI());
988 // Proxy times should have been updated, so get them again.
989 EXPECT_LE(proxy_resolve_end_time, info.proxy_resolve_start_time());
990 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
991 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
992 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
993 proxy_resolve_start_time = info.proxy_resolve_start_time();
994 proxy_resolve_end_time = info.proxy_resolve_end_time();
996 // We fake another error. It should now try the third one.
997 TestCompletionCallback callback4;
998 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
999 net::ERR_PROXY_CONNECTION_FAILED,
1000 &info, callback4.callback(), NULL,
1001 NULL, BoundNetLog());
1002 EXPECT_EQ(OK, rv);
1003 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
1005 // We fake another error. At this point we have tried all of the
1006 // proxy servers we thought were valid; next we try the proxy server
1007 // that was in our bad proxies map (foopy1:8080).
1008 TestCompletionCallback callback5;
1009 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
1010 net::ERR_PROXY_CONNECTION_FAILED,
1011 &info, callback5.callback(), NULL,
1012 NULL, BoundNetLog());
1013 EXPECT_EQ(OK, rv);
1014 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1016 // Fake another error, the last proxy is gone, the list should now be empty,
1017 // so there is nothing left to try.
1018 TestCompletionCallback callback6;
1019 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
1020 net::ERR_PROXY_CONNECTION_FAILED,
1021 &info, callback6.callback(), NULL,
1022 NULL, BoundNetLog());
1023 EXPECT_EQ(ERR_FAILED, rv);
1024 EXPECT_FALSE(info.is_direct());
1025 EXPECT_TRUE(info.is_empty());
1027 // Proxy times should not have been modified by fallback.
1028 EXPECT_EQ(proxy_resolve_start_time, info.proxy_resolve_start_time());
1029 EXPECT_EQ(proxy_resolve_end_time, info.proxy_resolve_end_time());
1031 // Look up proxies again
1032 TestCompletionCallback callback7;
1033 rv = service.ResolveProxy(url, net::LOAD_NORMAL, &info, callback7.callback(),
1034 NULL, NULL, BoundNetLog());
1035 EXPECT_EQ(ERR_IO_PENDING, rv);
1037 ASSERT_EQ(1u, resolver->pending_requests().size());
1038 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
1040 // This time, the first 3 results have been found to be bad, but only the
1041 // first proxy has been confirmed ...
1042 resolver->pending_requests()[0]->results()->UseNamedProxy(
1043 "foopy1:8080;foopy3:7070;foopy2:9090;foopy4:9091");
1044 resolver->pending_requests()[0]->CompleteNow(OK);
1046 // ... therefore, we should see the second proxy first.
1047 EXPECT_EQ(OK, callback7.WaitForResult());
1048 EXPECT_FALSE(info.is_direct());
1049 EXPECT_EQ("foopy3:7070", info.proxy_server().ToURI());
1051 EXPECT_LE(proxy_resolve_end_time, info.proxy_resolve_start_time());
1052 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1053 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1054 // TODO(nsylvain): Test that the proxy can be retried after the delay.
1057 // This test is similar to ProxyFallback, but this time we have an explicit
1058 // fallback choice to DIRECT.
1059 TEST_F(ProxyServiceTest, ProxyFallbackToDirect) {
1060 MockProxyConfigService* config_service =
1061 new MockProxyConfigService("http://foopy/proxy.pac");
1063 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
1065 ProxyService service(config_service, resolver, NULL);
1067 GURL url("http://www.google.com/");
1069 // Get the proxy information.
1070 ProxyInfo info;
1071 TestCompletionCallback callback1;
1072 int rv = service.ResolveProxy(
1073 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL,
1074 BoundNetLog());
1075 EXPECT_EQ(ERR_IO_PENDING, rv);
1077 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1078 resolver->pending_set_pac_script_request()->script_data()->url());
1079 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1081 ASSERT_EQ(1u, resolver->pending_requests().size());
1082 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
1084 // Set the result in proxy resolver.
1085 resolver->pending_requests()[0]->results()->UsePacString(
1086 "PROXY foopy1:8080; PROXY foopy2:9090; DIRECT");
1087 resolver->pending_requests()[0]->CompleteNow(OK);
1089 // Get the first result.
1090 EXPECT_EQ(OK, callback1.WaitForResult());
1091 EXPECT_FALSE(info.is_direct());
1092 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1094 // Fake an error on the proxy.
1095 TestCompletionCallback callback2;
1096 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
1097 net::ERR_PROXY_CONNECTION_FAILED,
1098 &info, callback2.callback(), NULL,
1099 NULL, BoundNetLog());
1100 EXPECT_EQ(OK, rv);
1102 // Now we get back the second proxy.
1103 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
1105 // Fake an error on this proxy as well.
1106 TestCompletionCallback callback3;
1107 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
1108 net::ERR_PROXY_CONNECTION_FAILED,
1109 &info, callback3.callback(), NULL,
1110 NULL, BoundNetLog());
1111 EXPECT_EQ(OK, rv);
1113 // Finally, we get back DIRECT.
1114 EXPECT_TRUE(info.is_direct());
1116 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1117 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1118 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1120 // Now we tell the proxy service that even DIRECT failed.
1121 TestCompletionCallback callback4;
1122 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
1123 net::ERR_PROXY_CONNECTION_FAILED,
1124 &info, callback4.callback(), NULL,
1125 NULL, BoundNetLog());
1126 // There was nothing left to try after DIRECT, so we are out of
1127 // choices.
1128 EXPECT_EQ(ERR_FAILED, rv);
1131 TEST_F(ProxyServiceTest, ProxyFallback_NewSettings) {
1132 // Test proxy failover when new settings are available.
1134 MockProxyConfigService* config_service =
1135 new MockProxyConfigService("http://foopy/proxy.pac");
1137 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
1139 ProxyService service(config_service, resolver, NULL);
1141 GURL url("http://www.google.com/");
1143 // Get the proxy information.
1144 ProxyInfo info;
1145 TestCompletionCallback callback1;
1146 int rv = service.ResolveProxy(
1147 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL,
1148 BoundNetLog());
1149 EXPECT_EQ(ERR_IO_PENDING, rv);
1151 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1152 resolver->pending_set_pac_script_request()->script_data()->url());
1153 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1155 ASSERT_EQ(1u, resolver->pending_requests().size());
1156 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
1158 // Set the result in proxy resolver.
1159 resolver->pending_requests()[0]->results()->UseNamedProxy(
1160 "foopy1:8080;foopy2:9090");
1161 resolver->pending_requests()[0]->CompleteNow(OK);
1163 // The first item is valid.
1164 EXPECT_EQ(OK, callback1.WaitForResult());
1165 EXPECT_FALSE(info.is_direct());
1166 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1168 // Fake an error on the proxy, and also a new configuration on the proxy.
1169 config_service->SetConfig(
1170 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy-new/proxy.pac")));
1172 TestCompletionCallback callback2;
1173 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
1174 net::ERR_PROXY_CONNECTION_FAILED,
1175 &info, callback2.callback(), NULL,
1176 NULL, BoundNetLog());
1177 EXPECT_EQ(ERR_IO_PENDING, rv);
1179 EXPECT_EQ(GURL("http://foopy-new/proxy.pac"),
1180 resolver->pending_set_pac_script_request()->script_data()->url());
1181 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1183 ASSERT_EQ(1u, resolver->pending_requests().size());
1184 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
1186 resolver->pending_requests()[0]->results()->UseNamedProxy(
1187 "foopy1:8080;foopy2:9090");
1188 resolver->pending_requests()[0]->CompleteNow(OK);
1190 // The first proxy is still there since the configuration changed.
1191 EXPECT_EQ(OK, callback2.WaitForResult());
1192 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1194 // We fake another error. It should now ignore the first one.
1195 TestCompletionCallback callback3;
1196 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
1197 net::ERR_PROXY_CONNECTION_FAILED,
1198 &info, callback3.callback(), NULL,
1199 NULL, BoundNetLog());
1200 EXPECT_EQ(OK, rv);
1201 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
1203 // We simulate a new configuration.
1204 config_service->SetConfig(
1205 ProxyConfig::CreateFromCustomPacURL(
1206 GURL("http://foopy-new2/proxy.pac")));
1208 // We fake another error. It should go back to the first proxy.
1209 TestCompletionCallback callback4;
1210 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
1211 net::ERR_PROXY_CONNECTION_FAILED,
1212 &info, callback4.callback(), NULL,
1213 NULL, BoundNetLog());
1214 EXPECT_EQ(ERR_IO_PENDING, rv);
1216 EXPECT_EQ(GURL("http://foopy-new2/proxy.pac"),
1217 resolver->pending_set_pac_script_request()->script_data()->url());
1218 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1220 ASSERT_EQ(1u, resolver->pending_requests().size());
1221 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
1223 resolver->pending_requests()[0]->results()->UseNamedProxy(
1224 "foopy1:8080;foopy2:9090");
1225 resolver->pending_requests()[0]->CompleteNow(OK);
1227 EXPECT_EQ(OK, callback4.WaitForResult());
1228 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1230 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1231 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1232 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1235 TEST_F(ProxyServiceTest, ProxyFallback_BadConfig) {
1236 // Test proxy failover when the configuration is bad.
1238 MockProxyConfigService* config_service =
1239 new MockProxyConfigService("http://foopy/proxy.pac");
1241 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
1243 ProxyService service(config_service, resolver, NULL);
1245 GURL url("http://www.google.com/");
1247 // Get the proxy information.
1248 ProxyInfo info;
1249 TestCompletionCallback callback1;
1250 int rv = service.ResolveProxy(
1251 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL,
1252 BoundNetLog());
1253 EXPECT_EQ(ERR_IO_PENDING, rv);
1255 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1256 resolver->pending_set_pac_script_request()->script_data()->url());
1257 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1258 ASSERT_EQ(1u, resolver->pending_requests().size());
1259 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
1261 resolver->pending_requests()[0]->results()->UseNamedProxy(
1262 "foopy1:8080;foopy2:9090");
1263 resolver->pending_requests()[0]->CompleteNow(OK);
1265 // The first item is valid.
1266 EXPECT_EQ(OK, callback1.WaitForResult());
1267 EXPECT_FALSE(info.is_direct());
1268 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1270 // Fake a proxy error.
1271 TestCompletionCallback callback2;
1272 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
1273 net::ERR_PROXY_CONNECTION_FAILED,
1274 &info, callback2.callback(), NULL,
1275 NULL, BoundNetLog());
1276 EXPECT_EQ(OK, rv);
1278 // The first proxy is ignored, and the second one is selected.
1279 EXPECT_FALSE(info.is_direct());
1280 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
1282 // Fake a PAC failure.
1283 ProxyInfo info2;
1284 TestCompletionCallback callback3;
1285 rv = service.ResolveProxy(
1286 url, net::LOAD_NORMAL, &info2, callback3.callback(), NULL, NULL,
1287 BoundNetLog());
1288 EXPECT_EQ(ERR_IO_PENDING, rv);
1290 ASSERT_EQ(1u, resolver->pending_requests().size());
1291 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
1293 // This simulates a javascript runtime error in the PAC script.
1294 resolver->pending_requests()[0]->CompleteNow(ERR_FAILED);
1296 // Although the resolver failed, the ProxyService will implicitly fall-back
1297 // to a DIRECT connection.
1298 EXPECT_EQ(OK, callback3.WaitForResult());
1299 EXPECT_TRUE(info2.is_direct());
1300 EXPECT_FALSE(info2.is_empty());
1302 // The PAC script will work properly next time and successfully return a
1303 // proxy list. Since we have not marked the configuration as bad, it should
1304 // "just work" the next time we call it.
1305 ProxyInfo info3;
1306 TestCompletionCallback callback4;
1307 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
1308 net::ERR_PROXY_CONNECTION_FAILED,
1309 &info3, callback4.callback(),
1310 NULL, NULL, BoundNetLog());
1311 EXPECT_EQ(ERR_IO_PENDING, rv);
1313 ASSERT_EQ(1u, resolver->pending_requests().size());
1314 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
1316 resolver->pending_requests()[0]->results()->UseNamedProxy(
1317 "foopy1:8080;foopy2:9090");
1318 resolver->pending_requests()[0]->CompleteNow(OK);
1320 // The first proxy is not there since the it was added to the bad proxies
1321 // list by the earlier ReconsiderProxyAfterError().
1322 EXPECT_EQ(OK, callback4.WaitForResult());
1323 EXPECT_FALSE(info3.is_direct());
1324 EXPECT_EQ("foopy1:8080", info3.proxy_server().ToURI());
1326 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1327 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1328 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1331 TEST_F(ProxyServiceTest, ProxyFallback_BadConfigMandatory) {
1332 // Test proxy failover when the configuration is bad.
1334 ProxyConfig config(
1335 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
1337 config.set_pac_mandatory(true);
1338 MockProxyConfigService* config_service = new MockProxyConfigService(config);
1340 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
1342 ProxyService service(config_service, resolver, NULL);
1344 GURL url("http://www.google.com/");
1346 // Get the proxy information.
1347 ProxyInfo info;
1348 TestCompletionCallback callback1;
1349 int rv = service.ResolveProxy(
1350 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL,
1351 BoundNetLog());
1352 EXPECT_EQ(ERR_IO_PENDING, rv);
1354 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1355 resolver->pending_set_pac_script_request()->script_data()->url());
1356 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1357 ASSERT_EQ(1u, resolver->pending_requests().size());
1358 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
1360 resolver->pending_requests()[0]->results()->UseNamedProxy(
1361 "foopy1:8080;foopy2:9090");
1362 resolver->pending_requests()[0]->CompleteNow(OK);
1364 // The first item is valid.
1365 EXPECT_EQ(OK, callback1.WaitForResult());
1366 EXPECT_FALSE(info.is_direct());
1367 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1369 // Fake a proxy error.
1370 TestCompletionCallback callback2;
1371 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
1372 net::ERR_PROXY_CONNECTION_FAILED,
1373 &info, callback2.callback(), NULL,
1374 NULL, BoundNetLog());
1375 EXPECT_EQ(OK, rv);
1377 // The first proxy is ignored, and the second one is selected.
1378 EXPECT_FALSE(info.is_direct());
1379 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
1381 // Fake a PAC failure.
1382 ProxyInfo info2;
1383 TestCompletionCallback callback3;
1384 rv = service.ResolveProxy(
1385 url, net::LOAD_NORMAL, &info2, callback3.callback(), NULL, NULL,
1386 BoundNetLog());
1387 EXPECT_EQ(ERR_IO_PENDING, rv);
1389 ASSERT_EQ(1u, resolver->pending_requests().size());
1390 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
1392 // This simulates a javascript runtime error in the PAC script.
1393 resolver->pending_requests()[0]->CompleteNow(ERR_FAILED);
1395 // Although the resolver failed, the ProxyService will NOT fall-back
1396 // to a DIRECT connection as it is configured as mandatory.
1397 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
1398 callback3.WaitForResult());
1399 EXPECT_FALSE(info2.is_direct());
1400 EXPECT_TRUE(info2.is_empty());
1402 // The PAC script will work properly next time and successfully return a
1403 // proxy list. Since we have not marked the configuration as bad, it should
1404 // "just work" the next time we call it.
1405 ProxyInfo info3;
1406 TestCompletionCallback callback4;
1407 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL,
1408 net::ERR_PROXY_CONNECTION_FAILED,
1409 &info3, callback4.callback(),
1410 NULL, NULL, BoundNetLog());
1411 EXPECT_EQ(ERR_IO_PENDING, rv);
1413 ASSERT_EQ(1u, resolver->pending_requests().size());
1414 EXPECT_EQ(url, resolver->pending_requests()[0]->url());
1416 resolver->pending_requests()[0]->results()->UseNamedProxy(
1417 "foopy1:8080;foopy2:9090");
1418 resolver->pending_requests()[0]->CompleteNow(OK);
1420 // The first proxy is not there since the it was added to the bad proxies
1421 // list by the earlier ReconsiderProxyAfterError().
1422 EXPECT_EQ(OK, callback4.WaitForResult());
1423 EXPECT_FALSE(info3.is_direct());
1424 EXPECT_EQ("foopy1:8080", info3.proxy_server().ToURI());
1427 TEST_F(ProxyServiceTest, ProxyBypassList) {
1428 // Test that the proxy bypass rules are consulted.
1430 TestCompletionCallback callback[2];
1431 ProxyInfo info[2];
1432 ProxyConfig config;
1433 config.proxy_rules().ParseFromString("foopy1:8080;foopy2:9090");
1434 config.set_auto_detect(false);
1435 config.proxy_rules().bypass_rules.ParseFromString("*.org");
1437 ProxyService service(
1438 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1440 int rv;
1441 GURL url1("http://www.webkit.org");
1442 GURL url2("http://www.webkit.com");
1444 // Request for a .org domain should bypass proxy.
1445 rv = service.ResolveProxy(
1446 url1, net::LOAD_NORMAL, &info[0], callback[0].callback(), NULL, NULL,
1447 BoundNetLog());
1448 EXPECT_EQ(OK, rv);
1449 EXPECT_TRUE(info[0].is_direct());
1451 // Request for a .com domain hits the proxy.
1452 rv = service.ResolveProxy(
1453 url2, net::LOAD_NORMAL, &info[1], callback[1].callback(), NULL, NULL,
1454 BoundNetLog());
1455 EXPECT_EQ(OK, rv);
1456 EXPECT_EQ("foopy1:8080", info[1].proxy_server().ToURI());
1460 TEST_F(ProxyServiceTest, PerProtocolProxyTests) {
1461 ProxyConfig config;
1462 config.proxy_rules().ParseFromString("http=foopy1:8080;https=foopy2:8080");
1463 config.set_auto_detect(false);
1465 ProxyService service(
1466 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1467 GURL test_url("http://www.msn.com");
1468 ProxyInfo info;
1469 TestCompletionCallback callback;
1470 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info,
1471 callback.callback(), NULL, NULL,
1472 BoundNetLog());
1473 EXPECT_EQ(OK, rv);
1474 EXPECT_FALSE(info.is_direct());
1475 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1478 ProxyService service(
1479 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1480 GURL test_url("ftp://ftp.google.com");
1481 ProxyInfo info;
1482 TestCompletionCallback callback;
1483 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info,
1484 callback.callback(), NULL,
1485 NULL, BoundNetLog());
1486 EXPECT_EQ(OK, rv);
1487 EXPECT_TRUE(info.is_direct());
1488 EXPECT_EQ("direct://", info.proxy_server().ToURI());
1491 ProxyService service(
1492 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1493 GURL test_url("https://webbranch.techcu.com");
1494 ProxyInfo info;
1495 TestCompletionCallback callback;
1496 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info,
1497 callback.callback(), NULL,
1498 NULL, BoundNetLog());
1499 EXPECT_EQ(OK, rv);
1500 EXPECT_FALSE(info.is_direct());
1501 EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI());
1504 config.proxy_rules().ParseFromString("foopy1:8080");
1505 ProxyService service(
1506 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1507 GURL test_url("http://www.microsoft.com");
1508 ProxyInfo info;
1509 TestCompletionCallback callback;
1510 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info,
1511 callback.callback(), NULL,
1512 NULL, BoundNetLog());
1513 EXPECT_EQ(OK, rv);
1514 EXPECT_FALSE(info.is_direct());
1515 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1519 TEST_F(ProxyServiceTest, ProxyConfigSourcePropagates) {
1520 // Test that the proxy config source is set correctly when resolving proxies
1521 // using manual proxy rules. Namely, the config source should only be set if
1522 // any of the rules were applied.
1524 ProxyConfig config;
1525 config.set_source(PROXY_CONFIG_SOURCE_TEST);
1526 config.proxy_rules().ParseFromString("https=foopy2:8080");
1527 ProxyService service(
1528 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1529 GURL test_url("http://www.google.com");
1530 ProxyInfo info;
1531 TestCompletionCallback callback;
1532 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info,
1533 callback.callback(), NULL,
1534 NULL, BoundNetLog());
1535 ASSERT_EQ(OK, rv);
1536 // Should be SOURCE_TEST, even if there are no HTTP proxies configured.
1537 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
1540 ProxyConfig config;
1541 config.set_source(PROXY_CONFIG_SOURCE_TEST);
1542 config.proxy_rules().ParseFromString("https=foopy2:8080");
1543 ProxyService service(
1544 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1545 GURL test_url("https://www.google.com");
1546 ProxyInfo info;
1547 TestCompletionCallback callback;
1548 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info,
1549 callback.callback(), NULL,
1550 NULL, BoundNetLog());
1551 ASSERT_EQ(OK, rv);
1552 // Used the HTTPS proxy. So source should be TEST.
1553 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
1556 ProxyConfig config;
1557 config.set_source(PROXY_CONFIG_SOURCE_TEST);
1558 ProxyService service(
1559 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1560 GURL test_url("http://www.google.com");
1561 ProxyInfo info;
1562 TestCompletionCallback callback;
1563 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info,
1564 callback.callback(), NULL,
1565 NULL, BoundNetLog());
1566 ASSERT_EQ(OK, rv);
1567 // ProxyConfig is empty. Source should still be TEST.
1568 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
1572 // If only HTTP and a SOCKS proxy are specified, check if ftp/https queries
1573 // fall back to the SOCKS proxy.
1574 TEST_F(ProxyServiceTest, DefaultProxyFallbackToSOCKS) {
1575 ProxyConfig config;
1576 config.proxy_rules().ParseFromString("http=foopy1:8080;socks=foopy2:1080");
1577 config.set_auto_detect(false);
1578 EXPECT_EQ(ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
1579 config.proxy_rules().type);
1582 ProxyService service(
1583 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1584 GURL test_url("http://www.msn.com");
1585 ProxyInfo info;
1586 TestCompletionCallback callback;
1587 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info,
1588 callback.callback(), NULL,
1589 NULL, BoundNetLog());
1590 EXPECT_EQ(OK, rv);
1591 EXPECT_FALSE(info.is_direct());
1592 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1595 ProxyService service(
1596 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1597 GURL test_url("ftp://ftp.google.com");
1598 ProxyInfo info;
1599 TestCompletionCallback callback;
1600 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info,
1601 callback.callback(), NULL,
1602 NULL, BoundNetLog());
1603 EXPECT_EQ(OK, rv);
1604 EXPECT_FALSE(info.is_direct());
1605 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI());
1608 ProxyService service(
1609 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1610 GURL test_url("https://webbranch.techcu.com");
1611 ProxyInfo info;
1612 TestCompletionCallback callback;
1613 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info,
1614 callback.callback(), NULL,
1615 NULL, BoundNetLog());
1616 EXPECT_EQ(OK, rv);
1617 EXPECT_FALSE(info.is_direct());
1618 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI());
1621 ProxyService service(
1622 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL);
1623 GURL test_url("unknown://www.microsoft.com");
1624 ProxyInfo info;
1625 TestCompletionCallback callback;
1626 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info,
1627 callback.callback(), NULL,
1628 NULL, BoundNetLog());
1629 EXPECT_EQ(OK, rv);
1630 EXPECT_FALSE(info.is_direct());
1631 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI());
1635 // Test cancellation of an in-progress request.
1636 TEST_F(ProxyServiceTest, CancelInProgressRequest) {
1637 MockProxyConfigService* config_service =
1638 new MockProxyConfigService("http://foopy/proxy.pac");
1640 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
1642 ProxyService service(config_service, resolver, NULL);
1644 // Start 3 requests.
1646 ProxyInfo info1;
1647 TestCompletionCallback callback1;
1648 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL,
1649 &info1, callback1.callback(), NULL, NULL,
1650 BoundNetLog());
1651 EXPECT_EQ(ERR_IO_PENDING, rv);
1653 // Nothing has been sent to the proxy resolver yet, since the proxy
1654 // resolver has not been configured yet.
1655 ASSERT_EQ(0u, resolver->pending_requests().size());
1657 // Successfully initialize the PAC script.
1658 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1659 resolver->pending_set_pac_script_request()->script_data()->url());
1660 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1662 ASSERT_EQ(1u, resolver->pending_requests().size());
1663 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
1665 ProxyInfo info2;
1666 TestCompletionCallback callback2;
1667 ProxyService::PacRequest* request2;
1668 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2,
1669 callback2.callback(), &request2, NULL,
1670 BoundNetLog());
1671 EXPECT_EQ(ERR_IO_PENDING, rv);
1672 ASSERT_EQ(2u, resolver->pending_requests().size());
1673 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url());
1675 ProxyInfo info3;
1676 TestCompletionCallback callback3;
1677 rv = service.ResolveProxy(GURL("http://request3"), net::LOAD_NORMAL, &info3,
1678 callback3.callback(), NULL, NULL, BoundNetLog());
1679 EXPECT_EQ(ERR_IO_PENDING, rv);
1680 ASSERT_EQ(3u, resolver->pending_requests().size());
1681 EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[2]->url());
1683 // Cancel the second request
1684 service.CancelPacRequest(request2);
1686 ASSERT_EQ(2u, resolver->pending_requests().size());
1687 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
1688 EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[1]->url());
1690 // Complete the two un-cancelled requests.
1691 // We complete the last one first, just to mix it up a bit.
1692 resolver->pending_requests()[1]->results()->UseNamedProxy("request3:80");
1693 resolver->pending_requests()[1]->CompleteNow(OK);
1695 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
1696 resolver->pending_requests()[0]->CompleteNow(OK);
1698 // Complete and verify that requests ran as expected.
1699 EXPECT_EQ(OK, callback1.WaitForResult());
1700 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
1702 EXPECT_FALSE(callback2.have_result()); // Cancelled.
1703 ASSERT_EQ(1u, resolver->cancelled_requests().size());
1704 EXPECT_EQ(GURL("http://request2"), resolver->cancelled_requests()[0]->url());
1706 EXPECT_EQ(OK, callback3.WaitForResult());
1707 EXPECT_EQ("request3:80", info3.proxy_server().ToURI());
1710 // Test the initial PAC download for resolver that expects bytes.
1711 TEST_F(ProxyServiceTest, InitialPACScriptDownload) {
1712 MockProxyConfigService* config_service =
1713 new MockProxyConfigService("http://foopy/proxy.pac");
1715 MockAsyncProxyResolverExpectsBytes* resolver =
1716 new MockAsyncProxyResolverExpectsBytes;
1718 ProxyService service(config_service, resolver, NULL);
1720 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1721 service.SetProxyScriptFetchers(fetcher,
1722 new DoNothingDhcpProxyScriptFetcher());
1724 // Start 3 requests.
1726 ProxyInfo info1;
1727 TestCompletionCallback callback1;
1728 ProxyService::PacRequest* request1;
1729 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL,
1730 &info1, callback1.callback(), &request1, NULL,
1731 BoundNetLog());
1732 EXPECT_EQ(ERR_IO_PENDING, rv);
1734 // The first request should have triggered download of PAC script.
1735 EXPECT_TRUE(fetcher->has_pending_request());
1736 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1738 ProxyInfo info2;
1739 TestCompletionCallback callback2;
1740 ProxyService::PacRequest* request2;
1741 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2,
1742 callback2.callback(), &request2, NULL,
1743 BoundNetLog());
1744 EXPECT_EQ(ERR_IO_PENDING, rv);
1746 ProxyInfo info3;
1747 TestCompletionCallback callback3;
1748 ProxyService::PacRequest* request3;
1749 rv = service.ResolveProxy(GURL("http://request3"), net::LOAD_NORMAL, &info3,
1750 callback3.callback(), &request3, NULL,
1751 BoundNetLog());
1752 EXPECT_EQ(ERR_IO_PENDING, rv);
1754 // Nothing has been sent to the resolver yet.
1755 EXPECT_TRUE(resolver->pending_requests().empty());
1757 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT,
1758 service.GetLoadState(request1));
1759 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT,
1760 service.GetLoadState(request2));
1761 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT,
1762 service.GetLoadState(request3));
1764 // At this point the ProxyService should be waiting for the
1765 // ProxyScriptFetcher to invoke its completion callback, notifying it of
1766 // PAC script download completion.
1767 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
1769 // Now that the PAC script is downloaded, it will have been sent to the proxy
1770 // resolver.
1771 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
1772 resolver->pending_set_pac_script_request()->script_data()->utf16());
1773 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1775 ASSERT_EQ(3u, resolver->pending_requests().size());
1776 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
1777 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url());
1778 EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[2]->url());
1780 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request1));
1781 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request2));
1782 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request3));
1784 // Complete all the requests (in some order).
1785 // Note that as we complete requests, they shift up in |pending_requests()|.
1787 resolver->pending_requests()[2]->results()->UseNamedProxy("request3:80");
1788 resolver->pending_requests()[2]->CompleteNow(OK);
1790 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
1791 resolver->pending_requests()[0]->CompleteNow(OK);
1793 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80");
1794 resolver->pending_requests()[0]->CompleteNow(OK);
1796 // Complete and verify that requests ran as expected.
1797 EXPECT_EQ(OK, callback1.WaitForResult());
1798 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
1799 EXPECT_FALSE(info1.proxy_resolve_start_time().is_null());
1800 EXPECT_FALSE(info1.proxy_resolve_end_time().is_null());
1801 EXPECT_LE(info1.proxy_resolve_start_time(), info1.proxy_resolve_end_time());
1803 EXPECT_EQ(OK, callback2.WaitForResult());
1804 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
1805 EXPECT_FALSE(info2.proxy_resolve_start_time().is_null());
1806 EXPECT_FALSE(info2.proxy_resolve_end_time().is_null());
1807 EXPECT_LE(info2.proxy_resolve_start_time(), info2.proxy_resolve_end_time());
1809 EXPECT_EQ(OK, callback3.WaitForResult());
1810 EXPECT_EQ("request3:80", info3.proxy_server().ToURI());
1811 EXPECT_FALSE(info3.proxy_resolve_start_time().is_null());
1812 EXPECT_FALSE(info3.proxy_resolve_end_time().is_null());
1813 EXPECT_LE(info3.proxy_resolve_start_time(), info3.proxy_resolve_end_time());
1816 // Test changing the ProxyScriptFetcher while PAC download is in progress.
1817 TEST_F(ProxyServiceTest, ChangeScriptFetcherWhilePACDownloadInProgress) {
1818 MockProxyConfigService* config_service =
1819 new MockProxyConfigService("http://foopy/proxy.pac");
1821 MockAsyncProxyResolverExpectsBytes* resolver =
1822 new MockAsyncProxyResolverExpectsBytes;
1824 ProxyService service(config_service, resolver, NULL);
1826 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1827 service.SetProxyScriptFetchers(fetcher,
1828 new DoNothingDhcpProxyScriptFetcher());
1830 // Start 2 requests.
1832 ProxyInfo info1;
1833 TestCompletionCallback callback1;
1834 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL,
1835 &info1, callback1.callback(), NULL, NULL,
1836 BoundNetLog());
1837 EXPECT_EQ(ERR_IO_PENDING, rv);
1839 // The first request should have triggered download of PAC script.
1840 EXPECT_TRUE(fetcher->has_pending_request());
1841 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1843 ProxyInfo info2;
1844 TestCompletionCallback callback2;
1845 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2,
1846 callback2.callback(), NULL, NULL, BoundNetLog());
1847 EXPECT_EQ(ERR_IO_PENDING, rv);
1849 // At this point the ProxyService should be waiting for the
1850 // ProxyScriptFetcher to invoke its completion callback, notifying it of
1851 // PAC script download completion.
1853 // We now change out the ProxyService's script fetcher. We should restart
1854 // the initialization with the new fetcher.
1856 fetcher = new MockProxyScriptFetcher;
1857 service.SetProxyScriptFetchers(fetcher,
1858 new DoNothingDhcpProxyScriptFetcher());
1860 // Nothing has been sent to the resolver yet.
1861 EXPECT_TRUE(resolver->pending_requests().empty());
1863 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
1865 // Now that the PAC script is downloaded, it will have been sent to the proxy
1866 // resolver.
1867 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
1868 resolver->pending_set_pac_script_request()->script_data()->utf16());
1869 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1871 ASSERT_EQ(2u, resolver->pending_requests().size());
1872 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
1873 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url());
1876 // Test cancellation of a request, while the PAC script is being fetched.
1877 TEST_F(ProxyServiceTest, CancelWhilePACFetching) {
1878 MockProxyConfigService* config_service =
1879 new MockProxyConfigService("http://foopy/proxy.pac");
1881 MockAsyncProxyResolverExpectsBytes* resolver =
1882 new MockAsyncProxyResolverExpectsBytes;
1884 ProxyService service(config_service, resolver, NULL);
1886 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1887 service.SetProxyScriptFetchers(fetcher,
1888 new DoNothingDhcpProxyScriptFetcher());
1890 // Start 3 requests.
1891 ProxyInfo info1;
1892 TestCompletionCallback callback1;
1893 ProxyService::PacRequest* request1;
1894 CapturingBoundNetLog log1;
1895 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL,
1896 &info1, callback1.callback(), &request1, NULL,
1897 log1.bound());
1898 EXPECT_EQ(ERR_IO_PENDING, rv);
1900 // The first request should have triggered download of PAC script.
1901 EXPECT_TRUE(fetcher->has_pending_request());
1902 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1904 ProxyInfo info2;
1905 TestCompletionCallback callback2;
1906 ProxyService::PacRequest* request2;
1907 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2,
1908 callback2.callback(), &request2, NULL,
1909 BoundNetLog());
1910 EXPECT_EQ(ERR_IO_PENDING, rv);
1912 ProxyInfo info3;
1913 TestCompletionCallback callback3;
1914 rv = service.ResolveProxy(GURL("http://request3"), net::LOAD_NORMAL, &info3,
1915 callback3.callback(), NULL, NULL, BoundNetLog());
1916 EXPECT_EQ(ERR_IO_PENDING, rv);
1918 // Nothing has been sent to the resolver yet.
1919 EXPECT_TRUE(resolver->pending_requests().empty());
1921 // Cancel the first 2 requests.
1922 service.CancelPacRequest(request1);
1923 service.CancelPacRequest(request2);
1925 // At this point the ProxyService should be waiting for the
1926 // ProxyScriptFetcher to invoke its completion callback, notifying it of
1927 // PAC script download completion.
1928 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
1930 // Now that the PAC script is downloaded, it will have been sent to the
1931 // proxy resolver.
1932 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
1933 resolver->pending_set_pac_script_request()->script_data()->utf16());
1934 resolver->pending_set_pac_script_request()->CompleteNow(OK);
1936 ASSERT_EQ(1u, resolver->pending_requests().size());
1937 EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[0]->url());
1939 // Complete all the requests.
1940 resolver->pending_requests()[0]->results()->UseNamedProxy("request3:80");
1941 resolver->pending_requests()[0]->CompleteNow(OK);
1943 EXPECT_EQ(OK, callback3.WaitForResult());
1944 EXPECT_EQ("request3:80", info3.proxy_server().ToURI());
1946 EXPECT_TRUE(resolver->cancelled_requests().empty());
1948 EXPECT_FALSE(callback1.have_result()); // Cancelled.
1949 EXPECT_FALSE(callback2.have_result()); // Cancelled.
1951 CapturingNetLog::CapturedEntryList entries1;
1952 log1.GetEntries(&entries1);
1954 // Check the NetLog for request 1 (which was cancelled) got filled properly.
1955 EXPECT_EQ(4u, entries1.size());
1956 EXPECT_TRUE(LogContainsBeginEvent(
1957 entries1, 0, NetLog::TYPE_PROXY_SERVICE));
1958 EXPECT_TRUE(LogContainsBeginEvent(
1959 entries1, 1, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
1960 // Note that TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC is never completed before
1961 // the cancellation occured.
1962 EXPECT_TRUE(LogContainsEvent(
1963 entries1, 2, NetLog::TYPE_CANCELLED, NetLog::PHASE_NONE));
1964 EXPECT_TRUE(LogContainsEndEvent(
1965 entries1, 3, NetLog::TYPE_PROXY_SERVICE));
1968 // Test that if auto-detect fails, we fall-back to the custom pac.
1969 TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomPac) {
1970 ProxyConfig config;
1971 config.set_auto_detect(true);
1972 config.set_pac_url(GURL("http://foopy/proxy.pac"));
1973 config.proxy_rules().ParseFromString("http=foopy:80"); // Won't be used.
1975 MockProxyConfigService* config_service = new MockProxyConfigService(config);
1976 MockAsyncProxyResolverExpectsBytes* resolver =
1977 new MockAsyncProxyResolverExpectsBytes;
1978 ProxyService service(config_service, resolver, NULL);
1980 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1981 service.SetProxyScriptFetchers(fetcher,
1982 new DoNothingDhcpProxyScriptFetcher());
1984 // Start 2 requests.
1986 ProxyInfo info1;
1987 TestCompletionCallback callback1;
1988 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL,
1989 &info1, callback1.callback(), NULL, NULL,
1990 BoundNetLog());
1991 EXPECT_EQ(ERR_IO_PENDING, rv);
1993 ProxyInfo info2;
1994 TestCompletionCallback callback2;
1995 ProxyService::PacRequest* request2;
1996 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2,
1997 callback2.callback(), &request2, NULL,
1998 BoundNetLog());
1999 EXPECT_EQ(ERR_IO_PENDING, rv);
2001 // Check that nothing has been sent to the proxy resolver yet.
2002 ASSERT_EQ(0u, resolver->pending_requests().size());
2004 // It should be trying to auto-detect first -- FAIL the autodetect during
2005 // the script download.
2006 EXPECT_TRUE(fetcher->has_pending_request());
2007 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
2008 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
2010 // Next it should be trying the custom PAC url.
2011 EXPECT_TRUE(fetcher->has_pending_request());
2012 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2013 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2015 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2016 resolver->pending_set_pac_script_request()->script_data()->utf16());
2017 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2019 // Now finally, the pending requests should have been sent to the resolver
2020 // (which was initialized with custom PAC script).
2022 ASSERT_EQ(2u, resolver->pending_requests().size());
2023 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
2024 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url());
2026 // Complete the pending requests.
2027 resolver->pending_requests()[1]->results()->UseNamedProxy("request2:80");
2028 resolver->pending_requests()[1]->CompleteNow(OK);
2029 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2030 resolver->pending_requests()[0]->CompleteNow(OK);
2032 // Verify that requests ran as expected.
2033 EXPECT_EQ(OK, callback1.WaitForResult());
2034 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2035 EXPECT_FALSE(info1.proxy_resolve_start_time().is_null());
2036 EXPECT_FALSE(info1.proxy_resolve_end_time().is_null());
2037 EXPECT_LE(info1.proxy_resolve_start_time(), info1.proxy_resolve_end_time());
2039 EXPECT_EQ(OK, callback2.WaitForResult());
2040 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2041 EXPECT_FALSE(info2.proxy_resolve_start_time().is_null());
2042 EXPECT_FALSE(info2.proxy_resolve_end_time().is_null());
2043 EXPECT_LE(info2.proxy_resolve_start_time(), info2.proxy_resolve_end_time());
2046 // This is the same test as FallbackFromAutodetectToCustomPac, except
2047 // the auto-detect script fails parsing rather than downloading.
2048 TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomPac2) {
2049 ProxyConfig config;
2050 config.set_auto_detect(true);
2051 config.set_pac_url(GURL("http://foopy/proxy.pac"));
2052 config.proxy_rules().ParseFromString("http=foopy:80"); // Won't be used.
2054 MockProxyConfigService* config_service = new MockProxyConfigService(config);
2055 MockAsyncProxyResolverExpectsBytes* resolver =
2056 new MockAsyncProxyResolverExpectsBytes;
2057 ProxyService service(config_service, resolver, NULL);
2059 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2060 service.SetProxyScriptFetchers(fetcher,
2061 new DoNothingDhcpProxyScriptFetcher());
2063 // Start 2 requests.
2065 ProxyInfo info1;
2066 TestCompletionCallback callback1;
2067 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL,
2068 &info1, callback1.callback(), NULL, NULL,
2069 BoundNetLog());
2070 EXPECT_EQ(ERR_IO_PENDING, rv);
2072 ProxyInfo info2;
2073 TestCompletionCallback callback2;
2074 ProxyService::PacRequest* request2;
2075 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2,
2076 callback2.callback(), &request2, NULL,
2077 BoundNetLog());
2078 EXPECT_EQ(ERR_IO_PENDING, rv);
2080 // Check that nothing has been sent to the proxy resolver yet.
2081 ASSERT_EQ(0u, resolver->pending_requests().size());
2083 // It should be trying to auto-detect first -- succeed the download.
2084 EXPECT_TRUE(fetcher->has_pending_request());
2085 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
2086 fetcher->NotifyFetchCompletion(OK, "invalid-script-contents");
2088 // The script contents passed failed basic verification step (since didn't
2089 // contain token FindProxyForURL), so it was never passed to the resolver.
2091 // Next it should be trying the custom PAC url.
2092 EXPECT_TRUE(fetcher->has_pending_request());
2093 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2094 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2096 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2097 resolver->pending_set_pac_script_request()->script_data()->utf16());
2098 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2100 // Now finally, the pending requests should have been sent to the resolver
2101 // (which was initialized with custom PAC script).
2103 ASSERT_EQ(2u, resolver->pending_requests().size());
2104 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
2105 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url());
2107 // Complete the pending requests.
2108 resolver->pending_requests()[1]->results()->UseNamedProxy("request2:80");
2109 resolver->pending_requests()[1]->CompleteNow(OK);
2110 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2111 resolver->pending_requests()[0]->CompleteNow(OK);
2113 // Verify that requests ran as expected.
2114 EXPECT_EQ(OK, callback1.WaitForResult());
2115 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2117 EXPECT_EQ(OK, callback2.WaitForResult());
2118 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2121 // Test that if all of auto-detect, a custom PAC script, and manual settings
2122 // are given, then we will try them in that order.
2123 TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomToManual) {
2124 ProxyConfig config;
2125 config.set_auto_detect(true);
2126 config.set_pac_url(GURL("http://foopy/proxy.pac"));
2127 config.proxy_rules().ParseFromString("http=foopy:80");
2129 MockProxyConfigService* config_service = new MockProxyConfigService(config);
2130 MockAsyncProxyResolverExpectsBytes* resolver =
2131 new MockAsyncProxyResolverExpectsBytes;
2132 ProxyService service(config_service, resolver, NULL);
2134 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2135 service.SetProxyScriptFetchers(fetcher,
2136 new DoNothingDhcpProxyScriptFetcher());
2138 // Start 2 requests.
2140 ProxyInfo info1;
2141 TestCompletionCallback callback1;
2142 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL,
2143 &info1, callback1.callback(), NULL, NULL,
2144 BoundNetLog());
2145 EXPECT_EQ(ERR_IO_PENDING, rv);
2147 ProxyInfo info2;
2148 TestCompletionCallback callback2;
2149 ProxyService::PacRequest* request2;
2150 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2,
2151 callback2.callback(), &request2, NULL,
2152 BoundNetLog());
2153 EXPECT_EQ(ERR_IO_PENDING, rv);
2155 // Check that nothing has been sent to the proxy resolver yet.
2156 ASSERT_EQ(0u, resolver->pending_requests().size());
2158 // It should be trying to auto-detect first -- fail the download.
2159 EXPECT_TRUE(fetcher->has_pending_request());
2160 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
2161 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
2163 // Next it should be trying the custom PAC url -- fail the download.
2164 EXPECT_TRUE(fetcher->has_pending_request());
2165 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2166 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
2168 // Since we never managed to initialize a ProxyResolver, nothing should have
2169 // been sent to it.
2170 ASSERT_EQ(0u, resolver->pending_requests().size());
2172 // Verify that requests ran as expected -- they should have fallen back to
2173 // the manual proxy configuration for HTTP urls.
2174 EXPECT_EQ(OK, callback1.WaitForResult());
2175 EXPECT_EQ("foopy:80", info1.proxy_server().ToURI());
2177 EXPECT_EQ(OK, callback2.WaitForResult());
2178 EXPECT_EQ("foopy:80", info2.proxy_server().ToURI());
2181 // Test that the bypass rules are NOT applied when using autodetect.
2182 TEST_F(ProxyServiceTest, BypassDoesntApplyToPac) {
2183 ProxyConfig config;
2184 config.set_auto_detect(true);
2185 config.set_pac_url(GURL("http://foopy/proxy.pac"));
2186 config.proxy_rules().ParseFromString("http=foopy:80"); // Not used.
2187 config.proxy_rules().bypass_rules.ParseFromString("www.google.com");
2189 MockProxyConfigService* config_service = new MockProxyConfigService(config);
2190 MockAsyncProxyResolverExpectsBytes* resolver =
2191 new MockAsyncProxyResolverExpectsBytes;
2192 ProxyService service(config_service, resolver, NULL);
2194 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2195 service.SetProxyScriptFetchers(fetcher,
2196 new DoNothingDhcpProxyScriptFetcher());
2198 // Start 1 requests.
2200 ProxyInfo info1;
2201 TestCompletionCallback callback1;
2202 int rv = service.ResolveProxy(
2203 GURL("http://www.google.com"), net::LOAD_NORMAL, &info1,
2204 callback1.callback(), NULL, NULL, BoundNetLog());
2205 EXPECT_EQ(ERR_IO_PENDING, rv);
2207 // Check that nothing has been sent to the proxy resolver yet.
2208 ASSERT_EQ(0u, resolver->pending_requests().size());
2210 // It should be trying to auto-detect first -- succeed the download.
2211 EXPECT_TRUE(fetcher->has_pending_request());
2212 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
2213 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2215 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2216 resolver->pending_set_pac_script_request()->script_data()->utf16());
2217 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2219 ASSERT_EQ(1u, resolver->pending_requests().size());
2220 EXPECT_EQ(GURL("http://www.google.com"),
2221 resolver->pending_requests()[0]->url());
2223 // Complete the pending request.
2224 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2225 resolver->pending_requests()[0]->CompleteNow(OK);
2227 // Verify that request ran as expected.
2228 EXPECT_EQ(OK, callback1.WaitForResult());
2229 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2231 // Start another request, it should pickup the bypass item.
2232 ProxyInfo info2;
2233 TestCompletionCallback callback2;
2234 rv = service.ResolveProxy(GURL("http://www.google.com"), net::LOAD_NORMAL,
2235 &info2, callback2.callback(), NULL, NULL,
2236 BoundNetLog());
2237 EXPECT_EQ(ERR_IO_PENDING, rv);
2239 ASSERT_EQ(1u, resolver->pending_requests().size());
2240 EXPECT_EQ(GURL("http://www.google.com"),
2241 resolver->pending_requests()[0]->url());
2243 // Complete the pending request.
2244 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80");
2245 resolver->pending_requests()[0]->CompleteNow(OK);
2247 EXPECT_EQ(OK, callback2.WaitForResult());
2248 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2251 // Delete the ProxyService while InitProxyResolver has an outstanding
2252 // request to the script fetcher. When run under valgrind, should not
2253 // have any memory errors (used to be that the ProxyScriptFetcher was
2254 // being deleted prior to the InitProxyResolver).
2255 TEST_F(ProxyServiceTest, DeleteWhileInitProxyResolverHasOutstandingFetch) {
2256 ProxyConfig config =
2257 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"));
2259 MockProxyConfigService* config_service = new MockProxyConfigService(config);
2260 MockAsyncProxyResolverExpectsBytes* resolver =
2261 new MockAsyncProxyResolverExpectsBytes;
2262 ProxyService service(config_service, resolver, NULL);
2264 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2265 service.SetProxyScriptFetchers(fetcher,
2266 new DoNothingDhcpProxyScriptFetcher());
2268 // Start 1 request.
2270 ProxyInfo info1;
2271 TestCompletionCallback callback1;
2272 int rv = service.ResolveProxy(GURL("http://www.google.com"), net::LOAD_NORMAL,
2273 &info1, callback1.callback(), NULL, NULL,
2274 BoundNetLog());
2275 EXPECT_EQ(ERR_IO_PENDING, rv);
2277 // Check that nothing has been sent to the proxy resolver yet.
2278 ASSERT_EQ(0u, resolver->pending_requests().size());
2280 // InitProxyResolver should have issued a request to the ProxyScriptFetcher
2281 // and be waiting on that to complete.
2282 EXPECT_TRUE(fetcher->has_pending_request());
2283 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2286 // Delete the ProxyService while InitProxyResolver has an outstanding
2287 // request to the proxy resolver. When run under valgrind, should not
2288 // have any memory errors (used to be that the ProxyResolver was
2289 // being deleted prior to the InitProxyResolver).
2290 TEST_F(ProxyServiceTest, DeleteWhileInitProxyResolverHasOutstandingSet) {
2291 MockProxyConfigService* config_service =
2292 new MockProxyConfigService("http://foopy/proxy.pac");
2294 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
2296 ProxyService service(config_service, resolver, NULL);
2298 GURL url("http://www.google.com/");
2300 ProxyInfo info;
2301 TestCompletionCallback callback;
2302 int rv = service.ResolveProxy(
2303 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL,
2304 BoundNetLog());
2305 EXPECT_EQ(ERR_IO_PENDING, rv);
2307 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
2308 resolver->pending_set_pac_script_request()->script_data()->url());
2311 TEST_F(ProxyServiceTest, ResetProxyConfigService) {
2312 ProxyConfig config1;
2313 config1.proxy_rules().ParseFromString("foopy1:8080");
2314 config1.set_auto_detect(false);
2315 ProxyService service(
2316 new MockProxyConfigService(config1),
2317 new MockAsyncProxyResolverExpectsBytes, NULL);
2319 ProxyInfo info;
2320 TestCompletionCallback callback1;
2321 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL,
2322 &info, callback1.callback(), NULL, NULL,
2323 BoundNetLog());
2324 EXPECT_EQ(OK, rv);
2325 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
2327 ProxyConfig config2;
2328 config2.proxy_rules().ParseFromString("foopy2:8080");
2329 config2.set_auto_detect(false);
2330 service.ResetConfigService(new MockProxyConfigService(config2));
2331 TestCompletionCallback callback2;
2332 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info,
2333 callback2.callback(), NULL, NULL, BoundNetLog());
2334 EXPECT_EQ(OK, rv);
2335 EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI());
2338 // Test that when going from a configuration that required PAC to one
2339 // that does NOT, we unset the variable |should_use_proxy_resolver_|.
2340 TEST_F(ProxyServiceTest, UpdateConfigFromPACToDirect) {
2341 ProxyConfig config = ProxyConfig::CreateAutoDetect();
2343 MockProxyConfigService* config_service = new MockProxyConfigService(config);
2344 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
2345 ProxyService service(config_service, resolver, NULL);
2347 // Start 1 request.
2349 ProxyInfo info1;
2350 TestCompletionCallback callback1;
2351 int rv = service.ResolveProxy(GURL("http://www.google.com"), net::LOAD_NORMAL,
2352 &info1, callback1.callback(), NULL, NULL,
2353 BoundNetLog());
2354 EXPECT_EQ(ERR_IO_PENDING, rv);
2356 // Check that nothing has been sent to the proxy resolver yet.
2357 ASSERT_EQ(0u, resolver->pending_requests().size());
2359 // Successfully set the autodetect script.
2360 EXPECT_EQ(ProxyResolverScriptData::TYPE_AUTO_DETECT,
2361 resolver->pending_set_pac_script_request()->script_data()->type());
2362 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2364 // Complete the pending request.
2365 ASSERT_EQ(1u, resolver->pending_requests().size());
2366 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2367 resolver->pending_requests()[0]->CompleteNow(OK);
2369 // Verify that request ran as expected.
2370 EXPECT_EQ(OK, callback1.WaitForResult());
2371 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2373 // Force the ProxyService to pull down a new proxy configuration.
2374 // (Even though the configuration isn't old/bad).
2376 // This new configuration no longer has auto_detect set, so
2377 // requests should complete synchronously now as direct-connect.
2378 config_service->SetConfig(ProxyConfig::CreateDirect());
2380 // Start another request -- the effective configuration has changed.
2381 ProxyInfo info2;
2382 TestCompletionCallback callback2;
2383 rv = service.ResolveProxy(GURL("http://www.google.com"), net::LOAD_NORMAL,
2384 &info2, callback2.callback(), NULL, NULL,
2385 BoundNetLog());
2386 EXPECT_EQ(OK, rv);
2388 EXPECT_TRUE(info2.is_direct());
2391 TEST_F(ProxyServiceTest, NetworkChangeTriggersPacRefetch) {
2392 MockProxyConfigService* config_service =
2393 new MockProxyConfigService("http://foopy/proxy.pac");
2395 MockAsyncProxyResolverExpectsBytes* resolver =
2396 new MockAsyncProxyResolverExpectsBytes;
2398 CapturingNetLog log;
2400 ProxyService service(config_service, resolver, &log);
2402 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2403 service.SetProxyScriptFetchers(fetcher,
2404 new DoNothingDhcpProxyScriptFetcher());
2406 // Disable the "wait after IP address changes" hack, so this unit-test can
2407 // complete quickly.
2408 service.set_stall_proxy_auto_config_delay(base::TimeDelta());
2410 // Start 1 request.
2412 ProxyInfo info1;
2413 TestCompletionCallback callback1;
2414 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL,
2415 &info1, callback1.callback(), NULL, NULL,
2416 BoundNetLog());
2417 EXPECT_EQ(ERR_IO_PENDING, rv);
2419 // The first request should have triggered initial download of PAC script.
2420 EXPECT_TRUE(fetcher->has_pending_request());
2421 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2423 // Nothing has been sent to the resolver yet.
2424 EXPECT_TRUE(resolver->pending_requests().empty());
2426 // At this point the ProxyService should be waiting for the
2427 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2428 // PAC script download completion.
2429 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2431 // Now that the PAC script is downloaded, the request will have been sent to
2432 // the proxy resolver.
2433 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2434 resolver->pending_set_pac_script_request()->script_data()->utf16());
2435 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2437 ASSERT_EQ(1u, resolver->pending_requests().size());
2438 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
2440 // Complete the pending request.
2441 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2442 resolver->pending_requests()[0]->CompleteNow(OK);
2444 // Wait for completion callback, and verify that the request ran as expected.
2445 EXPECT_EQ(OK, callback1.WaitForResult());
2446 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2448 // Now simluate a change in the network. The ProxyConfigService is still
2449 // going to return the same PAC URL as before, but this URL needs to be
2450 // refetched on the new network.
2451 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
2452 base::MessageLoop::current()->RunUntilIdle(); // Notification happens async.
2454 // Start a second request.
2455 ProxyInfo info2;
2456 TestCompletionCallback callback2;
2457 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2,
2458 callback2.callback(), NULL, NULL, BoundNetLog());
2459 EXPECT_EQ(ERR_IO_PENDING, rv);
2461 // This second request should have triggered the re-download of the PAC
2462 // script (since we marked the network as having changed).
2463 EXPECT_TRUE(fetcher->has_pending_request());
2464 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2466 // Nothing has been sent to the resolver yet.
2467 EXPECT_TRUE(resolver->pending_requests().empty());
2469 // Simulate the PAC script fetch as having completed (this time with
2470 // different data).
2471 fetcher->NotifyFetchCompletion(OK, kValidPacScript2);
2473 // Now that the PAC script is downloaded, the second request will have been
2474 // sent to the proxy resolver.
2475 EXPECT_EQ(ASCIIToUTF16(kValidPacScript2),
2476 resolver->pending_set_pac_script_request()->script_data()->utf16());
2477 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2479 ASSERT_EQ(1u, resolver->pending_requests().size());
2480 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[0]->url());
2482 // Complete the pending second request.
2483 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80");
2484 resolver->pending_requests()[0]->CompleteNow(OK);
2486 // Wait for completion callback, and verify that the request ran as expected.
2487 EXPECT_EQ(OK, callback2.WaitForResult());
2488 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2490 // Check that the expected events were output to the log stream. In particular
2491 // PROXY_CONFIG_CHANGED should have only been emitted once (for the initial
2492 // setup), and NOT a second time when the IP address changed.
2493 CapturingNetLog::CapturedEntryList entries;
2494 log.GetEntries(&entries);
2496 EXPECT_TRUE(LogContainsEntryWithType(entries, 0,
2497 NetLog::TYPE_PROXY_CONFIG_CHANGED));
2498 ASSERT_EQ(9u, entries.size());
2499 for (size_t i = 1; i < entries.size(); ++i)
2500 EXPECT_NE(NetLog::TYPE_PROXY_CONFIG_CHANGED, entries[i].type);
2503 // This test verifies that the PAC script specified by the settings is
2504 // periodically polled for changes. Specifically, if the initial fetch fails due
2505 // to a network error, we will eventually re-configure the service to use the
2506 // script once it becomes available.
2507 TEST_F(ProxyServiceTest, PACScriptRefetchAfterFailure) {
2508 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2509 // runs quickly.
2510 ImmediatePollPolicy poll_policy;
2511 ProxyService::set_pac_script_poll_policy(&poll_policy);
2513 MockProxyConfigService* config_service =
2514 new MockProxyConfigService("http://foopy/proxy.pac");
2516 MockAsyncProxyResolverExpectsBytes* resolver =
2517 new MockAsyncProxyResolverExpectsBytes;
2519 ProxyService service(config_service, resolver, NULL);
2521 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2522 service.SetProxyScriptFetchers(fetcher,
2523 new DoNothingDhcpProxyScriptFetcher());
2525 // Start 1 request.
2527 ProxyInfo info1;
2528 TestCompletionCallback callback1;
2529 int rv = service.ResolveProxy(
2530 GURL("http://request1"), net::LOAD_NORMAL, &info1, callback1.callback(),
2531 NULL, NULL, BoundNetLog());
2532 EXPECT_EQ(ERR_IO_PENDING, rv);
2534 // The first request should have triggered initial download of PAC script.
2535 EXPECT_TRUE(fetcher->has_pending_request());
2536 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2538 // Nothing has been sent to the resolver yet.
2539 EXPECT_TRUE(resolver->pending_requests().empty());
2541 // At this point the ProxyService should be waiting for the
2542 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2543 // PAC script download completion.
2545 // We simulate a failed download attempt, the proxy service should now
2546 // fall-back to DIRECT connections.
2547 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
2549 ASSERT_TRUE(resolver->pending_requests().empty());
2551 // Wait for completion callback, and verify it used DIRECT.
2552 EXPECT_EQ(OK, callback1.WaitForResult());
2553 EXPECT_TRUE(info1.is_direct());
2555 // At this point we have initialized the proxy service using a PAC script,
2556 // however it failed and fell-back to DIRECT.
2558 // A background task to periodically re-check the PAC script for validity will
2559 // have been started. We will now wait for the next download attempt to start.
2561 // Note that we shouldn't have to wait long here, since our test enables a
2562 // special unit-test mode.
2563 fetcher->WaitUntilFetch();
2565 ASSERT_TRUE(resolver->pending_requests().empty());
2567 // Make sure that our background checker is trying to download the expected
2568 // PAC script (same one as before). This time we will simulate a successful
2569 // download of the script.
2570 EXPECT_TRUE(fetcher->has_pending_request());
2571 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2572 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2574 base::MessageLoop::current()->RunUntilIdle();
2576 // Now that the PAC script is downloaded, it should be used to initialize the
2577 // ProxyResolver. Simulate a successful parse.
2578 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2579 resolver->pending_set_pac_script_request()->script_data()->utf16());
2580 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2582 // At this point the ProxyService should have re-configured itself to use the
2583 // PAC script (thereby recovering from the initial fetch failure). We will
2584 // verify that the next Resolve request uses the resolver rather than
2585 // DIRECT.
2587 // Start a second request.
2588 ProxyInfo info2;
2589 TestCompletionCallback callback2;
2590 rv = service.ResolveProxy(
2591 GURL("http://request2"), net::LOAD_NORMAL, &info2, callback2.callback(),
2592 NULL, NULL, BoundNetLog());
2593 EXPECT_EQ(ERR_IO_PENDING, rv);
2595 // Check that it was sent to the resolver.
2596 ASSERT_EQ(1u, resolver->pending_requests().size());
2597 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[0]->url());
2599 // Complete the pending second request.
2600 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80");
2601 resolver->pending_requests()[0]->CompleteNow(OK);
2603 // Wait for completion callback, and verify that the request ran as expected.
2604 EXPECT_EQ(OK, callback2.WaitForResult());
2605 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2608 // This test verifies that the PAC script specified by the settings is
2609 // periodically polled for changes. Specifically, if the initial fetch succeeds,
2610 // however at a later time its *contents* change, we will eventually
2611 // re-configure the service to use the new script.
2612 TEST_F(ProxyServiceTest, PACScriptRefetchAfterContentChange) {
2613 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2614 // runs quickly.
2615 ImmediatePollPolicy poll_policy;
2616 ProxyService::set_pac_script_poll_policy(&poll_policy);
2618 MockProxyConfigService* config_service =
2619 new MockProxyConfigService("http://foopy/proxy.pac");
2621 MockAsyncProxyResolverExpectsBytes* resolver =
2622 new MockAsyncProxyResolverExpectsBytes;
2624 ProxyService service(config_service, resolver, NULL);
2626 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2627 service.SetProxyScriptFetchers(fetcher,
2628 new DoNothingDhcpProxyScriptFetcher());
2630 // Start 1 request.
2632 ProxyInfo info1;
2633 TestCompletionCallback callback1;
2634 int rv = service.ResolveProxy(
2635 GURL("http://request1"), net::LOAD_NORMAL, &info1, callback1.callback(),
2636 NULL, NULL, BoundNetLog());
2637 EXPECT_EQ(ERR_IO_PENDING, rv);
2639 // The first request should have triggered initial download of PAC script.
2640 EXPECT_TRUE(fetcher->has_pending_request());
2641 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2643 // Nothing has been sent to the resolver yet.
2644 EXPECT_TRUE(resolver->pending_requests().empty());
2646 // At this point the ProxyService should be waiting for the
2647 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2648 // PAC script download completion.
2649 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2651 // Now that the PAC script is downloaded, the request will have been sent to
2652 // the proxy resolver.
2653 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2654 resolver->pending_set_pac_script_request()->script_data()->utf16());
2655 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2657 ASSERT_EQ(1u, resolver->pending_requests().size());
2658 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
2660 // Complete the pending request.
2661 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2662 resolver->pending_requests()[0]->CompleteNow(OK);
2664 // Wait for completion callback, and verify that the request ran as expected.
2665 EXPECT_EQ(OK, callback1.WaitForResult());
2666 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2668 // At this point we have initialized the proxy service using a PAC script.
2670 // A background task to periodically re-check the PAC script for validity will
2671 // have been started. We will now wait for the next download attempt to start.
2673 // Note that we shouldn't have to wait long here, since our test enables a
2674 // special unit-test mode.
2675 fetcher->WaitUntilFetch();
2677 ASSERT_TRUE(resolver->pending_requests().empty());
2679 // Make sure that our background checker is trying to download the expected
2680 // PAC script (same one as before). This time we will simulate a successful
2681 // download of a DIFFERENT script.
2682 EXPECT_TRUE(fetcher->has_pending_request());
2683 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2684 fetcher->NotifyFetchCompletion(OK, kValidPacScript2);
2686 base::MessageLoop::current()->RunUntilIdle();
2688 // Now that the PAC script is downloaded, it should be used to initialize the
2689 // ProxyResolver. Simulate a successful parse.
2690 EXPECT_EQ(ASCIIToUTF16(kValidPacScript2),
2691 resolver->pending_set_pac_script_request()->script_data()->utf16());
2692 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2694 // At this point the ProxyService should have re-configured itself to use the
2695 // new PAC script.
2697 // Start a second request.
2698 ProxyInfo info2;
2699 TestCompletionCallback callback2;
2700 rv = service.ResolveProxy(
2701 GURL("http://request2"), net::LOAD_NORMAL, &info2, callback2.callback(),
2702 NULL, NULL, BoundNetLog());
2703 EXPECT_EQ(ERR_IO_PENDING, rv);
2705 // Check that it was sent to the resolver.
2706 ASSERT_EQ(1u, resolver->pending_requests().size());
2707 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[0]->url());
2709 // Complete the pending second request.
2710 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80");
2711 resolver->pending_requests()[0]->CompleteNow(OK);
2713 // Wait for completion callback, and verify that the request ran as expected.
2714 EXPECT_EQ(OK, callback2.WaitForResult());
2715 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2718 // This test verifies that the PAC script specified by the settings is
2719 // periodically polled for changes. Specifically, if the initial fetch succeeds
2720 // and so does the next poll, however the contents of the downloaded script
2721 // have NOT changed, then we do not bother to re-initialize the proxy resolver.
2722 TEST_F(ProxyServiceTest, PACScriptRefetchAfterContentUnchanged) {
2723 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2724 // runs quickly.
2725 ImmediatePollPolicy poll_policy;
2726 ProxyService::set_pac_script_poll_policy(&poll_policy);
2728 MockProxyConfigService* config_service =
2729 new MockProxyConfigService("http://foopy/proxy.pac");
2731 MockAsyncProxyResolverExpectsBytes* resolver =
2732 new MockAsyncProxyResolverExpectsBytes;
2734 ProxyService service(config_service, resolver, NULL);
2736 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2737 service.SetProxyScriptFetchers(fetcher,
2738 new DoNothingDhcpProxyScriptFetcher());
2740 // Start 1 request.
2742 ProxyInfo info1;
2743 TestCompletionCallback callback1;
2744 int rv = service.ResolveProxy(
2745 GURL("http://request1"), net::LOAD_NORMAL, &info1, callback1.callback(),
2746 NULL, NULL, BoundNetLog());
2747 EXPECT_EQ(ERR_IO_PENDING, rv);
2749 // The first request should have triggered initial download of PAC script.
2750 EXPECT_TRUE(fetcher->has_pending_request());
2751 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2753 // Nothing has been sent to the resolver yet.
2754 EXPECT_TRUE(resolver->pending_requests().empty());
2756 // At this point the ProxyService should be waiting for the
2757 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2758 // PAC script download completion.
2759 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2761 // Now that the PAC script is downloaded, the request will have been sent to
2762 // the proxy resolver.
2763 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2764 resolver->pending_set_pac_script_request()->script_data()->utf16());
2765 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2767 ASSERT_EQ(1u, resolver->pending_requests().size());
2768 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
2770 // Complete the pending request.
2771 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2772 resolver->pending_requests()[0]->CompleteNow(OK);
2774 // Wait for completion callback, and verify that the request ran as expected.
2775 EXPECT_EQ(OK, callback1.WaitForResult());
2776 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2778 // At this point we have initialized the proxy service using a PAC script.
2780 // A background task to periodically re-check the PAC script for validity will
2781 // have been started. We will now wait for the next download attempt to start.
2783 // Note that we shouldn't have to wait long here, since our test enables a
2784 // special unit-test mode.
2785 fetcher->WaitUntilFetch();
2787 ASSERT_TRUE(resolver->pending_requests().empty());
2789 // Make sure that our background checker is trying to download the expected
2790 // PAC script (same one as before). We will simulate the same response as
2791 // last time (i.e. the script is unchanged).
2792 EXPECT_TRUE(fetcher->has_pending_request());
2793 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2794 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2796 base::MessageLoop::current()->RunUntilIdle();
2798 ASSERT_FALSE(resolver->has_pending_set_pac_script_request());
2800 // At this point the ProxyService is still running the same PAC script as
2801 // before.
2803 // Start a second request.
2804 ProxyInfo info2;
2805 TestCompletionCallback callback2;
2806 rv = service.ResolveProxy(
2807 GURL("http://request2"), net::LOAD_NORMAL, &info2, callback2.callback(),
2808 NULL, NULL, BoundNetLog());
2809 EXPECT_EQ(ERR_IO_PENDING, rv);
2811 // Check that it was sent to the resolver.
2812 ASSERT_EQ(1u, resolver->pending_requests().size());
2813 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[0]->url());
2815 // Complete the pending second request.
2816 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80");
2817 resolver->pending_requests()[0]->CompleteNow(OK);
2819 // Wait for completion callback, and verify that the request ran as expected.
2820 EXPECT_EQ(OK, callback2.WaitForResult());
2821 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2824 // This test verifies that the PAC script specified by the settings is
2825 // periodically polled for changes. Specifically, if the initial fetch succeeds,
2826 // however at a later time it starts to fail, we should re-configure the
2827 // ProxyService to stop using that PAC script.
2828 TEST_F(ProxyServiceTest, PACScriptRefetchAfterSuccess) {
2829 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2830 // runs quickly.
2831 ImmediatePollPolicy poll_policy;
2832 ProxyService::set_pac_script_poll_policy(&poll_policy);
2834 MockProxyConfigService* config_service =
2835 new MockProxyConfigService("http://foopy/proxy.pac");
2837 MockAsyncProxyResolverExpectsBytes* resolver =
2838 new MockAsyncProxyResolverExpectsBytes;
2840 ProxyService service(config_service, resolver, NULL);
2842 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2843 service.SetProxyScriptFetchers(fetcher,
2844 new DoNothingDhcpProxyScriptFetcher());
2846 // Start 1 request.
2848 ProxyInfo info1;
2849 TestCompletionCallback callback1;
2850 int rv = service.ResolveProxy(
2851 GURL("http://request1"), net::LOAD_NORMAL, &info1, callback1.callback(),
2852 NULL, NULL, BoundNetLog());
2853 EXPECT_EQ(ERR_IO_PENDING, rv);
2855 // The first request should have triggered initial download of PAC script.
2856 EXPECT_TRUE(fetcher->has_pending_request());
2857 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2859 // Nothing has been sent to the resolver yet.
2860 EXPECT_TRUE(resolver->pending_requests().empty());
2862 // At this point the ProxyService should be waiting for the
2863 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2864 // PAC script download completion.
2865 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2867 // Now that the PAC script is downloaded, the request will have been sent to
2868 // the proxy resolver.
2869 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2870 resolver->pending_set_pac_script_request()->script_data()->utf16());
2871 resolver->pending_set_pac_script_request()->CompleteNow(OK);
2873 ASSERT_EQ(1u, resolver->pending_requests().size());
2874 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
2876 // Complete the pending request.
2877 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
2878 resolver->pending_requests()[0]->CompleteNow(OK);
2880 // Wait for completion callback, and verify that the request ran as expected.
2881 EXPECT_EQ(OK, callback1.WaitForResult());
2882 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2884 // At this point we have initialized the proxy service using a PAC script.
2886 // A background task to periodically re-check the PAC script for validity will
2887 // have been started. We will now wait for the next download attempt to start.
2889 // Note that we shouldn't have to wait long here, since our test enables a
2890 // special unit-test mode.
2891 fetcher->WaitUntilFetch();
2893 ASSERT_TRUE(resolver->pending_requests().empty());
2895 // Make sure that our background checker is trying to download the expected
2896 // PAC script (same one as before). This time we will simulate a failure
2897 // to download the script.
2898 EXPECT_TRUE(fetcher->has_pending_request());
2899 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2900 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
2902 base::MessageLoop::current()->RunUntilIdle();
2904 // At this point the ProxyService should have re-configured itself to use
2905 // DIRECT connections rather than the given proxy resolver.
2907 // Start a second request.
2908 ProxyInfo info2;
2909 TestCompletionCallback callback2;
2910 rv = service.ResolveProxy(
2911 GURL("http://request2"), net::LOAD_NORMAL, &info2, callback2.callback(),
2912 NULL, NULL, BoundNetLog());
2913 EXPECT_EQ(OK, rv);
2914 EXPECT_TRUE(info2.is_direct());
2917 // Tests that the code which decides at what times to poll the PAC
2918 // script follows the expected policy.
2919 TEST_F(ProxyServiceTest, PACScriptPollingPolicy) {
2920 // Retrieve the internal polling policy implementation used by ProxyService.
2921 scoped_ptr<ProxyService::PacPollPolicy> policy =
2922 ProxyService::CreateDefaultPacPollPolicy();
2924 int error;
2925 ProxyService::PacPollPolicy::Mode mode;
2926 const base::TimeDelta initial_delay = base::TimeDelta::FromMilliseconds(-1);
2927 base::TimeDelta delay = initial_delay;
2929 // --------------------------------------------------
2930 // Test the poll sequence in response to a failure.
2931 // --------------------------------------------------
2932 error = ERR_NAME_NOT_RESOLVED;
2934 // Poll #0
2935 mode = policy->GetNextDelay(error, initial_delay, &delay);
2936 EXPECT_EQ(8, delay.InSeconds());
2937 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_USE_TIMER, mode);
2939 // Poll #1
2940 mode = policy->GetNextDelay(error, delay, &delay);
2941 EXPECT_EQ(32, delay.InSeconds());
2942 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2944 // Poll #2
2945 mode = policy->GetNextDelay(error, delay, &delay);
2946 EXPECT_EQ(120, delay.InSeconds());
2947 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2949 // Poll #3
2950 mode = policy->GetNextDelay(error, delay, &delay);
2951 EXPECT_EQ(14400, delay.InSeconds());
2952 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2954 // Poll #4
2955 mode = policy->GetNextDelay(error, delay, &delay);
2956 EXPECT_EQ(14400, delay.InSeconds());
2957 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2959 // --------------------------------------------------
2960 // Test the poll sequence in response to a success.
2961 // --------------------------------------------------
2962 error = OK;
2964 // Poll #0
2965 mode = policy->GetNextDelay(error, initial_delay, &delay);
2966 EXPECT_EQ(43200, delay.InSeconds());
2967 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2969 // Poll #1
2970 mode = policy->GetNextDelay(error, delay, &delay);
2971 EXPECT_EQ(43200, delay.InSeconds());
2972 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2974 // Poll #2
2975 mode = policy->GetNextDelay(error, delay, &delay);
2976 EXPECT_EQ(43200, delay.InSeconds());
2977 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
2980 // This tests the polling of the PAC script. Specifically, it tests that
2981 // polling occurs in response to user activity.
2982 TEST_F(ProxyServiceTest, PACScriptRefetchAfterActivity) {
2983 ImmediateAfterActivityPollPolicy poll_policy;
2984 ProxyService::set_pac_script_poll_policy(&poll_policy);
2986 MockProxyConfigService* config_service =
2987 new MockProxyConfigService("http://foopy/proxy.pac");
2989 MockAsyncProxyResolverExpectsBytes* resolver =
2990 new MockAsyncProxyResolverExpectsBytes;
2992 ProxyService service(config_service, resolver, NULL);
2994 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2995 service.SetProxyScriptFetchers(fetcher,
2996 new DoNothingDhcpProxyScriptFetcher());
2998 // Start 1 request.
3000 ProxyInfo info1;
3001 TestCompletionCallback callback1;
3002 int rv = service.ResolveProxy(
3003 GURL("http://request1"), net::LOAD_NORMAL, &info1, callback1.callback(),
3004 NULL, NULL, BoundNetLog());
3005 EXPECT_EQ(ERR_IO_PENDING, rv);
3007 // The first request should have triggered initial download of PAC script.
3008 EXPECT_TRUE(fetcher->has_pending_request());
3009 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
3011 // Nothing has been sent to the resolver yet.
3012 EXPECT_TRUE(resolver->pending_requests().empty());
3014 // At this point the ProxyService should be waiting for the
3015 // ProxyScriptFetcher to invoke its completion callback, notifying it of
3016 // PAC script download completion.
3017 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
3019 // Now that the PAC script is downloaded, the request will have been sent to
3020 // the proxy resolver.
3021 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
3022 resolver->pending_set_pac_script_request()->script_data()->utf16());
3023 resolver->pending_set_pac_script_request()->CompleteNow(OK);
3025 ASSERT_EQ(1u, resolver->pending_requests().size());
3026 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
3028 // Complete the pending request.
3029 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
3030 resolver->pending_requests()[0]->CompleteNow(OK);
3032 // Wait for completion callback, and verify that the request ran as expected.
3033 EXPECT_EQ(OK, callback1.WaitForResult());
3034 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
3036 // At this point we have initialized the proxy service using a PAC script.
3037 // Our PAC poller is set to update ONLY in response to network activity,
3038 // (i.e. another call to ResolveProxy()).
3040 ASSERT_FALSE(fetcher->has_pending_request());
3041 ASSERT_TRUE(resolver->pending_requests().empty());
3043 // Start a second request.
3044 ProxyInfo info2;
3045 TestCompletionCallback callback2;
3046 rv = service.ResolveProxy(
3047 GURL("http://request2"), net::LOAD_NORMAL, &info2, callback2.callback(),
3048 NULL, NULL, BoundNetLog());
3049 EXPECT_EQ(ERR_IO_PENDING, rv);
3051 // This request should have sent work to the resolver; complete it.
3052 ASSERT_EQ(1u, resolver->pending_requests().size());
3053 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[0]->url());
3054 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80");
3055 resolver->pending_requests()[0]->CompleteNow(OK);
3057 EXPECT_EQ(OK, callback2.WaitForResult());
3058 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
3060 // In response to getting that resolve request, the poller should have
3061 // started the next poll, and made it as far as to request the download.
3063 EXPECT_TRUE(fetcher->has_pending_request());
3064 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
3066 // This time we will fail the download, to simulate a PAC script change.
3067 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
3069 // Drain the message loop, so ProxyService is notified of the change
3070 // and has a chance to re-configure itself.
3071 base::MessageLoop::current()->RunUntilIdle();
3073 // Start a third request -- this time we expect to get a direct connection
3074 // since the PAC script poller experienced a failure.
3075 ProxyInfo info3;
3076 TestCompletionCallback callback3;
3077 rv = service.ResolveProxy(
3078 GURL("http://request3"), net::LOAD_NORMAL, &info3, callback3.callback(),
3079 NULL, NULL, BoundNetLog());
3080 EXPECT_EQ(OK, rv);
3081 EXPECT_TRUE(info3.is_direct());
3084 } // namespace net