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