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