Home | History | Annotate | Download | only in proxy
      1 // Copyright (c) 2011 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/string_util.h"
     12 #include "base/utf_string_conversions.h"
     13 #include "googleurl/src/gurl.h"
     14 #include "net/base/net_errors.h"
     15 #include "net/base/net_log.h"
     16 #include "net/base/net_log_unittest.h"
     17 #include "net/base/test_completion_callback.h"
     18 #include "net/proxy/mock_proxy_resolver.h"
     19 #include "net/proxy/proxy_config_service.h"
     20 #include "net/proxy/proxy_resolver.h"
     21 #include "net/proxy/proxy_script_fetcher.h"
     22 #include "testing/gtest/include/gtest/gtest.h"
     23 
     24 // TODO(eroman): Write a test which exercises
     25 //              ProxyService::SuspendAllPendingRequests().
     26 namespace net {
     27 namespace {
     28 
     29 class MockProxyConfigService: public ProxyConfigService {
     30  public:
     31   explicit MockProxyConfigService(const ProxyConfig& config)
     32       : availability_(CONFIG_VALID),
     33         config_(config) {
     34   }
     35 
     36   explicit MockProxyConfigService(const std::string& pac_url)
     37       : availability_(CONFIG_VALID),
     38         config_(ProxyConfig::CreateFromCustomPacURL(GURL(pac_url))) {
     39   }
     40 
     41   virtual void AddObserver(Observer* observer) {
     42     observers_.AddObserver(observer);
     43   }
     44 
     45   virtual void RemoveObserver(Observer* observer) {
     46     observers_.RemoveObserver(observer);
     47   }
     48 
     49   virtual ConfigAvailability GetLatestProxyConfig(ProxyConfig* results) {
     50     if (availability_ == CONFIG_VALID)
     51       *results = config_;
     52     return availability_;
     53   }
     54 
     55   void SetConfig(const ProxyConfig& config) {
     56     availability_ = CONFIG_VALID;
     57     config_ = config;
     58     FOR_EACH_OBSERVER(Observer, observers_,
     59                       OnProxyConfigChanged(config_, availability_));
     60   }
     61 
     62  private:
     63   ConfigAvailability availability_;
     64   ProxyConfig config_;
     65   ObserverList<Observer, true> observers_;
     66 };
     67 
     68 }  // namespace
     69 
     70 // A mock ProxyScriptFetcher. No result will be returned to the fetch client
     71 // until we call NotifyFetchCompletion() to set the results.
     72 class MockProxyScriptFetcher : public ProxyScriptFetcher {
     73  public:
     74   MockProxyScriptFetcher()
     75       : pending_request_callback_(NULL), pending_request_text_(NULL) {
     76   }
     77 
     78   // ProxyScriptFetcher implementation.
     79   virtual int Fetch(const GURL& url,
     80                     string16* text,
     81                     CompletionCallback* callback) {
     82     DCHECK(!has_pending_request());
     83 
     84     // Save the caller's information, and have them wait.
     85     pending_request_url_ = url;
     86     pending_request_callback_ = callback;
     87     pending_request_text_ = text;
     88     return ERR_IO_PENDING;
     89   }
     90 
     91   void NotifyFetchCompletion(int result, const std::string& ascii_text) {
     92     DCHECK(has_pending_request());
     93     *pending_request_text_ = ASCIIToUTF16(ascii_text);
     94     CompletionCallback* callback = pending_request_callback_;
     95     pending_request_callback_ = NULL;
     96     callback->Run(result);
     97   }
     98 
     99   virtual void Cancel() {}
    100 
    101   virtual URLRequestContext* GetRequestContext() { return NULL; }
    102 
    103   const GURL& pending_request_url() const {
    104     return pending_request_url_;
    105   }
    106 
    107   bool has_pending_request() const {
    108     return pending_request_callback_ != NULL;
    109   }
    110 
    111  private:
    112   GURL pending_request_url_;
    113   CompletionCallback* pending_request_callback_;
    114   string16* pending_request_text_;
    115 };
    116 
    117 TEST(ProxyServiceTest, Direct) {
    118   MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
    119   scoped_refptr<ProxyService> service(
    120       new ProxyService(new MockProxyConfigService(
    121           ProxyConfig::CreateDirect()), resolver, NULL));
    122 
    123   GURL url("http://www.google.com/");
    124 
    125   ProxyInfo info;
    126   TestCompletionCallback callback;
    127   CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
    128   int rv = service->ResolveProxy(url, &info, &callback, NULL, log.bound());
    129   EXPECT_EQ(OK, rv);
    130   EXPECT_TRUE(resolver->pending_requests().empty());
    131 
    132   EXPECT_TRUE(info.is_direct());
    133 
    134   // Check the NetLog was filled correctly.
    135   CapturingNetLog::EntryList entries;
    136   log.GetEntries(&entries);
    137 
    138   EXPECT_EQ(3u, entries.size());
    139   EXPECT_TRUE(LogContainsBeginEvent(
    140       entries, 0, NetLog::TYPE_PROXY_SERVICE));
    141   EXPECT_TRUE(LogContainsEvent(
    142       entries, 1, NetLog::TYPE_PROXY_SERVICE_RESOLVED_PROXY_LIST,
    143       NetLog::PHASE_NONE));
    144   EXPECT_TRUE(LogContainsEndEvent(
    145       entries, 2, NetLog::TYPE_PROXY_SERVICE));
    146 }
    147 
    148 TEST(ProxyServiceTest, PAC) {
    149   MockProxyConfigService* config_service =
    150       new MockProxyConfigService("http://foopy/proxy.pac");
    151 
    152   MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
    153 
    154   scoped_refptr<ProxyService> service(
    155       new ProxyService(config_service, resolver, NULL));
    156 
    157   GURL url("http://www.google.com/");
    158 
    159   ProxyInfo info;
    160   TestCompletionCallback callback;
    161   CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
    162 
    163   int rv = service->ResolveProxy(url, &info, &callback, NULL, log.bound());
    164   EXPECT_EQ(ERR_IO_PENDING, rv);
    165 
    166   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
    167             resolver->pending_set_pac_script_request()->script_data()->url());
    168   resolver->pending_set_pac_script_request()->CompleteNow(OK);
    169 
    170   ASSERT_EQ(1u, resolver->pending_requests().size());
    171   EXPECT_EQ(url, resolver->pending_requests()[0]->url());
    172 
    173   // Set the result in proxy resolver.
    174   resolver->pending_requests()[0]->results()->UseNamedProxy("foopy");
    175   resolver->pending_requests()[0]->CompleteNow(OK);
    176 
    177   EXPECT_EQ(OK, callback.WaitForResult());
    178   EXPECT_FALSE(info.is_direct());
    179   EXPECT_EQ("foopy:80", info.proxy_server().ToURI());
    180 
    181   // Check the NetLog was filled correctly.
    182   CapturingNetLog::EntryList entries;
    183   log.GetEntries(&entries);
    184 
    185   EXPECT_EQ(5u, entries.size());
    186   EXPECT_TRUE(LogContainsBeginEvent(
    187       entries, 0, NetLog::TYPE_PROXY_SERVICE));
    188   EXPECT_TRUE(LogContainsBeginEvent(
    189       entries, 1, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
    190   EXPECT_TRUE(LogContainsEndEvent(
    191       entries, 2, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
    192   EXPECT_TRUE(LogContainsEndEvent(
    193       entries, 4, NetLog::TYPE_PROXY_SERVICE));
    194 }
    195 
    196 // Test that the proxy resolver does not see the URL's username/password
    197 // or its reference section.
    198 TEST(ProxyServiceTest, PAC_NoIdentityOrHash) {
    199   MockProxyConfigService* config_service =
    200       new MockProxyConfigService("http://foopy/proxy.pac");
    201 
    202   MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
    203 
    204   scoped_refptr<ProxyService> service(
    205       new ProxyService(config_service, resolver, NULL));
    206 
    207   GURL url("http://username:password@www.google.com/?ref#hash#hash");
    208 
    209   ProxyInfo info;
    210   TestCompletionCallback callback;
    211   int rv = service->ResolveProxy(url, &info, &callback, NULL, BoundNetLog());
    212   EXPECT_EQ(ERR_IO_PENDING, rv);
    213 
    214   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
    215             resolver->pending_set_pac_script_request()->script_data()->url());
    216   resolver->pending_set_pac_script_request()->CompleteNow(OK);
    217 
    218   ASSERT_EQ(1u, resolver->pending_requests().size());
    219   // The URL should have been simplified, stripping the username/password/hash.
    220   EXPECT_EQ(GURL("http://www.google.com/?ref"),
    221                  resolver->pending_requests()[0]->url());
    222 
    223   // We end here without ever completing the request -- destruction of
    224   // ProxyService will cancel the outstanding request.
    225 }
    226 
    227 TEST(ProxyServiceTest, PAC_FailoverWithoutDirect) {
    228   MockProxyConfigService* config_service =
    229       new MockProxyConfigService("http://foopy/proxy.pac");
    230   MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
    231 
    232   scoped_refptr<ProxyService> service(
    233       new ProxyService(config_service, resolver, NULL));
    234 
    235   GURL url("http://www.google.com/");
    236 
    237   ProxyInfo info;
    238   TestCompletionCallback callback1;
    239   int rv = service->ResolveProxy(url, &info, &callback1, NULL, BoundNetLog());
    240   EXPECT_EQ(ERR_IO_PENDING, rv);
    241 
    242   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
    243             resolver->pending_set_pac_script_request()->script_data()->url());
    244   resolver->pending_set_pac_script_request()->CompleteNow(OK);
    245 
    246   ASSERT_EQ(1u, resolver->pending_requests().size());
    247   EXPECT_EQ(url, resolver->pending_requests()[0]->url());
    248 
    249   // Set the result in proxy resolver.
    250   resolver->pending_requests()[0]->results()->UseNamedProxy("foopy:8080");
    251   resolver->pending_requests()[0]->CompleteNow(OK);
    252 
    253   EXPECT_EQ(OK, callback1.WaitForResult());
    254   EXPECT_FALSE(info.is_direct());
    255   EXPECT_EQ("foopy:8080", info.proxy_server().ToURI());
    256 
    257   // Now, imagine that connecting to foopy:8080 fails: there is nothing
    258   // left to fallback to, since our proxy list was NOT terminated by
    259   // DIRECT.
    260   TestCompletionCallback callback2;
    261   rv = service->ReconsiderProxyAfterError(url, &info, &callback2, NULL,
    262                                           BoundNetLog());
    263   // ReconsiderProxyAfterError returns error indicating nothing left.
    264   EXPECT_EQ(ERR_FAILED, rv);
    265   EXPECT_TRUE(info.is_empty());
    266 }
    267 
    268 // The proxy list could potentially contain the DIRECT fallback choice
    269 // in a location other than the very end of the list, and could even
    270 // specify it multiple times.
    271 //
    272 // This is not a typical usage, but we will obey it.
    273 // (If we wanted to disallow this type of input, the right place to
    274 // enforce it would be in parsing the PAC result string).
    275 //
    276 // This test will use the PAC result string:
    277 //
    278 //   "DIRECT ; PROXY foobar:10 ; DIRECT ; PROXY foobar:20"
    279 //
    280 // For which we expect it to try DIRECT, then foobar:10, then DIRECT again,
    281 // then foobar:20, and then give up and error.
    282 //
    283 // The important check of this test is to make sure that DIRECT is not somehow
    284 // cached as being a bad proxy.
    285 TEST(ProxyServiceTest, PAC_FailoverAfterDirect) {
    286   MockProxyConfigService* config_service =
    287       new MockProxyConfigService("http://foopy/proxy.pac");
    288   MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
    289 
    290   scoped_refptr<ProxyService> service(
    291       new ProxyService(config_service, resolver, NULL));
    292 
    293   GURL url("http://www.google.com/");
    294 
    295   ProxyInfo info;
    296   TestCompletionCallback callback1;
    297   int rv = service->ResolveProxy(url, &info, &callback1, NULL, BoundNetLog());
    298   EXPECT_EQ(ERR_IO_PENDING, rv);
    299 
    300   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
    301             resolver->pending_set_pac_script_request()->script_data()->url());
    302   resolver->pending_set_pac_script_request()->CompleteNow(OK);
    303 
    304   ASSERT_EQ(1u, resolver->pending_requests().size());
    305   EXPECT_EQ(url, resolver->pending_requests()[0]->url());
    306 
    307   // Set the result in proxy resolver.
    308   resolver->pending_requests()[0]->results()->UsePacString(
    309       "DIRECT ; PROXY foobar:10 ; DIRECT ; PROXY foobar:20");
    310   resolver->pending_requests()[0]->CompleteNow(OK);
    311 
    312   EXPECT_EQ(OK, callback1.WaitForResult());
    313   EXPECT_TRUE(info.is_direct());
    314 
    315   // Fallback 1.
    316   TestCompletionCallback callback2;
    317   rv = service->ReconsiderProxyAfterError(url, &info, &callback2, NULL,
    318                                           BoundNetLog());
    319   EXPECT_EQ(OK, rv);
    320   EXPECT_FALSE(info.is_direct());
    321   EXPECT_EQ("foobar:10", info.proxy_server().ToURI());
    322 
    323   // Fallback 2.
    324   TestCompletionCallback callback3;
    325   rv = service->ReconsiderProxyAfterError(url, &info, &callback3, NULL,
    326                                           BoundNetLog());
    327   EXPECT_EQ(OK, rv);
    328   EXPECT_TRUE(info.is_direct());
    329 
    330   // Fallback 3.
    331   TestCompletionCallback callback4;
    332   rv = service->ReconsiderProxyAfterError(url, &info, &callback4, NULL,
    333                                           BoundNetLog());
    334   EXPECT_EQ(OK, rv);
    335   EXPECT_FALSE(info.is_direct());
    336   EXPECT_EQ("foobar:20", info.proxy_server().ToURI());
    337 
    338   // Fallback 4 -- Nothing to fall back to!
    339   TestCompletionCallback callback5;
    340   rv = service->ReconsiderProxyAfterError(url, &info, &callback5, NULL,
    341                                           BoundNetLog());
    342   EXPECT_EQ(ERR_FAILED, rv);
    343   EXPECT_TRUE(info.is_empty());
    344 }
    345 
    346 TEST(ProxyServiceTest, ProxyResolverFails) {
    347   // Test what happens when the ProxyResolver fails. The download and setting
    348   // of the PAC script have already succeeded, so this corresponds with a
    349   // javascript runtime error while calling FindProxyForURL().
    350 
    351   MockProxyConfigService* config_service =
    352       new MockProxyConfigService("http://foopy/proxy.pac");
    353 
    354   MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
    355 
    356   scoped_refptr<ProxyService> service(
    357       new ProxyService(config_service, resolver, NULL));
    358 
    359   // Start first resolve request.
    360   GURL url("http://www.google.com/");
    361   ProxyInfo info;
    362   TestCompletionCallback callback1;
    363   int rv = service->ResolveProxy(url, &info, &callback1, NULL, BoundNetLog());
    364   EXPECT_EQ(ERR_IO_PENDING, rv);
    365 
    366   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
    367             resolver->pending_set_pac_script_request()->script_data()->url());
    368   resolver->pending_set_pac_script_request()->CompleteNow(OK);
    369 
    370   ASSERT_EQ(1u, resolver->pending_requests().size());
    371   EXPECT_EQ(url, resolver->pending_requests()[0]->url());
    372 
    373   // Fail the first resolve request in MockAsyncProxyResolver.
    374   resolver->pending_requests()[0]->CompleteNow(ERR_FAILED);
    375 
    376   // Although the proxy resolver failed the request, ProxyService implicitly
    377   // falls-back to DIRECT.
    378   EXPECT_EQ(OK, callback1.WaitForResult());
    379   EXPECT_TRUE(info.is_direct());
    380 
    381   // The second resolve request will try to run through the proxy resolver,
    382   // regardless of whether the first request failed in it.
    383   TestCompletionCallback callback2;
    384   rv = service->ResolveProxy(url, &info, &callback2, NULL, BoundNetLog());
    385   EXPECT_EQ(ERR_IO_PENDING, rv);
    386 
    387   ASSERT_EQ(1u, resolver->pending_requests().size());
    388   EXPECT_EQ(url, resolver->pending_requests()[0]->url());
    389 
    390   // This time we will have the resolver succeed (perhaps the PAC script has
    391   // a dependency on the current time).
    392   resolver->pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080");
    393   resolver->pending_requests()[0]->CompleteNow(OK);
    394 
    395   EXPECT_EQ(OK, callback2.WaitForResult());
    396   EXPECT_FALSE(info.is_direct());
    397   EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI());
    398 }
    399 
    400 TEST(ProxyServiceTest, ProxyFallback) {
    401   // Test what happens when we specify multiple proxy servers and some of them
    402   // are bad.
    403 
    404   MockProxyConfigService* config_service =
    405       new MockProxyConfigService("http://foopy/proxy.pac");
    406 
    407   MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
    408 
    409   scoped_refptr<ProxyService> service(
    410       new ProxyService(config_service, resolver, NULL));
    411 
    412   GURL url("http://www.google.com/");
    413 
    414   // Get the proxy information.
    415   ProxyInfo info;
    416   TestCompletionCallback callback1;
    417   int rv = service->ResolveProxy(url, &info, &callback1, NULL, BoundNetLog());
    418   EXPECT_EQ(ERR_IO_PENDING, rv);
    419 
    420   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
    421             resolver->pending_set_pac_script_request()->script_data()->url());
    422   resolver->pending_set_pac_script_request()->CompleteNow(OK);
    423 
    424   ASSERT_EQ(1u, resolver->pending_requests().size());
    425   EXPECT_EQ(url, resolver->pending_requests()[0]->url());
    426 
    427   // Set the result in proxy resolver.
    428   resolver->pending_requests()[0]->results()->UseNamedProxy(
    429       "foopy1:8080;foopy2:9090");
    430   resolver->pending_requests()[0]->CompleteNow(OK);
    431 
    432   // The first item is valid.
    433   EXPECT_EQ(OK, callback1.WaitForResult());
    434   EXPECT_FALSE(info.is_direct());
    435   EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
    436 
    437   // Fake an error on the proxy.
    438   TestCompletionCallback callback2;
    439   rv = service->ReconsiderProxyAfterError(url, &info, &callback2, NULL,
    440                                           BoundNetLog());
    441   EXPECT_EQ(OK, rv);
    442 
    443   // The second proxy should be specified.
    444   EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
    445 
    446   TestCompletionCallback callback3;
    447   rv = service->ResolveProxy(url, &info, &callback3, NULL, BoundNetLog());
    448   EXPECT_EQ(ERR_IO_PENDING, rv);
    449 
    450   ASSERT_EQ(1u, resolver->pending_requests().size());
    451   EXPECT_EQ(url, resolver->pending_requests()[0]->url());
    452 
    453   // Set the result in proxy resolver -- the second result is already known
    454   // to be bad, so we will not try to use it initially.
    455   resolver->pending_requests()[0]->results()->UseNamedProxy(
    456       "foopy3:7070;foopy1:8080;foopy2:9090");
    457   resolver->pending_requests()[0]->CompleteNow(OK);
    458 
    459   EXPECT_EQ(OK, callback3.WaitForResult());
    460   EXPECT_FALSE(info.is_direct());
    461   EXPECT_EQ("foopy3:7070", info.proxy_server().ToURI());
    462 
    463   // We fake another error. It should now try the third one.
    464   TestCompletionCallback callback4;
    465   rv = service->ReconsiderProxyAfterError(url, &info, &callback4, NULL,
    466                                           BoundNetLog());
    467   EXPECT_EQ(OK, rv);
    468   EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
    469 
    470   // We fake another error. At this point we have tried all of the
    471   // proxy servers we thought were valid; next we try the proxy server
    472   // that was in our bad proxies map (foopy1:8080).
    473   TestCompletionCallback callback5;
    474   rv = service->ReconsiderProxyAfterError(url, &info, &callback5, NULL,
    475                                           BoundNetLog());
    476   EXPECT_EQ(OK, rv);
    477   EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
    478 
    479   // Fake another error, the last proxy is gone, the list should now be empty,
    480   // so there is nothing left to try.
    481   TestCompletionCallback callback6;
    482   rv = service->ReconsiderProxyAfterError(url, &info, &callback6, NULL,
    483                                           BoundNetLog());
    484   EXPECT_EQ(ERR_FAILED, rv);
    485   EXPECT_FALSE(info.is_direct());
    486   EXPECT_TRUE(info.is_empty());
    487 
    488   // TODO(nsylvain): Test that the proxy can be retried after the delay.
    489 }
    490 
    491 // This test is similar to ProxyFallback, but this time we have an explicit
    492 // fallback choice to DIRECT.
    493 TEST(ProxyServiceTest, ProxyFallbackToDirect) {
    494   MockProxyConfigService* config_service =
    495       new MockProxyConfigService("http://foopy/proxy.pac");
    496 
    497   MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
    498 
    499   scoped_refptr<ProxyService> service(
    500       new ProxyService(config_service, resolver, NULL));
    501 
    502   GURL url("http://www.google.com/");
    503 
    504   // Get the proxy information.
    505   ProxyInfo info;
    506   TestCompletionCallback callback1;
    507   int rv = service->ResolveProxy(url, &info, &callback1, NULL, BoundNetLog());
    508   EXPECT_EQ(ERR_IO_PENDING, rv);
    509 
    510   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
    511             resolver->pending_set_pac_script_request()->script_data()->url());
    512   resolver->pending_set_pac_script_request()->CompleteNow(OK);
    513 
    514   ASSERT_EQ(1u, resolver->pending_requests().size());
    515   EXPECT_EQ(url, resolver->pending_requests()[0]->url());
    516 
    517   // Set the result in proxy resolver.
    518   resolver->pending_requests()[0]->results()->UsePacString(
    519       "PROXY foopy1:8080; PROXY foopy2:9090; DIRECT");
    520   resolver->pending_requests()[0]->CompleteNow(OK);
    521 
    522   // Get the first result.
    523   EXPECT_EQ(OK, callback1.WaitForResult());
    524   EXPECT_FALSE(info.is_direct());
    525   EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
    526 
    527   // Fake an error on the proxy.
    528   TestCompletionCallback callback2;
    529   rv = service->ReconsiderProxyAfterError(url, &info, &callback2, NULL,
    530                                           BoundNetLog());
    531   EXPECT_EQ(OK, rv);
    532 
    533   // Now we get back the second proxy.
    534   EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
    535 
    536   // Fake an error on this proxy as well.
    537   TestCompletionCallback callback3;
    538   rv = service->ReconsiderProxyAfterError(url, &info, &callback3, NULL,
    539                                           BoundNetLog());
    540   EXPECT_EQ(OK, rv);
    541 
    542   // Finally, we get back DIRECT.
    543   EXPECT_TRUE(info.is_direct());
    544 
    545   // Now we tell the proxy service that even DIRECT failed.
    546   TestCompletionCallback callback4;
    547   rv = service->ReconsiderProxyAfterError(url, &info, &callback4, NULL,
    548                                           BoundNetLog());
    549   // There was nothing left to try after DIRECT, so we are out of
    550   // choices.
    551   EXPECT_EQ(ERR_FAILED, rv);
    552 }
    553 
    554 TEST(ProxyServiceTest, ProxyFallback_NewSettings) {
    555   // Test proxy failover when new settings are available.
    556 
    557   MockProxyConfigService* config_service =
    558       new MockProxyConfigService("http://foopy/proxy.pac");
    559 
    560   MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
    561 
    562   scoped_refptr<ProxyService> service(
    563       new ProxyService(config_service, resolver, NULL));
    564 
    565   GURL url("http://www.google.com/");
    566 
    567   // Get the proxy information.
    568   ProxyInfo info;
    569   TestCompletionCallback callback1;
    570   int rv = service->ResolveProxy(url, &info, &callback1, NULL, BoundNetLog());
    571   EXPECT_EQ(ERR_IO_PENDING, rv);
    572 
    573   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
    574             resolver->pending_set_pac_script_request()->script_data()->url());
    575   resolver->pending_set_pac_script_request()->CompleteNow(OK);
    576 
    577   ASSERT_EQ(1u, resolver->pending_requests().size());
    578   EXPECT_EQ(url, resolver->pending_requests()[0]->url());
    579 
    580   // Set the result in proxy resolver.
    581   resolver->pending_requests()[0]->results()->UseNamedProxy(
    582       "foopy1:8080;foopy2:9090");
    583   resolver->pending_requests()[0]->CompleteNow(OK);
    584 
    585   // The first item is valid.
    586   EXPECT_EQ(OK, callback1.WaitForResult());
    587   EXPECT_FALSE(info.is_direct());
    588   EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
    589 
    590   // Fake an error on the proxy, and also a new configuration on the proxy.
    591   config_service->SetConfig(
    592       ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy-new/proxy.pac")));
    593 
    594   TestCompletionCallback callback2;
    595   rv = service->ReconsiderProxyAfterError(url, &info, &callback2, NULL,
    596                                           BoundNetLog());
    597   EXPECT_EQ(ERR_IO_PENDING, rv);
    598 
    599   EXPECT_EQ(GURL("http://foopy-new/proxy.pac"),
    600             resolver->pending_set_pac_script_request()->script_data()->url());
    601   resolver->pending_set_pac_script_request()->CompleteNow(OK);
    602 
    603   ASSERT_EQ(1u, resolver->pending_requests().size());
    604   EXPECT_EQ(url, resolver->pending_requests()[0]->url());
    605 
    606   resolver->pending_requests()[0]->results()->UseNamedProxy(
    607       "foopy1:8080;foopy2:9090");
    608   resolver->pending_requests()[0]->CompleteNow(OK);
    609 
    610   // The first proxy is still there since the configuration changed.
    611   EXPECT_EQ(OK, callback2.WaitForResult());
    612   EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
    613 
    614   // We fake another error. It should now ignore the first one.
    615   TestCompletionCallback callback3;
    616   rv = service->ReconsiderProxyAfterError(url, &info, &callback3, NULL,
    617                                           BoundNetLog());
    618   EXPECT_EQ(OK, rv);
    619   EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
    620 
    621   // We simulate a new configuration.
    622   config_service->SetConfig(
    623       ProxyConfig::CreateFromCustomPacURL(
    624           GURL("http://foopy-new2/proxy.pac")));
    625 
    626   // We fake another error. It should go back to the first proxy.
    627   TestCompletionCallback callback4;
    628   rv = service->ReconsiderProxyAfterError(url, &info, &callback4, NULL,
    629                                           BoundNetLog());
    630   EXPECT_EQ(ERR_IO_PENDING, rv);
    631 
    632   EXPECT_EQ(GURL("http://foopy-new2/proxy.pac"),
    633             resolver->pending_set_pac_script_request()->script_data()->url());
    634   resolver->pending_set_pac_script_request()->CompleteNow(OK);
    635 
    636   ASSERT_EQ(1u, resolver->pending_requests().size());
    637   EXPECT_EQ(url, resolver->pending_requests()[0]->url());
    638 
    639   resolver->pending_requests()[0]->results()->UseNamedProxy(
    640       "foopy1:8080;foopy2:9090");
    641   resolver->pending_requests()[0]->CompleteNow(OK);
    642 
    643   EXPECT_EQ(OK, callback4.WaitForResult());
    644   EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
    645 }
    646 
    647 TEST(ProxyServiceTest, ProxyFallback_BadConfig) {
    648   // Test proxy failover when the configuration is bad.
    649 
    650   MockProxyConfigService* config_service =
    651       new MockProxyConfigService("http://foopy/proxy.pac");
    652 
    653   MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
    654 
    655   scoped_refptr<ProxyService> service(
    656       new ProxyService(config_service, resolver, NULL));
    657 
    658   GURL url("http://www.google.com/");
    659 
    660   // Get the proxy information.
    661   ProxyInfo info;
    662   TestCompletionCallback callback1;
    663   int rv = service->ResolveProxy(url, &info, &callback1, NULL, BoundNetLog());
    664   EXPECT_EQ(ERR_IO_PENDING, rv);
    665 
    666   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
    667             resolver->pending_set_pac_script_request()->script_data()->url());
    668   resolver->pending_set_pac_script_request()->CompleteNow(OK);
    669   ASSERT_EQ(1u, resolver->pending_requests().size());
    670   EXPECT_EQ(url, resolver->pending_requests()[0]->url());
    671 
    672   resolver->pending_requests()[0]->results()->UseNamedProxy(
    673       "foopy1:8080;foopy2:9090");
    674   resolver->pending_requests()[0]->CompleteNow(OK);
    675 
    676   // The first item is valid.
    677   EXPECT_EQ(OK, callback1.WaitForResult());
    678   EXPECT_FALSE(info.is_direct());
    679   EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
    680 
    681   // Fake a proxy error.
    682   TestCompletionCallback callback2;
    683   rv = service->ReconsiderProxyAfterError(url, &info, &callback2, NULL,
    684                                           BoundNetLog());
    685   EXPECT_EQ(OK, rv);
    686 
    687   // The first proxy is ignored, and the second one is selected.
    688   EXPECT_FALSE(info.is_direct());
    689   EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
    690 
    691   // Fake a PAC failure.
    692   ProxyInfo info2;
    693   TestCompletionCallback callback3;
    694   rv = service->ResolveProxy(url, &info2, &callback3, NULL, BoundNetLog());
    695   EXPECT_EQ(ERR_IO_PENDING, rv);
    696 
    697   ASSERT_EQ(1u, resolver->pending_requests().size());
    698   EXPECT_EQ(url, resolver->pending_requests()[0]->url());
    699 
    700   // This simulates a javascript runtime error in the PAC script.
    701   resolver->pending_requests()[0]->CompleteNow(ERR_FAILED);
    702 
    703   // Although the resolver failed, the ProxyService will implicitly fall-back
    704   // to a DIRECT connection.
    705   EXPECT_EQ(OK, callback3.WaitForResult());
    706   EXPECT_TRUE(info2.is_direct());
    707   EXPECT_FALSE(info2.is_empty());
    708 
    709   // The PAC script will work properly next time and successfully return a
    710   // proxy list. Since we have not marked the configuration as bad, it should
    711   // "just work" the next time we call it.
    712   ProxyInfo info3;
    713   TestCompletionCallback callback4;
    714   rv = service->ReconsiderProxyAfterError(url, &info3, &callback4, NULL,
    715                                           BoundNetLog());
    716   EXPECT_EQ(ERR_IO_PENDING, rv);
    717 
    718   ASSERT_EQ(1u, resolver->pending_requests().size());
    719   EXPECT_EQ(url, resolver->pending_requests()[0]->url());
    720 
    721   resolver->pending_requests()[0]->results()->UseNamedProxy(
    722       "foopy1:8080;foopy2:9090");
    723   resolver->pending_requests()[0]->CompleteNow(OK);
    724 
    725   // The first proxy is not there since the it was added to the bad proxies
    726   // list by the earlier ReconsiderProxyAfterError().
    727   EXPECT_EQ(OK, callback4.WaitForResult());
    728   EXPECT_FALSE(info3.is_direct());
    729   EXPECT_EQ("foopy1:8080", info3.proxy_server().ToURI());
    730 }
    731 
    732 TEST(ProxyServiceTest, ProxyBypassList) {
    733   // Test that the proxy bypass rules are consulted.
    734 
    735   TestCompletionCallback callback[2];
    736   ProxyInfo info[2];
    737   ProxyConfig config;
    738   config.proxy_rules().ParseFromString("foopy1:8080;foopy2:9090");
    739   config.set_auto_detect(false);
    740   config.proxy_rules().bypass_rules.ParseFromString("*.org");
    741 
    742   scoped_refptr<ProxyService> service(new ProxyService(
    743       new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL));
    744 
    745   int rv;
    746   GURL url1("http://www.webkit.org");
    747   GURL url2("http://www.webkit.com");
    748 
    749   // Request for a .org domain should bypass proxy.
    750   rv = service->ResolveProxy(url1, &info[0], &callback[0], NULL, BoundNetLog());
    751   EXPECT_EQ(OK, rv);
    752   EXPECT_TRUE(info[0].is_direct());
    753 
    754   // Request for a .com domain hits the proxy.
    755   rv = service->ResolveProxy(url2, &info[1], &callback[1], NULL, BoundNetLog());
    756   EXPECT_EQ(OK, rv);
    757   EXPECT_EQ("foopy1:8080", info[1].proxy_server().ToURI());
    758 }
    759 
    760 
    761 TEST(ProxyServiceTest, PerProtocolProxyTests) {
    762   ProxyConfig config;
    763   config.proxy_rules().ParseFromString("http=foopy1:8080;https=foopy2:8080");
    764   config.set_auto_detect(false);
    765   {
    766     scoped_refptr<ProxyService> service(new ProxyService(
    767         new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL));
    768     GURL test_url("http://www.msn.com");
    769     ProxyInfo info;
    770     TestCompletionCallback callback;
    771     int rv = service->ResolveProxy(test_url, &info, &callback, NULL,
    772                                    BoundNetLog());
    773     EXPECT_EQ(OK, rv);
    774     EXPECT_FALSE(info.is_direct());
    775     EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
    776   }
    777   {
    778     scoped_refptr<ProxyService> service(new ProxyService(
    779         new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL));
    780     GURL test_url("ftp://ftp.google.com");
    781     ProxyInfo info;
    782     TestCompletionCallback callback;
    783     int rv = service->ResolveProxy(test_url, &info, &callback, NULL,
    784                                    BoundNetLog());
    785     EXPECT_EQ(OK, rv);
    786     EXPECT_TRUE(info.is_direct());
    787     EXPECT_EQ("direct://", info.proxy_server().ToURI());
    788   }
    789   {
    790     scoped_refptr<ProxyService> service(new ProxyService(
    791         new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL));
    792     GURL test_url("https://webbranch.techcu.com");
    793     ProxyInfo info;
    794     TestCompletionCallback callback;
    795     int rv = service->ResolveProxy(test_url, &info, &callback, NULL,
    796                                    BoundNetLog());
    797     EXPECT_EQ(OK, rv);
    798     EXPECT_FALSE(info.is_direct());
    799     EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI());
    800   }
    801   {
    802     config.proxy_rules().ParseFromString("foopy1:8080");
    803     scoped_refptr<ProxyService> service(new ProxyService(
    804         new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL));
    805     GURL test_url("http://www.microsoft.com");
    806     ProxyInfo info;
    807     TestCompletionCallback callback;
    808     int rv = service->ResolveProxy(test_url, &info, &callback, NULL,
    809                                    BoundNetLog());
    810     EXPECT_EQ(OK, rv);
    811     EXPECT_FALSE(info.is_direct());
    812     EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
    813   }
    814 }
    815 
    816 // If only HTTP and a SOCKS proxy are specified, check if ftp/https queries
    817 // fall back to the SOCKS proxy.
    818 TEST(ProxyServiceTest, DefaultProxyFallbackToSOCKS) {
    819   ProxyConfig config;
    820   config.proxy_rules().ParseFromString("http=foopy1:8080;socks=foopy2:1080");
    821   config.set_auto_detect(false);
    822   EXPECT_EQ(ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
    823             config.proxy_rules().type);
    824 
    825   {
    826     scoped_refptr<ProxyService> service(new ProxyService(
    827         new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL));
    828     GURL test_url("http://www.msn.com");
    829     ProxyInfo info;
    830     TestCompletionCallback callback;
    831     int rv = service->ResolveProxy(test_url, &info, &callback, NULL,
    832                                    BoundNetLog());
    833     EXPECT_EQ(OK, rv);
    834     EXPECT_FALSE(info.is_direct());
    835     EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
    836   }
    837   {
    838     scoped_refptr<ProxyService> service(new ProxyService(
    839         new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL));
    840     GURL test_url("ftp://ftp.google.com");
    841     ProxyInfo info;
    842     TestCompletionCallback callback;
    843     int rv = service->ResolveProxy(test_url, &info, &callback, NULL,
    844                                    BoundNetLog());
    845     EXPECT_EQ(OK, rv);
    846     EXPECT_FALSE(info.is_direct());
    847     EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI());
    848   }
    849   {
    850     scoped_refptr<ProxyService> service(new ProxyService(
    851         new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL));
    852     GURL test_url("https://webbranch.techcu.com");
    853     ProxyInfo info;
    854     TestCompletionCallback callback;
    855     int rv = service->ResolveProxy(test_url, &info, &callback, NULL,
    856                                    BoundNetLog());
    857     EXPECT_EQ(OK, rv);
    858     EXPECT_FALSE(info.is_direct());
    859     EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI());
    860   }
    861   {
    862     scoped_refptr<ProxyService> service(new ProxyService(
    863         new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL));
    864     GURL test_url("unknown://www.microsoft.com");
    865     ProxyInfo info;
    866     TestCompletionCallback callback;
    867     int rv = service->ResolveProxy(test_url, &info, &callback, NULL,
    868                                    BoundNetLog());
    869     EXPECT_EQ(OK, rv);
    870     EXPECT_FALSE(info.is_direct());
    871     EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI());
    872   }
    873 }
    874 
    875 // Test cancellation of an in-progress request.
    876 TEST(ProxyServiceTest, CancelInProgressRequest) {
    877   MockProxyConfigService* config_service =
    878       new MockProxyConfigService("http://foopy/proxy.pac");
    879 
    880   MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
    881 
    882   scoped_refptr<ProxyService> service(
    883       new ProxyService(config_service, resolver, NULL));
    884 
    885   // Start 3 requests.
    886 
    887   ProxyInfo info1;
    888   TestCompletionCallback callback1;
    889   int rv = service->ResolveProxy(
    890       GURL("http://request1"), &info1, &callback1, NULL, BoundNetLog());
    891   EXPECT_EQ(ERR_IO_PENDING, rv);
    892 
    893   // Nothing has been sent to the proxy resolver yet, since the proxy
    894   // resolver has not been configured yet.
    895   ASSERT_EQ(0u, resolver->pending_requests().size());
    896 
    897   // Successfully initialize the PAC script.
    898   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
    899             resolver->pending_set_pac_script_request()->script_data()->url());
    900   resolver->pending_set_pac_script_request()->CompleteNow(OK);
    901 
    902   ASSERT_EQ(1u, resolver->pending_requests().size());
    903   EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
    904 
    905   ProxyInfo info2;
    906   TestCompletionCallback callback2;
    907   ProxyService::PacRequest* request2;
    908   rv = service->ResolveProxy(
    909       GURL("http://request2"), &info2, &callback2, &request2, BoundNetLog());
    910   EXPECT_EQ(ERR_IO_PENDING, rv);
    911   ASSERT_EQ(2u, resolver->pending_requests().size());
    912   EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url());
    913 
    914   ProxyInfo info3;
    915   TestCompletionCallback callback3;
    916   rv = service->ResolveProxy(
    917       GURL("http://request3"), &info3, &callback3, NULL, BoundNetLog());
    918   EXPECT_EQ(ERR_IO_PENDING, rv);
    919   ASSERT_EQ(3u, resolver->pending_requests().size());
    920   EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[2]->url());
    921 
    922   // Cancel the second request
    923   service->CancelPacRequest(request2);
    924 
    925   ASSERT_EQ(2u, resolver->pending_requests().size());
    926   EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
    927   EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[1]->url());
    928 
    929   // Complete the two un-cancelled requests.
    930   // We complete the last one first, just to mix it up a bit.
    931   resolver->pending_requests()[1]->results()->UseNamedProxy("request3:80");
    932   resolver->pending_requests()[1]->CompleteNow(OK);
    933 
    934   resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
    935   resolver->pending_requests()[0]->CompleteNow(OK);
    936 
    937   // Complete and verify that requests ran as expected.
    938   EXPECT_EQ(OK, callback1.WaitForResult());
    939   EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
    940 
    941   EXPECT_FALSE(callback2.have_result());  // Cancelled.
    942   ASSERT_EQ(1u, resolver->cancelled_requests().size());
    943   EXPECT_EQ(GURL("http://request2"), resolver->cancelled_requests()[0]->url());
    944 
    945   EXPECT_EQ(OK, callback3.WaitForResult());
    946   EXPECT_EQ("request3:80", info3.proxy_server().ToURI());
    947 }
    948 
    949 // Test the initial PAC download for resolver that expects bytes.
    950 TEST(ProxyServiceTest, InitialPACScriptDownload) {
    951   MockProxyConfigService* config_service =
    952       new MockProxyConfigService("http://foopy/proxy.pac");
    953 
    954   MockAsyncProxyResolverExpectsBytes* resolver =
    955       new MockAsyncProxyResolverExpectsBytes;
    956 
    957   scoped_refptr<ProxyService> service(
    958       new ProxyService(config_service, resolver, NULL));
    959 
    960   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
    961   service->SetProxyScriptFetcher(fetcher);
    962 
    963   // Start 3 requests.
    964 
    965   ProxyInfo info1;
    966   TestCompletionCallback callback1;
    967   int rv = service->ResolveProxy(
    968       GURL("http://request1"), &info1, &callback1, NULL, BoundNetLog());
    969   EXPECT_EQ(ERR_IO_PENDING, rv);
    970 
    971   // The first request should have triggered download of PAC script.
    972   EXPECT_TRUE(fetcher->has_pending_request());
    973   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
    974 
    975   ProxyInfo info2;
    976   TestCompletionCallback callback2;
    977   rv = service->ResolveProxy(
    978       GURL("http://request2"), &info2, &callback2, NULL, BoundNetLog());
    979   EXPECT_EQ(ERR_IO_PENDING, rv);
    980 
    981   ProxyInfo info3;
    982   TestCompletionCallback callback3;
    983   rv = service->ResolveProxy(
    984       GURL("http://request3"), &info3, &callback3, NULL, BoundNetLog());
    985   EXPECT_EQ(ERR_IO_PENDING, rv);
    986 
    987   // Nothing has been sent to the resolver yet.
    988   EXPECT_TRUE(resolver->pending_requests().empty());
    989 
    990   // At this point the ProxyService should be waiting for the
    991   // ProxyScriptFetcher to invoke its completion callback, notifying it of
    992   // PAC script download completion.
    993   fetcher->NotifyFetchCompletion(OK, "pac-v1");
    994 
    995   // Now that the PAC script is downloaded, it will have been sent to the proxy
    996   // resolver.
    997   EXPECT_EQ(ASCIIToUTF16("pac-v1"),
    998             resolver->pending_set_pac_script_request()->script_data()->utf16());
    999   resolver->pending_set_pac_script_request()->CompleteNow(OK);
   1000 
   1001   ASSERT_EQ(3u, resolver->pending_requests().size());
   1002   EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
   1003   EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url());
   1004   EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[2]->url());
   1005 
   1006   // Complete all the requests (in some order).
   1007   // Note that as we complete requests, they shift up in |pending_requests()|.
   1008 
   1009   resolver->pending_requests()[2]->results()->UseNamedProxy("request3:80");
   1010   resolver->pending_requests()[2]->CompleteNow(OK);
   1011 
   1012   resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
   1013   resolver->pending_requests()[0]->CompleteNow(OK);
   1014 
   1015   resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80");
   1016   resolver->pending_requests()[0]->CompleteNow(OK);
   1017 
   1018   // Complete and verify that requests ran as expected.
   1019   EXPECT_EQ(OK, callback1.WaitForResult());
   1020   EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
   1021 
   1022   EXPECT_EQ(OK, callback2.WaitForResult());
   1023   EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
   1024 
   1025   EXPECT_EQ(OK, callback3.WaitForResult());
   1026   EXPECT_EQ("request3:80", info3.proxy_server().ToURI());
   1027 }
   1028 
   1029 // Test changing the ProxyScriptFetcher while PAC download is in progress.
   1030 TEST(ProxyServiceTest, ChangeScriptFetcherWhilePACDownloadInProgress) {
   1031   MockProxyConfigService* config_service =
   1032       new MockProxyConfigService("http://foopy/proxy.pac");
   1033 
   1034   MockAsyncProxyResolverExpectsBytes* resolver =
   1035       new MockAsyncProxyResolverExpectsBytes;
   1036 
   1037   scoped_refptr<ProxyService> service(
   1038       new ProxyService(config_service, resolver, NULL));
   1039 
   1040   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
   1041   service->SetProxyScriptFetcher(fetcher);
   1042 
   1043   // Start 2 requests.
   1044 
   1045   ProxyInfo info1;
   1046   TestCompletionCallback callback1;
   1047   int rv = service->ResolveProxy(
   1048       GURL("http://request1"), &info1, &callback1, NULL, BoundNetLog());
   1049   EXPECT_EQ(ERR_IO_PENDING, rv);
   1050 
   1051   // The first request should have triggered download of PAC script.
   1052   EXPECT_TRUE(fetcher->has_pending_request());
   1053   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
   1054 
   1055   ProxyInfo info2;
   1056   TestCompletionCallback callback2;
   1057   rv = service->ResolveProxy(
   1058       GURL("http://request2"), &info2, &callback2, NULL, BoundNetLog());
   1059   EXPECT_EQ(ERR_IO_PENDING, rv);
   1060 
   1061   // At this point the ProxyService should be waiting for the
   1062   // ProxyScriptFetcher to invoke its completion callback, notifying it of
   1063   // PAC script download completion.
   1064 
   1065   // We now change out the ProxyService's script fetcher. We should restart
   1066   // the initialization with the new fetcher.
   1067 
   1068   fetcher = new MockProxyScriptFetcher;
   1069   service->SetProxyScriptFetcher(fetcher);
   1070 
   1071   // Nothing has been sent to the resolver yet.
   1072   EXPECT_TRUE(resolver->pending_requests().empty());
   1073 
   1074   fetcher->NotifyFetchCompletion(OK, "pac-v1");
   1075 
   1076   // Now that the PAC script is downloaded, it will have been sent to the proxy
   1077   // resolver.
   1078   EXPECT_EQ(ASCIIToUTF16("pac-v1"),
   1079             resolver->pending_set_pac_script_request()->script_data()->utf16());
   1080   resolver->pending_set_pac_script_request()->CompleteNow(OK);
   1081 
   1082   ASSERT_EQ(2u, resolver->pending_requests().size());
   1083   EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
   1084   EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url());
   1085 }
   1086 
   1087 // Test cancellation of a request, while the PAC script is being fetched.
   1088 TEST(ProxyServiceTest, CancelWhilePACFetching) {
   1089   MockProxyConfigService* config_service =
   1090       new MockProxyConfigService("http://foopy/proxy.pac");
   1091 
   1092   MockAsyncProxyResolverExpectsBytes* resolver =
   1093       new MockAsyncProxyResolverExpectsBytes;
   1094 
   1095   scoped_refptr<ProxyService> service(
   1096       new ProxyService(config_service, resolver, NULL));
   1097 
   1098   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
   1099   service->SetProxyScriptFetcher(fetcher);
   1100 
   1101   // Start 3 requests.
   1102   ProxyInfo info1;
   1103   TestCompletionCallback callback1;
   1104   ProxyService::PacRequest* request1;
   1105   CapturingBoundNetLog log1(CapturingNetLog::kUnbounded);
   1106   int rv = service->ResolveProxy(
   1107       GURL("http://request1"), &info1, &callback1, &request1, log1.bound());
   1108   EXPECT_EQ(ERR_IO_PENDING, rv);
   1109 
   1110   // The first request should have triggered download of PAC script.
   1111   EXPECT_TRUE(fetcher->has_pending_request());
   1112   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
   1113 
   1114   ProxyInfo info2;
   1115   TestCompletionCallback callback2;
   1116   ProxyService::PacRequest* request2;
   1117   rv = service->ResolveProxy(
   1118       GURL("http://request2"), &info2, &callback2, &request2, BoundNetLog());
   1119   EXPECT_EQ(ERR_IO_PENDING, rv);
   1120 
   1121   ProxyInfo info3;
   1122   TestCompletionCallback callback3;
   1123   rv = service->ResolveProxy(
   1124       GURL("http://request3"), &info3, &callback3, NULL, BoundNetLog());
   1125   EXPECT_EQ(ERR_IO_PENDING, rv);
   1126 
   1127   // Nothing has been sent to the resolver yet.
   1128   EXPECT_TRUE(resolver->pending_requests().empty());
   1129 
   1130   // Cancel the first 2 requests.
   1131   service->CancelPacRequest(request1);
   1132   service->CancelPacRequest(request2);
   1133 
   1134   // At this point the ProxyService should be waiting for the
   1135   // ProxyScriptFetcher to invoke its completion callback, notifying it of
   1136   // PAC script download completion.
   1137   fetcher->NotifyFetchCompletion(OK, "pac-v1");
   1138 
   1139   // Now that the PAC script is downloaded, it will have been sent to the
   1140   // proxy resolver.
   1141   EXPECT_EQ(ASCIIToUTF16("pac-v1"),
   1142             resolver->pending_set_pac_script_request()->script_data()->utf16());
   1143   resolver->pending_set_pac_script_request()->CompleteNow(OK);
   1144 
   1145   ASSERT_EQ(1u, resolver->pending_requests().size());
   1146   EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[0]->url());
   1147 
   1148   // Complete all the requests.
   1149   resolver->pending_requests()[0]->results()->UseNamedProxy("request3:80");
   1150   resolver->pending_requests()[0]->CompleteNow(OK);
   1151 
   1152   EXPECT_EQ(OK, callback3.WaitForResult());
   1153   EXPECT_EQ("request3:80", info3.proxy_server().ToURI());
   1154 
   1155   EXPECT_TRUE(resolver->cancelled_requests().empty());
   1156 
   1157   EXPECT_FALSE(callback1.have_result());  // Cancelled.
   1158   EXPECT_FALSE(callback2.have_result());  // Cancelled.
   1159 
   1160   CapturingNetLog::EntryList entries1;
   1161   log1.GetEntries(&entries1);
   1162 
   1163   // Check the NetLog for request 1 (which was cancelled) got filled properly.
   1164   EXPECT_EQ(4u, entries1.size());
   1165   EXPECT_TRUE(LogContainsBeginEvent(
   1166       entries1, 0, NetLog::TYPE_PROXY_SERVICE));
   1167   EXPECT_TRUE(LogContainsBeginEvent(
   1168       entries1, 1, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
   1169   // Note that TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC is never completed before
   1170   // the cancellation occured.
   1171   EXPECT_TRUE(LogContainsEvent(
   1172       entries1, 2, NetLog::TYPE_CANCELLED, NetLog::PHASE_NONE));
   1173   EXPECT_TRUE(LogContainsEndEvent(
   1174       entries1, 3, NetLog::TYPE_PROXY_SERVICE));
   1175 }
   1176 
   1177 // Test that if auto-detect fails, we fall-back to the custom pac.
   1178 TEST(ProxyServiceTest, FallbackFromAutodetectToCustomPac) {
   1179   ProxyConfig config;
   1180   config.set_auto_detect(true);
   1181   config.set_pac_url(GURL("http://foopy/proxy.pac"));
   1182   config.proxy_rules().ParseFromString("http=foopy:80");  // Won't be used.
   1183 
   1184   MockProxyConfigService* config_service = new MockProxyConfigService(config);
   1185   MockAsyncProxyResolverExpectsBytes* resolver =
   1186       new MockAsyncProxyResolverExpectsBytes;
   1187   scoped_refptr<ProxyService> service(
   1188       new ProxyService(config_service, resolver, NULL));
   1189 
   1190   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
   1191   service->SetProxyScriptFetcher(fetcher);
   1192 
   1193   // Start 2 requests.
   1194 
   1195   ProxyInfo info1;
   1196   TestCompletionCallback callback1;
   1197   int rv = service->ResolveProxy(
   1198       GURL("http://request1"), &info1, &callback1, NULL, BoundNetLog());
   1199   EXPECT_EQ(ERR_IO_PENDING, rv);
   1200 
   1201   ProxyInfo info2;
   1202   TestCompletionCallback callback2;
   1203   ProxyService::PacRequest* request2;
   1204   rv = service->ResolveProxy(
   1205       GURL("http://request2"), &info2, &callback2, &request2, BoundNetLog());
   1206   EXPECT_EQ(ERR_IO_PENDING, rv);
   1207 
   1208   // Check that nothing has been sent to the proxy resolver yet.
   1209   ASSERT_EQ(0u, resolver->pending_requests().size());
   1210 
   1211   // It should be trying to auto-detect first -- FAIL the autodetect during
   1212   // the script download.
   1213   EXPECT_TRUE(fetcher->has_pending_request());
   1214   EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
   1215   fetcher->NotifyFetchCompletion(ERR_FAILED, "");
   1216 
   1217   // Next it should be trying the custom PAC url.
   1218   EXPECT_TRUE(fetcher->has_pending_request());
   1219   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
   1220   fetcher->NotifyFetchCompletion(OK, "custom-pac-script");
   1221 
   1222   EXPECT_EQ(ASCIIToUTF16("custom-pac-script"),
   1223             resolver->pending_set_pac_script_request()->script_data()->utf16());
   1224   resolver->pending_set_pac_script_request()->CompleteNow(OK);
   1225 
   1226   // Now finally, the pending requests should have been sent to the resolver
   1227   // (which was initialized with custom PAC script).
   1228 
   1229   ASSERT_EQ(2u, resolver->pending_requests().size());
   1230   EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
   1231   EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url());
   1232 
   1233   // Complete the pending requests.
   1234   resolver->pending_requests()[1]->results()->UseNamedProxy("request2:80");
   1235   resolver->pending_requests()[1]->CompleteNow(OK);
   1236   resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
   1237   resolver->pending_requests()[0]->CompleteNow(OK);
   1238 
   1239   // Verify that requests ran as expected.
   1240   EXPECT_EQ(OK, callback1.WaitForResult());
   1241   EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
   1242 
   1243   EXPECT_EQ(OK, callback2.WaitForResult());
   1244   EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
   1245 }
   1246 
   1247 // This is the same test as FallbackFromAutodetectToCustomPac, except
   1248 // the auto-detect script fails parsing rather than downloading.
   1249 TEST(ProxyServiceTest, FallbackFromAutodetectToCustomPac2) {
   1250   ProxyConfig config;
   1251   config.set_auto_detect(true);
   1252   config.set_pac_url(GURL("http://foopy/proxy.pac"));
   1253   config.proxy_rules().ParseFromString("http=foopy:80");  // Won't be used.
   1254 
   1255   MockProxyConfigService* config_service = new MockProxyConfigService(config);
   1256   MockAsyncProxyResolverExpectsBytes* resolver =
   1257       new MockAsyncProxyResolverExpectsBytes;
   1258   scoped_refptr<ProxyService> service(
   1259       new ProxyService(config_service, resolver, NULL));
   1260 
   1261   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
   1262   service->SetProxyScriptFetcher(fetcher);
   1263 
   1264   // Start 2 requests.
   1265 
   1266   ProxyInfo info1;
   1267   TestCompletionCallback callback1;
   1268   int rv = service->ResolveProxy(
   1269       GURL("http://request1"), &info1, &callback1, NULL, BoundNetLog());
   1270   EXPECT_EQ(ERR_IO_PENDING, rv);
   1271 
   1272   ProxyInfo info2;
   1273   TestCompletionCallback callback2;
   1274   ProxyService::PacRequest* request2;
   1275   rv = service->ResolveProxy(
   1276       GURL("http://request2"), &info2, &callback2, &request2, BoundNetLog());
   1277   EXPECT_EQ(ERR_IO_PENDING, rv);
   1278 
   1279   // Check that nothing has been sent to the proxy resolver yet.
   1280   ASSERT_EQ(0u, resolver->pending_requests().size());
   1281 
   1282   // It should be trying to auto-detect first -- succeed the download.
   1283   EXPECT_TRUE(fetcher->has_pending_request());
   1284   EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
   1285   fetcher->NotifyFetchCompletion(OK, "invalid-script-contents");
   1286 
   1287   // Simulate a parse error.
   1288   EXPECT_EQ(ASCIIToUTF16("invalid-script-contents"),
   1289             resolver->pending_set_pac_script_request()->script_data()->utf16());
   1290   resolver->pending_set_pac_script_request()->CompleteNow(
   1291       ERR_PAC_SCRIPT_FAILED);
   1292 
   1293   // Next it should be trying the custom PAC url.
   1294   EXPECT_TRUE(fetcher->has_pending_request());
   1295   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
   1296   fetcher->NotifyFetchCompletion(OK, "custom-pac-script");
   1297 
   1298   EXPECT_EQ(ASCIIToUTF16("custom-pac-script"),
   1299             resolver->pending_set_pac_script_request()->script_data()->utf16());
   1300   resolver->pending_set_pac_script_request()->CompleteNow(OK);
   1301 
   1302   // Now finally, the pending requests should have been sent to the resolver
   1303   // (which was initialized with custom PAC script).
   1304 
   1305   ASSERT_EQ(2u, resolver->pending_requests().size());
   1306   EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
   1307   EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url());
   1308 
   1309   // Complete the pending requests.
   1310   resolver->pending_requests()[1]->results()->UseNamedProxy("request2:80");
   1311   resolver->pending_requests()[1]->CompleteNow(OK);
   1312   resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
   1313   resolver->pending_requests()[0]->CompleteNow(OK);
   1314 
   1315   // Verify that requests ran as expected.
   1316   EXPECT_EQ(OK, callback1.WaitForResult());
   1317   EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
   1318 
   1319   EXPECT_EQ(OK, callback2.WaitForResult());
   1320   EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
   1321 }
   1322 
   1323 // Test that if all of auto-detect, a custom PAC script, and manual settings
   1324 // are given, then we will try them in that order.
   1325 TEST(ProxyServiceTest, FallbackFromAutodetectToCustomToManual) {
   1326   ProxyConfig config;
   1327   config.set_auto_detect(true);
   1328   config.set_pac_url(GURL("http://foopy/proxy.pac"));
   1329   config.proxy_rules().ParseFromString("http=foopy:80");
   1330 
   1331   MockProxyConfigService* config_service = new MockProxyConfigService(config);
   1332   MockAsyncProxyResolverExpectsBytes* resolver =
   1333       new MockAsyncProxyResolverExpectsBytes;
   1334   scoped_refptr<ProxyService> service(
   1335       new ProxyService(config_service, resolver, NULL));
   1336 
   1337   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
   1338   service->SetProxyScriptFetcher(fetcher);
   1339 
   1340   // Start 2 requests.
   1341 
   1342   ProxyInfo info1;
   1343   TestCompletionCallback callback1;
   1344   int rv = service->ResolveProxy(
   1345       GURL("http://request1"), &info1, &callback1, NULL, BoundNetLog());
   1346   EXPECT_EQ(ERR_IO_PENDING, rv);
   1347 
   1348   ProxyInfo info2;
   1349   TestCompletionCallback callback2;
   1350   ProxyService::PacRequest* request2;
   1351   rv = service->ResolveProxy(
   1352       GURL("http://request2"), &info2, &callback2, &request2, BoundNetLog());
   1353   EXPECT_EQ(ERR_IO_PENDING, rv);
   1354 
   1355   // Check that nothing has been sent to the proxy resolver yet.
   1356   ASSERT_EQ(0u, resolver->pending_requests().size());
   1357 
   1358   // It should be trying to auto-detect first -- fail the download.
   1359   EXPECT_TRUE(fetcher->has_pending_request());
   1360   EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
   1361   fetcher->NotifyFetchCompletion(ERR_FAILED, "");
   1362 
   1363   // Next it should be trying the custom PAC url -- fail the download.
   1364   EXPECT_TRUE(fetcher->has_pending_request());
   1365   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
   1366   fetcher->NotifyFetchCompletion(ERR_FAILED, "");
   1367 
   1368   // Since we never managed to initialize a ProxyResolver, nothing should have
   1369   // been sent to it.
   1370   ASSERT_EQ(0u, resolver->pending_requests().size());
   1371 
   1372   // Verify that requests ran as expected -- they should have fallen back to
   1373   // the manual proxy configuration for HTTP urls.
   1374   EXPECT_EQ(OK, callback1.WaitForResult());
   1375   EXPECT_EQ("foopy:80", info1.proxy_server().ToURI());
   1376 
   1377   EXPECT_EQ(OK, callback2.WaitForResult());
   1378   EXPECT_EQ("foopy:80", info2.proxy_server().ToURI());
   1379 }
   1380 
   1381 // Test that the bypass rules are NOT applied when using autodetect.
   1382 TEST(ProxyServiceTest, BypassDoesntApplyToPac) {
   1383   ProxyConfig config;
   1384   config.set_auto_detect(true);
   1385   config.set_pac_url(GURL("http://foopy/proxy.pac"));
   1386   config.proxy_rules().ParseFromString("http=foopy:80");  // Not used.
   1387   config.proxy_rules().bypass_rules.ParseFromString("www.google.com");
   1388 
   1389   MockProxyConfigService* config_service = new MockProxyConfigService(config);
   1390   MockAsyncProxyResolverExpectsBytes* resolver =
   1391       new MockAsyncProxyResolverExpectsBytes;
   1392   scoped_refptr<ProxyService> service(
   1393       new ProxyService(config_service, resolver, NULL));
   1394 
   1395   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
   1396   service->SetProxyScriptFetcher(fetcher);
   1397 
   1398   // Start 1 requests.
   1399 
   1400   ProxyInfo info1;
   1401   TestCompletionCallback callback1;
   1402   int rv = service->ResolveProxy(
   1403       GURL("http://www.google.com"), &info1, &callback1, NULL, BoundNetLog());
   1404   EXPECT_EQ(ERR_IO_PENDING, rv);
   1405 
   1406   // Check that nothing has been sent to the proxy resolver yet.
   1407   ASSERT_EQ(0u, resolver->pending_requests().size());
   1408 
   1409   // It should be trying to auto-detect first -- succeed the download.
   1410   EXPECT_TRUE(fetcher->has_pending_request());
   1411   EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
   1412   fetcher->NotifyFetchCompletion(OK, "auto-detect");
   1413 
   1414   EXPECT_EQ(ASCIIToUTF16("auto-detect"),
   1415             resolver->pending_set_pac_script_request()->script_data()->utf16());
   1416   resolver->pending_set_pac_script_request()->CompleteNow(OK);
   1417 
   1418   ASSERT_EQ(1u, resolver->pending_requests().size());
   1419   EXPECT_EQ(GURL("http://www.google.com"),
   1420             resolver->pending_requests()[0]->url());
   1421 
   1422   // Complete the pending request.
   1423   resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
   1424   resolver->pending_requests()[0]->CompleteNow(OK);
   1425 
   1426   // Verify that request ran as expected.
   1427   EXPECT_EQ(OK, callback1.WaitForResult());
   1428   EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
   1429 
   1430   // Start another request, it should pickup the bypass item.
   1431   ProxyInfo info2;
   1432   TestCompletionCallback callback2;
   1433   rv = service->ResolveProxy(
   1434       GURL("http://www.google.com"), &info2, &callback2, NULL, BoundNetLog());
   1435   EXPECT_EQ(ERR_IO_PENDING, rv);
   1436 
   1437   ASSERT_EQ(1u, resolver->pending_requests().size());
   1438   EXPECT_EQ(GURL("http://www.google.com"),
   1439             resolver->pending_requests()[0]->url());
   1440 
   1441   // Complete the pending request.
   1442   resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80");
   1443   resolver->pending_requests()[0]->CompleteNow(OK);
   1444 
   1445   EXPECT_EQ(OK, callback2.WaitForResult());
   1446   EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
   1447 }
   1448 
   1449 // Delete the ProxyService while InitProxyResolver has an outstanding
   1450 // request to the script fetcher. When run under valgrind, should not
   1451 // have any memory errors (used to be that the ProxyScriptFetcher was
   1452 // being deleted prior to the InitProxyResolver).
   1453 TEST(ProxyServiceTest, DeleteWhileInitProxyResolverHasOutstandingFetch) {
   1454   ProxyConfig config =
   1455     ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"));
   1456 
   1457   MockProxyConfigService* config_service = new MockProxyConfigService(config);
   1458   MockAsyncProxyResolverExpectsBytes* resolver =
   1459       new MockAsyncProxyResolverExpectsBytes;
   1460   scoped_refptr<ProxyService> service(
   1461       new ProxyService(config_service, resolver, NULL));
   1462 
   1463   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
   1464   service->SetProxyScriptFetcher(fetcher);
   1465 
   1466   // Start 1 request.
   1467 
   1468   ProxyInfo info1;
   1469   TestCompletionCallback callback1;
   1470   int rv = service->ResolveProxy(
   1471       GURL("http://www.google.com"), &info1, &callback1, NULL, BoundNetLog());
   1472   EXPECT_EQ(ERR_IO_PENDING, rv);
   1473 
   1474   // Check that nothing has been sent to the proxy resolver yet.
   1475   ASSERT_EQ(0u, resolver->pending_requests().size());
   1476 
   1477   // InitProxyResolver should have issued a request to the ProxyScriptFetcher
   1478   // and be waiting on that to complete.
   1479   EXPECT_TRUE(fetcher->has_pending_request());
   1480   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
   1481 
   1482   // Delete the ProxyService
   1483   service = NULL;
   1484 }
   1485 
   1486 // Delete the ProxyService while InitProxyResolver has an outstanding
   1487 // request to the proxy resolver. When run under valgrind, should not
   1488 // have any memory errors (used to be that the ProxyResolver was
   1489 // being deleted prior to the InitProxyResolver).
   1490 TEST(ProxyServiceTest, DeleteWhileInitProxyResolverHasOutstandingSet) {
   1491   MockProxyConfigService* config_service =
   1492       new MockProxyConfigService("http://foopy/proxy.pac");
   1493 
   1494   MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
   1495 
   1496   scoped_refptr<ProxyService> service(
   1497       new ProxyService(config_service, resolver, NULL));
   1498 
   1499   GURL url("http://www.google.com/");
   1500 
   1501   ProxyInfo info;
   1502   TestCompletionCallback callback;
   1503   int rv = service->ResolveProxy(url, &info, &callback, NULL, BoundNetLog());
   1504   EXPECT_EQ(ERR_IO_PENDING, rv);
   1505 
   1506   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
   1507             resolver->pending_set_pac_script_request()->script_data()->url());
   1508 
   1509   // Delete the ProxyService.
   1510   service = NULL;
   1511 }
   1512 
   1513 TEST(ProxyServiceTest, ResetProxyConfigService) {
   1514   ProxyConfig config1;
   1515   config1.proxy_rules().ParseFromString("foopy1:8080");
   1516   config1.set_auto_detect(false);
   1517   scoped_refptr<ProxyService> service(new ProxyService(
   1518       new MockProxyConfigService(config1),
   1519       new MockAsyncProxyResolverExpectsBytes, NULL));
   1520 
   1521   ProxyInfo info;
   1522   TestCompletionCallback callback1;
   1523   int rv = service->ResolveProxy(
   1524       GURL("http://request1"), &info, &callback1, NULL, BoundNetLog());
   1525   EXPECT_EQ(OK, rv);
   1526   EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
   1527 
   1528   ProxyConfig config2;
   1529   config2.proxy_rules().ParseFromString("foopy2:8080");
   1530   config2.set_auto_detect(false);
   1531   service->ResetConfigService(new MockProxyConfigService(config2));
   1532   TestCompletionCallback callback2;
   1533   rv = service->ResolveProxy(
   1534       GURL("http://request2"), &info, &callback2, NULL, BoundNetLog());
   1535   EXPECT_EQ(OK, rv);
   1536   EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI());
   1537 }
   1538 
   1539 // Test that when going from a configuration that required PAC to one
   1540 // that does NOT, we unset the variable |should_use_proxy_resolver_|.
   1541 TEST(ProxyServiceTest, UpdateConfigFromPACToDirect) {
   1542   ProxyConfig config = ProxyConfig::CreateAutoDetect();
   1543 
   1544   MockProxyConfigService* config_service = new MockProxyConfigService(config);
   1545   MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
   1546   scoped_refptr<ProxyService> service(
   1547       new ProxyService(config_service, resolver, NULL));
   1548 
   1549   // Start 1 request.
   1550 
   1551   ProxyInfo info1;
   1552   TestCompletionCallback callback1;
   1553   int rv = service->ResolveProxy(
   1554       GURL("http://www.google.com"), &info1, &callback1, NULL, BoundNetLog());
   1555   EXPECT_EQ(ERR_IO_PENDING, rv);
   1556 
   1557   // Check that nothing has been sent to the proxy resolver yet.
   1558   ASSERT_EQ(0u, resolver->pending_requests().size());
   1559 
   1560   // Successfully set the autodetect script.
   1561   EXPECT_EQ(ProxyResolverScriptData::TYPE_AUTO_DETECT,
   1562             resolver->pending_set_pac_script_request()->script_data()->type());
   1563   resolver->pending_set_pac_script_request()->CompleteNow(OK);
   1564 
   1565   // Complete the pending request.
   1566   ASSERT_EQ(1u, resolver->pending_requests().size());
   1567   resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
   1568   resolver->pending_requests()[0]->CompleteNow(OK);
   1569 
   1570   // Verify that request ran as expected.
   1571   EXPECT_EQ(OK, callback1.WaitForResult());
   1572   EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
   1573 
   1574   // Force the ProxyService to pull down a new proxy configuration.
   1575   // (Even though the configuration isn't old/bad).
   1576   //
   1577   // This new configuration no longer has auto_detect set, so
   1578   // requests should complete synchronously now as direct-connect.
   1579   config_service->SetConfig(ProxyConfig::CreateDirect());
   1580 
   1581   // Start another request -- the effective configuration has changed.
   1582   ProxyInfo info2;
   1583   TestCompletionCallback callback2;
   1584   rv = service->ResolveProxy(
   1585       GURL("http://www.google.com"), &info2, &callback2, NULL, BoundNetLog());
   1586   EXPECT_EQ(OK, rv);
   1587 
   1588   EXPECT_TRUE(info2.is_direct());
   1589 }
   1590 
   1591 TEST(ProxyServiceTest, NetworkChangeTriggersPacRefetch) {
   1592   MockProxyConfigService* config_service =
   1593       new MockProxyConfigService("http://foopy/proxy.pac");
   1594 
   1595   MockAsyncProxyResolverExpectsBytes* resolver =
   1596       new MockAsyncProxyResolverExpectsBytes;
   1597 
   1598   CapturingNetLog log(CapturingNetLog::kUnbounded);
   1599 
   1600   scoped_refptr<ProxyService> service(
   1601       new ProxyService(config_service, resolver, &log));
   1602 
   1603   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
   1604   service->SetProxyScriptFetcher(fetcher);
   1605 
   1606   // Disable the "wait after IP address changes" hack, so this unit-test can
   1607   // complete quickly.
   1608   service->set_stall_proxy_auto_config_delay(base::TimeDelta());
   1609 
   1610   // Start 1 request.
   1611 
   1612   ProxyInfo info1;
   1613   TestCompletionCallback callback1;
   1614   int rv = service->ResolveProxy(
   1615       GURL("http://request1"), &info1, &callback1, NULL, BoundNetLog());
   1616   EXPECT_EQ(ERR_IO_PENDING, rv);
   1617 
   1618   // The first request should have triggered initial download of PAC script.
   1619   EXPECT_TRUE(fetcher->has_pending_request());
   1620   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
   1621 
   1622   // Nothing has been sent to the resolver yet.
   1623   EXPECT_TRUE(resolver->pending_requests().empty());
   1624 
   1625   // At this point the ProxyService should be waiting for the
   1626   // ProxyScriptFetcher to invoke its completion callback, notifying it of
   1627   // PAC script download completion.
   1628   fetcher->NotifyFetchCompletion(OK, "pac-v1");
   1629 
   1630   // Now that the PAC script is downloaded, the request will have been sent to
   1631   // the proxy resolver.
   1632   EXPECT_EQ(ASCIIToUTF16("pac-v1"),
   1633             resolver->pending_set_pac_script_request()->script_data()->utf16());
   1634   resolver->pending_set_pac_script_request()->CompleteNow(OK);
   1635 
   1636   ASSERT_EQ(1u, resolver->pending_requests().size());
   1637   EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
   1638 
   1639   // Complete the pending request.
   1640   resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
   1641   resolver->pending_requests()[0]->CompleteNow(OK);
   1642 
   1643   // Wait for completion callback, and verify that the request ran as expected.
   1644   EXPECT_EQ(OK, callback1.WaitForResult());
   1645   EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
   1646 
   1647   // Now simluate a change in the network. The ProxyConfigService is still
   1648   // going to return the same PAC URL as before, but this URL needs to be
   1649   // refetched on the new network.
   1650   NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
   1651   MessageLoop::current()->RunAllPending();  // Notification happens async.
   1652 
   1653   // Start a second request.
   1654   ProxyInfo info2;
   1655   TestCompletionCallback callback2;
   1656   rv = service->ResolveProxy(
   1657       GURL("http://request2"), &info2, &callback2, NULL, BoundNetLog());
   1658   EXPECT_EQ(ERR_IO_PENDING, rv);
   1659 
   1660   // This second request should have triggered the re-download of the PAC
   1661   // script (since we marked the network as having changed).
   1662   EXPECT_TRUE(fetcher->has_pending_request());
   1663   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
   1664 
   1665   // Nothing has been sent to the resolver yet.
   1666   EXPECT_TRUE(resolver->pending_requests().empty());
   1667 
   1668   // Simulate the PAC script fetch as having completed (this time with
   1669   // different data).
   1670   fetcher->NotifyFetchCompletion(OK, "pac-v2");
   1671 
   1672   // Now that the PAC script is downloaded, the second request will have been
   1673   // sent to the proxy resolver.
   1674   EXPECT_EQ(ASCIIToUTF16("pac-v2"),
   1675             resolver->pending_set_pac_script_request()->script_data()->utf16());
   1676   resolver->pending_set_pac_script_request()->CompleteNow(OK);
   1677 
   1678   ASSERT_EQ(1u, resolver->pending_requests().size());
   1679   EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[0]->url());
   1680 
   1681   // Complete the pending second request.
   1682   resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80");
   1683   resolver->pending_requests()[0]->CompleteNow(OK);
   1684 
   1685   // Wait for completion callback, and verify that the request ran as expected.
   1686   EXPECT_EQ(OK, callback2.WaitForResult());
   1687   EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
   1688 
   1689   // Check that the expected events were outputted to the log stream.
   1690   // In particular, PROXY_CONFIG_CHANGED should have only been emitted once
   1691   // (for the initial setup), and NOT a second time when the IP address
   1692   // changed.
   1693   CapturingNetLog::EntryList entries;
   1694   log.GetEntries(&entries);
   1695 
   1696   EXPECT_TRUE(LogContainsEntryWithType(entries, 0,
   1697                                        NetLog::TYPE_PROXY_CONFIG_CHANGED));
   1698   ASSERT_EQ(13u, entries.size());
   1699   for (size_t i = 1; i < entries.size(); ++i)
   1700     EXPECT_NE(NetLog::TYPE_PROXY_CONFIG_CHANGED, entries[i].type);
   1701 }
   1702 
   1703 }  // namespace net
   1704