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