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"
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/network_delegate_impl.h"
16 #include "net/base/test_completion_callback.h"
17 #include "net/log/net_log.h"
18 #include "net/log/net_log_unittest.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"
28 using base::ASCIIToUTF16
;
30 // TODO(eroman): Write a test which exercises
31 // ProxyService::SuspendAllPendingRequests().
35 // This polling policy will decide to poll every 1 ms.
36 class ImmediatePollPolicy
: public ProxyService::PacPollPolicy
{
38 ImmediatePollPolicy() {}
40 Mode
GetNextDelay(int error
,
41 base::TimeDelta current_delay
,
42 base::TimeDelta
* next_delay
) const override
{
43 *next_delay
= base::TimeDelta::FromMilliseconds(1);
44 return MODE_USE_TIMER
;
48 DISALLOW_COPY_AND_ASSIGN(ImmediatePollPolicy
);
51 // This polling policy chooses a fantastically large delay. In other words, it
52 // will never trigger a poll
53 class NeverPollPolicy
: public ProxyService::PacPollPolicy
{
57 Mode
GetNextDelay(int error
,
58 base::TimeDelta current_delay
,
59 base::TimeDelta
* next_delay
) const override
{
60 *next_delay
= base::TimeDelta::FromDays(60);
61 return MODE_USE_TIMER
;
65 DISALLOW_COPY_AND_ASSIGN(NeverPollPolicy
);
68 // This polling policy starts a poll immediately after network activity.
69 class ImmediateAfterActivityPollPolicy
: public ProxyService::PacPollPolicy
{
71 ImmediateAfterActivityPollPolicy() {}
73 Mode
GetNextDelay(int error
,
74 base::TimeDelta current_delay
,
75 base::TimeDelta
* next_delay
) const override
{
76 *next_delay
= base::TimeDelta();
77 return MODE_START_AFTER_ACTIVITY
;
81 DISALLOW_COPY_AND_ASSIGN(ImmediateAfterActivityPollPolicy
);
84 // This test fixture is used to partially disable the background polling done by
85 // the ProxyService (which it uses to detect whenever its PAC script contents or
86 // WPAD results have changed).
88 // We disable the feature by setting the poll interval to something really
89 // large, so it will never actually be reached even on the slowest bots that run
92 // We disable the polling in order to avoid any timing dependencies in the
93 // tests. If the bot were to run the tests very slowly and we hadn't disabled
94 // polling, then it might start a background re-try in the middle of our test
95 // and confuse our expectations leading to flaky failures.
97 // The tests which verify the polling code re-enable the polling behavior but
98 // are careful to avoid timing problems.
99 class ProxyServiceTest
: public testing::Test
{
101 void SetUp() override
{
102 testing::Test::SetUp();
104 ProxyService::set_pac_script_poll_policy(&never_poll_policy_
);
107 void TearDown() override
{
108 // Restore the original policy.
109 ProxyService::set_pac_script_poll_policy(previous_policy_
);
110 testing::Test::TearDown();
114 NeverPollPolicy never_poll_policy_
;
115 const ProxyService::PacPollPolicy
* previous_policy_
;
118 const char kValidPacScript1
[] = "pac-script-v1-FindProxyForURL";
119 const char kValidPacScript2
[] = "pac-script-v2-FindProxyForURL";
121 class MockProxyConfigService
: public ProxyConfigService
{
123 explicit MockProxyConfigService(const ProxyConfig
& config
)
124 : availability_(CONFIG_VALID
),
128 explicit MockProxyConfigService(const std::string
& pac_url
)
129 : availability_(CONFIG_VALID
),
130 config_(ProxyConfig::CreateFromCustomPacURL(GURL(pac_url
))) {
133 void AddObserver(Observer
* observer
) override
{
134 observers_
.AddObserver(observer
);
137 void RemoveObserver(Observer
* observer
) override
{
138 observers_
.RemoveObserver(observer
);
141 ConfigAvailability
GetLatestProxyConfig(ProxyConfig
* results
) override
{
142 if (availability_
== CONFIG_VALID
)
144 return availability_
;
147 void SetConfig(const ProxyConfig
& config
) {
148 availability_
= CONFIG_VALID
;
150 FOR_EACH_OBSERVER(Observer
, observers_
,
151 OnProxyConfigChanged(config_
, availability_
));
155 ConfigAvailability availability_
;
157 ObserverList
<Observer
, true> observers_
;
160 // A test network delegate that exercises the OnResolveProxy callback.
161 class TestResolveProxyNetworkDelegate
: public NetworkDelegateImpl
{
163 TestResolveProxyNetworkDelegate()
164 : on_resolve_proxy_called_(false),
166 remove_proxy_(false),
167 proxy_service_(NULL
) {
170 void OnResolveProxy(const GURL
& url
,
172 const ProxyService
& proxy_service
,
173 ProxyInfo
* result
) override
{
174 on_resolve_proxy_called_
= true;
175 proxy_service_
= &proxy_service
;
176 DCHECK(!add_proxy_
|| !remove_proxy_
);
178 result
->UseNamedProxy("delegate_proxy.com");
179 } else if (remove_proxy_
) {
184 bool on_resolve_proxy_called() const {
185 return on_resolve_proxy_called_
;
188 void set_add_proxy(bool add_proxy
) {
189 add_proxy_
= add_proxy
;
192 void set_remove_proxy(bool remove_proxy
) {
193 remove_proxy_
= remove_proxy
;
196 const ProxyService
* proxy_service() const {
197 return proxy_service_
;
201 bool on_resolve_proxy_called_
;
204 const ProxyService
* proxy_service_
;
207 // A test network delegate that exercises the OnProxyFallback callback.
208 class TestProxyFallbackNetworkDelegate
: public NetworkDelegateImpl
{
210 TestProxyFallbackNetworkDelegate()
211 : on_proxy_fallback_called_(false),
212 proxy_fallback_net_error_(OK
) {
215 void OnProxyFallback(const ProxyServer
& proxy_server
,
216 int net_error
) override
{
217 proxy_server_
= proxy_server
;
218 proxy_fallback_net_error_
= net_error
;
219 on_proxy_fallback_called_
= true;
222 bool on_proxy_fallback_called() const {
223 return on_proxy_fallback_called_
;
226 const ProxyServer
& proxy_server() const {
227 return proxy_server_
;
230 int proxy_fallback_net_error() const {
231 return proxy_fallback_net_error_
;
235 bool on_proxy_fallback_called_
;
236 ProxyServer proxy_server_
;
237 int proxy_fallback_net_error_
;
242 TEST_F(ProxyServiceTest
, Direct
) {
243 MockAsyncProxyResolver resolver
;
244 ProxyService
service(
245 new MockProxyConfigService(ProxyConfig::CreateDirect()),
246 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
248 GURL
url("http://www.google.com/");
251 TestCompletionCallback callback
;
253 int rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info
, callback
.callback(),
254 NULL
, NULL
, log
.bound());
256 EXPECT_TRUE(resolver
.pending_requests().empty());
258 EXPECT_TRUE(info
.is_direct());
259 EXPECT_TRUE(info
.proxy_resolve_start_time().is_null());
260 EXPECT_TRUE(info
.proxy_resolve_end_time().is_null());
262 // Check the NetLog was filled correctly.
263 TestNetLog::CapturedEntryList entries
;
264 log
.GetEntries(&entries
);
266 EXPECT_EQ(3u, entries
.size());
267 EXPECT_TRUE(LogContainsBeginEvent(
268 entries
, 0, NetLog::TYPE_PROXY_SERVICE
));
269 EXPECT_TRUE(LogContainsEvent(
270 entries
, 1, NetLog::TYPE_PROXY_SERVICE_RESOLVED_PROXY_LIST
,
271 NetLog::PHASE_NONE
));
272 EXPECT_TRUE(LogContainsEndEvent(
273 entries
, 2, NetLog::TYPE_PROXY_SERVICE
));
276 TEST_F(ProxyServiceTest
, OnResolveProxyCallbackAddProxy
) {
278 config
.proxy_rules().ParseFromString("foopy1:8080");
279 config
.set_auto_detect(false);
280 config
.proxy_rules().bypass_rules
.ParseFromString("*.org");
282 ProxyService
service(new MockProxyConfigService(config
), nullptr, NULL
);
284 GURL
url("http://www.google.com/");
285 GURL
bypass_url("http://internet.org");
288 TestCompletionCallback callback
;
291 // First, warm up the ProxyService.
292 int rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info
, callback
.callback(),
293 NULL
, NULL
, log
.bound());
296 // Verify that network delegate is invoked.
297 TestResolveProxyNetworkDelegate delegate
;
298 rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info
, callback
.callback(), NULL
,
299 &delegate
, log
.bound());
300 EXPECT_TRUE(delegate
.on_resolve_proxy_called());
301 EXPECT_EQ(&service
, delegate
.proxy_service());
303 // Verify that the NetworkDelegate's behavior is stateless across
304 // invocations of ResolveProxy. Start by having the callback add a proxy
305 // and checking that subsequent requests are not affected.
306 delegate
.set_add_proxy(true);
308 // Callback should interpose:
309 rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info
, callback
.callback(), NULL
,
310 &delegate
, log
.bound());
311 EXPECT_FALSE(info
.is_direct());
312 EXPECT_EQ(info
.proxy_server().host_port_pair().host(), "delegate_proxy.com");
313 delegate
.set_add_proxy(false);
315 // Check non-bypassed URL:
316 rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info
, callback
.callback(), NULL
,
317 &delegate
, log
.bound());
318 EXPECT_FALSE(info
.is_direct());
319 EXPECT_EQ(info
.proxy_server().host_port_pair().host(), "foopy1");
321 // Check bypassed URL:
322 rv
= service
.ResolveProxy(bypass_url
, LOAD_NORMAL
, &info
, callback
.callback(),
323 NULL
, &delegate
, log
.bound());
324 EXPECT_TRUE(info
.is_direct());
327 TEST_F(ProxyServiceTest
, OnResolveProxyCallbackRemoveProxy
) {
328 // Same as OnResolveProxyCallbackAddProxy, but verify that the
329 // NetworkDelegate's behavior is stateless across invocations after it
330 // *removes* a proxy.
332 config
.proxy_rules().ParseFromString("foopy1:8080");
333 config
.set_auto_detect(false);
334 config
.proxy_rules().bypass_rules
.ParseFromString("*.org");
336 ProxyService
service(new MockProxyConfigService(config
), nullptr, NULL
);
338 GURL
url("http://www.google.com/");
339 GURL
bypass_url("http://internet.org");
342 TestCompletionCallback callback
;
345 // First, warm up the ProxyService.
346 int rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info
, callback
.callback(),
347 NULL
, NULL
, log
.bound());
350 TestResolveProxyNetworkDelegate delegate
;
351 delegate
.set_remove_proxy(true);
353 // Callback should interpose:
354 rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info
, callback
.callback(), NULL
,
355 &delegate
, log
.bound());
356 EXPECT_TRUE(info
.is_direct());
357 delegate
.set_remove_proxy(false);
359 // Check non-bypassed URL:
360 rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info
, callback
.callback(), NULL
,
361 &delegate
, log
.bound());
362 EXPECT_FALSE(info
.is_direct());
363 EXPECT_EQ(info
.proxy_server().host_port_pair().host(), "foopy1");
365 // Check bypassed URL:
366 rv
= service
.ResolveProxy(bypass_url
, LOAD_NORMAL
, &info
, callback
.callback(),
367 NULL
, &delegate
, log
.bound());
368 EXPECT_TRUE(info
.is_direct());
371 TEST_F(ProxyServiceTest
, PAC
) {
372 MockProxyConfigService
* config_service
=
373 new MockProxyConfigService("http://foopy/proxy.pac");
375 MockAsyncProxyResolver resolver
;
377 ProxyService
service(
379 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
381 GURL
url("http://www.google.com/");
384 TestCompletionCallback callback
;
385 ProxyService::PacRequest
* request
;
388 int rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info
, callback
.callback(),
389 &request
, NULL
, log
.bound());
390 EXPECT_EQ(ERR_IO_PENDING
, rv
);
392 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL
, service
.GetLoadState(request
));
394 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
395 resolver
.pending_set_pac_script_request()->script_data()->url());
396 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
398 ASSERT_EQ(1u, resolver
.pending_requests().size());
399 EXPECT_EQ(url
, resolver
.pending_requests()[0]->url());
401 // Set the result in proxy resolver.
402 resolver
.pending_requests()[0]->results()->UseNamedProxy("foopy");
403 resolver
.pending_requests()[0]->CompleteNow(OK
);
405 EXPECT_EQ(OK
, callback
.WaitForResult());
406 EXPECT_FALSE(info
.is_direct());
407 EXPECT_EQ("foopy:80", info
.proxy_server().ToURI());
408 EXPECT_TRUE(info
.did_use_pac_script());
410 EXPECT_FALSE(info
.proxy_resolve_start_time().is_null());
411 EXPECT_FALSE(info
.proxy_resolve_end_time().is_null());
412 EXPECT_LE(info
.proxy_resolve_start_time(), info
.proxy_resolve_end_time());
414 // Check the NetLog was filled correctly.
415 TestNetLog::CapturedEntryList entries
;
416 log
.GetEntries(&entries
);
418 EXPECT_EQ(5u, entries
.size());
419 EXPECT_TRUE(LogContainsBeginEvent(
420 entries
, 0, NetLog::TYPE_PROXY_SERVICE
));
421 EXPECT_TRUE(LogContainsBeginEvent(
422 entries
, 1, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC
));
423 EXPECT_TRUE(LogContainsEndEvent(
424 entries
, 2, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC
));
425 EXPECT_TRUE(LogContainsEndEvent(
426 entries
, 4, NetLog::TYPE_PROXY_SERVICE
));
429 // Test that the proxy resolver does not see the URL's username/password
430 // or its reference section.
431 TEST_F(ProxyServiceTest
, PAC_NoIdentityOrHash
) {
432 MockProxyConfigService
* config_service
=
433 new MockProxyConfigService("http://foopy/proxy.pac");
435 MockAsyncProxyResolver resolver
;
437 ProxyService
service(
439 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
441 GURL
url("http://username:password@www.google.com/?ref#hash#hash");
444 TestCompletionCallback callback
;
445 int rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info
, callback
.callback(),
446 NULL
, NULL
, BoundNetLog());
447 EXPECT_EQ(ERR_IO_PENDING
, rv
);
449 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
450 resolver
.pending_set_pac_script_request()->script_data()->url());
451 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
453 ASSERT_EQ(1u, resolver
.pending_requests().size());
454 // The URL should have been simplified, stripping the username/password/hash.
455 EXPECT_EQ(GURL("http://www.google.com/?ref"),
456 resolver
.pending_requests()[0]->url());
458 // We end here without ever completing the request -- destruction of
459 // ProxyService will cancel the outstanding request.
462 TEST_F(ProxyServiceTest
, PAC_FailoverWithoutDirect
) {
463 MockProxyConfigService
* config_service
=
464 new MockProxyConfigService("http://foopy/proxy.pac");
465 MockAsyncProxyResolver resolver
;
467 ProxyService
service(
469 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
471 GURL
url("http://www.google.com/");
474 TestCompletionCallback callback1
;
475 int rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info
, callback1
.callback(),
476 NULL
, NULL
, BoundNetLog());
477 EXPECT_EQ(ERR_IO_PENDING
, rv
);
479 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
480 resolver
.pending_set_pac_script_request()->script_data()->url());
481 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
483 ASSERT_EQ(1u, resolver
.pending_requests().size());
484 EXPECT_EQ(url
, resolver
.pending_requests()[0]->url());
486 // Set the result in proxy resolver.
487 resolver
.pending_requests()[0]->results()->UseNamedProxy("foopy:8080");
488 resolver
.pending_requests()[0]->CompleteNow(OK
);
490 EXPECT_EQ(OK
, callback1
.WaitForResult());
491 EXPECT_FALSE(info
.is_direct());
492 EXPECT_EQ("foopy:8080", info
.proxy_server().ToURI());
493 EXPECT_TRUE(info
.did_use_pac_script());
495 EXPECT_FALSE(info
.proxy_resolve_start_time().is_null());
496 EXPECT_FALSE(info
.proxy_resolve_end_time().is_null());
497 EXPECT_LE(info
.proxy_resolve_start_time(), info
.proxy_resolve_end_time());
499 // Now, imagine that connecting to foopy:8080 fails: there is nothing
500 // left to fallback to, since our proxy list was NOT terminated by
502 NetworkDelegateImpl network_delegate
;
503 TestCompletionCallback callback2
;
504 ProxyServer expected_proxy_server
= info
.proxy_server();
505 rv
= service
.ReconsiderProxyAfterError(
506 url
, LOAD_NORMAL
, ERR_PROXY_CONNECTION_FAILED
, &info
,
507 callback2
.callback(), NULL
, &network_delegate
, BoundNetLog());
508 // ReconsiderProxyAfterError returns error indicating nothing left.
509 EXPECT_EQ(ERR_FAILED
, rv
);
510 EXPECT_TRUE(info
.is_empty());
513 // Test that if the execution of the PAC script fails (i.e. javascript runtime
514 // error), and the PAC settings are non-mandatory, that we fall-back to direct.
515 TEST_F(ProxyServiceTest
, PAC_RuntimeError
) {
516 MockProxyConfigService
* config_service
=
517 new MockProxyConfigService("http://foopy/proxy.pac");
518 MockAsyncProxyResolver resolver
;
520 ProxyService
service(
522 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
524 GURL
url("http://this-causes-js-error/");
527 TestCompletionCallback callback1
;
528 int rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info
, callback1
.callback(),
529 NULL
, NULL
, BoundNetLog());
530 EXPECT_EQ(ERR_IO_PENDING
, rv
);
532 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
533 resolver
.pending_set_pac_script_request()->script_data()->url());
534 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
536 ASSERT_EQ(1u, resolver
.pending_requests().size());
537 EXPECT_EQ(url
, resolver
.pending_requests()[0]->url());
539 // Simulate a failure in the PAC executor.
540 resolver
.pending_requests()[0]->CompleteNow(ERR_PAC_SCRIPT_FAILED
);
542 EXPECT_EQ(OK
, callback1
.WaitForResult());
544 // Since the PAC script was non-mandatory, we should have fallen-back to
546 EXPECT_TRUE(info
.is_direct());
547 EXPECT_TRUE(info
.did_use_pac_script());
548 EXPECT_EQ(1, info
.config_id());
550 EXPECT_FALSE(info
.proxy_resolve_start_time().is_null());
551 EXPECT_FALSE(info
.proxy_resolve_end_time().is_null());
552 EXPECT_LE(info
.proxy_resolve_start_time(), info
.proxy_resolve_end_time());
555 // The proxy list could potentially contain the DIRECT fallback choice
556 // in a location other than the very end of the list, and could even
557 // specify it multiple times.
559 // This is not a typical usage, but we will obey it.
560 // (If we wanted to disallow this type of input, the right place to
561 // enforce it would be in parsing the PAC result string).
563 // This test will use the PAC result string:
565 // "DIRECT ; PROXY foobar:10 ; DIRECT ; PROXY foobar:20"
567 // For which we expect it to try DIRECT, then foobar:10, then DIRECT again,
568 // then foobar:20, and then give up and error.
570 // The important check of this test is to make sure that DIRECT is not somehow
571 // cached as being a bad proxy.
572 TEST_F(ProxyServiceTest
, PAC_FailoverAfterDirect
) {
573 MockProxyConfigService
* config_service
=
574 new MockProxyConfigService("http://foopy/proxy.pac");
575 MockAsyncProxyResolver resolver
;
577 ProxyService
service(
579 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
581 GURL
url("http://www.google.com/");
584 TestCompletionCallback callback1
;
585 int rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info
, callback1
.callback(),
586 NULL
, NULL
, BoundNetLog());
587 EXPECT_EQ(ERR_IO_PENDING
, rv
);
589 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
590 resolver
.pending_set_pac_script_request()->script_data()->url());
591 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
593 ASSERT_EQ(1u, resolver
.pending_requests().size());
594 EXPECT_EQ(url
, resolver
.pending_requests()[0]->url());
596 // Set the result in proxy resolver.
597 resolver
.pending_requests()[0]->results()->UsePacString(
598 "DIRECT ; PROXY foobar:10 ; DIRECT ; PROXY foobar:20");
599 resolver
.pending_requests()[0]->CompleteNow(OK
);
601 EXPECT_EQ(OK
, callback1
.WaitForResult());
602 EXPECT_TRUE(info
.is_direct());
605 TestCompletionCallback callback2
;
606 rv
= service
.ReconsiderProxyAfterError(
607 url
, LOAD_NORMAL
, ERR_PROXY_CONNECTION_FAILED
, &info
,
608 callback2
.callback(), NULL
, NULL
, BoundNetLog());
610 EXPECT_FALSE(info
.is_direct());
611 EXPECT_EQ("foobar:10", info
.proxy_server().ToURI());
614 NetworkDelegateImpl network_delegate
;
615 ProxyServer expected_proxy_server3
= info
.proxy_server();
616 TestCompletionCallback callback3
;
617 rv
= service
.ReconsiderProxyAfterError(
618 url
, LOAD_NORMAL
, ERR_PROXY_CONNECTION_FAILED
, &info
,
619 callback3
.callback(), NULL
, &network_delegate
, BoundNetLog());
621 EXPECT_TRUE(info
.is_direct());
624 ProxyServer expected_proxy_server4
= info
.proxy_server();
625 TestCompletionCallback callback4
;
626 rv
= service
.ReconsiderProxyAfterError(
627 url
, LOAD_NORMAL
, ERR_PROXY_CONNECTION_FAILED
, &info
,
628 callback4
.callback(), NULL
, &network_delegate
, BoundNetLog());
630 EXPECT_FALSE(info
.is_direct());
631 EXPECT_EQ("foobar:20", info
.proxy_server().ToURI());
633 // Fallback 4 -- Nothing to fall back to!
634 ProxyServer expected_proxy_server5
= info
.proxy_server();
635 TestCompletionCallback callback5
;
636 rv
= service
.ReconsiderProxyAfterError(
637 url
, LOAD_NORMAL
, ERR_PROXY_CONNECTION_FAILED
, &info
,
638 callback5
.callback(), NULL
, &network_delegate
, BoundNetLog());
639 EXPECT_EQ(ERR_FAILED
, rv
);
640 EXPECT_TRUE(info
.is_empty());
643 TEST_F(ProxyServiceTest
, PAC_ConfigSourcePropagates
) {
644 // Test whether the ProxyConfigSource set by the ProxyConfigService is applied
645 // to ProxyInfo after the proxy is resolved via a PAC script.
647 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"));
648 config
.set_source(PROXY_CONFIG_SOURCE_TEST
);
650 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
651 MockAsyncProxyResolver resolver
;
652 ProxyService
service(
654 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
656 // Resolve something.
657 GURL
url("http://www.google.com/");
659 TestCompletionCallback callback
;
660 int rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info
, callback
.callback(),
661 NULL
, NULL
, BoundNetLog());
662 ASSERT_EQ(ERR_IO_PENDING
, rv
);
663 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
664 ASSERT_EQ(1u, resolver
.pending_requests().size());
666 // Set the result in proxy resolver.
667 resolver
.pending_requests()[0]->results()->UseNamedProxy("foopy");
668 resolver
.pending_requests()[0]->CompleteNow(OK
);
670 EXPECT_EQ(OK
, callback
.WaitForResult());
671 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST
, info
.config_source());
672 EXPECT_TRUE(info
.did_use_pac_script());
674 EXPECT_FALSE(info
.proxy_resolve_start_time().is_null());
675 EXPECT_FALSE(info
.proxy_resolve_end_time().is_null());
676 EXPECT_LE(info
.proxy_resolve_start_time(), info
.proxy_resolve_end_time());
679 TEST_F(ProxyServiceTest
, ProxyResolverFails
) {
680 // Test what happens when the ProxyResolver fails. The download and setting
681 // of the PAC script have already succeeded, so this corresponds with a
682 // javascript runtime error while calling FindProxyForURL().
684 MockProxyConfigService
* config_service
=
685 new MockProxyConfigService("http://foopy/proxy.pac");
687 MockAsyncProxyResolver resolver
;
689 ProxyService
service(
691 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
693 // Start first resolve request.
694 GURL
url("http://www.google.com/");
696 TestCompletionCallback callback1
;
697 int rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info
, callback1
.callback(),
698 NULL
, NULL
, BoundNetLog());
699 EXPECT_EQ(ERR_IO_PENDING
, rv
);
701 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
702 resolver
.pending_set_pac_script_request()->script_data()->url());
703 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
705 ASSERT_EQ(1u, resolver
.pending_requests().size());
706 EXPECT_EQ(url
, resolver
.pending_requests()[0]->url());
708 // Fail the first resolve request in MockAsyncProxyResolver.
709 resolver
.pending_requests()[0]->CompleteNow(ERR_FAILED
);
711 // Although the proxy resolver failed the request, ProxyService implicitly
712 // falls-back to DIRECT.
713 EXPECT_EQ(OK
, callback1
.WaitForResult());
714 EXPECT_TRUE(info
.is_direct());
716 // Failed PAC executions still have proxy resolution times.
717 EXPECT_FALSE(info
.proxy_resolve_start_time().is_null());
718 EXPECT_FALSE(info
.proxy_resolve_end_time().is_null());
719 EXPECT_LE(info
.proxy_resolve_start_time(), info
.proxy_resolve_end_time());
721 // The second resolve request will try to run through the proxy resolver,
722 // regardless of whether the first request failed in it.
723 TestCompletionCallback callback2
;
724 rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info
, callback2
.callback(), NULL
,
725 NULL
, BoundNetLog());
726 EXPECT_EQ(ERR_IO_PENDING
, rv
);
728 ASSERT_EQ(1u, resolver
.pending_requests().size());
729 EXPECT_EQ(url
, resolver
.pending_requests()[0]->url());
731 // This time we will have the resolver succeed (perhaps the PAC script has
732 // a dependency on the current time).
733 resolver
.pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080");
734 resolver
.pending_requests()[0]->CompleteNow(OK
);
736 EXPECT_EQ(OK
, callback2
.WaitForResult());
737 EXPECT_FALSE(info
.is_direct());
738 EXPECT_EQ("foopy_valid:8080", info
.proxy_server().ToURI());
741 TEST_F(ProxyServiceTest
, ProxyScriptFetcherFailsDownloadingMandatoryPac
) {
742 // Test what happens when the ProxyScriptResolver fails to download a
743 // mandatory PAC script.
746 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
747 config
.set_pac_mandatory(true);
749 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
751 MockAsyncProxyResolver resolver
;
753 ProxyService
service(
755 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
757 // Start first resolve request.
758 GURL
url("http://www.google.com/");
760 TestCompletionCallback callback1
;
761 int rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info
, callback1
.callback(),
762 NULL
, NULL
, BoundNetLog());
763 EXPECT_EQ(ERR_IO_PENDING
, rv
);
765 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
766 resolver
.pending_set_pac_script_request()->script_data()->url());
767 resolver
.pending_set_pac_script_request()->CompleteNow(ERR_FAILED
);
769 ASSERT_EQ(0u, resolver
.pending_requests().size());
770 // As the proxy resolver failed the request and is configured for a mandatory
771 // PAC script, ProxyService must not implicitly fall-back to DIRECT.
772 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED
,
773 callback1
.WaitForResult());
774 EXPECT_FALSE(info
.is_direct());
776 // As the proxy resolver failed the request and is configured for a mandatory
777 // PAC script, ProxyService must not implicitly fall-back to DIRECT.
778 TestCompletionCallback callback2
;
779 rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info
, callback2
.callback(), NULL
,
780 NULL
, BoundNetLog());
781 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED
, rv
);
782 EXPECT_FALSE(info
.is_direct());
785 TEST_F(ProxyServiceTest
, ProxyResolverFailsParsingJavaScriptMandatoryPac
) {
786 // Test what happens when the ProxyResolver fails that is configured to use a
787 // mandatory PAC script. The download of the PAC script has already
788 // succeeded but the PAC script contains no valid javascript.
791 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
792 config
.set_pac_mandatory(true);
794 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
796 MockAsyncProxyResolverExpectsBytes resolver
;
798 ProxyService
service(
800 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
802 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
803 DhcpProxyScriptFetcher
* dhcp_fetcher
= new DoNothingDhcpProxyScriptFetcher();
804 service
.SetProxyScriptFetchers(fetcher
, dhcp_fetcher
);
806 // Start resolve request.
807 GURL
url("http://www.google.com/");
809 TestCompletionCallback callback
;
810 int rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info
, callback
.callback(),
811 NULL
, NULL
, BoundNetLog());
812 EXPECT_EQ(ERR_IO_PENDING
, rv
);
814 // Check that nothing has been sent to the proxy resolver yet.
815 ASSERT_EQ(0u, resolver
.pending_requests().size());
817 // Downloading the PAC script succeeds.
818 EXPECT_TRUE(fetcher
->has_pending_request());
819 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
820 fetcher
->NotifyFetchCompletion(OK
, "invalid-script-contents");
822 EXPECT_FALSE(fetcher
->has_pending_request());
823 ASSERT_EQ(0u, resolver
.pending_requests().size());
825 // Since ProxyScriptDecider failed to identify a valid PAC and PAC was
826 // mandatory for this configuration, the ProxyService must not implicitly
827 // fall-back to DIRECT.
828 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED
,
829 callback
.WaitForResult());
830 EXPECT_FALSE(info
.is_direct());
833 TEST_F(ProxyServiceTest
, ProxyResolverFailsInJavaScriptMandatoryPac
) {
834 // Test what happens when the ProxyResolver fails that is configured to use a
835 // mandatory PAC script. The download and setting of the PAC script have
836 // already succeeded, so this corresponds with a javascript runtime error
837 // while calling FindProxyForURL().
840 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
841 config
.set_pac_mandatory(true);
843 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
845 MockAsyncProxyResolver resolver
;
847 ProxyService
service(
849 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
851 // Start first resolve request.
852 GURL
url("http://www.google.com/");
854 TestCompletionCallback callback1
;
855 int rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info
, callback1
.callback(),
856 NULL
, NULL
, BoundNetLog());
857 EXPECT_EQ(ERR_IO_PENDING
, rv
);
859 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
860 resolver
.pending_set_pac_script_request()->script_data()->url());
861 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
863 ASSERT_EQ(1u, resolver
.pending_requests().size());
864 EXPECT_EQ(url
, resolver
.pending_requests()[0]->url());
866 // Fail the first resolve request in MockAsyncProxyResolver.
867 resolver
.pending_requests()[0]->CompleteNow(ERR_FAILED
);
869 // As the proxy resolver failed the request and is configured for a mandatory
870 // PAC script, ProxyService must not implicitly fall-back to DIRECT.
871 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED
,
872 callback1
.WaitForResult());
873 EXPECT_FALSE(info
.is_direct());
875 // The second resolve request will try to run through the proxy resolver,
876 // regardless of whether the first request failed in it.
877 TestCompletionCallback callback2
;
878 rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info
, callback2
.callback(), NULL
,
879 NULL
, BoundNetLog());
880 EXPECT_EQ(ERR_IO_PENDING
, rv
);
882 ASSERT_EQ(1u, resolver
.pending_requests().size());
883 EXPECT_EQ(url
, resolver
.pending_requests()[0]->url());
885 // This time we will have the resolver succeed (perhaps the PAC script has
886 // a dependency on the current time).
887 resolver
.pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080");
888 resolver
.pending_requests()[0]->CompleteNow(OK
);
890 EXPECT_EQ(OK
, callback2
.WaitForResult());
891 EXPECT_FALSE(info
.is_direct());
892 EXPECT_EQ("foopy_valid:8080", info
.proxy_server().ToURI());
895 TEST_F(ProxyServiceTest
, ProxyFallback
) {
896 // Test what happens when we specify multiple proxy servers and some of them
899 MockProxyConfigService
* config_service
=
900 new MockProxyConfigService("http://foopy/proxy.pac");
902 MockAsyncProxyResolver resolver
;
904 ProxyService
service(
906 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
908 GURL
url("http://www.google.com/");
910 // Get the proxy information.
912 TestCompletionCallback callback1
;
913 int rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info
, callback1
.callback(),
914 NULL
, NULL
, BoundNetLog());
915 EXPECT_EQ(ERR_IO_PENDING
, rv
);
917 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
918 resolver
.pending_set_pac_script_request()->script_data()->url());
919 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
921 ASSERT_EQ(1u, resolver
.pending_requests().size());
922 EXPECT_EQ(url
, resolver
.pending_requests()[0]->url());
924 // Set the result in proxy resolver.
925 resolver
.pending_requests()[0]->results()->UseNamedProxy(
926 "foopy1:8080;foopy2:9090");
927 resolver
.pending_requests()[0]->CompleteNow(OK
);
929 // The first item is valid.
930 EXPECT_EQ(OK
, callback1
.WaitForResult());
931 EXPECT_FALSE(info
.is_direct());
932 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
934 EXPECT_FALSE(info
.proxy_resolve_start_time().is_null());
935 EXPECT_FALSE(info
.proxy_resolve_end_time().is_null());
936 EXPECT_LE(info
.proxy_resolve_start_time(), info
.proxy_resolve_end_time());
937 base::TimeTicks proxy_resolve_start_time
= info
.proxy_resolve_start_time();
938 base::TimeTicks proxy_resolve_end_time
= info
.proxy_resolve_end_time();
940 // Fake an error on the proxy.
941 TestCompletionCallback callback2
;
942 rv
= service
.ReconsiderProxyAfterError(
943 url
, LOAD_NORMAL
, ERR_PROXY_CONNECTION_FAILED
, &info
,
944 callback2
.callback(), NULL
, NULL
, BoundNetLog());
947 // Proxy times should not have been modified by fallback.
948 EXPECT_EQ(proxy_resolve_start_time
, info
.proxy_resolve_start_time());
949 EXPECT_EQ(proxy_resolve_end_time
, info
.proxy_resolve_end_time());
951 // The second proxy should be specified.
952 EXPECT_EQ("foopy2:9090", info
.proxy_server().ToURI());
953 // Report back that the second proxy worked. This will globally mark the
954 // first proxy as bad.
955 TestProxyFallbackNetworkDelegate test_delegate
;
956 service
.ReportSuccess(info
, &test_delegate
);
957 EXPECT_EQ("foopy1:8080", test_delegate
.proxy_server().ToURI());
958 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED
,
959 test_delegate
.proxy_fallback_net_error());
961 TestCompletionCallback callback3
;
962 rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info
, callback3
.callback(), NULL
,
963 NULL
, BoundNetLog());
964 EXPECT_EQ(ERR_IO_PENDING
, rv
);
966 ASSERT_EQ(1u, resolver
.pending_requests().size());
967 EXPECT_EQ(url
, resolver
.pending_requests()[0]->url());
969 // Set the result in proxy resolver -- the second result is already known
970 // to be bad, so we will not try to use it initially.
971 resolver
.pending_requests()[0]->results()->UseNamedProxy(
972 "foopy3:7070;foopy1:8080;foopy2:9090");
973 resolver
.pending_requests()[0]->CompleteNow(OK
);
975 EXPECT_EQ(OK
, callback3
.WaitForResult());
976 EXPECT_FALSE(info
.is_direct());
977 EXPECT_EQ("foopy3:7070", info
.proxy_server().ToURI());
979 // Proxy times should have been updated, so get them again.
980 EXPECT_LE(proxy_resolve_end_time
, info
.proxy_resolve_start_time());
981 EXPECT_FALSE(info
.proxy_resolve_start_time().is_null());
982 EXPECT_FALSE(info
.proxy_resolve_end_time().is_null());
983 EXPECT_LE(info
.proxy_resolve_start_time(), info
.proxy_resolve_end_time());
984 proxy_resolve_start_time
= info
.proxy_resolve_start_time();
985 proxy_resolve_end_time
= info
.proxy_resolve_end_time();
987 // We fake another error. It should now try the third one.
988 TestCompletionCallback callback4
;
989 rv
= service
.ReconsiderProxyAfterError(
990 url
, LOAD_NORMAL
, ERR_PROXY_CONNECTION_FAILED
, &info
,
991 callback4
.callback(), NULL
, NULL
, BoundNetLog());
993 EXPECT_EQ("foopy2:9090", info
.proxy_server().ToURI());
995 // We fake another error. At this point we have tried all of the
996 // proxy servers we thought were valid; next we try the proxy server
997 // that was in our bad proxies map (foopy1:8080).
998 TestCompletionCallback callback5
;
999 rv
= service
.ReconsiderProxyAfterError(
1000 url
, LOAD_NORMAL
, ERR_PROXY_CONNECTION_FAILED
, &info
,
1001 callback5
.callback(), NULL
, NULL
, BoundNetLog());
1003 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
1005 // Fake another error, the last proxy is gone, the list should now be empty,
1006 // so there is nothing left to try.
1007 TestCompletionCallback callback6
;
1008 rv
= service
.ReconsiderProxyAfterError(
1009 url
, LOAD_NORMAL
, ERR_PROXY_CONNECTION_FAILED
, &info
,
1010 callback6
.callback(), NULL
, NULL
, BoundNetLog());
1011 EXPECT_EQ(ERR_FAILED
, rv
);
1012 EXPECT_FALSE(info
.is_direct());
1013 EXPECT_TRUE(info
.is_empty());
1015 // Proxy times should not have been modified by fallback.
1016 EXPECT_EQ(proxy_resolve_start_time
, info
.proxy_resolve_start_time());
1017 EXPECT_EQ(proxy_resolve_end_time
, info
.proxy_resolve_end_time());
1019 // Look up proxies again
1020 TestCompletionCallback callback7
;
1021 rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info
, callback7
.callback(), NULL
,
1022 NULL
, BoundNetLog());
1023 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1025 ASSERT_EQ(1u, resolver
.pending_requests().size());
1026 EXPECT_EQ(url
, resolver
.pending_requests()[0]->url());
1028 // This time, the first 3 results have been found to be bad, but only the
1029 // first proxy has been confirmed ...
1030 resolver
.pending_requests()[0]->results()->UseNamedProxy(
1031 "foopy1:8080;foopy3:7070;foopy2:9090;foopy4:9091");
1032 resolver
.pending_requests()[0]->CompleteNow(OK
);
1034 // ... therefore, we should see the second proxy first.
1035 EXPECT_EQ(OK
, callback7
.WaitForResult());
1036 EXPECT_FALSE(info
.is_direct());
1037 EXPECT_EQ("foopy3:7070", info
.proxy_server().ToURI());
1039 EXPECT_LE(proxy_resolve_end_time
, info
.proxy_resolve_start_time());
1040 EXPECT_FALSE(info
.proxy_resolve_start_time().is_null());
1041 EXPECT_FALSE(info
.proxy_resolve_end_time().is_null());
1042 // TODO(nsylvain): Test that the proxy can be retried after the delay.
1045 // This test is similar to ProxyFallback, but this time we have an explicit
1046 // fallback choice to DIRECT.
1047 TEST_F(ProxyServiceTest
, ProxyFallbackToDirect
) {
1048 MockProxyConfigService
* config_service
=
1049 new MockProxyConfigService("http://foopy/proxy.pac");
1051 MockAsyncProxyResolver resolver
;
1053 ProxyService
service(
1055 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
1057 GURL
url("http://www.google.com/");
1059 // Get the proxy information.
1061 TestCompletionCallback callback1
;
1062 int rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info
, callback1
.callback(),
1063 NULL
, NULL
, BoundNetLog());
1064 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1066 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1067 resolver
.pending_set_pac_script_request()->script_data()->url());
1068 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
1070 ASSERT_EQ(1u, resolver
.pending_requests().size());
1071 EXPECT_EQ(url
, resolver
.pending_requests()[0]->url());
1073 // Set the result in proxy resolver.
1074 resolver
.pending_requests()[0]->results()->UsePacString(
1075 "PROXY foopy1:8080; PROXY foopy2:9090; DIRECT");
1076 resolver
.pending_requests()[0]->CompleteNow(OK
);
1078 // Get the first result.
1079 EXPECT_EQ(OK
, callback1
.WaitForResult());
1080 EXPECT_FALSE(info
.is_direct());
1081 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
1083 // Fake an error on the proxy.
1084 TestCompletionCallback callback2
;
1085 rv
= service
.ReconsiderProxyAfterError(
1086 url
, LOAD_NORMAL
, ERR_PROXY_CONNECTION_FAILED
, &info
,
1087 callback2
.callback(), NULL
, NULL
, BoundNetLog());
1090 // Now we get back the second proxy.
1091 EXPECT_EQ("foopy2:9090", info
.proxy_server().ToURI());
1093 // Fake an error on this proxy as well.
1094 TestCompletionCallback callback3
;
1095 rv
= service
.ReconsiderProxyAfterError(
1096 url
, LOAD_NORMAL
, ERR_PROXY_CONNECTION_FAILED
, &info
,
1097 callback3
.callback(), NULL
, NULL
, BoundNetLog());
1100 // Finally, we get back DIRECT.
1101 EXPECT_TRUE(info
.is_direct());
1103 EXPECT_FALSE(info
.proxy_resolve_start_time().is_null());
1104 EXPECT_FALSE(info
.proxy_resolve_end_time().is_null());
1105 EXPECT_LE(info
.proxy_resolve_start_time(), info
.proxy_resolve_end_time());
1107 // Now we tell the proxy service that even DIRECT failed.
1108 TestCompletionCallback callback4
;
1109 rv
= service
.ReconsiderProxyAfterError(
1110 url
, LOAD_NORMAL
, ERR_PROXY_CONNECTION_FAILED
, &info
,
1111 callback4
.callback(), NULL
, NULL
, BoundNetLog());
1112 // There was nothing left to try after DIRECT, so we are out of
1114 EXPECT_EQ(ERR_FAILED
, rv
);
1117 TEST_F(ProxyServiceTest
, ProxyFallback_NewSettings
) {
1118 // Test proxy failover when new settings are available.
1120 MockProxyConfigService
* config_service
=
1121 new MockProxyConfigService("http://foopy/proxy.pac");
1123 MockAsyncProxyResolver resolver
;
1125 ProxyService
service(
1127 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
1129 GURL
url("http://www.google.com/");
1131 // Get the proxy information.
1133 TestCompletionCallback callback1
;
1134 int rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info
, callback1
.callback(),
1135 NULL
, NULL
, BoundNetLog());
1136 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1138 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1139 resolver
.pending_set_pac_script_request()->script_data()->url());
1140 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
1142 ASSERT_EQ(1u, resolver
.pending_requests().size());
1143 EXPECT_EQ(url
, resolver
.pending_requests()[0]->url());
1145 // Set the result in proxy resolver.
1146 resolver
.pending_requests()[0]->results()->UseNamedProxy(
1147 "foopy1:8080;foopy2:9090");
1148 resolver
.pending_requests()[0]->CompleteNow(OK
);
1150 // The first item is valid.
1151 EXPECT_EQ(OK
, callback1
.WaitForResult());
1152 EXPECT_FALSE(info
.is_direct());
1153 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
1155 // Fake an error on the proxy, and also a new configuration on the proxy.
1156 config_service
->SetConfig(
1157 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy-new/proxy.pac")));
1159 TestCompletionCallback callback2
;
1160 rv
= service
.ReconsiderProxyAfterError(
1161 url
, LOAD_NORMAL
, ERR_PROXY_CONNECTION_FAILED
, &info
,
1162 callback2
.callback(), NULL
, NULL
, BoundNetLog());
1163 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1165 EXPECT_EQ(GURL("http://foopy-new/proxy.pac"),
1166 resolver
.pending_set_pac_script_request()->script_data()->url());
1167 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
1169 ASSERT_EQ(1u, resolver
.pending_requests().size());
1170 EXPECT_EQ(url
, resolver
.pending_requests()[0]->url());
1172 resolver
.pending_requests()[0]->results()->UseNamedProxy(
1173 "foopy1:8080;foopy2:9090");
1174 resolver
.pending_requests()[0]->CompleteNow(OK
);
1176 // The first proxy is still there since the configuration changed.
1177 EXPECT_EQ(OK
, callback2
.WaitForResult());
1178 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
1180 // We fake another error. It should now ignore the first one.
1181 TestCompletionCallback callback3
;
1182 rv
= service
.ReconsiderProxyAfterError(
1183 url
, LOAD_NORMAL
, ERR_PROXY_CONNECTION_FAILED
, &info
,
1184 callback3
.callback(), NULL
, NULL
, BoundNetLog());
1186 EXPECT_EQ("foopy2:9090", info
.proxy_server().ToURI());
1188 // We simulate a new configuration.
1189 config_service
->SetConfig(
1190 ProxyConfig::CreateFromCustomPacURL(
1191 GURL("http://foopy-new2/proxy.pac")));
1193 // We fake another error. It should go back to the first proxy.
1194 TestCompletionCallback callback4
;
1195 rv
= service
.ReconsiderProxyAfterError(
1196 url
, LOAD_NORMAL
, ERR_PROXY_CONNECTION_FAILED
, &info
,
1197 callback4
.callback(), NULL
, NULL
, BoundNetLog());
1198 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1200 EXPECT_EQ(GURL("http://foopy-new2/proxy.pac"),
1201 resolver
.pending_set_pac_script_request()->script_data()->url());
1202 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
1204 ASSERT_EQ(1u, resolver
.pending_requests().size());
1205 EXPECT_EQ(url
, resolver
.pending_requests()[0]->url());
1207 resolver
.pending_requests()[0]->results()->UseNamedProxy(
1208 "foopy1:8080;foopy2:9090");
1209 resolver
.pending_requests()[0]->CompleteNow(OK
);
1211 EXPECT_EQ(OK
, callback4
.WaitForResult());
1212 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
1214 EXPECT_FALSE(info
.proxy_resolve_start_time().is_null());
1215 EXPECT_FALSE(info
.proxy_resolve_end_time().is_null());
1216 EXPECT_LE(info
.proxy_resolve_start_time(), info
.proxy_resolve_end_time());
1219 TEST_F(ProxyServiceTest
, ProxyFallback_BadConfig
) {
1220 // Test proxy failover when the configuration is bad.
1222 MockProxyConfigService
* config_service
=
1223 new MockProxyConfigService("http://foopy/proxy.pac");
1225 MockAsyncProxyResolver resolver
;
1227 ProxyService
service(
1229 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
1231 GURL
url("http://www.google.com/");
1233 // Get the proxy information.
1235 TestCompletionCallback callback1
;
1236 int rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info
, callback1
.callback(),
1237 NULL
, NULL
, BoundNetLog());
1238 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1240 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1241 resolver
.pending_set_pac_script_request()->script_data()->url());
1242 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
1243 ASSERT_EQ(1u, resolver
.pending_requests().size());
1244 EXPECT_EQ(url
, resolver
.pending_requests()[0]->url());
1246 resolver
.pending_requests()[0]->results()->UseNamedProxy(
1247 "foopy1:8080;foopy2:9090");
1248 resolver
.pending_requests()[0]->CompleteNow(OK
);
1250 // The first item is valid.
1251 EXPECT_EQ(OK
, callback1
.WaitForResult());
1252 EXPECT_FALSE(info
.is_direct());
1253 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
1255 // Fake a proxy error.
1256 TestCompletionCallback callback2
;
1257 rv
= service
.ReconsiderProxyAfterError(
1258 url
, LOAD_NORMAL
, ERR_PROXY_CONNECTION_FAILED
, &info
,
1259 callback2
.callback(), NULL
, NULL
, BoundNetLog());
1262 // The first proxy is ignored, and the second one is selected.
1263 EXPECT_FALSE(info
.is_direct());
1264 EXPECT_EQ("foopy2:9090", info
.proxy_server().ToURI());
1266 // Fake a PAC failure.
1268 TestCompletionCallback callback3
;
1269 rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info2
, callback3
.callback(),
1270 NULL
, NULL
, BoundNetLog());
1271 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1273 ASSERT_EQ(1u, resolver
.pending_requests().size());
1274 EXPECT_EQ(url
, resolver
.pending_requests()[0]->url());
1276 // This simulates a javascript runtime error in the PAC script.
1277 resolver
.pending_requests()[0]->CompleteNow(ERR_FAILED
);
1279 // Although the resolver failed, the ProxyService will implicitly fall-back
1280 // to a DIRECT connection.
1281 EXPECT_EQ(OK
, callback3
.WaitForResult());
1282 EXPECT_TRUE(info2
.is_direct());
1283 EXPECT_FALSE(info2
.is_empty());
1285 // The PAC script will work properly next time and successfully return a
1286 // proxy list. Since we have not marked the configuration as bad, it should
1287 // "just work" the next time we call it.
1289 TestCompletionCallback callback4
;
1290 rv
= service
.ReconsiderProxyAfterError(
1291 url
, LOAD_NORMAL
, ERR_PROXY_CONNECTION_FAILED
, &info3
,
1292 callback4
.callback(), NULL
, NULL
, BoundNetLog());
1293 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1295 ASSERT_EQ(1u, resolver
.pending_requests().size());
1296 EXPECT_EQ(url
, resolver
.pending_requests()[0]->url());
1298 resolver
.pending_requests()[0]->results()->UseNamedProxy(
1299 "foopy1:8080;foopy2:9090");
1300 resolver
.pending_requests()[0]->CompleteNow(OK
);
1302 // The first proxy is not there since the it was added to the bad proxies
1303 // list by the earlier ReconsiderProxyAfterError().
1304 EXPECT_EQ(OK
, callback4
.WaitForResult());
1305 EXPECT_FALSE(info3
.is_direct());
1306 EXPECT_EQ("foopy1:8080", info3
.proxy_server().ToURI());
1308 EXPECT_FALSE(info
.proxy_resolve_start_time().is_null());
1309 EXPECT_FALSE(info
.proxy_resolve_end_time().is_null());
1310 EXPECT_LE(info
.proxy_resolve_start_time(), info
.proxy_resolve_end_time());
1313 TEST_F(ProxyServiceTest
, ProxyFallback_BadConfigMandatory
) {
1314 // Test proxy failover when the configuration is bad.
1317 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
1319 config
.set_pac_mandatory(true);
1320 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
1322 MockAsyncProxyResolver resolver
;
1324 ProxyService
service(
1326 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
1328 GURL
url("http://www.google.com/");
1330 // Get the proxy information.
1332 TestCompletionCallback callback1
;
1333 int rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info
, callback1
.callback(),
1334 NULL
, NULL
, BoundNetLog());
1335 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1337 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1338 resolver
.pending_set_pac_script_request()->script_data()->url());
1339 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
1340 ASSERT_EQ(1u, resolver
.pending_requests().size());
1341 EXPECT_EQ(url
, resolver
.pending_requests()[0]->url());
1343 resolver
.pending_requests()[0]->results()->UseNamedProxy(
1344 "foopy1:8080;foopy2:9090");
1345 resolver
.pending_requests()[0]->CompleteNow(OK
);
1347 // The first item is valid.
1348 EXPECT_EQ(OK
, callback1
.WaitForResult());
1349 EXPECT_FALSE(info
.is_direct());
1350 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
1352 // Fake a proxy error.
1353 TestCompletionCallback callback2
;
1354 rv
= service
.ReconsiderProxyAfterError(
1355 url
, LOAD_NORMAL
, ERR_PROXY_CONNECTION_FAILED
, &info
,
1356 callback2
.callback(), NULL
, NULL
, BoundNetLog());
1359 // The first proxy is ignored, and the second one is selected.
1360 EXPECT_FALSE(info
.is_direct());
1361 EXPECT_EQ("foopy2:9090", info
.proxy_server().ToURI());
1363 // Fake a PAC failure.
1365 TestCompletionCallback callback3
;
1366 rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info2
, callback3
.callback(),
1367 NULL
, NULL
, BoundNetLog());
1368 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1370 ASSERT_EQ(1u, resolver
.pending_requests().size());
1371 EXPECT_EQ(url
, resolver
.pending_requests()[0]->url());
1373 // This simulates a javascript runtime error in the PAC script.
1374 resolver
.pending_requests()[0]->CompleteNow(ERR_FAILED
);
1376 // Although the resolver failed, the ProxyService will NOT fall-back
1377 // to a DIRECT connection as it is configured as mandatory.
1378 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED
,
1379 callback3
.WaitForResult());
1380 EXPECT_FALSE(info2
.is_direct());
1381 EXPECT_TRUE(info2
.is_empty());
1383 // The PAC script will work properly next time and successfully return a
1384 // proxy list. Since we have not marked the configuration as bad, it should
1385 // "just work" the next time we call it.
1387 TestCompletionCallback callback4
;
1388 rv
= service
.ReconsiderProxyAfterError(
1389 url
, LOAD_NORMAL
, ERR_PROXY_CONNECTION_FAILED
, &info3
,
1390 callback4
.callback(), NULL
, NULL
, BoundNetLog());
1391 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1393 ASSERT_EQ(1u, resolver
.pending_requests().size());
1394 EXPECT_EQ(url
, resolver
.pending_requests()[0]->url());
1396 resolver
.pending_requests()[0]->results()->UseNamedProxy(
1397 "foopy1:8080;foopy2:9090");
1398 resolver
.pending_requests()[0]->CompleteNow(OK
);
1400 // The first proxy is not there since the it was added to the bad proxies
1401 // list by the earlier ReconsiderProxyAfterError().
1402 EXPECT_EQ(OK
, callback4
.WaitForResult());
1403 EXPECT_FALSE(info3
.is_direct());
1404 EXPECT_EQ("foopy1:8080", info3
.proxy_server().ToURI());
1407 TEST_F(ProxyServiceTest
, ProxyBypassList
) {
1408 // Test that the proxy bypass rules are consulted.
1410 TestCompletionCallback callback
[2];
1413 config
.proxy_rules().ParseFromString("foopy1:8080;foopy2:9090");
1414 config
.set_auto_detect(false);
1415 config
.proxy_rules().bypass_rules
.ParseFromString("*.org");
1417 ProxyService
service(new MockProxyConfigService(config
), nullptr, NULL
);
1420 GURL
url1("http://www.webkit.org");
1421 GURL
url2("http://www.webkit.com");
1423 // Request for a .org domain should bypass proxy.
1424 rv
= service
.ResolveProxy(url1
, LOAD_NORMAL
, &info
[0], callback
[0].callback(),
1425 NULL
, NULL
, BoundNetLog());
1427 EXPECT_TRUE(info
[0].is_direct());
1429 // Request for a .com domain hits the proxy.
1430 rv
= service
.ResolveProxy(url2
, LOAD_NORMAL
, &info
[1], callback
[1].callback(),
1431 NULL
, NULL
, BoundNetLog());
1433 EXPECT_EQ("foopy1:8080", info
[1].proxy_server().ToURI());
1437 TEST_F(ProxyServiceTest
, PerProtocolProxyTests
) {
1439 config
.proxy_rules().ParseFromString("http=foopy1:8080;https=foopy2:8080");
1440 config
.set_auto_detect(false);
1442 ProxyService
service(new MockProxyConfigService(config
), nullptr, NULL
);
1443 GURL
test_url("http://www.msn.com");
1445 TestCompletionCallback callback
;
1447 service
.ResolveProxy(test_url
, LOAD_NORMAL
, &info
, callback
.callback(),
1448 NULL
, NULL
, BoundNetLog());
1450 EXPECT_FALSE(info
.is_direct());
1451 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
1454 ProxyService
service(new MockProxyConfigService(config
), nullptr, NULL
);
1455 GURL
test_url("ftp://ftp.google.com");
1457 TestCompletionCallback callback
;
1459 service
.ResolveProxy(test_url
, LOAD_NORMAL
, &info
, callback
.callback(),
1460 NULL
, NULL
, BoundNetLog());
1462 EXPECT_TRUE(info
.is_direct());
1463 EXPECT_EQ("direct://", info
.proxy_server().ToURI());
1466 ProxyService
service(new MockProxyConfigService(config
), nullptr, NULL
);
1467 GURL
test_url("https://webbranch.techcu.com");
1469 TestCompletionCallback callback
;
1471 service
.ResolveProxy(test_url
, LOAD_NORMAL
, &info
, callback
.callback(),
1472 NULL
, NULL
, BoundNetLog());
1474 EXPECT_FALSE(info
.is_direct());
1475 EXPECT_EQ("foopy2:8080", info
.proxy_server().ToURI());
1478 config
.proxy_rules().ParseFromString("foopy1:8080");
1479 ProxyService
service(new MockProxyConfigService(config
), nullptr, NULL
);
1480 GURL
test_url("http://www.microsoft.com");
1482 TestCompletionCallback callback
;
1484 service
.ResolveProxy(test_url
, LOAD_NORMAL
, &info
, callback
.callback(),
1485 NULL
, NULL
, BoundNetLog());
1487 EXPECT_FALSE(info
.is_direct());
1488 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
1492 TEST_F(ProxyServiceTest
, ProxyConfigSourcePropagates
) {
1493 // Test that the proxy config source is set correctly when resolving proxies
1494 // using manual proxy rules. Namely, the config source should only be set if
1495 // any of the rules were applied.
1498 config
.set_source(PROXY_CONFIG_SOURCE_TEST
);
1499 config
.proxy_rules().ParseFromString("https=foopy2:8080");
1500 ProxyService
service(new MockProxyConfigService(config
), nullptr, NULL
);
1501 GURL
test_url("http://www.google.com");
1503 TestCompletionCallback callback
;
1505 service
.ResolveProxy(test_url
, LOAD_NORMAL
, &info
, callback
.callback(),
1506 NULL
, NULL
, BoundNetLog());
1508 // Should be SOURCE_TEST, even if there are no HTTP proxies configured.
1509 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST
, info
.config_source());
1513 config
.set_source(PROXY_CONFIG_SOURCE_TEST
);
1514 config
.proxy_rules().ParseFromString("https=foopy2:8080");
1515 ProxyService
service(new MockProxyConfigService(config
), nullptr, NULL
);
1516 GURL
test_url("https://www.google.com");
1518 TestCompletionCallback callback
;
1520 service
.ResolveProxy(test_url
, LOAD_NORMAL
, &info
, callback
.callback(),
1521 NULL
, NULL
, BoundNetLog());
1523 // Used the HTTPS proxy. So source should be TEST.
1524 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST
, info
.config_source());
1528 config
.set_source(PROXY_CONFIG_SOURCE_TEST
);
1529 ProxyService
service(new MockProxyConfigService(config
), nullptr, NULL
);
1530 GURL
test_url("http://www.google.com");
1532 TestCompletionCallback callback
;
1534 service
.ResolveProxy(test_url
, LOAD_NORMAL
, &info
, callback
.callback(),
1535 NULL
, NULL
, BoundNetLog());
1537 // ProxyConfig is empty. Source should still be TEST.
1538 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST
, info
.config_source());
1542 // If only HTTP and a SOCKS proxy are specified, check if ftp/https queries
1543 // fall back to the SOCKS proxy.
1544 TEST_F(ProxyServiceTest
, DefaultProxyFallbackToSOCKS
) {
1546 config
.proxy_rules().ParseFromString("http=foopy1:8080;socks=foopy2:1080");
1547 config
.set_auto_detect(false);
1548 EXPECT_EQ(ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME
,
1549 config
.proxy_rules().type
);
1552 ProxyService
service(new MockProxyConfigService(config
), nullptr, NULL
);
1553 GURL
test_url("http://www.msn.com");
1555 TestCompletionCallback callback
;
1557 service
.ResolveProxy(test_url
, LOAD_NORMAL
, &info
, callback
.callback(),
1558 NULL
, NULL
, BoundNetLog());
1560 EXPECT_FALSE(info
.is_direct());
1561 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
1564 ProxyService
service(new MockProxyConfigService(config
), nullptr, NULL
);
1565 GURL
test_url("ftp://ftp.google.com");
1567 TestCompletionCallback callback
;
1569 service
.ResolveProxy(test_url
, LOAD_NORMAL
, &info
, callback
.callback(),
1570 NULL
, NULL
, BoundNetLog());
1572 EXPECT_FALSE(info
.is_direct());
1573 EXPECT_EQ("socks4://foopy2:1080", info
.proxy_server().ToURI());
1576 ProxyService
service(new MockProxyConfigService(config
), nullptr, NULL
);
1577 GURL
test_url("https://webbranch.techcu.com");
1579 TestCompletionCallback callback
;
1581 service
.ResolveProxy(test_url
, LOAD_NORMAL
, &info
, callback
.callback(),
1582 NULL
, NULL
, BoundNetLog());
1584 EXPECT_FALSE(info
.is_direct());
1585 EXPECT_EQ("socks4://foopy2:1080", info
.proxy_server().ToURI());
1588 ProxyService
service(new MockProxyConfigService(config
), nullptr, NULL
);
1589 GURL
test_url("unknown://www.microsoft.com");
1591 TestCompletionCallback callback
;
1593 service
.ResolveProxy(test_url
, LOAD_NORMAL
, &info
, callback
.callback(),
1594 NULL
, NULL
, BoundNetLog());
1596 EXPECT_FALSE(info
.is_direct());
1597 EXPECT_EQ("socks4://foopy2:1080", info
.proxy_server().ToURI());
1601 // Test cancellation of an in-progress request.
1602 TEST_F(ProxyServiceTest
, CancelInProgressRequest
) {
1603 MockProxyConfigService
* config_service
=
1604 new MockProxyConfigService("http://foopy/proxy.pac");
1606 MockAsyncProxyResolver resolver
;
1608 ProxyService
service(
1610 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
1612 // Start 3 requests.
1615 TestCompletionCallback callback1
;
1617 service
.ResolveProxy(GURL("http://request1"), LOAD_NORMAL
, &info1
,
1618 callback1
.callback(), NULL
, NULL
, BoundNetLog());
1619 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1621 // Nothing has been sent to the proxy resolver yet, since the proxy
1622 // resolver has not been configured yet.
1623 ASSERT_EQ(0u, resolver
.pending_requests().size());
1625 // Successfully initialize the PAC script.
1626 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1627 resolver
.pending_set_pac_script_request()->script_data()->url());
1628 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
1630 ASSERT_EQ(1u, resolver
.pending_requests().size());
1631 EXPECT_EQ(GURL("http://request1"), resolver
.pending_requests()[0]->url());
1634 TestCompletionCallback callback2
;
1635 ProxyService::PacRequest
* request2
;
1636 rv
= service
.ResolveProxy(GURL("http://request2"), LOAD_NORMAL
, &info2
,
1637 callback2
.callback(), &request2
, NULL
,
1639 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1640 ASSERT_EQ(2u, resolver
.pending_requests().size());
1641 EXPECT_EQ(GURL("http://request2"), resolver
.pending_requests()[1]->url());
1644 TestCompletionCallback callback3
;
1645 rv
= service
.ResolveProxy(GURL("http://request3"), LOAD_NORMAL
, &info3
,
1646 callback3
.callback(), NULL
, NULL
, BoundNetLog());
1647 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1648 ASSERT_EQ(3u, resolver
.pending_requests().size());
1649 EXPECT_EQ(GURL("http://request3"), resolver
.pending_requests()[2]->url());
1651 // Cancel the second request
1652 service
.CancelPacRequest(request2
);
1654 ASSERT_EQ(2u, resolver
.pending_requests().size());
1655 EXPECT_EQ(GURL("http://request1"), resolver
.pending_requests()[0]->url());
1656 EXPECT_EQ(GURL("http://request3"), resolver
.pending_requests()[1]->url());
1658 // Complete the two un-cancelled requests.
1659 // We complete the last one first, just to mix it up a bit.
1660 resolver
.pending_requests()[1]->results()->UseNamedProxy("request3:80");
1661 resolver
.pending_requests()[1]->CompleteNow(OK
);
1663 resolver
.pending_requests()[0]->results()->UseNamedProxy("request1:80");
1664 resolver
.pending_requests()[0]->CompleteNow(OK
);
1666 // Complete and verify that requests ran as expected.
1667 EXPECT_EQ(OK
, callback1
.WaitForResult());
1668 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
1670 EXPECT_FALSE(callback2
.have_result()); // Cancelled.
1671 ASSERT_EQ(1u, resolver
.cancelled_requests().size());
1672 EXPECT_EQ(GURL("http://request2"), resolver
.cancelled_requests()[0]->url());
1674 EXPECT_EQ(OK
, callback3
.WaitForResult());
1675 EXPECT_EQ("request3:80", info3
.proxy_server().ToURI());
1678 // Test the initial PAC download for resolver that expects bytes.
1679 TEST_F(ProxyServiceTest
, InitialPACScriptDownload
) {
1680 MockProxyConfigService
* config_service
=
1681 new MockProxyConfigService("http://foopy/proxy.pac");
1683 MockAsyncProxyResolverExpectsBytes resolver
;
1685 ProxyService
service(
1687 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
1689 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
1690 service
.SetProxyScriptFetchers(fetcher
,
1691 new DoNothingDhcpProxyScriptFetcher());
1693 // Start 3 requests.
1696 TestCompletionCallback callback1
;
1697 ProxyService::PacRequest
* request1
;
1698 int rv
= service
.ResolveProxy(GURL("http://request1"), LOAD_NORMAL
, &info1
,
1699 callback1
.callback(), &request1
, NULL
,
1701 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1703 // The first request should have triggered download of PAC script.
1704 EXPECT_TRUE(fetcher
->has_pending_request());
1705 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
1708 TestCompletionCallback callback2
;
1709 ProxyService::PacRequest
* request2
;
1710 rv
= service
.ResolveProxy(GURL("http://request2"), LOAD_NORMAL
, &info2
,
1711 callback2
.callback(), &request2
, NULL
,
1713 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1716 TestCompletionCallback callback3
;
1717 ProxyService::PacRequest
* request3
;
1718 rv
= service
.ResolveProxy(GURL("http://request3"), LOAD_NORMAL
, &info3
,
1719 callback3
.callback(), &request3
, NULL
,
1721 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1723 // Nothing has been sent to the resolver yet.
1724 EXPECT_TRUE(resolver
.pending_requests().empty());
1726 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT
,
1727 service
.GetLoadState(request1
));
1728 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT
,
1729 service
.GetLoadState(request2
));
1730 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT
,
1731 service
.GetLoadState(request3
));
1733 // At this point the ProxyService should be waiting for the
1734 // ProxyScriptFetcher to invoke its completion callback, notifying it of
1735 // PAC script download completion.
1736 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
1738 // Now that the PAC script is downloaded, it will have been sent to the proxy
1740 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
1741 resolver
.pending_set_pac_script_request()->script_data()->utf16());
1742 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
1744 ASSERT_EQ(3u, resolver
.pending_requests().size());
1745 EXPECT_EQ(GURL("http://request1"), resolver
.pending_requests()[0]->url());
1746 EXPECT_EQ(GURL("http://request2"), resolver
.pending_requests()[1]->url());
1747 EXPECT_EQ(GURL("http://request3"), resolver
.pending_requests()[2]->url());
1749 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL
, service
.GetLoadState(request1
));
1750 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL
, service
.GetLoadState(request2
));
1751 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL
, service
.GetLoadState(request3
));
1753 // Complete all the requests (in some order).
1754 // Note that as we complete requests, they shift up in |pending_requests()|.
1756 resolver
.pending_requests()[2]->results()->UseNamedProxy("request3:80");
1757 resolver
.pending_requests()[2]->CompleteNow(OK
);
1759 resolver
.pending_requests()[0]->results()->UseNamedProxy("request1:80");
1760 resolver
.pending_requests()[0]->CompleteNow(OK
);
1762 resolver
.pending_requests()[0]->results()->UseNamedProxy("request2:80");
1763 resolver
.pending_requests()[0]->CompleteNow(OK
);
1765 // Complete and verify that requests ran as expected.
1766 EXPECT_EQ(OK
, callback1
.WaitForResult());
1767 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
1768 EXPECT_FALSE(info1
.proxy_resolve_start_time().is_null());
1769 EXPECT_FALSE(info1
.proxy_resolve_end_time().is_null());
1770 EXPECT_LE(info1
.proxy_resolve_start_time(), info1
.proxy_resolve_end_time());
1772 EXPECT_EQ(OK
, callback2
.WaitForResult());
1773 EXPECT_EQ("request2:80", info2
.proxy_server().ToURI());
1774 EXPECT_FALSE(info2
.proxy_resolve_start_time().is_null());
1775 EXPECT_FALSE(info2
.proxy_resolve_end_time().is_null());
1776 EXPECT_LE(info2
.proxy_resolve_start_time(), info2
.proxy_resolve_end_time());
1778 EXPECT_EQ(OK
, callback3
.WaitForResult());
1779 EXPECT_EQ("request3:80", info3
.proxy_server().ToURI());
1780 EXPECT_FALSE(info3
.proxy_resolve_start_time().is_null());
1781 EXPECT_FALSE(info3
.proxy_resolve_end_time().is_null());
1782 EXPECT_LE(info3
.proxy_resolve_start_time(), info3
.proxy_resolve_end_time());
1785 // Test changing the ProxyScriptFetcher while PAC download is in progress.
1786 TEST_F(ProxyServiceTest
, ChangeScriptFetcherWhilePACDownloadInProgress
) {
1787 MockProxyConfigService
* config_service
=
1788 new MockProxyConfigService("http://foopy/proxy.pac");
1790 MockAsyncProxyResolverExpectsBytes resolver
;
1792 ProxyService
service(
1794 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
1796 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
1797 service
.SetProxyScriptFetchers(fetcher
,
1798 new DoNothingDhcpProxyScriptFetcher());
1800 // Start 2 requests.
1803 TestCompletionCallback callback1
;
1805 service
.ResolveProxy(GURL("http://request1"), LOAD_NORMAL
, &info1
,
1806 callback1
.callback(), NULL
, NULL
, BoundNetLog());
1807 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1809 // The first request should have triggered download of PAC script.
1810 EXPECT_TRUE(fetcher
->has_pending_request());
1811 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
1814 TestCompletionCallback callback2
;
1815 rv
= service
.ResolveProxy(GURL("http://request2"), LOAD_NORMAL
, &info2
,
1816 callback2
.callback(), NULL
, NULL
, BoundNetLog());
1817 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1819 // At this point the ProxyService should be waiting for the
1820 // ProxyScriptFetcher to invoke its completion callback, notifying it of
1821 // PAC script download completion.
1823 // We now change out the ProxyService's script fetcher. We should restart
1824 // the initialization with the new fetcher.
1826 fetcher
= new MockProxyScriptFetcher
;
1827 service
.SetProxyScriptFetchers(fetcher
,
1828 new DoNothingDhcpProxyScriptFetcher());
1830 // Nothing has been sent to the resolver yet.
1831 EXPECT_TRUE(resolver
.pending_requests().empty());
1833 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
1835 // Now that the PAC script is downloaded, it will have been sent to the proxy
1837 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
1838 resolver
.pending_set_pac_script_request()->script_data()->utf16());
1839 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
1841 ASSERT_EQ(2u, resolver
.pending_requests().size());
1842 EXPECT_EQ(GURL("http://request1"), resolver
.pending_requests()[0]->url());
1843 EXPECT_EQ(GURL("http://request2"), resolver
.pending_requests()[1]->url());
1846 // Test cancellation of a request, while the PAC script is being fetched.
1847 TEST_F(ProxyServiceTest
, CancelWhilePACFetching
) {
1848 MockProxyConfigService
* config_service
=
1849 new MockProxyConfigService("http://foopy/proxy.pac");
1851 MockAsyncProxyResolverExpectsBytes resolver
;
1853 ProxyService
service(
1855 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
1857 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
1858 service
.SetProxyScriptFetchers(fetcher
,
1859 new DoNothingDhcpProxyScriptFetcher());
1861 // Start 3 requests.
1863 TestCompletionCallback callback1
;
1864 ProxyService::PacRequest
* request1
;
1865 BoundTestNetLog log1
;
1867 service
.ResolveProxy(GURL("http://request1"), LOAD_NORMAL
, &info1
,
1868 callback1
.callback(), &request1
, NULL
, log1
.bound());
1869 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1871 // The first request should have triggered download of PAC script.
1872 EXPECT_TRUE(fetcher
->has_pending_request());
1873 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
1876 TestCompletionCallback callback2
;
1877 ProxyService::PacRequest
* request2
;
1878 rv
= service
.ResolveProxy(GURL("http://request2"), LOAD_NORMAL
, &info2
,
1879 callback2
.callback(), &request2
, NULL
,
1881 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1884 TestCompletionCallback callback3
;
1885 rv
= service
.ResolveProxy(GURL("http://request3"), LOAD_NORMAL
, &info3
,
1886 callback3
.callback(), NULL
, NULL
, BoundNetLog());
1887 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1889 // Nothing has been sent to the resolver yet.
1890 EXPECT_TRUE(resolver
.pending_requests().empty());
1892 // Cancel the first 2 requests.
1893 service
.CancelPacRequest(request1
);
1894 service
.CancelPacRequest(request2
);
1896 // At this point the ProxyService should be waiting for the
1897 // ProxyScriptFetcher to invoke its completion callback, notifying it of
1898 // PAC script download completion.
1899 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
1901 // Now that the PAC script is downloaded, it will have been sent to the
1903 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
1904 resolver
.pending_set_pac_script_request()->script_data()->utf16());
1905 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
1907 ASSERT_EQ(1u, resolver
.pending_requests().size());
1908 EXPECT_EQ(GURL("http://request3"), resolver
.pending_requests()[0]->url());
1910 // Complete all the requests.
1911 resolver
.pending_requests()[0]->results()->UseNamedProxy("request3:80");
1912 resolver
.pending_requests()[0]->CompleteNow(OK
);
1914 EXPECT_EQ(OK
, callback3
.WaitForResult());
1915 EXPECT_EQ("request3:80", info3
.proxy_server().ToURI());
1917 EXPECT_TRUE(resolver
.cancelled_requests().empty());
1919 EXPECT_FALSE(callback1
.have_result()); // Cancelled.
1920 EXPECT_FALSE(callback2
.have_result()); // Cancelled.
1922 TestNetLog::CapturedEntryList entries1
;
1923 log1
.GetEntries(&entries1
);
1925 // Check the NetLog for request 1 (which was cancelled) got filled properly.
1926 EXPECT_EQ(4u, entries1
.size());
1927 EXPECT_TRUE(LogContainsBeginEvent(
1928 entries1
, 0, NetLog::TYPE_PROXY_SERVICE
));
1929 EXPECT_TRUE(LogContainsBeginEvent(
1930 entries1
, 1, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC
));
1931 // Note that TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC is never completed before
1932 // the cancellation occured.
1933 EXPECT_TRUE(LogContainsEvent(
1934 entries1
, 2, NetLog::TYPE_CANCELLED
, NetLog::PHASE_NONE
));
1935 EXPECT_TRUE(LogContainsEndEvent(
1936 entries1
, 3, NetLog::TYPE_PROXY_SERVICE
));
1939 // Test that if auto-detect fails, we fall-back to the custom pac.
1940 TEST_F(ProxyServiceTest
, FallbackFromAutodetectToCustomPac
) {
1942 config
.set_auto_detect(true);
1943 config
.set_pac_url(GURL("http://foopy/proxy.pac"));
1944 config
.proxy_rules().ParseFromString("http=foopy:80"); // Won't be used.
1946 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
1947 MockAsyncProxyResolverExpectsBytes resolver
;
1948 ProxyService
service(
1950 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
1952 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
1953 service
.SetProxyScriptFetchers(fetcher
,
1954 new DoNothingDhcpProxyScriptFetcher());
1956 // Start 2 requests.
1959 TestCompletionCallback callback1
;
1961 service
.ResolveProxy(GURL("http://request1"), LOAD_NORMAL
, &info1
,
1962 callback1
.callback(), NULL
, NULL
, BoundNetLog());
1963 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1966 TestCompletionCallback callback2
;
1967 ProxyService::PacRequest
* request2
;
1968 rv
= service
.ResolveProxy(GURL("http://request2"), LOAD_NORMAL
, &info2
,
1969 callback2
.callback(), &request2
, NULL
,
1971 EXPECT_EQ(ERR_IO_PENDING
, rv
);
1973 // Check that nothing has been sent to the proxy resolver yet.
1974 ASSERT_EQ(0u, resolver
.pending_requests().size());
1976 // It should be trying to auto-detect first -- FAIL the autodetect during
1977 // the script download.
1978 EXPECT_TRUE(fetcher
->has_pending_request());
1979 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher
->pending_request_url());
1980 fetcher
->NotifyFetchCompletion(ERR_FAILED
, std::string());
1982 // Next it should be trying the custom PAC url.
1983 EXPECT_TRUE(fetcher
->has_pending_request());
1984 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
1985 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
1987 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
1988 resolver
.pending_set_pac_script_request()->script_data()->utf16());
1989 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
1991 // Now finally, the pending requests should have been sent to the resolver
1992 // (which was initialized with custom PAC script).
1994 ASSERT_EQ(2u, resolver
.pending_requests().size());
1995 EXPECT_EQ(GURL("http://request1"), resolver
.pending_requests()[0]->url());
1996 EXPECT_EQ(GURL("http://request2"), resolver
.pending_requests()[1]->url());
1998 // Complete the pending requests.
1999 resolver
.pending_requests()[1]->results()->UseNamedProxy("request2:80");
2000 resolver
.pending_requests()[1]->CompleteNow(OK
);
2001 resolver
.pending_requests()[0]->results()->UseNamedProxy("request1:80");
2002 resolver
.pending_requests()[0]->CompleteNow(OK
);
2004 // Verify that requests ran as expected.
2005 EXPECT_EQ(OK
, callback1
.WaitForResult());
2006 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
2007 EXPECT_FALSE(info1
.proxy_resolve_start_time().is_null());
2008 EXPECT_FALSE(info1
.proxy_resolve_end_time().is_null());
2009 EXPECT_LE(info1
.proxy_resolve_start_time(), info1
.proxy_resolve_end_time());
2011 EXPECT_EQ(OK
, callback2
.WaitForResult());
2012 EXPECT_EQ("request2:80", info2
.proxy_server().ToURI());
2013 EXPECT_FALSE(info2
.proxy_resolve_start_time().is_null());
2014 EXPECT_FALSE(info2
.proxy_resolve_end_time().is_null());
2015 EXPECT_LE(info2
.proxy_resolve_start_time(), info2
.proxy_resolve_end_time());
2018 // This is the same test as FallbackFromAutodetectToCustomPac, except
2019 // the auto-detect script fails parsing rather than downloading.
2020 TEST_F(ProxyServiceTest
, FallbackFromAutodetectToCustomPac2
) {
2022 config
.set_auto_detect(true);
2023 config
.set_pac_url(GURL("http://foopy/proxy.pac"));
2024 config
.proxy_rules().ParseFromString("http=foopy:80"); // Won't be used.
2026 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
2027 MockAsyncProxyResolverExpectsBytes resolver
;
2028 ProxyService
service(
2030 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
2032 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
2033 service
.SetProxyScriptFetchers(fetcher
,
2034 new DoNothingDhcpProxyScriptFetcher());
2036 // Start 2 requests.
2039 TestCompletionCallback callback1
;
2041 service
.ResolveProxy(GURL("http://request1"), LOAD_NORMAL
, &info1
,
2042 callback1
.callback(), NULL
, NULL
, BoundNetLog());
2043 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2046 TestCompletionCallback callback2
;
2047 ProxyService::PacRequest
* request2
;
2048 rv
= service
.ResolveProxy(GURL("http://request2"), LOAD_NORMAL
, &info2
,
2049 callback2
.callback(), &request2
, NULL
,
2051 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2053 // Check that nothing has been sent to the proxy resolver yet.
2054 ASSERT_EQ(0u, resolver
.pending_requests().size());
2056 // It should be trying to auto-detect first -- succeed the download.
2057 EXPECT_TRUE(fetcher
->has_pending_request());
2058 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher
->pending_request_url());
2059 fetcher
->NotifyFetchCompletion(OK
, "invalid-script-contents");
2061 // The script contents passed failed basic verification step (since didn't
2062 // contain token FindProxyForURL), so it was never passed to the resolver.
2064 // Next it should be trying the custom PAC url.
2065 EXPECT_TRUE(fetcher
->has_pending_request());
2066 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2067 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
2069 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
2070 resolver
.pending_set_pac_script_request()->script_data()->utf16());
2071 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
2073 // Now finally, the pending requests should have been sent to the resolver
2074 // (which was initialized with custom PAC script).
2076 ASSERT_EQ(2u, resolver
.pending_requests().size());
2077 EXPECT_EQ(GURL("http://request1"), resolver
.pending_requests()[0]->url());
2078 EXPECT_EQ(GURL("http://request2"), resolver
.pending_requests()[1]->url());
2080 // Complete the pending requests.
2081 resolver
.pending_requests()[1]->results()->UseNamedProxy("request2:80");
2082 resolver
.pending_requests()[1]->CompleteNow(OK
);
2083 resolver
.pending_requests()[0]->results()->UseNamedProxy("request1:80");
2084 resolver
.pending_requests()[0]->CompleteNow(OK
);
2086 // Verify that requests ran as expected.
2087 EXPECT_EQ(OK
, callback1
.WaitForResult());
2088 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
2090 EXPECT_EQ(OK
, callback2
.WaitForResult());
2091 EXPECT_EQ("request2:80", info2
.proxy_server().ToURI());
2094 // Test that if all of auto-detect, a custom PAC script, and manual settings
2095 // are given, then we will try them in that order.
2096 TEST_F(ProxyServiceTest
, FallbackFromAutodetectToCustomToManual
) {
2098 config
.set_auto_detect(true);
2099 config
.set_pac_url(GURL("http://foopy/proxy.pac"));
2100 config
.proxy_rules().ParseFromString("http=foopy:80");
2102 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
2103 MockAsyncProxyResolverExpectsBytes resolver
;
2104 ProxyService
service(
2106 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
2108 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
2109 service
.SetProxyScriptFetchers(fetcher
,
2110 new DoNothingDhcpProxyScriptFetcher());
2112 // Start 2 requests.
2115 TestCompletionCallback callback1
;
2117 service
.ResolveProxy(GURL("http://request1"), LOAD_NORMAL
, &info1
,
2118 callback1
.callback(), NULL
, NULL
, BoundNetLog());
2119 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2122 TestCompletionCallback callback2
;
2123 ProxyService::PacRequest
* request2
;
2124 rv
= service
.ResolveProxy(GURL("http://request2"), LOAD_NORMAL
, &info2
,
2125 callback2
.callback(), &request2
, NULL
,
2127 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2129 // Check that nothing has been sent to the proxy resolver yet.
2130 ASSERT_EQ(0u, resolver
.pending_requests().size());
2132 // It should be trying to auto-detect first -- fail the download.
2133 EXPECT_TRUE(fetcher
->has_pending_request());
2134 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher
->pending_request_url());
2135 fetcher
->NotifyFetchCompletion(ERR_FAILED
, std::string());
2137 // Next it should be trying the custom PAC url -- fail the download.
2138 EXPECT_TRUE(fetcher
->has_pending_request());
2139 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2140 fetcher
->NotifyFetchCompletion(ERR_FAILED
, std::string());
2142 // Since we never managed to initialize a resolver, nothing should have been
2144 ASSERT_EQ(0u, resolver
.pending_requests().size());
2146 // Verify that requests ran as expected -- they should have fallen back to
2147 // the manual proxy configuration for HTTP urls.
2148 EXPECT_EQ(OK
, callback1
.WaitForResult());
2149 EXPECT_EQ("foopy:80", info1
.proxy_server().ToURI());
2151 EXPECT_EQ(OK
, callback2
.WaitForResult());
2152 EXPECT_EQ("foopy:80", info2
.proxy_server().ToURI());
2155 // Test that the bypass rules are NOT applied when using autodetect.
2156 TEST_F(ProxyServiceTest
, BypassDoesntApplyToPac
) {
2158 config
.set_auto_detect(true);
2159 config
.set_pac_url(GURL("http://foopy/proxy.pac"));
2160 config
.proxy_rules().ParseFromString("http=foopy:80"); // Not used.
2161 config
.proxy_rules().bypass_rules
.ParseFromString("www.google.com");
2163 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
2164 MockAsyncProxyResolverExpectsBytes resolver
;
2165 ProxyService
service(
2167 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
2169 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
2170 service
.SetProxyScriptFetchers(fetcher
,
2171 new DoNothingDhcpProxyScriptFetcher());
2173 // Start 1 requests.
2176 TestCompletionCallback callback1
;
2178 service
.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL
, &info1
,
2179 callback1
.callback(), NULL
, NULL
, BoundNetLog());
2180 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2182 // Check that nothing has been sent to the proxy resolver yet.
2183 ASSERT_EQ(0u, resolver
.pending_requests().size());
2185 // It should be trying to auto-detect first -- succeed the download.
2186 EXPECT_TRUE(fetcher
->has_pending_request());
2187 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher
->pending_request_url());
2188 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
2190 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
2191 resolver
.pending_set_pac_script_request()->script_data()->utf16());
2192 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
2194 ASSERT_EQ(1u, resolver
.pending_requests().size());
2195 EXPECT_EQ(GURL("http://www.google.com"),
2196 resolver
.pending_requests()[0]->url());
2198 // Complete the pending request.
2199 resolver
.pending_requests()[0]->results()->UseNamedProxy("request1:80");
2200 resolver
.pending_requests()[0]->CompleteNow(OK
);
2202 // Verify that request ran as expected.
2203 EXPECT_EQ(OK
, callback1
.WaitForResult());
2204 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
2206 // Start another request, it should pickup the bypass item.
2208 TestCompletionCallback callback2
;
2209 rv
= service
.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL
, &info2
,
2210 callback2
.callback(), NULL
, NULL
, BoundNetLog());
2211 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2213 ASSERT_EQ(1u, resolver
.pending_requests().size());
2214 EXPECT_EQ(GURL("http://www.google.com"),
2215 resolver
.pending_requests()[0]->url());
2217 // Complete the pending request.
2218 resolver
.pending_requests()[0]->results()->UseNamedProxy("request2:80");
2219 resolver
.pending_requests()[0]->CompleteNow(OK
);
2221 EXPECT_EQ(OK
, callback2
.WaitForResult());
2222 EXPECT_EQ("request2:80", info2
.proxy_server().ToURI());
2225 // Delete the ProxyService while InitProxyResolver has an outstanding
2226 // request to the script fetcher. When run under valgrind, should not
2227 // have any memory errors (used to be that the ProxyScriptFetcher was
2228 // being deleted prior to the InitProxyResolver).
2229 TEST_F(ProxyServiceTest
, DeleteWhileInitProxyResolverHasOutstandingFetch
) {
2230 ProxyConfig config
=
2231 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"));
2233 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
2234 MockAsyncProxyResolverExpectsBytes resolver
;
2235 ProxyService
service(
2237 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
2239 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
2240 service
.SetProxyScriptFetchers(fetcher
,
2241 new DoNothingDhcpProxyScriptFetcher());
2246 TestCompletionCallback callback1
;
2248 service
.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL
, &info1
,
2249 callback1
.callback(), NULL
, NULL
, BoundNetLog());
2250 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2252 // Check that nothing has been sent to the proxy resolver yet.
2253 ASSERT_EQ(0u, resolver
.pending_requests().size());
2255 // InitProxyResolver should have issued a request to the ProxyScriptFetcher
2256 // and be waiting on that to complete.
2257 EXPECT_TRUE(fetcher
->has_pending_request());
2258 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2261 // Delete the ProxyService while InitProxyResolver has an outstanding
2262 // request to the proxy resolver. When run under valgrind, should not
2263 // have any memory errors (used to be that the ProxyResolver was
2264 // being deleted prior to the InitProxyResolver).
2265 TEST_F(ProxyServiceTest
, DeleteWhileInitProxyResolverHasOutstandingSet
) {
2266 MockProxyConfigService
* config_service
=
2267 new MockProxyConfigService("http://foopy/proxy.pac");
2269 MockAsyncProxyResolver resolver
;
2271 ProxyService
service(
2273 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
2275 GURL
url("http://www.google.com/");
2278 TestCompletionCallback callback
;
2279 int rv
= service
.ResolveProxy(url
, LOAD_NORMAL
, &info
, callback
.callback(),
2280 NULL
, NULL
, BoundNetLog());
2281 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2283 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
2284 resolver
.pending_set_pac_script_request()->script_data()->url());
2287 TEST_F(ProxyServiceTest
, ResetProxyConfigService
) {
2288 ProxyConfig config1
;
2289 config1
.proxy_rules().ParseFromString("foopy1:8080");
2290 config1
.set_auto_detect(false);
2291 ProxyService
service(new MockProxyConfigService(config1
), nullptr, NULL
);
2294 TestCompletionCallback callback1
;
2296 service
.ResolveProxy(GURL("http://request1"), LOAD_NORMAL
, &info
,
2297 callback1
.callback(), NULL
, NULL
, BoundNetLog());
2299 EXPECT_EQ("foopy1:8080", info
.proxy_server().ToURI());
2301 ProxyConfig config2
;
2302 config2
.proxy_rules().ParseFromString("foopy2:8080");
2303 config2
.set_auto_detect(false);
2304 service
.ResetConfigService(new MockProxyConfigService(config2
));
2305 TestCompletionCallback callback2
;
2306 rv
= service
.ResolveProxy(GURL("http://request2"), LOAD_NORMAL
, &info
,
2307 callback2
.callback(), NULL
, NULL
, BoundNetLog());
2309 EXPECT_EQ("foopy2:8080", info
.proxy_server().ToURI());
2312 // Test that when going from a configuration that required PAC to one
2313 // that does NOT, we unset the variable |should_use_proxy_resolver_|.
2314 TEST_F(ProxyServiceTest
, UpdateConfigFromPACToDirect
) {
2315 ProxyConfig config
= ProxyConfig::CreateAutoDetect();
2317 MockProxyConfigService
* config_service
= new MockProxyConfigService(config
);
2318 MockAsyncProxyResolver resolver
;
2319 ProxyService
service(
2321 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
2326 TestCompletionCallback callback1
;
2328 service
.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL
, &info1
,
2329 callback1
.callback(), NULL
, NULL
, BoundNetLog());
2330 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2332 // Check that nothing has been sent to the proxy resolver yet.
2333 ASSERT_EQ(0u, resolver
.pending_requests().size());
2335 // Successfully set the autodetect script.
2336 EXPECT_EQ(ProxyResolverScriptData::TYPE_AUTO_DETECT
,
2337 resolver
.pending_set_pac_script_request()->script_data()->type());
2338 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
2340 // Complete the pending request.
2341 ASSERT_EQ(1u, resolver
.pending_requests().size());
2342 resolver
.pending_requests()[0]->results()->UseNamedProxy("request1:80");
2343 resolver
.pending_requests()[0]->CompleteNow(OK
);
2345 // Verify that request ran as expected.
2346 EXPECT_EQ(OK
, callback1
.WaitForResult());
2347 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
2349 // Force the ProxyService to pull down a new proxy configuration.
2350 // (Even though the configuration isn't old/bad).
2352 // This new configuration no longer has auto_detect set, so
2353 // requests should complete synchronously now as direct-connect.
2354 config_service
->SetConfig(ProxyConfig::CreateDirect());
2356 // Start another request -- the effective configuration has changed.
2358 TestCompletionCallback callback2
;
2359 rv
= service
.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL
, &info2
,
2360 callback2
.callback(), NULL
, NULL
, BoundNetLog());
2363 EXPECT_TRUE(info2
.is_direct());
2366 TEST_F(ProxyServiceTest
, NetworkChangeTriggersPacRefetch
) {
2367 MockProxyConfigService
* config_service
=
2368 new MockProxyConfigService("http://foopy/proxy.pac");
2370 MockAsyncProxyResolverExpectsBytes resolver
;
2374 ProxyService
service(
2376 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), &log
);
2378 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
2379 service
.SetProxyScriptFetchers(fetcher
,
2380 new DoNothingDhcpProxyScriptFetcher());
2382 // Disable the "wait after IP address changes" hack, so this unit-test can
2383 // complete quickly.
2384 service
.set_stall_proxy_auto_config_delay(base::TimeDelta());
2389 TestCompletionCallback callback1
;
2391 service
.ResolveProxy(GURL("http://request1"), LOAD_NORMAL
, &info1
,
2392 callback1
.callback(), NULL
, NULL
, BoundNetLog());
2393 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2395 // The first request should have triggered initial download of PAC script.
2396 EXPECT_TRUE(fetcher
->has_pending_request());
2397 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2399 // Nothing has been sent to the resolver yet.
2400 EXPECT_TRUE(resolver
.pending_requests().empty());
2402 // At this point the ProxyService should be waiting for the
2403 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2404 // PAC script download completion.
2405 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
2407 // Now that the PAC script is downloaded, the request will have been sent to
2408 // the proxy resolver.
2409 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
2410 resolver
.pending_set_pac_script_request()->script_data()->utf16());
2411 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
2413 ASSERT_EQ(1u, resolver
.pending_requests().size());
2414 EXPECT_EQ(GURL("http://request1"), resolver
.pending_requests()[0]->url());
2416 // Complete the pending request.
2417 resolver
.pending_requests()[0]->results()->UseNamedProxy("request1:80");
2418 resolver
.pending_requests()[0]->CompleteNow(OK
);
2420 // Wait for completion callback, and verify that the request ran as expected.
2421 EXPECT_EQ(OK
, callback1
.WaitForResult());
2422 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
2424 // Now simluate a change in the network. The ProxyConfigService is still
2425 // going to return the same PAC URL as before, but this URL needs to be
2426 // refetched on the new network.
2427 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
2428 base::MessageLoop::current()->RunUntilIdle(); // Notification happens async.
2430 // Start a second request.
2432 TestCompletionCallback callback2
;
2433 rv
= service
.ResolveProxy(GURL("http://request2"), LOAD_NORMAL
, &info2
,
2434 callback2
.callback(), NULL
, NULL
, BoundNetLog());
2435 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2437 // This second request should have triggered the re-download of the PAC
2438 // script (since we marked the network as having changed).
2439 EXPECT_TRUE(fetcher
->has_pending_request());
2440 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2442 // Nothing has been sent to the resolver yet.
2443 EXPECT_TRUE(resolver
.pending_requests().empty());
2445 // Simulate the PAC script fetch as having completed (this time with
2447 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript2
);
2449 // Now that the PAC script is downloaded, the second request will have been
2450 // sent to the proxy resolver.
2451 EXPECT_EQ(ASCIIToUTF16(kValidPacScript2
),
2452 resolver
.pending_set_pac_script_request()->script_data()->utf16());
2453 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
2455 ASSERT_EQ(1u, resolver
.pending_requests().size());
2456 EXPECT_EQ(GURL("http://request2"), resolver
.pending_requests()[0]->url());
2458 // Complete the pending second request.
2459 resolver
.pending_requests()[0]->results()->UseNamedProxy("request2:80");
2460 resolver
.pending_requests()[0]->CompleteNow(OK
);
2462 // Wait for completion callback, and verify that the request ran as expected.
2463 EXPECT_EQ(OK
, callback2
.WaitForResult());
2464 EXPECT_EQ("request2:80", info2
.proxy_server().ToURI());
2466 // Check that the expected events were output to the log stream. In particular
2467 // PROXY_CONFIG_CHANGED should have only been emitted once (for the initial
2468 // setup), and NOT a second time when the IP address changed.
2469 TestNetLog::CapturedEntryList entries
;
2470 log
.GetEntries(&entries
);
2472 EXPECT_TRUE(LogContainsEntryWithType(entries
, 0,
2473 NetLog::TYPE_PROXY_CONFIG_CHANGED
));
2474 ASSERT_EQ(9u, entries
.size());
2475 for (size_t i
= 1; i
< entries
.size(); ++i
)
2476 EXPECT_NE(NetLog::TYPE_PROXY_CONFIG_CHANGED
, entries
[i
].type
);
2479 // This test verifies that the PAC script specified by the settings is
2480 // periodically polled for changes. Specifically, if the initial fetch fails due
2481 // to a network error, we will eventually re-configure the service to use the
2482 // script once it becomes available.
2483 TEST_F(ProxyServiceTest
, PACScriptRefetchAfterFailure
) {
2484 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2486 ImmediatePollPolicy poll_policy
;
2487 ProxyService::set_pac_script_poll_policy(&poll_policy
);
2489 MockProxyConfigService
* config_service
=
2490 new MockProxyConfigService("http://foopy/proxy.pac");
2492 MockAsyncProxyResolverExpectsBytes resolver
;
2494 ProxyService
service(
2496 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
2498 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
2499 service
.SetProxyScriptFetchers(fetcher
,
2500 new DoNothingDhcpProxyScriptFetcher());
2505 TestCompletionCallback callback1
;
2507 service
.ResolveProxy(GURL("http://request1"), LOAD_NORMAL
, &info1
,
2508 callback1
.callback(), NULL
, NULL
, BoundNetLog());
2509 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2511 // The first request should have triggered initial download of PAC script.
2512 EXPECT_TRUE(fetcher
->has_pending_request());
2513 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2515 // Nothing has been sent to the resolver yet.
2516 EXPECT_TRUE(resolver
.pending_requests().empty());
2518 // At this point the ProxyService should be waiting for the
2519 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2520 // PAC script download completion.
2522 // We simulate a failed download attempt, the proxy service should now
2523 // fall-back to DIRECT connections.
2524 fetcher
->NotifyFetchCompletion(ERR_FAILED
, std::string());
2526 ASSERT_TRUE(resolver
.pending_requests().empty());
2528 // Wait for completion callback, and verify it used DIRECT.
2529 EXPECT_EQ(OK
, callback1
.WaitForResult());
2530 EXPECT_TRUE(info1
.is_direct());
2532 // At this point we have initialized the proxy service using a PAC script,
2533 // however it failed and fell-back to DIRECT.
2535 // A background task to periodically re-check the PAC script for validity will
2536 // have been started. We will now wait for the next download attempt to start.
2538 // Note that we shouldn't have to wait long here, since our test enables a
2539 // special unit-test mode.
2540 fetcher
->WaitUntilFetch();
2542 ASSERT_TRUE(resolver
.pending_requests().empty());
2544 // Make sure that our background checker is trying to download the expected
2545 // PAC script (same one as before). This time we will simulate a successful
2546 // download of the script.
2547 EXPECT_TRUE(fetcher
->has_pending_request());
2548 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2549 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
2551 base::MessageLoop::current()->RunUntilIdle();
2553 // Now that the PAC script is downloaded, it should be used to initialize the
2554 // ProxyResolver. Simulate a successful parse.
2555 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
2556 resolver
.pending_set_pac_script_request()->script_data()->utf16());
2557 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
2559 // At this point the ProxyService should have re-configured itself to use the
2560 // PAC script (thereby recovering from the initial fetch failure). We will
2561 // verify that the next Resolve request uses the resolver rather than
2564 // Start a second request.
2566 TestCompletionCallback callback2
;
2567 rv
= service
.ResolveProxy(GURL("http://request2"), LOAD_NORMAL
, &info2
,
2568 callback2
.callback(), NULL
, NULL
, BoundNetLog());
2569 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2571 // Check that it was sent to the resolver.
2572 ASSERT_EQ(1u, resolver
.pending_requests().size());
2573 EXPECT_EQ(GURL("http://request2"), resolver
.pending_requests()[0]->url());
2575 // Complete the pending second request.
2576 resolver
.pending_requests()[0]->results()->UseNamedProxy("request2:80");
2577 resolver
.pending_requests()[0]->CompleteNow(OK
);
2579 // Wait for completion callback, and verify that the request ran as expected.
2580 EXPECT_EQ(OK
, callback2
.WaitForResult());
2581 EXPECT_EQ("request2:80", info2
.proxy_server().ToURI());
2584 // This test verifies that the PAC script specified by the settings is
2585 // periodically polled for changes. Specifically, if the initial fetch succeeds,
2586 // however at a later time its *contents* change, we will eventually
2587 // re-configure the service to use the new script.
2588 TEST_F(ProxyServiceTest
, PACScriptRefetchAfterContentChange
) {
2589 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2591 ImmediatePollPolicy poll_policy
;
2592 ProxyService::set_pac_script_poll_policy(&poll_policy
);
2594 MockProxyConfigService
* config_service
=
2595 new MockProxyConfigService("http://foopy/proxy.pac");
2597 MockAsyncProxyResolverExpectsBytes resolver
;
2599 ProxyService
service(
2601 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
2603 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
2604 service
.SetProxyScriptFetchers(fetcher
,
2605 new DoNothingDhcpProxyScriptFetcher());
2610 TestCompletionCallback callback1
;
2612 service
.ResolveProxy(GURL("http://request1"), LOAD_NORMAL
, &info1
,
2613 callback1
.callback(), NULL
, NULL
, BoundNetLog());
2614 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2616 // The first request should have triggered initial download of PAC script.
2617 EXPECT_TRUE(fetcher
->has_pending_request());
2618 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2620 // Nothing has been sent to the resolver yet.
2621 EXPECT_TRUE(resolver
.pending_requests().empty());
2623 // At this point the ProxyService should be waiting for the
2624 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2625 // PAC script download completion.
2626 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
2628 // Now that the PAC script is downloaded, the request will have been sent to
2629 // the proxy resolver.
2630 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
2631 resolver
.pending_set_pac_script_request()->script_data()->utf16());
2632 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
2634 ASSERT_EQ(1u, resolver
.pending_requests().size());
2635 EXPECT_EQ(GURL("http://request1"), resolver
.pending_requests()[0]->url());
2637 // Complete the pending request.
2638 resolver
.pending_requests()[0]->results()->UseNamedProxy("request1:80");
2639 resolver
.pending_requests()[0]->CompleteNow(OK
);
2641 // Wait for completion callback, and verify that the request ran as expected.
2642 EXPECT_EQ(OK
, callback1
.WaitForResult());
2643 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
2645 // At this point we have initialized the proxy service using a PAC script.
2647 // A background task to periodically re-check the PAC script for validity will
2648 // have been started. We will now wait for the next download attempt to start.
2650 // Note that we shouldn't have to wait long here, since our test enables a
2651 // special unit-test mode.
2652 fetcher
->WaitUntilFetch();
2654 ASSERT_TRUE(resolver
.pending_requests().empty());
2656 // Make sure that our background checker is trying to download the expected
2657 // PAC script (same one as before). This time we will simulate a successful
2658 // download of a DIFFERENT script.
2659 EXPECT_TRUE(fetcher
->has_pending_request());
2660 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2661 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript2
);
2663 base::MessageLoop::current()->RunUntilIdle();
2665 // Now that the PAC script is downloaded, it should be used to initialize the
2666 // ProxyResolver. Simulate a successful parse.
2667 EXPECT_EQ(ASCIIToUTF16(kValidPacScript2
),
2668 resolver
.pending_set_pac_script_request()->script_data()->utf16());
2669 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
2671 // At this point the ProxyService should have re-configured itself to use the
2674 // Start a second request.
2676 TestCompletionCallback callback2
;
2677 rv
= service
.ResolveProxy(GURL("http://request2"), LOAD_NORMAL
, &info2
,
2678 callback2
.callback(), NULL
, NULL
, BoundNetLog());
2679 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2681 // Check that it was sent to the resolver.
2682 ASSERT_EQ(1u, resolver
.pending_requests().size());
2683 EXPECT_EQ(GURL("http://request2"), resolver
.pending_requests()[0]->url());
2685 // Complete the pending second request.
2686 resolver
.pending_requests()[0]->results()->UseNamedProxy("request2:80");
2687 resolver
.pending_requests()[0]->CompleteNow(OK
);
2689 // Wait for completion callback, and verify that the request ran as expected.
2690 EXPECT_EQ(OK
, callback2
.WaitForResult());
2691 EXPECT_EQ("request2:80", info2
.proxy_server().ToURI());
2694 // This test verifies that the PAC script specified by the settings is
2695 // periodically polled for changes. Specifically, if the initial fetch succeeds
2696 // and so does the next poll, however the contents of the downloaded script
2697 // have NOT changed, then we do not bother to re-initialize the proxy resolver.
2698 TEST_F(ProxyServiceTest
, PACScriptRefetchAfterContentUnchanged
) {
2699 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2701 ImmediatePollPolicy poll_policy
;
2702 ProxyService::set_pac_script_poll_policy(&poll_policy
);
2704 MockProxyConfigService
* config_service
=
2705 new MockProxyConfigService("http://foopy/proxy.pac");
2707 MockAsyncProxyResolverExpectsBytes resolver
;
2709 ProxyService
service(
2711 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
2713 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
2714 service
.SetProxyScriptFetchers(fetcher
,
2715 new DoNothingDhcpProxyScriptFetcher());
2720 TestCompletionCallback callback1
;
2722 service
.ResolveProxy(GURL("http://request1"), LOAD_NORMAL
, &info1
,
2723 callback1
.callback(), NULL
, NULL
, BoundNetLog());
2724 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2726 // The first request should have triggered initial download of PAC script.
2727 EXPECT_TRUE(fetcher
->has_pending_request());
2728 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2730 // Nothing has been sent to the resolver yet.
2731 EXPECT_TRUE(resolver
.pending_requests().empty());
2733 // At this point the ProxyService should be waiting for the
2734 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2735 // PAC script download completion.
2736 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
2738 // Now that the PAC script is downloaded, the request will have been sent to
2739 // the proxy resolver.
2740 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
2741 resolver
.pending_set_pac_script_request()->script_data()->utf16());
2742 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
2744 ASSERT_EQ(1u, resolver
.pending_requests().size());
2745 EXPECT_EQ(GURL("http://request1"), resolver
.pending_requests()[0]->url());
2747 // Complete the pending request.
2748 resolver
.pending_requests()[0]->results()->UseNamedProxy("request1:80");
2749 resolver
.pending_requests()[0]->CompleteNow(OK
);
2751 // Wait for completion callback, and verify that the request ran as expected.
2752 EXPECT_EQ(OK
, callback1
.WaitForResult());
2753 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
2755 // At this point we have initialized the proxy service using a PAC script.
2757 // A background task to periodically re-check the PAC script for validity will
2758 // have been started. We will now wait for the next download attempt to start.
2760 // Note that we shouldn't have to wait long here, since our test enables a
2761 // special unit-test mode.
2762 fetcher
->WaitUntilFetch();
2764 ASSERT_TRUE(resolver
.pending_requests().empty());
2766 // Make sure that our background checker is trying to download the expected
2767 // PAC script (same one as before). We will simulate the same response as
2768 // last time (i.e. the script is unchanged).
2769 EXPECT_TRUE(fetcher
->has_pending_request());
2770 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2771 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
2773 base::MessageLoop::current()->RunUntilIdle();
2775 ASSERT_FALSE(resolver
.has_pending_set_pac_script_request());
2777 // At this point the ProxyService is still running the same PAC script as
2780 // Start a second request.
2782 TestCompletionCallback callback2
;
2783 rv
= service
.ResolveProxy(GURL("http://request2"), LOAD_NORMAL
, &info2
,
2784 callback2
.callback(), NULL
, NULL
, BoundNetLog());
2785 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2787 // Check that it was sent to the resolver.
2788 ASSERT_EQ(1u, resolver
.pending_requests().size());
2789 EXPECT_EQ(GURL("http://request2"), resolver
.pending_requests()[0]->url());
2791 // Complete the pending second request.
2792 resolver
.pending_requests()[0]->results()->UseNamedProxy("request2:80");
2793 resolver
.pending_requests()[0]->CompleteNow(OK
);
2795 // Wait for completion callback, and verify that the request ran as expected.
2796 EXPECT_EQ(OK
, callback2
.WaitForResult());
2797 EXPECT_EQ("request2:80", info2
.proxy_server().ToURI());
2800 // This test verifies that the PAC script specified by the settings is
2801 // periodically polled for changes. Specifically, if the initial fetch succeeds,
2802 // however at a later time it starts to fail, we should re-configure the
2803 // ProxyService to stop using that PAC script.
2804 TEST_F(ProxyServiceTest
, PACScriptRefetchAfterSuccess
) {
2805 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2807 ImmediatePollPolicy poll_policy
;
2808 ProxyService::set_pac_script_poll_policy(&poll_policy
);
2810 MockProxyConfigService
* config_service
=
2811 new MockProxyConfigService("http://foopy/proxy.pac");
2813 MockAsyncProxyResolverExpectsBytes resolver
;
2815 ProxyService
service(
2817 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
2819 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
2820 service
.SetProxyScriptFetchers(fetcher
,
2821 new DoNothingDhcpProxyScriptFetcher());
2826 TestCompletionCallback callback1
;
2828 service
.ResolveProxy(GURL("http://request1"), LOAD_NORMAL
, &info1
,
2829 callback1
.callback(), NULL
, NULL
, BoundNetLog());
2830 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2832 // The first request should have triggered initial download of PAC script.
2833 EXPECT_TRUE(fetcher
->has_pending_request());
2834 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2836 // Nothing has been sent to the resolver yet.
2837 EXPECT_TRUE(resolver
.pending_requests().empty());
2839 // At this point the ProxyService should be waiting for the
2840 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2841 // PAC script download completion.
2842 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
2844 // Now that the PAC script is downloaded, the request will have been sent to
2845 // the proxy resolver.
2846 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
2847 resolver
.pending_set_pac_script_request()->script_data()->utf16());
2848 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
2850 ASSERT_EQ(1u, resolver
.pending_requests().size());
2851 EXPECT_EQ(GURL("http://request1"), resolver
.pending_requests()[0]->url());
2853 // Complete the pending request.
2854 resolver
.pending_requests()[0]->results()->UseNamedProxy("request1:80");
2855 resolver
.pending_requests()[0]->CompleteNow(OK
);
2857 // Wait for completion callback, and verify that the request ran as expected.
2858 EXPECT_EQ(OK
, callback1
.WaitForResult());
2859 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
2861 // At this point we have initialized the proxy service using a PAC script.
2863 // A background task to periodically re-check the PAC script for validity will
2864 // have been started. We will now wait for the next download attempt to start.
2866 // Note that we shouldn't have to wait long here, since our test enables a
2867 // special unit-test mode.
2868 fetcher
->WaitUntilFetch();
2870 ASSERT_TRUE(resolver
.pending_requests().empty());
2872 // Make sure that our background checker is trying to download the expected
2873 // PAC script (same one as before). This time we will simulate a failure
2874 // to download the script.
2875 EXPECT_TRUE(fetcher
->has_pending_request());
2876 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2877 fetcher
->NotifyFetchCompletion(ERR_FAILED
, std::string());
2879 base::MessageLoop::current()->RunUntilIdle();
2881 // At this point the ProxyService should have re-configured itself to use
2882 // DIRECT connections rather than the given proxy resolver.
2884 // Start a second request.
2886 TestCompletionCallback callback2
;
2887 rv
= service
.ResolveProxy(GURL("http://request2"), LOAD_NORMAL
, &info2
,
2888 callback2
.callback(), NULL
, NULL
, BoundNetLog());
2890 EXPECT_TRUE(info2
.is_direct());
2893 // Tests that the code which decides at what times to poll the PAC
2894 // script follows the expected policy.
2895 TEST_F(ProxyServiceTest
, PACScriptPollingPolicy
) {
2896 // Retrieve the internal polling policy implementation used by ProxyService.
2897 scoped_ptr
<ProxyService::PacPollPolicy
> policy
=
2898 ProxyService::CreateDefaultPacPollPolicy();
2901 ProxyService::PacPollPolicy::Mode mode
;
2902 const base::TimeDelta initial_delay
= base::TimeDelta::FromMilliseconds(-1);
2903 base::TimeDelta delay
= initial_delay
;
2905 // --------------------------------------------------
2906 // Test the poll sequence in response to a failure.
2907 // --------------------------------------------------
2908 error
= ERR_NAME_NOT_RESOLVED
;
2911 mode
= policy
->GetNextDelay(error
, initial_delay
, &delay
);
2912 EXPECT_EQ(8, delay
.InSeconds());
2913 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_USE_TIMER
, mode
);
2916 mode
= policy
->GetNextDelay(error
, delay
, &delay
);
2917 EXPECT_EQ(32, delay
.InSeconds());
2918 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY
, mode
);
2921 mode
= policy
->GetNextDelay(error
, delay
, &delay
);
2922 EXPECT_EQ(120, delay
.InSeconds());
2923 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY
, mode
);
2926 mode
= policy
->GetNextDelay(error
, delay
, &delay
);
2927 EXPECT_EQ(14400, delay
.InSeconds());
2928 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY
, mode
);
2931 mode
= policy
->GetNextDelay(error
, delay
, &delay
);
2932 EXPECT_EQ(14400, delay
.InSeconds());
2933 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY
, mode
);
2935 // --------------------------------------------------
2936 // Test the poll sequence in response to a success.
2937 // --------------------------------------------------
2941 mode
= policy
->GetNextDelay(error
, initial_delay
, &delay
);
2942 EXPECT_EQ(43200, delay
.InSeconds());
2943 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY
, mode
);
2946 mode
= policy
->GetNextDelay(error
, delay
, &delay
);
2947 EXPECT_EQ(43200, delay
.InSeconds());
2948 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY
, mode
);
2951 mode
= policy
->GetNextDelay(error
, delay
, &delay
);
2952 EXPECT_EQ(43200, delay
.InSeconds());
2953 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY
, mode
);
2956 // This tests the polling of the PAC script. Specifically, it tests that
2957 // polling occurs in response to user activity.
2958 TEST_F(ProxyServiceTest
, PACScriptRefetchAfterActivity
) {
2959 ImmediateAfterActivityPollPolicy poll_policy
;
2960 ProxyService::set_pac_script_poll_policy(&poll_policy
);
2962 MockProxyConfigService
* config_service
=
2963 new MockProxyConfigService("http://foopy/proxy.pac");
2965 MockAsyncProxyResolverExpectsBytes resolver
;
2967 ProxyService
service(
2969 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
2971 MockProxyScriptFetcher
* fetcher
= new MockProxyScriptFetcher
;
2972 service
.SetProxyScriptFetchers(fetcher
,
2973 new DoNothingDhcpProxyScriptFetcher());
2978 TestCompletionCallback callback1
;
2980 service
.ResolveProxy(GURL("http://request1"), LOAD_NORMAL
, &info1
,
2981 callback1
.callback(), NULL
, NULL
, BoundNetLog());
2982 EXPECT_EQ(ERR_IO_PENDING
, rv
);
2984 // The first request should have triggered initial download of PAC script.
2985 EXPECT_TRUE(fetcher
->has_pending_request());
2986 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
2988 // Nothing has been sent to the resolver yet.
2989 EXPECT_TRUE(resolver
.pending_requests().empty());
2991 // At this point the ProxyService should be waiting for the
2992 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2993 // PAC script download completion.
2994 fetcher
->NotifyFetchCompletion(OK
, kValidPacScript1
);
2996 // Now that the PAC script is downloaded, the request will have been sent to
2997 // the proxy resolver.
2998 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1
),
2999 resolver
.pending_set_pac_script_request()->script_data()->utf16());
3000 resolver
.pending_set_pac_script_request()->CompleteNow(OK
);
3002 ASSERT_EQ(1u, resolver
.pending_requests().size());
3003 EXPECT_EQ(GURL("http://request1"), resolver
.pending_requests()[0]->url());
3005 // Complete the pending request.
3006 resolver
.pending_requests()[0]->results()->UseNamedProxy("request1:80");
3007 resolver
.pending_requests()[0]->CompleteNow(OK
);
3009 // Wait for completion callback, and verify that the request ran as expected.
3010 EXPECT_EQ(OK
, callback1
.WaitForResult());
3011 EXPECT_EQ("request1:80", info1
.proxy_server().ToURI());
3013 // At this point we have initialized the proxy service using a PAC script.
3014 // Our PAC poller is set to update ONLY in response to network activity,
3015 // (i.e. another call to ResolveProxy()).
3017 ASSERT_FALSE(fetcher
->has_pending_request());
3018 ASSERT_TRUE(resolver
.pending_requests().empty());
3020 // Start a second request.
3022 TestCompletionCallback callback2
;
3023 rv
= service
.ResolveProxy(GURL("http://request2"), LOAD_NORMAL
, &info2
,
3024 callback2
.callback(), NULL
, NULL
, BoundNetLog());
3025 EXPECT_EQ(ERR_IO_PENDING
, rv
);
3027 // This request should have sent work to the resolver; complete it.
3028 ASSERT_EQ(1u, resolver
.pending_requests().size());
3029 EXPECT_EQ(GURL("http://request2"), resolver
.pending_requests()[0]->url());
3030 resolver
.pending_requests()[0]->results()->UseNamedProxy("request2:80");
3031 resolver
.pending_requests()[0]->CompleteNow(OK
);
3033 EXPECT_EQ(OK
, callback2
.WaitForResult());
3034 EXPECT_EQ("request2:80", info2
.proxy_server().ToURI());
3036 // In response to getting that resolve request, the poller should have
3037 // started the next poll, and made it as far as to request the download.
3039 EXPECT_TRUE(fetcher
->has_pending_request());
3040 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher
->pending_request_url());
3042 // This time we will fail the download, to simulate a PAC script change.
3043 fetcher
->NotifyFetchCompletion(ERR_FAILED
, std::string());
3045 // Drain the message loop, so ProxyService is notified of the change
3046 // and has a chance to re-configure itself.
3047 base::MessageLoop::current()->RunUntilIdle();
3049 // Start a third request -- this time we expect to get a direct connection
3050 // since the PAC script poller experienced a failure.
3052 TestCompletionCallback callback3
;
3053 rv
= service
.ResolveProxy(GURL("http://request3"), LOAD_NORMAL
, &info3
,
3054 callback3
.callback(), NULL
, NULL
, BoundNetLog());
3056 EXPECT_TRUE(info3
.is_direct());
3059 // Test that the synchronous resolution fails when a PAC script is active.
3060 TEST_F(ProxyServiceTest
, SynchronousWithPAC
) {
3061 MockProxyConfigService
* config_service
=
3062 new MockProxyConfigService("http://foopy/proxy.pac");
3064 MockAsyncProxyResolver resolver
;
3066 ProxyService
service(
3068 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
3070 GURL
url("http://www.google.com/");
3074 BoundTestNetLog log
;
3076 bool synchronous_success
= service
.TryResolveProxySynchronously(
3077 url
, LOAD_NORMAL
, &info
, NULL
, log
.bound());
3078 EXPECT_FALSE(synchronous_success
);
3080 // No request should have been queued.
3081 EXPECT_EQ(0u, resolver
.pending_requests().size());
3083 // |info| should not have been modified.
3084 EXPECT_TRUE(info
.is_direct());
3087 // Test that synchronous results are returned correctly if a fixed proxy
3088 // configuration is active.
3089 TEST_F(ProxyServiceTest
, SynchronousWithFixedConfiguration
) {
3091 config
.proxy_rules().ParseFromString("foopy1:8080");
3092 config
.set_auto_detect(false);
3094 MockAsyncProxyResolver resolver
;
3096 ProxyService
service(
3097 new MockProxyConfigService(config
),
3098 make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver
)), NULL
);
3100 GURL
url("http://www.google.com/");
3103 BoundTestNetLog log
;
3105 bool synchronous_success
= service
.TryResolveProxySynchronously(
3106 url
, LOAD_NORMAL
, &info
, NULL
, log
.bound());
3107 EXPECT_TRUE(synchronous_success
);
3108 EXPECT_FALSE(info
.is_direct());
3109 EXPECT_EQ("foopy1", info
.proxy_server().host_port_pair().host());
3111 // No request should have been queued.
3112 EXPECT_EQ(0u, resolver
.pending_requests().size());