Only grant permissions to new extensions from sync if they have the expected version
[chromium-blink-merge.git] / net / proxy / proxy_service_unittest.cc
blob2b34fbef987d0c0bda71615a55b127d7d23acd5e
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 <cstdarg>
8 #include <vector>
10 #include "base/format_macros.h"
11 #include "base/logging.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "net/base/load_flags.h"
15 #include "net/base/net_errors.h"
16 #include "net/base/network_delegate_impl.h"
17 #include "net/base/test_completion_callback.h"
18 #include "net/log/net_log.h"
19 #include "net/log/test_net_log.h"
20 #include "net/log/test_net_log_entry.h"
21 #include "net/log/test_net_log_util.h"
22 #include "net/proxy/dhcp_proxy_script_fetcher.h"
23 #include "net/proxy/mock_proxy_resolver.h"
24 #include "net/proxy/mock_proxy_script_fetcher.h"
25 #include "net/proxy/proxy_config_service.h"
26 #include "net/proxy/proxy_resolver.h"
27 #include "net/proxy/proxy_script_fetcher.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29 #include "url/gurl.h"
31 using base::ASCIIToUTF16;
33 // TODO(eroman): Write a test which exercises
34 // ProxyService::SuspendAllPendingRequests().
35 namespace net {
36 namespace {
38 // This polling policy will decide to poll every 1 ms.
39 class ImmediatePollPolicy : public ProxyService::PacPollPolicy {
40 public:
41 ImmediatePollPolicy() {}
43 Mode GetNextDelay(int error,
44 base::TimeDelta current_delay,
45 base::TimeDelta* next_delay) const override {
46 *next_delay = base::TimeDelta::FromMilliseconds(1);
47 return MODE_USE_TIMER;
50 private:
51 DISALLOW_COPY_AND_ASSIGN(ImmediatePollPolicy);
54 // This polling policy chooses a fantastically large delay. In other words, it
55 // will never trigger a poll
56 class NeverPollPolicy : public ProxyService::PacPollPolicy {
57 public:
58 NeverPollPolicy() {}
60 Mode GetNextDelay(int error,
61 base::TimeDelta current_delay,
62 base::TimeDelta* next_delay) const override {
63 *next_delay = base::TimeDelta::FromDays(60);
64 return MODE_USE_TIMER;
67 private:
68 DISALLOW_COPY_AND_ASSIGN(NeverPollPolicy);
71 // This polling policy starts a poll immediately after network activity.
72 class ImmediateAfterActivityPollPolicy : public ProxyService::PacPollPolicy {
73 public:
74 ImmediateAfterActivityPollPolicy() {}
76 Mode GetNextDelay(int error,
77 base::TimeDelta current_delay,
78 base::TimeDelta* next_delay) const override {
79 *next_delay = base::TimeDelta();
80 return MODE_START_AFTER_ACTIVITY;
83 private:
84 DISALLOW_COPY_AND_ASSIGN(ImmediateAfterActivityPollPolicy);
87 // This test fixture is used to partially disable the background polling done by
88 // the ProxyService (which it uses to detect whenever its PAC script contents or
89 // WPAD results have changed).
91 // We disable the feature by setting the poll interval to something really
92 // large, so it will never actually be reached even on the slowest bots that run
93 // these tests.
95 // We disable the polling in order to avoid any timing dependencies in the
96 // tests. If the bot were to run the tests very slowly and we hadn't disabled
97 // polling, then it might start a background re-try in the middle of our test
98 // and confuse our expectations leading to flaky failures.
100 // The tests which verify the polling code re-enable the polling behavior but
101 // are careful to avoid timing problems.
102 class ProxyServiceTest : public testing::Test {
103 protected:
104 void SetUp() override {
105 testing::Test::SetUp();
106 previous_policy_ =
107 ProxyService::set_pac_script_poll_policy(&never_poll_policy_);
110 void TearDown() override {
111 // Restore the original policy.
112 ProxyService::set_pac_script_poll_policy(previous_policy_);
113 testing::Test::TearDown();
116 private:
117 NeverPollPolicy never_poll_policy_;
118 const ProxyService::PacPollPolicy* previous_policy_;
121 const char kValidPacScript1[] = "pac-script-v1-FindProxyForURL";
122 const char kValidPacScript2[] = "pac-script-v2-FindProxyForURL";
124 class MockProxyConfigService: public ProxyConfigService {
125 public:
126 explicit MockProxyConfigService(const ProxyConfig& config)
127 : availability_(CONFIG_VALID),
128 config_(config) {
131 explicit MockProxyConfigService(const std::string& pac_url)
132 : availability_(CONFIG_VALID),
133 config_(ProxyConfig::CreateFromCustomPacURL(GURL(pac_url))) {
136 void AddObserver(Observer* observer) override {
137 observers_.AddObserver(observer);
140 void RemoveObserver(Observer* observer) override {
141 observers_.RemoveObserver(observer);
144 ConfigAvailability GetLatestProxyConfig(ProxyConfig* results) override {
145 if (availability_ == CONFIG_VALID)
146 *results = config_;
147 return availability_;
150 void SetConfig(const ProxyConfig& config) {
151 availability_ = CONFIG_VALID;
152 config_ = config;
153 FOR_EACH_OBSERVER(Observer, observers_,
154 OnProxyConfigChanged(config_, availability_));
157 private:
158 ConfigAvailability availability_;
159 ProxyConfig config_;
160 base::ObserverList<Observer, true> observers_;
163 // A test network delegate that exercises the OnResolveProxy callback.
164 class TestResolveProxyNetworkDelegate : public NetworkDelegateImpl {
165 public:
166 TestResolveProxyNetworkDelegate()
167 : on_resolve_proxy_called_(false),
168 add_proxy_(false),
169 remove_proxy_(false),
170 proxy_service_(NULL) {
173 void OnResolveProxy(const GURL& url,
174 int load_flags,
175 const ProxyService& proxy_service,
176 ProxyInfo* result) override {
177 on_resolve_proxy_called_ = true;
178 proxy_service_ = &proxy_service;
179 DCHECK(!add_proxy_ || !remove_proxy_);
180 if (add_proxy_) {
181 result->UseNamedProxy("delegate_proxy.com");
182 } else if (remove_proxy_) {
183 result->UseDirect();
187 bool on_resolve_proxy_called() const {
188 return on_resolve_proxy_called_;
191 void set_add_proxy(bool add_proxy) {
192 add_proxy_ = add_proxy;
195 void set_remove_proxy(bool remove_proxy) {
196 remove_proxy_ = remove_proxy;
199 const ProxyService* proxy_service() const {
200 return proxy_service_;
203 private:
204 bool on_resolve_proxy_called_;
205 bool add_proxy_;
206 bool remove_proxy_;
207 const ProxyService* proxy_service_;
210 // A test network delegate that exercises the OnProxyFallback callback.
211 class TestProxyFallbackNetworkDelegate : public NetworkDelegateImpl {
212 public:
213 TestProxyFallbackNetworkDelegate()
214 : on_proxy_fallback_called_(false),
215 proxy_fallback_net_error_(OK) {
218 void OnProxyFallback(const ProxyServer& proxy_server,
219 int net_error) override {
220 proxy_server_ = proxy_server;
221 proxy_fallback_net_error_ = net_error;
222 on_proxy_fallback_called_ = true;
225 bool on_proxy_fallback_called() const {
226 return on_proxy_fallback_called_;
229 const ProxyServer& proxy_server() const {
230 return proxy_server_;
233 int proxy_fallback_net_error() const {
234 return proxy_fallback_net_error_;
237 private:
238 bool on_proxy_fallback_called_;
239 ProxyServer proxy_server_;
240 int proxy_fallback_net_error_;
243 using RequestMap =
244 std::map<GURL, scoped_refptr<MockAsyncProxyResolver::Request>>;
246 // Given a list of requests |list| from a MockAsyncProxyResolver and a list of
247 // target URLs |_urls|, asserts that the set of URLs of the requests appearing
248 // in |list| is exactly the set of URLs in |_urls|, and produces a RequestMap in
249 // |*map| containing the requests corresponding to those target |_urls|.
251 // Note that this function must return void to allow use of gtest's ASSERT_*
252 // macros inside it.
253 RequestMap GetRequestsForURLs(
254 const MockAsyncProxyResolver::RequestsList& requests,
255 const std::vector<GURL>& urls) {
256 RequestMap map;
258 for (const auto& it : requests)
259 map[it->url()] = it;
261 if (urls.size() != map.size()) {
262 ADD_FAILURE() << "map size (" << map.size() << ") != urls size ("
263 << urls.size() << ")";
264 return map;
266 for (const auto& it : urls) {
267 if (map.count(it) != 1U) {
268 ADD_FAILURE() << "url not in map: " << it.spec();
269 break;
272 return map;
275 // Given a MockAsyncProxyResolver |resolver| and some GURLs, validates that the
276 // set of pending request URLs for |resolver| is exactly the supplied list of
277 // URLs and returns a map from URLs to the corresponding pending requests.
278 RequestMap GetPendingRequestsForURLs(const MockAsyncProxyResolver& resolver,
279 const GURL& url1 = GURL(),
280 const GURL& url2 = GURL(),
281 const GURL& url3 = GURL()) {
282 std::vector<GURL> urls;
283 if (!url1.is_empty())
284 urls.push_back(url1);
285 if (!url2.is_empty())
286 urls.push_back(url2);
287 if (!url3.is_empty())
288 urls.push_back(url3);
289 return GetRequestsForURLs(resolver.pending_requests(), urls);
292 // Given a MockAsyncProxyResolver |resolver| and some GURLs, validates that the
293 // set of cancelled request URLs for |resolver| is exactly the supplied list of
294 // URLs and returns a map from URLs to the corresponding cancelled requests.
295 RequestMap GetCancelledRequestsForURLs(const MockAsyncProxyResolver& resolver,
296 const GURL& url1 = GURL(),
297 const GURL& url2 = GURL(),
298 const GURL& url3 = GURL()) {
299 std::vector<GURL> urls;
300 if (!url1.is_empty())
301 urls.push_back(url1);
302 if (!url2.is_empty())
303 urls.push_back(url2);
304 if (!url3.is_empty())
305 urls.push_back(url3);
306 return GetRequestsForURLs(resolver.cancelled_requests(), urls);
309 } // namespace
311 TEST_F(ProxyServiceTest, Direct) {
312 MockAsyncProxyResolverFactory* factory =
313 new MockAsyncProxyResolverFactory(false);
314 ProxyService service(new MockProxyConfigService(ProxyConfig::CreateDirect()),
315 make_scoped_ptr(factory), NULL);
317 GURL url("http://www.google.com/");
319 ProxyInfo info;
320 TestCompletionCallback callback;
321 BoundTestNetLog log;
322 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
323 NULL, NULL, log.bound());
324 EXPECT_EQ(OK, rv);
325 EXPECT_TRUE(factory->pending_requests().empty());
327 EXPECT_TRUE(info.is_direct());
328 EXPECT_TRUE(info.proxy_resolve_start_time().is_null());
329 EXPECT_TRUE(info.proxy_resolve_end_time().is_null());
331 // Check the NetLog was filled correctly.
332 TestNetLogEntry::List entries;
333 log.GetEntries(&entries);
335 EXPECT_EQ(3u, entries.size());
336 EXPECT_TRUE(LogContainsBeginEvent(
337 entries, 0, NetLog::TYPE_PROXY_SERVICE));
338 EXPECT_TRUE(LogContainsEvent(
339 entries, 1, NetLog::TYPE_PROXY_SERVICE_RESOLVED_PROXY_LIST,
340 NetLog::PHASE_NONE));
341 EXPECT_TRUE(LogContainsEndEvent(
342 entries, 2, NetLog::TYPE_PROXY_SERVICE));
345 TEST_F(ProxyServiceTest, OnResolveProxyCallbackAddProxy) {
346 ProxyConfig config;
347 config.proxy_rules().ParseFromString("foopy1:8080");
348 config.set_auto_detect(false);
349 config.proxy_rules().bypass_rules.ParseFromString("*.org");
351 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
353 GURL url("http://www.google.com/");
354 GURL bypass_url("http://internet.org");
356 ProxyInfo info;
357 TestCompletionCallback callback;
358 BoundTestNetLog log;
360 // First, warm up the ProxyService.
361 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
362 NULL, NULL, log.bound());
363 EXPECT_EQ(OK, rv);
365 // Verify that network delegate is invoked.
366 TestResolveProxyNetworkDelegate delegate;
367 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), NULL,
368 &delegate, log.bound());
369 EXPECT_TRUE(delegate.on_resolve_proxy_called());
370 EXPECT_EQ(&service, delegate.proxy_service());
372 // Verify that the NetworkDelegate's behavior is stateless across
373 // invocations of ResolveProxy. Start by having the callback add a proxy
374 // and checking that subsequent requests are not affected.
375 delegate.set_add_proxy(true);
377 // Callback should interpose:
378 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), NULL,
379 &delegate, log.bound());
380 EXPECT_FALSE(info.is_direct());
381 EXPECT_EQ(info.proxy_server().host_port_pair().host(), "delegate_proxy.com");
382 delegate.set_add_proxy(false);
384 // Check non-bypassed URL:
385 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), NULL,
386 &delegate, log.bound());
387 EXPECT_FALSE(info.is_direct());
388 EXPECT_EQ(info.proxy_server().host_port_pair().host(), "foopy1");
390 // Check bypassed URL:
391 rv = service.ResolveProxy(bypass_url, LOAD_NORMAL, &info, callback.callback(),
392 NULL, &delegate, log.bound());
393 EXPECT_TRUE(info.is_direct());
396 TEST_F(ProxyServiceTest, OnResolveProxyCallbackRemoveProxy) {
397 // Same as OnResolveProxyCallbackAddProxy, but verify that the
398 // NetworkDelegate's behavior is stateless across invocations after it
399 // *removes* a proxy.
400 ProxyConfig config;
401 config.proxy_rules().ParseFromString("foopy1:8080");
402 config.set_auto_detect(false);
403 config.proxy_rules().bypass_rules.ParseFromString("*.org");
405 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
407 GURL url("http://www.google.com/");
408 GURL bypass_url("http://internet.org");
410 ProxyInfo info;
411 TestCompletionCallback callback;
412 BoundTestNetLog log;
414 // First, warm up the ProxyService.
415 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
416 NULL, NULL, log.bound());
417 EXPECT_EQ(OK, rv);
419 TestResolveProxyNetworkDelegate delegate;
420 delegate.set_remove_proxy(true);
422 // Callback should interpose:
423 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), NULL,
424 &delegate, log.bound());
425 EXPECT_TRUE(info.is_direct());
426 delegate.set_remove_proxy(false);
428 // Check non-bypassed URL:
429 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), NULL,
430 &delegate, log.bound());
431 EXPECT_FALSE(info.is_direct());
432 EXPECT_EQ(info.proxy_server().host_port_pair().host(), "foopy1");
434 // Check bypassed URL:
435 rv = service.ResolveProxy(bypass_url, LOAD_NORMAL, &info, callback.callback(),
436 NULL, &delegate, log.bound());
437 EXPECT_TRUE(info.is_direct());
440 TEST_F(ProxyServiceTest, PAC) {
441 MockProxyConfigService* config_service =
442 new MockProxyConfigService("http://foopy/proxy.pac");
444 MockAsyncProxyResolver resolver;
445 MockAsyncProxyResolverFactory* factory =
446 new MockAsyncProxyResolverFactory(false);
448 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
450 GURL url("http://www.google.com/");
452 ProxyInfo info;
453 TestCompletionCallback callback;
454 ProxyService::PacRequest* request;
455 BoundTestNetLog log;
457 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
458 &request, NULL, log.bound());
459 EXPECT_EQ(ERR_IO_PENDING, rv);
461 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request));
463 ASSERT_EQ(1u, factory->pending_requests().size());
464 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
465 factory->pending_requests()[0]->script_data()->url());
466 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
468 ASSERT_EQ(1u, resolver.pending_requests().size());
469 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
471 // Set the result in proxy resolver.
472 resolver.pending_requests()[0]->results()->UseNamedProxy("foopy");
473 resolver.pending_requests()[0]->CompleteNow(OK);
475 EXPECT_EQ(OK, callback.WaitForResult());
476 EXPECT_FALSE(info.is_direct());
477 EXPECT_EQ("foopy:80", info.proxy_server().ToURI());
478 EXPECT_TRUE(info.did_use_pac_script());
480 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
481 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
482 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
484 // Check the NetLog was filled correctly.
485 TestNetLogEntry::List entries;
486 log.GetEntries(&entries);
488 EXPECT_EQ(5u, entries.size());
489 EXPECT_TRUE(LogContainsBeginEvent(
490 entries, 0, NetLog::TYPE_PROXY_SERVICE));
491 EXPECT_TRUE(LogContainsBeginEvent(
492 entries, 1, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
493 EXPECT_TRUE(LogContainsEndEvent(
494 entries, 2, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
495 EXPECT_TRUE(LogContainsEndEvent(
496 entries, 4, NetLog::TYPE_PROXY_SERVICE));
499 // Test that the proxy resolver does not see the URL's username/password
500 // or its reference section.
501 TEST_F(ProxyServiceTest, PAC_NoIdentityOrHash) {
502 MockProxyConfigService* config_service =
503 new MockProxyConfigService("http://foopy/proxy.pac");
505 MockAsyncProxyResolver resolver;
506 MockAsyncProxyResolverFactory* factory =
507 new MockAsyncProxyResolverFactory(false);
509 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
511 GURL url("http://username:password@www.google.com/?ref#hash#hash");
513 ProxyInfo info;
514 TestCompletionCallback callback;
515 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
516 NULL, NULL, BoundNetLog());
517 EXPECT_EQ(ERR_IO_PENDING, rv);
519 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
520 factory->pending_requests()[0]->script_data()->url());
521 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
523 ASSERT_EQ(1u, resolver.pending_requests().size());
524 // The URL should have been simplified, stripping the username/password/hash.
525 EXPECT_EQ(GURL("http://www.google.com/?ref"),
526 resolver.pending_requests()[0]->url());
528 // We end here without ever completing the request -- destruction of
529 // ProxyService will cancel the outstanding request.
532 TEST_F(ProxyServiceTest, PAC_FailoverWithoutDirect) {
533 MockProxyConfigService* config_service =
534 new MockProxyConfigService("http://foopy/proxy.pac");
535 MockAsyncProxyResolver resolver;
536 MockAsyncProxyResolverFactory* factory =
537 new MockAsyncProxyResolverFactory(false);
539 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
541 GURL url("http://www.google.com/");
543 ProxyInfo info;
544 TestCompletionCallback callback1;
545 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
546 NULL, NULL, BoundNetLog());
547 EXPECT_EQ(ERR_IO_PENDING, rv);
549 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
550 factory->pending_requests()[0]->script_data()->url());
551 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
553 ASSERT_EQ(1u, resolver.pending_requests().size());
554 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
556 // Set the result in proxy resolver.
557 resolver.pending_requests()[0]->results()->UseNamedProxy("foopy:8080");
558 resolver.pending_requests()[0]->CompleteNow(OK);
560 EXPECT_EQ(OK, callback1.WaitForResult());
561 EXPECT_FALSE(info.is_direct());
562 EXPECT_EQ("foopy:8080", info.proxy_server().ToURI());
563 EXPECT_TRUE(info.did_use_pac_script());
565 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
566 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
567 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
569 // Now, imagine that connecting to foopy:8080 fails: there is nothing
570 // left to fallback to, since our proxy list was NOT terminated by
571 // DIRECT.
572 NetworkDelegateImpl network_delegate;
573 TestCompletionCallback callback2;
574 ProxyServer expected_proxy_server = info.proxy_server();
575 rv = service.ReconsiderProxyAfterError(
576 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
577 callback2.callback(), NULL, &network_delegate, BoundNetLog());
578 // ReconsiderProxyAfterError returns error indicating nothing left.
579 EXPECT_EQ(ERR_FAILED, rv);
580 EXPECT_TRUE(info.is_empty());
583 // Test that if the execution of the PAC script fails (i.e. javascript runtime
584 // error), and the PAC settings are non-mandatory, that we fall-back to direct.
585 TEST_F(ProxyServiceTest, PAC_RuntimeError) {
586 MockProxyConfigService* config_service =
587 new MockProxyConfigService("http://foopy/proxy.pac");
588 MockAsyncProxyResolver resolver;
589 MockAsyncProxyResolverFactory* factory =
590 new MockAsyncProxyResolverFactory(false);
592 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
594 GURL url("http://this-causes-js-error/");
596 ProxyInfo info;
597 TestCompletionCallback callback1;
598 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
599 NULL, NULL, BoundNetLog());
600 EXPECT_EQ(ERR_IO_PENDING, rv);
602 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
603 factory->pending_requests()[0]->script_data()->url());
604 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
606 ASSERT_EQ(1u, resolver.pending_requests().size());
607 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
609 // Simulate a failure in the PAC executor.
610 resolver.pending_requests()[0]->CompleteNow(ERR_PAC_SCRIPT_FAILED);
612 EXPECT_EQ(OK, callback1.WaitForResult());
614 // Since the PAC script was non-mandatory, we should have fallen-back to
615 // DIRECT.
616 EXPECT_TRUE(info.is_direct());
617 EXPECT_TRUE(info.did_use_pac_script());
618 EXPECT_EQ(1, info.config_id());
620 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
621 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
622 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
625 // The proxy list could potentially contain the DIRECT fallback choice
626 // in a location other than the very end of the list, and could even
627 // specify it multiple times.
629 // This is not a typical usage, but we will obey it.
630 // (If we wanted to disallow this type of input, the right place to
631 // enforce it would be in parsing the PAC result string).
633 // This test will use the PAC result string:
635 // "DIRECT ; PROXY foobar:10 ; DIRECT ; PROXY foobar:20"
637 // For which we expect it to try DIRECT, then foobar:10, then DIRECT again,
638 // then foobar:20, and then give up and error.
640 // The important check of this test is to make sure that DIRECT is not somehow
641 // cached as being a bad proxy.
642 TEST_F(ProxyServiceTest, PAC_FailoverAfterDirect) {
643 MockProxyConfigService* config_service =
644 new MockProxyConfigService("http://foopy/proxy.pac");
645 MockAsyncProxyResolver resolver;
646 MockAsyncProxyResolverFactory* factory =
647 new MockAsyncProxyResolverFactory(false);
649 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
651 GURL url("http://www.google.com/");
653 ProxyInfo info;
654 TestCompletionCallback callback1;
655 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
656 NULL, NULL, BoundNetLog());
657 EXPECT_EQ(ERR_IO_PENDING, rv);
659 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
660 factory->pending_requests()[0]->script_data()->url());
661 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
663 ASSERT_EQ(1u, resolver.pending_requests().size());
664 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
666 // Set the result in proxy resolver.
667 resolver.pending_requests()[0]->results()->UsePacString(
668 "DIRECT ; PROXY foobar:10 ; DIRECT ; PROXY foobar:20");
669 resolver.pending_requests()[0]->CompleteNow(OK);
671 EXPECT_EQ(OK, callback1.WaitForResult());
672 EXPECT_TRUE(info.is_direct());
674 // Fallback 1.
675 TestCompletionCallback callback2;
676 rv = service.ReconsiderProxyAfterError(
677 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
678 callback2.callback(), NULL, NULL, BoundNetLog());
679 EXPECT_EQ(OK, rv);
680 EXPECT_FALSE(info.is_direct());
681 EXPECT_EQ("foobar:10", info.proxy_server().ToURI());
683 // Fallback 2.
684 NetworkDelegateImpl network_delegate;
685 ProxyServer expected_proxy_server3 = info.proxy_server();
686 TestCompletionCallback callback3;
687 rv = service.ReconsiderProxyAfterError(
688 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
689 callback3.callback(), NULL, &network_delegate, BoundNetLog());
690 EXPECT_EQ(OK, rv);
691 EXPECT_TRUE(info.is_direct());
693 // Fallback 3.
694 ProxyServer expected_proxy_server4 = info.proxy_server();
695 TestCompletionCallback callback4;
696 rv = service.ReconsiderProxyAfterError(
697 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
698 callback4.callback(), NULL, &network_delegate, BoundNetLog());
699 EXPECT_EQ(OK, rv);
700 EXPECT_FALSE(info.is_direct());
701 EXPECT_EQ("foobar:20", info.proxy_server().ToURI());
703 // Fallback 4 -- Nothing to fall back to!
704 ProxyServer expected_proxy_server5 = info.proxy_server();
705 TestCompletionCallback callback5;
706 rv = service.ReconsiderProxyAfterError(
707 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
708 callback5.callback(), NULL, &network_delegate, BoundNetLog());
709 EXPECT_EQ(ERR_FAILED, rv);
710 EXPECT_TRUE(info.is_empty());
713 TEST_F(ProxyServiceTest, PAC_ConfigSourcePropagates) {
714 // Test whether the ProxyConfigSource set by the ProxyConfigService is applied
715 // to ProxyInfo after the proxy is resolved via a PAC script.
716 ProxyConfig config =
717 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"));
718 config.set_source(PROXY_CONFIG_SOURCE_TEST);
720 MockProxyConfigService* config_service = new MockProxyConfigService(config);
721 MockAsyncProxyResolver resolver;
722 MockAsyncProxyResolverFactory* factory =
723 new MockAsyncProxyResolverFactory(false);
724 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
726 // Resolve something.
727 GURL url("http://www.google.com/");
728 ProxyInfo info;
729 TestCompletionCallback callback;
730 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
731 NULL, NULL, BoundNetLog());
732 ASSERT_EQ(ERR_IO_PENDING, rv);
733 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
734 ASSERT_EQ(1u, resolver.pending_requests().size());
736 // Set the result in proxy resolver.
737 resolver.pending_requests()[0]->results()->UseNamedProxy("foopy");
738 resolver.pending_requests()[0]->CompleteNow(OK);
740 EXPECT_EQ(OK, callback.WaitForResult());
741 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
742 EXPECT_TRUE(info.did_use_pac_script());
744 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
745 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
746 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
749 TEST_F(ProxyServiceTest, ProxyResolverFails) {
750 // Test what happens when the ProxyResolver fails. The download and setting
751 // of the PAC script have already succeeded, so this corresponds with a
752 // javascript runtime error while calling FindProxyForURL().
754 MockProxyConfigService* config_service =
755 new MockProxyConfigService("http://foopy/proxy.pac");
757 MockAsyncProxyResolver resolver;
758 MockAsyncProxyResolverFactory* factory =
759 new MockAsyncProxyResolverFactory(false);
761 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
763 // Start first resolve request.
764 GURL url("http://www.google.com/");
765 ProxyInfo info;
766 TestCompletionCallback callback1;
767 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
768 NULL, NULL, BoundNetLog());
769 EXPECT_EQ(ERR_IO_PENDING, rv);
771 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
772 factory->pending_requests()[0]->script_data()->url());
773 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
775 ASSERT_EQ(1u, resolver.pending_requests().size());
776 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
778 // Fail the first resolve request in MockAsyncProxyResolver.
779 resolver.pending_requests()[0]->CompleteNow(ERR_FAILED);
781 // Although the proxy resolver failed the request, ProxyService implicitly
782 // falls-back to DIRECT.
783 EXPECT_EQ(OK, callback1.WaitForResult());
784 EXPECT_TRUE(info.is_direct());
786 // Failed PAC executions still have proxy resolution times.
787 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
788 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
789 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
791 // The second resolve request will try to run through the proxy resolver,
792 // regardless of whether the first request failed in it.
793 TestCompletionCallback callback2;
794 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback2.callback(), NULL,
795 NULL, BoundNetLog());
796 EXPECT_EQ(ERR_IO_PENDING, rv);
798 ASSERT_EQ(1u, resolver.pending_requests().size());
799 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
801 // This time we will have the resolver succeed (perhaps the PAC script has
802 // a dependency on the current time).
803 resolver.pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080");
804 resolver.pending_requests()[0]->CompleteNow(OK);
806 EXPECT_EQ(OK, callback2.WaitForResult());
807 EXPECT_FALSE(info.is_direct());
808 EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI());
811 TEST_F(ProxyServiceTest, ProxyResolverTerminatedDuringRequest) {
812 // Test what happens when the ProxyResolver fails with a fatal error while
813 // a GetProxyForURL() call is in progress.
815 MockProxyConfigService* config_service =
816 new MockProxyConfigService("http://foopy/proxy.pac");
818 MockAsyncProxyResolver resolver;
819 MockAsyncProxyResolverFactory* factory =
820 new MockAsyncProxyResolverFactory(false);
822 ProxyService service(config_service, make_scoped_ptr(factory), nullptr);
824 // Start first resolve request.
825 GURL url("http://www.google.com/");
826 ProxyInfo info;
827 TestCompletionCallback callback1;
828 int rv =
829 service.ResolveProxy(url, net::LOAD_NORMAL, &info, callback1.callback(),
830 nullptr, nullptr, BoundNetLog());
831 EXPECT_EQ(ERR_IO_PENDING, rv);
833 ASSERT_EQ(1u, factory->pending_requests().size());
834 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
835 factory->pending_requests()[0]->script_data()->url());
836 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
838 ASSERT_EQ(1u, resolver.pending_requests().size());
839 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
841 // Fail the first resolve request in MockAsyncProxyResolver.
842 resolver.pending_requests()[0]->CompleteNow(ERR_PAC_SCRIPT_TERMINATED);
844 // Although the proxy resolver failed the request, ProxyService implicitly
845 // falls-back to DIRECT.
846 EXPECT_EQ(OK, callback1.WaitForResult());
847 EXPECT_TRUE(info.is_direct());
849 // Failed PAC executions still have proxy resolution times.
850 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
851 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
852 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
854 // With no other requests, the ProxyService waits for a new request before
855 // initializing a new ProxyResolver.
856 EXPECT_TRUE(factory->pending_requests().empty());
858 TestCompletionCallback callback2;
859 rv = service.ResolveProxy(url, net::LOAD_NORMAL, &info, callback2.callback(),
860 nullptr, nullptr, BoundNetLog());
861 EXPECT_EQ(ERR_IO_PENDING, rv);
863 ASSERT_EQ(1u, factory->pending_requests().size());
864 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
865 factory->pending_requests()[0]->script_data()->url());
866 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
868 ASSERT_EQ(1u, resolver.pending_requests().size());
869 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
871 // This time we will have the resolver succeed.
872 resolver.pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080");
873 resolver.pending_requests()[0]->CompleteNow(OK);
875 EXPECT_EQ(OK, callback2.WaitForResult());
876 EXPECT_FALSE(info.is_direct());
877 EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI());
880 TEST_F(ProxyServiceTest,
881 ProxyResolverTerminatedDuringRequestWithConcurrentRequest) {
882 // Test what happens when the ProxyResolver fails with a fatal error while
883 // a GetProxyForURL() call is in progress.
885 MockProxyConfigService* config_service =
886 new MockProxyConfigService("http://foopy/proxy.pac");
888 MockAsyncProxyResolver resolver;
889 MockAsyncProxyResolverFactory* factory =
890 new MockAsyncProxyResolverFactory(false);
892 ProxyService service(config_service, make_scoped_ptr(factory), nullptr);
894 // Start two resolve requests.
895 GURL url1("http://www.google.com/");
896 GURL url2("https://www.google.com/");
897 ProxyInfo info;
898 TestCompletionCallback callback1;
899 int rv =
900 service.ResolveProxy(url1, net::LOAD_NORMAL, &info, callback1.callback(),
901 nullptr, nullptr, BoundNetLog());
902 EXPECT_EQ(ERR_IO_PENDING, rv);
903 TestCompletionCallback callback2;
904 rv = service.ResolveProxy(url2, net::LOAD_NORMAL, &info, callback2.callback(),
905 nullptr, nullptr, BoundNetLog());
906 EXPECT_EQ(ERR_IO_PENDING, rv);
908 ASSERT_EQ(1u, factory->pending_requests().size());
909 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
910 factory->pending_requests()[0]->script_data()->url());
911 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
913 RequestMap requests = GetPendingRequestsForURLs(resolver, url1, url2);
915 // Fail the first resolve request in MockAsyncProxyResolver.
916 requests[url1]->CompleteNow(ERR_PAC_SCRIPT_TERMINATED);
918 // Although the proxy resolver failed the request, ProxyService implicitly
919 // falls-back to DIRECT.
920 EXPECT_EQ(OK, callback1.WaitForResult());
921 EXPECT_TRUE(info.is_direct());
923 // Failed PAC executions still have proxy resolution times.
924 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
925 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
926 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
928 // The second request is cancelled when the proxy resolver terminates.
929 requests = GetCancelledRequestsForURLs(resolver, url2);
931 // Since a second request was in progress, the ProxyService starts
932 // initializating a new ProxyResolver.
933 ASSERT_EQ(1u, factory->pending_requests().size());
934 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
935 factory->pending_requests()[0]->script_data()->url());
936 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
938 requests = GetPendingRequestsForURLs(resolver, url2);
940 // This request succeeds.
941 requests[url2]->results()->UseNamedProxy("foopy_valid:8080");
942 requests[url2]->CompleteNow(OK);
944 EXPECT_EQ(OK, callback2.WaitForResult());
945 EXPECT_FALSE(info.is_direct());
946 EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI());
949 TEST_F(ProxyServiceTest, ProxyScriptFetcherFailsDownloadingMandatoryPac) {
950 // Test what happens when the ProxyScriptResolver fails to download a
951 // mandatory PAC script.
953 ProxyConfig config(
954 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
955 config.set_pac_mandatory(true);
957 MockProxyConfigService* config_service = new MockProxyConfigService(config);
959 MockAsyncProxyResolverFactory* factory =
960 new MockAsyncProxyResolverFactory(false);
962 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
964 // Start first resolve request.
965 GURL url("http://www.google.com/");
966 ProxyInfo info;
967 TestCompletionCallback callback1;
968 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
969 NULL, NULL, BoundNetLog());
970 EXPECT_EQ(ERR_IO_PENDING, rv);
972 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
973 factory->pending_requests()[0]->script_data()->url());
974 factory->pending_requests()[0]->CompleteNow(ERR_FAILED, nullptr);
976 ASSERT_EQ(0u, factory->pending_requests().size());
977 // As the proxy resolver factory failed the request and is configured for a
978 // mandatory PAC script, ProxyService must not implicitly fall-back to DIRECT.
979 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
980 callback1.WaitForResult());
981 EXPECT_FALSE(info.is_direct());
983 // As the proxy resolver factory failed the request and is configured for a
984 // mandatory PAC script, ProxyService must not implicitly fall-back to DIRECT.
985 TestCompletionCallback callback2;
986 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback2.callback(), NULL,
987 NULL, BoundNetLog());
988 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED, rv);
989 EXPECT_FALSE(info.is_direct());
992 TEST_F(ProxyServiceTest, ProxyResolverFailsParsingJavaScriptMandatoryPac) {
993 // Test what happens when the ProxyResolver fails that is configured to use a
994 // mandatory PAC script. The download of the PAC script has already
995 // succeeded but the PAC script contains no valid javascript.
997 ProxyConfig config(
998 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
999 config.set_pac_mandatory(true);
1001 MockProxyConfigService* config_service = new MockProxyConfigService(config);
1003 MockAsyncProxyResolverFactory* factory =
1004 new MockAsyncProxyResolverFactory(true);
1006 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
1008 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1009 service.SetProxyScriptFetchers(
1010 fetcher, make_scoped_ptr(new DoNothingDhcpProxyScriptFetcher()));
1012 // Start resolve request.
1013 GURL url("http://www.google.com/");
1014 ProxyInfo info;
1015 TestCompletionCallback callback;
1016 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
1017 NULL, NULL, BoundNetLog());
1018 EXPECT_EQ(ERR_IO_PENDING, rv);
1020 // Check that nothing has been sent to the proxy resolver factory yet.
1021 ASSERT_EQ(0u, factory->pending_requests().size());
1023 // Downloading the PAC script succeeds.
1024 EXPECT_TRUE(fetcher->has_pending_request());
1025 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1026 fetcher->NotifyFetchCompletion(OK, "invalid-script-contents");
1028 EXPECT_FALSE(fetcher->has_pending_request());
1029 ASSERT_EQ(0u, factory->pending_requests().size());
1031 // Since ProxyScriptDecider failed to identify a valid PAC and PAC was
1032 // mandatory for this configuration, the ProxyService must not implicitly
1033 // fall-back to DIRECT.
1034 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
1035 callback.WaitForResult());
1036 EXPECT_FALSE(info.is_direct());
1039 TEST_F(ProxyServiceTest, ProxyResolverFailsInJavaScriptMandatoryPac) {
1040 // Test what happens when the ProxyResolver fails that is configured to use a
1041 // mandatory PAC script. The download and setting of the PAC script have
1042 // already succeeded, so this corresponds with a javascript runtime error
1043 // while calling FindProxyForURL().
1045 ProxyConfig config(
1046 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
1047 config.set_pac_mandatory(true);
1049 MockProxyConfigService* config_service = new MockProxyConfigService(config);
1051 MockAsyncProxyResolver resolver;
1052 MockAsyncProxyResolverFactory* factory =
1053 new MockAsyncProxyResolverFactory(false);
1055 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
1057 // Start first resolve request.
1058 GURL url("http://www.google.com/");
1059 ProxyInfo info;
1060 TestCompletionCallback callback1;
1061 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
1062 NULL, NULL, BoundNetLog());
1063 EXPECT_EQ(ERR_IO_PENDING, rv);
1065 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1066 factory->pending_requests()[0]->script_data()->url());
1067 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1069 ASSERT_EQ(1u, resolver.pending_requests().size());
1070 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1072 // Fail the first resolve request in MockAsyncProxyResolver.
1073 resolver.pending_requests()[0]->CompleteNow(ERR_FAILED);
1075 // As the proxy resolver failed the request and is configured for a mandatory
1076 // PAC script, ProxyService must not implicitly fall-back to DIRECT.
1077 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
1078 callback1.WaitForResult());
1079 EXPECT_FALSE(info.is_direct());
1081 // The second resolve request will try to run through the proxy resolver,
1082 // regardless of whether the first request failed in it.
1083 TestCompletionCallback callback2;
1084 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback2.callback(), NULL,
1085 NULL, BoundNetLog());
1086 EXPECT_EQ(ERR_IO_PENDING, rv);
1088 ASSERT_EQ(1u, resolver.pending_requests().size());
1089 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1091 // This time we will have the resolver succeed (perhaps the PAC script has
1092 // a dependency on the current time).
1093 resolver.pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080");
1094 resolver.pending_requests()[0]->CompleteNow(OK);
1096 EXPECT_EQ(OK, callback2.WaitForResult());
1097 EXPECT_FALSE(info.is_direct());
1098 EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI());
1101 TEST_F(ProxyServiceTest, ProxyFallback) {
1102 // Test what happens when we specify multiple proxy servers and some of them
1103 // are bad.
1105 MockProxyConfigService* config_service =
1106 new MockProxyConfigService("http://foopy/proxy.pac");
1108 MockAsyncProxyResolver resolver;
1109 MockAsyncProxyResolverFactory* factory =
1110 new MockAsyncProxyResolverFactory(false);
1112 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
1114 GURL url("http://www.google.com/");
1116 // Get the proxy information.
1117 ProxyInfo info;
1118 TestCompletionCallback callback1;
1119 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
1120 NULL, NULL, BoundNetLog());
1121 EXPECT_EQ(ERR_IO_PENDING, rv);
1123 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1124 factory->pending_requests()[0]->script_data()->url());
1125 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1127 ASSERT_EQ(1u, resolver.pending_requests().size());
1128 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1130 // Set the result in proxy resolver.
1131 resolver.pending_requests()[0]->results()->UseNamedProxy(
1132 "foopy1:8080;foopy2:9090");
1133 resolver.pending_requests()[0]->CompleteNow(OK);
1135 // The first item is valid.
1136 EXPECT_EQ(OK, callback1.WaitForResult());
1137 EXPECT_FALSE(info.is_direct());
1138 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1140 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1141 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1142 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1143 base::TimeTicks proxy_resolve_start_time = info.proxy_resolve_start_time();
1144 base::TimeTicks proxy_resolve_end_time = info.proxy_resolve_end_time();
1146 // Fake an error on the proxy.
1147 TestCompletionCallback callback2;
1148 rv = service.ReconsiderProxyAfterError(
1149 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1150 callback2.callback(), NULL, NULL, BoundNetLog());
1151 EXPECT_EQ(OK, rv);
1153 // Proxy times should not have been modified by fallback.
1154 EXPECT_EQ(proxy_resolve_start_time, info.proxy_resolve_start_time());
1155 EXPECT_EQ(proxy_resolve_end_time, info.proxy_resolve_end_time());
1157 // The second proxy should be specified.
1158 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
1159 // Report back that the second proxy worked. This will globally mark the
1160 // first proxy as bad.
1161 TestProxyFallbackNetworkDelegate test_delegate;
1162 service.ReportSuccess(info, &test_delegate);
1163 EXPECT_EQ("foopy1:8080", test_delegate.proxy_server().ToURI());
1164 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED,
1165 test_delegate.proxy_fallback_net_error());
1167 TestCompletionCallback callback3;
1168 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback3.callback(), NULL,
1169 NULL, BoundNetLog());
1170 EXPECT_EQ(ERR_IO_PENDING, rv);
1172 ASSERT_EQ(1u, resolver.pending_requests().size());
1173 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1175 // Set the result in proxy resolver -- the second result is already known
1176 // to be bad, so we will not try to use it initially.
1177 resolver.pending_requests()[0]->results()->UseNamedProxy(
1178 "foopy3:7070;foopy1:8080;foopy2:9090");
1179 resolver.pending_requests()[0]->CompleteNow(OK);
1181 EXPECT_EQ(OK, callback3.WaitForResult());
1182 EXPECT_FALSE(info.is_direct());
1183 EXPECT_EQ("foopy3:7070", info.proxy_server().ToURI());
1185 // Proxy times should have been updated, so get them again.
1186 EXPECT_LE(proxy_resolve_end_time, info.proxy_resolve_start_time());
1187 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1188 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1189 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1190 proxy_resolve_start_time = info.proxy_resolve_start_time();
1191 proxy_resolve_end_time = info.proxy_resolve_end_time();
1193 // We fake another error. It should now try the third one.
1194 TestCompletionCallback callback4;
1195 rv = service.ReconsiderProxyAfterError(
1196 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1197 callback4.callback(), NULL, NULL, BoundNetLog());
1198 EXPECT_EQ(OK, rv);
1199 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
1201 // We fake another error. At this point we have tried all of the
1202 // proxy servers we thought were valid; next we try the proxy server
1203 // that was in our bad proxies map (foopy1:8080).
1204 TestCompletionCallback callback5;
1205 rv = service.ReconsiderProxyAfterError(
1206 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1207 callback5.callback(), NULL, NULL, BoundNetLog());
1208 EXPECT_EQ(OK, rv);
1209 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1211 // Fake another error, the last proxy is gone, the list should now be empty,
1212 // so there is nothing left to try.
1213 TestCompletionCallback callback6;
1214 rv = service.ReconsiderProxyAfterError(
1215 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1216 callback6.callback(), NULL, NULL, BoundNetLog());
1217 EXPECT_EQ(ERR_FAILED, rv);
1218 EXPECT_FALSE(info.is_direct());
1219 EXPECT_TRUE(info.is_empty());
1221 // Proxy times should not have been modified by fallback.
1222 EXPECT_EQ(proxy_resolve_start_time, info.proxy_resolve_start_time());
1223 EXPECT_EQ(proxy_resolve_end_time, info.proxy_resolve_end_time());
1225 // Look up proxies again
1226 TestCompletionCallback callback7;
1227 rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback7.callback(), NULL,
1228 NULL, BoundNetLog());
1229 EXPECT_EQ(ERR_IO_PENDING, rv);
1231 ASSERT_EQ(1u, resolver.pending_requests().size());
1232 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1234 // This time, the first 3 results have been found to be bad, but only the
1235 // first proxy has been confirmed ...
1236 resolver.pending_requests()[0]->results()->UseNamedProxy(
1237 "foopy1:8080;foopy3:7070;foopy2:9090;foopy4:9091");
1238 resolver.pending_requests()[0]->CompleteNow(OK);
1240 // ... therefore, we should see the second proxy first.
1241 EXPECT_EQ(OK, callback7.WaitForResult());
1242 EXPECT_FALSE(info.is_direct());
1243 EXPECT_EQ("foopy3:7070", info.proxy_server().ToURI());
1245 EXPECT_LE(proxy_resolve_end_time, info.proxy_resolve_start_time());
1246 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1247 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1248 // TODO(nsylvain): Test that the proxy can be retried after the delay.
1251 // This test is similar to ProxyFallback, but this time we have an explicit
1252 // fallback choice to DIRECT.
1253 TEST_F(ProxyServiceTest, ProxyFallbackToDirect) {
1254 MockProxyConfigService* config_service =
1255 new MockProxyConfigService("http://foopy/proxy.pac");
1257 MockAsyncProxyResolver resolver;
1258 MockAsyncProxyResolverFactory* factory =
1259 new MockAsyncProxyResolverFactory(false);
1261 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
1263 GURL url("http://www.google.com/");
1265 // Get the proxy information.
1266 ProxyInfo info;
1267 TestCompletionCallback callback1;
1268 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
1269 NULL, NULL, BoundNetLog());
1270 EXPECT_EQ(ERR_IO_PENDING, rv);
1272 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1273 factory->pending_requests()[0]->script_data()->url());
1274 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1276 ASSERT_EQ(1u, resolver.pending_requests().size());
1277 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1279 // Set the result in proxy resolver.
1280 resolver.pending_requests()[0]->results()->UsePacString(
1281 "PROXY foopy1:8080; PROXY foopy2:9090; DIRECT");
1282 resolver.pending_requests()[0]->CompleteNow(OK);
1284 // Get the first result.
1285 EXPECT_EQ(OK, callback1.WaitForResult());
1286 EXPECT_FALSE(info.is_direct());
1287 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1289 // Fake an error on the proxy.
1290 TestCompletionCallback callback2;
1291 rv = service.ReconsiderProxyAfterError(
1292 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1293 callback2.callback(), NULL, NULL, BoundNetLog());
1294 EXPECT_EQ(OK, rv);
1296 // Now we get back the second proxy.
1297 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
1299 // Fake an error on this proxy as well.
1300 TestCompletionCallback callback3;
1301 rv = service.ReconsiderProxyAfterError(
1302 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1303 callback3.callback(), NULL, NULL, BoundNetLog());
1304 EXPECT_EQ(OK, rv);
1306 // Finally, we get back DIRECT.
1307 EXPECT_TRUE(info.is_direct());
1309 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1310 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1311 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1313 // Now we tell the proxy service that even DIRECT failed.
1314 TestCompletionCallback callback4;
1315 rv = service.ReconsiderProxyAfterError(
1316 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1317 callback4.callback(), NULL, NULL, BoundNetLog());
1318 // There was nothing left to try after DIRECT, so we are out of
1319 // choices.
1320 EXPECT_EQ(ERR_FAILED, rv);
1323 TEST_F(ProxyServiceTest, ProxyFallback_NewSettings) {
1324 // Test proxy failover when new settings are available.
1326 MockProxyConfigService* config_service =
1327 new MockProxyConfigService("http://foopy/proxy.pac");
1329 MockAsyncProxyResolver resolver;
1330 MockAsyncProxyResolverFactory* factory =
1331 new MockAsyncProxyResolverFactory(false);
1333 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
1335 GURL url("http://www.google.com/");
1337 // Get the proxy information.
1338 ProxyInfo info;
1339 TestCompletionCallback callback1;
1340 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
1341 NULL, NULL, BoundNetLog());
1342 EXPECT_EQ(ERR_IO_PENDING, rv);
1344 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1345 factory->pending_requests()[0]->script_data()->url());
1346 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1348 ASSERT_EQ(1u, resolver.pending_requests().size());
1349 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1351 // Set the result in proxy resolver.
1352 resolver.pending_requests()[0]->results()->UseNamedProxy(
1353 "foopy1:8080;foopy2:9090");
1354 resolver.pending_requests()[0]->CompleteNow(OK);
1356 // The first item is valid.
1357 EXPECT_EQ(OK, callback1.WaitForResult());
1358 EXPECT_FALSE(info.is_direct());
1359 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1361 // Fake an error on the proxy, and also a new configuration on the proxy.
1362 config_service->SetConfig(
1363 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy-new/proxy.pac")));
1365 TestCompletionCallback callback2;
1366 rv = service.ReconsiderProxyAfterError(
1367 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1368 callback2.callback(), NULL, NULL, BoundNetLog());
1369 EXPECT_EQ(ERR_IO_PENDING, rv);
1371 EXPECT_EQ(GURL("http://foopy-new/proxy.pac"),
1372 factory->pending_requests()[0]->script_data()->url());
1373 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1375 ASSERT_EQ(1u, resolver.pending_requests().size());
1376 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1378 resolver.pending_requests()[0]->results()->UseNamedProxy(
1379 "foopy1:8080;foopy2:9090");
1380 resolver.pending_requests()[0]->CompleteNow(OK);
1382 // The first proxy is still there since the configuration changed.
1383 EXPECT_EQ(OK, callback2.WaitForResult());
1384 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1386 // We fake another error. It should now ignore the first one.
1387 TestCompletionCallback callback3;
1388 rv = service.ReconsiderProxyAfterError(
1389 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1390 callback3.callback(), NULL, NULL, BoundNetLog());
1391 EXPECT_EQ(OK, rv);
1392 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
1394 // We simulate a new configuration.
1395 config_service->SetConfig(
1396 ProxyConfig::CreateFromCustomPacURL(
1397 GURL("http://foopy-new2/proxy.pac")));
1399 // We fake another error. It should go back to the first proxy.
1400 TestCompletionCallback callback4;
1401 rv = service.ReconsiderProxyAfterError(
1402 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1403 callback4.callback(), NULL, NULL, BoundNetLog());
1404 EXPECT_EQ(ERR_IO_PENDING, rv);
1406 EXPECT_EQ(GURL("http://foopy-new2/proxy.pac"),
1407 factory->pending_requests()[0]->script_data()->url());
1408 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1410 ASSERT_EQ(1u, resolver.pending_requests().size());
1411 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1413 resolver.pending_requests()[0]->results()->UseNamedProxy(
1414 "foopy1:8080;foopy2:9090");
1415 resolver.pending_requests()[0]->CompleteNow(OK);
1417 EXPECT_EQ(OK, callback4.WaitForResult());
1418 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1420 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1421 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1422 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1425 TEST_F(ProxyServiceTest, ProxyFallback_BadConfig) {
1426 // Test proxy failover when the configuration is bad.
1428 MockProxyConfigService* config_service =
1429 new MockProxyConfigService("http://foopy/proxy.pac");
1431 MockAsyncProxyResolver resolver;
1432 MockAsyncProxyResolverFactory* factory =
1433 new MockAsyncProxyResolverFactory(false);
1435 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
1437 GURL url("http://www.google.com/");
1439 // Get the proxy information.
1440 ProxyInfo info;
1441 TestCompletionCallback callback1;
1442 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
1443 NULL, NULL, BoundNetLog());
1444 EXPECT_EQ(ERR_IO_PENDING, rv);
1446 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1447 factory->pending_requests()[0]->script_data()->url());
1448 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1449 ASSERT_EQ(1u, resolver.pending_requests().size());
1450 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1452 resolver.pending_requests()[0]->results()->UseNamedProxy(
1453 "foopy1:8080;foopy2:9090");
1454 resolver.pending_requests()[0]->CompleteNow(OK);
1456 // The first item is valid.
1457 EXPECT_EQ(OK, callback1.WaitForResult());
1458 EXPECT_FALSE(info.is_direct());
1459 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1461 // Fake a proxy error.
1462 TestCompletionCallback callback2;
1463 rv = service.ReconsiderProxyAfterError(
1464 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1465 callback2.callback(), NULL, NULL, BoundNetLog());
1466 EXPECT_EQ(OK, rv);
1468 // The first proxy is ignored, and the second one is selected.
1469 EXPECT_FALSE(info.is_direct());
1470 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
1472 // Fake a PAC failure.
1473 ProxyInfo info2;
1474 TestCompletionCallback callback3;
1475 rv = service.ResolveProxy(url, LOAD_NORMAL, &info2, callback3.callback(),
1476 NULL, NULL, BoundNetLog());
1477 EXPECT_EQ(ERR_IO_PENDING, rv);
1479 ASSERT_EQ(1u, resolver.pending_requests().size());
1480 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1482 // This simulates a javascript runtime error in the PAC script.
1483 resolver.pending_requests()[0]->CompleteNow(ERR_FAILED);
1485 // Although the resolver failed, the ProxyService will implicitly fall-back
1486 // to a DIRECT connection.
1487 EXPECT_EQ(OK, callback3.WaitForResult());
1488 EXPECT_TRUE(info2.is_direct());
1489 EXPECT_FALSE(info2.is_empty());
1491 // The PAC script will work properly next time and successfully return a
1492 // proxy list. Since we have not marked the configuration as bad, it should
1493 // "just work" the next time we call it.
1494 ProxyInfo info3;
1495 TestCompletionCallback callback4;
1496 rv = service.ReconsiderProxyAfterError(
1497 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info3,
1498 callback4.callback(), NULL, NULL, BoundNetLog());
1499 EXPECT_EQ(ERR_IO_PENDING, rv);
1501 ASSERT_EQ(1u, resolver.pending_requests().size());
1502 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1504 resolver.pending_requests()[0]->results()->UseNamedProxy(
1505 "foopy1:8080;foopy2:9090");
1506 resolver.pending_requests()[0]->CompleteNow(OK);
1508 // The first proxy is not there since the it was added to the bad proxies
1509 // list by the earlier ReconsiderProxyAfterError().
1510 EXPECT_EQ(OK, callback4.WaitForResult());
1511 EXPECT_FALSE(info3.is_direct());
1512 EXPECT_EQ("foopy1:8080", info3.proxy_server().ToURI());
1514 EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1515 EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1516 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1519 TEST_F(ProxyServiceTest, ProxyFallback_BadConfigMandatory) {
1520 // Test proxy failover when the configuration is bad.
1522 ProxyConfig config(
1523 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
1525 config.set_pac_mandatory(true);
1526 MockProxyConfigService* config_service = new MockProxyConfigService(config);
1528 MockAsyncProxyResolver resolver;
1529 MockAsyncProxyResolverFactory* factory =
1530 new MockAsyncProxyResolverFactory(false);
1532 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
1534 GURL url("http://www.google.com/");
1536 // Get the proxy information.
1537 ProxyInfo info;
1538 TestCompletionCallback callback1;
1539 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(),
1540 NULL, NULL, BoundNetLog());
1541 EXPECT_EQ(ERR_IO_PENDING, rv);
1543 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1544 factory->pending_requests()[0]->script_data()->url());
1545 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1546 ASSERT_EQ(1u, resolver.pending_requests().size());
1547 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1549 resolver.pending_requests()[0]->results()->UseNamedProxy(
1550 "foopy1:8080;foopy2:9090");
1551 resolver.pending_requests()[0]->CompleteNow(OK);
1553 // The first item is valid.
1554 EXPECT_EQ(OK, callback1.WaitForResult());
1555 EXPECT_FALSE(info.is_direct());
1556 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1558 // Fake a proxy error.
1559 TestCompletionCallback callback2;
1560 rv = service.ReconsiderProxyAfterError(
1561 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info,
1562 callback2.callback(), NULL, NULL, BoundNetLog());
1563 EXPECT_EQ(OK, rv);
1565 // The first proxy is ignored, and the second one is selected.
1566 EXPECT_FALSE(info.is_direct());
1567 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
1569 // Fake a PAC failure.
1570 ProxyInfo info2;
1571 TestCompletionCallback callback3;
1572 rv = service.ResolveProxy(url, LOAD_NORMAL, &info2, callback3.callback(),
1573 NULL, NULL, BoundNetLog());
1574 EXPECT_EQ(ERR_IO_PENDING, rv);
1576 ASSERT_EQ(1u, resolver.pending_requests().size());
1577 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1579 // This simulates a javascript runtime error in the PAC script.
1580 resolver.pending_requests()[0]->CompleteNow(ERR_FAILED);
1582 // Although the resolver failed, the ProxyService will NOT fall-back
1583 // to a DIRECT connection as it is configured as mandatory.
1584 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
1585 callback3.WaitForResult());
1586 EXPECT_FALSE(info2.is_direct());
1587 EXPECT_TRUE(info2.is_empty());
1589 // The PAC script will work properly next time and successfully return a
1590 // proxy list. Since we have not marked the configuration as bad, it should
1591 // "just work" the next time we call it.
1592 ProxyInfo info3;
1593 TestCompletionCallback callback4;
1594 rv = service.ReconsiderProxyAfterError(
1595 url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info3,
1596 callback4.callback(), NULL, NULL, BoundNetLog());
1597 EXPECT_EQ(ERR_IO_PENDING, rv);
1599 ASSERT_EQ(1u, resolver.pending_requests().size());
1600 EXPECT_EQ(url, resolver.pending_requests()[0]->url());
1602 resolver.pending_requests()[0]->results()->UseNamedProxy(
1603 "foopy1:8080;foopy2:9090");
1604 resolver.pending_requests()[0]->CompleteNow(OK);
1606 // The first proxy is not there since the it was added to the bad proxies
1607 // list by the earlier ReconsiderProxyAfterError().
1608 EXPECT_EQ(OK, callback4.WaitForResult());
1609 EXPECT_FALSE(info3.is_direct());
1610 EXPECT_EQ("foopy1:8080", info3.proxy_server().ToURI());
1613 TEST_F(ProxyServiceTest, ProxyBypassList) {
1614 // Test that the proxy bypass rules are consulted.
1616 TestCompletionCallback callback[2];
1617 ProxyInfo info[2];
1618 ProxyConfig config;
1619 config.proxy_rules().ParseFromString("foopy1:8080;foopy2:9090");
1620 config.set_auto_detect(false);
1621 config.proxy_rules().bypass_rules.ParseFromString("*.org");
1623 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1625 int rv;
1626 GURL url1("http://www.webkit.org");
1627 GURL url2("http://www.webkit.com");
1629 // Request for a .org domain should bypass proxy.
1630 rv = service.ResolveProxy(url1, LOAD_NORMAL, &info[0], callback[0].callback(),
1631 NULL, NULL, BoundNetLog());
1632 EXPECT_EQ(OK, rv);
1633 EXPECT_TRUE(info[0].is_direct());
1635 // Request for a .com domain hits the proxy.
1636 rv = service.ResolveProxy(url2, LOAD_NORMAL, &info[1], callback[1].callback(),
1637 NULL, NULL, BoundNetLog());
1638 EXPECT_EQ(OK, rv);
1639 EXPECT_EQ("foopy1:8080", info[1].proxy_server().ToURI());
1642 TEST_F(ProxyServiceTest, MarkProxiesAsBadTests) {
1643 ProxyConfig config;
1644 config.proxy_rules().ParseFromString(
1645 "http=foopy1:8080;http=foopy2:8080;http=foopy3.8080;http=foopy4:8080");
1646 config.set_auto_detect(false);
1648 ProxyList proxy_list;
1649 std::vector<ProxyServer> additional_bad_proxies;
1650 for (const ProxyServer& proxy_server :
1651 config.proxy_rules().proxies_for_http.GetAll()) {
1652 proxy_list.AddProxyServer(proxy_server);
1653 if (proxy_server == config.proxy_rules().proxies_for_http.Get())
1654 continue;
1656 additional_bad_proxies.push_back(proxy_server);
1659 EXPECT_EQ(3u, additional_bad_proxies.size());
1661 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1662 ProxyInfo proxy_info;
1663 proxy_info.UseProxyList(proxy_list);
1664 const ProxyRetryInfoMap& retry_info = service.proxy_retry_info();
1665 service.MarkProxiesAsBadUntil(proxy_info, base::TimeDelta::FromSeconds(1),
1666 additional_bad_proxies, BoundNetLog());
1667 ASSERT_EQ(4u, retry_info.size());
1668 for (const ProxyServer& proxy_server :
1669 config.proxy_rules().proxies_for_http.GetAll()) {
1670 ProxyRetryInfoMap::const_iterator i =
1671 retry_info.find(proxy_server.host_port_pair().ToString());
1672 ASSERT_TRUE(i != retry_info.end());
1676 TEST_F(ProxyServiceTest, PerProtocolProxyTests) {
1677 ProxyConfig config;
1678 config.proxy_rules().ParseFromString("http=foopy1:8080;https=foopy2:8080");
1679 config.set_auto_detect(false);
1681 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1682 GURL test_url("http://www.msn.com");
1683 ProxyInfo info;
1684 TestCompletionCallback callback;
1685 int rv =
1686 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1687 NULL, NULL, BoundNetLog());
1688 EXPECT_EQ(OK, rv);
1689 EXPECT_FALSE(info.is_direct());
1690 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1693 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1694 GURL test_url("ftp://ftp.google.com");
1695 ProxyInfo info;
1696 TestCompletionCallback callback;
1697 int rv =
1698 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1699 NULL, NULL, BoundNetLog());
1700 EXPECT_EQ(OK, rv);
1701 EXPECT_TRUE(info.is_direct());
1702 EXPECT_EQ("direct://", info.proxy_server().ToURI());
1705 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1706 GURL test_url("https://webbranch.techcu.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 EXPECT_EQ(OK, rv);
1713 EXPECT_FALSE(info.is_direct());
1714 EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI());
1717 config.proxy_rules().ParseFromString("foopy1:8080");
1718 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1719 GURL test_url("http://www.microsoft.com");
1720 ProxyInfo info;
1721 TestCompletionCallback callback;
1722 int rv =
1723 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1724 NULL, NULL, BoundNetLog());
1725 EXPECT_EQ(OK, rv);
1726 EXPECT_FALSE(info.is_direct());
1727 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1731 TEST_F(ProxyServiceTest, ProxyConfigSourcePropagates) {
1732 // Test that the proxy config source is set correctly when resolving proxies
1733 // using manual proxy rules. Namely, the config source should only be set if
1734 // any of the rules were applied.
1736 ProxyConfig config;
1737 config.set_source(PROXY_CONFIG_SOURCE_TEST);
1738 config.proxy_rules().ParseFromString("https=foopy2:8080");
1739 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1740 GURL test_url("http://www.google.com");
1741 ProxyInfo info;
1742 TestCompletionCallback callback;
1743 int rv =
1744 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1745 NULL, NULL, BoundNetLog());
1746 ASSERT_EQ(OK, rv);
1747 // Should be SOURCE_TEST, even if there are no HTTP proxies configured.
1748 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
1751 ProxyConfig config;
1752 config.set_source(PROXY_CONFIG_SOURCE_TEST);
1753 config.proxy_rules().ParseFromString("https=foopy2:8080");
1754 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1755 GURL test_url("https://www.google.com");
1756 ProxyInfo info;
1757 TestCompletionCallback callback;
1758 int rv =
1759 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1760 NULL, NULL, BoundNetLog());
1761 ASSERT_EQ(OK, rv);
1762 // Used the HTTPS proxy. So source should be TEST.
1763 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
1766 ProxyConfig config;
1767 config.set_source(PROXY_CONFIG_SOURCE_TEST);
1768 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1769 GURL test_url("http://www.google.com");
1770 ProxyInfo info;
1771 TestCompletionCallback callback;
1772 int rv =
1773 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1774 NULL, NULL, BoundNetLog());
1775 ASSERT_EQ(OK, rv);
1776 // ProxyConfig is empty. Source should still be TEST.
1777 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source());
1781 // If only HTTP and a SOCKS proxy are specified, check if ftp/https queries
1782 // fall back to the SOCKS proxy.
1783 TEST_F(ProxyServiceTest, DefaultProxyFallbackToSOCKS) {
1784 ProxyConfig config;
1785 config.proxy_rules().ParseFromString("http=foopy1:8080;socks=foopy2:1080");
1786 config.set_auto_detect(false);
1787 EXPECT_EQ(ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
1788 config.proxy_rules().type);
1791 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1792 GURL test_url("http://www.msn.com");
1793 ProxyInfo info;
1794 TestCompletionCallback callback;
1795 int rv =
1796 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1797 NULL, NULL, BoundNetLog());
1798 EXPECT_EQ(OK, rv);
1799 EXPECT_FALSE(info.is_direct());
1800 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1803 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1804 GURL test_url("ftp://ftp.google.com");
1805 ProxyInfo info;
1806 TestCompletionCallback callback;
1807 int rv =
1808 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1809 NULL, NULL, BoundNetLog());
1810 EXPECT_EQ(OK, rv);
1811 EXPECT_FALSE(info.is_direct());
1812 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI());
1815 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1816 GURL test_url("https://webbranch.techcu.com");
1817 ProxyInfo info;
1818 TestCompletionCallback callback;
1819 int rv =
1820 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1821 NULL, NULL, BoundNetLog());
1822 EXPECT_EQ(OK, rv);
1823 EXPECT_FALSE(info.is_direct());
1824 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI());
1827 ProxyService service(new MockProxyConfigService(config), nullptr, NULL);
1828 GURL test_url("unknown://www.microsoft.com");
1829 ProxyInfo info;
1830 TestCompletionCallback callback;
1831 int rv =
1832 service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(),
1833 NULL, NULL, BoundNetLog());
1834 EXPECT_EQ(OK, rv);
1835 EXPECT_FALSE(info.is_direct());
1836 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI());
1840 // Test cancellation of an in-progress request.
1841 TEST_F(ProxyServiceTest, CancelInProgressRequest) {
1842 const GURL url1("http://request1");
1843 const GURL url2("http://request2");
1844 const GURL url3("http://request3");
1845 MockProxyConfigService* config_service =
1846 new MockProxyConfigService("http://foopy/proxy.pac");
1848 MockAsyncProxyResolver resolver;
1849 MockAsyncProxyResolverFactory* factory =
1850 new MockAsyncProxyResolverFactory(false);
1852 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
1854 // Start 3 requests.
1856 ProxyInfo info1;
1857 TestCompletionCallback callback1;
1858 int rv = service.ResolveProxy(url1, LOAD_NORMAL, &info1, callback1.callback(),
1859 NULL, NULL, BoundNetLog());
1860 EXPECT_EQ(ERR_IO_PENDING, rv);
1862 // Successfully initialize the PAC script.
1863 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1864 factory->pending_requests()[0]->script_data()->url());
1865 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1867 GetPendingRequestsForURLs(resolver, url1);
1869 ProxyInfo info2;
1870 TestCompletionCallback callback2;
1871 ProxyService::PacRequest* request2;
1872 rv = service.ResolveProxy(url2, LOAD_NORMAL, &info2, callback2.callback(),
1873 &request2, NULL, BoundNetLog());
1874 EXPECT_EQ(ERR_IO_PENDING, rv);
1876 GetPendingRequestsForURLs(resolver, url1, url2);
1878 ProxyInfo info3;
1879 TestCompletionCallback callback3;
1880 rv = service.ResolveProxy(url3, LOAD_NORMAL, &info3, callback3.callback(),
1881 NULL, NULL, BoundNetLog());
1882 EXPECT_EQ(ERR_IO_PENDING, rv);
1883 GetPendingRequestsForURLs(resolver, url1, url2, url3);
1885 // Cancel the second request
1886 service.CancelPacRequest(request2);
1888 RequestMap requests = GetPendingRequestsForURLs(resolver, url1, url3);
1890 // Complete the two un-cancelled requests.
1891 // We complete the last one first, just to mix it up a bit.
1892 requests[url3]->results()->UseNamedProxy("request3:80");
1893 requests[url3]->CompleteNow(OK);
1895 requests[url1]->results()->UseNamedProxy("request1:80");
1896 requests[url1]->CompleteNow(OK);
1898 // Complete and verify that requests ran as expected.
1899 EXPECT_EQ(OK, callback1.WaitForResult());
1900 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
1902 EXPECT_FALSE(callback2.have_result()); // Cancelled.
1903 GetCancelledRequestsForURLs(resolver, url2);
1905 EXPECT_EQ(OK, callback3.WaitForResult());
1906 EXPECT_EQ("request3:80", info3.proxy_server().ToURI());
1909 // Test the initial PAC download for resolver that expects bytes.
1910 TEST_F(ProxyServiceTest, InitialPACScriptDownload) {
1911 const GURL url1("http://request1");
1912 const GURL url2("http://request2");
1913 const GURL url3("http://request3");
1915 MockProxyConfigService* config_service =
1916 new MockProxyConfigService("http://foopy/proxy.pac");
1918 MockAsyncProxyResolver resolver;
1919 MockAsyncProxyResolverFactory* factory =
1920 new MockAsyncProxyResolverFactory(true);
1922 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
1924 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1925 service.SetProxyScriptFetchers(
1926 fetcher, make_scoped_ptr(new DoNothingDhcpProxyScriptFetcher()));
1928 // Start 3 requests.
1930 ProxyInfo info1;
1931 TestCompletionCallback callback1;
1932 ProxyService::PacRequest* request1;
1933 int rv = service.ResolveProxy(url1, LOAD_NORMAL, &info1, callback1.callback(),
1934 &request1, NULL, BoundNetLog());
1935 EXPECT_EQ(ERR_IO_PENDING, rv);
1937 // The first request should have triggered download of PAC script.
1938 EXPECT_TRUE(fetcher->has_pending_request());
1939 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1941 ProxyInfo info2;
1942 TestCompletionCallback callback2;
1943 ProxyService::PacRequest* request2;
1944 rv = service.ResolveProxy(url2, LOAD_NORMAL, &info2, callback2.callback(),
1945 &request2, NULL, BoundNetLog());
1946 EXPECT_EQ(ERR_IO_PENDING, rv);
1948 ProxyInfo info3;
1949 TestCompletionCallback callback3;
1950 ProxyService::PacRequest* request3;
1951 rv = service.ResolveProxy(url3, LOAD_NORMAL, &info3, callback3.callback(),
1952 &request3, NULL, BoundNetLog());
1953 EXPECT_EQ(ERR_IO_PENDING, rv);
1955 // Nothing has been sent to the factory yet.
1956 EXPECT_TRUE(factory->pending_requests().empty());
1958 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT,
1959 service.GetLoadState(request1));
1960 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT,
1961 service.GetLoadState(request2));
1962 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT,
1963 service.GetLoadState(request3));
1965 // At this point the ProxyService should be waiting for the
1966 // ProxyScriptFetcher to invoke its completion callback, notifying it of
1967 // PAC script download completion.
1968 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
1970 // Now that the PAC script is downloaded, it will have been sent to the proxy
1971 // resolver.
1972 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
1973 factory->pending_requests()[0]->script_data()->utf16());
1974 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1976 RequestMap requests = GetPendingRequestsForURLs(resolver, url1, url2, url3);
1978 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request1));
1979 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request2));
1980 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request3));
1982 // Complete all the requests (in some order).
1984 requests[url3]->results()->UseNamedProxy("request3:80");
1985 requests[url3]->CompleteNow(OK);
1987 requests[url1]->results()->UseNamedProxy("request1:80");
1988 requests[url1]->CompleteNow(OK);
1990 requests[url2]->results()->UseNamedProxy("request2:80");
1991 requests[url2]->CompleteNow(OK);
1993 // Complete and verify that requests ran as expected.
1994 EXPECT_EQ(OK, callback1.WaitForResult());
1995 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
1996 EXPECT_FALSE(info1.proxy_resolve_start_time().is_null());
1997 EXPECT_FALSE(info1.proxy_resolve_end_time().is_null());
1998 EXPECT_LE(info1.proxy_resolve_start_time(), info1.proxy_resolve_end_time());
2000 EXPECT_EQ(OK, callback2.WaitForResult());
2001 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2002 EXPECT_FALSE(info2.proxy_resolve_start_time().is_null());
2003 EXPECT_FALSE(info2.proxy_resolve_end_time().is_null());
2004 EXPECT_LE(info2.proxy_resolve_start_time(), info2.proxy_resolve_end_time());
2006 EXPECT_EQ(OK, callback3.WaitForResult());
2007 EXPECT_EQ("request3:80", info3.proxy_server().ToURI());
2008 EXPECT_FALSE(info3.proxy_resolve_start_time().is_null());
2009 EXPECT_FALSE(info3.proxy_resolve_end_time().is_null());
2010 EXPECT_LE(info3.proxy_resolve_start_time(), info3.proxy_resolve_end_time());
2013 // Test changing the ProxyScriptFetcher while PAC download is in progress.
2014 TEST_F(ProxyServiceTest, ChangeScriptFetcherWhilePACDownloadInProgress) {
2015 const GURL url1("http://request1");
2016 const GURL url2("http://request2");
2017 MockProxyConfigService* config_service =
2018 new MockProxyConfigService("http://foopy/proxy.pac");
2020 MockAsyncProxyResolver resolver;
2021 MockAsyncProxyResolverFactory* factory =
2022 new MockAsyncProxyResolverFactory(true);
2024 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
2026 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2027 service.SetProxyScriptFetchers(
2028 fetcher, make_scoped_ptr(new DoNothingDhcpProxyScriptFetcher()));
2030 // Start 2 requests.
2032 ProxyInfo info1;
2033 TestCompletionCallback callback1;
2034 int rv = service.ResolveProxy(url1, LOAD_NORMAL, &info1, callback1.callback(),
2035 NULL, NULL, BoundNetLog());
2036 EXPECT_EQ(ERR_IO_PENDING, rv);
2038 // The first request should have triggered download of PAC script.
2039 EXPECT_TRUE(fetcher->has_pending_request());
2040 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2042 ProxyInfo info2;
2043 TestCompletionCallback callback2;
2044 rv = service.ResolveProxy(url2, LOAD_NORMAL, &info2, callback2.callback(),
2045 NULL, NULL, BoundNetLog());
2046 EXPECT_EQ(ERR_IO_PENDING, rv);
2048 // At this point the ProxyService should be waiting for the
2049 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2050 // PAC script download completion.
2052 // We now change out the ProxyService's script fetcher. We should restart
2053 // the initialization with the new fetcher.
2055 fetcher = new MockProxyScriptFetcher;
2056 service.SetProxyScriptFetchers(
2057 fetcher, make_scoped_ptr(new DoNothingDhcpProxyScriptFetcher()));
2059 // Nothing has been sent to the factory yet.
2060 EXPECT_TRUE(factory->pending_requests().empty());
2062 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2064 // Now that the PAC script is downloaded, it will have been sent to the proxy
2065 // resolver.
2066 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2067 factory->pending_requests()[0]->script_data()->utf16());
2068 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2070 GetPendingRequestsForURLs(resolver, url1, url2);
2073 // Test cancellation of a request, while the PAC script is being fetched.
2074 TEST_F(ProxyServiceTest, CancelWhilePACFetching) {
2075 MockProxyConfigService* config_service =
2076 new MockProxyConfigService("http://foopy/proxy.pac");
2078 MockAsyncProxyResolver resolver;
2079 MockAsyncProxyResolverFactory* factory =
2080 new MockAsyncProxyResolverFactory(true);
2082 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
2084 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2085 service.SetProxyScriptFetchers(
2086 fetcher, make_scoped_ptr(new DoNothingDhcpProxyScriptFetcher()));
2088 // Start 3 requests.
2089 ProxyInfo info1;
2090 TestCompletionCallback callback1;
2091 ProxyService::PacRequest* request1;
2092 BoundTestNetLog log1;
2093 int rv =
2094 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
2095 callback1.callback(), &request1, NULL, log1.bound());
2096 EXPECT_EQ(ERR_IO_PENDING, rv);
2098 // The first request should have triggered download of PAC script.
2099 EXPECT_TRUE(fetcher->has_pending_request());
2100 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2102 ProxyInfo info2;
2103 TestCompletionCallback callback2;
2104 ProxyService::PacRequest* request2;
2105 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
2106 callback2.callback(), &request2, NULL,
2107 BoundNetLog());
2108 EXPECT_EQ(ERR_IO_PENDING, rv);
2110 ProxyInfo info3;
2111 TestCompletionCallback callback3;
2112 rv = service.ResolveProxy(GURL("http://request3"), LOAD_NORMAL, &info3,
2113 callback3.callback(), NULL, NULL, BoundNetLog());
2114 EXPECT_EQ(ERR_IO_PENDING, rv);
2116 // Nothing has been sent to the factory yet.
2117 EXPECT_TRUE(factory->pending_requests().empty());
2119 // Cancel the first 2 requests.
2120 service.CancelPacRequest(request1);
2121 service.CancelPacRequest(request2);
2123 // At this point the ProxyService should be waiting for the
2124 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2125 // PAC script download completion.
2126 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2128 // Now that the PAC script is downloaded, it will have been sent to the
2129 // proxy resolver.
2130 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2131 factory->pending_requests()[0]->script_data()->utf16());
2132 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2134 ASSERT_EQ(1u, resolver.pending_requests().size());
2135 EXPECT_EQ(GURL("http://request3"), resolver.pending_requests()[0]->url());
2137 // Complete all the requests.
2138 resolver.pending_requests()[0]->results()->UseNamedProxy("request3:80");
2139 resolver.pending_requests()[0]->CompleteNow(OK);
2141 EXPECT_EQ(OK, callback3.WaitForResult());
2142 EXPECT_EQ("request3:80", info3.proxy_server().ToURI());
2144 EXPECT_TRUE(resolver.cancelled_requests().empty());
2146 EXPECT_FALSE(callback1.have_result()); // Cancelled.
2147 EXPECT_FALSE(callback2.have_result()); // Cancelled.
2149 TestNetLogEntry::List entries1;
2150 log1.GetEntries(&entries1);
2152 // Check the NetLog for request 1 (which was cancelled) got filled properly.
2153 EXPECT_EQ(4u, entries1.size());
2154 EXPECT_TRUE(LogContainsBeginEvent(
2155 entries1, 0, NetLog::TYPE_PROXY_SERVICE));
2156 EXPECT_TRUE(LogContainsBeginEvent(
2157 entries1, 1, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
2158 // Note that TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC is never completed before
2159 // the cancellation occured.
2160 EXPECT_TRUE(LogContainsEvent(
2161 entries1, 2, NetLog::TYPE_CANCELLED, NetLog::PHASE_NONE));
2162 EXPECT_TRUE(LogContainsEndEvent(
2163 entries1, 3, NetLog::TYPE_PROXY_SERVICE));
2166 // Test that if auto-detect fails, we fall-back to the custom pac.
2167 TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomPac) {
2168 const GURL url1("http://request1");
2169 const GURL url2("http://request2");
2170 ProxyConfig config;
2171 config.set_auto_detect(true);
2172 config.set_pac_url(GURL("http://foopy/proxy.pac"));
2173 config.proxy_rules().ParseFromString("http=foopy:80"); // Won't be used.
2175 MockProxyConfigService* config_service = new MockProxyConfigService(config);
2176 MockAsyncProxyResolver resolver;
2177 MockAsyncProxyResolverFactory* factory =
2178 new MockAsyncProxyResolverFactory(true);
2179 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
2181 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2182 service.SetProxyScriptFetchers(
2183 fetcher, make_scoped_ptr(new DoNothingDhcpProxyScriptFetcher()));
2185 // Start 2 requests.
2187 ProxyInfo info1;
2188 TestCompletionCallback callback1;
2189 int rv = service.ResolveProxy(url1, LOAD_NORMAL, &info1, callback1.callback(),
2190 NULL, NULL, BoundNetLog());
2191 EXPECT_EQ(ERR_IO_PENDING, rv);
2193 ProxyInfo info2;
2194 TestCompletionCallback callback2;
2195 ProxyService::PacRequest* request2;
2196 rv = service.ResolveProxy(url2, LOAD_NORMAL, &info2, callback2.callback(),
2197 &request2, NULL, BoundNetLog());
2198 EXPECT_EQ(ERR_IO_PENDING, rv);
2200 // Check that nothing has been sent to the proxy resolver factory yet.
2201 ASSERT_EQ(0u, factory->pending_requests().size());
2203 // It should be trying to auto-detect first -- FAIL the autodetect during
2204 // the script download.
2205 EXPECT_TRUE(fetcher->has_pending_request());
2206 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
2207 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
2209 // Next it should be trying the custom PAC url.
2210 EXPECT_TRUE(fetcher->has_pending_request());
2211 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2212 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2214 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2215 factory->pending_requests()[0]->script_data()->utf16());
2216 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2218 // Now finally, the pending requests should have been sent to the resolver
2219 // (which was initialized with custom PAC script).
2221 RequestMap requests = GetPendingRequestsForURLs(resolver, url1, url2);
2223 // Complete the pending requests.
2224 requests[url2]->results()->UseNamedProxy("request2:80");
2225 requests[url2]->CompleteNow(OK);
2226 requests[url1]->results()->UseNamedProxy("request1:80");
2227 requests[url1]->CompleteNow(OK);
2229 // Verify that requests ran as expected.
2230 EXPECT_EQ(OK, callback1.WaitForResult());
2231 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2232 EXPECT_FALSE(info1.proxy_resolve_start_time().is_null());
2233 EXPECT_FALSE(info1.proxy_resolve_end_time().is_null());
2234 EXPECT_LE(info1.proxy_resolve_start_time(), info1.proxy_resolve_end_time());
2236 EXPECT_EQ(OK, callback2.WaitForResult());
2237 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2238 EXPECT_FALSE(info2.proxy_resolve_start_time().is_null());
2239 EXPECT_FALSE(info2.proxy_resolve_end_time().is_null());
2240 EXPECT_LE(info2.proxy_resolve_start_time(), info2.proxy_resolve_end_time());
2243 // This is the same test as FallbackFromAutodetectToCustomPac, except
2244 // the auto-detect script fails parsing rather than downloading.
2245 TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomPac2) {
2246 const GURL url1("http://request1");
2247 const GURL url2("http://request2");
2248 ProxyConfig config;
2249 config.set_auto_detect(true);
2250 config.set_pac_url(GURL("http://foopy/proxy.pac"));
2251 config.proxy_rules().ParseFromString("http=foopy:80"); // Won't be used.
2253 MockProxyConfigService* config_service = new MockProxyConfigService(config);
2254 MockAsyncProxyResolver resolver;
2255 MockAsyncProxyResolverFactory* factory =
2256 new MockAsyncProxyResolverFactory(true);
2257 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
2259 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2260 service.SetProxyScriptFetchers(
2261 fetcher, make_scoped_ptr(new DoNothingDhcpProxyScriptFetcher()));
2263 // Start 2 requests.
2265 ProxyInfo info1;
2266 TestCompletionCallback callback1;
2267 int rv = service.ResolveProxy(url1, LOAD_NORMAL, &info1, callback1.callback(),
2268 NULL, NULL, BoundNetLog());
2269 EXPECT_EQ(ERR_IO_PENDING, rv);
2271 ProxyInfo info2;
2272 TestCompletionCallback callback2;
2273 ProxyService::PacRequest* request2;
2274 rv = service.ResolveProxy(url2, LOAD_NORMAL, &info2, callback2.callback(),
2275 &request2, NULL, BoundNetLog());
2276 EXPECT_EQ(ERR_IO_PENDING, rv);
2278 // Check that nothing has been sent to the proxy resolver factory yet.
2279 ASSERT_EQ(0u, factory->pending_requests().size());
2281 // It should be trying to auto-detect first -- succeed the download.
2282 EXPECT_TRUE(fetcher->has_pending_request());
2283 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
2284 fetcher->NotifyFetchCompletion(OK, "invalid-script-contents");
2286 // The script contents passed failed basic verification step (since didn't
2287 // contain token FindProxyForURL), so it was never passed to the resolver.
2289 // Next it should be trying the custom PAC url.
2290 EXPECT_TRUE(fetcher->has_pending_request());
2291 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2292 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2294 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2295 factory->pending_requests()[0]->script_data()->utf16());
2296 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2298 // Now finally, the pending requests should have been sent to the resolver
2299 // (which was initialized with custom PAC script).
2301 RequestMap requests = GetPendingRequestsForURLs(resolver, url1, url2);
2303 // Complete the pending requests.
2304 requests[url2]->results()->UseNamedProxy("request2:80");
2305 requests[url2]->CompleteNow(OK);
2306 requests[url1]->results()->UseNamedProxy("request1:80");
2307 requests[url1]->CompleteNow(OK);
2309 // Verify that requests ran as expected.
2310 EXPECT_EQ(OK, callback1.WaitForResult());
2311 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2313 EXPECT_EQ(OK, callback2.WaitForResult());
2314 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2317 // Test that if all of auto-detect, a custom PAC script, and manual settings
2318 // are given, then we will try them in that order.
2319 TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomToManual) {
2320 ProxyConfig config;
2321 config.set_auto_detect(true);
2322 config.set_pac_url(GURL("http://foopy/proxy.pac"));
2323 config.proxy_rules().ParseFromString("http=foopy:80");
2325 MockProxyConfigService* config_service = new MockProxyConfigService(config);
2326 MockAsyncProxyResolverFactory* factory =
2327 new MockAsyncProxyResolverFactory(true);
2328 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
2330 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2331 service.SetProxyScriptFetchers(
2332 fetcher, make_scoped_ptr(new DoNothingDhcpProxyScriptFetcher()));
2334 // Start 2 requests.
2336 ProxyInfo info1;
2337 TestCompletionCallback callback1;
2338 int rv =
2339 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
2340 callback1.callback(), NULL, NULL, BoundNetLog());
2341 EXPECT_EQ(ERR_IO_PENDING, rv);
2343 ProxyInfo info2;
2344 TestCompletionCallback callback2;
2345 ProxyService::PacRequest* request2;
2346 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
2347 callback2.callback(), &request2, NULL,
2348 BoundNetLog());
2349 EXPECT_EQ(ERR_IO_PENDING, rv);
2351 // Check that nothing has been sent to the proxy resolver factory yet.
2352 ASSERT_EQ(0u, factory->pending_requests().size());
2354 // It should be trying to auto-detect first -- fail the download.
2355 EXPECT_TRUE(fetcher->has_pending_request());
2356 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
2357 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
2359 // Next it should be trying the custom PAC url -- fail the download.
2360 EXPECT_TRUE(fetcher->has_pending_request());
2361 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2362 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
2364 // Since we never managed to initialize a resolver, nothing should have been
2365 // sent to it.
2366 ASSERT_EQ(0u, factory->pending_requests().size());
2368 // Verify that requests ran as expected -- they should have fallen back to
2369 // the manual proxy configuration for HTTP urls.
2370 EXPECT_EQ(OK, callback1.WaitForResult());
2371 EXPECT_EQ("foopy:80", info1.proxy_server().ToURI());
2373 EXPECT_EQ(OK, callback2.WaitForResult());
2374 EXPECT_EQ("foopy:80", info2.proxy_server().ToURI());
2377 // Test that the bypass rules are NOT applied when using autodetect.
2378 TEST_F(ProxyServiceTest, BypassDoesntApplyToPac) {
2379 ProxyConfig config;
2380 config.set_auto_detect(true);
2381 config.set_pac_url(GURL("http://foopy/proxy.pac"));
2382 config.proxy_rules().ParseFromString("http=foopy:80"); // Not used.
2383 config.proxy_rules().bypass_rules.ParseFromString("www.google.com");
2385 MockProxyConfigService* config_service = new MockProxyConfigService(config);
2386 MockAsyncProxyResolver resolver;
2387 MockAsyncProxyResolverFactory* factory =
2388 new MockAsyncProxyResolverFactory(true);
2389 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
2391 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2392 service.SetProxyScriptFetchers(
2393 fetcher, make_scoped_ptr(new DoNothingDhcpProxyScriptFetcher()));
2395 // Start 1 requests.
2397 ProxyInfo info1;
2398 TestCompletionCallback callback1;
2399 int rv =
2400 service.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL, &info1,
2401 callback1.callback(), NULL, NULL, BoundNetLog());
2402 EXPECT_EQ(ERR_IO_PENDING, rv);
2404 // Check that nothing has been sent to the proxy resolver factory yet.
2405 ASSERT_EQ(0u, factory->pending_requests().size());
2407 // It should be trying to auto-detect first -- succeed the download.
2408 EXPECT_TRUE(fetcher->has_pending_request());
2409 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
2410 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2412 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2413 factory->pending_requests()[0]->script_data()->utf16());
2414 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2416 ASSERT_EQ(1u, resolver.pending_requests().size());
2417 EXPECT_EQ(GURL("http://www.google.com"),
2418 resolver.pending_requests()[0]->url());
2420 // Complete the pending request.
2421 resolver.pending_requests()[0]->results()->UseNamedProxy("request1:80");
2422 resolver.pending_requests()[0]->CompleteNow(OK);
2424 // Verify that request ran as expected.
2425 EXPECT_EQ(OK, callback1.WaitForResult());
2426 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2428 // Start another request, it should pickup the bypass item.
2429 ProxyInfo info2;
2430 TestCompletionCallback callback2;
2431 rv = service.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL, &info2,
2432 callback2.callback(), NULL, NULL, BoundNetLog());
2433 EXPECT_EQ(ERR_IO_PENDING, rv);
2435 ASSERT_EQ(1u, resolver.pending_requests().size());
2436 EXPECT_EQ(GURL("http://www.google.com"),
2437 resolver.pending_requests()[0]->url());
2439 // Complete the pending request.
2440 resolver.pending_requests()[0]->results()->UseNamedProxy("request2:80");
2441 resolver.pending_requests()[0]->CompleteNow(OK);
2443 EXPECT_EQ(OK, callback2.WaitForResult());
2444 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2447 // Delete the ProxyService while InitProxyResolver has an outstanding
2448 // request to the script fetcher. When run under valgrind, should not
2449 // have any memory errors (used to be that the ProxyScriptFetcher was
2450 // being deleted prior to the InitProxyResolver).
2451 TEST_F(ProxyServiceTest, DeleteWhileInitProxyResolverHasOutstandingFetch) {
2452 ProxyConfig config =
2453 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"));
2455 MockProxyConfigService* config_service = new MockProxyConfigService(config);
2456 MockAsyncProxyResolverFactory* factory =
2457 new MockAsyncProxyResolverFactory(true);
2458 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
2460 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2461 service.SetProxyScriptFetchers(
2462 fetcher, make_scoped_ptr(new DoNothingDhcpProxyScriptFetcher()));
2464 // Start 1 request.
2466 ProxyInfo info1;
2467 TestCompletionCallback callback1;
2468 int rv =
2469 service.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL, &info1,
2470 callback1.callback(), NULL, NULL, BoundNetLog());
2471 EXPECT_EQ(ERR_IO_PENDING, rv);
2473 // Check that nothing has been sent to the proxy resolver factory yet.
2474 ASSERT_EQ(0u, factory->pending_requests().size());
2476 // InitProxyResolver should have issued a request to the ProxyScriptFetcher
2477 // and be waiting on that to complete.
2478 EXPECT_TRUE(fetcher->has_pending_request());
2479 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2482 // Delete the ProxyService while InitProxyResolver has an outstanding
2483 // request to the proxy resolver. When run under valgrind, should not
2484 // have any memory errors (used to be that the ProxyResolver was
2485 // being deleted prior to the InitProxyResolver).
2486 TEST_F(ProxyServiceTest, DeleteWhileInitProxyResolverHasOutstandingSet) {
2487 MockProxyConfigService* config_service =
2488 new MockProxyConfigService("http://foopy/proxy.pac");
2490 MockAsyncProxyResolverFactory* factory =
2491 new MockAsyncProxyResolverFactory(false);
2493 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
2495 GURL url("http://www.google.com/");
2497 ProxyInfo info;
2498 TestCompletionCallback callback;
2499 int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(),
2500 NULL, NULL, BoundNetLog());
2501 EXPECT_EQ(ERR_IO_PENDING, rv);
2503 EXPECT_EQ(GURL("http://foopy/proxy.pac"),
2504 factory->pending_requests()[0]->script_data()->url());
2507 TEST_F(ProxyServiceTest, ResetProxyConfigService) {
2508 ProxyConfig config1;
2509 config1.proxy_rules().ParseFromString("foopy1:8080");
2510 config1.set_auto_detect(false);
2511 ProxyService service(new MockProxyConfigService(config1), nullptr, NULL);
2513 ProxyInfo info;
2514 TestCompletionCallback callback1;
2515 int rv =
2516 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info,
2517 callback1.callback(), NULL, NULL, BoundNetLog());
2518 EXPECT_EQ(OK, rv);
2519 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
2521 ProxyConfig config2;
2522 config2.proxy_rules().ParseFromString("foopy2:8080");
2523 config2.set_auto_detect(false);
2524 service.ResetConfigService(new MockProxyConfigService(config2));
2525 TestCompletionCallback callback2;
2526 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info,
2527 callback2.callback(), NULL, NULL, BoundNetLog());
2528 EXPECT_EQ(OK, rv);
2529 EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI());
2532 // Test that when going from a configuration that required PAC to one
2533 // that does NOT, we unset the variable |should_use_proxy_resolver_|.
2534 TEST_F(ProxyServiceTest, UpdateConfigFromPACToDirect) {
2535 ProxyConfig config = ProxyConfig::CreateAutoDetect();
2537 MockProxyConfigService* config_service = new MockProxyConfigService(config);
2538 MockAsyncProxyResolver resolver;
2539 MockAsyncProxyResolverFactory* factory =
2540 new MockAsyncProxyResolverFactory(false);
2541 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
2543 // Start 1 request.
2545 ProxyInfo info1;
2546 TestCompletionCallback callback1;
2547 int rv =
2548 service.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL, &info1,
2549 callback1.callback(), NULL, NULL, BoundNetLog());
2550 EXPECT_EQ(ERR_IO_PENDING, rv);
2552 // Successfully set the autodetect script.
2553 EXPECT_EQ(ProxyResolverScriptData::TYPE_AUTO_DETECT,
2554 factory->pending_requests()[0]->script_data()->type());
2555 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2557 // Complete the pending request.
2558 ASSERT_EQ(1u, resolver.pending_requests().size());
2559 resolver.pending_requests()[0]->results()->UseNamedProxy("request1:80");
2560 resolver.pending_requests()[0]->CompleteNow(OK);
2562 // Verify that request ran as expected.
2563 EXPECT_EQ(OK, callback1.WaitForResult());
2564 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2566 // Force the ProxyService to pull down a new proxy configuration.
2567 // (Even though the configuration isn't old/bad).
2569 // This new configuration no longer has auto_detect set, so
2570 // requests should complete synchronously now as direct-connect.
2571 config_service->SetConfig(ProxyConfig::CreateDirect());
2573 // Start another request -- the effective configuration has changed.
2574 ProxyInfo info2;
2575 TestCompletionCallback callback2;
2576 rv = service.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL, &info2,
2577 callback2.callback(), NULL, NULL, BoundNetLog());
2578 EXPECT_EQ(OK, rv);
2580 EXPECT_TRUE(info2.is_direct());
2583 TEST_F(ProxyServiceTest, NetworkChangeTriggersPacRefetch) {
2584 MockProxyConfigService* config_service =
2585 new MockProxyConfigService("http://foopy/proxy.pac");
2587 MockAsyncProxyResolver resolver;
2588 MockAsyncProxyResolverFactory* factory =
2589 new MockAsyncProxyResolverFactory(true);
2591 TestNetLog log;
2593 ProxyService service(config_service, make_scoped_ptr(factory), &log);
2595 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2596 service.SetProxyScriptFetchers(
2597 fetcher, make_scoped_ptr(new DoNothingDhcpProxyScriptFetcher()));
2599 // Disable the "wait after IP address changes" hack, so this unit-test can
2600 // complete quickly.
2601 service.set_stall_proxy_auto_config_delay(base::TimeDelta());
2603 // Start 1 request.
2605 ProxyInfo info1;
2606 TestCompletionCallback callback1;
2607 int rv =
2608 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
2609 callback1.callback(), NULL, NULL, BoundNetLog());
2610 EXPECT_EQ(ERR_IO_PENDING, rv);
2612 // The first request should have triggered initial download of PAC script.
2613 EXPECT_TRUE(fetcher->has_pending_request());
2614 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2616 // Nothing has been sent to the factory yet.
2617 EXPECT_TRUE(factory->pending_requests().empty());
2619 // At this point the ProxyService should be waiting for the
2620 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2621 // PAC script download completion.
2622 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2624 // Now that the PAC script is downloaded, the request will have been sent to
2625 // the proxy resolver.
2626 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2627 factory->pending_requests()[0]->script_data()->utf16());
2628 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2630 ASSERT_EQ(1u, resolver.pending_requests().size());
2631 EXPECT_EQ(GURL("http://request1"), resolver.pending_requests()[0]->url());
2633 // Complete the pending request.
2634 resolver.pending_requests()[0]->results()->UseNamedProxy("request1:80");
2635 resolver.pending_requests()[0]->CompleteNow(OK);
2637 // Wait for completion callback, and verify that the request ran as expected.
2638 EXPECT_EQ(OK, callback1.WaitForResult());
2639 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2641 // Now simluate a change in the network. The ProxyConfigService is still
2642 // going to return the same PAC URL as before, but this URL needs to be
2643 // refetched on the new network.
2644 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
2645 base::MessageLoop::current()->RunUntilIdle(); // Notification happens async.
2647 // Start a second request.
2648 ProxyInfo info2;
2649 TestCompletionCallback callback2;
2650 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
2651 callback2.callback(), NULL, NULL, BoundNetLog());
2652 EXPECT_EQ(ERR_IO_PENDING, rv);
2654 // This second request should have triggered the re-download of the PAC
2655 // script (since we marked the network as having changed).
2656 EXPECT_TRUE(fetcher->has_pending_request());
2657 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2659 // Nothing has been sent to the factory yet.
2660 EXPECT_TRUE(factory->pending_requests().empty());
2662 // Simulate the PAC script fetch as having completed (this time with
2663 // different data).
2664 fetcher->NotifyFetchCompletion(OK, kValidPacScript2);
2666 // Now that the PAC script is downloaded, the second request will have been
2667 // sent to the proxy resolver.
2668 EXPECT_EQ(ASCIIToUTF16(kValidPacScript2),
2669 factory->pending_requests()[0]->script_data()->utf16());
2670 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2672 ASSERT_EQ(1u, resolver.pending_requests().size());
2673 EXPECT_EQ(GURL("http://request2"), resolver.pending_requests()[0]->url());
2675 // Complete the pending second request.
2676 resolver.pending_requests()[0]->results()->UseNamedProxy("request2:80");
2677 resolver.pending_requests()[0]->CompleteNow(OK);
2679 // Wait for completion callback, and verify that the request ran as expected.
2680 EXPECT_EQ(OK, callback2.WaitForResult());
2681 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2683 // Check that the expected events were output to the log stream. In particular
2684 // PROXY_CONFIG_CHANGED should have only been emitted once (for the initial
2685 // setup), and NOT a second time when the IP address changed.
2686 TestNetLogEntry::List entries;
2687 log.GetEntries(&entries);
2689 EXPECT_TRUE(LogContainsEntryWithType(entries, 0,
2690 NetLog::TYPE_PROXY_CONFIG_CHANGED));
2691 ASSERT_EQ(9u, entries.size());
2692 for (size_t i = 1; i < entries.size(); ++i)
2693 EXPECT_NE(NetLog::TYPE_PROXY_CONFIG_CHANGED, entries[i].type);
2696 // This test verifies that the PAC script specified by the settings is
2697 // periodically polled for changes. Specifically, if the initial fetch fails due
2698 // to a network error, we will eventually re-configure the service to use the
2699 // script once it becomes available.
2700 TEST_F(ProxyServiceTest, PACScriptRefetchAfterFailure) {
2701 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2702 // runs quickly.
2703 ImmediatePollPolicy poll_policy;
2704 ProxyService::set_pac_script_poll_policy(&poll_policy);
2706 MockProxyConfigService* config_service =
2707 new MockProxyConfigService("http://foopy/proxy.pac");
2709 MockAsyncProxyResolver resolver;
2710 MockAsyncProxyResolverFactory* factory =
2711 new MockAsyncProxyResolverFactory(true);
2713 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
2715 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2716 service.SetProxyScriptFetchers(
2717 fetcher, make_scoped_ptr(new DoNothingDhcpProxyScriptFetcher()));
2719 // Start 1 request.
2721 ProxyInfo info1;
2722 TestCompletionCallback callback1;
2723 int rv =
2724 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
2725 callback1.callback(), NULL, NULL, BoundNetLog());
2726 EXPECT_EQ(ERR_IO_PENDING, rv);
2728 // The first request should have triggered initial download of PAC script.
2729 EXPECT_TRUE(fetcher->has_pending_request());
2730 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2732 // Nothing has been sent to the factory yet.
2733 EXPECT_TRUE(factory->pending_requests().empty());
2735 // At this point the ProxyService should be waiting for the
2736 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2737 // PAC script download completion.
2739 // We simulate a failed download attempt, the proxy service should now
2740 // fall-back to DIRECT connections.
2741 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
2743 ASSERT_TRUE(factory->pending_requests().empty());
2745 // Wait for completion callback, and verify it used DIRECT.
2746 EXPECT_EQ(OK, callback1.WaitForResult());
2747 EXPECT_TRUE(info1.is_direct());
2749 // At this point we have initialized the proxy service using a PAC script,
2750 // however it failed and fell-back to DIRECT.
2752 // A background task to periodically re-check the PAC script for validity will
2753 // have been started. We will now wait for the next download attempt to start.
2755 // Note that we shouldn't have to wait long here, since our test enables a
2756 // special unit-test mode.
2757 fetcher->WaitUntilFetch();
2759 ASSERT_TRUE(factory->pending_requests().empty());
2761 // Make sure that our background checker is trying to download the expected
2762 // PAC script (same one as before). This time we will simulate a successful
2763 // download of the script.
2764 EXPECT_TRUE(fetcher->has_pending_request());
2765 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2766 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2768 base::MessageLoop::current()->RunUntilIdle();
2770 // Now that the PAC script is downloaded, it should be used to initialize the
2771 // ProxyResolver. Simulate a successful parse.
2772 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2773 factory->pending_requests()[0]->script_data()->utf16());
2774 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2776 // At this point the ProxyService should have re-configured itself to use the
2777 // PAC script (thereby recovering from the initial fetch failure). We will
2778 // verify that the next Resolve request uses the resolver rather than
2779 // DIRECT.
2781 // Start a second request.
2782 ProxyInfo info2;
2783 TestCompletionCallback callback2;
2784 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
2785 callback2.callback(), NULL, NULL, BoundNetLog());
2786 EXPECT_EQ(ERR_IO_PENDING, rv);
2788 // Check that it was sent to the resolver.
2789 ASSERT_EQ(1u, resolver.pending_requests().size());
2790 EXPECT_EQ(GURL("http://request2"), resolver.pending_requests()[0]->url());
2792 // Complete the pending second request.
2793 resolver.pending_requests()[0]->results()->UseNamedProxy("request2:80");
2794 resolver.pending_requests()[0]->CompleteNow(OK);
2796 // Wait for completion callback, and verify that the request ran as expected.
2797 EXPECT_EQ(OK, callback2.WaitForResult());
2798 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2801 // This test verifies that the PAC script specified by the settings is
2802 // periodically polled for changes. Specifically, if the initial fetch succeeds,
2803 // however at a later time its *contents* change, we will eventually
2804 // re-configure the service to use the new script.
2805 TEST_F(ProxyServiceTest, PACScriptRefetchAfterContentChange) {
2806 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2807 // runs quickly.
2808 ImmediatePollPolicy poll_policy;
2809 ProxyService::set_pac_script_poll_policy(&poll_policy);
2811 MockProxyConfigService* config_service =
2812 new MockProxyConfigService("http://foopy/proxy.pac");
2814 MockAsyncProxyResolver resolver;
2815 MockAsyncProxyResolverFactory* factory =
2816 new MockAsyncProxyResolverFactory(true);
2818 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
2820 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2821 service.SetProxyScriptFetchers(
2822 fetcher, make_scoped_ptr(new DoNothingDhcpProxyScriptFetcher()));
2824 // Start 1 request.
2826 ProxyInfo info1;
2827 TestCompletionCallback callback1;
2828 int rv =
2829 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
2830 callback1.callback(), NULL, NULL, BoundNetLog());
2831 EXPECT_EQ(ERR_IO_PENDING, rv);
2833 // The first request should have triggered initial download of PAC script.
2834 EXPECT_TRUE(fetcher->has_pending_request());
2835 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2837 // Nothing has been sent to the factory yet.
2838 EXPECT_TRUE(factory->pending_requests().empty());
2840 // At this point the ProxyService should be waiting for the
2841 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2842 // PAC script download completion.
2843 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2845 // Now that the PAC script is downloaded, the request will have been sent to
2846 // the proxy resolver.
2847 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2848 factory->pending_requests()[0]->script_data()->utf16());
2849 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2851 ASSERT_EQ(1u, resolver.pending_requests().size());
2852 EXPECT_EQ(GURL("http://request1"), resolver.pending_requests()[0]->url());
2854 // Complete the pending request.
2855 resolver.pending_requests()[0]->results()->UseNamedProxy("request1:80");
2856 resolver.pending_requests()[0]->CompleteNow(OK);
2858 // Wait for completion callback, and verify that the request ran as expected.
2859 EXPECT_EQ(OK, callback1.WaitForResult());
2860 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2862 // At this point we have initialized the proxy service using a PAC script.
2864 // A background task to periodically re-check the PAC script for validity will
2865 // have been started. We will now wait for the next download attempt to start.
2867 // Note that we shouldn't have to wait long here, since our test enables a
2868 // special unit-test mode.
2869 fetcher->WaitUntilFetch();
2871 ASSERT_TRUE(factory->pending_requests().empty());
2872 ASSERT_TRUE(resolver.pending_requests().empty());
2874 // Make sure that our background checker is trying to download the expected
2875 // PAC script (same one as before). This time we will simulate a successful
2876 // download of a DIFFERENT script.
2877 EXPECT_TRUE(fetcher->has_pending_request());
2878 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2879 fetcher->NotifyFetchCompletion(OK, kValidPacScript2);
2881 base::MessageLoop::current()->RunUntilIdle();
2883 // Now that the PAC script is downloaded, it should be used to initialize the
2884 // ProxyResolver. Simulate a successful parse.
2885 EXPECT_EQ(ASCIIToUTF16(kValidPacScript2),
2886 factory->pending_requests()[0]->script_data()->utf16());
2887 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2889 // At this point the ProxyService should have re-configured itself to use the
2890 // new PAC script.
2892 // Start a second request.
2893 ProxyInfo info2;
2894 TestCompletionCallback callback2;
2895 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
2896 callback2.callback(), NULL, NULL, BoundNetLog());
2897 EXPECT_EQ(ERR_IO_PENDING, rv);
2899 // Check that it was sent to the resolver.
2900 ASSERT_EQ(1u, resolver.pending_requests().size());
2901 EXPECT_EQ(GURL("http://request2"), resolver.pending_requests()[0]->url());
2903 // Complete the pending second request.
2904 resolver.pending_requests()[0]->results()->UseNamedProxy("request2:80");
2905 resolver.pending_requests()[0]->CompleteNow(OK);
2907 // Wait for completion callback, and verify that the request ran as expected.
2908 EXPECT_EQ(OK, callback2.WaitForResult());
2909 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
2912 // This test verifies that the PAC script specified by the settings is
2913 // periodically polled for changes. Specifically, if the initial fetch succeeds
2914 // and so does the next poll, however the contents of the downloaded script
2915 // have NOT changed, then we do not bother to re-initialize the proxy resolver.
2916 TEST_F(ProxyServiceTest, PACScriptRefetchAfterContentUnchanged) {
2917 // Change the retry policy to wait a mere 1 ms before retrying, so the test
2918 // runs quickly.
2919 ImmediatePollPolicy poll_policy;
2920 ProxyService::set_pac_script_poll_policy(&poll_policy);
2922 MockProxyConfigService* config_service =
2923 new MockProxyConfigService("http://foopy/proxy.pac");
2925 MockAsyncProxyResolver resolver;
2926 MockAsyncProxyResolverFactory* factory =
2927 new MockAsyncProxyResolverFactory(true);
2929 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
2931 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
2932 service.SetProxyScriptFetchers(
2933 fetcher, make_scoped_ptr(new DoNothingDhcpProxyScriptFetcher()));
2935 // Start 1 request.
2937 ProxyInfo info1;
2938 TestCompletionCallback callback1;
2939 int rv =
2940 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
2941 callback1.callback(), NULL, NULL, BoundNetLog());
2942 EXPECT_EQ(ERR_IO_PENDING, rv);
2944 // The first request should have triggered initial download of PAC script.
2945 EXPECT_TRUE(fetcher->has_pending_request());
2946 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2948 // Nothing has been sent to the factory yet.
2949 EXPECT_TRUE(factory->pending_requests().empty());
2951 // At this point the ProxyService should be waiting for the
2952 // ProxyScriptFetcher to invoke its completion callback, notifying it of
2953 // PAC script download completion.
2954 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2956 // Now that the PAC script is downloaded, the request will have been sent to
2957 // the proxy resolver.
2958 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
2959 factory->pending_requests()[0]->script_data()->utf16());
2960 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2962 ASSERT_EQ(1u, resolver.pending_requests().size());
2963 EXPECT_EQ(GURL("http://request1"), resolver.pending_requests()[0]->url());
2965 // Complete the pending request.
2966 resolver.pending_requests()[0]->results()->UseNamedProxy("request1:80");
2967 resolver.pending_requests()[0]->CompleteNow(OK);
2969 // Wait for completion callback, and verify that the request ran as expected.
2970 EXPECT_EQ(OK, callback1.WaitForResult());
2971 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
2973 // At this point we have initialized the proxy service using a PAC script.
2975 // A background task to periodically re-check the PAC script for validity will
2976 // have been started. We will now wait for the next download attempt to start.
2978 // Note that we shouldn't have to wait long here, since our test enables a
2979 // special unit-test mode.
2980 fetcher->WaitUntilFetch();
2982 ASSERT_TRUE(factory->pending_requests().empty());
2983 ASSERT_TRUE(resolver.pending_requests().empty());
2985 // Make sure that our background checker is trying to download the expected
2986 // PAC script (same one as before). We will simulate the same response as
2987 // last time (i.e. the script is unchanged).
2988 EXPECT_TRUE(fetcher->has_pending_request());
2989 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
2990 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
2992 base::MessageLoop::current()->RunUntilIdle();
2994 ASSERT_TRUE(factory->pending_requests().empty());
2995 ASSERT_TRUE(resolver.pending_requests().empty());
2997 // At this point the ProxyService is still running the same PAC script as
2998 // before.
3000 // Start a second request.
3001 ProxyInfo info2;
3002 TestCompletionCallback callback2;
3003 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
3004 callback2.callback(), NULL, NULL, BoundNetLog());
3005 EXPECT_EQ(ERR_IO_PENDING, rv);
3007 // Check that it was sent to the resolver.
3008 ASSERT_EQ(1u, resolver.pending_requests().size());
3009 EXPECT_EQ(GURL("http://request2"), resolver.pending_requests()[0]->url());
3011 // Complete the pending second request.
3012 resolver.pending_requests()[0]->results()->UseNamedProxy("request2:80");
3013 resolver.pending_requests()[0]->CompleteNow(OK);
3015 // Wait for completion callback, and verify that the request ran as expected.
3016 EXPECT_EQ(OK, callback2.WaitForResult());
3017 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
3020 // This test verifies that the PAC script specified by the settings is
3021 // periodically polled for changes. Specifically, if the initial fetch succeeds,
3022 // however at a later time it starts to fail, we should re-configure the
3023 // ProxyService to stop using that PAC script.
3024 TEST_F(ProxyServiceTest, PACScriptRefetchAfterSuccess) {
3025 // Change the retry policy to wait a mere 1 ms before retrying, so the test
3026 // runs quickly.
3027 ImmediatePollPolicy poll_policy;
3028 ProxyService::set_pac_script_poll_policy(&poll_policy);
3030 MockProxyConfigService* config_service =
3031 new MockProxyConfigService("http://foopy/proxy.pac");
3033 MockAsyncProxyResolver resolver;
3034 MockAsyncProxyResolverFactory* factory =
3035 new MockAsyncProxyResolverFactory(true);
3037 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
3039 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
3040 service.SetProxyScriptFetchers(
3041 fetcher, make_scoped_ptr(new DoNothingDhcpProxyScriptFetcher()));
3043 // Start 1 request.
3045 ProxyInfo info1;
3046 TestCompletionCallback callback1;
3047 int rv =
3048 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
3049 callback1.callback(), NULL, NULL, BoundNetLog());
3050 EXPECT_EQ(ERR_IO_PENDING, rv);
3052 // The first request should have triggered initial download of PAC script.
3053 EXPECT_TRUE(fetcher->has_pending_request());
3054 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
3056 // Nothing has been sent to the factory yet.
3057 EXPECT_TRUE(factory->pending_requests().empty());
3059 // At this point the ProxyService should be waiting for the
3060 // ProxyScriptFetcher to invoke its completion callback, notifying it of
3061 // PAC script download completion.
3062 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
3064 // Now that the PAC script is downloaded, the request will have been sent to
3065 // the proxy resolver.
3066 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
3067 factory->pending_requests()[0]->script_data()->utf16());
3068 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
3070 ASSERT_EQ(1u, resolver.pending_requests().size());
3071 EXPECT_EQ(GURL("http://request1"), resolver.pending_requests()[0]->url());
3073 // Complete the pending request.
3074 resolver.pending_requests()[0]->results()->UseNamedProxy("request1:80");
3075 resolver.pending_requests()[0]->CompleteNow(OK);
3077 // Wait for completion callback, and verify that the request ran as expected.
3078 EXPECT_EQ(OK, callback1.WaitForResult());
3079 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
3081 // At this point we have initialized the proxy service using a PAC script.
3083 // A background task to periodically re-check the PAC script for validity will
3084 // have been started. We will now wait for the next download attempt to start.
3086 // Note that we shouldn't have to wait long here, since our test enables a
3087 // special unit-test mode.
3088 fetcher->WaitUntilFetch();
3090 ASSERT_TRUE(factory->pending_requests().empty());
3091 ASSERT_TRUE(resolver.pending_requests().empty());
3093 // Make sure that our background checker is trying to download the expected
3094 // PAC script (same one as before). This time we will simulate a failure
3095 // to download the script.
3096 EXPECT_TRUE(fetcher->has_pending_request());
3097 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
3098 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
3100 base::MessageLoop::current()->RunUntilIdle();
3102 // At this point the ProxyService should have re-configured itself to use
3103 // DIRECT connections rather than the given proxy resolver.
3105 // Start a second request.
3106 ProxyInfo info2;
3107 TestCompletionCallback callback2;
3108 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
3109 callback2.callback(), NULL, NULL, BoundNetLog());
3110 EXPECT_EQ(OK, rv);
3111 EXPECT_TRUE(info2.is_direct());
3114 // Tests that the code which decides at what times to poll the PAC
3115 // script follows the expected policy.
3116 TEST_F(ProxyServiceTest, PACScriptPollingPolicy) {
3117 // Retrieve the internal polling policy implementation used by ProxyService.
3118 scoped_ptr<ProxyService::PacPollPolicy> policy =
3119 ProxyService::CreateDefaultPacPollPolicy();
3121 int error;
3122 ProxyService::PacPollPolicy::Mode mode;
3123 const base::TimeDelta initial_delay = base::TimeDelta::FromMilliseconds(-1);
3124 base::TimeDelta delay = initial_delay;
3126 // --------------------------------------------------
3127 // Test the poll sequence in response to a failure.
3128 // --------------------------------------------------
3129 error = ERR_NAME_NOT_RESOLVED;
3131 // Poll #0
3132 mode = policy->GetNextDelay(error, initial_delay, &delay);
3133 EXPECT_EQ(8, delay.InSeconds());
3134 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_USE_TIMER, mode);
3136 // Poll #1
3137 mode = policy->GetNextDelay(error, delay, &delay);
3138 EXPECT_EQ(32, delay.InSeconds());
3139 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
3141 // Poll #2
3142 mode = policy->GetNextDelay(error, delay, &delay);
3143 EXPECT_EQ(120, delay.InSeconds());
3144 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
3146 // Poll #3
3147 mode = policy->GetNextDelay(error, delay, &delay);
3148 EXPECT_EQ(14400, delay.InSeconds());
3149 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
3151 // Poll #4
3152 mode = policy->GetNextDelay(error, delay, &delay);
3153 EXPECT_EQ(14400, delay.InSeconds());
3154 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
3156 // --------------------------------------------------
3157 // Test the poll sequence in response to a success.
3158 // --------------------------------------------------
3159 error = OK;
3161 // Poll #0
3162 mode = policy->GetNextDelay(error, initial_delay, &delay);
3163 EXPECT_EQ(43200, delay.InSeconds());
3164 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
3166 // Poll #1
3167 mode = policy->GetNextDelay(error, delay, &delay);
3168 EXPECT_EQ(43200, delay.InSeconds());
3169 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
3171 // Poll #2
3172 mode = policy->GetNextDelay(error, delay, &delay);
3173 EXPECT_EQ(43200, delay.InSeconds());
3174 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode);
3177 // This tests the polling of the PAC script. Specifically, it tests that
3178 // polling occurs in response to user activity.
3179 TEST_F(ProxyServiceTest, PACScriptRefetchAfterActivity) {
3180 ImmediateAfterActivityPollPolicy poll_policy;
3181 ProxyService::set_pac_script_poll_policy(&poll_policy);
3183 MockProxyConfigService* config_service =
3184 new MockProxyConfigService("http://foopy/proxy.pac");
3186 MockAsyncProxyResolver resolver;
3187 MockAsyncProxyResolverFactory* factory =
3188 new MockAsyncProxyResolverFactory(true);
3190 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
3192 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
3193 service.SetProxyScriptFetchers(
3194 fetcher, make_scoped_ptr(new DoNothingDhcpProxyScriptFetcher()));
3196 // Start 1 request.
3198 ProxyInfo info1;
3199 TestCompletionCallback callback1;
3200 int rv =
3201 service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1,
3202 callback1.callback(), NULL, NULL, BoundNetLog());
3203 EXPECT_EQ(ERR_IO_PENDING, rv);
3205 // The first request should have triggered initial download of PAC script.
3206 EXPECT_TRUE(fetcher->has_pending_request());
3207 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
3209 // Nothing has been sent to the factory yet.
3210 EXPECT_TRUE(factory->pending_requests().empty());
3212 // At this point the ProxyService should be waiting for the
3213 // ProxyScriptFetcher to invoke its completion callback, notifying it of
3214 // PAC script download completion.
3215 fetcher->NotifyFetchCompletion(OK, kValidPacScript1);
3217 // Now that the PAC script is downloaded, the request will have been sent to
3218 // the proxy resolver.
3219 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1),
3220 factory->pending_requests()[0]->script_data()->utf16());
3221 factory->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
3223 ASSERT_EQ(1u, resolver.pending_requests().size());
3224 EXPECT_EQ(GURL("http://request1"), resolver.pending_requests()[0]->url());
3226 // Complete the pending request.
3227 resolver.pending_requests()[0]->results()->UseNamedProxy("request1:80");
3228 resolver.pending_requests()[0]->CompleteNow(OK);
3230 // Wait for completion callback, and verify that the request ran as expected.
3231 EXPECT_EQ(OK, callback1.WaitForResult());
3232 EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
3234 // At this point we have initialized the proxy service using a PAC script.
3235 // Our PAC poller is set to update ONLY in response to network activity,
3236 // (i.e. another call to ResolveProxy()).
3238 ASSERT_FALSE(fetcher->has_pending_request());
3239 ASSERT_TRUE(factory->pending_requests().empty());
3240 ASSERT_TRUE(resolver.pending_requests().empty());
3242 // Start a second request.
3243 ProxyInfo info2;
3244 TestCompletionCallback callback2;
3245 rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2,
3246 callback2.callback(), NULL, NULL, BoundNetLog());
3247 EXPECT_EQ(ERR_IO_PENDING, rv);
3249 // This request should have sent work to the resolver; complete it.
3250 ASSERT_EQ(1u, resolver.pending_requests().size());
3251 EXPECT_EQ(GURL("http://request2"), resolver.pending_requests()[0]->url());
3252 resolver.pending_requests()[0]->results()->UseNamedProxy("request2:80");
3253 resolver.pending_requests()[0]->CompleteNow(OK);
3255 EXPECT_EQ(OK, callback2.WaitForResult());
3256 EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
3258 // In response to getting that resolve request, the poller should have
3259 // started the next poll, and made it as far as to request the download.
3261 EXPECT_TRUE(fetcher->has_pending_request());
3262 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
3264 // This time we will fail the download, to simulate a PAC script change.
3265 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string());
3267 // Drain the message loop, so ProxyService is notified of the change
3268 // and has a chance to re-configure itself.
3269 base::MessageLoop::current()->RunUntilIdle();
3271 // Start a third request -- this time we expect to get a direct connection
3272 // since the PAC script poller experienced a failure.
3273 ProxyInfo info3;
3274 TestCompletionCallback callback3;
3275 rv = service.ResolveProxy(GURL("http://request3"), LOAD_NORMAL, &info3,
3276 callback3.callback(), NULL, NULL, BoundNetLog());
3277 EXPECT_EQ(OK, rv);
3278 EXPECT_TRUE(info3.is_direct());
3281 // Test that the synchronous resolution fails when a PAC script is active.
3282 TEST_F(ProxyServiceTest, SynchronousWithPAC) {
3283 MockProxyConfigService* config_service =
3284 new MockProxyConfigService("http://foopy/proxy.pac");
3286 MockAsyncProxyResolverFactory* factory =
3287 new MockAsyncProxyResolverFactory(false);
3289 ProxyService service(config_service, make_scoped_ptr(factory), NULL);
3291 GURL url("http://www.google.com/");
3293 ProxyInfo info;
3294 info.UseDirect();
3295 BoundTestNetLog log;
3297 bool synchronous_success = service.TryResolveProxySynchronously(
3298 url, LOAD_NORMAL, &info, NULL, log.bound());
3299 EXPECT_FALSE(synchronous_success);
3301 // |info| should not have been modified.
3302 EXPECT_TRUE(info.is_direct());
3305 // Test that synchronous results are returned correctly if a fixed proxy
3306 // configuration is active.
3307 TEST_F(ProxyServiceTest, SynchronousWithFixedConfiguration) {
3308 ProxyConfig config;
3309 config.proxy_rules().ParseFromString("foopy1:8080");
3310 config.set_auto_detect(false);
3312 MockAsyncProxyResolverFactory* factory =
3313 new MockAsyncProxyResolverFactory(false);
3315 ProxyService service(new MockProxyConfigService(config),
3316 make_scoped_ptr(factory), NULL);
3318 GURL url("http://www.google.com/");
3320 ProxyInfo info;
3321 BoundTestNetLog log;
3323 bool synchronous_success = service.TryResolveProxySynchronously(
3324 url, LOAD_NORMAL, &info, NULL, log.bound());
3325 EXPECT_TRUE(synchronous_success);
3326 EXPECT_FALSE(info.is_direct());
3327 EXPECT_EQ("foopy1", info.proxy_server().host_port_pair().host());
3329 // No request should have been queued.
3330 EXPECT_EQ(0u, factory->pending_requests().size());
3333 } // namespace net