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