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