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