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