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