Roll src/third_party/WebKit a2aeeb7:6373c4f (svn 198318:198336)
[chromium-blink-merge.git] / net / proxy / proxy_service_unittest.cc
blob6d6c747d954df093958bc2256107ebc9f5e5982b
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/proxy/proxy_service.h"
7 #include <vector>
9 #include "base/format_macros.h"
10 #include "base/logging.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "net/base/load_flags.h"
14 #include "net/base/net_errors.h"
15 #include "net/base/network_delegate_impl.h"
16 #include "net/base/test_completion_callback.h"
17 #include "net/log/net_log.h"
18 #include "net/log/test_net_log.h"
19 #include "net/log/test_net_log_entry.h"
20 #include "net/log/test_net_log_util.h"
21 #include "net/proxy/dhcp_proxy_script_fetcher.h"
22 #include "net/proxy/mock_proxy_resolver.h"
23 #include "net/proxy/mock_proxy_script_fetcher.h"
24 #include "net/proxy/proxy_config_service.h"
25 #include "net/proxy/proxy_resolver.h"
26 #include "net/proxy/proxy_script_fetcher.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28 #include "url/gurl.h"
30 using base::ASCIIToUTF16;
32 // TODO(eroman): Write a test which exercises
33 // ProxyService::SuspendAllPendingRequests().
34 namespace net {
35 namespace {
37 // This polling policy will decide to poll every 1 ms.
38 class ImmediatePollPolicy : public ProxyService::PacPollPolicy {
39 public:
40 ImmediatePollPolicy() {}
42 Mode GetNextDelay(int error,
43 base::TimeDelta current_delay,
44 base::TimeDelta* next_delay) const override {
45 *next_delay = base::TimeDelta::FromMilliseconds(1);
46 return MODE_USE_TIMER;
49 private:
50 DISALLOW_COPY_AND_ASSIGN(ImmediatePollPolicy);
53 // This polling policy chooses a fantastically large delay. In other words, it
54 // will never trigger a poll
55 class NeverPollPolicy : public ProxyService::PacPollPolicy {
56 public:
57 NeverPollPolicy() {}
59 Mode GetNextDelay(int error,
60 base::TimeDelta current_delay,
61 base::TimeDelta* next_delay) const override {
62 *next_delay = base::TimeDelta::FromDays(60);
63 return MODE_USE_TIMER;
66 private:
67 DISALLOW_COPY_AND_ASSIGN(NeverPollPolicy);
70 // This polling policy starts a poll immediately after network activity.
71 class ImmediateAfterActivityPollPolicy : public ProxyService::PacPollPolicy {
72 public:
73 ImmediateAfterActivityPollPolicy() {}
75 Mode GetNextDelay(int error,
76 base::TimeDelta current_delay,
77 base::TimeDelta* next_delay) const override {
78 *next_delay = base::TimeDelta();
79 return MODE_START_AFTER_ACTIVITY;
82 private:
83 DISALLOW_COPY_AND_ASSIGN(ImmediateAfterActivityPollPolicy);
86 // This test fixture is used to partially disable the background polling done by
87 // the ProxyService (which it uses to detect whenever its PAC script contents or
88 // WPAD results have changed).
90 // We disable the feature by setting the poll interval to something really
91 // large, so it will never actually be reached even on the slowest bots that run
92 // these tests.
94 // We disable the polling in order to avoid any timing dependencies in the
95 // tests. If the bot were to run the tests very slowly and we hadn't disabled
96 // polling, then it might start a background re-try in the middle of our test
97 // and confuse our expectations leading to flaky failures.
99 // The tests which verify the polling code re-enable the polling behavior but
100 // are careful to avoid timing problems.
101 class ProxyServiceTest : public testing::Test {
102 protected:
103 void SetUp() override {
104 testing::Test::SetUp();
105 previous_policy_ =
106 ProxyService::set_pac_script_poll_policy(&never_poll_policy_);
109 void TearDown() override {
110 // Restore the original policy.
111 ProxyService::set_pac_script_poll_policy(previous_policy_);
112 testing::Test::TearDown();
115 private:
116 NeverPollPolicy never_poll_policy_;
117 const ProxyService::PacPollPolicy* previous_policy_;
120 const char kValidPacScript1[] = "pac-script-v1-FindProxyForURL";
121 const char kValidPacScript2[] = "pac-script-v2-FindProxyForURL";
123 class MockProxyConfigService: public ProxyConfigService {
124 public:
125 explicit MockProxyConfigService(const ProxyConfig& config)
126 : availability_(CONFIG_VALID),
127 config_(config) {
130 explicit MockProxyConfigService(const std::string& pac_url)
131 : availability_(CONFIG_VALID),
132 config_(ProxyConfig::CreateFromCustomPacURL(GURL(pac_url))) {
135 void AddObserver(Observer* observer) override {
136 observers_.AddObserver(observer);
139 void RemoveObserver(Observer* observer) override {
140 observers_.RemoveObserver(observer);
143 ConfigAvailability GetLatestProxyConfig(ProxyConfig* results) override {
144 if (availability_ == CONFIG_VALID)
145 *results = config_;
146 return availability_;
149 void SetConfig(const ProxyConfig& config) {
150 availability_ = CONFIG_VALID;
151 config_ = config;
152 FOR_EACH_OBSERVER(Observer, observers_,
153 OnProxyConfigChanged(config_, availability_));
156 private:
157 ConfigAvailability availability_;
158 ProxyConfig config_;
159 base::ObserverList<Observer, true> observers_;
162 // A test network delegate that exercises the OnResolveProxy callback.
163 class TestResolveProxyNetworkDelegate : public NetworkDelegateImpl {
164 public:
165 TestResolveProxyNetworkDelegate()
166 : on_resolve_proxy_called_(false),
167 add_proxy_(false),
168 remove_proxy_(false),
169 proxy_service_(NULL) {
172 void OnResolveProxy(const GURL& url,
173 int load_flags,
174 const ProxyService& proxy_service,
175 ProxyInfo* result) override {
176 on_resolve_proxy_called_ = true;
177 proxy_service_ = &proxy_service;
178 DCHECK(!add_proxy_ || !remove_proxy_);
179 if (add_proxy_) {
180 result->UseNamedProxy("delegate_proxy.com");
181 } else if (remove_proxy_) {
182 result->UseDirect();
186 bool on_resolve_proxy_called() const {
187 return on_resolve_proxy_called_;
190 void set_add_proxy(bool add_proxy) {
191 add_proxy_ = add_proxy;
194 void set_remove_proxy(bool remove_proxy) {
195 remove_proxy_ = remove_proxy;
198 const ProxyService* proxy_service() const {
199 return proxy_service_;
202 private:
203 bool on_resolve_proxy_called_;
204 bool add_proxy_;
205 bool remove_proxy_;
206 const ProxyService* proxy_service_;
209 // A test network delegate that exercises the OnProxyFallback callback.
210 class TestProxyFallbackNetworkDelegate : public NetworkDelegateImpl {
211 public:
212 TestProxyFallbackNetworkDelegate()
213 : on_proxy_fallback_called_(false),
214 proxy_fallback_net_error_(OK) {
217 void OnProxyFallback(const ProxyServer& proxy_server,
218 int net_error) override {
219 proxy_server_ = proxy_server;
220 proxy_fallback_net_error_ = net_error;
221 on_proxy_fallback_called_ = true;
224 bool on_proxy_fallback_called() const {
225 return on_proxy_fallback_called_;
228 const ProxyServer& proxy_server() const {
229 return proxy_server_;
232 int proxy_fallback_net_error() const {
233 return proxy_fallback_net_error_;
236 private:
237 bool on_proxy_fallback_called_;
238 ProxyServer proxy_server_;
239 int proxy_fallback_net_error_;
242 } // namespace
244 TEST_F(ProxyServiceTest, Direct) {
245 MockAsyncProxyResolverFactory* factory =
246 new MockAsyncProxyResolverFactory(false);
247 ProxyService service(new MockProxyConfigService(ProxyConfig::CreateDirect()),
248 make_scoped_ptr(factory), NULL);
250 GURL url("http://www.google.com/");
252 ProxyInfo info;
253 TestCompletionCallback callback;
254 BoundTestNetLog log;
255 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
256 NULL, NULL, log.bound());
257 EXPECT_EQ(OK, rv);
258 EXPECT_TRUE(factory->pending_requests().empty());
260 EXPECT_TRUE(info.is_direct());
261 EXPECT_TRUE(info.proxy_resolve_start_time().is_null());
262 EXPECT_TRUE(info.proxy_resolve_end_time().is_null());
264 // Check the NetLog was filled correctly.
265 TestNetLogEntry::List entries;
266 log.GetEntries(&entries);
268 EXPECT_EQ(3u, entries.size());
269 EXPECT_TRUE(LogContainsBeginEvent(
270 entries, 0, NetLog::TYPE_PROXY_SERVICE));
271 EXPECT_TRUE(LogContainsEvent(
272 entries, 1, NetLog::TYPE_PROXY_SERVICE_RESOLVED_PROXY_LIST,
273 NetLog::PHASE_NONE));
274 EXPECT_TRUE(LogContainsEndEvent(
275 entries, 2, NetLog::TYPE_PROXY_SERVICE));
278 TEST_F(ProxyServiceTest, OnResolveProxyCallbackAddProxy) {
279 ProxyConfig config;
280 config.proxy_rules().ParseFromString("foopy1:8080");
281 config.set_auto_detect(false);
282 config.proxy_rules().bypass_rules.ParseFromString("*.org");
284 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
286 GURL url("http://www.google.com/");
287 GURL bypass_url("http://internet.org");
289 ProxyInfo info;
290 TestCompletionCallback callback;
291 BoundTestNetLog log;
293 // First, warm up the ProxyService.
294 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
295 NULL, NULL, log.bound());
296 EXPECT_EQ(OK, rv);
298 // Verify that network delegate is invoked.
299 TestResolveProxyNetworkDelegate delegate;
300 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), NULL,
301 &delegate, log.bound());
302 EXPECT_TRUE(delegate.on_resolve_proxy_called());
303 EXPECT_EQ(&service, delegate.proxy_service());
305 // Verify that the NetworkDelegate's behavior is stateless across
306 // invocations of ResolveProxy. Start by having the callback add a proxy
307 // and checking that subsequent requests are not affected.
308 delegate.set_add_proxy(true);
310 // Callback should interpose:
311 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), NULL,
312 &delegate, log.bound());
313 EXPECT_FALSE(info.is_direct());
314 EXPECT_EQ(info.proxy_server().host_port_pair().host(), "delegate_proxy.com");
315 delegate.set_add_proxy(false);
317 // Check non-bypassed URL:
318 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), NULL,
319 &delegate, log.bound());
320 EXPECT_FALSE(info.is_direct());
321 EXPECT_EQ(info.proxy_server().host_port_pair().host(), "foopy1");
323 // Check bypassed URL:
324 rv = service.ResolveProxy(bypass_url, LOAD_NORMAL, &info, callback.callback(),
325 NULL, &delegate, log.bound());
326 EXPECT_TRUE(info.is_direct());
329 TEST_F(ProxyServiceTest, OnResolveProxyCallbackRemoveProxy) {
330 // Same as OnResolveProxyCallbackAddProxy, but verify that the
331 // NetworkDelegate's behavior is stateless across invocations after it
332 // *removes* a proxy.
333 ProxyConfig config;
334 config.proxy_rules().ParseFromString("foopy1:8080");
335 config.set_auto_detect(false);
336 config.proxy_rules().bypass_rules.ParseFromString("*.org");
338 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
340 GURL url("http://www.google.com/");
341 GURL bypass_url("http://internet.org");
343 ProxyInfo info;
344 TestCompletionCallback callback;
345 BoundTestNetLog log;
347 // First, warm up the ProxyService.
348 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
349 NULL, NULL, log.bound());
350 EXPECT_EQ(OK, rv);
352 TestResolveProxyNetworkDelegate delegate;
353 delegate.set_remove_proxy(true);
355 // Callback should interpose:
356 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), NULL,
357 &delegate, log.bound());
358 EXPECT_TRUE(info.is_direct());
359 delegate.set_remove_proxy(false);
361 // Check non-bypassed URL:
362 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), NULL,
363 &delegate, log.bound());
364 EXPECT_FALSE(info.is_direct());
365 EXPECT_EQ(info.proxy_server().host_port_pair().host(), "foopy1");
367 // Check bypassed URL:
368 rv = service.ResolveProxy(bypass_url, LOAD_NORMAL, &info, callback.callback(),
369 NULL, &delegate, log.bound());
370 EXPECT_TRUE(info.is_direct());
373 TEST_F(ProxyServiceTest, PAC) {
374 MockProxyConfigService* config_service =
375 new MockProxyConfigService("http://foopy/proxy.pac");
377 MockAsyncProxyResolver resolver;
378 MockAsyncProxyResolverFactory* factory =
379 new MockAsyncProxyResolverFactory(false);
381 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
383 GURL url("http://www.google.com/");
385 ProxyInfo info;
386 TestCompletionCallback callback;
387 ProxyService::PacRequest* request;
388 BoundTestNetLog log;
390 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
391 &request, NULL, log.bound());
392 EXPECT_EQ(ERR_IO_PENDING, rv);
394 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request));
396 ASSERT_EQ(1u, factory->pending_requests().size());
397 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
398 factory->pending_requests()[0]->script_data()->url());
399 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
401 ASSERT_EQ(1u, resolver.pending_requests().size());
402 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
404 // Set the result in proxy resolver.
405 resolver.pending_requests()[0]->results()->UseNamedProxy("foopy");
406 resolver.pending_requests()[0]->CompleteNow(OK);
408 EXPECT_EQ(OK, callback.WaitForResult());
409 EXPECT_FALSE(info.is_direct());
410 EXPECT_EQ("foopy:80", info.proxy_server().ToURI());
411 EXPECT_TRUE(info.did_use_pac_script());
413 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
414 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
415 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
417 // Check the NetLog was filled correctly.
418 TestNetLogEntry::List entries;
419 log.GetEntries(&entries);
421 EXPECT_EQ(5u, entries.size());
422 EXPECT_TRUE(LogContainsBeginEvent(
423 entries, 0, NetLog::TYPE_PROXY_SERVICE));
424 EXPECT_TRUE(LogContainsBeginEvent(
425 entries, 1, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
426 EXPECT_TRUE(LogContainsEndEvent(
427 entries, 2, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
428 EXPECT_TRUE(LogContainsEndEvent(
429 entries, 4, NetLog::TYPE_PROXY_SERVICE));
432 // Test that the proxy resolver does not see the URL's username/password
433 // or its reference section.
434 TEST_F(ProxyServiceTest, PAC_NoIdentityOrHash) {
435 MockProxyConfigService* config_service =
436 new MockProxyConfigService("http://foopy/proxy.pac");
438 MockAsyncProxyResolver resolver;
439 MockAsyncProxyResolverFactory* factory =
440 new MockAsyncProxyResolverFactory(false);
442 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
444 GURL url("http://username:password@www.google.com/?ref#hash#hash");
446 ProxyInfo info;
447 TestCompletionCallback callback;
448 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
449 NULL, NULL, BoundNetLog());
450 EXPECT_EQ(ERR_IO_PENDING, rv);
452 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
453 factory->pending_requests()[0]->script_data()->url());
454 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
456 ASSERT_EQ(1u, resolver.pending_requests().size());
457 // The URL should have been simplified, stripping the username/password/hash.
458 EXPECT_EQ(GURL("http://www.google.com/?ref"),
459 resolver.pending_requests()[0]->url());
461 // We end here without ever completing the request -- destruction of
462 // ProxyService will cancel the outstanding request.
465 TEST_F(ProxyServiceTest, PAC_FailoverWithoutDirect) {
466 MockProxyConfigService* config_service =
467 new MockProxyConfigService("http://foopy/proxy.pac");
468 MockAsyncProxyResolver resolver;
469 MockAsyncProxyResolverFactory* factory =
470 new MockAsyncProxyResolverFactory(false);
472 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
474 GURL url("http://www.google.com/");
476 ProxyInfo info;
477 TestCompletionCallback callback1;
478 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
479 NULL, NULL, BoundNetLog());
480 EXPECT_EQ(ERR_IO_PENDING, rv);
482 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
483 factory->pending_requests()[0]->script_data()->url());
484 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
486 ASSERT_EQ(1u, resolver.pending_requests().size());
487 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
489 // Set the result in proxy resolver.
490 resolver.pending_requests()[0]->results()->UseNamedProxy("foopy:8080");
491 resolver.pending_requests()[0]->CompleteNow(OK);
493 EXPECT_EQ(OK, callback1.WaitForResult());
494 EXPECT_FALSE(info.is_direct());
495 EXPECT_EQ("foopy:8080", info.proxy_server().ToURI());
496 EXPECT_TRUE(info.did_use_pac_script());
498 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
499 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
500 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
502 // Now, imagine that connecting to foopy:8080 fails: there is nothing
503 // left to fallback to, since our proxy list was NOT terminated by
504 // DIRECT.
505 NetworkDelegateImpl network_delegate;
506 TestCompletionCallback callback2;
507 ProxyServer expected_proxy_server = info.proxy_server();
508 rv = service.ReconsiderProxyAfterError(
509 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
510 callback2.callback(), NULL, &network_delegate, BoundNetLog());
511 // ReconsiderProxyAfterError returns error indicating nothing left.
512 EXPECT_EQ(ERR_FAILED, rv);
513 EXPECT_TRUE(info.is_empty());
516 // Test that if the execution of the PAC script fails (i.e. javascript runtime
517 // error), and the PAC settings are non-mandatory, that we fall-back to direct.
518 TEST_F(ProxyServiceTest, PAC_RuntimeError) {
519 MockProxyConfigService* config_service =
520 new MockProxyConfigService("http://foopy/proxy.pac");
521 MockAsyncProxyResolver resolver;
522 MockAsyncProxyResolverFactory* factory =
523 new MockAsyncProxyResolverFactory(false);
525 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
527 GURL url("http://this-causes-js-error/");
529 ProxyInfo info;
530 TestCompletionCallback callback1;
531 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
532 NULL, NULL, BoundNetLog());
533 EXPECT_EQ(ERR_IO_PENDING, rv);
535 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
536 factory->pending_requests()[0]->script_data()->url());
537 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
539 ASSERT_EQ(1u, resolver.pending_requests().size());
540 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
542 // Simulate a failure in the PAC executor.
543 resolver.pending_requests()[0]->CompleteNow(ERR_PAC_SCRIPT_FAILED);
545 EXPECT_EQ(OK, callback1.WaitForResult());
547 // Since the PAC script was non-mandatory, we should have fallen-back to
548 // DIRECT.
549 EXPECT_TRUE(info.is_direct());
550 EXPECT_TRUE(info.did_use_pac_script());
551 EXPECT_EQ(1, info.config_id());
553 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
554 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
555 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
558 // The proxy list could potentially contain the DIRECT fallback choice
559 // in a location other than the very end of the list, and could even
560 // specify it multiple times.
562 // This is not a typical usage, but we will obey it.
563 // (If we wanted to disallow this type of input, the right place to
564 // enforce it would be in parsing the PAC result string).
566 // This test will use the PAC result string:
568 // "DIRECT ; PROXY foobar:10 ; DIRECT ; PROXY foobar:20"
570 // For which we expect it to try DIRECT, then foobar:10, then DIRECT again,
571 // then foobar:20, and then give up and error.
573 // The important check of this test is to make sure that DIRECT is not somehow
574 // cached as being a bad proxy.
575 TEST_F(ProxyServiceTest, PAC_FailoverAfterDirect) {
576 MockProxyConfigService* config_service =
577 new MockProxyConfigService("http://foopy/proxy.pac");
578 MockAsyncProxyResolver resolver;
579 MockAsyncProxyResolverFactory* factory =
580 new MockAsyncProxyResolverFactory(false);
582 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
584 GURL url("http://www.google.com/");
586 ProxyInfo info;
587 TestCompletionCallback callback1;
588 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
589 NULL, NULL, BoundNetLog());
590 EXPECT_EQ(ERR_IO_PENDING, rv);
592 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
593 factory->pending_requests()[0]->script_data()->url());
594 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
596 ASSERT_EQ(1u, resolver.pending_requests().size());
597 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
599 // Set the result in proxy resolver.
600 resolver.pending_requests()[0]->results()->UsePacString(
601 "DIRECT ; PROXY foobar:10 ; DIRECT ; PROXY foobar:20");
602 resolver.pending_requests()[0]->CompleteNow(OK);
604 EXPECT_EQ(OK, callback1.WaitForResult());
605 EXPECT_TRUE(info.is_direct());
607 // Fallback 1.
608 TestCompletionCallback callback2;
609 rv = service.ReconsiderProxyAfterError(
610 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
611 callback2.callback(), NULL, NULL, BoundNetLog());
612 EXPECT_EQ(OK, rv);
613 EXPECT_FALSE(info.is_direct());
614 EXPECT_EQ("foobar:10", info.proxy_server().ToURI());
616 // Fallback 2.
617 NetworkDelegateImpl network_delegate;
618 ProxyServer expected_proxy_server3 = info.proxy_server();
619 TestCompletionCallback callback3;
620 rv = service.ReconsiderProxyAfterError(
621 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
622 callback3.callback(), NULL, &network_delegate, BoundNetLog());
623 EXPECT_EQ(OK, rv);
624 EXPECT_TRUE(info.is_direct());
626 // Fallback 3.
627 ProxyServer expected_proxy_server4 = info.proxy_server();
628 TestCompletionCallback callback4;
629 rv = service.ReconsiderProxyAfterError(
630 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
631 callback4.callback(), NULL, &network_delegate, BoundNetLog());
632 EXPECT_EQ(OK, rv);
633 EXPECT_FALSE(info.is_direct());
634 EXPECT_EQ("foobar:20", info.proxy_server().ToURI());
636 // Fallback 4 -- Nothing to fall back to!
637 ProxyServer expected_proxy_server5 = info.proxy_server();
638 TestCompletionCallback callback5;
639 rv = service.ReconsiderProxyAfterError(
640 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
641 callback5.callback(), NULL, &network_delegate, BoundNetLog());
642 EXPECT_EQ(ERR_FAILED, rv);
643 EXPECT_TRUE(info.is_empty());
646 TEST_F(ProxyServiceTest, PAC_ConfigSourcePropagates) {
647 // Test whether the ProxyConfigSource set by the ProxyConfigService is applied
648 // to ProxyInfo after the proxy is resolved via a PAC script.
649 ProxyConfig config =
650 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"));
651 config.set_source(PROXY_CONFIG_SOURCE_TEST);
653 MockProxyConfigService* config_service = new MockProxyConfigService(config);
654 MockAsyncProxyResolver resolver;
655 MockAsyncProxyResolverFactory* factory =
656 new MockAsyncProxyResolverFactory(false);
657 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
659 // Resolve something.
660 GURL url("http://www.google.com/");
661 ProxyInfo info;
662 TestCompletionCallback callback;
663 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
664 NULL, NULL, BoundNetLog());
665 ASSERT_EQ(ERR_IO_PENDING, rv);
666 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
667 ASSERT_EQ(1u, resolver.pending_requests().size());
669 // Set the result in proxy resolver.
670 resolver.pending_requests()[0]->results()->UseNamedProxy("foopy");
671 resolver.pending_requests()[0]->CompleteNow(OK);
673 EXPECT_EQ(OK, callback.WaitForResult());
674 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
675 EXPECT_TRUE(info.did_use_pac_script());
677 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
678 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
679 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
682 TEST_F(ProxyServiceTest, ProxyResolverFails) {
683 // Test what happens when the ProxyResolver fails. The download and setting
684 // of the PAC script have already succeeded, so this corresponds with a
685 // javascript runtime error while calling FindProxyForURL().
687 MockProxyConfigService* config_service =
688 new MockProxyConfigService("http://foopy/proxy.pac");
690 MockAsyncProxyResolver resolver;
691 MockAsyncProxyResolverFactory* factory =
692 new MockAsyncProxyResolverFactory(false);
694 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
696 // Start first resolve request.
697 GURL url("http://www.google.com/");
698 ProxyInfo info;
699 TestCompletionCallback callback1;
700 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
701 NULL, NULL, BoundNetLog());
702 EXPECT_EQ(ERR_IO_PENDING, rv);
704 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
705 factory->pending_requests()[0]->script_data()->url());
706 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
708 ASSERT_EQ(1u, resolver.pending_requests().size());
709 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
711 // Fail the first resolve request in MockAsyncProxyResolver.
712 resolver.pending_requests()[0]->CompleteNow(ERR_FAILED);
714 // Although the proxy resolver failed the request, ProxyService implicitly
715 // falls-back to DIRECT.
716 EXPECT_EQ(OK, callback1.WaitForResult());
717 EXPECT_TRUE(info.is_direct());
719 // Failed PAC executions still have proxy resolution times.
720 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
721 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
722 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
724 // The second resolve request will try to run through the proxy resolver,
725 // regardless of whether the first request failed in it.
726 TestCompletionCallback callback2;
727 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback2.callback(), NULL,
728 NULL, BoundNetLog());
729 EXPECT_EQ(ERR_IO_PENDING, rv);
731 ASSERT_EQ(1u, resolver.pending_requests().size());
732 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
734 // This time we will have the resolver succeed (perhaps the PAC script has
735 // a dependency on the current time).
736 resolver.pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080");
737 resolver.pending_requests()[0]->CompleteNow(OK);
739 EXPECT_EQ(OK, callback2.WaitForResult());
740 EXPECT_FALSE(info.is_direct());
741 EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI());
744 TEST_F(ProxyServiceTest, ProxyResolverTerminatedDuringRequest) {
745 // Test what happens when the ProxyResolver fails with a fatal error while
746 // a GetProxyForURL() call is in progress.
748 MockProxyConfigService* config_service =
749 new MockProxyConfigService("http://foopy/proxy.pac");
751 MockAsyncProxyResolver resolver;
752 MockAsyncProxyResolverFactory* factory =
753 new MockAsyncProxyResolverFactory(false);
755 ProxyService service(config_service, make_scoped_ptr(factory), nullptr);
757 // Start first resolve request.
758 GURL url("http://www.google.com/");
759 ProxyInfo info;
760 TestCompletionCallback callback1;
761 int rv =
762 service.ResolveProxy(url, net::LOAD_NORMAL, &info, callback1.callback(),
763 nullptr, nullptr, BoundNetLog());
764 EXPECT_EQ(ERR_IO_PENDING, rv);
766 ASSERT_EQ(1u, factory->pending_requests().size());
767 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
768 factory->pending_requests()[0]->script_data()->url());
769 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
771 ASSERT_EQ(1u, resolver.pending_requests().size());
772 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
774 // Fail the first resolve request in MockAsyncProxyResolver.
775 resolver.pending_requests()[0]->CompleteNow(ERR_PAC_SCRIPT_TERMINATED);
777 // Although the proxy resolver failed the request, ProxyService implicitly
778 // falls-back to DIRECT.
779 EXPECT_EQ(OK, callback1.WaitForResult());
780 EXPECT_TRUE(info.is_direct());
782 // Failed PAC executions still have proxy resolution times.
783 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
784 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
785 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
787 // With no other requests, the ProxyService waits for a new request before
788 // initializing a new ProxyResolver.
789 EXPECT_TRUE(factory->pending_requests().empty());
791 TestCompletionCallback callback2;
792 rv = service.ResolveProxy(url, net::LOAD_NORMAL, &info, callback2.callback(),
793 nullptr, nullptr, BoundNetLog());
794 EXPECT_EQ(ERR_IO_PENDING, rv);
796 ASSERT_EQ(1u, factory->pending_requests().size());
797 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
798 factory->pending_requests()[0]->script_data()->url());
799 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
801 ASSERT_EQ(1u, resolver.pending_requests().size());
802 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
804 // This time we will have the resolver succeed.
805 resolver.pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080");
806 resolver.pending_requests()[0]->CompleteNow(OK);
808 EXPECT_EQ(OK, callback2.WaitForResult());
809 EXPECT_FALSE(info.is_direct());
810 EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI());
813 TEST_F(ProxyServiceTest,
814 ProxyResolverTerminatedDuringRequestWithConcurrentRequest) {
815 // Test what happens when the ProxyResolver fails with a fatal error while
816 // a GetProxyForURL() call is in progress.
818 MockProxyConfigService* config_service =
819 new MockProxyConfigService("http://foopy/proxy.pac");
821 MockAsyncProxyResolver resolver;
822 MockAsyncProxyResolverFactory* factory =
823 new MockAsyncProxyResolverFactory(false);
825 ProxyService service(config_service, make_scoped_ptr(factory), nullptr);
827 // Start two resolve requests.
828 GURL url1("http://www.google.com/");
829 GURL url2("https://www.google.com/");
830 ProxyInfo info;
831 TestCompletionCallback callback1;
832 int rv =
833 service.ResolveProxy(url1, net::LOAD_NORMAL, &info, callback1.callback(),
834 nullptr, nullptr, BoundNetLog());
835 EXPECT_EQ(ERR_IO_PENDING, rv);
836 TestCompletionCallback callback2;
837 rv = service.ResolveProxy(url2, net::LOAD_NORMAL, &info, callback2.callback(),
838 nullptr, nullptr, BoundNetLog());
839 EXPECT_EQ(ERR_IO_PENDING, rv);
841 ASSERT_EQ(1u, factory->pending_requests().size());
842 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
843 factory->pending_requests()[0]->script_data()->url());
844 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
846 ASSERT_EQ(2u, resolver.pending_requests().size());
847 EXPECT_EQ(url1, resolver.pending_requests()[0]->url());
848 EXPECT_EQ(url2, resolver.pending_requests()[1]->url());
850 // Fail the first resolve request in MockAsyncProxyResolver.
851 resolver.pending_requests()[0]->CompleteNow(ERR_PAC_SCRIPT_TERMINATED);
853 // Although the proxy resolver failed the request, ProxyService implicitly
854 // falls-back to DIRECT.
855 EXPECT_EQ(OK, callback1.WaitForResult());
856 EXPECT_TRUE(info.is_direct());
858 // Failed PAC executions still have proxy resolution times.
859 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
860 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
861 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
863 // The second request is cancelled when the proxy resolver terminates.
864 ASSERT_EQ(1u, resolver.cancelled_requests().size());
865 EXPECT_EQ(url2, resolver.cancelled_requests()[0]->url());
867 // Since a second request was in progress, the ProxyService starts
868 // initializating a new ProxyResolver.
869 ASSERT_EQ(1u, factory->pending_requests().size());
870 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
871 factory->pending_requests()[0]->script_data()->url());
872 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
874 ASSERT_EQ(1u, resolver.pending_requests().size());
875 EXPECT_EQ(url2, resolver.pending_requests()[0]->url());
877 // This request succeeds.
878 resolver.pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080");
879 resolver.pending_requests()[0]->CompleteNow(OK);
881 EXPECT_EQ(OK, callback2.WaitForResult());
882 EXPECT_FALSE(info.is_direct());
883 EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI());
886 TEST_F(ProxyServiceTest, ProxyScriptFetcherFailsDownloadingMandatoryPac) {
887 // Test what happens when the ProxyScriptResolver fails to download a
888 // mandatory PAC script.
890 ProxyConfig config(
891 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
892 config.set_pac_mandatory(true);
894 MockProxyConfigService* config_service = new MockProxyConfigService(config);
896 MockAsyncProxyResolverFactory* factory =
897 new MockAsyncProxyResolverFactory(false);
899 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
901 // Start first resolve request.
902 GURL url("http://www.google.com/");
903 ProxyInfo info;
904 TestCompletionCallback callback1;
905 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
906 NULL, NULL, BoundNetLog());
907 EXPECT_EQ(ERR_IO_PENDING, rv);
909 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
910 factory->pending_requests()[0]->script_data()->url());
911 factory->pending_requests()[0]->CompleteNow(ERR_FAILED, nullptr);
913 ASSERT_EQ(0u, factory->pending_requests().size());
914 // As the proxy resolver factory failed the request and is configured for a
915 // mandatory PAC script, ProxyService must not implicitly fall-back to DIRECT.
916 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
917 callback1.WaitForResult());
918 EXPECT_FALSE(info.is_direct());
920 // As the proxy resolver factory failed the request and is configured for a
921 // mandatory PAC script, ProxyService must not implicitly fall-back to DIRECT.
922 TestCompletionCallback callback2;
923 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback2.callback(), NULL,
924 NULL, BoundNetLog());
925 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED, rv);
926 EXPECT_FALSE(info.is_direct());
929 TEST_F(ProxyServiceTest, ProxyResolverFailsParsingJavaScriptMandatoryPac) {
930 // Test what happens when the ProxyResolver fails that is configured to use a
931 // mandatory PAC script. The download of the PAC script has already
932 // succeeded but the PAC script contains no valid javascript.
934 ProxyConfig config(
935 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
936 config.set_pac_mandatory(true);
938 MockProxyConfigService* config_service = new MockProxyConfigService(config);
940 MockAsyncProxyResolverFactory* factory =
941 new MockAsyncProxyResolverFactory(true);
943 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
945 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
946 DhcpProxyScriptFetcher* dhcp_fetcher = new DoNothingDhcpProxyScriptFetcher();
947 service.SetProxyScriptFetchers(fetcher, dhcp_fetcher);
949 // Start resolve request.
950 GURL url("http://www.google.com/");
951 ProxyInfo info;
952 TestCompletionCallback callback;
953 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
954 NULL, NULL, BoundNetLog());
955 EXPECT_EQ(ERR_IO_PENDING, rv);
957 // Check that nothing has been sent to the proxy resolver factory yet.
958 ASSERT_EQ(0u, factory->pending_requests().size());
960 // Downloading the PAC script succeeds.
961 EXPECT_TRUE(fetcher->has_pending_request());
962 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
963 fetcher->NotifyFetchCompletion(OK, "invalid-script-contents");
965 EXPECT_FALSE(fetcher->has_pending_request());
966 ASSERT_EQ(0u, factory->pending_requests().size());
968 // Since ProxyScriptDecider failed to identify a valid PAC and PAC was
969 // mandatory for this configuration, the ProxyService must not implicitly
970 // fall-back to DIRECT.
971 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
972 callback.WaitForResult());
973 EXPECT_FALSE(info.is_direct());
976 TEST_F(ProxyServiceTest, ProxyResolverFailsInJavaScriptMandatoryPac) {
977 // Test what happens when the ProxyResolver fails that is configured to use a
978 // mandatory PAC script. The download and setting of the PAC script have
979 // already succeeded, so this corresponds with a javascript runtime error
980 // while calling FindProxyForURL().
982 ProxyConfig config(
983 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
984 config.set_pac_mandatory(true);
986 MockProxyConfigService* config_service = new MockProxyConfigService(config);
988 MockAsyncProxyResolver resolver;
989 MockAsyncProxyResolverFactory* factory =
990 new MockAsyncProxyResolverFactory(false);
992 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
994 // Start first resolve request.
995 GURL url("http://www.google.com/");
996 ProxyInfo info;
997 TestCompletionCallback callback1;
998 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
999 NULL, NULL, BoundNetLog());
1000 EXPECT_EQ(ERR_IO_PENDING, rv);
1002 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1003 factory->pending_requests()[0]->script_data()->url());
1004 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1006 ASSERT_EQ(1u, resolver.pending_requests().size());
1007 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1009 // Fail the first resolve request in MockAsyncProxyResolver.
1010 resolver.pending_requests()[0]->CompleteNow(ERR_FAILED);
1012 // As the proxy resolver failed the request and is configured for a mandatory
1013 // PAC script, ProxyService must not implicitly fall-back to DIRECT.
1014 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
1015 callback1.WaitForResult());
1016 EXPECT_FALSE(info.is_direct());
1018 // The second resolve request will try to run through the proxy resolver,
1019 // regardless of whether the first request failed in it.
1020 TestCompletionCallback callback2;
1021 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback2.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 we will have the resolver succeed (perhaps the PAC script has
1029 // a dependency on the current time).
1030 resolver.pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080");
1031 resolver.pending_requests()[0]->CompleteNow(OK);
1033 EXPECT_EQ(OK, callback2.WaitForResult());
1034 EXPECT_FALSE(info.is_direct());
1035 EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI());
1038 TEST_F(ProxyServiceTest, ProxyFallback) {
1039 // Test what happens when we specify multiple proxy servers and some of them
1040 // are bad.
1042 MockProxyConfigService* config_service =
1043 new MockProxyConfigService("http://foopy/proxy.pac");
1045 MockAsyncProxyResolver resolver;
1046 MockAsyncProxyResolverFactory* factory =
1047 new MockAsyncProxyResolverFactory(false);
1049 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
1051 GURL url("http://www.google.com/");
1053 // Get the proxy information.
1054 ProxyInfo info;
1055 TestCompletionCallback callback1;
1056 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
1057 NULL, NULL, BoundNetLog());
1058 EXPECT_EQ(ERR_IO_PENDING, rv);
1060 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1061 factory->pending_requests()[0]->script_data()->url());
1062 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1064 ASSERT_EQ(1u, resolver.pending_requests().size());
1065 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1067 // Set the result in proxy resolver.
1068 resolver.pending_requests()[0]->results()->UseNamedProxy(
1069 "foopy1:8080;foopy2:9090");
1070 resolver.pending_requests()[0]->CompleteNow(OK);
1072 // The first item is valid.
1073 EXPECT_EQ(OK, callback1.WaitForResult());
1074 EXPECT_FALSE(info.is_direct());
1075 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1077 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1078 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1079 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1080 base::TimeTicks proxy_resolve_start_time = info.proxy_resolve_start_time();
1081 base::TimeTicks proxy_resolve_end_time = info.proxy_resolve_end_time();
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());
1088 EXPECT_EQ(OK, rv);
1090 // Proxy times should not have been modified by fallback.
1091 EXPECT_EQ(proxy_resolve_start_time, info.proxy_resolve_start_time());
1092 EXPECT_EQ(proxy_resolve_end_time, info.proxy_resolve_end_time());
1094 // The second proxy should be specified.
1095 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
1096 // Report back that the second proxy worked. This will globally mark the
1097 // first proxy as bad.
1098 TestProxyFallbackNetworkDelegate test_delegate;
1099 service.ReportSuccess(info, &test_delegate);
1100 EXPECT_EQ("foopy1:8080", test_delegate.proxy_server().ToURI());
1101 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED,
1102 test_delegate.proxy_fallback_net_error());
1104 TestCompletionCallback callback3;
1105 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback3.callback(), NULL,
1106 NULL, BoundNetLog());
1107 EXPECT_EQ(ERR_IO_PENDING, rv);
1109 ASSERT_EQ(1u, resolver.pending_requests().size());
1110 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1112 // Set the result in proxy resolver -- the second result is already known
1113 // to be bad, so we will not try to use it initially.
1114 resolver.pending_requests()[0]->results()->UseNamedProxy(
1115 "foopy3:7070;foopy1:8080;foopy2:9090");
1116 resolver.pending_requests()[0]->CompleteNow(OK);
1118 EXPECT_EQ(OK, callback3.WaitForResult());
1119 EXPECT_FALSE(info.is_direct());
1120 EXPECT_EQ("foopy3:7070", info.proxy_server().ToURI());
1122 // Proxy times should have been updated, so get them again.
1123 EXPECT_LE(proxy_resolve_end_time, info.proxy_resolve_start_time());
1124 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1125 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1126 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1127 proxy_resolve_start_time = info.proxy_resolve_start_time();
1128 proxy_resolve_end_time = info.proxy_resolve_end_time();
1130 // We fake another error. It should now try the third one.
1131 TestCompletionCallback callback4;
1132 rv = service.ReconsiderProxyAfterError(
1133 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1134 callback4.callback(), NULL, NULL, BoundNetLog());
1135 EXPECT_EQ(OK, rv);
1136 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
1138 // We fake another error. At this point we have tried all of the
1139 // proxy servers we thought were valid; next we try the proxy server
1140 // that was in our bad proxies map (foopy1:8080).
1141 TestCompletionCallback callback5;
1142 rv = service.ReconsiderProxyAfterError(
1143 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1144 callback5.callback(), NULL, NULL, BoundNetLog());
1145 EXPECT_EQ(OK, rv);
1146 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1148 // Fake another error, the last proxy is gone, the list should now be empty,
1149 // so there is nothing left to try.
1150 TestCompletionCallback callback6;
1151 rv = service.ReconsiderProxyAfterError(
1152 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1153 callback6.callback(), NULL, NULL, BoundNetLog());
1154 EXPECT_EQ(ERR_FAILED, rv);
1155 EXPECT_FALSE(info.is_direct());
1156 EXPECT_TRUE(info.is_empty());
1158 // Proxy times should not have been modified by fallback.
1159 EXPECT_EQ(proxy_resolve_start_time, info.proxy_resolve_start_time());
1160 EXPECT_EQ(proxy_resolve_end_time, info.proxy_resolve_end_time());
1162 // Look up proxies again
1163 TestCompletionCallback callback7;
1164 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback7.callback(), NULL,
1165 NULL, BoundNetLog());
1166 EXPECT_EQ(ERR_IO_PENDING, rv);
1168 ASSERT_EQ(1u, resolver.pending_requests().size());
1169 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1171 // This time, the first 3 results have been found to be bad, but only the
1172 // first proxy has been confirmed ...
1173 resolver.pending_requests()[0]->results()->UseNamedProxy(
1174 "foopy1:8080;foopy3:7070;foopy2:9090;foopy4:9091");
1175 resolver.pending_requests()[0]->CompleteNow(OK);
1177 // ... therefore, we should see the second proxy first.
1178 EXPECT_EQ(OK, callback7.WaitForResult());
1179 EXPECT_FALSE(info.is_direct());
1180 EXPECT_EQ("foopy3:7070", info.proxy_server().ToURI());
1182 EXPECT_LE(proxy_resolve_end_time, info.proxy_resolve_start_time());
1183 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1184 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1185 // TODO(nsylvain): Test that the proxy can be retried after the delay.
1188 // This test is similar to ProxyFallback, but this time we have an explicit
1189 // fallback choice to DIRECT.
1190 TEST_F(ProxyServiceTest, ProxyFallbackToDirect) {
1191 MockProxyConfigService* config_service =
1192 new MockProxyConfigService("http://foopy/proxy.pac");
1194 MockAsyncProxyResolver resolver;
1195 MockAsyncProxyResolverFactory* factory =
1196 new MockAsyncProxyResolverFactory(false);
1198 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
1200 GURL url("http://www.google.com/");
1202 // Get the proxy information.
1203 ProxyInfo info;
1204 TestCompletionCallback callback1;
1205 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
1206 NULL, NULL, BoundNetLog());
1207 EXPECT_EQ(ERR_IO_PENDING, rv);
1209 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1210 factory->pending_requests()[0]->script_data()->url());
1211 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1213 ASSERT_EQ(1u, resolver.pending_requests().size());
1214 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1216 // Set the result in proxy resolver.
1217 resolver.pending_requests()[0]->results()->UsePacString(
1218 "PROXY foopy1:8080; PROXY foopy2:9090; DIRECT");
1219 resolver.pending_requests()[0]->CompleteNow(OK);
1221 // Get the first result.
1222 EXPECT_EQ(OK, callback1.WaitForResult());
1223 EXPECT_FALSE(info.is_direct());
1224 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1226 // Fake an error on the proxy.
1227 TestCompletionCallback callback2;
1228 rv = service.ReconsiderProxyAfterError(
1229 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1230 callback2.callback(), NULL, NULL, BoundNetLog());
1231 EXPECT_EQ(OK, rv);
1233 // Now we get back the second proxy.
1234 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
1236 // Fake an error on this proxy as well.
1237 TestCompletionCallback callback3;
1238 rv = service.ReconsiderProxyAfterError(
1239 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1240 callback3.callback(), NULL, NULL, BoundNetLog());
1241 EXPECT_EQ(OK, rv);
1243 // Finally, we get back DIRECT.
1244 EXPECT_TRUE(info.is_direct());
1246 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1247 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1248 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1250 // Now we tell the proxy service that even DIRECT failed.
1251 TestCompletionCallback callback4;
1252 rv = service.ReconsiderProxyAfterError(
1253 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1254 callback4.callback(), NULL, NULL, BoundNetLog());
1255 // There was nothing left to try after DIRECT, so we are out of
1256 // choices.
1257 EXPECT_EQ(ERR_FAILED, rv);
1260 TEST_F(ProxyServiceTest, ProxyFallback_NewSettings) {
1261 // Test proxy failover when new settings are available.
1263 MockProxyConfigService* config_service =
1264 new MockProxyConfigService("http://foopy/proxy.pac");
1266 MockAsyncProxyResolver resolver;
1267 MockAsyncProxyResolverFactory* factory =
1268 new MockAsyncProxyResolverFactory(false);
1270 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
1272 GURL url("http://www.google.com/");
1274 // Get the proxy information.
1275 ProxyInfo info;
1276 TestCompletionCallback callback1;
1277 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
1278 NULL, NULL, BoundNetLog());
1279 EXPECT_EQ(ERR_IO_PENDING, rv);
1281 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1282 factory->pending_requests()[0]->script_data()->url());
1283 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1285 ASSERT_EQ(1u, resolver.pending_requests().size());
1286 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1288 // Set the result in proxy resolver.
1289 resolver.pending_requests()[0]->results()->UseNamedProxy(
1290 "foopy1:8080;foopy2:9090");
1291 resolver.pending_requests()[0]->CompleteNow(OK);
1293 // The first item is valid.
1294 EXPECT_EQ(OK, callback1.WaitForResult());
1295 EXPECT_FALSE(info.is_direct());
1296 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1298 // Fake an error on the proxy, and also a new configuration on the proxy.
1299 config_service->SetConfig(
1300 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy-new/proxy.pac")));
1302 TestCompletionCallback callback2;
1303 rv = service.ReconsiderProxyAfterError(
1304 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1305 callback2.callback(), NULL, NULL, BoundNetLog());
1306 EXPECT_EQ(ERR_IO_PENDING, rv);
1308 EXPECT_EQ(GURL("http://foopy-new/proxy.pac"),
1309 factory->pending_requests()[0]->script_data()->url());
1310 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1312 ASSERT_EQ(1u, resolver.pending_requests().size());
1313 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1315 resolver.pending_requests()[0]->results()->UseNamedProxy(
1316 "foopy1:8080;foopy2:9090");
1317 resolver.pending_requests()[0]->CompleteNow(OK);
1319 // The first proxy is still there since the configuration changed.
1320 EXPECT_EQ(OK, callback2.WaitForResult());
1321 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1323 // We fake another error. It should now ignore the first one.
1324 TestCompletionCallback callback3;
1325 rv = service.ReconsiderProxyAfterError(
1326 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1327 callback3.callback(), NULL, NULL, BoundNetLog());
1328 EXPECT_EQ(OK, rv);
1329 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
1331 // We simulate a new configuration.
1332 config_service->SetConfig(
1333 ProxyConfig::CreateFromCustomPacURL(
1334 GURL("http://foopy-new2/proxy.pac")));
1336 // We fake another error. It should go back to the first proxy.
1337 TestCompletionCallback callback4;
1338 rv = service.ReconsiderProxyAfterError(
1339 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1340 callback4.callback(), NULL, NULL, BoundNetLog());
1341 EXPECT_EQ(ERR_IO_PENDING, rv);
1343 EXPECT_EQ(GURL("http://foopy-new2/proxy.pac"),
1344 factory->pending_requests()[0]->script_data()->url());
1345 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1347 ASSERT_EQ(1u, resolver.pending_requests().size());
1348 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1350 resolver.pending_requests()[0]->results()->UseNamedProxy(
1351 "foopy1:8080;foopy2:9090");
1352 resolver.pending_requests()[0]->CompleteNow(OK);
1354 EXPECT_EQ(OK, callback4.WaitForResult());
1355 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1357 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1358 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1359 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1362 TEST_F(ProxyServiceTest, ProxyFallback_BadConfig) {
1363 // Test proxy failover when the configuration is bad.
1365 MockProxyConfigService* config_service =
1366 new MockProxyConfigService("http://foopy/proxy.pac");
1368 MockAsyncProxyResolver resolver;
1369 MockAsyncProxyResolverFactory* factory =
1370 new MockAsyncProxyResolverFactory(false);
1372 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
1374 GURL url("http://www.google.com/");
1376 // Get the proxy information.
1377 ProxyInfo info;
1378 TestCompletionCallback callback1;
1379 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
1380 NULL, NULL, BoundNetLog());
1381 EXPECT_EQ(ERR_IO_PENDING, rv);
1383 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1384 factory->pending_requests()[0]->script_data()->url());
1385 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1386 ASSERT_EQ(1u, resolver.pending_requests().size());
1387 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1389 resolver.pending_requests()[0]->results()->UseNamedProxy(
1390 "foopy1:8080;foopy2:9090");
1391 resolver.pending_requests()[0]->CompleteNow(OK);
1393 // The first item is valid.
1394 EXPECT_EQ(OK, callback1.WaitForResult());
1395 EXPECT_FALSE(info.is_direct());
1396 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1398 // Fake a proxy error.
1399 TestCompletionCallback callback2;
1400 rv = service.ReconsiderProxyAfterError(
1401 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1402 callback2.callback(), NULL, NULL, BoundNetLog());
1403 EXPECT_EQ(OK, rv);
1405 // The first proxy is ignored, and the second one is selected.
1406 EXPECT_FALSE(info.is_direct());
1407 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
1409 // Fake a PAC failure.
1410 ProxyInfo info2;
1411 TestCompletionCallback callback3;
1412 rv = service.ResolveProxy(url, LOAD_NORMAL, &info2, callback3.callback(),
1413 NULL, NULL, BoundNetLog());
1414 EXPECT_EQ(ERR_IO_PENDING, rv);
1416 ASSERT_EQ(1u, resolver.pending_requests().size());
1417 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1419 // This simulates a javascript runtime error in the PAC script.
1420 resolver.pending_requests()[0]->CompleteNow(ERR_FAILED);
1422 // Although the resolver failed, the ProxyService will implicitly fall-back
1423 // to a DIRECT connection.
1424 EXPECT_EQ(OK, callback3.WaitForResult());
1425 EXPECT_TRUE(info2.is_direct());
1426 EXPECT_FALSE(info2.is_empty());
1428 // The PAC script will work properly next time and successfully return a
1429 // proxy list. Since we have not marked the configuration as bad, it should
1430 // "just work" the next time we call it.
1431 ProxyInfo info3;
1432 TestCompletionCallback callback4;
1433 rv = service.ReconsiderProxyAfterError(
1434 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info3,
1435 callback4.callback(), NULL, NULL, BoundNetLog());
1436 EXPECT_EQ(ERR_IO_PENDING, rv);
1438 ASSERT_EQ(1u, resolver.pending_requests().size());
1439 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1441 resolver.pending_requests()[0]->results()->UseNamedProxy(
1442 "foopy1:8080;foopy2:9090");
1443 resolver.pending_requests()[0]->CompleteNow(OK);
1445 // The first proxy is not there since the it was added to the bad proxies
1446 // list by the earlier ReconsiderProxyAfterError().
1447 EXPECT_EQ(OK, callback4.WaitForResult());
1448 EXPECT_FALSE(info3.is_direct());
1449 EXPECT_EQ("foopy1:8080", info3.proxy_server().ToURI());
1451 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1452 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1453 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1456 TEST_F(ProxyServiceTest, ProxyFallback_BadConfigMandatory) {
1457 // Test proxy failover when the configuration is bad.
1459 ProxyConfig config(
1460 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
1462 config.set_pac_mandatory(true);
1463 MockProxyConfigService* config_service = new MockProxyConfigService(config);
1465 MockAsyncProxyResolver resolver;
1466 MockAsyncProxyResolverFactory* factory =
1467 new MockAsyncProxyResolverFactory(false);
1469 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
1471 GURL url("http://www.google.com/");
1473 // Get the proxy information.
1474 ProxyInfo info;
1475 TestCompletionCallback callback1;
1476 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
1477 NULL, NULL, BoundNetLog());
1478 EXPECT_EQ(ERR_IO_PENDING, rv);
1480 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1481 factory->pending_requests()[0]->script_data()->url());
1482 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1483 ASSERT_EQ(1u, resolver.pending_requests().size());
1484 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1486 resolver.pending_requests()[0]->results()->UseNamedProxy(
1487 "foopy1:8080;foopy2:9090");
1488 resolver.pending_requests()[0]->CompleteNow(OK);
1490 // The first item is valid.
1491 EXPECT_EQ(OK, callback1.WaitForResult());
1492 EXPECT_FALSE(info.is_direct());
1493 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1495 // Fake a proxy error.
1496 TestCompletionCallback callback2;
1497 rv = service.ReconsiderProxyAfterError(
1498 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1499 callback2.callback(), NULL, NULL, BoundNetLog());
1500 EXPECT_EQ(OK, rv);
1502 // The first proxy is ignored, and the second one is selected.
1503 EXPECT_FALSE(info.is_direct());
1504 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
1506 // Fake a PAC failure.
1507 ProxyInfo info2;
1508 TestCompletionCallback callback3;
1509 rv = service.ResolveProxy(url, LOAD_NORMAL, &info2, callback3.callback(),
1510 NULL, NULL, BoundNetLog());
1511 EXPECT_EQ(ERR_IO_PENDING, rv);
1513 ASSERT_EQ(1u, resolver.pending_requests().size());
1514 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1516 // This simulates a javascript runtime error in the PAC script.
1517 resolver.pending_requests()[0]->CompleteNow(ERR_FAILED);
1519 // Although the resolver failed, the ProxyService will NOT fall-back
1520 // to a DIRECT connection as it is configured as mandatory.
1521 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
1522 callback3.WaitForResult());
1523 EXPECT_FALSE(info2.is_direct());
1524 EXPECT_TRUE(info2.is_empty());
1526 // The PAC script will work properly next time and successfully return a
1527 // proxy list. Since we have not marked the configuration as bad, it should
1528 // "just work" the next time we call it.
1529 ProxyInfo info3;
1530 TestCompletionCallback callback4;
1531 rv = service.ReconsiderProxyAfterError(
1532 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info3,
1533 callback4.callback(), NULL, NULL, BoundNetLog());
1534 EXPECT_EQ(ERR_IO_PENDING, rv);
1536 ASSERT_EQ(1u, resolver.pending_requests().size());
1537 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1539 resolver.pending_requests()[0]->results()->UseNamedProxy(
1540 "foopy1:8080;foopy2:9090");
1541 resolver.pending_requests()[0]->CompleteNow(OK);
1543 // The first proxy is not there since the it was added to the bad proxies
1544 // list by the earlier ReconsiderProxyAfterError().
1545 EXPECT_EQ(OK, callback4.WaitForResult());
1546 EXPECT_FALSE(info3.is_direct());
1547 EXPECT_EQ("foopy1:8080", info3.proxy_server().ToURI());
1550 TEST_F(ProxyServiceTest, ProxyBypassList) {
1551 // Test that the proxy bypass rules are consulted.
1553 TestCompletionCallback callback[2];
1554 ProxyInfo info[2];
1555 ProxyConfig config;
1556 config.proxy_rules().ParseFromString("foopy1:8080;foopy2:9090");
1557 config.set_auto_detect(false);
1558 config.proxy_rules().bypass_rules.ParseFromString("*.org");
1560 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1562 int rv;
1563 GURL url1("http://www.webkit.org");
1564 GURL url2("http://www.webkit.com");
1566 // Request for a .org domain should bypass proxy.
1567 rv = service.ResolveProxy(url1, LOAD_NORMAL, &info[0], callback[0].callback(),
1568 NULL, NULL, BoundNetLog());
1569 EXPECT_EQ(OK, rv);
1570 EXPECT_TRUE(info[0].is_direct());
1572 // Request for a .com domain hits the proxy.
1573 rv = service.ResolveProxy(url2, LOAD_NORMAL, &info[1], callback[1].callback(),
1574 NULL, NULL, BoundNetLog());
1575 EXPECT_EQ(OK, rv);
1576 EXPECT_EQ("foopy1:8080", info[1].proxy_server().ToURI());
1579 TEST_F(ProxyServiceTest, MarkProxiesAsBadTests) {
1580 ProxyConfig config;
1581 config.proxy_rules().ParseFromString(
1582 "http=foopy1:8080;http=foopy2:8080;http=foopy3.8080;http=foopy4:8080");
1583 config.set_auto_detect(false);
1585 ProxyList proxy_list;
1586 std::vector<ProxyServer> additional_bad_proxies;
1587 for (const ProxyServer& proxy_server :
1588 config.proxy_rules().proxies_for_http.GetAll()) {
1589 proxy_list.AddProxyServer(proxy_server);
1590 if (proxy_server == config.proxy_rules().proxies_for_http.Get())
1591 continue;
1593 additional_bad_proxies.push_back(proxy_server);
1596 EXPECT_EQ(3u, additional_bad_proxies.size());
1598 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1599 ProxyInfo proxy_info;
1600 proxy_info.UseProxyList(proxy_list);
1601 const ProxyRetryInfoMap& retry_info = service.proxy_retry_info();
1602 service.MarkProxiesAsBadUntil(proxy_info, base::TimeDelta::FromSeconds(1),
1603 additional_bad_proxies, BoundNetLog());
1604 ASSERT_EQ(4u, retry_info.size());
1605 for (const ProxyServer& proxy_server :
1606 config.proxy_rules().proxies_for_http.GetAll()) {
1607 ProxyRetryInfoMap::const_iterator i =
1608 retry_info.find(proxy_server.host_port_pair().ToString());
1609 ASSERT_TRUE(i != retry_info.end());
1613 TEST_F(ProxyServiceTest, PerProtocolProxyTests) {
1614 ProxyConfig config;
1615 config.proxy_rules().ParseFromString("http=foopy1:8080;https=foopy2:8080");
1616 config.set_auto_detect(false);
1618 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1619 GURL test_url("http://www.msn.com");
1620 ProxyInfo info;
1621 TestCompletionCallback callback;
1622 int rv =
1623 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1624 NULL, NULL, BoundNetLog());
1625 EXPECT_EQ(OK, rv);
1626 EXPECT_FALSE(info.is_direct());
1627 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1630 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1631 GURL test_url("ftp://ftp.google.com");
1632 ProxyInfo info;
1633 TestCompletionCallback callback;
1634 int rv =
1635 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1636 NULL, NULL, BoundNetLog());
1637 EXPECT_EQ(OK, rv);
1638 EXPECT_TRUE(info.is_direct());
1639 EXPECT_EQ("direct://", info.proxy_server().ToURI());
1642 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1643 GURL test_url("https://webbranch.techcu.com");
1644 ProxyInfo info;
1645 TestCompletionCallback callback;
1646 int rv =
1647 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1648 NULL, NULL, BoundNetLog());
1649 EXPECT_EQ(OK, rv);
1650 EXPECT_FALSE(info.is_direct());
1651 EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI());
1654 config.proxy_rules().ParseFromString("foopy1:8080");
1655 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1656 GURL test_url("http://www.microsoft.com");
1657 ProxyInfo info;
1658 TestCompletionCallback callback;
1659 int rv =
1660 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1661 NULL, NULL, BoundNetLog());
1662 EXPECT_EQ(OK, rv);
1663 EXPECT_FALSE(info.is_direct());
1664 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1668 TEST_F(ProxyServiceTest, ProxyConfigSourcePropagates) {
1669 // Test that the proxy config source is set correctly when resolving proxies
1670 // using manual proxy rules. Namely, the config source should only be set if
1671 // any of the rules were applied.
1673 ProxyConfig config;
1674 config.set_source(PROXY_CONFIG_SOURCE_TEST);
1675 config.proxy_rules().ParseFromString("https=foopy2:8080");
1676 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1677 GURL test_url("http://www.google.com");
1678 ProxyInfo info;
1679 TestCompletionCallback callback;
1680 int rv =
1681 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1682 NULL, NULL, BoundNetLog());
1683 ASSERT_EQ(OK, rv);
1684 // Should be SOURCE_TEST, even if there are no HTTP proxies configured.
1685 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
1688 ProxyConfig config;
1689 config.set_source(PROXY_CONFIG_SOURCE_TEST);
1690 config.proxy_rules().ParseFromString("https=foopy2:8080");
1691 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1692 GURL test_url("https://www.google.com");
1693 ProxyInfo info;
1694 TestCompletionCallback callback;
1695 int rv =
1696 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1697 NULL, NULL, BoundNetLog());
1698 ASSERT_EQ(OK, rv);
1699 // Used the HTTPS proxy. So source should be TEST.
1700 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
1703 ProxyConfig config;
1704 config.set_source(PROXY_CONFIG_SOURCE_TEST);
1705 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1706 GURL test_url("http://www.google.com");
1707 ProxyInfo info;
1708 TestCompletionCallback callback;
1709 int rv =
1710 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1711 NULL, NULL, BoundNetLog());
1712 ASSERT_EQ(OK, rv);
1713 // ProxyConfig is empty. Source should still be TEST.
1714 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
1718 // If only HTTP and a SOCKS proxy are specified, check if ftp/https queries
1719 // fall back to the SOCKS proxy.
1720 TEST_F(ProxyServiceTest, DefaultProxyFallbackToSOCKS) {
1721 ProxyConfig config;
1722 config.proxy_rules().ParseFromString("http=foopy1:8080;socks=foopy2:1080");
1723 config.set_auto_detect(false);
1724 EXPECT_EQ(ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
1725 config.proxy_rules().type);
1728 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1729 GURL test_url("http://www.msn.com");
1730 ProxyInfo info;
1731 TestCompletionCallback callback;
1732 int rv =
1733 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1734 NULL, NULL, BoundNetLog());
1735 EXPECT_EQ(OK, rv);
1736 EXPECT_FALSE(info.is_direct());
1737 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1740 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1741 GURL test_url("ftp://ftp.google.com");
1742 ProxyInfo info;
1743 TestCompletionCallback callback;
1744 int rv =
1745 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1746 NULL, NULL, BoundNetLog());
1747 EXPECT_EQ(OK, rv);
1748 EXPECT_FALSE(info.is_direct());
1749 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI());
1752 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1753 GURL test_url("https://webbranch.techcu.com");
1754 ProxyInfo info;
1755 TestCompletionCallback callback;
1756 int rv =
1757 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1758 NULL, NULL, BoundNetLog());
1759 EXPECT_EQ(OK, rv);
1760 EXPECT_FALSE(info.is_direct());
1761 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI());
1764 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1765 GURL test_url("unknown://www.microsoft.com");
1766 ProxyInfo info;
1767 TestCompletionCallback callback;
1768 int rv =
1769 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1770 NULL, NULL, BoundNetLog());
1771 EXPECT_EQ(OK, rv);
1772 EXPECT_FALSE(info.is_direct());
1773 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI());
1777 // Test cancellation of an in-progress request.
1778 TEST_F(ProxyServiceTest, CancelInProgressRequest) {
1779 MockProxyConfigService* config_service =
1780 new MockProxyConfigService("http://foopy/proxy.pac");
1782 MockAsyncProxyResolver resolver;
1783 MockAsyncProxyResolverFactory* factory =
1784 new MockAsyncProxyResolverFactory(false);
1786 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
1788 // Start 3 requests.
1790 ProxyInfo info1;
1791 TestCompletionCallback callback1;
1792 int rv =
1793 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
1794 callback1.callback(), NULL, NULL, BoundNetLog());
1795 EXPECT_EQ(ERR_IO_PENDING, rv);
1797 // Successfully initialize the PAC script.
1798 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1799 factory->pending_requests()[0]->script_data()->url());
1800 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1802 ASSERT_EQ(1u, resolver.pending_requests().size());
1803 EXPECT_EQ(GURL("http://request1"), resolver.pending_requests()[0]->url());
1805 ProxyInfo info2;
1806 TestCompletionCallback callback2;
1807 ProxyService::PacRequest* request2;
1808 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
1809 callback2.callback(), &request2, NULL,
1810 BoundNetLog());
1811 EXPECT_EQ(ERR_IO_PENDING, rv);
1812 ASSERT_EQ(2u, resolver.pending_requests().size());
1813 EXPECT_EQ(GURL("http://request2"), resolver.pending_requests()[1]->url());
1815 ProxyInfo info3;
1816 TestCompletionCallback callback3;
1817 rv = service.ResolveProxy(GURL("http://request3"), LOAD_NORMAL, &info3,
1818 callback3.callback(), NULL, NULL, BoundNetLog());
1819 EXPECT_EQ(ERR_IO_PENDING, rv);
1820 ASSERT_EQ(3u, resolver.pending_requests().size());
1821 EXPECT_EQ(GURL("http://request3"), resolver.pending_requests()[2]->url());
1823 // Cancel the second request
1824 service.CancelPacRequest(request2);
1826 ASSERT_EQ(2u, resolver.pending_requests().size());
1827 EXPECT_EQ(GURL("http://request1"), resolver.pending_requests()[0]->url());
1828 EXPECT_EQ(GURL("http://request3"), resolver.pending_requests()[1]->url());
1830 // Complete the two un-cancelled requests.
1831 // We complete the last one first, just to mix it up a bit.
1832 resolver.pending_requests()[1]->results()->UseNamedProxy("request3:80");
1833 resolver.pending_requests()[1]->CompleteNow(OK);
1835 resolver.pending_requests()[0]->results()->UseNamedProxy("request1:80");
1836 resolver.pending_requests()[0]->CompleteNow(OK);
1838 // Complete and verify that requests ran as expected.
1839 EXPECT_EQ(OK, callback1.WaitForResult());
1840 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
1842 EXPECT_FALSE(callback2.have_result()); // Cancelled.
1843 ASSERT_EQ(1u, resolver.cancelled_requests().size());
1844 EXPECT_EQ(GURL("http://request2"), resolver.cancelled_requests()[0]->url());
1846 EXPECT_EQ(OK, callback3.WaitForResult());
1847 EXPECT_EQ("request3:80", info3.proxy_server().ToURI());
1850 // Test the initial PAC download for resolver that expects bytes.
1851 TEST_F(ProxyServiceTest, InitialPACScriptDownload) {
1852 MockProxyConfigService* config_service =
1853 new MockProxyConfigService("http://foopy/proxy.pac");
1855 MockAsyncProxyResolver resolver;
1856 MockAsyncProxyResolverFactory* factory =
1857 new MockAsyncProxyResolverFactory(true);
1859 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
1861 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1862 service.SetProxyScriptFetchers(fetcher,
1863 new DoNothingDhcpProxyScriptFetcher());
1865 // Start 3 requests.
1867 ProxyInfo info1;
1868 TestCompletionCallback callback1;
1869 ProxyService::PacRequest* request1;
1870 int rv = service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
1871 callback1.callback(), &request1, NULL,
1872 BoundNetLog());
1873 EXPECT_EQ(ERR_IO_PENDING, rv);
1875 // The first request should have triggered download of PAC script.
1876 EXPECT_TRUE(fetcher->has_pending_request());
1877 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1879 ProxyInfo info2;
1880 TestCompletionCallback callback2;
1881 ProxyService::PacRequest* request2;
1882 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
1883 callback2.callback(), &request2, NULL,
1884 BoundNetLog());
1885 EXPECT_EQ(ERR_IO_PENDING, rv);
1887 ProxyInfo info3;
1888 TestCompletionCallback callback3;
1889 ProxyService::PacRequest* request3;
1890 rv = service.ResolveProxy(GURL("http://request3"), LOAD_NORMAL, &info3,
1891 callback3.callback(), &request3, NULL,
1892 BoundNetLog());
1893 EXPECT_EQ(ERR_IO_PENDING, rv);
1895 // Nothing has been sent to the factory yet.
1896 EXPECT_TRUE(factory->pending_requests().empty());
1898 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT,
1899 service.GetLoadState(request1));
1900 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT,
1901 service.GetLoadState(request2));
1902 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT,
1903 service.GetLoadState(request3));
1905 // At this point the ProxyService should be waiting for the
1906 // ProxyScriptFetcher to invoke its completion callback, notifying it of
1907 // PAC script download completion.
1908 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
1910 // Now that the PAC script is downloaded, it will have been sent to the proxy
1911 // resolver.
1912 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
1913 factory->pending_requests()[0]->script_data()->utf16());
1914 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1916 ASSERT_EQ(3u, resolver.pending_requests().size());
1917 EXPECT_EQ(GURL("http://request1"), resolver.pending_requests()[0]->url());
1918 EXPECT_EQ(GURL("http://request2"), resolver.pending_requests()[1]->url());
1919 EXPECT_EQ(GURL("http://request3"), resolver.pending_requests()[2]->url());
1921 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request1));
1922 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request2));
1923 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request3));
1925 // Complete all the requests (in some order).
1926 // Note that as we complete requests, they shift up in |pending_requests()|.
1928 resolver.pending_requests()[2]->results()->UseNamedProxy("request3:80");
1929 resolver.pending_requests()[2]->CompleteNow(OK);
1931 resolver.pending_requests()[0]->results()->UseNamedProxy("request1:80");
1932 resolver.pending_requests()[0]->CompleteNow(OK);
1934 resolver.pending_requests()[0]->results()->UseNamedProxy("request2:80");
1935 resolver.pending_requests()[0]->CompleteNow(OK);
1937 // Complete and verify that requests ran as expected.
1938 EXPECT_EQ(OK, callback1.WaitForResult());
1939 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
1940 EXPECT_FALSE(info1.proxy_resolve_start_time().is_null());
1941 EXPECT_FALSE(info1.proxy_resolve_end_time().is_null());
1942 EXPECT_LE(info1.proxy_resolve_start_time(), info1.proxy_resolve_end_time());
1944 EXPECT_EQ(OK, callback2.WaitForResult());
1945 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
1946 EXPECT_FALSE(info2.proxy_resolve_start_time().is_null());
1947 EXPECT_FALSE(info2.proxy_resolve_end_time().is_null());
1948 EXPECT_LE(info2.proxy_resolve_start_time(), info2.proxy_resolve_end_time());
1950 EXPECT_EQ(OK, callback3.WaitForResult());
1951 EXPECT_EQ("request3:80", info3.proxy_server().ToURI());
1952 EXPECT_FALSE(info3.proxy_resolve_start_time().is_null());
1953 EXPECT_FALSE(info3.proxy_resolve_end_time().is_null());
1954 EXPECT_LE(info3.proxy_resolve_start_time(), info3.proxy_resolve_end_time());
1957 // Test changing the ProxyScriptFetcher while PAC download is in progress.
1958 TEST_F(ProxyServiceTest, ChangeScriptFetcherWhilePACDownloadInProgress) {
1959 MockProxyConfigService* config_service =
1960 new MockProxyConfigService("http://foopy/proxy.pac");
1962 MockAsyncProxyResolver resolver;
1963 MockAsyncProxyResolverFactory* factory =
1964 new MockAsyncProxyResolverFactory(true);
1966 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
1968 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1969 service.SetProxyScriptFetchers(fetcher,
1970 new DoNothingDhcpProxyScriptFetcher());
1972 // Start 2 requests.
1974 ProxyInfo info1;
1975 TestCompletionCallback callback1;
1976 int rv =
1977 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
1978 callback1.callback(), NULL, NULL, BoundNetLog());
1979 EXPECT_EQ(ERR_IO_PENDING, rv);
1981 // The first request should have triggered download of PAC script.
1982 EXPECT_TRUE(fetcher->has_pending_request());
1983 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1985 ProxyInfo info2;
1986 TestCompletionCallback callback2;
1987 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
1988 callback2.callback(), NULL, NULL, BoundNetLog());
1989 EXPECT_EQ(ERR_IO_PENDING, rv);
1991 // At this point the ProxyService should be waiting for the
1992 // ProxyScriptFetcher to invoke its completion callback, notifying it of
1993 // PAC script download completion.
1995 // We now change out the ProxyService's script fetcher. We should restart
1996 // the initialization with the new fetcher.
1998 fetcher = new MockProxyScriptFetcher;
1999 service.SetProxyScriptFetchers(fetcher,
2000 new DoNothingDhcpProxyScriptFetcher());
2002 // Nothing has been sent to the factory yet.
2003 EXPECT_TRUE(factory->pending_requests().empty());
2005 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2007 // Now that the PAC script is downloaded, it will have been sent to the proxy
2008 // resolver.
2009 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2010 factory->pending_requests()[0]->script_data()->utf16());
2011 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2013 ASSERT_EQ(2u, resolver.pending_requests().size());
2014 EXPECT_EQ(GURL("http://request1"), resolver.pending_requests()[0]->url());
2015 EXPECT_EQ(GURL("http://request2"), resolver.pending_requests()[1]->url());
2018 // Test cancellation of a request, while the PAC script is being fetched.
2019 TEST_F(ProxyServiceTest, CancelWhilePACFetching) {
2020 MockProxyConfigService* config_service =
2021 new MockProxyConfigService("http://foopy/proxy.pac");
2023 MockAsyncProxyResolver resolver;
2024 MockAsyncProxyResolverFactory* factory =
2025 new MockAsyncProxyResolverFactory(true);
2027 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
2029 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2030 service.SetProxyScriptFetchers(fetcher,
2031 new DoNothingDhcpProxyScriptFetcher());
2033 // Start 3 requests.
2034 ProxyInfo info1;
2035 TestCompletionCallback callback1;
2036 ProxyService::PacRequest* request1;
2037 BoundTestNetLog log1;
2038 int rv =
2039 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
2040 callback1.callback(), &request1, NULL, log1.bound());
2041 EXPECT_EQ(ERR_IO_PENDING, rv);
2043 // The first request should have triggered download of PAC script.
2044 EXPECT_TRUE(fetcher->has_pending_request());
2045 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2047 ProxyInfo info2;
2048 TestCompletionCallback callback2;
2049 ProxyService::PacRequest* request2;
2050 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
2051 callback2.callback(), &request2, NULL,
2052 BoundNetLog());
2053 EXPECT_EQ(ERR_IO_PENDING, rv);
2055 ProxyInfo info3;
2056 TestCompletionCallback callback3;
2057 rv = service.ResolveProxy(GURL("http://request3"), LOAD_NORMAL, &info3,
2058 callback3.callback(), NULL, NULL, BoundNetLog());
2059 EXPECT_EQ(ERR_IO_PENDING, rv);
2061 // Nothing has been sent to the factory yet.
2062 EXPECT_TRUE(factory->pending_requests().empty());
2064 // Cancel the first 2 requests.
2065 service.CancelPacRequest(request1);
2066 service.CancelPacRequest(request2);
2068 // At this point the ProxyService should be waiting for the
2069 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2070 // PAC script download completion.
2071 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2073 // Now that the PAC script is downloaded, it will have been sent to the
2074 // proxy resolver.
2075 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2076 factory->pending_requests()[0]->script_data()->utf16());
2077 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2079 ASSERT_EQ(1u, resolver.pending_requests().size());
2080 EXPECT_EQ(GURL("http://request3"), resolver.pending_requests()[0]->url());
2082 // Complete all the requests.
2083 resolver.pending_requests()[0]->results()->UseNamedProxy("request3:80");
2084 resolver.pending_requests()[0]->CompleteNow(OK);
2086 EXPECT_EQ(OK, callback3.WaitForResult());
2087 EXPECT_EQ("request3:80", info3.proxy_server().ToURI());
2089 EXPECT_TRUE(resolver.cancelled_requests().empty());
2091 EXPECT_FALSE(callback1.have_result()); // Cancelled.
2092 EXPECT_FALSE(callback2.have_result()); // Cancelled.
2094 TestNetLogEntry::List entries1;
2095 log1.GetEntries(&entries1);
2097 // Check the NetLog for request 1 (which was cancelled) got filled properly.
2098 EXPECT_EQ(4u, entries1.size());
2099 EXPECT_TRUE(LogContainsBeginEvent(
2100 entries1, 0, NetLog::TYPE_PROXY_SERVICE));
2101 EXPECT_TRUE(LogContainsBeginEvent(
2102 entries1, 1, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
2103 // Note that TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC is never completed before
2104 // the cancellation occured.
2105 EXPECT_TRUE(LogContainsEvent(
2106 entries1, 2, NetLog::TYPE_CANCELLED, NetLog::PHASE_NONE));
2107 EXPECT_TRUE(LogContainsEndEvent(
2108 entries1, 3, NetLog::TYPE_PROXY_SERVICE));
2111 // Test that if auto-detect fails, we fall-back to the custom pac.
2112 TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomPac) {
2113 ProxyConfig config;
2114 config.set_auto_detect(true);
2115 config.set_pac_url(GURL("http://foopy/proxy.pac"));
2116 config.proxy_rules().ParseFromString("http=foopy:80"); // Won't be used.
2118 MockProxyConfigService* config_service = new MockProxyConfigService(config);
2119 MockAsyncProxyResolver resolver;
2120 MockAsyncProxyResolverFactory* factory =
2121 new MockAsyncProxyResolverFactory(true);
2122 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
2124 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2125 service.SetProxyScriptFetchers(fetcher,
2126 new DoNothingDhcpProxyScriptFetcher());
2128 // Start 2 requests.
2130 ProxyInfo info1;
2131 TestCompletionCallback callback1;
2132 int rv =
2133 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
2134 callback1.callback(), NULL, NULL, BoundNetLog());
2135 EXPECT_EQ(ERR_IO_PENDING, rv);
2137 ProxyInfo info2;
2138 TestCompletionCallback callback2;
2139 ProxyService::PacRequest* request2;
2140 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
2141 callback2.callback(), &request2, NULL,
2142 BoundNetLog());
2143 EXPECT_EQ(ERR_IO_PENDING, rv);
2145 // Check that nothing has been sent to the proxy resolver factory yet.
2146 ASSERT_EQ(0u, factory->pending_requests().size());
2148 // It should be trying to auto-detect first -- FAIL the autodetect during
2149 // the script download.
2150 EXPECT_TRUE(fetcher->has_pending_request());
2151 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
2152 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
2154 // Next it should be trying the custom PAC url.
2155 EXPECT_TRUE(fetcher->has_pending_request());
2156 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2157 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2159 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2160 factory->pending_requests()[0]->script_data()->utf16());
2161 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2163 // Now finally, the pending requests should have been sent to the resolver
2164 // (which was initialized with custom PAC script).
2166 ASSERT_EQ(2u, resolver.pending_requests().size());
2167 EXPECT_EQ(GURL("http://request1"), resolver.pending_requests()[0]->url());
2168 EXPECT_EQ(GURL("http://request2"), resolver.pending_requests()[1]->url());
2170 // Complete the pending requests.
2171 resolver.pending_requests()[1]->results()->UseNamedProxy("request2:80");
2172 resolver.pending_requests()[1]->CompleteNow(OK);
2173 resolver.pending_requests()[0]->results()->UseNamedProxy("request1:80");
2174 resolver.pending_requests()[0]->CompleteNow(OK);
2176 // Verify that requests ran as expected.
2177 EXPECT_EQ(OK, callback1.WaitForResult());
2178 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2179 EXPECT_FALSE(info1.proxy_resolve_start_time().is_null());
2180 EXPECT_FALSE(info1.proxy_resolve_end_time().is_null());
2181 EXPECT_LE(info1.proxy_resolve_start_time(), info1.proxy_resolve_end_time());
2183 EXPECT_EQ(OK, callback2.WaitForResult());
2184 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2185 EXPECT_FALSE(info2.proxy_resolve_start_time().is_null());
2186 EXPECT_FALSE(info2.proxy_resolve_end_time().is_null());
2187 EXPECT_LE(info2.proxy_resolve_start_time(), info2.proxy_resolve_end_time());
2190 // This is the same test as FallbackFromAutodetectToCustomPac, except
2191 // the auto-detect script fails parsing rather than downloading.
2192 TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomPac2) {
2193 ProxyConfig config;
2194 config.set_auto_detect(true);
2195 config.set_pac_url(GURL("http://foopy/proxy.pac"));
2196 config.proxy_rules().ParseFromString("http=foopy:80"); // Won't be used.
2198 MockProxyConfigService* config_service = new MockProxyConfigService(config);
2199 MockAsyncProxyResolver resolver;
2200 MockAsyncProxyResolverFactory* factory =
2201 new MockAsyncProxyResolverFactory(true);
2202 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
2204 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2205 service.SetProxyScriptFetchers(fetcher,
2206 new DoNothingDhcpProxyScriptFetcher());
2208 // Start 2 requests.
2210 ProxyInfo info1;
2211 TestCompletionCallback callback1;
2212 int rv =
2213 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
2214 callback1.callback(), NULL, NULL, BoundNetLog());
2215 EXPECT_EQ(ERR_IO_PENDING, rv);
2217 ProxyInfo info2;
2218 TestCompletionCallback callback2;
2219 ProxyService::PacRequest* request2;
2220 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
2221 callback2.callback(), &request2, NULL,
2222 BoundNetLog());
2223 EXPECT_EQ(ERR_IO_PENDING, rv);
2225 // Check that nothing has been sent to the proxy resolver factory yet.
2226 ASSERT_EQ(0u, factory->pending_requests().size());
2228 // It should be trying to auto-detect first -- succeed the download.
2229 EXPECT_TRUE(fetcher->has_pending_request());
2230 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
2231 fetcher->NotifyFetchCompletion(OK, "invalid-script-contents");
2233 // The script contents passed failed basic verification step (since didn't
2234 // contain token FindProxyForURL), so it was never passed to the resolver.
2236 // Next it should be trying the custom PAC url.
2237 EXPECT_TRUE(fetcher->has_pending_request());
2238 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2239 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2241 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2242 factory->pending_requests()[0]->script_data()->utf16());
2243 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2245 // Now finally, the pending requests should have been sent to the resolver
2246 // (which was initialized with custom PAC script).
2248 ASSERT_EQ(2u, resolver.pending_requests().size());
2249 EXPECT_EQ(GURL("http://request1"), resolver.pending_requests()[0]->url());
2250 EXPECT_EQ(GURL("http://request2"), resolver.pending_requests()[1]->url());
2252 // Complete the pending requests.
2253 resolver.pending_requests()[1]->results()->UseNamedProxy("request2:80");
2254 resolver.pending_requests()[1]->CompleteNow(OK);
2255 resolver.pending_requests()[0]->results()->UseNamedProxy("request1:80");
2256 resolver.pending_requests()[0]->CompleteNow(OK);
2258 // Verify that requests ran as expected.
2259 EXPECT_EQ(OK, callback1.WaitForResult());
2260 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2262 EXPECT_EQ(OK, callback2.WaitForResult());
2263 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2266 // Test that if all of auto-detect, a custom PAC script, and manual settings
2267 // are given, then we will try them in that order.
2268 TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomToManual) {
2269 ProxyConfig config;
2270 config.set_auto_detect(true);
2271 config.set_pac_url(GURL("http://foopy/proxy.pac"));
2272 config.proxy_rules().ParseFromString("http=foopy:80");
2274 MockProxyConfigService* config_service = new MockProxyConfigService(config);
2275 MockAsyncProxyResolverFactory* factory =
2276 new MockAsyncProxyResolverFactory(true);
2277 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
2279 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2280 service.SetProxyScriptFetchers(fetcher,
2281 new DoNothingDhcpProxyScriptFetcher());
2283 // Start 2 requests.
2285 ProxyInfo info1;
2286 TestCompletionCallback callback1;
2287 int rv =
2288 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
2289 callback1.callback(), NULL, NULL, BoundNetLog());
2290 EXPECT_EQ(ERR_IO_PENDING, rv);
2292 ProxyInfo info2;
2293 TestCompletionCallback callback2;
2294 ProxyService::PacRequest* request2;
2295 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
2296 callback2.callback(), &request2, NULL,
2297 BoundNetLog());
2298 EXPECT_EQ(ERR_IO_PENDING, rv);
2300 // Check that nothing has been sent to the proxy resolver factory yet.
2301 ASSERT_EQ(0u, factory->pending_requests().size());
2303 // It should be trying to auto-detect first -- fail the download.
2304 EXPECT_TRUE(fetcher->has_pending_request());
2305 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
2306 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
2308 // Next it should be trying the custom PAC url -- fail the download.
2309 EXPECT_TRUE(fetcher->has_pending_request());
2310 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2311 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
2313 // Since we never managed to initialize a resolver, nothing should have been
2314 // sent to it.
2315 ASSERT_EQ(0u, factory->pending_requests().size());
2317 // Verify that requests ran as expected -- they should have fallen back to
2318 // the manual proxy configuration for HTTP urls.
2319 EXPECT_EQ(OK, callback1.WaitForResult());
2320 EXPECT_EQ("foopy:80", info1.proxy_server().ToURI());
2322 EXPECT_EQ(OK, callback2.WaitForResult());
2323 EXPECT_EQ("foopy:80", info2.proxy_server().ToURI());
2326 // Test that the bypass rules are NOT applied when using autodetect.
2327 TEST_F(ProxyServiceTest, BypassDoesntApplyToPac) {
2328 ProxyConfig config;
2329 config.set_auto_detect(true);
2330 config.set_pac_url(GURL("http://foopy/proxy.pac"));
2331 config.proxy_rules().ParseFromString("http=foopy:80"); // Not used.
2332 config.proxy_rules().bypass_rules.ParseFromString("www.google.com");
2334 MockProxyConfigService* config_service = new MockProxyConfigService(config);
2335 MockAsyncProxyResolver resolver;
2336 MockAsyncProxyResolverFactory* factory =
2337 new MockAsyncProxyResolverFactory(true);
2338 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
2340 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2341 service.SetProxyScriptFetchers(fetcher,
2342 new DoNothingDhcpProxyScriptFetcher());
2344 // Start 1 requests.
2346 ProxyInfo info1;
2347 TestCompletionCallback callback1;
2348 int rv =
2349 service.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL, &info1,
2350 callback1.callback(), NULL, NULL, BoundNetLog());
2351 EXPECT_EQ(ERR_IO_PENDING, rv);
2353 // Check that nothing has been sent to the proxy resolver factory yet.
2354 ASSERT_EQ(0u, factory->pending_requests().size());
2356 // It should be trying to auto-detect first -- succeed the download.
2357 EXPECT_TRUE(fetcher->has_pending_request());
2358 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
2359 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2361 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2362 factory->pending_requests()[0]->script_data()->utf16());
2363 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2365 ASSERT_EQ(1u, resolver.pending_requests().size());
2366 EXPECT_EQ(GURL("http://www.google.com"),
2367 resolver.pending_requests()[0]->url());
2369 // Complete the pending request.
2370 resolver.pending_requests()[0]->results()->UseNamedProxy("request1:80");
2371 resolver.pending_requests()[0]->CompleteNow(OK);
2373 // Verify that request ran as expected.
2374 EXPECT_EQ(OK, callback1.WaitForResult());
2375 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2377 // Start another request, it should pickup the bypass item.
2378 ProxyInfo info2;
2379 TestCompletionCallback callback2;
2380 rv = service.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL, &info2,
2381 callback2.callback(), NULL, NULL, BoundNetLog());
2382 EXPECT_EQ(ERR_IO_PENDING, rv);
2384 ASSERT_EQ(1u, resolver.pending_requests().size());
2385 EXPECT_EQ(GURL("http://www.google.com"),
2386 resolver.pending_requests()[0]->url());
2388 // Complete the pending request.
2389 resolver.pending_requests()[0]->results()->UseNamedProxy("request2:80");
2390 resolver.pending_requests()[0]->CompleteNow(OK);
2392 EXPECT_EQ(OK, callback2.WaitForResult());
2393 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2396 // Delete the ProxyService while InitProxyResolver has an outstanding
2397 // request to the script fetcher. When run under valgrind, should not
2398 // have any memory errors (used to be that the ProxyScriptFetcher was
2399 // being deleted prior to the InitProxyResolver).
2400 TEST_F(ProxyServiceTest, DeleteWhileInitProxyResolverHasOutstandingFetch) {
2401 ProxyConfig config =
2402 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"));
2404 MockProxyConfigService* config_service = new MockProxyConfigService(config);
2405 MockAsyncProxyResolverFactory* factory =
2406 new MockAsyncProxyResolverFactory(true);
2407 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
2409 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2410 service.SetProxyScriptFetchers(fetcher,
2411 new DoNothingDhcpProxyScriptFetcher());
2413 // Start 1 request.
2415 ProxyInfo info1;
2416 TestCompletionCallback callback1;
2417 int rv =
2418 service.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL, &info1,
2419 callback1.callback(), NULL, NULL, BoundNetLog());
2420 EXPECT_EQ(ERR_IO_PENDING, rv);
2422 // Check that nothing has been sent to the proxy resolver factory yet.
2423 ASSERT_EQ(0u, factory->pending_requests().size());
2425 // InitProxyResolver should have issued a request to the ProxyScriptFetcher
2426 // and be waiting on that to complete.
2427 EXPECT_TRUE(fetcher->has_pending_request());
2428 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2431 // Delete the ProxyService while InitProxyResolver has an outstanding
2432 // request to the proxy resolver. When run under valgrind, should not
2433 // have any memory errors (used to be that the ProxyResolver was
2434 // being deleted prior to the InitProxyResolver).
2435 TEST_F(ProxyServiceTest, DeleteWhileInitProxyResolverHasOutstandingSet) {
2436 MockProxyConfigService* config_service =
2437 new MockProxyConfigService("http://foopy/proxy.pac");
2439 MockAsyncProxyResolverFactory* factory =
2440 new MockAsyncProxyResolverFactory(false);
2442 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
2444 GURL url("http://www.google.com/");
2446 ProxyInfo info;
2447 TestCompletionCallback callback;
2448 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
2449 NULL, NULL, BoundNetLog());
2450 EXPECT_EQ(ERR_IO_PENDING, rv);
2452 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
2453 factory->pending_requests()[0]->script_data()->url());
2456 TEST_F(ProxyServiceTest, ResetProxyConfigService) {
2457 ProxyConfig config1;
2458 config1.proxy_rules().ParseFromString("foopy1:8080");
2459 config1.set_auto_detect(false);
2460 ProxyService service(new MockProxyConfigService(config1), nullptr, NULL);
2462 ProxyInfo info;
2463 TestCompletionCallback callback1;
2464 int rv =
2465 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info,
2466 callback1.callback(), NULL, NULL, BoundNetLog());
2467 EXPECT_EQ(OK, rv);
2468 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
2470 ProxyConfig config2;
2471 config2.proxy_rules().ParseFromString("foopy2:8080");
2472 config2.set_auto_detect(false);
2473 service.ResetConfigService(new MockProxyConfigService(config2));
2474 TestCompletionCallback callback2;
2475 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info,
2476 callback2.callback(), NULL, NULL, BoundNetLog());
2477 EXPECT_EQ(OK, rv);
2478 EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI());
2481 // Test that when going from a configuration that required PAC to one
2482 // that does NOT, we unset the variable |should_use_proxy_resolver_|.
2483 TEST_F(ProxyServiceTest, UpdateConfigFromPACToDirect) {
2484 ProxyConfig config = ProxyConfig::CreateAutoDetect();
2486 MockProxyConfigService* config_service = new MockProxyConfigService(config);
2487 MockAsyncProxyResolver resolver;
2488 MockAsyncProxyResolverFactory* factory =
2489 new MockAsyncProxyResolverFactory(false);
2490 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
2492 // Start 1 request.
2494 ProxyInfo info1;
2495 TestCompletionCallback callback1;
2496 int rv =
2497 service.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL, &info1,
2498 callback1.callback(), NULL, NULL, BoundNetLog());
2499 EXPECT_EQ(ERR_IO_PENDING, rv);
2501 // Successfully set the autodetect script.
2502 EXPECT_EQ(ProxyResolverScriptData::TYPE_AUTO_DETECT,
2503 factory->pending_requests()[0]->script_data()->type());
2504 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2506 // Complete the pending request.
2507 ASSERT_EQ(1u, resolver.pending_requests().size());
2508 resolver.pending_requests()[0]->results()->UseNamedProxy("request1:80");
2509 resolver.pending_requests()[0]->CompleteNow(OK);
2511 // Verify that request ran as expected.
2512 EXPECT_EQ(OK, callback1.WaitForResult());
2513 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2515 // Force the ProxyService to pull down a new proxy configuration.
2516 // (Even though the configuration isn't old/bad).
2518 // This new configuration no longer has auto_detect set, so
2519 // requests should complete synchronously now as direct-connect.
2520 config_service->SetConfig(ProxyConfig::CreateDirect());
2522 // Start another request -- the effective configuration has changed.
2523 ProxyInfo info2;
2524 TestCompletionCallback callback2;
2525 rv = service.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL, &info2,
2526 callback2.callback(), NULL, NULL, BoundNetLog());
2527 EXPECT_EQ(OK, rv);
2529 EXPECT_TRUE(info2.is_direct());
2532 TEST_F(ProxyServiceTest, NetworkChangeTriggersPacRefetch) {
2533 MockProxyConfigService* config_service =
2534 new MockProxyConfigService("http://foopy/proxy.pac");
2536 MockAsyncProxyResolver resolver;
2537 MockAsyncProxyResolverFactory* factory =
2538 new MockAsyncProxyResolverFactory(true);
2540 TestNetLog log;
2542 ProxyService service(config_service, make_scoped_ptr(factory), &log);
2544 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2545 service.SetProxyScriptFetchers(fetcher,
2546 new DoNothingDhcpProxyScriptFetcher());
2548 // Disable the "wait after IP address changes" hack, so this unit-test can
2549 // complete quickly.
2550 service.set_stall_proxy_auto_config_delay(base::TimeDelta());
2552 // Start 1 request.
2554 ProxyInfo info1;
2555 TestCompletionCallback callback1;
2556 int rv =
2557 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
2558 callback1.callback(), NULL, NULL, BoundNetLog());
2559 EXPECT_EQ(ERR_IO_PENDING, rv);
2561 // The first request should have triggered initial download of PAC script.
2562 EXPECT_TRUE(fetcher->has_pending_request());
2563 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2565 // Nothing has been sent to the factory yet.
2566 EXPECT_TRUE(factory->pending_requests().empty());
2568 // At this point the ProxyService should be waiting for the
2569 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2570 // PAC script download completion.
2571 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2573 // Now that the PAC script is downloaded, the request will have been sent to
2574 // the proxy resolver.
2575 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2576 factory->pending_requests()[0]->script_data()->utf16());
2577 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2579 ASSERT_EQ(1u, resolver.pending_requests().size());
2580 EXPECT_EQ(GURL("http://request1"), resolver.pending_requests()[0]->url());
2582 // Complete the pending request.
2583 resolver.pending_requests()[0]->results()->UseNamedProxy("request1:80");
2584 resolver.pending_requests()[0]->CompleteNow(OK);
2586 // Wait for completion callback, and verify that the request ran as expected.
2587 EXPECT_EQ(OK, callback1.WaitForResult());
2588 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2590 // Now simluate a change in the network. The ProxyConfigService is still
2591 // going to return the same PAC URL as before, but this URL needs to be
2592 // refetched on the new network.
2593 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
2594 base::MessageLoop::current()->RunUntilIdle(); // Notification happens async.
2596 // Start a second request.
2597 ProxyInfo info2;
2598 TestCompletionCallback callback2;
2599 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
2600 callback2.callback(), NULL, NULL, BoundNetLog());
2601 EXPECT_EQ(ERR_IO_PENDING, rv);
2603 // This second request should have triggered the re-download of the PAC
2604 // script (since we marked the network as having changed).
2605 EXPECT_TRUE(fetcher->has_pending_request());
2606 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2608 // Nothing has been sent to the factory yet.
2609 EXPECT_TRUE(factory->pending_requests().empty());
2611 // Simulate the PAC script fetch as having completed (this time with
2612 // different data).
2613 fetcher->NotifyFetchCompletion(OK, kValidPacScript2);
2615 // Now that the PAC script is downloaded, the second request will have been
2616 // sent to the proxy resolver.
2617 EXPECT_EQ(ASCIIToUTF16(kValidPacScript2),
2618 factory->pending_requests()[0]->script_data()->utf16());
2619 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2621 ASSERT_EQ(1u, resolver.pending_requests().size());
2622 EXPECT_EQ(GURL("http://request2"), resolver.pending_requests()[0]->url());
2624 // Complete the pending second request.
2625 resolver.pending_requests()[0]->results()->UseNamedProxy("request2:80");
2626 resolver.pending_requests()[0]->CompleteNow(OK);
2628 // Wait for completion callback, and verify that the request ran as expected.
2629 EXPECT_EQ(OK, callback2.WaitForResult());
2630 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2632 // Check that the expected events were output to the log stream. In particular
2633 // PROXY_CONFIG_CHANGED should have only been emitted once (for the initial
2634 // setup), and NOT a second time when the IP address changed.
2635 TestNetLogEntry::List entries;
2636 log.GetEntries(&entries);
2638 EXPECT_TRUE(LogContainsEntryWithType(entries, 0,
2639 NetLog::TYPE_PROXY_CONFIG_CHANGED));
2640 ASSERT_EQ(9u, entries.size());
2641 for (size_t i = 1; i < entries.size(); ++i)
2642 EXPECT_NE(NetLog::TYPE_PROXY_CONFIG_CHANGED, entries[i].type);
2645 // This test verifies that the PAC script specified by the settings is
2646 // periodically polled for changes. Specifically, if the initial fetch fails due
2647 // to a network error, we will eventually re-configure the service to use the
2648 // script once it becomes available.
2649 TEST_F(ProxyServiceTest, PACScriptRefetchAfterFailure) {
2650 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2651 // runs quickly.
2652 ImmediatePollPolicy poll_policy;
2653 ProxyService::set_pac_script_poll_policy(&poll_policy);
2655 MockProxyConfigService* config_service =
2656 new MockProxyConfigService("http://foopy/proxy.pac");
2658 MockAsyncProxyResolver resolver;
2659 MockAsyncProxyResolverFactory* factory =
2660 new MockAsyncProxyResolverFactory(true);
2662 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
2664 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2665 service.SetProxyScriptFetchers(fetcher,
2666 new DoNothingDhcpProxyScriptFetcher());
2668 // Start 1 request.
2670 ProxyInfo info1;
2671 TestCompletionCallback callback1;
2672 int rv =
2673 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
2674 callback1.callback(), NULL, NULL, BoundNetLog());
2675 EXPECT_EQ(ERR_IO_PENDING, rv);
2677 // The first request should have triggered initial download of PAC script.
2678 EXPECT_TRUE(fetcher->has_pending_request());
2679 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2681 // Nothing has been sent to the factory yet.
2682 EXPECT_TRUE(factory->pending_requests().empty());
2684 // At this point the ProxyService should be waiting for the
2685 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2686 // PAC script download completion.
2688 // We simulate a failed download attempt, the proxy service should now
2689 // fall-back to DIRECT connections.
2690 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
2692 ASSERT_TRUE(factory->pending_requests().empty());
2694 // Wait for completion callback, and verify it used DIRECT.
2695 EXPECT_EQ(OK, callback1.WaitForResult());
2696 EXPECT_TRUE(info1.is_direct());
2698 // At this point we have initialized the proxy service using a PAC script,
2699 // however it failed and fell-back to DIRECT.
2701 // A background task to periodically re-check the PAC script for validity will
2702 // have been started. We will now wait for the next download attempt to start.
2704 // Note that we shouldn't have to wait long here, since our test enables a
2705 // special unit-test mode.
2706 fetcher->WaitUntilFetch();
2708 ASSERT_TRUE(factory->pending_requests().empty());
2710 // Make sure that our background checker is trying to download the expected
2711 // PAC script (same one as before). This time we will simulate a successful
2712 // download of the script.
2713 EXPECT_TRUE(fetcher->has_pending_request());
2714 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2715 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2717 base::MessageLoop::current()->RunUntilIdle();
2719 // Now that the PAC script is downloaded, it should be used to initialize the
2720 // ProxyResolver. Simulate a successful parse.
2721 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2722 factory->pending_requests()[0]->script_data()->utf16());
2723 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2725 // At this point the ProxyService should have re-configured itself to use the
2726 // PAC script (thereby recovering from the initial fetch failure). We will
2727 // verify that the next Resolve request uses the resolver rather than
2728 // DIRECT.
2730 // Start a second request.
2731 ProxyInfo info2;
2732 TestCompletionCallback callback2;
2733 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
2734 callback2.callback(), NULL, NULL, BoundNetLog());
2735 EXPECT_EQ(ERR_IO_PENDING, rv);
2737 // Check that it was sent to the resolver.
2738 ASSERT_EQ(1u, resolver.pending_requests().size());
2739 EXPECT_EQ(GURL("http://request2"), resolver.pending_requests()[0]->url());
2741 // Complete the pending second request.
2742 resolver.pending_requests()[0]->results()->UseNamedProxy("request2:80");
2743 resolver.pending_requests()[0]->CompleteNow(OK);
2745 // Wait for completion callback, and verify that the request ran as expected.
2746 EXPECT_EQ(OK, callback2.WaitForResult());
2747 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2750 // This test verifies that the PAC script specified by the settings is
2751 // periodically polled for changes. Specifically, if the initial fetch succeeds,
2752 // however at a later time its *contents* change, we will eventually
2753 // re-configure the service to use the new script.
2754 TEST_F(ProxyServiceTest, PACScriptRefetchAfterContentChange) {
2755 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2756 // runs quickly.
2757 ImmediatePollPolicy poll_policy;
2758 ProxyService::set_pac_script_poll_policy(&poll_policy);
2760 MockProxyConfigService* config_service =
2761 new MockProxyConfigService("http://foopy/proxy.pac");
2763 MockAsyncProxyResolver resolver;
2764 MockAsyncProxyResolverFactory* factory =
2765 new MockAsyncProxyResolverFactory(true);
2767 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
2769 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2770 service.SetProxyScriptFetchers(fetcher,
2771 new DoNothingDhcpProxyScriptFetcher());
2773 // Start 1 request.
2775 ProxyInfo info1;
2776 TestCompletionCallback callback1;
2777 int rv =
2778 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
2779 callback1.callback(), NULL, NULL, BoundNetLog());
2780 EXPECT_EQ(ERR_IO_PENDING, rv);
2782 // The first request should have triggered initial download of PAC script.
2783 EXPECT_TRUE(fetcher->has_pending_request());
2784 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2786 // Nothing has been sent to the factory yet.
2787 EXPECT_TRUE(factory->pending_requests().empty());
2789 // At this point the ProxyService should be waiting for the
2790 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2791 // PAC script download completion.
2792 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2794 // Now that the PAC script is downloaded, the request will have been sent to
2795 // the proxy resolver.
2796 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2797 factory->pending_requests()[0]->script_data()->utf16());
2798 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2800 ASSERT_EQ(1u, resolver.pending_requests().size());
2801 EXPECT_EQ(GURL("http://request1"), resolver.pending_requests()[0]->url());
2803 // Complete the pending request.
2804 resolver.pending_requests()[0]->results()->UseNamedProxy("request1:80");
2805 resolver.pending_requests()[0]->CompleteNow(OK);
2807 // Wait for completion callback, and verify that the request ran as expected.
2808 EXPECT_EQ(OK, callback1.WaitForResult());
2809 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2811 // At this point we have initialized the proxy service using a PAC script.
2813 // A background task to periodically re-check the PAC script for validity will
2814 // have been started. We will now wait for the next download attempt to start.
2816 // Note that we shouldn't have to wait long here, since our test enables a
2817 // special unit-test mode.
2818 fetcher->WaitUntilFetch();
2820 ASSERT_TRUE(factory->pending_requests().empty());
2821 ASSERT_TRUE(resolver.pending_requests().empty());
2823 // Make sure that our background checker is trying to download the expected
2824 // PAC script (same one as before). This time we will simulate a successful
2825 // download of a DIFFERENT script.
2826 EXPECT_TRUE(fetcher->has_pending_request());
2827 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2828 fetcher->NotifyFetchCompletion(OK, kValidPacScript2);
2830 base::MessageLoop::current()->RunUntilIdle();
2832 // Now that the PAC script is downloaded, it should be used to initialize the
2833 // ProxyResolver. Simulate a successful parse.
2834 EXPECT_EQ(ASCIIToUTF16(kValidPacScript2),
2835 factory->pending_requests()[0]->script_data()->utf16());
2836 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2838 // At this point the ProxyService should have re-configured itself to use the
2839 // new PAC script.
2841 // Start a second request.
2842 ProxyInfo info2;
2843 TestCompletionCallback callback2;
2844 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
2845 callback2.callback(), NULL, NULL, BoundNetLog());
2846 EXPECT_EQ(ERR_IO_PENDING, rv);
2848 // Check that it was sent to the resolver.
2849 ASSERT_EQ(1u, resolver.pending_requests().size());
2850 EXPECT_EQ(GURL("http://request2"), resolver.pending_requests()[0]->url());
2852 // Complete the pending second request.
2853 resolver.pending_requests()[0]->results()->UseNamedProxy("request2:80");
2854 resolver.pending_requests()[0]->CompleteNow(OK);
2856 // Wait for completion callback, and verify that the request ran as expected.
2857 EXPECT_EQ(OK, callback2.WaitForResult());
2858 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2861 // This test verifies that the PAC script specified by the settings is
2862 // periodically polled for changes. Specifically, if the initial fetch succeeds
2863 // and so does the next poll, however the contents of the downloaded script
2864 // have NOT changed, then we do not bother to re-initialize the proxy resolver.
2865 TEST_F(ProxyServiceTest, PACScriptRefetchAfterContentUnchanged) {
2866 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2867 // runs quickly.
2868 ImmediatePollPolicy poll_policy;
2869 ProxyService::set_pac_script_poll_policy(&poll_policy);
2871 MockProxyConfigService* config_service =
2872 new MockProxyConfigService("http://foopy/proxy.pac");
2874 MockAsyncProxyResolver resolver;
2875 MockAsyncProxyResolverFactory* factory =
2876 new MockAsyncProxyResolverFactory(true);
2878 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
2880 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2881 service.SetProxyScriptFetchers(fetcher,
2882 new DoNothingDhcpProxyScriptFetcher());
2884 // Start 1 request.
2886 ProxyInfo info1;
2887 TestCompletionCallback callback1;
2888 int rv =
2889 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
2890 callback1.callback(), NULL, NULL, BoundNetLog());
2891 EXPECT_EQ(ERR_IO_PENDING, rv);
2893 // The first request should have triggered initial download of PAC script.
2894 EXPECT_TRUE(fetcher->has_pending_request());
2895 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2897 // Nothing has been sent to the factory yet.
2898 EXPECT_TRUE(factory->pending_requests().empty());
2900 // At this point the ProxyService should be waiting for the
2901 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2902 // PAC script download completion.
2903 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2905 // Now that the PAC script is downloaded, the request will have been sent to
2906 // the proxy resolver.
2907 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2908 factory->pending_requests()[0]->script_data()->utf16());
2909 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2911 ASSERT_EQ(1u, resolver.pending_requests().size());
2912 EXPECT_EQ(GURL("http://request1"), resolver.pending_requests()[0]->url());
2914 // Complete the pending request.
2915 resolver.pending_requests()[0]->results()->UseNamedProxy("request1:80");
2916 resolver.pending_requests()[0]->CompleteNow(OK);
2918 // Wait for completion callback, and verify that the request ran as expected.
2919 EXPECT_EQ(OK, callback1.WaitForResult());
2920 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2922 // At this point we have initialized the proxy service using a PAC script.
2924 // A background task to periodically re-check the PAC script for validity will
2925 // have been started. We will now wait for the next download attempt to start.
2927 // Note that we shouldn't have to wait long here, since our test enables a
2928 // special unit-test mode.
2929 fetcher->WaitUntilFetch();
2931 ASSERT_TRUE(factory->pending_requests().empty());
2932 ASSERT_TRUE(resolver.pending_requests().empty());
2934 // Make sure that our background checker is trying to download the expected
2935 // PAC script (same one as before). We will simulate the same response as
2936 // last time (i.e. the script is unchanged).
2937 EXPECT_TRUE(fetcher->has_pending_request());
2938 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2939 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2941 base::MessageLoop::current()->RunUntilIdle();
2943 ASSERT_TRUE(factory->pending_requests().empty());
2944 ASSERT_TRUE(resolver.pending_requests().empty());
2946 // At this point the ProxyService is still running the same PAC script as
2947 // before.
2949 // Start a second request.
2950 ProxyInfo info2;
2951 TestCompletionCallback callback2;
2952 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
2953 callback2.callback(), NULL, NULL, BoundNetLog());
2954 EXPECT_EQ(ERR_IO_PENDING, rv);
2956 // Check that it was sent to the resolver.
2957 ASSERT_EQ(1u, resolver.pending_requests().size());
2958 EXPECT_EQ(GURL("http://request2"), resolver.pending_requests()[0]->url());
2960 // Complete the pending second request.
2961 resolver.pending_requests()[0]->results()->UseNamedProxy("request2:80");
2962 resolver.pending_requests()[0]->CompleteNow(OK);
2964 // Wait for completion callback, and verify that the request ran as expected.
2965 EXPECT_EQ(OK, callback2.WaitForResult());
2966 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2969 // This test verifies that the PAC script specified by the settings is
2970 // periodically polled for changes. Specifically, if the initial fetch succeeds,
2971 // however at a later time it starts to fail, we should re-configure the
2972 // ProxyService to stop using that PAC script.
2973 TEST_F(ProxyServiceTest, PACScriptRefetchAfterSuccess) {
2974 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2975 // runs quickly.
2976 ImmediatePollPolicy poll_policy;
2977 ProxyService::set_pac_script_poll_policy(&poll_policy);
2979 MockProxyConfigService* config_service =
2980 new MockProxyConfigService("http://foopy/proxy.pac");
2982 MockAsyncProxyResolver resolver;
2983 MockAsyncProxyResolverFactory* factory =
2984 new MockAsyncProxyResolverFactory(true);
2986 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
2988 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2989 service.SetProxyScriptFetchers(fetcher,
2990 new DoNothingDhcpProxyScriptFetcher());
2992 // Start 1 request.
2994 ProxyInfo info1;
2995 TestCompletionCallback callback1;
2996 int rv =
2997 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
2998 callback1.callback(), NULL, NULL, BoundNetLog());
2999 EXPECT_EQ(ERR_IO_PENDING, rv);
3001 // The first request should have triggered initial download of PAC script.
3002 EXPECT_TRUE(fetcher->has_pending_request());
3003 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
3005 // Nothing has been sent to the factory yet.
3006 EXPECT_TRUE(factory->pending_requests().empty());
3008 // At this point the ProxyService should be waiting for the
3009 // ProxyScriptFetcher to invoke its completion callback, notifying it of
3010 // PAC script download completion.
3011 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
3013 // Now that the PAC script is downloaded, the request will have been sent to
3014 // the proxy resolver.
3015 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
3016 factory->pending_requests()[0]->script_data()->utf16());
3017 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
3019 ASSERT_EQ(1u, resolver.pending_requests().size());
3020 EXPECT_EQ(GURL("http://request1"), resolver.pending_requests()[0]->url());
3022 // Complete the pending request.
3023 resolver.pending_requests()[0]->results()->UseNamedProxy("request1:80");
3024 resolver.pending_requests()[0]->CompleteNow(OK);
3026 // Wait for completion callback, and verify that the request ran as expected.
3027 EXPECT_EQ(OK, callback1.WaitForResult());
3028 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
3030 // At this point we have initialized the proxy service using a PAC script.
3032 // A background task to periodically re-check the PAC script for validity will
3033 // have been started. We will now wait for the next download attempt to start.
3035 // Note that we shouldn't have to wait long here, since our test enables a
3036 // special unit-test mode.
3037 fetcher->WaitUntilFetch();
3039 ASSERT_TRUE(factory->pending_requests().empty());
3040 ASSERT_TRUE(resolver.pending_requests().empty());
3042 // Make sure that our background checker is trying to download the expected
3043 // PAC script (same one as before). This time we will simulate a failure
3044 // to download the script.
3045 EXPECT_TRUE(fetcher->has_pending_request());
3046 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
3047 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
3049 base::MessageLoop::current()->RunUntilIdle();
3051 // At this point the ProxyService should have re-configured itself to use
3052 // DIRECT connections rather than the given proxy resolver.
3054 // Start a second request.
3055 ProxyInfo info2;
3056 TestCompletionCallback callback2;
3057 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
3058 callback2.callback(), NULL, NULL, BoundNetLog());
3059 EXPECT_EQ(OK, rv);
3060 EXPECT_TRUE(info2.is_direct());
3063 // Tests that the code which decides at what times to poll the PAC
3064 // script follows the expected policy.
3065 TEST_F(ProxyServiceTest, PACScriptPollingPolicy) {
3066 // Retrieve the internal polling policy implementation used by ProxyService.
3067 scoped_ptr<ProxyService::PacPollPolicy> policy =
3068 ProxyService::CreateDefaultPacPollPolicy();
3070 int error;
3071 ProxyService::PacPollPolicy::Mode mode;
3072 const base::TimeDelta initial_delay = base::TimeDelta::FromMilliseconds(-1);
3073 base::TimeDelta delay = initial_delay;
3075 // --------------------------------------------------
3076 // Test the poll sequence in response to a failure.
3077 // --------------------------------------------------
3078 error = ERR_NAME_NOT_RESOLVED;
3080 // Poll #0
3081 mode = policy->GetNextDelay(error, initial_delay, &delay);
3082 EXPECT_EQ(8, delay.InSeconds());
3083 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_USE_TIMER, mode);
3085 // Poll #1
3086 mode = policy->GetNextDelay(error, delay, &delay);
3087 EXPECT_EQ(32, delay.InSeconds());
3088 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
3090 // Poll #2
3091 mode = policy->GetNextDelay(error, delay, &delay);
3092 EXPECT_EQ(120, delay.InSeconds());
3093 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
3095 // Poll #3
3096 mode = policy->GetNextDelay(error, delay, &delay);
3097 EXPECT_EQ(14400, delay.InSeconds());
3098 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
3100 // Poll #4
3101 mode = policy->GetNextDelay(error, delay, &delay);
3102 EXPECT_EQ(14400, delay.InSeconds());
3103 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
3105 // --------------------------------------------------
3106 // Test the poll sequence in response to a success.
3107 // --------------------------------------------------
3108 error = OK;
3110 // Poll #0
3111 mode = policy->GetNextDelay(error, initial_delay, &delay);
3112 EXPECT_EQ(43200, delay.InSeconds());
3113 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
3115 // Poll #1
3116 mode = policy->GetNextDelay(error, delay, &delay);
3117 EXPECT_EQ(43200, delay.InSeconds());
3118 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
3120 // Poll #2
3121 mode = policy->GetNextDelay(error, delay, &delay);
3122 EXPECT_EQ(43200, delay.InSeconds());
3123 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
3126 // This tests the polling of the PAC script. Specifically, it tests that
3127 // polling occurs in response to user activity.
3128 TEST_F(ProxyServiceTest, PACScriptRefetchAfterActivity) {
3129 ImmediateAfterActivityPollPolicy poll_policy;
3130 ProxyService::set_pac_script_poll_policy(&poll_policy);
3132 MockProxyConfigService* config_service =
3133 new MockProxyConfigService("http://foopy/proxy.pac");
3135 MockAsyncProxyResolver resolver;
3136 MockAsyncProxyResolverFactory* factory =
3137 new MockAsyncProxyResolverFactory(true);
3139 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
3141 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
3142 service.SetProxyScriptFetchers(fetcher,
3143 new DoNothingDhcpProxyScriptFetcher());
3145 // Start 1 request.
3147 ProxyInfo info1;
3148 TestCompletionCallback callback1;
3149 int rv =
3150 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
3151 callback1.callback(), NULL, NULL, BoundNetLog());
3152 EXPECT_EQ(ERR_IO_PENDING, rv);
3154 // The first request should have triggered initial download of PAC script.
3155 EXPECT_TRUE(fetcher->has_pending_request());
3156 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
3158 // Nothing has been sent to the factory yet.
3159 EXPECT_TRUE(factory->pending_requests().empty());
3161 // At this point the ProxyService should be waiting for the
3162 // ProxyScriptFetcher to invoke its completion callback, notifying it of
3163 // PAC script download completion.
3164 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
3166 // Now that the PAC script is downloaded, the request will have been sent to
3167 // the proxy resolver.
3168 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
3169 factory->pending_requests()[0]->script_data()->utf16());
3170 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
3172 ASSERT_EQ(1u, resolver.pending_requests().size());
3173 EXPECT_EQ(GURL("http://request1"), resolver.pending_requests()[0]->url());
3175 // Complete the pending request.
3176 resolver.pending_requests()[0]->results()->UseNamedProxy("request1:80");
3177 resolver.pending_requests()[0]->CompleteNow(OK);
3179 // Wait for completion callback, and verify that the request ran as expected.
3180 EXPECT_EQ(OK, callback1.WaitForResult());
3181 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
3183 // At this point we have initialized the proxy service using a PAC script.
3184 // Our PAC poller is set to update ONLY in response to network activity,
3185 // (i.e. another call to ResolveProxy()).
3187 ASSERT_FALSE(fetcher->has_pending_request());
3188 ASSERT_TRUE(factory->pending_requests().empty());
3189 ASSERT_TRUE(resolver.pending_requests().empty());
3191 // Start a second request.
3192 ProxyInfo info2;
3193 TestCompletionCallback callback2;
3194 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
3195 callback2.callback(), NULL, NULL, BoundNetLog());
3196 EXPECT_EQ(ERR_IO_PENDING, rv);
3198 // This request should have sent work to the resolver; complete it.
3199 ASSERT_EQ(1u, resolver.pending_requests().size());
3200 EXPECT_EQ(GURL("http://request2"), resolver.pending_requests()[0]->url());
3201 resolver.pending_requests()[0]->results()->UseNamedProxy("request2:80");
3202 resolver.pending_requests()[0]->CompleteNow(OK);
3204 EXPECT_EQ(OK, callback2.WaitForResult());
3205 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
3207 // In response to getting that resolve request, the poller should have
3208 // started the next poll, and made it as far as to request the download.
3210 EXPECT_TRUE(fetcher->has_pending_request());
3211 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
3213 // This time we will fail the download, to simulate a PAC script change.
3214 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
3216 // Drain the message loop, so ProxyService is notified of the change
3217 // and has a chance to re-configure itself.
3218 base::MessageLoop::current()->RunUntilIdle();
3220 // Start a third request -- this time we expect to get a direct connection
3221 // since the PAC script poller experienced a failure.
3222 ProxyInfo info3;
3223 TestCompletionCallback callback3;
3224 rv = service.ResolveProxy(GURL("http://request3"), LOAD_NORMAL, &info3,
3225 callback3.callback(), NULL, NULL, BoundNetLog());
3226 EXPECT_EQ(OK, rv);
3227 EXPECT_TRUE(info3.is_direct());
3230 // Test that the synchronous resolution fails when a PAC script is active.
3231 TEST_F(ProxyServiceTest, SynchronousWithPAC) {
3232 MockProxyConfigService* config_service =
3233 new MockProxyConfigService("http://foopy/proxy.pac");
3235 MockAsyncProxyResolverFactory* factory =
3236 new MockAsyncProxyResolverFactory(false);
3238 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
3240 GURL url("http://www.google.com/");
3242 ProxyInfo info;
3243 info.UseDirect();
3244 BoundTestNetLog log;
3246 bool synchronous_success = service.TryResolveProxySynchronously(
3247 url, LOAD_NORMAL, &info, NULL, log.bound());
3248 EXPECT_FALSE(synchronous_success);
3250 // |info| should not have been modified.
3251 EXPECT_TRUE(info.is_direct());
3254 // Test that synchronous results are returned correctly if a fixed proxy
3255 // configuration is active.
3256 TEST_F(ProxyServiceTest, SynchronousWithFixedConfiguration) {
3257 ProxyConfig config;
3258 config.proxy_rules().ParseFromString("foopy1:8080");
3259 config.set_auto_detect(false);
3261 MockAsyncProxyResolverFactory* factory =
3262 new MockAsyncProxyResolverFactory(false);
3264 ProxyService service(new MockProxyConfigService(config),
3265 make_scoped_ptr(factory), NULL);
3267 GURL url("http://www.google.com/");
3269 ProxyInfo info;
3270 BoundTestNetLog log;
3272 bool synchronous_success = service.TryResolveProxySynchronously(
3273 url, LOAD_NORMAL, &info, NULL, log.bound());
3274 EXPECT_TRUE(synchronous_success);
3275 EXPECT_FALSE(info.is_direct());
3276 EXPECT_EQ("foopy1", info.proxy_server().host_port_pair().host());
3278 // No request should have been queued.
3279 EXPECT_EQ(0u, factory->pending_requests().size());
3282 } // namespace net