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