• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
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_resolution/configured_proxy_resolution_service.h"
6 
7 #include <cstdarg>
8 #include <memory>
9 #include <string>
10 #include <utility>
11 #include <vector>
12 
13 #include "base/check.h"
14 #include "base/format_macros.h"
15 #include "base/functional/bind.h"
16 #include "base/memory/ptr_util.h"
17 #include "base/memory/raw_ptr.h"
18 #include "base/run_loop.h"
19 #include "base/strings/string_util.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "base/test/metrics/histogram_tester.h"
22 #include "base/time/time.h"
23 #include "net/base/mock_network_change_notifier.h"
24 #include "net/base/net_errors.h"
25 #include "net/base/network_anonymization_key.h"
26 #include "net/base/network_change_notifier.h"
27 #include "net/base/network_isolation_key.h"
28 #include "net/base/proxy_chain.h"
29 #include "net/base/proxy_delegate.h"
30 #include "net/base/proxy_server.h"
31 #include "net/base/proxy_string_util.h"
32 #include "net/base/schemeful_site.h"
33 #include "net/base/test_completion_callback.h"
34 #include "net/log/net_log.h"
35 #include "net/log/net_log_event_type.h"
36 #include "net/log/net_log_with_source.h"
37 #include "net/log/test_net_log.h"
38 #include "net/log/test_net_log_util.h"
39 #include "net/proxy_resolution/dhcp_pac_file_fetcher.h"
40 #include "net/proxy_resolution/mock_pac_file_fetcher.h"
41 #include "net/proxy_resolution/mock_proxy_resolver.h"
42 #include "net/proxy_resolution/pac_file_fetcher.h"
43 #include "net/proxy_resolution/proxy_config_service.h"
44 #include "net/proxy_resolution/proxy_resolution_request.h"
45 #include "net/proxy_resolution/proxy_resolver.h"
46 #include "net/test/gtest_util.h"
47 #include "net/test/test_with_task_environment.h"
48 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
49 #include "testing/gmock/include/gmock/gmock.h"
50 #include "testing/gtest/include/gtest/gtest.h"
51 #include "url/gurl.h"
52 
53 using testing::ElementsAre;
54 using testing::Key;
55 
56 using net::test::IsError;
57 using net::test::IsOk;
58 
59 // TODO(eroman): Write a test which exercises
60 //              ConfiguredProxyResolutionService::SuspendAllPendingRequests().
61 namespace net {
62 namespace {
63 
64 // This polling policy will decide to poll every 1 ms.
65 class ImmediatePollPolicy
66     : public ConfiguredProxyResolutionService::PacPollPolicy {
67  public:
68   ImmediatePollPolicy() = default;
69 
70   ImmediatePollPolicy(const ImmediatePollPolicy&) = delete;
71   ImmediatePollPolicy& operator=(const ImmediatePollPolicy&) = delete;
72 
GetNextDelay(int error,base::TimeDelta current_delay,base::TimeDelta * next_delay) const73   Mode GetNextDelay(int error,
74                     base::TimeDelta current_delay,
75                     base::TimeDelta* next_delay) const override {
76     *next_delay = base::Milliseconds(1);
77     return MODE_USE_TIMER;
78   }
79 };
80 
81 // This polling policy chooses a fantastically large delay. In other words, it
82 // will never trigger a poll
83 class NeverPollPolicy : public ConfiguredProxyResolutionService::PacPollPolicy {
84  public:
85   NeverPollPolicy() = default;
86 
87   NeverPollPolicy(const NeverPollPolicy&) = delete;
88   NeverPollPolicy& operator=(const NeverPollPolicy&) = delete;
89 
GetNextDelay(int error,base::TimeDelta current_delay,base::TimeDelta * next_delay) const90   Mode GetNextDelay(int error,
91                     base::TimeDelta current_delay,
92                     base::TimeDelta* next_delay) const override {
93     *next_delay = base::Days(60);
94     return MODE_USE_TIMER;
95   }
96 };
97 
98 // This polling policy starts a poll immediately after network activity.
99 class ImmediateAfterActivityPollPolicy
100     : public ConfiguredProxyResolutionService::PacPollPolicy {
101  public:
102   ImmediateAfterActivityPollPolicy() = default;
103 
104   ImmediateAfterActivityPollPolicy(const ImmediateAfterActivityPollPolicy&) =
105       delete;
106   ImmediateAfterActivityPollPolicy& operator=(
107       const ImmediateAfterActivityPollPolicy&) = delete;
108 
GetNextDelay(int error,base::TimeDelta current_delay,base::TimeDelta * next_delay) const109   Mode GetNextDelay(int error,
110                     base::TimeDelta current_delay,
111                     base::TimeDelta* next_delay) const override {
112     *next_delay = base::TimeDelta();
113     return MODE_START_AFTER_ACTIVITY;
114   }
115 };
116 
117 // This test fixture is used to partially disable the background polling done by
118 // the ConfiguredProxyResolutionService (which it uses to detect whenever its
119 // PAC script contents or WPAD results have changed).
120 //
121 // We disable the feature by setting the poll interval to something really
122 // large, so it will never actually be reached even on the slowest bots that run
123 // these tests.
124 //
125 // We disable the polling in order to avoid any timing dependencies in the
126 // tests. If the bot were to run the tests very slowly and we hadn't disabled
127 // polling, then it might start a background re-try in the middle of our test
128 // and confuse our expectations leading to flaky failures.
129 //
130 // The tests which verify the polling code re-enable the polling behavior but
131 // are careful to avoid timing problems.
132 class ConfiguredProxyResolutionServiceTest : public ::testing::Test,
133                                              public WithTaskEnvironment {
134  protected:
ConfiguredProxyResolutionServiceTest()135   ConfiguredProxyResolutionServiceTest()
136       : WithTaskEnvironment(
137             base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
138 
SetUp()139   void SetUp() override {
140     testing::Test::SetUp();
141     previous_policy_ =
142         ConfiguredProxyResolutionService::set_pac_script_poll_policy(
143             &never_poll_policy_);
144   }
145 
TearDown()146   void TearDown() override {
147     // Restore the original policy.
148     ConfiguredProxyResolutionService::set_pac_script_poll_policy(
149         previous_policy_);
150     testing::Test::TearDown();
151   }
152 
153  private:
154   NeverPollPolicy never_poll_policy_;
155   raw_ptr<const ConfiguredProxyResolutionService::PacPollPolicy>
156       previous_policy_;
157 };
158 
159 const char kValidPacScript1[] = "pac-script-v1-FindProxyForURL";
160 const char16_t kValidPacScript116[] = u"pac-script-v1-FindProxyForURL";
161 const char kValidPacScript2[] = "pac-script-v2-FindProxyForURL";
162 const char16_t kValidPacScript216[] = u"pac-script-v2-FindProxyForURL";
163 
164 class MockProxyConfigService : public ProxyConfigService {
165  public:
MockProxyConfigService(const ProxyConfig & config)166   explicit MockProxyConfigService(const ProxyConfig& config)
167       : config_(
168             ProxyConfigWithAnnotation(config, TRAFFIC_ANNOTATION_FOR_TESTS)) {}
169 
MockProxyConfigService(const std::string & pac_url)170   explicit MockProxyConfigService(const std::string& pac_url)
171       : config_(ProxyConfig::CreateFromCustomPacURL(GURL(pac_url)),
172                 TRAFFIC_ANNOTATION_FOR_TESTS) {}
173 
AddObserver(Observer * observer)174   void AddObserver(Observer* observer) override {
175     observers_.AddObserver(observer);
176   }
177 
RemoveObserver(Observer * observer)178   void RemoveObserver(Observer* observer) override {
179     observers_.RemoveObserver(observer);
180   }
181 
GetLatestProxyConfig(ProxyConfigWithAnnotation * results)182   ConfigAvailability GetLatestProxyConfig(
183       ProxyConfigWithAnnotation* results) override {
184     if (availability_ == CONFIG_VALID)
185       *results = config_;
186     return availability_;
187   }
188 
SetConfig(const ProxyConfigWithAnnotation & config)189   void SetConfig(const ProxyConfigWithAnnotation& config) {
190     availability_ = CONFIG_VALID;
191     config_ = config;
192     for (auto& observer : observers_)
193       observer.OnProxyConfigChanged(config_, availability_);
194   }
195 
SetPacUrlConfig(base::StringPiece pac_url)196   void SetPacUrlConfig(base::StringPiece pac_url) {
197     SetConfig(ProxyConfigWithAnnotation(
198         ProxyConfig::CreateFromCustomPacURL(GURL(pac_url)),
199         TRAFFIC_ANNOTATION_FOR_TESTS));
200   }
201 
202  private:
203   ConfigAvailability availability_ = CONFIG_VALID;
204   ProxyConfigWithAnnotation config_;
205   base::ObserverList<Observer, true>::Unchecked observers_;
206 };
207 
208 // A test network delegate that exercises the OnResolveProxy callback.
209 class TestResolveProxyDelegate : public ProxyDelegate {
210  public:
OnResolveProxy(const GURL & url,const NetworkAnonymizationKey & network_anonymization_key,const std::string & method,const ProxyRetryInfoMap & proxy_retry_info,ProxyInfo * result)211   void OnResolveProxy(const GURL& url,
212                       const NetworkAnonymizationKey& network_anonymization_key,
213                       const std::string& method,
214                       const ProxyRetryInfoMap& proxy_retry_info,
215                       ProxyInfo* result) override {
216     method_ = method;
217     num_resolve_proxy_called_++;
218     network_anonymization_key_ = network_anonymization_key;
219     proxy_retry_info_ = proxy_retry_info;
220     DCHECK(!add_proxy_ || !remove_proxy_);
221     if (add_proxy_) {
222       result->UseNamedProxy("delegate_proxy.com");
223     } else if (remove_proxy_) {
224       result->UseDirect();
225     }
226   }
227 
num_resolve_proxy_called() const228   int num_resolve_proxy_called() const { return num_resolve_proxy_called_; }
229 
method() const230   const std::string& method() const { return method_; }
231 
set_add_proxy(bool add_proxy)232   void set_add_proxy(bool add_proxy) { add_proxy_ = add_proxy; }
233 
set_remove_proxy(bool remove_proxy)234   void set_remove_proxy(bool remove_proxy) { remove_proxy_ = remove_proxy; }
235 
network_anonymization_key() const236   NetworkAnonymizationKey network_anonymization_key() const {
237     return network_anonymization_key_;
238   }
239 
proxy_retry_info() const240   const ProxyRetryInfoMap& proxy_retry_info() const {
241     return proxy_retry_info_;
242   }
243 
OnFallback(const ProxyChain & bad_chain,int net_error)244   void OnFallback(const ProxyChain& bad_chain, int net_error) override {}
245 
OnBeforeTunnelRequest(const ProxyChain & proxy_chain,size_t chain_index,HttpRequestHeaders * extra_headers)246   void OnBeforeTunnelRequest(const ProxyChain& proxy_chain,
247                              size_t chain_index,
248                              HttpRequestHeaders* extra_headers) override {}
249 
OnTunnelHeadersReceived(const ProxyChain & proxy_chain,size_t chain_index,const HttpResponseHeaders & response_headers)250   Error OnTunnelHeadersReceived(
251       const ProxyChain& proxy_chain,
252       size_t chain_index,
253       const HttpResponseHeaders& response_headers) override {
254     return OK;
255   }
256 
257  private:
258   int num_resolve_proxy_called_ = 0;
259   bool add_proxy_ = false;
260   bool remove_proxy_ = false;
261   std::string method_;
262   NetworkAnonymizationKey network_anonymization_key_;
263   ProxyRetryInfoMap proxy_retry_info_;
264 };
265 
266 // A test network delegate that exercises the OnProxyFallback callback.
267 class TestProxyFallbackProxyDelegate : public ProxyDelegate {
268  public:
269   // ProxyDelegate implementation:
OnResolveProxy(const GURL & url,const NetworkAnonymizationKey & network_anonymization_key,const std::string & method,const ProxyRetryInfoMap & proxy_retry_info,ProxyInfo * result)270   void OnResolveProxy(const GURL& url,
271                       const NetworkAnonymizationKey& network_anonymization_key,
272                       const std::string& method,
273                       const ProxyRetryInfoMap& proxy_retry_info,
274                       ProxyInfo* result) override {}
275 
OnFallback(const ProxyChain & bad_chain,int net_error)276   void OnFallback(const ProxyChain& bad_chain, int net_error) override {
277     proxy_chain_ = bad_chain;
278     last_proxy_fallback_net_error_ = net_error;
279     num_proxy_fallback_called_++;
280   }
281 
OnBeforeTunnelRequest(const ProxyChain & proxy_chain,size_t chain_index,HttpRequestHeaders * extra_headers)282   void OnBeforeTunnelRequest(const ProxyChain& proxy_chain,
283                              size_t chain_index,
284                              HttpRequestHeaders* extra_headers) override {}
285 
OnTunnelHeadersReceived(const ProxyChain & proxy_chain,size_t chain_index,const HttpResponseHeaders & response_headers)286   Error OnTunnelHeadersReceived(
287       const ProxyChain& proxy_chain,
288       size_t chain_index,
289       const HttpResponseHeaders& response_headers) override {
290     return OK;
291   }
292 
num_proxy_fallback_called() const293   bool num_proxy_fallback_called() const { return num_proxy_fallback_called_; }
294 
proxy_chain() const295   const ProxyChain& proxy_chain() const { return proxy_chain_; }
296 
last_proxy_fallback_net_error() const297   int last_proxy_fallback_net_error() const {
298     return last_proxy_fallback_net_error_;
299   }
300 
301  private:
302   int num_proxy_fallback_called_ = 0;
303   ProxyChain proxy_chain_;
304   int last_proxy_fallback_net_error_ = OK;
305 };
306 
307 using JobMap = std::map<GURL, MockAsyncProxyResolver::Job*>;
308 
309 // Given a jobmap and a list of target URLs |urls|, asserts that the set of URLs
310 // of the jobs appearing in |list| is exactly the set of URLs in |urls|.
GetJobsForURLs(const JobMap & map,const std::vector<GURL> & urls)311 JobMap GetJobsForURLs(const JobMap& map, const std::vector<GURL>& urls) {
312   size_t a = urls.size();
313   size_t b = map.size();
314   if (a != b) {
315     ADD_FAILURE() << "map size (" << map.size() << ") != urls size ("
316                   << urls.size() << ")";
317     return map;
318   }
319   for (const auto& it : urls) {
320     if (map.count(it) != 1U) {
321       ADD_FAILURE() << "url not in map: " << it.spec();
322       break;
323     }
324   }
325   return map;
326 }
327 
328 // Given a MockAsyncProxyResolver |resolver| and some GURLs, validates that the
329 // set of pending request URLs for |resolver| is exactly the supplied list of
330 // URLs and returns a map from URLs to the corresponding pending jobs.
GetPendingJobsForURLs(const MockAsyncProxyResolver & resolver,const GURL & url1=GURL (),const GURL & url2=GURL (),const GURL & url3=GURL ())331 JobMap GetPendingJobsForURLs(const MockAsyncProxyResolver& resolver,
332                              const GURL& url1 = GURL(),
333                              const GURL& url2 = GURL(),
334                              const GURL& url3 = GURL()) {
335   std::vector<GURL> urls;
336   if (!url1.is_empty())
337     urls.push_back(url1);
338   if (!url2.is_empty())
339     urls.push_back(url2);
340   if (!url3.is_empty())
341     urls.push_back(url3);
342 
343   JobMap map;
344   for (MockAsyncProxyResolver::Job* it : resolver.pending_jobs()) {
345     DCHECK(it);
346     map[it->url()] = it;
347   }
348 
349   return GetJobsForURLs(map, urls);
350 }
351 
352 // Given a MockAsyncProxyResolver |resolver| and some GURLs, validates that the
353 // set of cancelled request URLs for |resolver| is exactly the supplied list of
354 // URLs and returns a map from URLs to the corresponding cancelled jobs.
GetCancelledJobsForURLs(const MockAsyncProxyResolver & resolver,const GURL & url1=GURL (),const GURL & url2=GURL (),const GURL & url3=GURL ())355 JobMap GetCancelledJobsForURLs(const MockAsyncProxyResolver& resolver,
356                                const GURL& url1 = GURL(),
357                                const GURL& url2 = GURL(),
358                                const GURL& url3 = GURL()) {
359   std::vector<GURL> urls;
360   if (!url1.is_empty())
361     urls.push_back(url1);
362   if (!url2.is_empty())
363     urls.push_back(url2);
364   if (!url3.is_empty())
365     urls.push_back(url3);
366 
367   JobMap map;
368   for (const std::unique_ptr<MockAsyncProxyResolver::Job>& it :
369        resolver.cancelled_jobs()) {
370     DCHECK(it);
371     map[it->url()] = it.get();
372   }
373 
374   return GetJobsForURLs(map, urls);
375 }
376 
377 }  // namespace
378 
TEST_F(ConfiguredProxyResolutionServiceTest,Direct)379 TEST_F(ConfiguredProxyResolutionServiceTest, Direct) {
380   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
381   auto* factory_ptr = factory.get();
382   ConfiguredProxyResolutionService service(
383       std::make_unique<MockProxyConfigService>(ProxyConfig::CreateDirect()),
384       std::move(factory), nullptr, /*quick_check_enabled=*/true);
385 
386   GURL url("http://www.google.com/");
387 
388   ProxyInfo info;
389   TestCompletionCallback callback;
390   RecordingNetLogObserver net_log_observer;
391   std::unique_ptr<ProxyResolutionRequest> request;
392   int rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
393                                 &info, callback.callback(), &request,
394                                 NetLogWithSource::Make(NetLogSourceType::NONE));
395   EXPECT_THAT(rv, IsOk());
396   EXPECT_TRUE(factory_ptr->pending_requests().empty());
397 
398   EXPECT_TRUE(info.is_direct());
399   EXPECT_TRUE(info.proxy_resolve_start_time().is_null());
400   EXPECT_TRUE(info.proxy_resolve_end_time().is_null());
401 
402   // Check the NetLog was filled correctly.
403   auto entries = net_log_observer.GetEntries();
404 
405   EXPECT_EQ(3u, entries.size());
406   EXPECT_TRUE(LogContainsBeginEvent(entries, 0,
407                                     NetLogEventType::PROXY_RESOLUTION_SERVICE));
408   EXPECT_TRUE(LogContainsEvent(
409       entries, 1, NetLogEventType::PROXY_RESOLUTION_SERVICE_RESOLVED_PROXY_LIST,
410       NetLogEventPhase::NONE));
411   EXPECT_TRUE(LogContainsEndEvent(entries, 2,
412                                   NetLogEventType::PROXY_RESOLUTION_SERVICE));
413 }
414 
TEST_F(ConfiguredProxyResolutionServiceTest,OnResolveProxyCallbackAddProxy)415 TEST_F(ConfiguredProxyResolutionServiceTest, OnResolveProxyCallbackAddProxy) {
416   ProxyConfig config;
417   config.proxy_rules().ParseFromString("badproxy:8080,foopy1:8080");
418   config.set_auto_detect(false);
419   config.proxy_rules().bypass_rules.ParseFromString("*.org");
420 
421   ConfiguredProxyResolutionService service(
422       std::make_unique<MockProxyConfigService>(config), nullptr, nullptr,
423       /*quick_check_enabled=*/true);
424 
425   GURL url("http://www.google.com/");
426   GURL bypass_url("http://internet.org");
427 
428   ProxyInfo info;
429   TestCompletionCallback callback;
430   NetLogWithSource net_log_with_source =
431       NetLogWithSource::Make(NetLogSourceType::NONE);
432 
433   // First, warm up the ConfiguredProxyResolutionService and fake an error to
434   // mark the first server as bad.
435   std::unique_ptr<ProxyResolutionRequest> request;
436   int rv =
437       service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(), &info,
438                            callback.callback(), &request, net_log_with_source);
439   EXPECT_THAT(rv, IsOk());
440   EXPECT_EQ("[badproxy:8080]", info.proxy_chain().ToDebugString());
441 
442   EXPECT_TRUE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
443   EXPECT_EQ("[foopy1:8080]", info.proxy_chain().ToDebugString());
444 
445   service.ReportSuccess(info);
446 
447   // Verify that network delegate is invoked.
448   TestResolveProxyDelegate delegate;
449   service.SetProxyDelegate(&delegate);
450   rv = service.ResolveProxy(url, "GET", NetworkAnonymizationKey(), &info,
451                             callback.callback(), &request, net_log_with_source);
452   EXPECT_EQ(1, delegate.num_resolve_proxy_called());
453   EXPECT_THAT(delegate.proxy_retry_info(),
454               ElementsAre(Key(ProxyChain(ProxyUriToProxyChain(
455                   "badproxy:8080", ProxyServer::SCHEME_HTTP)))));
456   EXPECT_EQ(delegate.method(), "GET");
457 
458   // Verify that the ProxyDelegate's behavior is stateless across
459   // invocations of ResolveProxy. Start by having the callback add a proxy
460   // and checking that subsequent jobs are not affected.
461   delegate.set_add_proxy(true);
462 
463   // Callback should interpose:
464   rv = service.ResolveProxy(url, "GET", NetworkAnonymizationKey(), &info,
465                             callback.callback(), &request, net_log_with_source);
466   EXPECT_FALSE(info.is_direct());
467   EXPECT_EQ("[delegate_proxy.com:80]", info.proxy_chain().ToDebugString());
468   delegate.set_add_proxy(false);
469 
470   // Check non-bypassed URL:
471   rv = service.ResolveProxy(url, "GET", NetworkAnonymizationKey(), &info,
472                             callback.callback(), &request, net_log_with_source);
473   EXPECT_FALSE(info.is_direct());
474   EXPECT_EQ("[foopy1:8080]", info.proxy_chain().ToDebugString());
475 
476   // Check bypassed URL:
477   rv = service.ResolveProxy(bypass_url, "GET", NetworkAnonymizationKey(), &info,
478                             callback.callback(), &request, net_log_with_source);
479   EXPECT_TRUE(info.is_direct());
480 }
481 
TEST_F(ConfiguredProxyResolutionServiceTest,OnResolveProxyCallbackRemoveProxy)482 TEST_F(ConfiguredProxyResolutionServiceTest,
483        OnResolveProxyCallbackRemoveProxy) {
484   // Same as OnResolveProxyCallbackAddProxy, but verify that the
485   // ProxyDelegate's behavior is stateless across invocations after it
486   // *removes* a proxy.
487   ProxyConfig config;
488   config.proxy_rules().ParseFromString("foopy1:8080");
489   config.set_auto_detect(false);
490   config.proxy_rules().bypass_rules.ParseFromString("*.org");
491 
492   ConfiguredProxyResolutionService service(
493       std::make_unique<MockProxyConfigService>(config), nullptr, nullptr,
494       /*quick_check_enabled=*/true);
495 
496   GURL url("http://www.google.com/");
497   GURL bypass_url("http://internet.org");
498 
499   ProxyInfo info;
500   TestCompletionCallback callback;
501   NetLogWithSource net_log_with_source =
502       NetLogWithSource::Make(NetLogSourceType::NONE);
503 
504   // First, warm up the ConfiguredProxyResolutionService.
505   std::unique_ptr<ProxyResolutionRequest> request;
506   int rv =
507       service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(), &info,
508                            callback.callback(), &request, net_log_with_source);
509   EXPECT_THAT(rv, IsOk());
510 
511   TestResolveProxyDelegate delegate;
512   service.SetProxyDelegate(&delegate);
513   delegate.set_remove_proxy(true);
514 
515   // Callback should interpose:
516   rv = service.ResolveProxy(url, "GET", NetworkAnonymizationKey(), &info,
517                             callback.callback(), &request, net_log_with_source);
518   EXPECT_TRUE(info.is_direct());
519   delegate.set_remove_proxy(false);
520 
521   // Check non-bypassed URL:
522   rv = service.ResolveProxy(url, "GET", NetworkAnonymizationKey(), &info,
523                             callback.callback(), &request, net_log_with_source);
524   EXPECT_FALSE(info.is_direct());
525   EXPECT_EQ("[foopy1:8080]", info.proxy_chain().ToDebugString());
526 
527   // Check bypassed URL:
528   rv = service.ResolveProxy(bypass_url, "GET", NetworkAnonymizationKey(), &info,
529                             callback.callback(), &request, net_log_with_source);
530   EXPECT_TRUE(info.is_direct());
531 }
532 
TEST_F(ConfiguredProxyResolutionServiceTest,OnResolveProxyHasNak)533 TEST_F(ConfiguredProxyResolutionServiceTest, OnResolveProxyHasNak) {
534   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
535   ConfiguredProxyResolutionService service(
536       std::make_unique<MockProxyConfigService>(ProxyConfig::CreateDirect()),
537       std::move(factory), nullptr, /*quick_check_enabled=*/true);
538 
539   auto proxy_delegate = TestResolveProxyDelegate();
540   service.SetProxyDelegate(&proxy_delegate);
541 
542   GURL url("http://www.google.com/");
543   NetworkAnonymizationKey network_anonymization_key =
544       NetworkAnonymizationKey::CreateCrossSite(
545           SchemefulSite(GURL("http://example.com")));
546 
547   ProxyInfo info;
548   TestCompletionCallback callback;
549   std::unique_ptr<ProxyResolutionRequest> request;
550   service.ResolveProxy(url, std::string(), network_anonymization_key, &info,
551                        callback.callback(), &request,
552                        NetLogWithSource::Make(NetLogSourceType::NONE));
553 
554   EXPECT_EQ(network_anonymization_key,
555             proxy_delegate.network_anonymization_key());
556 }
557 
558 // Test callback that deletes an item when called.  This is used to test various
559 // permutations of important objects being deleted in the middle of a series of
560 // requests.
561 template <typename T>
562 class DeletingCallback : public TestCompletionCallbackBase {
563  public:
564   explicit DeletingCallback(std::unique_ptr<T>* deletee);
565 
566   DeletingCallback(const DeletingCallback&) = delete;
567   DeletingCallback& operator=(const DeletingCallback&) = delete;
568 
569   ~DeletingCallback() override;
570 
callback()571   CompletionOnceCallback callback() {
572     return base::BindOnce(&DeletingCallback::DeleteItem,
573                           base::Unretained(this));
574   }
575 
576  private:
DeleteItem(int result)577   void DeleteItem(int result) {
578     deletee_->reset();
579     SetResult(result);
580   }
581 
582   raw_ptr<std::unique_ptr<T>> deletee_;
583 };
584 
585 template <typename T>
DeletingCallback(std::unique_ptr<T> * deletee)586 DeletingCallback<T>::DeletingCallback(std::unique_ptr<T>* deletee)
587     : deletee_(deletee) {}
588 
589 template <typename T>
590 DeletingCallback<T>::~DeletingCallback() = default;
591 
592 // Test that the ConfiguredProxyResolutionService correctly handles the case
593 // where a request callback deletes another request.
TEST_F(ConfiguredProxyResolutionServiceTest,CallbackDeletesRequest)594 TEST_F(ConfiguredProxyResolutionServiceTest, CallbackDeletesRequest) {
595   auto config_service =
596       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
597   MockAsyncProxyResolver resolver;
598   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
599   auto* factory_ptr = factory.get();
600 
601   std::unique_ptr<ConfiguredProxyResolutionService> service =
602       std::make_unique<ConfiguredProxyResolutionService>(
603           std::move(config_service), std::move(factory), nullptr,
604           /*quick_check_enabled=*/true);
605 
606   GURL url("http://www.google.com/");
607   GURL url2("http://www.example.com/");
608 
609   ProxyInfo info;
610   std::unique_ptr<ProxyResolutionRequest> request, request2;
611   DeletingCallback<ProxyResolutionRequest> callback(&request2);
612   net::CompletionOnceCallback callback2 =
613       base::BindOnce([](int result) { ASSERT_FALSE(true); });
614 
615   int rv = service->ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
616                                  &info, callback.callback(), &request,
617                                  NetLogWithSource());
618   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
619 
620   rv = service->ResolveProxy(url2, std::string(), NetworkAnonymizationKey(),
621                              &info, std::move(callback2), &request2,
622                              NetLogWithSource());
623   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
624 
625   // Run pending requests.
626   ASSERT_EQ(1u, factory_ptr->pending_requests().size());
627   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
628             factory_ptr->pending_requests()[0]->script_data()->url());
629   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
630 
631   ASSERT_EQ(2u, resolver.pending_jobs().size());
632   // Job order is nondeterministic, as requests are stored in an std::set, so
633   // this loop figures out which one is the correct one to start.
634   int deleting_job = 2;
635   for (int i = 0; i < 2; i++) {
636     if (resolver.pending_jobs()[i]->url() == url) {
637       deleting_job = i;
638       break;
639     }
640     ASSERT_LE(i, 1);  // The loop should never actually make it to the end.
641   }
642 
643   // Set the result in proxy resolver.
644   resolver.pending_jobs()[deleting_job]->results()->UseNamedProxy("foopy");
645   resolver.pending_jobs()[deleting_job]->CompleteNow(OK);
646 
647   //// Only one of the callbacks should have been run:
648   EXPECT_TRUE(callback.have_result());
649   EXPECT_THAT(callback.WaitForResult(), IsOk());
650 
651   ASSERT_EQ(0u, resolver.pending_jobs().size());
652   ASSERT_EQ(1u, resolver.cancelled_jobs().size());
653   ASSERT_EQ(url2, resolver.cancelled_jobs()[0]->url());
654 }
655 
656 // Test that the ConfiguredProxyResolutionService correctly handles the case
657 // where a request callback deletes another request.  (Triggered by the loop in
658 // ConfiguredProxyResolutionService's destructor).
TEST_F(ConfiguredProxyResolutionServiceTest,CallbackDeletesRequestDuringDestructor)659 TEST_F(ConfiguredProxyResolutionServiceTest,
660        CallbackDeletesRequestDuringDestructor) {
661   auto config_service =
662       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
663 
664   MockAsyncProxyResolver resolver;
665   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
666 
667   std::unique_ptr<ConfiguredProxyResolutionService> service =
668       std::make_unique<ConfiguredProxyResolutionService>(
669           std::move(config_service), std::move(factory), nullptr,
670           /*quick_check_enabled=*/true);
671 
672   GURL url("http://www.google.com/");
673 
674   ProxyInfo info;
675   std::unique_ptr<ProxyResolutionRequest> request, request2;
676   DeletingCallback<ProxyResolutionRequest> callback(&request2),
677       callback2(&request);
678 
679   int rv = service->ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
680                                  &info, callback.callback(), &request,
681                                  NetLogWithSource());
682   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
683 
684   rv = service->ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
685                              &info, callback2.callback(), &request2,
686                              NetLogWithSource());
687   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
688 
689   // Make sure that ProxyResolutionServices is deleted before the requests, as
690   // this triggers completion of the pending requests.
691   service.reset();
692 
693   // Only one of the callbacks should have been run:
694   EXPECT_TRUE(callback.have_result() ^ callback2.have_result());
695 
696   // Callbacks run during destruction of ConfiguredProxyResolutionService for
697   // Requests that have not been started are called with net::ERR_ABORTED
698   if (callback.have_result()) {
699     EXPECT_THAT(callback.WaitForResult(),
700                 IsError(net::ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
701   }
702   if (callback2.have_result()) {
703     EXPECT_THAT(callback2.WaitForResult(),
704                 IsError(net::ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
705   }
706 }
707 
708 // Test that the ConfiguredProxyResolutionService correctly handles the case
709 // where a request callback deletes its own handle.
TEST_F(ConfiguredProxyResolutionServiceTest,CallbackDeletesSelf)710 TEST_F(ConfiguredProxyResolutionServiceTest, CallbackDeletesSelf) {
711   auto config_service =
712       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
713 
714   MockAsyncProxyResolver resolver;
715   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
716   auto* factory_ptr = factory.get();
717 
718   std::unique_ptr<ConfiguredProxyResolutionService> service =
719       std::make_unique<ConfiguredProxyResolutionService>(
720           std::move(config_service), std::move(factory), nullptr,
721           /*quick_check_enabled=*/true);
722 
723   GURL url("http://www.google.com/");
724   ProxyInfo info;
725 
726   std::unique_ptr<ProxyResolutionRequest> request1;
727   TestCompletionCallback callback1;
728   int rv = service->ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
729                                  &info, callback1.callback(), &request1,
730                                  NetLogWithSource());
731   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
732 
733   GURL url2("http://www.example.com/");
734   std::unique_ptr<ProxyResolutionRequest> request2;
735   DeletingCallback<ProxyResolutionRequest> callback2(&request2);
736   rv = service->ResolveProxy(url2, std::string(), NetworkAnonymizationKey(),
737                              &info, callback2.callback(), &request2,
738                              NetLogWithSource());
739   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
740 
741   std::unique_ptr<ProxyResolutionRequest> request3;
742   TestCompletionCallback callback3;
743   rv = service->ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
744                              &info, callback3.callback(), &request3,
745                              NetLogWithSource());
746   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
747 
748   ASSERT_EQ(1u, factory_ptr->pending_requests().size());
749   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
750             factory_ptr->pending_requests()[0]->script_data()->url());
751   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
752 
753   ASSERT_EQ(3u, resolver.pending_jobs().size());
754   // Job order is nondeterministic, as requests are stored in an std::set, so
755   // this loop figures out which one is the correct one to start.
756   int self_deleting_job = 3;
757   for (int i = 0; i < 3; i++) {
758     if (resolver.pending_jobs()[i]->url() == url2) {
759       self_deleting_job = i;
760       break;
761     }
762     ASSERT_LE(i, 2);  // The loop should never actually make it to the end.
763   }
764 
765   // Set the result in proxy resolver.
766   resolver.pending_jobs()[self_deleting_job]->results()->UseNamedProxy("foopy");
767   resolver.pending_jobs()[self_deleting_job]->CompleteNow(OK);
768 
769   ASSERT_EQ(2u, resolver.pending_jobs().size());
770   ASSERT_EQ(0u, resolver.cancelled_jobs().size());
771   ASSERT_EQ(url, resolver.pending_jobs()[0]->url());
772   ASSERT_EQ(url, resolver.pending_jobs()[1]->url());
773 }
774 
775 // Test that the ConfiguredProxyResolutionService correctly handles the case
776 // where a request callback deletes its own handle, when triggered by
777 // ConfiguredProxyResolutionService's destructor.
TEST_F(ConfiguredProxyResolutionServiceTest,CallbackDeletesSelfDuringDestructor)778 TEST_F(ConfiguredProxyResolutionServiceTest,
779        CallbackDeletesSelfDuringDestructor) {
780   auto config_service =
781       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
782 
783   MockAsyncProxyResolver resolver;
784   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
785 
786   std::unique_ptr<ConfiguredProxyResolutionService> service =
787       std::make_unique<ConfiguredProxyResolutionService>(
788           std::move(config_service), std::move(factory), nullptr,
789           /*quick_check_enabled=*/true);
790 
791   GURL url("http://www.google.com/");
792   ProxyInfo info;
793 
794   std::unique_ptr<ProxyResolutionRequest> request1;
795   TestCompletionCallback callback1;
796   int rv = service->ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
797                                  &info, callback1.callback(), &request1,
798                                  NetLogWithSource());
799   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
800 
801   std::unique_ptr<ProxyResolutionRequest> request2;
802   DeletingCallback<ProxyResolutionRequest> callback2(&request2);
803   rv = service->ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
804                              &info, callback2.callback(), &request2,
805                              NetLogWithSource());
806   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
807 
808   std::unique_ptr<ProxyResolutionRequest> request3;
809   TestCompletionCallback callback3;
810   rv = service->ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
811                              &info, callback3.callback(), &request3,
812                              NetLogWithSource());
813   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
814 
815   service.reset();
816 
817   EXPECT_THAT(callback1.WaitForResult(),
818               IsError(net::ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
819   EXPECT_THAT(callback2.WaitForResult(),
820               IsError(net::ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
821   EXPECT_THAT(callback3.WaitForResult(),
822               IsError(net::ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
823 }
824 
TEST_F(ConfiguredProxyResolutionServiceTest,ProxyServiceDeletedBeforeRequest)825 TEST_F(ConfiguredProxyResolutionServiceTest, ProxyServiceDeletedBeforeRequest) {
826   auto config_service =
827       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
828 
829   MockAsyncProxyResolver resolver;
830   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
831   auto* factory_ptr = factory.get();
832 
833   GURL url("http://www.google.com/");
834 
835   ProxyInfo info;
836   TestCompletionCallback callback;
837   std::unique_ptr<ProxyResolutionRequest> request;
838 
839   int rv;
840   {
841     ConfiguredProxyResolutionService service(std::move(config_service),
842                                              std::move(factory), nullptr,
843                                              /*quick_check_enabled=*/true);
844     rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
845                               &info, callback.callback(), &request,
846                               NetLogWithSource::Make(NetLogSourceType::NONE));
847     EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
848 
849     EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, request->GetLoadState());
850 
851     ASSERT_EQ(1u, factory_ptr->pending_requests().size());
852     EXPECT_EQ(GURL("http://foopy/proxy.pac"),
853               factory_ptr->pending_requests()[0]->script_data()->url());
854     factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
855     ASSERT_EQ(1u, resolver.pending_jobs().size());
856   }
857 
858   ASSERT_EQ(0u, resolver.pending_jobs().size());
859 
860   EXPECT_THAT(callback.WaitForResult(), IsOk());
861 }
862 
863 // Test that the ConfiguredProxyResolutionService correctly handles the case
864 // where a request callback deletes the service.
TEST_F(ConfiguredProxyResolutionServiceTest,CallbackDeletesService)865 TEST_F(ConfiguredProxyResolutionServiceTest, CallbackDeletesService) {
866   auto config_service =
867       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
868   auto* config_service_ptr = config_service.get();
869 
870   MockAsyncProxyResolver resolver;
871   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
872 
873   std::unique_ptr<ConfiguredProxyResolutionService> service =
874       std::make_unique<ConfiguredProxyResolutionService>(
875           std::move(config_service), std::move(factory), nullptr,
876           /*quick_check_enabled=*/true);
877 
878   GURL url("http://www.google.com/");
879 
880   ProxyInfo info;
881 
882   DeletingCallback<ConfiguredProxyResolutionService> callback(&service);
883   std::unique_ptr<ProxyResolutionRequest> request1;
884   int rv = service->ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
885                                  &info, callback.callback(), &request1,
886                                  NetLogWithSource());
887   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
888 
889   EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, request1->GetLoadState());
890 
891   TestCompletionCallback callback2;
892   std::unique_ptr<ProxyResolutionRequest> request2;
893   rv = service->ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
894                              &info, callback2.callback(), &request2,
895                              NetLogWithSource());
896   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
897 
898   TestCompletionCallback callback3;
899   std::unique_ptr<ProxyResolutionRequest> request3;
900   rv = service->ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
901                              &info, callback3.callback(), &request3,
902                              NetLogWithSource());
903   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
904 
905   config_service_ptr->SetConfig(ProxyConfigWithAnnotation(
906       ProxyConfig::CreateDirect(), TRAFFIC_ANNOTATION_FOR_TESTS));
907 
908   ASSERT_EQ(0u, resolver.pending_jobs().size());
909   ASSERT_THAT(callback.WaitForResult(), IsOk());
910   ASSERT_THAT(callback2.WaitForResult(), IsOk());
911   ASSERT_THAT(callback3.WaitForResult(), IsOk());
912 }
913 
TEST_F(ConfiguredProxyResolutionServiceTest,PAC)914 TEST_F(ConfiguredProxyResolutionServiceTest, PAC) {
915   auto config_service =
916       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
917 
918   MockAsyncProxyResolver resolver;
919   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
920   auto* factory_ptr = factory.get();
921 
922   ConfiguredProxyResolutionService service(std::move(config_service),
923                                            std::move(factory), nullptr,
924                                            /*quick_check_enabled=*/true);
925 
926   GURL url("http://www.google.com/");
927 
928   ProxyInfo info;
929   TestCompletionCallback callback;
930   std::unique_ptr<ProxyResolutionRequest> request;
931   RecordingNetLogObserver net_log_observer;
932 
933   int rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
934                                 &info, callback.callback(), &request,
935                                 NetLogWithSource::Make(NetLogSourceType::NONE));
936   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
937 
938   EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, request->GetLoadState());
939 
940   ASSERT_EQ(1u, factory_ptr->pending_requests().size());
941   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
942             factory_ptr->pending_requests()[0]->script_data()->url());
943   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
944 
945   ASSERT_EQ(1u, resolver.pending_jobs().size());
946   EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
947 
948   // Set the result in proxy resolver.
949   resolver.pending_jobs()[0]->results()->UseNamedProxy("foopy");
950   resolver.pending_jobs()[0]->CompleteNow(OK);
951 
952   EXPECT_THAT(callback.WaitForResult(), IsOk());
953   EXPECT_FALSE(info.is_direct());
954   EXPECT_EQ("[foopy:80]", info.proxy_chain().ToDebugString());
955 
956   EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
957   EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
958   EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
959 
960   // Check the NetLog was filled correctly.
961   auto entries = net_log_observer.GetEntries();
962 
963   EXPECT_EQ(5u, entries.size());
964   EXPECT_TRUE(LogContainsBeginEvent(entries, 0,
965                                     NetLogEventType::PROXY_RESOLUTION_SERVICE));
966   EXPECT_TRUE(LogContainsBeginEvent(
967       entries, 1,
968       NetLogEventType::PROXY_RESOLUTION_SERVICE_WAITING_FOR_INIT_PAC));
969   EXPECT_TRUE(LogContainsEndEvent(
970       entries, 2,
971       NetLogEventType::PROXY_RESOLUTION_SERVICE_WAITING_FOR_INIT_PAC));
972   EXPECT_TRUE(LogContainsEndEvent(entries, 4,
973                                   NetLogEventType::PROXY_RESOLUTION_SERVICE));
974 }
975 
976 // Test that the proxy resolver does not see the URL's username/password
977 // or its reference section.
TEST_F(ConfiguredProxyResolutionServiceTest,PAC_NoIdentityOrHash)978 TEST_F(ConfiguredProxyResolutionServiceTest, PAC_NoIdentityOrHash) {
979   auto config_service =
980       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
981 
982   MockAsyncProxyResolver resolver;
983   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
984   auto* factory_ptr = factory.get();
985 
986   ConfiguredProxyResolutionService service(std::move(config_service),
987                                            std::move(factory), nullptr,
988                                            /*quick_check_enabled=*/true);
989 
990   GURL url("http://username:password@www.google.com/?ref#hash#hash");
991 
992   ProxyInfo info;
993   TestCompletionCallback callback;
994   std::unique_ptr<ProxyResolutionRequest> request;
995   int rv =
996       service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(), &info,
997                            callback.callback(), &request, NetLogWithSource());
998   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
999 
1000   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1001             factory_ptr->pending_requests()[0]->script_data()->url());
1002   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1003 
1004   ASSERT_EQ(1u, resolver.pending_jobs().size());
1005   // The URL should have been simplified, stripping the username/password/hash.
1006   EXPECT_EQ(GURL("http://www.google.com/?ref"),
1007             resolver.pending_jobs()[0]->url());
1008 
1009   // We end here without ever completing the request -- destruction of
1010   // ConfiguredProxyResolutionService will cancel the outstanding request.
1011 }
1012 
TEST_F(ConfiguredProxyResolutionServiceTest,PAC_FailoverWithoutDirect)1013 TEST_F(ConfiguredProxyResolutionServiceTest, PAC_FailoverWithoutDirect) {
1014   auto config_service =
1015       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
1016   MockAsyncProxyResolver resolver;
1017   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
1018   auto* factory_ptr = factory.get();
1019 
1020   ConfiguredProxyResolutionService service(std::move(config_service),
1021                                            std::move(factory), nullptr,
1022                                            /*quick_check_enabled=*/true);
1023 
1024   GURL url("http://www.google.com/");
1025 
1026   ProxyInfo info;
1027   TestCompletionCallback callback1;
1028   std::unique_ptr<ProxyResolutionRequest> request1;
1029   int rv =
1030       service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(), &info,
1031                            callback1.callback(), &request1, NetLogWithSource());
1032   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1033 
1034   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1035             factory_ptr->pending_requests()[0]->script_data()->url());
1036   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1037 
1038   ASSERT_EQ(1u, resolver.pending_jobs().size());
1039   EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
1040 
1041   // Set the result in proxy resolver.
1042   resolver.pending_jobs()[0]->results()->UseNamedProxy("foopy:8080");
1043   resolver.pending_jobs()[0]->CompleteNow(OK);
1044 
1045   EXPECT_THAT(callback1.WaitForResult(), IsOk());
1046   EXPECT_FALSE(info.is_direct());
1047   EXPECT_EQ("[foopy:8080]", info.proxy_chain().ToDebugString());
1048 
1049   EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1050   EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1051   EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1052 
1053   // Now, imagine that connecting to foopy:8080 fails: there is nothing
1054   // left to fallback to, since our proxy list was NOT terminated by
1055   // DIRECT.
1056   EXPECT_FALSE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
1057   EXPECT_TRUE(info.is_empty());
1058 }
1059 
1060 // Test that if the execution of the PAC script fails (i.e. javascript runtime
1061 // error), and the PAC settings are non-mandatory, that we fall-back to direct.
TEST_F(ConfiguredProxyResolutionServiceTest,PAC_RuntimeError)1062 TEST_F(ConfiguredProxyResolutionServiceTest, PAC_RuntimeError) {
1063   auto config_service =
1064       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
1065   MockAsyncProxyResolver resolver;
1066   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
1067   auto* factory_ptr = factory.get();
1068 
1069   ConfiguredProxyResolutionService service(std::move(config_service),
1070                                            std::move(factory), nullptr,
1071                                            /*quick_check_enabled=*/true);
1072 
1073   GURL url("http://this-causes-js-error/");
1074 
1075   ProxyInfo info;
1076   TestCompletionCallback callback1;
1077   std::unique_ptr<ProxyResolutionRequest> request1;
1078   int rv =
1079       service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(), &info,
1080                            callback1.callback(), &request1, NetLogWithSource());
1081   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1082 
1083   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1084             factory_ptr->pending_requests()[0]->script_data()->url());
1085   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1086 
1087   ASSERT_EQ(1u, resolver.pending_jobs().size());
1088   EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
1089 
1090   // Simulate a failure in the PAC executor.
1091   resolver.pending_jobs()[0]->CompleteNow(ERR_PAC_SCRIPT_FAILED);
1092 
1093   EXPECT_THAT(callback1.WaitForResult(), IsOk());
1094 
1095   // Since the PAC script was non-mandatory, we should have fallen-back to
1096   // DIRECT.
1097   EXPECT_TRUE(info.is_direct());
1098 
1099   EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1100   EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1101   EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1102 }
1103 
1104 // The proxy list could potentially contain the DIRECT fallback choice
1105 // in a location other than the very end of the list, and could even
1106 // specify it multiple times.
1107 //
1108 // This is not a typical usage, but we will obey it.
1109 // (If we wanted to disallow this type of input, the right place to
1110 // enforce it would be in parsing the PAC result string).
1111 //
1112 // This test will use the PAC result string:
1113 //
1114 //   "DIRECT ; PROXY foobar:10 ; DIRECT ; PROXY foobar:20"
1115 //
1116 // For which we expect it to try DIRECT, then foobar:10, then DIRECT again,
1117 // then foobar:20, and then give up and error.
1118 //
1119 // The important check of this test is to make sure that DIRECT is not somehow
1120 // cached as being a bad proxy.
TEST_F(ConfiguredProxyResolutionServiceTest,PAC_FailoverAfterDirect)1121 TEST_F(ConfiguredProxyResolutionServiceTest, PAC_FailoverAfterDirect) {
1122   auto config_service =
1123       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
1124   MockAsyncProxyResolver resolver;
1125   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
1126   auto* factory_ptr = factory.get();
1127 
1128   ConfiguredProxyResolutionService service(std::move(config_service),
1129                                            std::move(factory), nullptr,
1130                                            /*quick_check_enabled=*/true);
1131 
1132   GURL url("http://www.google.com/");
1133 
1134   ProxyInfo info;
1135   TestCompletionCallback callback1;
1136   std::unique_ptr<ProxyResolutionRequest> request1;
1137   int rv =
1138       service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(), &info,
1139                            callback1.callback(), &request1, NetLogWithSource());
1140   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1141 
1142   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1143             factory_ptr->pending_requests()[0]->script_data()->url());
1144   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1145 
1146   ASSERT_EQ(1u, resolver.pending_jobs().size());
1147   EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
1148 
1149   // Set the result in proxy resolver.
1150   resolver.pending_jobs()[0]->results()->UsePacString(
1151       "DIRECT ; PROXY foobar:10 ; DIRECT ; PROXY foobar:20");
1152   resolver.pending_jobs()[0]->CompleteNow(OK);
1153 
1154   EXPECT_THAT(callback1.WaitForResult(), IsOk());
1155   EXPECT_TRUE(info.is_direct());
1156 
1157   // Fallback 1.
1158   EXPECT_TRUE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
1159   EXPECT_FALSE(info.is_direct());
1160   EXPECT_EQ("[foobar:10]", info.proxy_chain().ToDebugString());
1161 
1162   // Fallback 2.
1163   EXPECT_TRUE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
1164   EXPECT_TRUE(info.is_direct());
1165 
1166   // Fallback 3.
1167   EXPECT_TRUE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
1168   EXPECT_FALSE(info.is_direct());
1169   EXPECT_EQ("[foobar:20]", info.proxy_chain().ToDebugString());
1170 
1171   // Fallback 4 -- Nothing to fall back to!
1172   EXPECT_FALSE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
1173   EXPECT_TRUE(info.is_empty());
1174 }
1175 
TEST_F(ConfiguredProxyResolutionServiceTest,PAC_ConfigSourcePropagates)1176 TEST_F(ConfiguredProxyResolutionServiceTest, PAC_ConfigSourcePropagates) {
1177   // Test whether the ProxyConfigSource set by the ProxyConfigService is applied
1178   // to ProxyInfo after the proxy is resolved via a PAC script.
1179   ProxyConfig config =
1180       ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"));
1181 
1182   auto config_service = std::make_unique<MockProxyConfigService>(config);
1183   MockAsyncProxyResolver resolver;
1184   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
1185   auto* factory_ptr = factory.get();
1186   ConfiguredProxyResolutionService service(std::move(config_service),
1187                                            std::move(factory), nullptr,
1188                                            /*quick_check_enabled=*/true);
1189 
1190   // Resolve something.
1191   GURL url("http://www.google.com/");
1192   ProxyInfo info;
1193   TestCompletionCallback callback;
1194   std::unique_ptr<ProxyResolutionRequest> request;
1195   int rv =
1196       service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(), &info,
1197                            callback.callback(), &request, NetLogWithSource());
1198   ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
1199   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1200   ASSERT_EQ(1u, resolver.pending_jobs().size());
1201 
1202   // Set the result in proxy resolver.
1203   resolver.pending_jobs()[0]->results()->UseNamedProxy("foopy");
1204   resolver.pending_jobs()[0]->CompleteNow(OK);
1205 
1206   EXPECT_THAT(callback.WaitForResult(), IsOk());
1207   EXPECT_EQ(MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS),
1208             info.traffic_annotation());
1209 
1210   EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1211   EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1212   EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1213 }
1214 
TEST_F(ConfiguredProxyResolutionServiceTest,ProxyResolverFails)1215 TEST_F(ConfiguredProxyResolutionServiceTest, ProxyResolverFails) {
1216   // Test what happens when the ProxyResolver fails. The download and setting
1217   // of the PAC script have already succeeded, so this corresponds with a
1218   // javascript runtime error while calling FindProxyForURL().
1219 
1220   auto config_service =
1221       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
1222 
1223   MockAsyncProxyResolver resolver;
1224   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
1225   auto* factory_ptr = factory.get();
1226 
1227   ConfiguredProxyResolutionService service(std::move(config_service),
1228                                            std::move(factory), nullptr,
1229                                            /*quick_check_enabled=*/true);
1230 
1231   // Start first resolve request.
1232   GURL url("http://www.google.com/");
1233   ProxyInfo info;
1234   TestCompletionCallback callback1;
1235   std::unique_ptr<ProxyResolutionRequest> request;
1236   int rv =
1237       service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(), &info,
1238                            callback1.callback(), &request, NetLogWithSource());
1239   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1240 
1241   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1242             factory_ptr->pending_requests()[0]->script_data()->url());
1243   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1244 
1245   ASSERT_EQ(1u, resolver.pending_jobs().size());
1246   EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
1247 
1248   // Fail the first resolve request in MockAsyncProxyResolver.
1249   resolver.pending_jobs()[0]->CompleteNow(ERR_FAILED);
1250 
1251   // Although the proxy resolver failed the request,
1252   // ConfiguredProxyResolutionService implicitly falls-back to DIRECT.
1253   EXPECT_THAT(callback1.WaitForResult(), IsOk());
1254   EXPECT_TRUE(info.is_direct());
1255 
1256   // Failed PAC executions still have proxy resolution times.
1257   EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1258   EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1259   EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1260 
1261   // The second resolve request will try to run through the proxy resolver,
1262   // regardless of whether the first request failed in it.
1263   TestCompletionCallback callback2;
1264   rv =
1265       service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(), &info,
1266                            callback2.callback(), &request, NetLogWithSource());
1267   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1268 
1269   ASSERT_EQ(1u, resolver.pending_jobs().size());
1270   EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
1271 
1272   // This time we will have the resolver succeed (perhaps the PAC script has
1273   // a dependency on the current time).
1274   resolver.pending_jobs()[0]->results()->UseNamedProxy("foopy_valid:8080");
1275   resolver.pending_jobs()[0]->CompleteNow(OK);
1276 
1277   EXPECT_THAT(callback2.WaitForResult(), IsOk());
1278   EXPECT_FALSE(info.is_direct());
1279   EXPECT_EQ("[foopy_valid:8080]", info.proxy_chain().ToDebugString());
1280 }
1281 
TEST_F(ConfiguredProxyResolutionServiceTest,ProxyResolverTerminatedDuringRequest)1282 TEST_F(ConfiguredProxyResolutionServiceTest,
1283        ProxyResolverTerminatedDuringRequest) {
1284   // Test what happens when the ProxyResolver fails with a fatal error while
1285   // a GetProxyForURL() call is in progress.
1286 
1287   auto config_service =
1288       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
1289 
1290   MockAsyncProxyResolver resolver;
1291   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
1292   auto* factory_ptr = factory.get();
1293 
1294   ConfiguredProxyResolutionService service(std::move(config_service),
1295                                            std::move(factory), nullptr,
1296                                            /*quick_check_enabled=*/true);
1297 
1298   // Start first resolve request.
1299   GURL url("http://www.google.com/");
1300   ProxyInfo info;
1301   TestCompletionCallback callback1;
1302   std::unique_ptr<ProxyResolutionRequest> request;
1303   int rv =
1304       service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(), &info,
1305                            callback1.callback(), &request, NetLogWithSource());
1306   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1307 
1308   ASSERT_EQ(1u, factory_ptr->pending_requests().size());
1309   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1310             factory_ptr->pending_requests()[0]->script_data()->url());
1311   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1312 
1313   ASSERT_EQ(1u, resolver.pending_jobs().size());
1314   EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
1315 
1316   // Fail the first resolve request in MockAsyncProxyResolver.
1317   resolver.pending_jobs()[0]->CompleteNow(ERR_PAC_SCRIPT_TERMINATED);
1318 
1319   // Although the proxy resolver failed the request,
1320   // ConfiguredProxyResolutionService implicitly falls-back to DIRECT.
1321   EXPECT_THAT(callback1.WaitForResult(), IsOk());
1322   EXPECT_TRUE(info.is_direct());
1323 
1324   // Failed PAC executions still have proxy resolution times.
1325   EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1326   EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1327   EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1328 
1329   // With no other requests, the ConfiguredProxyResolutionService waits for a
1330   // new request before initializing a new ProxyResolver.
1331   EXPECT_TRUE(factory_ptr->pending_requests().empty());
1332 
1333   TestCompletionCallback callback2;
1334   rv =
1335       service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(), &info,
1336                            callback2.callback(), &request, NetLogWithSource());
1337   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1338 
1339   ASSERT_EQ(1u, factory_ptr->pending_requests().size());
1340   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1341             factory_ptr->pending_requests()[0]->script_data()->url());
1342   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1343 
1344   ASSERT_EQ(1u, resolver.pending_jobs().size());
1345   EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
1346 
1347   // This time we will have the resolver succeed.
1348   resolver.pending_jobs()[0]->results()->UseNamedProxy("foopy_valid:8080");
1349   resolver.pending_jobs()[0]->CompleteNow(OK);
1350 
1351   EXPECT_THAT(callback2.WaitForResult(), IsOk());
1352   EXPECT_FALSE(info.is_direct());
1353   EXPECT_EQ("[foopy_valid:8080]", info.proxy_chain().ToDebugString());
1354 }
1355 
TEST_F(ConfiguredProxyResolutionServiceTest,ProxyResolverTerminatedDuringRequestWithConcurrentRequest)1356 TEST_F(ConfiguredProxyResolutionServiceTest,
1357        ProxyResolverTerminatedDuringRequestWithConcurrentRequest) {
1358   // Test what happens when the ProxyResolver fails with a fatal error while
1359   // a GetProxyForURL() call is in progress.
1360 
1361   auto config_service =
1362       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
1363 
1364   MockAsyncProxyResolver resolver;
1365   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
1366   auto* factory_ptr = factory.get();
1367 
1368   ConfiguredProxyResolutionService service(std::move(config_service),
1369                                            std::move(factory), nullptr,
1370                                            /*quick_check_enabled=*/true);
1371 
1372   // Start two resolve requests.
1373   GURL url1("http://www.google.com/");
1374   GURL url2("https://www.google.com/");
1375   ProxyInfo info;
1376   TestCompletionCallback callback1;
1377   std::unique_ptr<ProxyResolutionRequest> request1, request2;
1378   int rv = service.ResolveProxy(url1, std::string(), NetworkAnonymizationKey(),
1379                                 &info, callback1.callback(), &request1,
1380                                 NetLogWithSource());
1381   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1382   TestCompletionCallback callback2;
1383   rv = service.ResolveProxy(url2, std::string(), NetworkAnonymizationKey(),
1384                             &info, callback2.callback(), &request2,
1385                             NetLogWithSource());
1386   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1387 
1388   ASSERT_EQ(1u, factory_ptr->pending_requests().size());
1389   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1390             factory_ptr->pending_requests()[0]->script_data()->url());
1391   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1392 
1393   JobMap jobs = GetPendingJobsForURLs(resolver, url1, url2);
1394 
1395   // Fail the first resolve request in MockAsyncProxyResolver.
1396   jobs[url1]->CompleteNow(ERR_PAC_SCRIPT_TERMINATED);
1397 
1398   // Although the proxy resolver failed the request,
1399   // ConfiguredProxyResolutionService implicitly falls-back to DIRECT.
1400   EXPECT_THAT(callback1.WaitForResult(), IsOk());
1401   EXPECT_TRUE(info.is_direct());
1402 
1403   // Failed PAC executions still have proxy resolution times.
1404   EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1405   EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1406   EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1407 
1408   // The second request is cancelled when the proxy resolver terminates.
1409   jobs = GetCancelledJobsForURLs(resolver, url2);
1410 
1411   // Since a second request was in progress, the
1412   // ConfiguredProxyResolutionService starts initializating a new ProxyResolver.
1413   ASSERT_EQ(1u, factory_ptr->pending_requests().size());
1414   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1415             factory_ptr->pending_requests()[0]->script_data()->url());
1416   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1417 
1418   jobs = GetPendingJobsForURLs(resolver, url2);
1419 
1420   // This request succeeds.
1421   jobs[url2]->results()->UseNamedProxy("foopy_valid:8080");
1422   jobs[url2]->CompleteNow(OK);
1423 
1424   EXPECT_THAT(callback2.WaitForResult(), IsOk());
1425   EXPECT_FALSE(info.is_direct());
1426   EXPECT_EQ("[foopy_valid:8080]", info.proxy_chain().ToDebugString());
1427 }
1428 
TEST_F(ConfiguredProxyResolutionServiceTest,PacFileFetcherFailsDownloadingMandatoryPac)1429 TEST_F(ConfiguredProxyResolutionServiceTest,
1430        PacFileFetcherFailsDownloadingMandatoryPac) {
1431   // Test what happens when the ProxyResolver fails to download a mandatory PAC
1432   // script.
1433 
1434   ProxyConfig config(
1435       ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
1436   config.set_pac_mandatory(true);
1437 
1438   auto config_service = std::make_unique<MockProxyConfigService>(config);
1439 
1440   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
1441   auto* factory_ptr = factory.get();
1442 
1443   ConfiguredProxyResolutionService service(std::move(config_service),
1444                                            std::move(factory), nullptr,
1445                                            /*quick_check_enabled=*/true);
1446 
1447   // Start first resolve request.
1448   GURL url("http://www.google.com/");
1449   ProxyInfo info;
1450   TestCompletionCallback callback1;
1451   std::unique_ptr<ProxyResolutionRequest> request;
1452   int rv =
1453       service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(), &info,
1454                            callback1.callback(), &request, NetLogWithSource());
1455   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1456 
1457   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1458             factory_ptr->pending_requests()[0]->script_data()->url());
1459   factory_ptr->pending_requests()[0]->CompleteNow(ERR_FAILED, nullptr);
1460 
1461   ASSERT_EQ(0u, factory_ptr->pending_requests().size());
1462   // As the proxy resolver factory failed the request and is configured for a
1463   // mandatory PAC script, ConfiguredProxyResolutionService must not implicitly
1464   // fall-back to DIRECT.
1465   EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
1466             callback1.WaitForResult());
1467   EXPECT_FALSE(info.is_direct());
1468 
1469   // As the proxy resolver factory failed the request and is configured for a
1470   // mandatory PAC script, ConfiguredProxyResolutionService must not implicitly
1471   // fall-back to DIRECT.
1472   TestCompletionCallback callback2;
1473   rv =
1474       service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(), &info,
1475                            callback2.callback(), &request, NetLogWithSource());
1476   EXPECT_THAT(rv, IsError(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED));
1477   EXPECT_FALSE(info.is_direct());
1478 }
1479 
TEST_F(ConfiguredProxyResolutionServiceTest,ProxyResolverFailsParsingJavaScriptMandatoryPac)1480 TEST_F(ConfiguredProxyResolutionServiceTest,
1481        ProxyResolverFailsParsingJavaScriptMandatoryPac) {
1482   // Test what happens when the ProxyResolver fails that is configured to use a
1483   // mandatory PAC script. The download of the PAC script has already
1484   // succeeded but the PAC script contains no valid javascript.
1485 
1486   ProxyConfig config(
1487       ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
1488   config.set_pac_mandatory(true);
1489 
1490   auto config_service = std::make_unique<MockProxyConfigService>(config);
1491 
1492   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
1493   auto* factory_ptr = factory.get();
1494 
1495   ConfiguredProxyResolutionService service(std::move(config_service),
1496                                            std::move(factory), nullptr,
1497                                            /*quick_check_enabled=*/true);
1498 
1499   auto fetcher = std::make_unique<MockPacFileFetcher>();
1500   auto* fetcher_ptr = fetcher.get();
1501   service.SetPacFileFetchers(std::move(fetcher),
1502                              std::make_unique<DoNothingDhcpPacFileFetcher>());
1503 
1504   // Start resolve request.
1505   GURL url("http://www.google.com/");
1506   ProxyInfo info;
1507   TestCompletionCallback callback;
1508   std::unique_ptr<ProxyResolutionRequest> request;
1509   int rv =
1510       service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(), &info,
1511                            callback.callback(), &request, NetLogWithSource());
1512   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1513 
1514   // Check that nothing has been sent to the proxy resolver factory yet.
1515   ASSERT_EQ(0u, factory_ptr->pending_requests().size());
1516 
1517   // Downloading the PAC script succeeds.
1518   EXPECT_TRUE(fetcher_ptr->has_pending_request());
1519   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
1520   fetcher_ptr->NotifyFetchCompletion(OK, "invalid-script-contents");
1521 
1522   EXPECT_FALSE(fetcher_ptr->has_pending_request());
1523   ASSERT_EQ(0u, factory_ptr->pending_requests().size());
1524 
1525   // Since PacFileDecider failed to identify a valid PAC and PAC was
1526   // mandatory for this configuration, the ConfiguredProxyResolutionService must
1527   // not implicitly fall-back to DIRECT.
1528   EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED, callback.WaitForResult());
1529   EXPECT_FALSE(info.is_direct());
1530 }
1531 
TEST_F(ConfiguredProxyResolutionServiceTest,ProxyResolverFailsInJavaScriptMandatoryPac)1532 TEST_F(ConfiguredProxyResolutionServiceTest,
1533        ProxyResolverFailsInJavaScriptMandatoryPac) {
1534   // Test what happens when the ProxyResolver fails that is configured to use a
1535   // mandatory PAC script. The download and setting of the PAC script have
1536   // already succeeded, so this corresponds with a javascript runtime error
1537   // while calling FindProxyForURL().
1538 
1539   ProxyConfig config(
1540       ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
1541   config.set_pac_mandatory(true);
1542 
1543   auto config_service = std::make_unique<MockProxyConfigService>(config);
1544 
1545   MockAsyncProxyResolver resolver;
1546   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
1547   auto* factory_ptr = factory.get();
1548 
1549   ConfiguredProxyResolutionService service(std::move(config_service),
1550                                            std::move(factory), nullptr,
1551                                            /*quick_check_enabled=*/true);
1552 
1553   // Start first resolve request.
1554   GURL url("http://www.google.com/");
1555   ProxyInfo info;
1556   TestCompletionCallback callback1;
1557   std::unique_ptr<ProxyResolutionRequest> request;
1558   int rv =
1559       service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(), &info,
1560                            callback1.callback(), &request, NetLogWithSource());
1561   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1562 
1563   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1564             factory_ptr->pending_requests()[0]->script_data()->url());
1565   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1566 
1567   ASSERT_EQ(1u, resolver.pending_jobs().size());
1568   EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
1569 
1570   // Fail the first resolve request in MockAsyncProxyResolver.
1571   resolver.pending_jobs()[0]->CompleteNow(ERR_FAILED);
1572 
1573   // As the proxy resolver failed the request and is configured for a mandatory
1574   // PAC script, ConfiguredProxyResolutionService must not implicitly fall-back
1575   // to DIRECT.
1576   EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
1577             callback1.WaitForResult());
1578   EXPECT_FALSE(info.is_direct());
1579 
1580   // The second resolve request will try to run through the proxy resolver,
1581   // regardless of whether the first request failed in it.
1582   TestCompletionCallback callback2;
1583   rv =
1584       service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(), &info,
1585                            callback2.callback(), &request, NetLogWithSource());
1586   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1587 
1588   ASSERT_EQ(1u, resolver.pending_jobs().size());
1589   EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
1590 
1591   // This time we will have the resolver succeed (perhaps the PAC script has
1592   // a dependency on the current time).
1593   resolver.pending_jobs()[0]->results()->UseNamedProxy("foopy_valid:8080");
1594   resolver.pending_jobs()[0]->CompleteNow(OK);
1595 
1596   EXPECT_THAT(callback2.WaitForResult(), IsOk());
1597   EXPECT_FALSE(info.is_direct());
1598   EXPECT_EQ("[foopy_valid:8080]", info.proxy_chain().ToDebugString());
1599 }
1600 
TEST_F(ConfiguredProxyResolutionServiceTest,ProxyFallback)1601 TEST_F(ConfiguredProxyResolutionServiceTest, ProxyFallback) {
1602   // Test what happens when we specify multiple proxy servers and some of them
1603   // are bad.
1604 
1605   auto config_service =
1606       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
1607 
1608   MockAsyncProxyResolver resolver;
1609   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
1610   auto* factory_ptr = factory.get();
1611 
1612   ConfiguredProxyResolutionService service(std::move(config_service),
1613                                            std::move(factory), nullptr,
1614                                            /*quick_check_enabled=*/true);
1615 
1616   GURL url("http://www.google.com/");
1617 
1618   // Get the proxy information.
1619   ProxyInfo info;
1620   TestCompletionCallback callback1;
1621   std::unique_ptr<ProxyResolutionRequest> request;
1622   int rv =
1623       service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(), &info,
1624                            callback1.callback(), &request, NetLogWithSource());
1625   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1626 
1627   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1628             factory_ptr->pending_requests()[0]->script_data()->url());
1629   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1630 
1631   ASSERT_EQ(1u, resolver.pending_jobs().size());
1632   EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
1633 
1634   // Set the result in proxy resolver.
1635   resolver.pending_jobs()[0]->results()->UseNamedProxy(
1636       "foopy1:8080;foopy2:9090");
1637   resolver.pending_jobs()[0]->CompleteNow(OK);
1638 
1639   // The first item is valid.
1640   EXPECT_THAT(callback1.WaitForResult(), IsOk());
1641   EXPECT_FALSE(info.is_direct());
1642   EXPECT_EQ("[foopy1:8080]", info.proxy_chain().ToDebugString());
1643 
1644   EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1645   EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1646   EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1647   base::TimeTicks proxy_resolve_start_time = info.proxy_resolve_start_time();
1648   base::TimeTicks proxy_resolve_end_time = info.proxy_resolve_end_time();
1649 
1650   // Fake an error on the proxy.
1651   EXPECT_TRUE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
1652 
1653   // Proxy times should not have been modified by fallback.
1654   EXPECT_EQ(proxy_resolve_start_time, info.proxy_resolve_start_time());
1655   EXPECT_EQ(proxy_resolve_end_time, info.proxy_resolve_end_time());
1656 
1657   // The second proxy should be specified.
1658   EXPECT_EQ("[foopy2:9090]", info.proxy_chain().ToDebugString());
1659   // Report back that the second proxy worked.  This will globally mark the
1660   // first proxy as bad.
1661   TestProxyFallbackProxyDelegate test_delegate;
1662   service.SetProxyDelegate(&test_delegate);
1663   service.ReportSuccess(info);
1664   EXPECT_EQ("[foopy1:8080]", test_delegate.proxy_chain().ToDebugString());
1665   EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED,
1666             test_delegate.last_proxy_fallback_net_error());
1667   service.SetProxyDelegate(nullptr);
1668 
1669   TestCompletionCallback callback3;
1670   rv =
1671       service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(), &info,
1672                            callback3.callback(), &request, NetLogWithSource());
1673   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1674 
1675   ASSERT_EQ(1u, resolver.pending_jobs().size());
1676   EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
1677 
1678   // Set the result in proxy resolver -- the second result is already known
1679   // to be bad, so we will not try to use it initially.
1680   resolver.pending_jobs()[0]->results()->UseNamedProxy(
1681       "foopy3:7070;foopy1:8080;foopy2:9090");
1682   resolver.pending_jobs()[0]->CompleteNow(OK);
1683 
1684   EXPECT_THAT(callback3.WaitForResult(), IsOk());
1685   EXPECT_FALSE(info.is_direct());
1686   EXPECT_EQ("[foopy3:7070]", info.proxy_chain().ToDebugString());
1687 
1688   // Proxy times should have been updated, so get them again.
1689   EXPECT_LE(proxy_resolve_end_time, info.proxy_resolve_start_time());
1690   EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1691   EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1692   EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1693   proxy_resolve_start_time = info.proxy_resolve_start_time();
1694   proxy_resolve_end_time = info.proxy_resolve_end_time();
1695 
1696   // We fake another error. It should now try the third one.
1697   EXPECT_TRUE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
1698   EXPECT_EQ("[foopy2:9090]", info.proxy_chain().ToDebugString());
1699 
1700   // We fake another error. At this point we have tried all of the
1701   // proxy servers we thought were valid; next we try the proxy server
1702   // that was in our bad proxies map (foopy1:8080).
1703   EXPECT_TRUE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
1704   EXPECT_EQ("[foopy1:8080]", info.proxy_chain().ToDebugString());
1705 
1706   // Fake another error, the last proxy is gone, the list should now be empty,
1707   // so there is nothing left to try.
1708   EXPECT_FALSE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
1709   EXPECT_FALSE(info.is_direct());
1710   EXPECT_TRUE(info.is_empty());
1711 
1712   // Proxy times should not have been modified by fallback.
1713   EXPECT_EQ(proxy_resolve_start_time, info.proxy_resolve_start_time());
1714   EXPECT_EQ(proxy_resolve_end_time, info.proxy_resolve_end_time());
1715 
1716   // Look up proxies again
1717   TestCompletionCallback callback7;
1718   rv =
1719       service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(), &info,
1720                            callback7.callback(), &request, NetLogWithSource());
1721   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1722 
1723   ASSERT_EQ(1u, resolver.pending_jobs().size());
1724   EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
1725 
1726   // This time, the first 3 results have been found to be bad, but only the
1727   // first proxy has been confirmed ...
1728   resolver.pending_jobs()[0]->results()->UseNamedProxy(
1729       "foopy1:8080;foopy3:7070;foopy2:9090;foopy4:9091");
1730   resolver.pending_jobs()[0]->CompleteNow(OK);
1731 
1732   // ... therefore, we should see the second proxy first.
1733   EXPECT_THAT(callback7.WaitForResult(), IsOk());
1734   EXPECT_FALSE(info.is_direct());
1735   EXPECT_EQ("[foopy3:7070]", info.proxy_chain().ToDebugString());
1736 
1737   EXPECT_LE(proxy_resolve_end_time, info.proxy_resolve_start_time());
1738   EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1739   EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1740   // TODO(nsylvain): Test that the proxy can be retried after the delay.
1741 }
1742 
1743 // This test is similar to ProxyFallback, but this time we have an explicit
1744 // fallback choice to DIRECT.
TEST_F(ConfiguredProxyResolutionServiceTest,ProxyFallbackToDirect)1745 TEST_F(ConfiguredProxyResolutionServiceTest, ProxyFallbackToDirect) {
1746   auto config_service =
1747       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
1748 
1749   MockAsyncProxyResolver resolver;
1750   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
1751   auto* factory_ptr = factory.get();
1752 
1753   ConfiguredProxyResolutionService service(std::move(config_service),
1754                                            std::move(factory), nullptr,
1755                                            /*quick_check_enabled=*/true);
1756 
1757   GURL url("http://www.google.com/");
1758 
1759   // Get the proxy information.
1760   ProxyInfo info;
1761   TestCompletionCallback callback1;
1762   std::unique_ptr<ProxyResolutionRequest> request1;
1763   int rv =
1764       service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(), &info,
1765                            callback1.callback(), &request1, NetLogWithSource());
1766   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1767 
1768   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1769             factory_ptr->pending_requests()[0]->script_data()->url());
1770   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1771 
1772   ASSERT_EQ(1u, resolver.pending_jobs().size());
1773   EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
1774 
1775   // Set the result in proxy resolver.
1776   resolver.pending_jobs()[0]->results()->UsePacString(
1777       "PROXY foopy1:8080; PROXY foopy2:9090; DIRECT");
1778   resolver.pending_jobs()[0]->CompleteNow(OK);
1779 
1780   // Get the first result.
1781   EXPECT_THAT(callback1.WaitForResult(), IsOk());
1782   EXPECT_FALSE(info.is_direct());
1783   EXPECT_EQ("[foopy1:8080]", info.proxy_chain().ToDebugString());
1784 
1785   // Fake an error on the proxy.
1786   EXPECT_TRUE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
1787 
1788   // Now we get back the second proxy.
1789   EXPECT_EQ("[foopy2:9090]", info.proxy_chain().ToDebugString());
1790 
1791   // Fake an error on this proxy as well.
1792   EXPECT_TRUE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
1793 
1794   // Finally, we get back DIRECT.
1795   EXPECT_TRUE(info.is_direct());
1796 
1797   EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1798   EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1799   EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1800 
1801   // Now we tell the proxy service that even DIRECT failed.
1802   // There was nothing left to try after DIRECT, so we are out of
1803   // choices.
1804   EXPECT_FALSE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
1805 }
1806 
TEST_F(ConfiguredProxyResolutionServiceTest,ProxyFallback_BadConfig)1807 TEST_F(ConfiguredProxyResolutionServiceTest, ProxyFallback_BadConfig) {
1808   // Test proxy failover when the configuration is bad.
1809 
1810   auto config_service =
1811       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
1812 
1813   MockAsyncProxyResolver resolver;
1814   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
1815   auto* factory_ptr = factory.get();
1816 
1817   ConfiguredProxyResolutionService service(std::move(config_service),
1818                                            std::move(factory), nullptr,
1819                                            /*quick_check_enabled=*/true);
1820 
1821   GURL url("http://www.google.com/");
1822 
1823   // Get the proxy information.
1824   ProxyInfo info;
1825   TestCompletionCallback callback1;
1826   TestResolveProxyDelegate delegate;
1827   std::unique_ptr<ProxyResolutionRequest> request;
1828   service.SetProxyDelegate(&delegate);
1829   int rv =
1830       service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(), &info,
1831                            callback1.callback(), &request, NetLogWithSource());
1832   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1833 
1834   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1835             factory_ptr->pending_requests()[0]->script_data()->url());
1836   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1837   ASSERT_EQ(1u, resolver.pending_jobs().size());
1838   EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
1839 
1840   resolver.pending_jobs()[0]->results()->UseNamedProxy(
1841       "foopy1:8080;foopy2:9090");
1842   resolver.pending_jobs()[0]->CompleteNow(OK);
1843 
1844   // The first item is valid.
1845   EXPECT_THAT(callback1.WaitForResult(), IsOk());
1846   EXPECT_FALSE(info.is_direct());
1847   EXPECT_EQ("[foopy1:8080]", info.proxy_chain().ToDebugString());
1848 
1849   // Fake a proxy error.
1850   EXPECT_TRUE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
1851 
1852   // The first proxy is ignored, and the second one is selected.
1853   EXPECT_FALSE(info.is_direct());
1854   EXPECT_EQ("[foopy2:9090]", info.proxy_chain().ToDebugString());
1855 
1856   // Persist foopy1's failure to |service|'s cache of bad proxies, so it will
1857   // be considered by subsequent calls to ResolveProxy().
1858   service.ReportSuccess(info);
1859 
1860   // Fake a PAC failure.
1861   ProxyInfo info2;
1862   TestCompletionCallback callback2;
1863   rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
1864                             &info2, callback2.callback(), &request,
1865                             NetLogWithSource());
1866   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1867 
1868   ASSERT_EQ(1u, resolver.pending_jobs().size());
1869   EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
1870 
1871   // This simulates a javascript runtime error in the PAC script.
1872   resolver.pending_jobs()[0]->CompleteNow(ERR_FAILED);
1873 
1874   // Although the resolver failed, the ConfiguredProxyResolutionService will
1875   // implicitly fall-back to a DIRECT connection.
1876   EXPECT_THAT(callback2.WaitForResult(), IsOk());
1877   EXPECT_TRUE(info2.is_direct());
1878   EXPECT_FALSE(info2.is_empty());
1879 
1880   // The PAC script will work properly next time and successfully return a
1881   // proxy list. Since we have not marked the configuration as bad, it should
1882   // "just work" the next time we call it.
1883   ProxyInfo info3;
1884   TestCompletionCallback callback3;
1885   std::unique_ptr<ProxyResolutionRequest> request3;
1886   rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
1887                             &info3, callback3.callback(), &request3,
1888                             NetLogWithSource());
1889   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1890 
1891   ASSERT_EQ(1u, resolver.pending_jobs().size());
1892   EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
1893 
1894   resolver.pending_jobs()[0]->results()->UseNamedProxy(
1895       "foopy1:8080;foopy2:9090");
1896   resolver.pending_jobs()[0]->CompleteNow(OK);
1897 
1898   // The first proxy was deprioritized since it was added to the bad proxies
1899   // list by the earlier ReportSuccess().
1900   EXPECT_THAT(callback3.WaitForResult(), IsOk());
1901   EXPECT_FALSE(info3.is_direct());
1902   EXPECT_EQ("[foopy2:9090]", info3.proxy_chain().ToDebugString());
1903   EXPECT_EQ(2u, info3.proxy_list().size());
1904 
1905   EXPECT_FALSE(info.proxy_resolve_start_time().is_null());
1906   EXPECT_FALSE(info.proxy_resolve_end_time().is_null());
1907   EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time());
1908 
1909   EXPECT_EQ(3, delegate.num_resolve_proxy_called());
1910 }
1911 
TEST_F(ConfiguredProxyResolutionServiceTest,ProxyFallback_BadConfigMandatory)1912 TEST_F(ConfiguredProxyResolutionServiceTest, ProxyFallback_BadConfigMandatory) {
1913   // Test proxy failover when the configuration is bad.
1914 
1915   ProxyConfig config(
1916       ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")));
1917 
1918   config.set_pac_mandatory(true);
1919   auto config_service = std::make_unique<MockProxyConfigService>(config);
1920 
1921   MockAsyncProxyResolver resolver;
1922   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
1923   auto* factory_ptr = factory.get();
1924 
1925   ConfiguredProxyResolutionService service(std::move(config_service),
1926                                            std::move(factory), nullptr,
1927                                            /*quick_check_enabled=*/true);
1928 
1929   GURL url("http://www.google.com/");
1930 
1931   // Get the proxy information.
1932   ProxyInfo info;
1933   TestCompletionCallback callback1;
1934   std::unique_ptr<ProxyResolutionRequest> request1;
1935   int rv =
1936       service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(), &info,
1937                            callback1.callback(), &request1, NetLogWithSource());
1938   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1939 
1940   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1941             factory_ptr->pending_requests()[0]->script_data()->url());
1942   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
1943   ASSERT_EQ(1u, resolver.pending_jobs().size());
1944   EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
1945 
1946   resolver.pending_jobs()[0]->results()->UseNamedProxy(
1947       "foopy1:8080;foopy2:9090");
1948   resolver.pending_jobs()[0]->CompleteNow(OK);
1949 
1950   // The first item is valid.
1951   EXPECT_THAT(callback1.WaitForResult(), IsOk());
1952   EXPECT_FALSE(info.is_direct());
1953   EXPECT_EQ("[foopy1:8080]", info.proxy_chain().ToDebugString());
1954 
1955   // Fake a proxy error.
1956   EXPECT_TRUE(info.Fallback(ERR_PROXY_CONNECTION_FAILED, NetLogWithSource()));
1957 
1958   // The first proxy is ignored, and the second one is selected.
1959   EXPECT_FALSE(info.is_direct());
1960   EXPECT_EQ("[foopy2:9090]", info.proxy_chain().ToDebugString());
1961 
1962   // Persist foopy1's failure to |service|'s cache of bad proxies, so it will
1963   // be considered by subsequent calls to ResolveProxy().
1964   service.ReportSuccess(info);
1965 
1966   // Fake a PAC failure.
1967   ProxyInfo info2;
1968   TestCompletionCallback callback3;
1969   std::unique_ptr<ProxyResolutionRequest> request3;
1970   rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
1971                             &info2, callback3.callback(), &request3,
1972                             NetLogWithSource());
1973   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1974 
1975   ASSERT_EQ(1u, resolver.pending_jobs().size());
1976   EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
1977 
1978   // This simulates a javascript runtime error in the PAC script.
1979   resolver.pending_jobs()[0]->CompleteNow(ERR_FAILED);
1980 
1981   // Although the resolver failed, the ConfiguredProxyResolutionService will NOT
1982   // fall-back to a DIRECT connection as it is configured as mandatory.
1983   EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED,
1984             callback3.WaitForResult());
1985   EXPECT_FALSE(info2.is_direct());
1986   EXPECT_TRUE(info2.is_empty());
1987 
1988   // The PAC script will work properly next time and successfully return a
1989   // proxy list. Since we have not marked the configuration as bad, it should
1990   // "just work" the next time we call it.
1991   ProxyInfo info3;
1992   TestCompletionCallback callback4;
1993   std::unique_ptr<ProxyResolutionRequest> request4;
1994   rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
1995                             &info3, callback4.callback(), &request4,
1996                             NetLogWithSource());
1997   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
1998 
1999   ASSERT_EQ(1u, resolver.pending_jobs().size());
2000   EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
2001 
2002   resolver.pending_jobs()[0]->results()->UseNamedProxy(
2003       "foopy1:8080;foopy2:9090");
2004   resolver.pending_jobs()[0]->CompleteNow(OK);
2005 
2006   // The first proxy was deprioritized since it was added to the bad proxies
2007   // list by the earlier ReportSuccess().
2008   EXPECT_THAT(callback4.WaitForResult(), IsOk());
2009   EXPECT_FALSE(info3.is_direct());
2010   EXPECT_EQ("[foopy2:9090]", info3.proxy_chain().ToDebugString());
2011   EXPECT_EQ(2u, info3.proxy_list().size());
2012 }
2013 
TEST_F(ConfiguredProxyResolutionServiceTest,ProxyBypassList)2014 TEST_F(ConfiguredProxyResolutionServiceTest, ProxyBypassList) {
2015   // Test that the proxy bypass rules are consulted.
2016 
2017   TestCompletionCallback callback[2];
2018   ProxyInfo info[2];
2019   ProxyConfig config;
2020   config.proxy_rules().ParseFromString("foopy1:8080;foopy2:9090");
2021   config.set_auto_detect(false);
2022   config.proxy_rules().bypass_rules.ParseFromString("*.org");
2023 
2024   ConfiguredProxyResolutionService service(
2025       std::make_unique<MockProxyConfigService>(config), nullptr, nullptr,
2026       /*quick_check_enabled=*/true);
2027 
2028   int rv;
2029   GURL url1("http://www.webkit.org");
2030   GURL url2("http://www.webkit.com");
2031   std::unique_ptr<ProxyResolutionRequest> request1;
2032   std::unique_ptr<ProxyResolutionRequest> request2;
2033 
2034   // Request for a .org domain should bypass proxy.
2035   rv = service.ResolveProxy(url1, std::string(), NetworkAnonymizationKey(),
2036                             &info[0], callback[0].callback(), &request1,
2037                             NetLogWithSource());
2038   EXPECT_THAT(rv, IsOk());
2039   EXPECT_TRUE(info[0].is_direct());
2040 
2041   // Request for a .com domain hits the proxy.
2042   rv = service.ResolveProxy(url2, std::string(), NetworkAnonymizationKey(),
2043                             &info[1], callback[1].callback(), &request2,
2044                             NetLogWithSource());
2045   EXPECT_THAT(rv, IsOk());
2046   EXPECT_EQ("[foopy1:8080]", info[1].proxy_chain().ToDebugString());
2047 }
2048 
TEST_F(ConfiguredProxyResolutionServiceTest,MarkProxiesAsBadTests)2049 TEST_F(ConfiguredProxyResolutionServiceTest, MarkProxiesAsBadTests) {
2050   ProxyConfig config;
2051   config.proxy_rules().ParseFromString(
2052       "http=foopy1:8080;http=foopy2:8080;http=foopy3:8080;http=foopy4:8080");
2053   config.set_auto_detect(false);
2054 
2055   ProxyList proxy_list;
2056   std::vector<ProxyChain> additional_bad_proxies;
2057   for (const ProxyChain& proxy_chain :
2058        config.proxy_rules().proxies_for_http.AllChains()) {
2059     proxy_list.AddProxyChain(proxy_chain);
2060     if (proxy_chain == config.proxy_rules().proxies_for_http.First()) {
2061       continue;
2062     }
2063 
2064     additional_bad_proxies.emplace_back(proxy_chain);
2065   }
2066 
2067   EXPECT_EQ(3u, additional_bad_proxies.size());
2068 
2069   ConfiguredProxyResolutionService service(
2070       std::make_unique<MockProxyConfigService>(config), nullptr, nullptr,
2071       /*quick_check_enabled=*/true);
2072   ProxyInfo proxy_info;
2073   proxy_info.UseProxyList(proxy_list);
2074   const ProxyRetryInfoMap& retry_info = service.proxy_retry_info();
2075   service.MarkProxiesAsBadUntil(proxy_info, base::Seconds(1),
2076                                 additional_bad_proxies, NetLogWithSource());
2077   ASSERT_EQ(4u, retry_info.size());
2078   for (const ProxyChain& proxy_chain :
2079        config.proxy_rules().proxies_for_http.AllChains()) {
2080     auto i = retry_info.find(proxy_chain);
2081     ASSERT_TRUE(i != retry_info.end());
2082   }
2083 }
2084 
TEST_F(ConfiguredProxyResolutionServiceTest,PerProtocolProxyTests)2085 TEST_F(ConfiguredProxyResolutionServiceTest, PerProtocolProxyTests) {
2086   ProxyConfig config;
2087   config.proxy_rules().ParseFromString("http=foopy1:8080;https=foopy2:8080");
2088   config.set_auto_detect(false);
2089   std::unique_ptr<ProxyResolutionRequest> request;
2090   {
2091     ConfiguredProxyResolutionService service(
2092         std::make_unique<MockProxyConfigService>(config), nullptr, nullptr,
2093         /*quick_check_enabled=*/true);
2094     GURL test_url("http://www.msn.com");
2095     ProxyInfo info;
2096     TestCompletionCallback callback;
2097     int rv = service.ResolveProxy(
2098         test_url, std::string(), NetworkAnonymizationKey(), &info,
2099         callback.callback(), &request, NetLogWithSource());
2100     EXPECT_THAT(rv, IsOk());
2101     EXPECT_FALSE(info.is_direct());
2102     EXPECT_EQ("[foopy1:8080]", info.proxy_chain().ToDebugString());
2103   }
2104   {
2105     ConfiguredProxyResolutionService service(
2106         std::make_unique<MockProxyConfigService>(config), nullptr, nullptr,
2107         /*quick_check_enabled=*/true);
2108     GURL test_url("ftp://ftp.google.com");
2109     ProxyInfo info;
2110     TestCompletionCallback callback;
2111     int rv = service.ResolveProxy(
2112         test_url, std::string(), NetworkAnonymizationKey(), &info,
2113         callback.callback(), &request, NetLogWithSource());
2114     EXPECT_THAT(rv, IsOk());
2115     EXPECT_TRUE(info.is_direct());
2116     EXPECT_EQ("[direct://]", info.proxy_chain().ToDebugString());
2117   }
2118   {
2119     ConfiguredProxyResolutionService service(
2120         std::make_unique<MockProxyConfigService>(config), nullptr, nullptr,
2121         /*quick_check_enabled=*/true);
2122     GURL test_url("https://webbranch.techcu.com");
2123     ProxyInfo info;
2124     TestCompletionCallback callback;
2125     int rv = service.ResolveProxy(
2126         test_url, std::string(), NetworkAnonymizationKey(), &info,
2127         callback.callback(), &request, NetLogWithSource());
2128     EXPECT_THAT(rv, IsOk());
2129     EXPECT_FALSE(info.is_direct());
2130     EXPECT_EQ("[foopy2:8080]", info.proxy_chain().ToDebugString());
2131   }
2132   {
2133     config.proxy_rules().ParseFromString("foopy1:8080");
2134     ConfiguredProxyResolutionService service(
2135         std::make_unique<MockProxyConfigService>(config), nullptr, nullptr,
2136         /*quick_check_enabled=*/true);
2137     GURL test_url("http://www.microsoft.com");
2138     ProxyInfo info;
2139     TestCompletionCallback callback;
2140     int rv = service.ResolveProxy(
2141         test_url, std::string(), NetworkAnonymizationKey(), &info,
2142         callback.callback(), &request, NetLogWithSource());
2143     EXPECT_THAT(rv, IsOk());
2144     EXPECT_FALSE(info.is_direct());
2145     EXPECT_EQ("[foopy1:8080]", info.proxy_chain().ToDebugString());
2146   }
2147 }
2148 
TEST_F(ConfiguredProxyResolutionServiceTest,ProxyConfigTrafficAnnotationPropagates)2149 TEST_F(ConfiguredProxyResolutionServiceTest,
2150        ProxyConfigTrafficAnnotationPropagates) {
2151   // Test that the proxy config source is set correctly when resolving proxies
2152   // using manual proxy rules. Namely, the config source should only be set if
2153   // any of the rules were applied.
2154   std::unique_ptr<ProxyResolutionRequest> request;
2155   {
2156     ProxyConfig config;
2157     config.proxy_rules().ParseFromString("https=foopy2:8080");
2158     ConfiguredProxyResolutionService service(
2159         std::make_unique<MockProxyConfigService>(config), nullptr, nullptr,
2160         /*quick_check_enabled=*/true);
2161     GURL test_url("http://www.google.com");
2162     ProxyInfo info;
2163     TestCompletionCallback callback;
2164     int rv = service.ResolveProxy(
2165         test_url, std::string(), NetworkAnonymizationKey(), &info,
2166         callback.callback(), &request, NetLogWithSource());
2167     ASSERT_THAT(rv, IsOk());
2168     // Should be test, even if there are no HTTP proxies configured.
2169     EXPECT_EQ(MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS),
2170               info.traffic_annotation());
2171   }
2172   {
2173     ProxyConfig config;
2174     config.proxy_rules().ParseFromString("https=foopy2:8080");
2175     ConfiguredProxyResolutionService service(
2176         std::make_unique<MockProxyConfigService>(config), nullptr, nullptr,
2177         /*quick_check_enabled=*/true);
2178     GURL test_url("https://www.google.com");
2179     ProxyInfo info;
2180     TestCompletionCallback callback;
2181     int rv = service.ResolveProxy(
2182         test_url, std::string(), NetworkAnonymizationKey(), &info,
2183         callback.callback(), &request, NetLogWithSource());
2184     ASSERT_THAT(rv, IsOk());
2185     // Used the HTTPS proxy. So traffic annotation should test.
2186     EXPECT_EQ(MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS),
2187               info.traffic_annotation());
2188   }
2189   {
2190     ProxyConfig config;
2191     ConfiguredProxyResolutionService service(
2192         std::make_unique<MockProxyConfigService>(config), nullptr, nullptr,
2193         /*quick_check_enabled=*/true);
2194     GURL test_url("http://www.google.com");
2195     ProxyInfo info;
2196     TestCompletionCallback callback;
2197     int rv = service.ResolveProxy(
2198         test_url, std::string(), NetworkAnonymizationKey(), &info,
2199         callback.callback(), &request, NetLogWithSource());
2200     ASSERT_THAT(rv, IsOk());
2201     // ProxyConfig is empty. Traffic annotation should still be TEST.
2202     EXPECT_EQ(MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS),
2203               info.traffic_annotation());
2204   }
2205 }
2206 
2207 // If only HTTP and a SOCKS proxy are specified, check if ftp/https queries
2208 // fall back to the SOCKS proxy.
TEST_F(ConfiguredProxyResolutionServiceTest,DefaultProxyFallbackToSOCKS)2209 TEST_F(ConfiguredProxyResolutionServiceTest, DefaultProxyFallbackToSOCKS) {
2210   ProxyConfig config;
2211   config.proxy_rules().ParseFromString("http=foopy1:8080;socks=foopy2:1080");
2212   config.set_auto_detect(false);
2213   EXPECT_EQ(ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME,
2214             config.proxy_rules().type);
2215 
2216   std::unique_ptr<ProxyResolutionRequest> request;
2217   {
2218     ConfiguredProxyResolutionService service(
2219         std::make_unique<MockProxyConfigService>(config), nullptr, nullptr,
2220         /*quick_check_enabled=*/true);
2221     GURL test_url("http://www.msn.com");
2222     ProxyInfo info;
2223     TestCompletionCallback callback;
2224     int rv = service.ResolveProxy(
2225         test_url, std::string(), NetworkAnonymizationKey(), &info,
2226         callback.callback(), &request, NetLogWithSource());
2227     EXPECT_THAT(rv, IsOk());
2228     EXPECT_FALSE(info.is_direct());
2229     EXPECT_EQ("[foopy1:8080]", info.proxy_chain().ToDebugString());
2230   }
2231   {
2232     ConfiguredProxyResolutionService service(
2233         std::make_unique<MockProxyConfigService>(config), nullptr, nullptr,
2234         /*quick_check_enabled=*/true);
2235     GURL test_url("ftp://ftp.google.com");
2236     ProxyInfo info;
2237     TestCompletionCallback callback;
2238     int rv = service.ResolveProxy(
2239         test_url, std::string(), NetworkAnonymizationKey(), &info,
2240         callback.callback(), &request, NetLogWithSource());
2241     EXPECT_THAT(rv, IsOk());
2242     EXPECT_FALSE(info.is_direct());
2243     EXPECT_EQ("[socks4://foopy2:1080]", info.proxy_chain().ToDebugString());
2244   }
2245   {
2246     ConfiguredProxyResolutionService service(
2247         std::make_unique<MockProxyConfigService>(config), nullptr, nullptr,
2248         /*quick_check_enabled=*/true);
2249     GURL test_url("https://webbranch.techcu.com");
2250     ProxyInfo info;
2251     TestCompletionCallback callback;
2252     int rv = service.ResolveProxy(
2253         test_url, std::string(), NetworkAnonymizationKey(), &info,
2254         callback.callback(), &request, NetLogWithSource());
2255     EXPECT_THAT(rv, IsOk());
2256     EXPECT_FALSE(info.is_direct());
2257     EXPECT_EQ("[socks4://foopy2:1080]", info.proxy_chain().ToDebugString());
2258   }
2259   {
2260     ConfiguredProxyResolutionService service(
2261         std::make_unique<MockProxyConfigService>(config), nullptr, nullptr,
2262         /*quick_check_enabled=*/true);
2263     GURL test_url("unknown://www.microsoft.com");
2264     ProxyInfo info;
2265     TestCompletionCallback callback;
2266     int rv = service.ResolveProxy(
2267         test_url, std::string(), NetworkAnonymizationKey(), &info,
2268         callback.callback(), &request, NetLogWithSource());
2269     EXPECT_THAT(rv, IsOk());
2270     EXPECT_FALSE(info.is_direct());
2271     EXPECT_EQ("[socks4://foopy2:1080]", info.proxy_chain().ToDebugString());
2272   }
2273 }
2274 
2275 // Test cancellation of an in-progress request.
TEST_F(ConfiguredProxyResolutionServiceTest,CancelInProgressRequest)2276 TEST_F(ConfiguredProxyResolutionServiceTest, CancelInProgressRequest) {
2277   const GURL url1("http://request1");
2278   const GURL url2("http://request2");
2279   const GURL url3("http://request3");
2280   auto config_service =
2281       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
2282 
2283   MockAsyncProxyResolver resolver;
2284   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
2285   auto* factory_ptr = factory.get();
2286 
2287   ConfiguredProxyResolutionService service(std::move(config_service),
2288                                            std::move(factory), nullptr,
2289                                            /*quick_check_enabled=*/true);
2290 
2291   // Start 3 requests.
2292 
2293   ProxyInfo info1;
2294   TestCompletionCallback callback1;
2295   std::unique_ptr<ProxyResolutionRequest> request1;
2296   int rv = service.ResolveProxy(url1, std::string(), NetworkAnonymizationKey(),
2297                                 &info1, callback1.callback(), &request1,
2298                                 NetLogWithSource());
2299   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2300 
2301   // Successfully initialize the PAC script.
2302   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
2303             factory_ptr->pending_requests()[0]->script_data()->url());
2304   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2305 
2306   GetPendingJobsForURLs(resolver, url1);
2307 
2308   ProxyInfo info2;
2309   TestCompletionCallback callback2;
2310   std::unique_ptr<ProxyResolutionRequest> request2;
2311   rv = service.ResolveProxy(url2, std::string(), NetworkAnonymizationKey(),
2312                             &info2, callback2.callback(), &request2,
2313                             NetLogWithSource());
2314   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2315 
2316   GetPendingJobsForURLs(resolver, url1, url2);
2317 
2318   ProxyInfo info3;
2319   TestCompletionCallback callback3;
2320   std::unique_ptr<ProxyResolutionRequest> request3;
2321   rv = service.ResolveProxy(url3, std::string(), NetworkAnonymizationKey(),
2322                             &info3, callback3.callback(), &request3,
2323                             NetLogWithSource());
2324   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2325   GetPendingJobsForURLs(resolver, url1, url2, url3);
2326 
2327   // Cancel the second request
2328   request2.reset();
2329 
2330   JobMap jobs = GetPendingJobsForURLs(resolver, url1, url3);
2331 
2332   // Complete the two un-cancelled jobs.
2333   // We complete the last one first, just to mix it up a bit.
2334   jobs[url3]->results()->UseNamedProxy("request3:80");
2335   jobs[url3]->CompleteNow(OK);  // dsaadsasd
2336 
2337   jobs[url1]->results()->UseNamedProxy("request1:80");
2338   jobs[url1]->CompleteNow(OK);
2339 
2340   EXPECT_EQ(OK, callback1.WaitForResult());
2341   EXPECT_EQ("[request1:80]", info1.proxy_chain().ToDebugString());
2342 
2343   EXPECT_FALSE(callback2.have_result());  // Cancelled.
2344   GetCancelledJobsForURLs(resolver, url2);
2345 
2346   EXPECT_THAT(callback3.WaitForResult(), IsOk());
2347   EXPECT_EQ("[request3:80]", info3.proxy_chain().ToDebugString());
2348 }
2349 
2350 // Test the initial PAC download for resolver that expects bytes.
TEST_F(ConfiguredProxyResolutionServiceTest,InitialPACScriptDownload)2351 TEST_F(ConfiguredProxyResolutionServiceTest, InitialPACScriptDownload) {
2352   const GURL url1("http://request1");
2353   const GURL url2("http://request2");
2354   const GURL url3("http://request3");
2355   auto config_service =
2356       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
2357 
2358   MockAsyncProxyResolver resolver;
2359   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
2360   auto* factory_ptr = factory.get();
2361 
2362   ConfiguredProxyResolutionService service(std::move(config_service),
2363                                            std::move(factory), nullptr,
2364                                            /*quick_check_enabled=*/true);
2365 
2366   auto fetcher = std::make_unique<MockPacFileFetcher>();
2367   auto* fetcher_ptr = fetcher.get();
2368   service.SetPacFileFetchers(std::move(fetcher),
2369                              std::make_unique<DoNothingDhcpPacFileFetcher>());
2370 
2371   // Start 3 requests.
2372 
2373   ProxyInfo info1;
2374   TestCompletionCallback callback1;
2375   std::unique_ptr<ProxyResolutionRequest> request1;
2376   int rv = service.ResolveProxy(url1, std::string(), NetworkAnonymizationKey(),
2377                                 &info1, callback1.callback(), &request1,
2378                                 NetLogWithSource());
2379   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2380 
2381   // The first request should have triggered download of PAC script.
2382   EXPECT_TRUE(fetcher_ptr->has_pending_request());
2383   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
2384 
2385   ProxyInfo info2;
2386   TestCompletionCallback callback2;
2387   std::unique_ptr<ProxyResolutionRequest> request2;
2388   rv = service.ResolveProxy(url2, std::string(), NetworkAnonymizationKey(),
2389                             &info2, callback2.callback(), &request2,
2390                             NetLogWithSource());
2391   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2392 
2393   ProxyInfo info3;
2394   TestCompletionCallback callback3;
2395   std::unique_ptr<ProxyResolutionRequest> request3;
2396   rv = service.ResolveProxy(url3, std::string(), NetworkAnonymizationKey(),
2397                             &info3, callback3.callback(), &request3,
2398                             NetLogWithSource());
2399   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2400 
2401   // Nothing has been sent to the factory yet.
2402   EXPECT_TRUE(factory_ptr->pending_requests().empty());
2403 
2404   EXPECT_EQ(LOAD_STATE_DOWNLOADING_PAC_FILE, request1->GetLoadState());
2405   EXPECT_EQ(LOAD_STATE_DOWNLOADING_PAC_FILE, request2->GetLoadState());
2406   EXPECT_EQ(LOAD_STATE_DOWNLOADING_PAC_FILE, request3->GetLoadState());
2407 
2408   // At this point the ConfiguredProxyResolutionService should be waiting for
2409   // the PacFileFetcher to invoke its completion callback, notifying it of PAC
2410   // script download completion.
2411   fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
2412 
2413   // Now that the PAC script is downloaded, it will have been sent to the proxy
2414   // resolver.
2415   EXPECT_EQ(kValidPacScript116,
2416             factory_ptr->pending_requests()[0]->script_data()->utf16());
2417   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2418 
2419   JobMap jobs = GetPendingJobsForURLs(resolver, url1, url2, url3);
2420 
2421   EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, request1->GetLoadState());
2422   EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, request2->GetLoadState());
2423   EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, request3->GetLoadState());
2424 
2425   // Complete all the jobs (in some order).
2426 
2427   jobs[url3]->results()->UseNamedProxy("request3:80");
2428   jobs[url3]->CompleteNow(OK);
2429 
2430   jobs[url1]->results()->UseNamedProxy("request1:80");
2431   jobs[url1]->CompleteNow(OK);
2432 
2433   jobs[url2]->results()->UseNamedProxy("request2:80");
2434   jobs[url2]->CompleteNow(OK);
2435 
2436   // Complete and verify that jobs ran as expected.
2437   EXPECT_EQ(OK, callback1.WaitForResult());
2438   // ProxyResolver::GetProxyForURL() to take a std::unique_ptr<Request>* rather
2439   // than a RequestHandle* (patchset #11 id:200001 of
2440   // https://codereview.chromium.org/1439053002/ )
2441   EXPECT_EQ("[request1:80]", info1.proxy_chain().ToDebugString());
2442   EXPECT_FALSE(info1.proxy_resolve_start_time().is_null());
2443   EXPECT_FALSE(info1.proxy_resolve_end_time().is_null());
2444   EXPECT_LE(info1.proxy_resolve_start_time(), info1.proxy_resolve_end_time());
2445 
2446   EXPECT_THAT(callback2.WaitForResult(), IsOk());
2447   EXPECT_EQ("[request2:80]", info2.proxy_chain().ToDebugString());
2448   EXPECT_FALSE(info2.proxy_resolve_start_time().is_null());
2449   EXPECT_FALSE(info2.proxy_resolve_end_time().is_null());
2450   EXPECT_LE(info2.proxy_resolve_start_time(), info2.proxy_resolve_end_time());
2451 
2452   EXPECT_THAT(callback3.WaitForResult(), IsOk());
2453   EXPECT_EQ("[request3:80]", info3.proxy_chain().ToDebugString());
2454   EXPECT_FALSE(info3.proxy_resolve_start_time().is_null());
2455   EXPECT_FALSE(info3.proxy_resolve_end_time().is_null());
2456   EXPECT_LE(info3.proxy_resolve_start_time(), info3.proxy_resolve_end_time());
2457 }
2458 
2459 // Test changing the PacFileFetcher while PAC download is in progress.
TEST_F(ConfiguredProxyResolutionServiceTest,ChangeScriptFetcherWhilePACDownloadInProgress)2460 TEST_F(ConfiguredProxyResolutionServiceTest,
2461        ChangeScriptFetcherWhilePACDownloadInProgress) {
2462   const GURL url1("http://request1");
2463   const GURL url2("http://request2");
2464   auto config_service =
2465       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
2466 
2467   MockAsyncProxyResolver resolver;
2468   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
2469   auto* factory_ptr = factory.get();
2470 
2471   ConfiguredProxyResolutionService service(std::move(config_service),
2472                                            std::move(factory), nullptr,
2473                                            /*quick_check_enabled=*/true);
2474 
2475   auto fetcher = std::make_unique<MockPacFileFetcher>();
2476   auto* fetcher_ptr = fetcher.get();
2477   service.SetPacFileFetchers(std::move(fetcher),
2478                              std::make_unique<DoNothingDhcpPacFileFetcher>());
2479 
2480   // Start 2 jobs.
2481 
2482   ProxyInfo info1;
2483   TestCompletionCallback callback1;
2484   std::unique_ptr<ProxyResolutionRequest> request1;
2485   int rv = service.ResolveProxy(url1, std::string(), NetworkAnonymizationKey(),
2486                                 &info1, callback1.callback(), &request1,
2487                                 NetLogWithSource());
2488   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2489 
2490   // The first request should have triggered download of PAC script.
2491   EXPECT_TRUE(fetcher_ptr->has_pending_request());
2492   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
2493 
2494   ProxyInfo info2;
2495   TestCompletionCallback callback2;
2496   std::unique_ptr<ProxyResolutionRequest> request2;
2497   rv = service.ResolveProxy(url2, std::string(), NetworkAnonymizationKey(),
2498                             &info2, callback2.callback(), &request2,
2499                             NetLogWithSource());
2500   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2501 
2502   // At this point the ConfiguredProxyResolutionService should be waiting for
2503   // the PacFileFetcher to invoke its completion callback, notifying it of PAC
2504   // script download completion.
2505 
2506   // We now change out the ConfiguredProxyResolutionService's script fetcher. We
2507   // should restart the initialization with the new fetcher.
2508 
2509   fetcher = std::make_unique<MockPacFileFetcher>();
2510   fetcher_ptr = fetcher.get();
2511   service.SetPacFileFetchers(std::move(fetcher),
2512                              std::make_unique<DoNothingDhcpPacFileFetcher>());
2513 
2514   // Nothing has been sent to the factory yet.
2515   EXPECT_TRUE(factory_ptr->pending_requests().empty());
2516 
2517   fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
2518 
2519   // Now that the PAC script is downloaded, it will have been sent to the proxy
2520   // resolver.
2521   EXPECT_EQ(kValidPacScript116,
2522             factory_ptr->pending_requests()[0]->script_data()->utf16());
2523   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2524 
2525   GetPendingJobsForURLs(resolver, url1, url2);
2526 }
2527 
2528 // Test cancellation of a request, while the PAC script is being fetched.
TEST_F(ConfiguredProxyResolutionServiceTest,CancelWhilePACFetching)2529 TEST_F(ConfiguredProxyResolutionServiceTest, CancelWhilePACFetching) {
2530   auto config_service =
2531       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
2532 
2533   MockAsyncProxyResolver resolver;
2534   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
2535   auto* factory_ptr = factory.get();
2536 
2537   ConfiguredProxyResolutionService service(std::move(config_service),
2538                                            std::move(factory), nullptr,
2539                                            /*quick_check_enabled=*/true);
2540 
2541   auto fetcher = std::make_unique<MockPacFileFetcher>();
2542   auto* fetcher_ptr = fetcher.get();
2543 
2544   service.SetPacFileFetchers(std::move(fetcher),
2545                              std::make_unique<DoNothingDhcpPacFileFetcher>());
2546 
2547   // Start 3 requests.
2548   ProxyInfo info1;
2549   TestCompletionCallback callback1;
2550   std::unique_ptr<ProxyResolutionRequest> request1;
2551   RecordingNetLogObserver net_log_observer;
2552   int rv = service.ResolveProxy(GURL("http://request1"), std::string(),
2553                                 NetworkAnonymizationKey(), &info1,
2554                                 callback1.callback(), &request1,
2555                                 NetLogWithSource::Make(NetLogSourceType::NONE));
2556   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2557 
2558   // The first request should have triggered download of PAC script.
2559   EXPECT_TRUE(fetcher_ptr->has_pending_request());
2560   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
2561 
2562   ProxyInfo info2;
2563   TestCompletionCallback callback2;
2564   std::unique_ptr<ProxyResolutionRequest> request2;
2565   rv = service.ResolveProxy(
2566       GURL("http://request2"), std::string(), NetworkAnonymizationKey(), &info2,
2567       callback2.callback(), &request2, NetLogWithSource());
2568   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2569 
2570   ProxyInfo info3;
2571   TestCompletionCallback callback3;
2572   std::unique_ptr<ProxyResolutionRequest> request3;
2573   rv = service.ResolveProxy(
2574       GURL("http://request3"), std::string(), NetworkAnonymizationKey(), &info3,
2575       callback3.callback(), &request3, NetLogWithSource());
2576   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2577 
2578   // Nothing has been sent to the factory yet.
2579   EXPECT_TRUE(factory_ptr->pending_requests().empty());
2580 
2581   // Cancel the first 2 jobs.
2582   request1.reset();
2583   request2.reset();
2584 
2585   // At this point the ConfiguredProxyResolutionService should be waiting for
2586   // the PacFileFetcher to invoke its completion callback, notifying it of PAC
2587   // script download completion.
2588   fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
2589 
2590   // Now that the PAC script is downloaded, it will have been sent to the
2591   // proxy resolver.
2592   EXPECT_EQ(kValidPacScript116,
2593             factory_ptr->pending_requests()[0]->script_data()->utf16());
2594   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2595 
2596   ASSERT_EQ(1u, resolver.pending_jobs().size());
2597   EXPECT_EQ(GURL("http://request3"), resolver.pending_jobs()[0]->url());
2598 
2599   // Complete all the jobs.
2600   resolver.pending_jobs()[0]->results()->UseNamedProxy("request3:80");
2601   resolver.pending_jobs()[0]->CompleteNow(OK);
2602 
2603   EXPECT_THAT(callback3.WaitForResult(), IsOk());
2604   EXPECT_EQ("[request3:80]", info3.proxy_chain().ToDebugString());
2605 
2606   EXPECT_TRUE(resolver.cancelled_jobs().empty());
2607 
2608   EXPECT_FALSE(callback1.have_result());  // Cancelled.
2609   EXPECT_FALSE(callback2.have_result());  // Cancelled.
2610 
2611   auto entries1 = net_log_observer.GetEntries();
2612 
2613   // Check the NetLog for request 1 (which was cancelled) got filled properly.
2614   EXPECT_EQ(4u, entries1.size());
2615   EXPECT_TRUE(LogContainsBeginEvent(entries1, 0,
2616                                     NetLogEventType::PROXY_RESOLUTION_SERVICE));
2617   EXPECT_TRUE(LogContainsBeginEvent(
2618       entries1, 1,
2619       NetLogEventType::PROXY_RESOLUTION_SERVICE_WAITING_FOR_INIT_PAC));
2620   // Note that PROXY_RESOLUTION_SERVICE_WAITING_FOR_INIT_PAC is never completed
2621   // before the cancellation occured.
2622   EXPECT_TRUE(LogContainsEvent(entries1, 2, NetLogEventType::CANCELLED,
2623                                NetLogEventPhase::NONE));
2624   EXPECT_TRUE(LogContainsEndEvent(entries1, 3,
2625                                   NetLogEventType::PROXY_RESOLUTION_SERVICE));
2626 }
2627 
2628 // Test that if auto-detect fails, we fall-back to the custom pac.
TEST_F(ConfiguredProxyResolutionServiceTest,FallbackFromAutodetectToCustomPac)2629 TEST_F(ConfiguredProxyResolutionServiceTest,
2630        FallbackFromAutodetectToCustomPac) {
2631   const GURL url1("http://request1");
2632   const GURL url2("http://request2");
2633   ProxyConfig config;
2634   config.set_auto_detect(true);
2635   config.set_pac_url(GURL("http://foopy/proxy.pac"));
2636   config.proxy_rules().ParseFromString("http=foopy:80");  // Won't be used.
2637 
2638   auto config_service = std::make_unique<MockProxyConfigService>(config);
2639   MockAsyncProxyResolver resolver;
2640   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
2641   auto* factory_ptr = factory.get();
2642   ConfiguredProxyResolutionService service(std::move(config_service),
2643                                            std::move(factory), nullptr,
2644                                            /*quick_check_enabled=*/true);
2645 
2646   auto fetcher = std::make_unique<MockPacFileFetcher>();
2647   auto* fetcher_ptr = fetcher.get();
2648   service.SetPacFileFetchers(std::move(fetcher),
2649                              std::make_unique<DoNothingDhcpPacFileFetcher>());
2650 
2651   // Start 2 requests.
2652 
2653   ProxyInfo info1;
2654   TestCompletionCallback callback1;
2655   std::unique_ptr<ProxyResolutionRequest> request1;
2656   int rv = service.ResolveProxy(url1, std::string(), NetworkAnonymizationKey(),
2657                                 &info1, callback1.callback(), &request1,
2658                                 NetLogWithSource());
2659   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2660 
2661   ProxyInfo info2;
2662   TestCompletionCallback callback2;
2663   std::unique_ptr<ProxyResolutionRequest> request2;
2664   rv = service.ResolveProxy(url2, std::string(), NetworkAnonymizationKey(),
2665                             &info2, callback2.callback(), &request2,
2666                             NetLogWithSource());
2667   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2668 
2669   // Check that nothing has been sent to the proxy resolver factory yet.
2670   ASSERT_EQ(0u, factory_ptr->pending_requests().size());
2671 
2672   // It should be trying to auto-detect first -- FAIL the autodetect during
2673   // the script download.
2674   EXPECT_TRUE(fetcher_ptr->has_pending_request());
2675   EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher_ptr->pending_request_url());
2676   fetcher_ptr->NotifyFetchCompletion(ERR_FAILED, std::string());
2677 
2678   // Next it should be trying the custom PAC url.
2679   EXPECT_TRUE(fetcher_ptr->has_pending_request());
2680   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
2681   fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
2682 
2683   EXPECT_EQ(kValidPacScript116,
2684             factory_ptr->pending_requests()[0]->script_data()->utf16());
2685   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2686 
2687   // Now finally, the pending jobs should have been sent to the resolver
2688   // (which was initialized with custom PAC script).
2689 
2690   JobMap jobs = GetPendingJobsForURLs(resolver, url1, url2);
2691 
2692   // Complete the pending jobs.
2693   jobs[url2]->results()->UseNamedProxy("request2:80");
2694   jobs[url2]->CompleteNow(OK);
2695   jobs[url1]->results()->UseNamedProxy("request1:80");
2696   jobs[url1]->CompleteNow(OK);
2697 
2698   // Verify that jobs ran as expected.
2699   EXPECT_EQ(OK, callback1.WaitForResult());
2700   // ProxyResolver::GetProxyForURL() to take a std::unique_ptr<Request>* rather
2701   // than a RequestHandle* (patchset #11 id:200001 of
2702   // https://codereview.chromium.org/1439053002/ )
2703   EXPECT_EQ("[request1:80]", info1.proxy_chain().ToDebugString());
2704   EXPECT_FALSE(info1.proxy_resolve_start_time().is_null());
2705   EXPECT_FALSE(info1.proxy_resolve_end_time().is_null());
2706   EXPECT_LE(info1.proxy_resolve_start_time(), info1.proxy_resolve_end_time());
2707 
2708   EXPECT_THAT(callback2.WaitForResult(), IsOk());
2709   EXPECT_EQ("[request2:80]", info2.proxy_chain().ToDebugString());
2710   EXPECT_FALSE(info2.proxy_resolve_start_time().is_null());
2711   EXPECT_FALSE(info2.proxy_resolve_end_time().is_null());
2712   EXPECT_LE(info2.proxy_resolve_start_time(), info2.proxy_resolve_end_time());
2713 }
2714 
2715 // This is the same test as FallbackFromAutodetectToCustomPac, except
2716 // the auto-detect script fails parsing rather than downloading.
TEST_F(ConfiguredProxyResolutionServiceTest,FallbackFromAutodetectToCustomPac2)2717 TEST_F(ConfiguredProxyResolutionServiceTest,
2718        FallbackFromAutodetectToCustomPac2) {
2719   const GURL url1("http://request1");
2720   const GURL url2("http://request2");
2721   ProxyConfig config;
2722   config.set_auto_detect(true);
2723   config.set_pac_url(GURL("http://foopy/proxy.pac"));
2724   config.proxy_rules().ParseFromString("http=foopy:80");  // Won't be used.
2725 
2726   auto config_service = std::make_unique<MockProxyConfigService>(config);
2727   MockAsyncProxyResolver resolver;
2728   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
2729   auto* factory_ptr = factory.get();
2730   ConfiguredProxyResolutionService service(std::move(config_service),
2731                                            std::move(factory), nullptr,
2732                                            /*quick_check_enabled=*/true);
2733 
2734   auto fetcher = std::make_unique<MockPacFileFetcher>();
2735   auto* fetcher_ptr = fetcher.get();
2736   service.SetPacFileFetchers(std::move(fetcher),
2737                              std::make_unique<DoNothingDhcpPacFileFetcher>());
2738 
2739   // Start 2 requests.
2740 
2741   ProxyInfo info1;
2742   TestCompletionCallback callback1;
2743   std::unique_ptr<ProxyResolutionRequest> request1;
2744   int rv = service.ResolveProxy(url1, std::string(), NetworkAnonymizationKey(),
2745                                 &info1, callback1.callback(), &request1,
2746                                 NetLogWithSource());
2747   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2748 
2749   ProxyInfo info2;
2750   TestCompletionCallback callback2;
2751   std::unique_ptr<ProxyResolutionRequest> request2;
2752   rv = service.ResolveProxy(url2, std::string(), NetworkAnonymizationKey(),
2753                             &info2, callback2.callback(), &request2,
2754                             NetLogWithSource());
2755   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2756 
2757   // Check that nothing has been sent to the proxy resolver factory yet.
2758   ASSERT_EQ(0u, factory_ptr->pending_requests().size());
2759 
2760   // It should be trying to auto-detect first -- succeed the download.
2761   EXPECT_TRUE(fetcher_ptr->has_pending_request());
2762   EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher_ptr->pending_request_url());
2763   fetcher_ptr->NotifyFetchCompletion(OK, "invalid-script-contents");
2764 
2765   // The script contents passed failed basic verification step (since didn't
2766   // contain token FindProxyForURL), so it was never passed to the resolver.
2767 
2768   // Next it should be trying the custom PAC url.
2769   EXPECT_TRUE(fetcher_ptr->has_pending_request());
2770   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
2771   fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
2772 
2773   EXPECT_EQ(kValidPacScript116,
2774             factory_ptr->pending_requests()[0]->script_data()->utf16());
2775   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2776 
2777   // Now finally, the pending jobs should have been sent to the resolver
2778   // (which was initialized with custom PAC script).
2779 
2780   JobMap jobs = GetPendingJobsForURLs(resolver, url1, url2);
2781 
2782   // Complete the pending jobs.
2783   jobs[url2]->results()->UseNamedProxy("request2:80");
2784   jobs[url2]->CompleteNow(OK);
2785   jobs[url1]->results()->UseNamedProxy("request1:80");
2786   jobs[url1]->CompleteNow(OK);
2787 
2788   // Verify that jobs ran as expected.
2789   EXPECT_EQ(OK, callback1.WaitForResult());
2790   // ProxyResolver::GetProxyForURL() to take a std::unique_ptr<Request>* rather
2791   // than a RequestHandle* (patchset #11 id:200001 of
2792   // https://codereview.chromium.org/1439053002/ )
2793   EXPECT_EQ("[request1:80]", info1.proxy_chain().ToDebugString());
2794 
2795   EXPECT_THAT(callback2.WaitForResult(), IsOk());
2796   EXPECT_EQ("[request2:80]", info2.proxy_chain().ToDebugString());
2797 }
2798 
2799 // Test that if all of auto-detect, a custom PAC script, and manual settings
2800 // are given, then we will try them in that order.
TEST_F(ConfiguredProxyResolutionServiceTest,FallbackFromAutodetectToCustomToManual)2801 TEST_F(ConfiguredProxyResolutionServiceTest,
2802        FallbackFromAutodetectToCustomToManual) {
2803   ProxyConfig config;
2804   config.set_auto_detect(true);
2805   config.set_pac_url(GURL("http://foopy/proxy.pac"));
2806   config.proxy_rules().ParseFromString("http=foopy:80");
2807 
2808   auto config_service = std::make_unique<MockProxyConfigService>(config);
2809   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
2810   auto* factory_ptr = factory.get();
2811   ConfiguredProxyResolutionService service(std::move(config_service),
2812                                            std::move(factory), nullptr,
2813                                            /*quick_check_enabled=*/true);
2814 
2815   auto fetcher = std::make_unique<MockPacFileFetcher>();
2816   auto* fetcher_ptr = fetcher.get();
2817   service.SetPacFileFetchers(std::move(fetcher),
2818                              std::make_unique<DoNothingDhcpPacFileFetcher>());
2819 
2820   // Start 2 jobs.
2821 
2822   ProxyInfo info1;
2823   TestCompletionCallback callback1;
2824   std::unique_ptr<ProxyResolutionRequest> request1;
2825   int rv = service.ResolveProxy(
2826       GURL("http://request1"), std::string(), NetworkAnonymizationKey(), &info1,
2827       callback1.callback(), &request1, NetLogWithSource());
2828   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2829 
2830   ProxyInfo info2;
2831   TestCompletionCallback callback2;
2832   std::unique_ptr<ProxyResolutionRequest> request2;
2833   rv = service.ResolveProxy(
2834       GURL("http://request2"), std::string(), NetworkAnonymizationKey(), &info2,
2835       callback2.callback(), &request2, NetLogWithSource());
2836   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2837 
2838   // Check that nothing has been sent to the proxy resolver factory yet.
2839   ASSERT_EQ(0u, factory_ptr->pending_requests().size());
2840 
2841   // It should be trying to auto-detect first -- fail the download.
2842   EXPECT_TRUE(fetcher_ptr->has_pending_request());
2843   EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher_ptr->pending_request_url());
2844   fetcher_ptr->NotifyFetchCompletion(ERR_FAILED, std::string());
2845 
2846   // Next it should be trying the custom PAC url -- fail the download.
2847   EXPECT_TRUE(fetcher_ptr->has_pending_request());
2848   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
2849   fetcher_ptr->NotifyFetchCompletion(ERR_FAILED, std::string());
2850 
2851   // Since we never managed to initialize a resolver, nothing should have been
2852   // sent to it.
2853   ASSERT_EQ(0u, factory_ptr->pending_requests().size());
2854 
2855   // Verify that jobs ran as expected -- they should have fallen back to
2856   // the manual proxy configuration for HTTP urls.
2857   EXPECT_THAT(callback1.WaitForResult(), IsOk());
2858   EXPECT_EQ("[foopy:80]", info1.proxy_chain().ToDebugString());
2859 
2860   EXPECT_THAT(callback2.WaitForResult(), IsOk());
2861   EXPECT_EQ("[foopy:80]", info2.proxy_chain().ToDebugString());
2862 }
2863 
2864 // Test that the bypass rules are NOT applied when using autodetect.
TEST_F(ConfiguredProxyResolutionServiceTest,BypassDoesntApplyToPac)2865 TEST_F(ConfiguredProxyResolutionServiceTest, BypassDoesntApplyToPac) {
2866   ProxyConfig config;
2867   config.set_auto_detect(true);
2868   config.set_pac_url(GURL("http://foopy/proxy.pac"));
2869   config.proxy_rules().ParseFromString("http=foopy:80");  // Not used.
2870   config.proxy_rules().bypass_rules.ParseFromString("www.google.com");
2871 
2872   auto config_service = std::make_unique<MockProxyConfigService>(config);
2873   MockAsyncProxyResolver resolver;
2874   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
2875   auto* factory_ptr = factory.get();
2876   ConfiguredProxyResolutionService service(std::move(config_service),
2877                                            std::move(factory), nullptr,
2878                                            /*quick_check_enabled=*/true);
2879 
2880   auto fetcher = std::make_unique<MockPacFileFetcher>();
2881   auto* fetcher_ptr = fetcher.get();
2882   service.SetPacFileFetchers(std::move(fetcher),
2883                              std::make_unique<DoNothingDhcpPacFileFetcher>());
2884 
2885   // Start 1 requests.
2886 
2887   ProxyInfo info1;
2888   TestCompletionCallback callback1;
2889   std::unique_ptr<ProxyResolutionRequest> request1;
2890   int rv = service.ResolveProxy(
2891       GURL("http://www.google.com"), std::string(), NetworkAnonymizationKey(),
2892       &info1, callback1.callback(), &request1, NetLogWithSource());
2893   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2894 
2895   // Check that nothing has been sent to the proxy resolver factory yet.
2896   ASSERT_EQ(0u, factory_ptr->pending_requests().size());
2897 
2898   // It should be trying to auto-detect first -- succeed the download.
2899   EXPECT_TRUE(fetcher_ptr->has_pending_request());
2900   EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher_ptr->pending_request_url());
2901   fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
2902 
2903   EXPECT_EQ(kValidPacScript116,
2904             factory_ptr->pending_requests()[0]->script_data()->utf16());
2905   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
2906 
2907   ASSERT_EQ(1u, resolver.pending_jobs().size());
2908   EXPECT_EQ(GURL("http://www.google.com"), resolver.pending_jobs()[0]->url());
2909 
2910   // Complete the pending request.
2911   resolver.pending_jobs()[0]->results()->UseNamedProxy("request1:80");
2912   resolver.pending_jobs()[0]->CompleteNow(OK);
2913 
2914   // Verify that request ran as expected.
2915   EXPECT_THAT(callback1.WaitForResult(), IsOk());
2916   EXPECT_EQ("[request1:80]", info1.proxy_chain().ToDebugString());
2917 
2918   // Start another request, it should pickup the bypass item.
2919   ProxyInfo info2;
2920   TestCompletionCallback callback2;
2921   std::unique_ptr<ProxyResolutionRequest> request2;
2922   rv = service.ResolveProxy(
2923       GURL("http://www.google.com"), std::string(), NetworkAnonymizationKey(),
2924       &info2, callback2.callback(), &request2, NetLogWithSource());
2925   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2926 
2927   ASSERT_EQ(1u, resolver.pending_jobs().size());
2928   EXPECT_EQ(GURL("http://www.google.com"), resolver.pending_jobs()[0]->url());
2929 
2930   // Complete the pending request.
2931   resolver.pending_jobs()[0]->results()->UseNamedProxy("request2:80");
2932   resolver.pending_jobs()[0]->CompleteNow(OK);
2933 
2934   EXPECT_THAT(callback2.WaitForResult(), IsOk());
2935   EXPECT_EQ("[request2:80]", info2.proxy_chain().ToDebugString());
2936 }
2937 
2938 // Delete the ConfiguredProxyResolutionService while InitProxyResolver has an
2939 // outstanding request to the script fetcher. When run under valgrind, should
2940 // not have any memory errors (used to be that the PacFileFetcher was being
2941 // deleted prior to the InitProxyResolver).
TEST_F(ConfiguredProxyResolutionServiceTest,DeleteWhileInitProxyResolverHasOutstandingFetch)2942 TEST_F(ConfiguredProxyResolutionServiceTest,
2943        DeleteWhileInitProxyResolverHasOutstandingFetch) {
2944   ProxyConfig config =
2945       ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"));
2946 
2947   auto config_service = std::make_unique<MockProxyConfigService>(config);
2948   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
2949   auto* factory_ptr = factory.get();
2950   ConfiguredProxyResolutionService service(std::move(config_service),
2951                                            std::move(factory), nullptr,
2952                                            /*quick_check_enabled=*/true);
2953 
2954   auto fetcher = std::make_unique<MockPacFileFetcher>();
2955   auto* fetcher_ptr = fetcher.get();
2956   service.SetPacFileFetchers(std::move(fetcher),
2957                              std::make_unique<DoNothingDhcpPacFileFetcher>());
2958 
2959   // Start 1 request.
2960 
2961   ProxyInfo info1;
2962   TestCompletionCallback callback1;
2963   std::unique_ptr<ProxyResolutionRequest> request1;
2964   int rv = service.ResolveProxy(
2965       GURL("http://www.google.com"), std::string(), NetworkAnonymizationKey(),
2966       &info1, callback1.callback(), &request1, NetLogWithSource());
2967   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
2968 
2969   // Check that nothing has been sent to the proxy resolver factory yet.
2970   ASSERT_EQ(0u, factory_ptr->pending_requests().size());
2971 
2972   // InitProxyResolver should have issued a request to the PacFileFetcher
2973   // and be waiting on that to complete.
2974   EXPECT_TRUE(fetcher_ptr->has_pending_request());
2975   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
2976 }
2977 
2978 // Delete the ConfiguredProxyResolutionService while InitProxyResolver has an
2979 // outstanding request to the proxy resolver. When run under valgrind, should
2980 // not have any memory errors (used to be that the ProxyResolver was being
2981 // deleted prior to the InitProxyResolver).
TEST_F(ConfiguredProxyResolutionServiceTest,DeleteWhileInitProxyResolverHasOutstandingSet)2982 TEST_F(ConfiguredProxyResolutionServiceTest,
2983        DeleteWhileInitProxyResolverHasOutstandingSet) {
2984   auto config_service =
2985       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
2986 
2987   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
2988   auto* factory_ptr = factory.get();
2989 
2990   ConfiguredProxyResolutionService service(std::move(config_service),
2991                                            std::move(factory), nullptr,
2992                                            /*quick_check_enabled=*/true);
2993 
2994   GURL url("http://www.google.com/");
2995 
2996   ProxyInfo info;
2997   TestCompletionCallback callback;
2998   std::unique_ptr<ProxyResolutionRequest> request;
2999   int rv =
3000       service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(), &info,
3001                            callback.callback(), &request, NetLogWithSource());
3002   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3003 
3004   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
3005             factory_ptr->pending_requests()[0]->script_data()->url());
3006 }
3007 
3008 // Test that when going from a configuration that required PAC to one
3009 // that does NOT, we unset the variable |should_use_proxy_resolver_|.
TEST_F(ConfiguredProxyResolutionServiceTest,UpdateConfigFromPACToDirect)3010 TEST_F(ConfiguredProxyResolutionServiceTest, UpdateConfigFromPACToDirect) {
3011   ProxyConfig config = ProxyConfig::CreateAutoDetect();
3012 
3013   auto config_service = std::make_unique<MockProxyConfigService>(config);
3014   auto* config_service_ptr = config_service.get();
3015   MockAsyncProxyResolver resolver;
3016   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
3017   auto* factory_ptr = factory.get();
3018   ConfiguredProxyResolutionService service(std::move(config_service),
3019                                            std::move(factory), nullptr,
3020                                            /*quick_check_enabled=*/true);
3021 
3022   // Start 1 request.
3023 
3024   ProxyInfo info1;
3025   TestCompletionCallback callback1;
3026   std::unique_ptr<ProxyResolutionRequest> request1;
3027   int rv = service.ResolveProxy(
3028       GURL("http://www.google.com"), std::string(), NetworkAnonymizationKey(),
3029       &info1, callback1.callback(), &request1, NetLogWithSource());
3030   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3031 
3032   // Successfully set the autodetect script.
3033   EXPECT_EQ(PacFileData::TYPE_AUTO_DETECT,
3034             factory_ptr->pending_requests()[0]->script_data()->type());
3035   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
3036 
3037   // Complete the pending request.
3038   ASSERT_EQ(1u, resolver.pending_jobs().size());
3039   resolver.pending_jobs()[0]->results()->UseNamedProxy("request1:80");
3040   resolver.pending_jobs()[0]->CompleteNow(OK);
3041 
3042   // Verify that request ran as expected.
3043   EXPECT_THAT(callback1.WaitForResult(), IsOk());
3044   EXPECT_EQ("[request1:80]", info1.proxy_chain().ToDebugString());
3045 
3046   // Force the ConfiguredProxyResolutionService to pull down a new proxy
3047   // configuration. (Even though the configuration isn't old/bad).
3048   //
3049   // This new configuration no longer has auto_detect set, so
3050   // jobs should complete synchronously now as direct-connect.
3051   config_service_ptr->SetConfig(ProxyConfigWithAnnotation::CreateDirect());
3052 
3053   // Start another request -- the effective configuration has changed.
3054   ProxyInfo info2;
3055   TestCompletionCallback callback2;
3056   std::unique_ptr<ProxyResolutionRequest> request2;
3057   rv = service.ResolveProxy(
3058       GURL("http://www.google.com"), std::string(), NetworkAnonymizationKey(),
3059       &info2, callback2.callback(), &request2, NetLogWithSource());
3060   EXPECT_THAT(rv, IsOk());
3061 
3062   EXPECT_TRUE(info2.is_direct());
3063 }
3064 
TEST_F(ConfiguredProxyResolutionServiceTest,NetworkChangeTriggersPacRefetch)3065 TEST_F(ConfiguredProxyResolutionServiceTest, NetworkChangeTriggersPacRefetch) {
3066   auto config_service =
3067       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
3068 
3069   MockAsyncProxyResolver resolver;
3070   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
3071   auto* factory_ptr = factory.get();
3072 
3073   RecordingNetLogObserver observer;
3074 
3075   ConfiguredProxyResolutionService service(
3076       std::move(config_service), std::move(factory), net::NetLog::Get(),
3077       /*quick_check_enabled=*/true);
3078 
3079   auto fetcher = std::make_unique<MockPacFileFetcher>();
3080   auto* fetcher_ptr = fetcher.get();
3081   service.SetPacFileFetchers(std::move(fetcher),
3082                              std::make_unique<DoNothingDhcpPacFileFetcher>());
3083 
3084   // Disable the "wait after IP address changes" hack, so this unit-test can
3085   // complete quickly.
3086   service.set_stall_proxy_auto_config_delay(base::TimeDelta());
3087 
3088   // Start 1 request.
3089 
3090   ProxyInfo info1;
3091   TestCompletionCallback callback1;
3092   std::unique_ptr<ProxyResolutionRequest> request1;
3093   int rv = service.ResolveProxy(
3094       GURL("http://request1"), std::string(), NetworkAnonymizationKey(), &info1,
3095       callback1.callback(), &request1, NetLogWithSource());
3096   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3097 
3098   // The first request should have triggered initial download of PAC script.
3099   EXPECT_TRUE(fetcher_ptr->has_pending_request());
3100   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
3101 
3102   // Nothing has been sent to the factory yet.
3103   EXPECT_TRUE(factory_ptr->pending_requests().empty());
3104 
3105   // At this point the ConfiguredProxyResolutionService should be waiting for
3106   // the PacFileFetcher to invoke its completion callback, notifying it of PAC
3107   // script download completion.
3108   fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
3109 
3110   // Now that the PAC script is downloaded, the request will have been sent to
3111   // the proxy resolver.
3112   EXPECT_EQ(kValidPacScript116,
3113             factory_ptr->pending_requests()[0]->script_data()->utf16());
3114   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
3115 
3116   ASSERT_EQ(1u, resolver.pending_jobs().size());
3117   EXPECT_EQ(GURL("http://request1"), resolver.pending_jobs()[0]->url());
3118 
3119   // Complete the pending request.
3120   resolver.pending_jobs()[0]->results()->UseNamedProxy("request1:80");
3121   resolver.pending_jobs()[0]->CompleteNow(OK);
3122 
3123   // Wait for completion callback, and verify that the request ran as expected.
3124   EXPECT_THAT(callback1.WaitForResult(), IsOk());
3125   EXPECT_EQ("[request1:80]", info1.proxy_chain().ToDebugString());
3126 
3127   // Now simluate a change in the network. The ProxyConfigService is still
3128   // going to return the same PAC URL as before, but this URL needs to be
3129   // refetched on the new network.
3130   NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
3131   base::RunLoop().RunUntilIdle();  // Notification happens async.
3132 
3133   // Start a second request.
3134   ProxyInfo info2;
3135   TestCompletionCallback callback2;
3136   std::unique_ptr<ProxyResolutionRequest> request2;
3137   rv = service.ResolveProxy(
3138       GURL("http://request2"), std::string(), NetworkAnonymizationKey(), &info2,
3139       callback2.callback(), &request2, NetLogWithSource());
3140   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3141 
3142   // This second request should have triggered the re-download of the PAC
3143   // script (since we marked the network as having changed).
3144   EXPECT_TRUE(fetcher_ptr->has_pending_request());
3145   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
3146 
3147   // Nothing has been sent to the factory yet.
3148   EXPECT_TRUE(factory_ptr->pending_requests().empty());
3149 
3150   // Simulate the PAC script fetch as having completed (this time with
3151   // different data).
3152   fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript2);
3153 
3154   // Now that the PAC script is downloaded, the second request will have been
3155   // sent to the proxy resolver.
3156   EXPECT_EQ(kValidPacScript216,
3157             factory_ptr->pending_requests()[0]->script_data()->utf16());
3158   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
3159 
3160   ASSERT_EQ(1u, resolver.pending_jobs().size());
3161   EXPECT_EQ(GURL("http://request2"), resolver.pending_jobs()[0]->url());
3162 
3163   // Complete the pending second request.
3164   resolver.pending_jobs()[0]->results()->UseNamedProxy("request2:80");
3165   resolver.pending_jobs()[0]->CompleteNow(OK);
3166 
3167   // Wait for completion callback, and verify that the request ran as expected.
3168   EXPECT_THAT(callback2.WaitForResult(), IsOk());
3169   EXPECT_EQ("[request2:80]", info2.proxy_chain().ToDebugString());
3170 
3171   // Check that the expected events were output to the log stream. In particular
3172   // PROXY_CONFIG_CHANGED should have only been emitted once (for the initial
3173   // setup), and NOT a second time when the IP address changed.
3174   auto entries = observer.GetEntries();
3175 
3176   EXPECT_TRUE(LogContainsEntryWithType(entries, 0,
3177                                        NetLogEventType::PROXY_CONFIG_CHANGED));
3178   ASSERT_EQ(9u, entries.size());
3179   for (size_t i = 1; i < entries.size(); ++i)
3180     EXPECT_NE(NetLogEventType::PROXY_CONFIG_CHANGED, entries[i].type);
3181 }
3182 
3183 // This test verifies that the PAC script specified by the settings is
3184 // periodically polled for changes. Specifically, if the initial fetch fails due
3185 // to a network error, we will eventually re-configure the service to use the
3186 // script once it becomes available.
TEST_F(ConfiguredProxyResolutionServiceTest,PACScriptRefetchAfterFailure)3187 TEST_F(ConfiguredProxyResolutionServiceTest, PACScriptRefetchAfterFailure) {
3188   // Change the retry policy to wait a mere 1 ms before retrying, so the test
3189   // runs quickly.
3190   ImmediatePollPolicy poll_policy;
3191   ConfiguredProxyResolutionService::set_pac_script_poll_policy(&poll_policy);
3192 
3193   auto config_service =
3194       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
3195 
3196   MockAsyncProxyResolver resolver;
3197   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
3198   auto* factory_ptr = factory.get();
3199 
3200   ConfiguredProxyResolutionService service(std::move(config_service),
3201                                            std::move(factory), nullptr,
3202                                            /*quick_check_enabled=*/true);
3203 
3204   auto fetcher = std::make_unique<MockPacFileFetcher>();
3205   auto* fetcher_ptr = fetcher.get();
3206   service.SetPacFileFetchers(std::move(fetcher),
3207                              std::make_unique<DoNothingDhcpPacFileFetcher>());
3208 
3209   // Start 1 request.
3210 
3211   ProxyInfo info1;
3212   TestCompletionCallback callback1;
3213   std::unique_ptr<ProxyResolutionRequest> request1;
3214   int rv = service.ResolveProxy(
3215       GURL("http://request1"), std::string(), NetworkAnonymizationKey(), &info1,
3216       callback1.callback(), &request1, NetLogWithSource());
3217   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3218 
3219   // The first request should have triggered initial download of PAC script.
3220   EXPECT_TRUE(fetcher_ptr->has_pending_request());
3221   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
3222 
3223   // Nothing has been sent to the factory yet.
3224   EXPECT_TRUE(factory_ptr->pending_requests().empty());
3225 
3226   // At this point the ConfiguredProxyResolutionService should be waiting for
3227   // the PacFileFetcher to invoke its completion callback, notifying it of PAC
3228   // script download completion.
3229   //
3230   // We simulate a failed download attempt, the proxy service should now
3231   // fall-back to DIRECT connections.
3232   fetcher_ptr->NotifyFetchCompletion(ERR_FAILED, std::string());
3233 
3234   ASSERT_TRUE(factory_ptr->pending_requests().empty());
3235 
3236   // Wait for completion callback, and verify it used DIRECT.
3237   EXPECT_THAT(callback1.WaitForResult(), IsOk());
3238   EXPECT_TRUE(info1.is_direct());
3239 
3240   // At this point we have initialized the proxy service using a PAC script,
3241   // however it failed and fell-back to DIRECT.
3242   //
3243   // A background task to periodically re-check the PAC script for validity will
3244   // have been started. We will now wait for the next download attempt to start.
3245   //
3246   // Note that we shouldn't have to wait long here, since our test enables a
3247   // special unit-test mode.
3248   fetcher_ptr->WaitUntilFetch();
3249 
3250   ASSERT_TRUE(factory_ptr->pending_requests().empty());
3251 
3252   // Make sure that our background checker is trying to download the expected
3253   // PAC script (same one as before). This time we will simulate a successful
3254   // download of the script.
3255   EXPECT_TRUE(fetcher_ptr->has_pending_request());
3256   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
3257   fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
3258 
3259   base::RunLoop().RunUntilIdle();
3260 
3261   // Now that the PAC script is downloaded, it should be used to initialize the
3262   // ProxyResolver. Simulate a successful parse.
3263   EXPECT_EQ(kValidPacScript116,
3264             factory_ptr->pending_requests()[0]->script_data()->utf16());
3265   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
3266 
3267   // At this point the ConfiguredProxyResolutionService should have
3268   // re-configured itself to use the PAC script (thereby recovering from the
3269   // initial fetch failure). We will verify that the next Resolve request uses
3270   // the resolver rather than DIRECT.
3271 
3272   // Start a second request.
3273   ProxyInfo info2;
3274   TestCompletionCallback callback2;
3275   std::unique_ptr<ProxyResolutionRequest> request2;
3276   rv = service.ResolveProxy(
3277       GURL("http://request2"), std::string(), NetworkAnonymizationKey(), &info2,
3278       callback2.callback(), &request2, NetLogWithSource());
3279   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3280 
3281   // Check that it was sent to the resolver.
3282   ASSERT_EQ(1u, resolver.pending_jobs().size());
3283   EXPECT_EQ(GURL("http://request2"), resolver.pending_jobs()[0]->url());
3284 
3285   // Complete the pending second request.
3286   resolver.pending_jobs()[0]->results()->UseNamedProxy("request2:80");
3287   resolver.pending_jobs()[0]->CompleteNow(OK);
3288 
3289   // Wait for completion callback, and verify that the request ran as expected.
3290   EXPECT_THAT(callback2.WaitForResult(), IsOk());
3291   EXPECT_EQ("[request2:80]", info2.proxy_chain().ToDebugString());
3292 }
3293 
3294 // This test verifies that the PAC script specified by the settings is
3295 // periodically polled for changes. Specifically, if the initial fetch succeeds,
3296 // however at a later time its *contents* change, we will eventually
3297 // re-configure the service to use the new script.
TEST_F(ConfiguredProxyResolutionServiceTest,PACScriptRefetchAfterContentChange)3298 TEST_F(ConfiguredProxyResolutionServiceTest,
3299        PACScriptRefetchAfterContentChange) {
3300   // Change the retry policy to wait a mere 1 ms before retrying, so the test
3301   // runs quickly.
3302   ImmediatePollPolicy poll_policy;
3303   ConfiguredProxyResolutionService::set_pac_script_poll_policy(&poll_policy);
3304 
3305   auto config_service =
3306       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
3307 
3308   MockAsyncProxyResolver resolver;
3309   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
3310   auto* factory_ptr = factory.get();
3311 
3312   ConfiguredProxyResolutionService service(std::move(config_service),
3313                                            std::move(factory), nullptr,
3314                                            /*quick_check_enabled=*/true);
3315 
3316   auto fetcher = std::make_unique<MockPacFileFetcher>();
3317   auto* fetcher_ptr = fetcher.get();
3318   service.SetPacFileFetchers(std::move(fetcher),
3319                              std::make_unique<DoNothingDhcpPacFileFetcher>());
3320 
3321   // Start 1 request.
3322 
3323   ProxyInfo info1;
3324   TestCompletionCallback callback1;
3325   std::unique_ptr<ProxyResolutionRequest> request1;
3326   int rv = service.ResolveProxy(
3327       GURL("http://request1"), std::string(), NetworkAnonymizationKey(), &info1,
3328       callback1.callback(), &request1, NetLogWithSource());
3329   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3330 
3331   // The first request should have triggered initial download of PAC script.
3332   EXPECT_TRUE(fetcher_ptr->has_pending_request());
3333   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
3334 
3335   // Nothing has been sent to the factory yet.
3336   EXPECT_TRUE(factory_ptr->pending_requests().empty());
3337 
3338   // At this point the ConfiguredProxyResolutionService should be waiting for
3339   // the PacFileFetcher to invoke its completion callback, notifying it of PAC
3340   // script download completion.
3341   fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
3342 
3343   // Now that the PAC script is downloaded, the request will have been sent to
3344   // the proxy resolver.
3345   EXPECT_EQ(kValidPacScript116,
3346             factory_ptr->pending_requests()[0]->script_data()->utf16());
3347   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
3348 
3349   ASSERT_EQ(1u, resolver.pending_jobs().size());
3350   EXPECT_EQ(GURL("http://request1"), resolver.pending_jobs()[0]->url());
3351 
3352   // Complete the pending request.
3353   resolver.pending_jobs()[0]->results()->UseNamedProxy("request1:80");
3354   resolver.pending_jobs()[0]->CompleteNow(OK);
3355 
3356   // Wait for completion callback, and verify that the request ran as expected.
3357   EXPECT_THAT(callback1.WaitForResult(), IsOk());
3358   EXPECT_EQ("[request1:80]", info1.proxy_chain().ToDebugString());
3359 
3360   // At this point we have initialized the proxy service using a PAC script.
3361   //
3362   // A background task to periodically re-check the PAC script for validity will
3363   // have been started. We will now wait for the next download attempt to start.
3364   //
3365   // Note that we shouldn't have to wait long here, since our test enables a
3366   // special unit-test mode.
3367   fetcher_ptr->WaitUntilFetch();
3368 
3369   ASSERT_TRUE(factory_ptr->pending_requests().empty());
3370   ASSERT_TRUE(resolver.pending_jobs().empty());
3371 
3372   // Make sure that our background checker is trying to download the expected
3373   // PAC script (same one as before). This time we will simulate a successful
3374   // download of a DIFFERENT script.
3375   EXPECT_TRUE(fetcher_ptr->has_pending_request());
3376   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
3377   fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript2);
3378 
3379   base::RunLoop().RunUntilIdle();
3380 
3381   // Now that the PAC script is downloaded, it should be used to initialize the
3382   // ProxyResolver. Simulate a successful parse.
3383   EXPECT_EQ(kValidPacScript216,
3384             factory_ptr->pending_requests()[0]->script_data()->utf16());
3385   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
3386 
3387   // At this point the ConfiguredProxyResolutionService should have
3388   // re-configured itself to use the new PAC script.
3389 
3390   // Start a second request.
3391   ProxyInfo info2;
3392   TestCompletionCallback callback2;
3393   std::unique_ptr<ProxyResolutionRequest> request2;
3394   rv = service.ResolveProxy(
3395       GURL("http://request2"), std::string(), NetworkAnonymizationKey(), &info2,
3396       callback2.callback(), &request2, NetLogWithSource());
3397   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3398 
3399   // Check that it was sent to the resolver.
3400   ASSERT_EQ(1u, resolver.pending_jobs().size());
3401   EXPECT_EQ(GURL("http://request2"), resolver.pending_jobs()[0]->url());
3402 
3403   // Complete the pending second request.
3404   resolver.pending_jobs()[0]->results()->UseNamedProxy("request2:80");
3405   resolver.pending_jobs()[0]->CompleteNow(OK);
3406 
3407   // Wait for completion callback, and verify that the request ran as expected.
3408   EXPECT_THAT(callback2.WaitForResult(), IsOk());
3409   EXPECT_EQ("[request2:80]", info2.proxy_chain().ToDebugString());
3410 }
3411 
3412 // This test verifies that the PAC script specified by the settings is
3413 // periodically polled for changes. Specifically, if the initial fetch succeeds
3414 // and so does the next poll, however the contents of the downloaded script
3415 // have NOT changed, then we do not bother to re-initialize the proxy resolver.
TEST_F(ConfiguredProxyResolutionServiceTest,PACScriptRefetchAfterContentUnchanged)3416 TEST_F(ConfiguredProxyResolutionServiceTest,
3417        PACScriptRefetchAfterContentUnchanged) {
3418   // Change the retry policy to wait a mere 1 ms before retrying, so the test
3419   // runs quickly.
3420   ImmediatePollPolicy poll_policy;
3421   ConfiguredProxyResolutionService::set_pac_script_poll_policy(&poll_policy);
3422 
3423   auto config_service =
3424       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
3425 
3426   MockAsyncProxyResolver resolver;
3427   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
3428   auto* factory_ptr = factory.get();
3429 
3430   ConfiguredProxyResolutionService service(std::move(config_service),
3431                                            std::move(factory), nullptr,
3432                                            /*quick_check_enabled=*/true);
3433 
3434   auto fetcher = std::make_unique<MockPacFileFetcher>();
3435   auto* fetcher_ptr = fetcher.get();
3436   service.SetPacFileFetchers(std::move(fetcher),
3437                              std::make_unique<DoNothingDhcpPacFileFetcher>());
3438 
3439   // Start 1 request.
3440 
3441   ProxyInfo info1;
3442   TestCompletionCallback callback1;
3443   std::unique_ptr<ProxyResolutionRequest> request1;
3444   int rv = service.ResolveProxy(
3445       GURL("http://request1"), std::string(), NetworkAnonymizationKey(), &info1,
3446       callback1.callback(), &request1, NetLogWithSource());
3447   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3448 
3449   // The first request should have triggered initial download of PAC script.
3450   EXPECT_TRUE(fetcher_ptr->has_pending_request());
3451   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
3452 
3453   // Nothing has been sent to the factory yet.
3454   EXPECT_TRUE(factory_ptr->pending_requests().empty());
3455 
3456   // At this point the ConfiguredProxyResolutionService should be waiting for
3457   // the PacFileFetcher to invoke its completion callback, notifying it of PAC
3458   // script download completion.
3459   fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
3460 
3461   // Now that the PAC script is downloaded, the request will have been sent to
3462   // the proxy resolver.
3463   EXPECT_EQ(kValidPacScript116,
3464             factory_ptr->pending_requests()[0]->script_data()->utf16());
3465   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
3466 
3467   ASSERT_EQ(1u, resolver.pending_jobs().size());
3468   EXPECT_EQ(GURL("http://request1"), resolver.pending_jobs()[0]->url());
3469 
3470   // Complete the pending request.
3471   resolver.pending_jobs()[0]->results()->UseNamedProxy("request1:80");
3472   resolver.pending_jobs()[0]->CompleteNow(OK);
3473 
3474   // Wait for completion callback, and verify that the request ran as expected.
3475   EXPECT_THAT(callback1.WaitForResult(), IsOk());
3476   EXPECT_EQ("[request1:80]", info1.proxy_chain().ToDebugString());
3477 
3478   // At this point we have initialized the proxy service using a PAC script.
3479   //
3480   // A background task to periodically re-check the PAC script for validity will
3481   // have been started. We will now wait for the next download attempt to start.
3482   //
3483   // Note that we shouldn't have to wait long here, since our test enables a
3484   // special unit-test mode.
3485   fetcher_ptr->WaitUntilFetch();
3486 
3487   ASSERT_TRUE(factory_ptr->pending_requests().empty());
3488   ASSERT_TRUE(resolver.pending_jobs().empty());
3489 
3490   // Make sure that our background checker is trying to download the expected
3491   // PAC script (same one as before). We will simulate the same response as
3492   // last time (i.e. the script is unchanged).
3493   EXPECT_TRUE(fetcher_ptr->has_pending_request());
3494   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
3495   fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
3496 
3497   base::RunLoop().RunUntilIdle();
3498 
3499   ASSERT_TRUE(factory_ptr->pending_requests().empty());
3500   ASSERT_TRUE(resolver.pending_jobs().empty());
3501 
3502   // At this point the ConfiguredProxyResolutionService is still running the
3503   // same PAC script as before.
3504 
3505   // Start a second request.
3506   ProxyInfo info2;
3507   TestCompletionCallback callback2;
3508   std::unique_ptr<ProxyResolutionRequest> request2;
3509   rv = service.ResolveProxy(
3510       GURL("http://request2"), std::string(), NetworkAnonymizationKey(), &info2,
3511       callback2.callback(), &request2, NetLogWithSource());
3512   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3513 
3514   // Check that it was sent to the resolver.
3515   ASSERT_EQ(1u, resolver.pending_jobs().size());
3516   EXPECT_EQ(GURL("http://request2"), resolver.pending_jobs()[0]->url());
3517 
3518   // Complete the pending second request.
3519   resolver.pending_jobs()[0]->results()->UseNamedProxy("request2:80");
3520   resolver.pending_jobs()[0]->CompleteNow(OK);
3521 
3522   // Wait for completion callback, and verify that the request ran as expected.
3523   EXPECT_THAT(callback2.WaitForResult(), IsOk());
3524   EXPECT_EQ("[request2:80]", info2.proxy_chain().ToDebugString());
3525 }
3526 
3527 // This test verifies that the PAC script specified by the settings is
3528 // periodically polled for changes. Specifically, if the initial fetch succeeds,
3529 // however at a later time it starts to fail, we should re-configure the
3530 // ConfiguredProxyResolutionService to stop using that PAC script.
TEST_F(ConfiguredProxyResolutionServiceTest,PACScriptRefetchAfterSuccess)3531 TEST_F(ConfiguredProxyResolutionServiceTest, PACScriptRefetchAfterSuccess) {
3532   // Change the retry policy to wait a mere 1 ms before retrying, so the test
3533   // runs quickly.
3534   ImmediatePollPolicy poll_policy;
3535   ConfiguredProxyResolutionService::set_pac_script_poll_policy(&poll_policy);
3536 
3537   auto config_service =
3538       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
3539 
3540   MockAsyncProxyResolver resolver;
3541   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
3542   auto* factory_ptr = factory.get();
3543 
3544   ConfiguredProxyResolutionService service(std::move(config_service),
3545                                            std::move(factory), nullptr,
3546                                            /*quick_check_enabled=*/true);
3547 
3548   auto fetcher = std::make_unique<MockPacFileFetcher>();
3549   auto* fetcher_ptr = fetcher.get();
3550   service.SetPacFileFetchers(std::move(fetcher),
3551                              std::make_unique<DoNothingDhcpPacFileFetcher>());
3552 
3553   // Start 1 request.
3554 
3555   ProxyInfo info1;
3556   TestCompletionCallback callback1;
3557   std::unique_ptr<ProxyResolutionRequest> request1;
3558   int rv = service.ResolveProxy(
3559       GURL("http://request1"), std::string(), NetworkAnonymizationKey(), &info1,
3560       callback1.callback(), &request1, NetLogWithSource());
3561   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3562 
3563   // The first request should have triggered initial download of PAC script.
3564   EXPECT_TRUE(fetcher_ptr->has_pending_request());
3565   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
3566 
3567   // Nothing has been sent to the factory yet.
3568   EXPECT_TRUE(factory_ptr->pending_requests().empty());
3569 
3570   // At this point the ConfiguredProxyResolutionService should be waiting for
3571   // the PacFileFetcher to invoke its completion callback, notifying it of PAC
3572   // script download completion.
3573   fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
3574 
3575   // Now that the PAC script is downloaded, the request will have been sent to
3576   // the proxy resolver.
3577   EXPECT_EQ(kValidPacScript116,
3578             factory_ptr->pending_requests()[0]->script_data()->utf16());
3579   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
3580 
3581   ASSERT_EQ(1u, resolver.pending_jobs().size());
3582   EXPECT_EQ(GURL("http://request1"), resolver.pending_jobs()[0]->url());
3583 
3584   // Complete the pending request.
3585   resolver.pending_jobs()[0]->results()->UseNamedProxy("request1:80");
3586   resolver.pending_jobs()[0]->CompleteNow(OK);
3587 
3588   // Wait for completion callback, and verify that the request ran as expected.
3589   EXPECT_THAT(callback1.WaitForResult(), IsOk());
3590   EXPECT_EQ("[request1:80]", info1.proxy_chain().ToDebugString());
3591 
3592   // At this point we have initialized the proxy service using a PAC script.
3593   //
3594   // A background task to periodically re-check the PAC script for validity will
3595   // have been started. We will now wait for the next download attempt to start.
3596   //
3597   // Note that we shouldn't have to wait long here, since our test enables a
3598   // special unit-test mode.
3599   fetcher_ptr->WaitUntilFetch();
3600 
3601   ASSERT_TRUE(factory_ptr->pending_requests().empty());
3602   ASSERT_TRUE(resolver.pending_jobs().empty());
3603 
3604   // Make sure that our background checker is trying to download the expected
3605   // PAC script (same one as before). This time we will simulate a failure
3606   // to download the script.
3607   EXPECT_TRUE(fetcher_ptr->has_pending_request());
3608   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
3609   fetcher_ptr->NotifyFetchCompletion(ERR_FAILED, std::string());
3610 
3611   base::RunLoop().RunUntilIdle();
3612 
3613   // At this point the ConfiguredProxyResolutionService should have
3614   // re-configured itself to use DIRECT connections rather than the given proxy
3615   // resolver.
3616 
3617   // Start a second request.
3618   ProxyInfo info2;
3619   TestCompletionCallback callback2;
3620   std::unique_ptr<ProxyResolutionRequest> request2;
3621   rv = service.ResolveProxy(
3622       GURL("http://request2"), std::string(), NetworkAnonymizationKey(), &info2,
3623       callback2.callback(), &request2, NetLogWithSource());
3624   EXPECT_THAT(rv, IsOk());
3625   EXPECT_TRUE(info2.is_direct());
3626 }
3627 
3628 // Tests that the code which decides at what times to poll the PAC
3629 // script follows the expected policy.
TEST_F(ConfiguredProxyResolutionServiceTest,PACScriptPollingPolicy)3630 TEST_F(ConfiguredProxyResolutionServiceTest, PACScriptPollingPolicy) {
3631   // Retrieve the internal polling policy implementation used by
3632   // ConfiguredProxyResolutionService.
3633   std::unique_ptr<ConfiguredProxyResolutionService::PacPollPolicy> policy =
3634       ConfiguredProxyResolutionService::CreateDefaultPacPollPolicy();
3635 
3636   int error;
3637   ConfiguredProxyResolutionService::PacPollPolicy::Mode mode;
3638   const base::TimeDelta initial_delay = base::Milliseconds(-1);
3639   base::TimeDelta delay = initial_delay;
3640 
3641   // --------------------------------------------------
3642   // Test the poll sequence in response to a failure.
3643   // --------------------------------------------------
3644   error = ERR_NAME_NOT_RESOLVED;
3645 
3646   // Poll #0
3647   mode = policy->GetNextDelay(error, initial_delay, &delay);
3648   EXPECT_EQ(8, delay.InSeconds());
3649   EXPECT_EQ(ConfiguredProxyResolutionService::PacPollPolicy::MODE_USE_TIMER,
3650             mode);
3651 
3652   // Poll #1
3653   mode = policy->GetNextDelay(error, delay, &delay);
3654   EXPECT_EQ(32, delay.InSeconds());
3655   EXPECT_EQ(ConfiguredProxyResolutionService::PacPollPolicy::
3656                 MODE_START_AFTER_ACTIVITY,
3657             mode);
3658 
3659   // Poll #2
3660   mode = policy->GetNextDelay(error, delay, &delay);
3661   EXPECT_EQ(120, delay.InSeconds());
3662   EXPECT_EQ(ConfiguredProxyResolutionService::PacPollPolicy::
3663                 MODE_START_AFTER_ACTIVITY,
3664             mode);
3665 
3666   // Poll #3
3667   mode = policy->GetNextDelay(error, delay, &delay);
3668   EXPECT_EQ(14400, delay.InSeconds());
3669   EXPECT_EQ(ConfiguredProxyResolutionService::PacPollPolicy::
3670                 MODE_START_AFTER_ACTIVITY,
3671             mode);
3672 
3673   // Poll #4
3674   mode = policy->GetNextDelay(error, delay, &delay);
3675   EXPECT_EQ(14400, delay.InSeconds());
3676   EXPECT_EQ(ConfiguredProxyResolutionService::PacPollPolicy::
3677                 MODE_START_AFTER_ACTIVITY,
3678             mode);
3679 
3680   // --------------------------------------------------
3681   // Test the poll sequence in response to a success.
3682   // --------------------------------------------------
3683   error = OK;
3684 
3685   // Poll #0
3686   mode = policy->GetNextDelay(error, initial_delay, &delay);
3687   EXPECT_EQ(43200, delay.InSeconds());
3688   EXPECT_EQ(ConfiguredProxyResolutionService::PacPollPolicy::
3689                 MODE_START_AFTER_ACTIVITY,
3690             mode);
3691 
3692   // Poll #1
3693   mode = policy->GetNextDelay(error, delay, &delay);
3694   EXPECT_EQ(43200, delay.InSeconds());
3695   EXPECT_EQ(ConfiguredProxyResolutionService::PacPollPolicy::
3696                 MODE_START_AFTER_ACTIVITY,
3697             mode);
3698 
3699   // Poll #2
3700   mode = policy->GetNextDelay(error, delay, &delay);
3701   EXPECT_EQ(43200, delay.InSeconds());
3702   EXPECT_EQ(ConfiguredProxyResolutionService::PacPollPolicy::
3703                 MODE_START_AFTER_ACTIVITY,
3704             mode);
3705 }
3706 
3707 // This tests the polling of the PAC script. Specifically, it tests that
3708 // polling occurs in response to user activity.
TEST_F(ConfiguredProxyResolutionServiceTest,PACScriptRefetchAfterActivity)3709 TEST_F(ConfiguredProxyResolutionServiceTest, PACScriptRefetchAfterActivity) {
3710   ImmediateAfterActivityPollPolicy poll_policy;
3711   ConfiguredProxyResolutionService::set_pac_script_poll_policy(&poll_policy);
3712 
3713   auto config_service =
3714       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
3715 
3716   MockAsyncProxyResolver resolver;
3717   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
3718   auto* factory_ptr = factory.get();
3719 
3720   ConfiguredProxyResolutionService service(std::move(config_service),
3721                                            std::move(factory), nullptr,
3722                                            /*quick_check_enabled=*/true);
3723 
3724   auto fetcher = std::make_unique<MockPacFileFetcher>();
3725   auto* fetcher_ptr = fetcher.get();
3726   service.SetPacFileFetchers(std::move(fetcher),
3727                              std::make_unique<DoNothingDhcpPacFileFetcher>());
3728 
3729   // Start 1 request.
3730 
3731   ProxyInfo info1;
3732   TestCompletionCallback callback1;
3733   std::unique_ptr<ProxyResolutionRequest> request1;
3734   int rv = service.ResolveProxy(
3735       GURL("http://request1"), std::string(), NetworkAnonymizationKey(), &info1,
3736       callback1.callback(), &request1, NetLogWithSource());
3737   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3738 
3739   // The first request should have triggered initial download of PAC script.
3740   EXPECT_TRUE(fetcher_ptr->has_pending_request());
3741   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
3742 
3743   // Nothing has been sent to the factory yet.
3744   EXPECT_TRUE(factory_ptr->pending_requests().empty());
3745 
3746   // At this point the ConfiguredProxyResolutionService should be waiting for
3747   // the PacFileFetcher to invoke its completion callback, notifying it of PAC
3748   // script download completion.
3749   fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
3750 
3751   // Now that the PAC script is downloaded, the request will have been sent to
3752   // the proxy resolver.
3753   EXPECT_EQ(kValidPacScript116,
3754             factory_ptr->pending_requests()[0]->script_data()->utf16());
3755   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
3756 
3757   ASSERT_EQ(1u, resolver.pending_jobs().size());
3758   EXPECT_EQ(GURL("http://request1"), resolver.pending_jobs()[0]->url());
3759 
3760   // Complete the pending request.
3761   resolver.pending_jobs()[0]->results()->UseNamedProxy("request1:80");
3762   resolver.pending_jobs()[0]->CompleteNow(OK);
3763 
3764   // Wait for completion callback, and verify that the request ran as expected.
3765   EXPECT_THAT(callback1.WaitForResult(), IsOk());
3766   EXPECT_EQ("[request1:80]", info1.proxy_chain().ToDebugString());
3767 
3768   // At this point we have initialized the proxy service using a PAC script.
3769   // Our PAC poller is set to update ONLY in response to network activity,
3770   // (i.e. another call to ResolveProxy()).
3771 
3772   ASSERT_FALSE(fetcher_ptr->has_pending_request());
3773   ASSERT_TRUE(factory_ptr->pending_requests().empty());
3774   ASSERT_TRUE(resolver.pending_jobs().empty());
3775 
3776   // Start a second request.
3777   ProxyInfo info2;
3778   TestCompletionCallback callback2;
3779   std::unique_ptr<ProxyResolutionRequest> request2;
3780   rv = service.ResolveProxy(
3781       GURL("http://request2"), std::string(), NetworkAnonymizationKey(), &info2,
3782       callback2.callback(), &request2, NetLogWithSource());
3783   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3784 
3785   // This request should have sent work to the resolver; complete it.
3786   ASSERT_EQ(1u, resolver.pending_jobs().size());
3787   EXPECT_EQ(GURL("http://request2"), resolver.pending_jobs()[0]->url());
3788   resolver.pending_jobs()[0]->results()->UseNamedProxy("request2:80");
3789   resolver.pending_jobs()[0]->CompleteNow(OK);
3790 
3791   EXPECT_THAT(callback2.WaitForResult(), IsOk());
3792   EXPECT_EQ("[request2:80]", info2.proxy_chain().ToDebugString());
3793 
3794   // In response to getting that resolve request, the poller should have
3795   // started the next poll, and made it as far as to request the download.
3796 
3797   EXPECT_TRUE(fetcher_ptr->has_pending_request());
3798   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
3799 
3800   // This time we will fail the download, to simulate a PAC script change.
3801   fetcher_ptr->NotifyFetchCompletion(ERR_FAILED, std::string());
3802 
3803   // Drain the message loop, so ConfiguredProxyResolutionService is notified of
3804   // the change and has a chance to re-configure itself.
3805   base::RunLoop().RunUntilIdle();
3806 
3807   // Start a third request -- this time we expect to get a direct connection
3808   // since the PAC script poller experienced a failure.
3809   ProxyInfo info3;
3810   TestCompletionCallback callback3;
3811   std::unique_ptr<ProxyResolutionRequest> request3;
3812   rv = service.ResolveProxy(
3813       GURL("http://request3"), std::string(), NetworkAnonymizationKey(), &info3,
3814       callback3.callback(), &request3, NetLogWithSource());
3815   EXPECT_THAT(rv, IsOk());
3816   EXPECT_TRUE(info3.is_direct());
3817 }
3818 
TEST_F(ConfiguredProxyResolutionServiceTest,IpAddressChangeResetsProxy)3819 TEST_F(ConfiguredProxyResolutionServiceTest, IpAddressChangeResetsProxy) {
3820   NeverPollPolicy poll_policy;
3821   ConfiguredProxyResolutionService::set_pac_script_poll_policy(&poll_policy);
3822 
3823   MockAsyncProxyResolver resolver;
3824   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(
3825       /*resolvers_expect_pac_bytes=*/true);
3826   MockAsyncProxyResolverFactory* factory_ptr = factory.get();
3827   ConfiguredProxyResolutionService service(
3828       std::make_unique<MockProxyConfigService>(ProxyConfig::CreateAutoDetect()),
3829       std::move(factory),
3830       /*net_log=*/nullptr, /*quick_check_enabled=*/true);
3831   auto fetcher = std::make_unique<MockPacFileFetcher>();
3832   MockPacFileFetcher* fetcher_ptr = fetcher.get();
3833   service.SetPacFileFetchers(std::move(fetcher),
3834                              std::make_unique<DoNothingDhcpPacFileFetcher>());
3835 
3836   const base::TimeDelta kConfigDelay = base::Seconds(5);
3837   service.set_stall_proxy_auto_config_delay(kConfigDelay);
3838 
3839   // Initialize by making and completing a proxy request.
3840   ProxyInfo info1;
3841   TestCompletionCallback callback1;
3842   std::unique_ptr<ProxyResolutionRequest> request1;
3843   int rv = service.ResolveProxy(
3844       GURL("http://request1"), std::string(), NetworkAnonymizationKey(), &info1,
3845       callback1.callback(), &request1, NetLogWithSource());
3846   ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
3847   ASSERT_TRUE(fetcher_ptr->has_pending_request());
3848   fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
3849   ASSERT_THAT(factory_ptr->pending_requests(), testing::SizeIs(1));
3850   EXPECT_EQ(kValidPacScript116,
3851             factory_ptr->pending_requests()[0]->script_data()->utf16());
3852   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
3853   ASSERT_THAT(resolver.pending_jobs(), testing::SizeIs(1));
3854   resolver.pending_jobs()[0]->CompleteNow(OK);
3855   ASSERT_THAT(callback1.WaitForResult(), IsOk());
3856   EXPECT_FALSE(fetcher_ptr->has_pending_request());
3857 
3858   // Expect IP address notification to trigger a fetch after wait period.
3859   NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
3860   FastForwardBy(kConfigDelay - base::Milliseconds(2));
3861   EXPECT_FALSE(fetcher_ptr->has_pending_request());
3862   FastForwardBy(base::Milliseconds(2));
3863   EXPECT_TRUE(fetcher_ptr->has_pending_request());
3864 
3865   // Leave pending fetch hanging.
3866 
3867   // Expect proxy requests are blocked on completion of change-triggered fetch.
3868   ProxyInfo info2;
3869   TestCompletionCallback callback2;
3870   std::unique_ptr<ProxyResolutionRequest> request2;
3871   rv = service.ResolveProxy(
3872       GURL("http://request1"), std::string(), NetworkAnonymizationKey(), &info2,
3873       callback2.callback(), &request2, NetLogWithSource());
3874   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3875   EXPECT_THAT(resolver.pending_jobs(), testing::IsEmpty());
3876 
3877   // Finish pending fetch and expect proxy request to be able to complete.
3878   fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript2);
3879   ASSERT_THAT(factory_ptr->pending_requests(), testing::SizeIs(1));
3880   EXPECT_EQ(kValidPacScript216,
3881             factory_ptr->pending_requests()[0]->script_data()->utf16());
3882   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
3883   ASSERT_THAT(resolver.pending_jobs(), testing::SizeIs(1));
3884   resolver.pending_jobs()[0]->CompleteNow(OK);
3885   EXPECT_THAT(callback2.WaitForResult(), IsOk());
3886   EXPECT_FALSE(fetcher_ptr->has_pending_request());
3887 }
3888 
TEST_F(ConfiguredProxyResolutionServiceTest,DnsChangeTriggersPoll)3889 TEST_F(ConfiguredProxyResolutionServiceTest, DnsChangeTriggersPoll) {
3890   ImmediateAfterActivityPollPolicy poll_policy;
3891   ConfiguredProxyResolutionService::set_pac_script_poll_policy(&poll_policy);
3892 
3893   MockAsyncProxyResolver resolver;
3894   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(
3895       /*resolvers_expect_pac_bytes=*/true);
3896   MockAsyncProxyResolverFactory* factory_ptr = factory.get();
3897   ConfiguredProxyResolutionService service(
3898       std::make_unique<MockProxyConfigService>(ProxyConfig::CreateAutoDetect()),
3899       std::move(factory),
3900       /*net_log=*/nullptr, /*quick_check_enabled=*/true);
3901   auto fetcher = std::make_unique<MockPacFileFetcher>();
3902   MockPacFileFetcher* fetcher_ptr = fetcher.get();
3903   service.SetPacFileFetchers(std::move(fetcher),
3904                              std::make_unique<DoNothingDhcpPacFileFetcher>());
3905 
3906   // Initialize config and poller by making and completing a proxy request.
3907   ProxyInfo info1;
3908   TestCompletionCallback callback1;
3909   std::unique_ptr<ProxyResolutionRequest> request1;
3910   int rv = service.ResolveProxy(
3911       GURL("http://request1"), std::string(), NetworkAnonymizationKey(), &info1,
3912       callback1.callback(), &request1, NetLogWithSource());
3913   ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
3914   ASSERT_TRUE(fetcher_ptr->has_pending_request());
3915   fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
3916   ASSERT_THAT(factory_ptr->pending_requests(), testing::SizeIs(1));
3917   EXPECT_EQ(kValidPacScript116,
3918             factory_ptr->pending_requests()[0]->script_data()->utf16());
3919   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
3920   ASSERT_THAT(resolver.pending_jobs(), testing::SizeIs(1));
3921   resolver.pending_jobs()[0]->CompleteNow(OK);
3922   ASSERT_THAT(callback1.WaitForResult(), IsOk());
3923   EXPECT_FALSE(fetcher_ptr->has_pending_request());
3924 
3925   // Expect DNS notification to trigger a fetch.
3926   NetworkChangeNotifier::NotifyObserversOfDNSChangeForTests();
3927   fetcher_ptr->WaitUntilFetch();
3928   EXPECT_TRUE(fetcher_ptr->has_pending_request());
3929 
3930   // Leave pending fetch hanging.
3931 
3932   // Expect proxy requests are not blocked on completion of DNS-triggered fetch.
3933   ProxyInfo info2;
3934   TestCompletionCallback callback2;
3935   std::unique_ptr<ProxyResolutionRequest> request2;
3936   rv = service.ResolveProxy(
3937       GURL("http://request2"), std::string(), NetworkAnonymizationKey(), &info2,
3938       callback2.callback(), &request2, NetLogWithSource());
3939   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
3940   ASSERT_THAT(resolver.pending_jobs(), testing::SizeIs(1));
3941   resolver.pending_jobs()[0]->CompleteNow(OK);
3942   EXPECT_THAT(callback2.WaitForResult(), IsOk());
3943 
3944   // Complete DNS-triggered fetch.
3945   fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript2);
3946   RunUntilIdle();
3947 
3948   // Expect further proxy requests to use the new fetch result.
3949   ProxyInfo info3;
3950   TestCompletionCallback callback3;
3951   std::unique_ptr<ProxyResolutionRequest> request3;
3952   rv = service.ResolveProxy(
3953       GURL("http://request3"), std::string(), NetworkAnonymizationKey(), &info3,
3954       callback3.callback(), &request3, NetLogWithSource());
3955   ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
3956   ASSERT_THAT(factory_ptr->pending_requests(), testing::SizeIs(1));
3957   EXPECT_EQ(kValidPacScript216,
3958             factory_ptr->pending_requests()[0]->script_data()->utf16());
3959   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
3960   ASSERT_THAT(resolver.pending_jobs(), testing::SizeIs(1));
3961   resolver.pending_jobs()[0]->CompleteNow(OK);
3962   ASSERT_THAT(callback3.WaitForResult(), IsOk());
3963   EXPECT_FALSE(fetcher_ptr->has_pending_request());
3964 }
3965 
TEST_F(ConfiguredProxyResolutionServiceTest,DnsChangeNoopWithoutResolver)3966 TEST_F(ConfiguredProxyResolutionServiceTest, DnsChangeNoopWithoutResolver) {
3967   ImmediateAfterActivityPollPolicy poll_policy;
3968   ConfiguredProxyResolutionService::set_pac_script_poll_policy(&poll_policy);
3969 
3970   MockAsyncProxyResolver resolver;
3971   ConfiguredProxyResolutionService service(
3972       std::make_unique<MockProxyConfigService>(ProxyConfig::CreateAutoDetect()),
3973       std::make_unique<MockAsyncProxyResolverFactory>(
3974           /*resolvers_expect_pac_bytes=*/true),
3975       /*net_log=*/nullptr, /*quick_check_enabled=*/true);
3976   auto fetcher = std::make_unique<MockPacFileFetcher>();
3977   MockPacFileFetcher* fetcher_ptr = fetcher.get();
3978   service.SetPacFileFetchers(std::move(fetcher),
3979                              std::make_unique<DoNothingDhcpPacFileFetcher>());
3980 
3981   // Expect DNS notification to do nothing because no proxy requests have yet
3982   // been made.
3983   NetworkChangeNotifier::NotifyObserversOfDNSChangeForTests();
3984   RunUntilIdle();
3985   EXPECT_FALSE(fetcher_ptr->has_pending_request());
3986 }
3987 
3988 // Helper class to exercise URL sanitization by submitting URLs to the
3989 // ConfiguredProxyResolutionService and returning the URL passed to the
3990 // ProxyResolver.
3991 class SanitizeUrlHelper {
3992  public:
SanitizeUrlHelper()3993   SanitizeUrlHelper() {
3994     auto config_service =
3995         std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
3996     auto factory = std::make_unique<MockAsyncProxyResolverFactory>(false);
3997     auto* factory_ptr = factory.get();
3998     service_ = std::make_unique<ConfiguredProxyResolutionService>(
3999         std::move(config_service), std::move(factory), nullptr,
4000         /*quick_check_enabled=*/true);
4001 
4002     // Do an initial request to initialize the service (configure the PAC
4003     // script).
4004     GURL url("http://example.com");
4005 
4006     ProxyInfo info;
4007     TestCompletionCallback callback;
4008     std::unique_ptr<ProxyResolutionRequest> request;
4009     int rv = service_->ResolveProxy(
4010         url, std::string(), NetworkAnonymizationKey(), &info,
4011         callback.callback(), &request, NetLogWithSource());
4012     EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
4013 
4014     // First step is to download the PAC script.
4015     EXPECT_EQ(GURL("http://foopy/proxy.pac"),
4016               factory_ptr->pending_requests()[0]->script_data()->url());
4017     factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
4018 
4019     EXPECT_EQ(1u, resolver.pending_jobs().size());
4020     EXPECT_EQ(url, resolver.pending_jobs()[0]->url());
4021 
4022     // Complete the request.
4023     resolver.pending_jobs()[0]->results()->UsePacString("DIRECT");
4024     resolver.pending_jobs()[0]->CompleteNow(OK);
4025     EXPECT_THAT(callback.WaitForResult(), IsOk());
4026     EXPECT_TRUE(info.is_direct());
4027   }
4028 
4029   // Makes a proxy resolution request through the
4030   // ConfiguredProxyResolutionService, and returns the URL that was submitted to
4031   // the Proxy Resolver.
SanitizeUrl(const GURL & raw_url)4032   GURL SanitizeUrl(const GURL& raw_url) {
4033     // Issue a request and see what URL is sent to the proxy resolver.
4034     ProxyInfo info;
4035     TestCompletionCallback callback;
4036     std::unique_ptr<ProxyResolutionRequest> request1;
4037     int rv = service_->ResolveProxy(
4038         raw_url, std::string(), NetworkAnonymizationKey(), &info,
4039         callback.callback(), &request1, NetLogWithSource());
4040     EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
4041 
4042     EXPECT_EQ(1u, resolver.pending_jobs().size());
4043 
4044     GURL sanitized_url = resolver.pending_jobs()[0]->url();
4045 
4046     // Complete the request.
4047     resolver.pending_jobs()[0]->results()->UsePacString("DIRECT");
4048     resolver.pending_jobs()[0]->CompleteNow(OK);
4049     EXPECT_THAT(callback.WaitForResult(), IsOk());
4050     EXPECT_TRUE(info.is_direct());
4051 
4052     return sanitized_url;
4053   }
4054 
4055  private:
4056   MockAsyncProxyResolver resolver;
4057   std::unique_ptr<ConfiguredProxyResolutionService> service_;
4058 };
4059 
4060 // Tests that input URLs to proxy resolution are sanitized before being passed
4061 // on to the ProxyResolver (i.e. PAC script evaluator). For instance PAC
4062 // scripts should not be able to see the path for https:// URLs.
TEST_F(ConfiguredProxyResolutionServiceTest,SanitizeUrlForPacScript)4063 TEST_F(ConfiguredProxyResolutionServiceTest, SanitizeUrlForPacScript) {
4064   const struct {
4065     const char* raw_url;
4066     const char* sanitized_url;
4067   } kTests[] = {
4068       // ---------------------------------
4069       // Sanitize cryptographic URLs.
4070       // ---------------------------------
4071 
4072       // Embedded identity is stripped.
4073       {
4074           "https://foo:bar@example.com/",
4075           "https://example.com/",
4076       },
4077       // Fragments and path are stripped.
4078       {
4079           "https://example.com/blah#hello",
4080           "https://example.com/",
4081       },
4082       // Query is stripped.
4083       {
4084           "https://example.com/?hello",
4085           "https://example.com/",
4086       },
4087       // The embedded identity and fragment are stripped.
4088       {
4089           "https://foo:bar@example.com/foo/bar/baz?hello#sigh",
4090           "https://example.com/",
4091       },
4092       // The URL's port should not be stripped.
4093       {
4094           "https://example.com:88/hi",
4095           "https://example.com:88/",
4096       },
4097       // Try a wss:// URL, to make sure it is treated as a cryptographic schemed
4098       // URL.
4099       {
4100           "wss://example.com:88/hi",
4101           "wss://example.com:88/",
4102       },
4103 
4104       // ---------------------------------
4105       // Sanitize non-cryptographic URLs.
4106       // ---------------------------------
4107 
4108       // Embedded identity is stripped.
4109       {
4110           "http://foo:bar@example.com/",
4111           "http://example.com/",
4112       },
4113       {
4114           "ftp://foo:bar@example.com/",
4115           "ftp://example.com/",
4116       },
4117       {
4118           "ftp://example.com/some/path/here",
4119           "ftp://example.com/some/path/here",
4120       },
4121       // Reference fragment is stripped.
4122       {
4123           "http://example.com/blah#hello",
4124           "http://example.com/blah",
4125       },
4126       // Query parameters are NOT stripped.
4127       {
4128           "http://example.com/foo/bar/baz?hello",
4129           "http://example.com/foo/bar/baz?hello",
4130       },
4131       // Fragment is stripped, but path and query are left intact.
4132       {
4133           "http://foo:bar@example.com/foo/bar/baz?hello#sigh",
4134           "http://example.com/foo/bar/baz?hello",
4135       },
4136       // Port numbers are not affected.
4137       {
4138           "http://example.com:88/hi",
4139           "http://example.com:88/hi",
4140       },
4141   };
4142 
4143   SanitizeUrlHelper helper;
4144 
4145   for (const auto& test : kTests) {
4146     GURL raw_url(test.raw_url);
4147     ASSERT_TRUE(raw_url.is_valid());
4148 
4149     EXPECT_EQ(GURL(test.sanitized_url), helper.SanitizeUrl(raw_url));
4150   }
4151 }
4152 
TEST_F(ConfiguredProxyResolutionServiceTest,OnShutdownWithLiveRequest)4153 TEST_F(ConfiguredProxyResolutionServiceTest, OnShutdownWithLiveRequest) {
4154   auto config_service =
4155       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
4156 
4157   MockAsyncProxyResolver resolver;
4158   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
4159 
4160   ConfiguredProxyResolutionService service(std::move(config_service),
4161                                            std::move(factory), nullptr,
4162                                            /*quick_check_enabled=*/true);
4163 
4164   auto fetcher = std::make_unique<MockPacFileFetcher>();
4165   auto* fetcher_ptr = fetcher.get();
4166   service.SetPacFileFetchers(std::move(fetcher),
4167                              std::make_unique<DoNothingDhcpPacFileFetcher>());
4168 
4169   ProxyInfo info;
4170   TestCompletionCallback callback;
4171   std::unique_ptr<ProxyResolutionRequest> request;
4172   int rv = service.ResolveProxy(
4173       GURL("http://request/"), std::string(), NetworkAnonymizationKey(), &info,
4174       callback.callback(), &request, NetLogWithSource());
4175   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
4176 
4177   // The first request should have triggered download of PAC script.
4178   EXPECT_TRUE(fetcher_ptr->has_pending_request());
4179   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher_ptr->pending_request_url());
4180 
4181   service.OnShutdown();
4182   base::RunLoop().RunUntilIdle();
4183   EXPECT_FALSE(callback.have_result());
4184   EXPECT_FALSE(fetcher_ptr->has_pending_request());
4185 }
4186 
TEST_F(ConfiguredProxyResolutionServiceTest,OnShutdownFollowedByRequest)4187 TEST_F(ConfiguredProxyResolutionServiceTest, OnShutdownFollowedByRequest) {
4188   auto config_service =
4189       std::make_unique<MockProxyConfigService>("http://foopy/proxy.pac");
4190 
4191   MockAsyncProxyResolver resolver;
4192   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
4193 
4194   ConfiguredProxyResolutionService service(std::move(config_service),
4195                                            std::move(factory), nullptr,
4196                                            /*quick_check_enabled=*/true);
4197 
4198   auto fetcher = std::make_unique<MockPacFileFetcher>();
4199   auto* fetcher_ptr = fetcher.get();
4200   service.SetPacFileFetchers(std::move(fetcher),
4201                              std::make_unique<DoNothingDhcpPacFileFetcher>());
4202 
4203   service.OnShutdown();
4204 
4205   ProxyInfo info;
4206   TestCompletionCallback callback;
4207   std::unique_ptr<ProxyResolutionRequest> request;
4208   int rv = service.ResolveProxy(
4209       GURL("http://request/"), std::string(), NetworkAnonymizationKey(), &info,
4210       callback.callback(), &request, NetLogWithSource());
4211   EXPECT_THAT(rv, IsOk());
4212   EXPECT_FALSE(fetcher_ptr->has_pending_request());
4213   EXPECT_TRUE(info.is_direct());
4214 }
4215 
4216 const char* kImplicityBypassedHosts[] = {
4217     "localhost",
4218     "localhost.",
4219     "foo.localhost",
4220     "127.0.0.1",
4221     "127.100.0.2",
4222     "[::1]",
4223     "169.254.3.2",
4224     "169.254.100.1",
4225     "[FE80::8]",
4226     "[feb8::1]",
4227 };
4228 
4229 const char* kUrlSchemes[] = {"http://", "https://", "ftp://"};
4230 
TEST_F(ConfiguredProxyResolutionServiceTest,ImplicitlyBypassWithManualSettings)4231 TEST_F(ConfiguredProxyResolutionServiceTest,
4232        ImplicitlyBypassWithManualSettings) {
4233   // Use manual proxy settings that specify a single proxy for all traffic.
4234   ProxyConfig config;
4235   config.proxy_rules().ParseFromString("foopy1:8080");
4236   config.set_auto_detect(false);
4237 
4238   auto service = ConfiguredProxyResolutionService::CreateFixedForTest(
4239       ProxyConfigWithAnnotation(config, TRAFFIC_ANNOTATION_FOR_TESTS));
4240 
4241   // A normal request should use the proxy.
4242   std::unique_ptr<ProxyResolutionRequest> request1;
4243   ProxyInfo info1;
4244   TestCompletionCallback callback1;
4245   int rv = service->ResolveProxy(
4246       GURL("http://www.example.com"), std::string(), NetworkAnonymizationKey(),
4247       &info1, callback1.callback(), &request1, NetLogWithSource());
4248   EXPECT_THAT(rv, IsOk());
4249   EXPECT_EQ("[foopy1:8080]", info1.proxy_chain().ToDebugString());
4250 
4251   // Test that localhost and link-local URLs bypass the proxy (independent of
4252   // the URL scheme).
4253   for (auto* host : kImplicityBypassedHosts) {
4254     for (auto* scheme : kUrlSchemes) {
4255       auto url = GURL(std::string(scheme) + std::string(host));
4256 
4257       std::unique_ptr<ProxyResolutionRequest> request;
4258       ProxyInfo info;
4259       TestCompletionCallback callback;
4260       rv = service->ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
4261                                  &info, callback.callback(), &request,
4262                                  NetLogWithSource());
4263       EXPECT_THAT(rv, IsOk());
4264       EXPECT_TRUE(info.is_direct());
4265     }
4266   }
4267 }
4268 
4269 // Test that the when using a PAC script (sourced via auto-detect) certain
4270 // localhost names are implicitly bypassed.
TEST_F(ConfiguredProxyResolutionServiceTest,ImplicitlyBypassWithPac)4271 TEST_F(ConfiguredProxyResolutionServiceTest, ImplicitlyBypassWithPac) {
4272   ProxyConfig config;
4273   config.set_auto_detect(true);
4274 
4275   auto config_service = std::make_unique<MockProxyConfigService>(config);
4276   MockAsyncProxyResolver resolver;
4277   auto factory = std::make_unique<MockAsyncProxyResolverFactory>(true);
4278   auto* factory_ptr = factory.get();
4279   ConfiguredProxyResolutionService service(std::move(config_service),
4280                                            std::move(factory), nullptr,
4281                                            /*quick_check_enabled=*/true);
4282 
4283   auto fetcher = std::make_unique<MockPacFileFetcher>();
4284   auto* fetcher_ptr = fetcher.get();
4285   service.SetPacFileFetchers(std::move(fetcher),
4286                              std::make_unique<DoNothingDhcpPacFileFetcher>());
4287 
4288   // Start 1 requests.
4289 
4290   ProxyInfo info1;
4291   TestCompletionCallback callback1;
4292   std::unique_ptr<ProxyResolutionRequest> request1;
4293   int rv = service.ResolveProxy(
4294       GURL("http://www.google.com"), std::string(), NetworkAnonymizationKey(),
4295       &info1, callback1.callback(), &request1, NetLogWithSource());
4296   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
4297 
4298   // This started auto-detect; complete it.
4299   ASSERT_EQ(0u, factory_ptr->pending_requests().size());
4300   EXPECT_TRUE(fetcher_ptr->has_pending_request());
4301   EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher_ptr->pending_request_url());
4302   fetcher_ptr->NotifyFetchCompletion(OK, kValidPacScript1);
4303 
4304   EXPECT_EQ(kValidPacScript116,
4305             factory_ptr->pending_requests()[0]->script_data()->utf16());
4306   factory_ptr->pending_requests()[0]->CompleteNowWithForwarder(OK, &resolver);
4307 
4308   ASSERT_EQ(1u, resolver.pending_jobs().size());
4309   EXPECT_EQ(GURL("http://www.google.com"), resolver.pending_jobs()[0]->url());
4310 
4311   // Complete the pending request.
4312   resolver.pending_jobs()[0]->results()->UseNamedProxy("request1:80");
4313   resolver.pending_jobs()[0]->CompleteNow(OK);
4314 
4315   // Verify that request ran as expected.
4316   EXPECT_THAT(callback1.WaitForResult(), IsOk());
4317   EXPECT_EQ("[request1:80]", info1.proxy_chain().ToDebugString());
4318 
4319   // Test that localhost and link-local URLs bypass the use of PAC script
4320   // (independent of the URL scheme).
4321   for (auto* host : kImplicityBypassedHosts) {
4322     for (auto* scheme : kUrlSchemes) {
4323       auto url = GURL(std::string(scheme) + std::string(host));
4324 
4325       std::unique_ptr<ProxyResolutionRequest> request;
4326       ProxyInfo info;
4327       TestCompletionCallback callback;
4328       rv = service.ResolveProxy(url, std::string(), NetworkAnonymizationKey(),
4329                                 &info, callback.callback(), &request,
4330                                 NetLogWithSource());
4331       EXPECT_THAT(rv, IsOk());
4332       EXPECT_TRUE(info.is_direct());
4333     }
4334   }
4335 }
4336 
TEST_F(ConfiguredProxyResolutionServiceTest,CastToConfiguredProxyResolutionService)4337 TEST_F(ConfiguredProxyResolutionServiceTest,
4338        CastToConfiguredProxyResolutionService) {
4339   auto config_service =
4340       std::make_unique<MockProxyConfigService>(ProxyConfig::CreateDirect());
4341 
4342   ConfiguredProxyResolutionService service(
4343       std::move(config_service),
4344       std::make_unique<MockAsyncProxyResolverFactory>(false), nullptr,
4345       /*quick_check_enabled=*/true);
4346 
4347   ConfiguredProxyResolutionService* casted_service = nullptr;
4348   EXPECT_TRUE(service.CastToConfiguredProxyResolutionService(&casted_service));
4349   EXPECT_EQ(&service, casted_service);
4350 }
4351 
4352 }  // namespace net
4353