1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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/proxy_service.h" 6 7 #include <vector> 8 9 #include "base/format_macros.h" 10 #include "base/logging.h" 11 #include "base/strings/string_util.h" 12 #include "base/strings/utf_string_conversions.h" 13 #include "net/base/load_flags.h" 14 #include "net/base/net_errors.h" 15 #include "net/base/net_log.h" 16 #include "net/base/net_log_unittest.h" 17 #include "net/base/network_delegate.h" 18 #include "net/base/test_completion_callback.h" 19 #include "net/proxy/dhcp_proxy_script_fetcher.h" 20 #include "net/proxy/mock_proxy_resolver.h" 21 #include "net/proxy/mock_proxy_script_fetcher.h" 22 #include "net/proxy/proxy_config_service.h" 23 #include "net/proxy/proxy_resolver.h" 24 #include "net/proxy/proxy_script_fetcher.h" 25 #include "testing/gtest/include/gtest/gtest.h" 26 #include "url/gurl.h" 27 28 using base::ASCIIToUTF16; 29 30 // TODO(eroman): Write a test which exercises 31 // ProxyService::SuspendAllPendingRequests(). 32 namespace net { 33 namespace { 34 35 // This polling policy will decide to poll every 1 ms. 36 class ImmediatePollPolicy : public ProxyService::PacPollPolicy { 37 public: 38 ImmediatePollPolicy() {} 39 40 virtual Mode GetNextDelay(int error, base::TimeDelta current_delay, 41 base::TimeDelta* next_delay) const OVERRIDE { 42 *next_delay = base::TimeDelta::FromMilliseconds(1); 43 return MODE_USE_TIMER; 44 } 45 46 private: 47 DISALLOW_COPY_AND_ASSIGN(ImmediatePollPolicy); 48 }; 49 50 // This polling policy chooses a fantastically large delay. In other words, it 51 // will never trigger a poll 52 class NeverPollPolicy : public ProxyService::PacPollPolicy { 53 public: 54 NeverPollPolicy() {} 55 56 virtual Mode GetNextDelay(int error, base::TimeDelta current_delay, 57 base::TimeDelta* next_delay) const OVERRIDE { 58 *next_delay = base::TimeDelta::FromDays(60); 59 return MODE_USE_TIMER; 60 } 61 62 private: 63 DISALLOW_COPY_AND_ASSIGN(NeverPollPolicy); 64 }; 65 66 // This polling policy starts a poll immediately after network activity. 67 class ImmediateAfterActivityPollPolicy : public ProxyService::PacPollPolicy { 68 public: 69 ImmediateAfterActivityPollPolicy() {} 70 71 virtual Mode GetNextDelay(int error, base::TimeDelta current_delay, 72 base::TimeDelta* next_delay) const OVERRIDE { 73 *next_delay = base::TimeDelta(); 74 return MODE_START_AFTER_ACTIVITY; 75 } 76 77 private: 78 DISALLOW_COPY_AND_ASSIGN(ImmediateAfterActivityPollPolicy); 79 }; 80 81 // This test fixture is used to partially disable the background polling done by 82 // the ProxyService (which it uses to detect whenever its PAC script contents or 83 // WPAD results have changed). 84 // 85 // We disable the feature by setting the poll interval to something really 86 // large, so it will never actually be reached even on the slowest bots that run 87 // these tests. 88 // 89 // We disable the polling in order to avoid any timing dependencies in the 90 // tests. If the bot were to run the tests very slowly and we hadn't disabled 91 // polling, then it might start a background re-try in the middle of our test 92 // and confuse our expectations leading to flaky failures. 93 // 94 // The tests which verify the polling code re-enable the polling behavior but 95 // are careful to avoid timing problems. 96 class ProxyServiceTest : public testing::Test { 97 protected: 98 virtual void SetUp() OVERRIDE { 99 testing::Test::SetUp(); 100 previous_policy_ = 101 ProxyService::set_pac_script_poll_policy(&never_poll_policy_); 102 } 103 104 virtual void TearDown() OVERRIDE { 105 // Restore the original policy. 106 ProxyService::set_pac_script_poll_policy(previous_policy_); 107 testing::Test::TearDown(); 108 } 109 110 private: 111 NeverPollPolicy never_poll_policy_; 112 const ProxyService::PacPollPolicy* previous_policy_; 113 }; 114 115 const char kValidPacScript1[] = "pac-script-v1-FindProxyForURL"; 116 const char kValidPacScript2[] = "pac-script-v2-FindProxyForURL"; 117 118 class MockProxyConfigService: public ProxyConfigService { 119 public: 120 explicit MockProxyConfigService(const ProxyConfig& config) 121 : availability_(CONFIG_VALID), 122 config_(config) { 123 } 124 125 explicit MockProxyConfigService(const std::string& pac_url) 126 : availability_(CONFIG_VALID), 127 config_(ProxyConfig::CreateFromCustomPacURL(GURL(pac_url))) { 128 } 129 130 virtual void AddObserver(Observer* observer) OVERRIDE { 131 observers_.AddObserver(observer); 132 } 133 134 virtual void RemoveObserver(Observer* observer) OVERRIDE { 135 observers_.RemoveObserver(observer); 136 } 137 138 virtual ConfigAvailability GetLatestProxyConfig(ProxyConfig* results) 139 OVERRIDE { 140 if (availability_ == CONFIG_VALID) 141 *results = config_; 142 return availability_; 143 } 144 145 void SetConfig(const ProxyConfig& config) { 146 availability_ = CONFIG_VALID; 147 config_ = config; 148 FOR_EACH_OBSERVER(Observer, observers_, 149 OnProxyConfigChanged(config_, availability_)); 150 } 151 152 private: 153 ConfigAvailability availability_; 154 ProxyConfig config_; 155 ObserverList<Observer, true> observers_; 156 }; 157 158 // A test network delegate that exercises the OnResolveProxy callback. 159 class TestResolveProxyNetworkDelegate : public NetworkDelegate { 160 public: 161 TestResolveProxyNetworkDelegate() 162 : on_resolve_proxy_called_(false), 163 add_proxy_(false), 164 remove_proxy_(false), 165 proxy_service_(NULL) { 166 } 167 168 virtual void OnResolveProxy(const GURL& url, 169 int load_flags, 170 const ProxyService& proxy_service, 171 ProxyInfo* result) OVERRIDE { 172 on_resolve_proxy_called_ = true; 173 proxy_service_ = &proxy_service; 174 DCHECK(!add_proxy_ || !remove_proxy_); 175 if (add_proxy_) { 176 result->UseNamedProxy("delegate_proxy.com"); 177 } else if (remove_proxy_) { 178 result->UseDirect(); 179 } 180 } 181 182 bool on_resolve_proxy_called() const { 183 return on_resolve_proxy_called_; 184 } 185 186 void set_add_proxy(bool add_proxy) { 187 add_proxy_ = add_proxy; 188 } 189 190 void set_remove_proxy(bool remove_proxy) { 191 remove_proxy_ = remove_proxy; 192 } 193 194 const ProxyService* proxy_service() const { 195 return proxy_service_; 196 } 197 198 private: 199 bool on_resolve_proxy_called_; 200 bool add_proxy_; 201 bool remove_proxy_; 202 const ProxyService* proxy_service_; 203 }; 204 205 // A test network delegate that exercises the OnProxyFallback callback. 206 class TestProxyFallbackNetworkDelegate : public NetworkDelegate { 207 public: 208 TestProxyFallbackNetworkDelegate() 209 : on_proxy_fallback_called_(false), 210 proxy_fallback_net_error_(OK) { 211 } 212 213 virtual void OnProxyFallback(const ProxyServer& proxy_server, 214 int net_error) OVERRIDE { 215 proxy_server_ = proxy_server; 216 proxy_fallback_net_error_ = net_error; 217 on_proxy_fallback_called_ = true; 218 } 219 220 bool on_proxy_fallback_called() const { 221 return on_proxy_fallback_called_; 222 } 223 224 const ProxyServer& proxy_server() const { 225 return proxy_server_; 226 } 227 228 int proxy_fallback_net_error() const { 229 return proxy_fallback_net_error_; 230 } 231 232 private: 233 bool on_proxy_fallback_called_; 234 ProxyServer proxy_server_; 235 int proxy_fallback_net_error_; 236 }; 237 238 } // namespace 239 240 TEST_F(ProxyServiceTest, Direct) { 241 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; 242 ProxyService service(new MockProxyConfigService( 243 ProxyConfig::CreateDirect()), resolver, NULL); 244 245 GURL url("http://www.google.com/"); 246 247 ProxyInfo info; 248 TestCompletionCallback callback; 249 CapturingBoundNetLog log; 250 int rv = service.ResolveProxy( 251 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL, 252 log.bound()); 253 EXPECT_EQ(OK, rv); 254 EXPECT_TRUE(resolver->pending_requests().empty()); 255 256 EXPECT_TRUE(info.is_direct()); 257 EXPECT_TRUE(info.proxy_resolve_start_time().is_null()); 258 EXPECT_TRUE(info.proxy_resolve_end_time().is_null()); 259 260 // Check the NetLog was filled correctly. 261 CapturingNetLog::CapturedEntryList entries; 262 log.GetEntries(&entries); 263 264 EXPECT_EQ(3u, entries.size()); 265 EXPECT_TRUE(LogContainsBeginEvent( 266 entries, 0, NetLog::TYPE_PROXY_SERVICE)); 267 EXPECT_TRUE(LogContainsEvent( 268 entries, 1, NetLog::TYPE_PROXY_SERVICE_RESOLVED_PROXY_LIST, 269 NetLog::PHASE_NONE)); 270 EXPECT_TRUE(LogContainsEndEvent( 271 entries, 2, NetLog::TYPE_PROXY_SERVICE)); 272 } 273 274 TEST_F(ProxyServiceTest, OnResolveProxyCallbackAddProxy) { 275 ProxyConfig config; 276 config.proxy_rules().ParseFromString("foopy1:8080"); 277 config.set_auto_detect(false); 278 config.proxy_rules().bypass_rules.ParseFromString("*.org"); 279 280 ProxyService service( 281 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL); 282 283 GURL url("http://www.google.com/"); 284 GURL bypass_url("http://internet.org"); 285 286 ProxyInfo info; 287 TestCompletionCallback callback; 288 CapturingBoundNetLog log; 289 290 // First, warm up the ProxyService. 291 int rv = service.ResolveProxy( 292 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL, 293 log.bound()); 294 EXPECT_EQ(OK, rv); 295 296 // Verify that network delegate is invoked. 297 TestResolveProxyNetworkDelegate delegate; 298 rv = service.ResolveProxy( 299 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, &delegate, 300 log.bound()); 301 EXPECT_TRUE(delegate.on_resolve_proxy_called()); 302 EXPECT_EQ(&service, delegate.proxy_service()); 303 304 // Verify that the NetworkDelegate's behavior is stateless across 305 // invocations of ResolveProxy. Start by having the callback add a proxy 306 // and checking that subsequent requests are not affected. 307 delegate.set_add_proxy(true); 308 309 // Callback should interpose: 310 rv = service.ResolveProxy( 311 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, &delegate, 312 log.bound()); 313 EXPECT_FALSE(info.is_direct()); 314 EXPECT_EQ(info.proxy_server().host_port_pair().host(), "delegate_proxy.com"); 315 delegate.set_add_proxy(false); 316 317 // Check non-bypassed URL: 318 rv = service.ResolveProxy( 319 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, &delegate, 320 log.bound()); 321 EXPECT_FALSE(info.is_direct()); 322 EXPECT_EQ(info.proxy_server().host_port_pair().host(), "foopy1"); 323 324 // Check bypassed URL: 325 rv = service.ResolveProxy( 326 bypass_url, net::LOAD_NORMAL, &info, callback.callback(), NULL, 327 &delegate, log.bound()); 328 EXPECT_TRUE(info.is_direct()); 329 } 330 331 TEST_F(ProxyServiceTest, OnResolveProxyCallbackRemoveProxy) { 332 // Same as OnResolveProxyCallbackAddProxy, but verify that the 333 // NetworkDelegate's behavior is stateless across invocations after it 334 // *removes* a proxy. 335 ProxyConfig config; 336 config.proxy_rules().ParseFromString("foopy1:8080"); 337 config.set_auto_detect(false); 338 config.proxy_rules().bypass_rules.ParseFromString("*.org"); 339 340 ProxyService service( 341 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL); 342 343 GURL url("http://www.google.com/"); 344 GURL bypass_url("http://internet.org"); 345 346 ProxyInfo info; 347 TestCompletionCallback callback; 348 CapturingBoundNetLog log; 349 350 // First, warm up the ProxyService. 351 int rv = service.ResolveProxy( 352 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL, 353 log.bound()); 354 EXPECT_EQ(OK, rv); 355 356 TestResolveProxyNetworkDelegate delegate; 357 delegate.set_remove_proxy(true); 358 359 // Callback should interpose: 360 rv = service.ResolveProxy( 361 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, &delegate, 362 log.bound()); 363 EXPECT_TRUE(info.is_direct()); 364 delegate.set_remove_proxy(false); 365 366 // Check non-bypassed URL: 367 rv = service.ResolveProxy( 368 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, &delegate, 369 log.bound()); 370 EXPECT_FALSE(info.is_direct()); 371 EXPECT_EQ(info.proxy_server().host_port_pair().host(), "foopy1"); 372 373 // Check bypassed URL: 374 rv = service.ResolveProxy( 375 bypass_url, net::LOAD_NORMAL, &info, callback.callback(), NULL, 376 &delegate, log.bound()); 377 EXPECT_TRUE(info.is_direct()); 378 } 379 380 TEST_F(ProxyServiceTest, PAC) { 381 MockProxyConfigService* config_service = 382 new MockProxyConfigService("http://foopy/proxy.pac"); 383 384 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; 385 386 ProxyService service(config_service, resolver, NULL); 387 388 GURL url("http://www.google.com/"); 389 390 ProxyInfo info; 391 TestCompletionCallback callback; 392 ProxyService::PacRequest* request; 393 CapturingBoundNetLog log; 394 395 int rv = service.ResolveProxy( 396 url, net::LOAD_NORMAL, &info, callback.callback(), &request, NULL, 397 log.bound()); 398 EXPECT_EQ(ERR_IO_PENDING, rv); 399 400 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request)); 401 402 EXPECT_EQ(GURL("http://foopy/proxy.pac"), 403 resolver->pending_set_pac_script_request()->script_data()->url()); 404 resolver->pending_set_pac_script_request()->CompleteNow(OK); 405 406 ASSERT_EQ(1u, resolver->pending_requests().size()); 407 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); 408 409 // Set the result in proxy resolver. 410 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy"); 411 resolver->pending_requests()[0]->CompleteNow(OK); 412 413 EXPECT_EQ(OK, callback.WaitForResult()); 414 EXPECT_FALSE(info.is_direct()); 415 EXPECT_EQ("foopy:80", info.proxy_server().ToURI()); 416 EXPECT_TRUE(info.did_use_pac_script()); 417 418 EXPECT_FALSE(info.proxy_resolve_start_time().is_null()); 419 EXPECT_FALSE(info.proxy_resolve_end_time().is_null()); 420 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time()); 421 422 // Check the NetLog was filled correctly. 423 CapturingNetLog::CapturedEntryList entries; 424 log.GetEntries(&entries); 425 426 EXPECT_EQ(5u, entries.size()); 427 EXPECT_TRUE(LogContainsBeginEvent( 428 entries, 0, NetLog::TYPE_PROXY_SERVICE)); 429 EXPECT_TRUE(LogContainsBeginEvent( 430 entries, 1, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC)); 431 EXPECT_TRUE(LogContainsEndEvent( 432 entries, 2, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC)); 433 EXPECT_TRUE(LogContainsEndEvent( 434 entries, 4, NetLog::TYPE_PROXY_SERVICE)); 435 } 436 437 // Test that the proxy resolver does not see the URL's username/password 438 // or its reference section. 439 TEST_F(ProxyServiceTest, PAC_NoIdentityOrHash) { 440 MockProxyConfigService* config_service = 441 new MockProxyConfigService("http://foopy/proxy.pac"); 442 443 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; 444 445 ProxyService service(config_service, resolver, NULL); 446 447 GURL url("http://username:password@www.google.com/?ref#hash#hash"); 448 449 ProxyInfo info; 450 TestCompletionCallback callback; 451 int rv = service.ResolveProxy( 452 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL, 453 BoundNetLog()); 454 EXPECT_EQ(ERR_IO_PENDING, rv); 455 456 EXPECT_EQ(GURL("http://foopy/proxy.pac"), 457 resolver->pending_set_pac_script_request()->script_data()->url()); 458 resolver->pending_set_pac_script_request()->CompleteNow(OK); 459 460 ASSERT_EQ(1u, resolver->pending_requests().size()); 461 // The URL should have been simplified, stripping the username/password/hash. 462 EXPECT_EQ(GURL("http://www.google.com/?ref"), 463 resolver->pending_requests()[0]->url()); 464 465 // We end here without ever completing the request -- destruction of 466 // ProxyService will cancel the outstanding request. 467 } 468 469 TEST_F(ProxyServiceTest, PAC_FailoverWithoutDirect) { 470 MockProxyConfigService* config_service = 471 new MockProxyConfigService("http://foopy/proxy.pac"); 472 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; 473 474 ProxyService service(config_service, resolver, NULL); 475 476 GURL url("http://www.google.com/"); 477 478 ProxyInfo info; 479 TestCompletionCallback callback1; 480 int rv = service.ResolveProxy( 481 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, 482 BoundNetLog()); 483 EXPECT_EQ(ERR_IO_PENDING, rv); 484 485 EXPECT_EQ(GURL("http://foopy/proxy.pac"), 486 resolver->pending_set_pac_script_request()->script_data()->url()); 487 resolver->pending_set_pac_script_request()->CompleteNow(OK); 488 489 ASSERT_EQ(1u, resolver->pending_requests().size()); 490 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); 491 492 // Set the result in proxy resolver. 493 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy:8080"); 494 resolver->pending_requests()[0]->CompleteNow(OK); 495 496 EXPECT_EQ(OK, callback1.WaitForResult()); 497 EXPECT_FALSE(info.is_direct()); 498 EXPECT_EQ("foopy:8080", info.proxy_server().ToURI()); 499 EXPECT_TRUE(info.did_use_pac_script()); 500 501 EXPECT_FALSE(info.proxy_resolve_start_time().is_null()); 502 EXPECT_FALSE(info.proxy_resolve_end_time().is_null()); 503 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time()); 504 505 // Now, imagine that connecting to foopy:8080 fails: there is nothing 506 // left to fallback to, since our proxy list was NOT terminated by 507 // DIRECT. 508 NetworkDelegate network_delegate; 509 TestCompletionCallback callback2; 510 ProxyServer expected_proxy_server = info.proxy_server(); 511 rv = service.ReconsiderProxyAfterError( 512 url, net::LOAD_NORMAL, net::ERR_PROXY_CONNECTION_FAILED, 513 &info, callback2.callback(), NULL, &network_delegate, BoundNetLog()); 514 // ReconsiderProxyAfterError returns error indicating nothing left. 515 EXPECT_EQ(ERR_FAILED, rv); 516 EXPECT_TRUE(info.is_empty()); 517 } 518 519 // Test that if the execution of the PAC script fails (i.e. javascript runtime 520 // error), and the PAC settings are non-mandatory, that we fall-back to direct. 521 TEST_F(ProxyServiceTest, PAC_RuntimeError) { 522 MockProxyConfigService* config_service = 523 new MockProxyConfigService("http://foopy/proxy.pac"); 524 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; 525 526 ProxyService service(config_service, resolver, NULL); 527 528 GURL url("http://this-causes-js-error/"); 529 530 ProxyInfo info; 531 TestCompletionCallback callback1; 532 int rv = service.ResolveProxy( 533 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, 534 BoundNetLog()); 535 EXPECT_EQ(ERR_IO_PENDING, rv); 536 537 EXPECT_EQ(GURL("http://foopy/proxy.pac"), 538 resolver->pending_set_pac_script_request()->script_data()->url()); 539 resolver->pending_set_pac_script_request()->CompleteNow(OK); 540 541 ASSERT_EQ(1u, resolver->pending_requests().size()); 542 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); 543 544 // Simulate a failure in the PAC executor. 545 resolver->pending_requests()[0]->CompleteNow(ERR_PAC_SCRIPT_FAILED); 546 547 EXPECT_EQ(OK, callback1.WaitForResult()); 548 549 // Since the PAC script was non-mandatory, we should have fallen-back to 550 // DIRECT. 551 EXPECT_TRUE(info.is_direct()); 552 EXPECT_TRUE(info.did_use_pac_script()); 553 EXPECT_EQ(1, info.config_id()); 554 555 EXPECT_FALSE(info.proxy_resolve_start_time().is_null()); 556 EXPECT_FALSE(info.proxy_resolve_end_time().is_null()); 557 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time()); 558 } 559 560 // The proxy list could potentially contain the DIRECT fallback choice 561 // in a location other than the very end of the list, and could even 562 // specify it multiple times. 563 // 564 // This is not a typical usage, but we will obey it. 565 // (If we wanted to disallow this type of input, the right place to 566 // enforce it would be in parsing the PAC result string). 567 // 568 // This test will use the PAC result string: 569 // 570 // "DIRECT ; PROXY foobar:10 ; DIRECT ; PROXY foobar:20" 571 // 572 // For which we expect it to try DIRECT, then foobar:10, then DIRECT again, 573 // then foobar:20, and then give up and error. 574 // 575 // The important check of this test is to make sure that DIRECT is not somehow 576 // cached as being a bad proxy. 577 TEST_F(ProxyServiceTest, PAC_FailoverAfterDirect) { 578 MockProxyConfigService* config_service = 579 new MockProxyConfigService("http://foopy/proxy.pac"); 580 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; 581 582 ProxyService service(config_service, resolver, NULL); 583 584 GURL url("http://www.google.com/"); 585 586 ProxyInfo info; 587 TestCompletionCallback callback1; 588 int rv = service.ResolveProxy( 589 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, 590 BoundNetLog()); 591 EXPECT_EQ(ERR_IO_PENDING, rv); 592 593 EXPECT_EQ(GURL("http://foopy/proxy.pac"), 594 resolver->pending_set_pac_script_request()->script_data()->url()); 595 resolver->pending_set_pac_script_request()->CompleteNow(OK); 596 597 ASSERT_EQ(1u, resolver->pending_requests().size()); 598 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); 599 600 // Set the result in proxy resolver. 601 resolver->pending_requests()[0]->results()->UsePacString( 602 "DIRECT ; PROXY foobar:10 ; DIRECT ; PROXY foobar:20"); 603 resolver->pending_requests()[0]->CompleteNow(OK); 604 605 EXPECT_EQ(OK, callback1.WaitForResult()); 606 EXPECT_TRUE(info.is_direct()); 607 608 // Fallback 1. 609 TestCompletionCallback callback2; 610 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, 611 net::ERR_PROXY_CONNECTION_FAILED, 612 &info, callback2.callback(), NULL, 613 NULL, BoundNetLog()); 614 EXPECT_EQ(OK, rv); 615 EXPECT_FALSE(info.is_direct()); 616 EXPECT_EQ("foobar:10", info.proxy_server().ToURI()); 617 618 // Fallback 2. 619 NetworkDelegate network_delegate; 620 ProxyServer expected_proxy_server3 = info.proxy_server(); 621 TestCompletionCallback callback3; 622 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, 623 net::ERR_PROXY_CONNECTION_FAILED, 624 &info, callback3.callback(), NULL, 625 &network_delegate, BoundNetLog()); 626 EXPECT_EQ(OK, rv); 627 EXPECT_TRUE(info.is_direct()); 628 629 // Fallback 3. 630 ProxyServer expected_proxy_server4 = info.proxy_server(); 631 TestCompletionCallback callback4; 632 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, 633 net::ERR_PROXY_CONNECTION_FAILED, 634 &info, callback4.callback(), NULL, 635 &network_delegate, BoundNetLog()); 636 EXPECT_EQ(OK, rv); 637 EXPECT_FALSE(info.is_direct()); 638 EXPECT_EQ("foobar:20", info.proxy_server().ToURI()); 639 640 // Fallback 4 -- Nothing to fall back to! 641 ProxyServer expected_proxy_server5 = info.proxy_server(); 642 TestCompletionCallback callback5; 643 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, 644 net::ERR_PROXY_CONNECTION_FAILED, 645 &info, callback5.callback(), NULL, 646 &network_delegate, BoundNetLog()); 647 EXPECT_EQ(ERR_FAILED, rv); 648 EXPECT_TRUE(info.is_empty()); 649 } 650 651 TEST_F(ProxyServiceTest, PAC_ConfigSourcePropagates) { 652 // Test whether the ProxyConfigSource set by the ProxyConfigService is applied 653 // to ProxyInfo after the proxy is resolved via a PAC script. 654 ProxyConfig config = 655 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")); 656 config.set_source(PROXY_CONFIG_SOURCE_TEST); 657 658 MockProxyConfigService* config_service = new MockProxyConfigService(config); 659 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; 660 ProxyService service(config_service, resolver, NULL); 661 662 // Resolve something. 663 GURL url("http://www.google.com/"); 664 ProxyInfo info; 665 TestCompletionCallback callback; 666 int rv = service.ResolveProxy( 667 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL, 668 BoundNetLog()); 669 ASSERT_EQ(ERR_IO_PENDING, rv); 670 resolver->pending_set_pac_script_request()->CompleteNow(OK); 671 ASSERT_EQ(1u, resolver->pending_requests().size()); 672 673 // Set the result in proxy resolver. 674 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy"); 675 resolver->pending_requests()[0]->CompleteNow(OK); 676 677 EXPECT_EQ(OK, callback.WaitForResult()); 678 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source()); 679 EXPECT_TRUE(info.did_use_pac_script()); 680 681 EXPECT_FALSE(info.proxy_resolve_start_time().is_null()); 682 EXPECT_FALSE(info.proxy_resolve_end_time().is_null()); 683 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time()); 684 } 685 686 TEST_F(ProxyServiceTest, ProxyResolverFails) { 687 // Test what happens when the ProxyResolver fails. The download and setting 688 // of the PAC script have already succeeded, so this corresponds with a 689 // javascript runtime error while calling FindProxyForURL(). 690 691 MockProxyConfigService* config_service = 692 new MockProxyConfigService("http://foopy/proxy.pac"); 693 694 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; 695 696 ProxyService service(config_service, resolver, NULL); 697 698 // Start first resolve request. 699 GURL url("http://www.google.com/"); 700 ProxyInfo info; 701 TestCompletionCallback callback1; 702 int rv = service.ResolveProxy( 703 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, 704 BoundNetLog()); 705 EXPECT_EQ(ERR_IO_PENDING, rv); 706 707 EXPECT_EQ(GURL("http://foopy/proxy.pac"), 708 resolver->pending_set_pac_script_request()->script_data()->url()); 709 resolver->pending_set_pac_script_request()->CompleteNow(OK); 710 711 ASSERT_EQ(1u, resolver->pending_requests().size()); 712 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); 713 714 // Fail the first resolve request in MockAsyncProxyResolver. 715 resolver->pending_requests()[0]->CompleteNow(ERR_FAILED); 716 717 // Although the proxy resolver failed the request, ProxyService implicitly 718 // falls-back to DIRECT. 719 EXPECT_EQ(OK, callback1.WaitForResult()); 720 EXPECT_TRUE(info.is_direct()); 721 722 // Failed PAC executions still have proxy resolution times. 723 EXPECT_FALSE(info.proxy_resolve_start_time().is_null()); 724 EXPECT_FALSE(info.proxy_resolve_end_time().is_null()); 725 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time()); 726 727 // The second resolve request will try to run through the proxy resolver, 728 // regardless of whether the first request failed in it. 729 TestCompletionCallback callback2; 730 rv = service.ResolveProxy( 731 url, net::LOAD_NORMAL, &info, callback2.callback(), NULL, NULL, 732 BoundNetLog()); 733 EXPECT_EQ(ERR_IO_PENDING, rv); 734 735 ASSERT_EQ(1u, resolver->pending_requests().size()); 736 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); 737 738 // This time we will have the resolver succeed (perhaps the PAC script has 739 // a dependency on the current time). 740 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080"); 741 resolver->pending_requests()[0]->CompleteNow(OK); 742 743 EXPECT_EQ(OK, callback2.WaitForResult()); 744 EXPECT_FALSE(info.is_direct()); 745 EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI()); 746 } 747 748 TEST_F(ProxyServiceTest, ProxyScriptFetcherFailsDownloadingMandatoryPac) { 749 // Test what happens when the ProxyScriptResolver fails to download a 750 // mandatory PAC script. 751 752 ProxyConfig config( 753 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"))); 754 config.set_pac_mandatory(true); 755 756 MockProxyConfigService* config_service = new MockProxyConfigService(config); 757 758 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; 759 760 ProxyService service(config_service, resolver, NULL); 761 762 // Start first resolve request. 763 GURL url("http://www.google.com/"); 764 ProxyInfo info; 765 TestCompletionCallback callback1; 766 int rv = service.ResolveProxy( 767 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, 768 BoundNetLog()); 769 EXPECT_EQ(ERR_IO_PENDING, rv); 770 771 EXPECT_EQ(GURL("http://foopy/proxy.pac"), 772 resolver->pending_set_pac_script_request()->script_data()->url()); 773 resolver->pending_set_pac_script_request()->CompleteNow(ERR_FAILED); 774 775 ASSERT_EQ(0u, resolver->pending_requests().size()); 776 777 // As the proxy resolver failed the request and is configured for a mandatory 778 // PAC script, ProxyService must not implicitly fall-back to DIRECT. 779 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED, 780 callback1.WaitForResult()); 781 EXPECT_FALSE(info.is_direct()); 782 783 // As the proxy resolver failed the request and is configured for a mandatory 784 // PAC script, ProxyService must not implicitly fall-back to DIRECT. 785 TestCompletionCallback callback2; 786 rv = service.ResolveProxy( 787 url, net::LOAD_NORMAL, &info, callback2.callback(), NULL, NULL, 788 BoundNetLog()); 789 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED, rv); 790 EXPECT_FALSE(info.is_direct()); 791 } 792 793 TEST_F(ProxyServiceTest, ProxyResolverFailsParsingJavaScriptMandatoryPac) { 794 // Test what happens when the ProxyResolver fails that is configured to use a 795 // mandatory PAC script. The download of the PAC script has already 796 // succeeded but the PAC script contains no valid javascript. 797 798 ProxyConfig config( 799 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"))); 800 config.set_pac_mandatory(true); 801 802 MockProxyConfigService* config_service = new MockProxyConfigService(config); 803 804 MockAsyncProxyResolverExpectsBytes* resolver = 805 new MockAsyncProxyResolverExpectsBytes; 806 807 ProxyService service(config_service, resolver, NULL); 808 809 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; 810 DhcpProxyScriptFetcher* dhcp_fetcher = new DoNothingDhcpProxyScriptFetcher(); 811 service.SetProxyScriptFetchers(fetcher, dhcp_fetcher); 812 813 // Start resolve request. 814 GURL url("http://www.google.com/"); 815 ProxyInfo info; 816 TestCompletionCallback callback; 817 int rv = service.ResolveProxy( 818 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL, 819 BoundNetLog()); 820 EXPECT_EQ(ERR_IO_PENDING, rv); 821 822 // Check that nothing has been sent to the proxy resolver yet. 823 ASSERT_EQ(0u, resolver->pending_requests().size()); 824 825 // Downloading the PAC script succeeds. 826 EXPECT_TRUE(fetcher->has_pending_request()); 827 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); 828 fetcher->NotifyFetchCompletion(OK, "invalid-script-contents"); 829 830 EXPECT_FALSE(fetcher->has_pending_request()); 831 ASSERT_EQ(0u, resolver->pending_requests().size()); 832 833 // Since ProxyScriptDecider failed to identify a valid PAC and PAC was 834 // mandatory for this configuration, the ProxyService must not implicitly 835 // fall-back to DIRECT. 836 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED, 837 callback.WaitForResult()); 838 EXPECT_FALSE(info.is_direct()); 839 } 840 841 TEST_F(ProxyServiceTest, ProxyResolverFailsInJavaScriptMandatoryPac) { 842 // Test what happens when the ProxyResolver fails that is configured to use a 843 // mandatory PAC script. The download and setting of the PAC script have 844 // already succeeded, so this corresponds with a javascript runtime error 845 // while calling FindProxyForURL(). 846 847 ProxyConfig config( 848 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"))); 849 config.set_pac_mandatory(true); 850 851 MockProxyConfigService* config_service = new MockProxyConfigService(config); 852 853 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; 854 855 ProxyService service(config_service, resolver, NULL); 856 857 // Start first resolve request. 858 GURL url("http://www.google.com/"); 859 ProxyInfo info; 860 TestCompletionCallback callback1; 861 int rv = service.ResolveProxy( 862 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, 863 BoundNetLog()); 864 EXPECT_EQ(ERR_IO_PENDING, rv); 865 866 EXPECT_EQ(GURL("http://foopy/proxy.pac"), 867 resolver->pending_set_pac_script_request()->script_data()->url()); 868 resolver->pending_set_pac_script_request()->CompleteNow(OK); 869 870 ASSERT_EQ(1u, resolver->pending_requests().size()); 871 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); 872 873 // Fail the first resolve request in MockAsyncProxyResolver. 874 resolver->pending_requests()[0]->CompleteNow(ERR_FAILED); 875 876 // As the proxy resolver failed the request and is configured for a mandatory 877 // PAC script, ProxyService must not implicitly fall-back to DIRECT. 878 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED, 879 callback1.WaitForResult()); 880 EXPECT_FALSE(info.is_direct()); 881 882 // The second resolve request will try to run through the proxy resolver, 883 // regardless of whether the first request failed in it. 884 TestCompletionCallback callback2; 885 rv = service.ResolveProxy( 886 url, net::LOAD_NORMAL, &info, callback2.callback(), NULL, NULL, 887 BoundNetLog()); 888 EXPECT_EQ(ERR_IO_PENDING, rv); 889 890 ASSERT_EQ(1u, resolver->pending_requests().size()); 891 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); 892 893 // This time we will have the resolver succeed (perhaps the PAC script has 894 // a dependency on the current time). 895 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080"); 896 resolver->pending_requests()[0]->CompleteNow(OK); 897 898 EXPECT_EQ(OK, callback2.WaitForResult()); 899 EXPECT_FALSE(info.is_direct()); 900 EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI()); 901 } 902 903 TEST_F(ProxyServiceTest, ProxyFallback) { 904 // Test what happens when we specify multiple proxy servers and some of them 905 // are bad. 906 907 MockProxyConfigService* config_service = 908 new MockProxyConfigService("http://foopy/proxy.pac"); 909 910 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; 911 912 ProxyService service(config_service, resolver, NULL); 913 914 GURL url("http://www.google.com/"); 915 916 // Get the proxy information. 917 ProxyInfo info; 918 TestCompletionCallback callback1; 919 int rv = service.ResolveProxy( 920 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, 921 BoundNetLog()); 922 EXPECT_EQ(ERR_IO_PENDING, rv); 923 924 EXPECT_EQ(GURL("http://foopy/proxy.pac"), 925 resolver->pending_set_pac_script_request()->script_data()->url()); 926 resolver->pending_set_pac_script_request()->CompleteNow(OK); 927 928 ASSERT_EQ(1u, resolver->pending_requests().size()); 929 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); 930 931 // Set the result in proxy resolver. 932 resolver->pending_requests()[0]->results()->UseNamedProxy( 933 "foopy1:8080;foopy2:9090"); 934 resolver->pending_requests()[0]->CompleteNow(OK); 935 936 // The first item is valid. 937 EXPECT_EQ(OK, callback1.WaitForResult()); 938 EXPECT_FALSE(info.is_direct()); 939 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); 940 941 EXPECT_FALSE(info.proxy_resolve_start_time().is_null()); 942 EXPECT_FALSE(info.proxy_resolve_end_time().is_null()); 943 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time()); 944 base::TimeTicks proxy_resolve_start_time = info.proxy_resolve_start_time(); 945 base::TimeTicks proxy_resolve_end_time = info.proxy_resolve_end_time(); 946 947 // Fake an error on the proxy. 948 TestCompletionCallback callback2; 949 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, 950 net::ERR_PROXY_CONNECTION_FAILED, 951 &info, callback2.callback(), NULL, 952 NULL, BoundNetLog()); 953 EXPECT_EQ(OK, rv); 954 955 // Proxy times should not have been modified by fallback. 956 EXPECT_EQ(proxy_resolve_start_time, info.proxy_resolve_start_time()); 957 EXPECT_EQ(proxy_resolve_end_time, info.proxy_resolve_end_time()); 958 959 // The second proxy should be specified. 960 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); 961 // Report back that the second proxy worked. This will globally mark the 962 // first proxy as bad. 963 TestProxyFallbackNetworkDelegate test_delegate; 964 service.ReportSuccess(info, &test_delegate); 965 EXPECT_EQ("foopy1:8080", test_delegate.proxy_server().ToURI()); 966 EXPECT_EQ(net::ERR_PROXY_CONNECTION_FAILED, 967 test_delegate.proxy_fallback_net_error()); 968 969 TestCompletionCallback callback3; 970 rv = service.ResolveProxy( 971 url, net::LOAD_NORMAL, &info, callback3.callback(), NULL, NULL, 972 BoundNetLog()); 973 EXPECT_EQ(ERR_IO_PENDING, rv); 974 975 ASSERT_EQ(1u, resolver->pending_requests().size()); 976 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); 977 978 // Set the result in proxy resolver -- the second result is already known 979 // to be bad, so we will not try to use it initially. 980 resolver->pending_requests()[0]->results()->UseNamedProxy( 981 "foopy3:7070;foopy1:8080;foopy2:9090"); 982 resolver->pending_requests()[0]->CompleteNow(OK); 983 984 EXPECT_EQ(OK, callback3.WaitForResult()); 985 EXPECT_FALSE(info.is_direct()); 986 EXPECT_EQ("foopy3:7070", info.proxy_server().ToURI()); 987 988 // Proxy times should have been updated, so get them again. 989 EXPECT_LE(proxy_resolve_end_time, info.proxy_resolve_start_time()); 990 EXPECT_FALSE(info.proxy_resolve_start_time().is_null()); 991 EXPECT_FALSE(info.proxy_resolve_end_time().is_null()); 992 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time()); 993 proxy_resolve_start_time = info.proxy_resolve_start_time(); 994 proxy_resolve_end_time = info.proxy_resolve_end_time(); 995 996 // We fake another error. It should now try the third one. 997 TestCompletionCallback callback4; 998 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, 999 net::ERR_PROXY_CONNECTION_FAILED, 1000 &info, callback4.callback(), NULL, 1001 NULL, BoundNetLog()); 1002 EXPECT_EQ(OK, rv); 1003 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); 1004 1005 // We fake another error. At this point we have tried all of the 1006 // proxy servers we thought were valid; next we try the proxy server 1007 // that was in our bad proxies map (foopy1:8080). 1008 TestCompletionCallback callback5; 1009 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, 1010 net::ERR_PROXY_CONNECTION_FAILED, 1011 &info, callback5.callback(), NULL, 1012 NULL, BoundNetLog()); 1013 EXPECT_EQ(OK, rv); 1014 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); 1015 1016 // Fake another error, the last proxy is gone, the list should now be empty, 1017 // so there is nothing left to try. 1018 TestCompletionCallback callback6; 1019 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, 1020 net::ERR_PROXY_CONNECTION_FAILED, 1021 &info, callback6.callback(), NULL, 1022 NULL, BoundNetLog()); 1023 EXPECT_EQ(ERR_FAILED, rv); 1024 EXPECT_FALSE(info.is_direct()); 1025 EXPECT_TRUE(info.is_empty()); 1026 1027 // Proxy times should not have been modified by fallback. 1028 EXPECT_EQ(proxy_resolve_start_time, info.proxy_resolve_start_time()); 1029 EXPECT_EQ(proxy_resolve_end_time, info.proxy_resolve_end_time()); 1030 1031 // Look up proxies again 1032 TestCompletionCallback callback7; 1033 rv = service.ResolveProxy(url, net::LOAD_NORMAL, &info, callback7.callback(), 1034 NULL, NULL, BoundNetLog()); 1035 EXPECT_EQ(ERR_IO_PENDING, rv); 1036 1037 ASSERT_EQ(1u, resolver->pending_requests().size()); 1038 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); 1039 1040 // This time, the first 3 results have been found to be bad, but only the 1041 // first proxy has been confirmed ... 1042 resolver->pending_requests()[0]->results()->UseNamedProxy( 1043 "foopy1:8080;foopy3:7070;foopy2:9090;foopy4:9091"); 1044 resolver->pending_requests()[0]->CompleteNow(OK); 1045 1046 // ... therefore, we should see the second proxy first. 1047 EXPECT_EQ(OK, callback7.WaitForResult()); 1048 EXPECT_FALSE(info.is_direct()); 1049 EXPECT_EQ("foopy3:7070", info.proxy_server().ToURI()); 1050 1051 EXPECT_LE(proxy_resolve_end_time, info.proxy_resolve_start_time()); 1052 EXPECT_FALSE(info.proxy_resolve_start_time().is_null()); 1053 EXPECT_FALSE(info.proxy_resolve_end_time().is_null()); 1054 // TODO(nsylvain): Test that the proxy can be retried after the delay. 1055 } 1056 1057 // This test is similar to ProxyFallback, but this time we have an explicit 1058 // fallback choice to DIRECT. 1059 TEST_F(ProxyServiceTest, ProxyFallbackToDirect) { 1060 MockProxyConfigService* config_service = 1061 new MockProxyConfigService("http://foopy/proxy.pac"); 1062 1063 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; 1064 1065 ProxyService service(config_service, resolver, NULL); 1066 1067 GURL url("http://www.google.com/"); 1068 1069 // Get the proxy information. 1070 ProxyInfo info; 1071 TestCompletionCallback callback1; 1072 int rv = service.ResolveProxy( 1073 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, 1074 BoundNetLog()); 1075 EXPECT_EQ(ERR_IO_PENDING, rv); 1076 1077 EXPECT_EQ(GURL("http://foopy/proxy.pac"), 1078 resolver->pending_set_pac_script_request()->script_data()->url()); 1079 resolver->pending_set_pac_script_request()->CompleteNow(OK); 1080 1081 ASSERT_EQ(1u, resolver->pending_requests().size()); 1082 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); 1083 1084 // Set the result in proxy resolver. 1085 resolver->pending_requests()[0]->results()->UsePacString( 1086 "PROXY foopy1:8080; PROXY foopy2:9090; DIRECT"); 1087 resolver->pending_requests()[0]->CompleteNow(OK); 1088 1089 // Get the first result. 1090 EXPECT_EQ(OK, callback1.WaitForResult()); 1091 EXPECT_FALSE(info.is_direct()); 1092 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); 1093 1094 // Fake an error on the proxy. 1095 TestCompletionCallback callback2; 1096 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, 1097 net::ERR_PROXY_CONNECTION_FAILED, 1098 &info, callback2.callback(), NULL, 1099 NULL, BoundNetLog()); 1100 EXPECT_EQ(OK, rv); 1101 1102 // Now we get back the second proxy. 1103 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); 1104 1105 // Fake an error on this proxy as well. 1106 TestCompletionCallback callback3; 1107 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, 1108 net::ERR_PROXY_CONNECTION_FAILED, 1109 &info, callback3.callback(), NULL, 1110 NULL, BoundNetLog()); 1111 EXPECT_EQ(OK, rv); 1112 1113 // Finally, we get back DIRECT. 1114 EXPECT_TRUE(info.is_direct()); 1115 1116 EXPECT_FALSE(info.proxy_resolve_start_time().is_null()); 1117 EXPECT_FALSE(info.proxy_resolve_end_time().is_null()); 1118 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time()); 1119 1120 // Now we tell the proxy service that even DIRECT failed. 1121 TestCompletionCallback callback4; 1122 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, 1123 net::ERR_PROXY_CONNECTION_FAILED, 1124 &info, callback4.callback(), NULL, 1125 NULL, BoundNetLog()); 1126 // There was nothing left to try after DIRECT, so we are out of 1127 // choices. 1128 EXPECT_EQ(ERR_FAILED, rv); 1129 } 1130 1131 TEST_F(ProxyServiceTest, ProxyFallback_NewSettings) { 1132 // Test proxy failover when new settings are available. 1133 1134 MockProxyConfigService* config_service = 1135 new MockProxyConfigService("http://foopy/proxy.pac"); 1136 1137 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; 1138 1139 ProxyService service(config_service, resolver, NULL); 1140 1141 GURL url("http://www.google.com/"); 1142 1143 // Get the proxy information. 1144 ProxyInfo info; 1145 TestCompletionCallback callback1; 1146 int rv = service.ResolveProxy( 1147 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, 1148 BoundNetLog()); 1149 EXPECT_EQ(ERR_IO_PENDING, rv); 1150 1151 EXPECT_EQ(GURL("http://foopy/proxy.pac"), 1152 resolver->pending_set_pac_script_request()->script_data()->url()); 1153 resolver->pending_set_pac_script_request()->CompleteNow(OK); 1154 1155 ASSERT_EQ(1u, resolver->pending_requests().size()); 1156 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); 1157 1158 // Set the result in proxy resolver. 1159 resolver->pending_requests()[0]->results()->UseNamedProxy( 1160 "foopy1:8080;foopy2:9090"); 1161 resolver->pending_requests()[0]->CompleteNow(OK); 1162 1163 // The first item is valid. 1164 EXPECT_EQ(OK, callback1.WaitForResult()); 1165 EXPECT_FALSE(info.is_direct()); 1166 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); 1167 1168 // Fake an error on the proxy, and also a new configuration on the proxy. 1169 config_service->SetConfig( 1170 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy-new/proxy.pac"))); 1171 1172 TestCompletionCallback callback2; 1173 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, 1174 net::ERR_PROXY_CONNECTION_FAILED, 1175 &info, callback2.callback(), NULL, 1176 NULL, BoundNetLog()); 1177 EXPECT_EQ(ERR_IO_PENDING, rv); 1178 1179 EXPECT_EQ(GURL("http://foopy-new/proxy.pac"), 1180 resolver->pending_set_pac_script_request()->script_data()->url()); 1181 resolver->pending_set_pac_script_request()->CompleteNow(OK); 1182 1183 ASSERT_EQ(1u, resolver->pending_requests().size()); 1184 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); 1185 1186 resolver->pending_requests()[0]->results()->UseNamedProxy( 1187 "foopy1:8080;foopy2:9090"); 1188 resolver->pending_requests()[0]->CompleteNow(OK); 1189 1190 // The first proxy is still there since the configuration changed. 1191 EXPECT_EQ(OK, callback2.WaitForResult()); 1192 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); 1193 1194 // We fake another error. It should now ignore the first one. 1195 TestCompletionCallback callback3; 1196 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, 1197 net::ERR_PROXY_CONNECTION_FAILED, 1198 &info, callback3.callback(), NULL, 1199 NULL, BoundNetLog()); 1200 EXPECT_EQ(OK, rv); 1201 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); 1202 1203 // We simulate a new configuration. 1204 config_service->SetConfig( 1205 ProxyConfig::CreateFromCustomPacURL( 1206 GURL("http://foopy-new2/proxy.pac"))); 1207 1208 // We fake another error. It should go back to the first proxy. 1209 TestCompletionCallback callback4; 1210 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, 1211 net::ERR_PROXY_CONNECTION_FAILED, 1212 &info, callback4.callback(), NULL, 1213 NULL, BoundNetLog()); 1214 EXPECT_EQ(ERR_IO_PENDING, rv); 1215 1216 EXPECT_EQ(GURL("http://foopy-new2/proxy.pac"), 1217 resolver->pending_set_pac_script_request()->script_data()->url()); 1218 resolver->pending_set_pac_script_request()->CompleteNow(OK); 1219 1220 ASSERT_EQ(1u, resolver->pending_requests().size()); 1221 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); 1222 1223 resolver->pending_requests()[0]->results()->UseNamedProxy( 1224 "foopy1:8080;foopy2:9090"); 1225 resolver->pending_requests()[0]->CompleteNow(OK); 1226 1227 EXPECT_EQ(OK, callback4.WaitForResult()); 1228 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); 1229 1230 EXPECT_FALSE(info.proxy_resolve_start_time().is_null()); 1231 EXPECT_FALSE(info.proxy_resolve_end_time().is_null()); 1232 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time()); 1233 } 1234 1235 TEST_F(ProxyServiceTest, ProxyFallback_BadConfig) { 1236 // Test proxy failover when the configuration is bad. 1237 1238 MockProxyConfigService* config_service = 1239 new MockProxyConfigService("http://foopy/proxy.pac"); 1240 1241 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; 1242 1243 ProxyService service(config_service, resolver, NULL); 1244 1245 GURL url("http://www.google.com/"); 1246 1247 // Get the proxy information. 1248 ProxyInfo info; 1249 TestCompletionCallback callback1; 1250 int rv = service.ResolveProxy( 1251 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, 1252 BoundNetLog()); 1253 EXPECT_EQ(ERR_IO_PENDING, rv); 1254 1255 EXPECT_EQ(GURL("http://foopy/proxy.pac"), 1256 resolver->pending_set_pac_script_request()->script_data()->url()); 1257 resolver->pending_set_pac_script_request()->CompleteNow(OK); 1258 ASSERT_EQ(1u, resolver->pending_requests().size()); 1259 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); 1260 1261 resolver->pending_requests()[0]->results()->UseNamedProxy( 1262 "foopy1:8080;foopy2:9090"); 1263 resolver->pending_requests()[0]->CompleteNow(OK); 1264 1265 // The first item is valid. 1266 EXPECT_EQ(OK, callback1.WaitForResult()); 1267 EXPECT_FALSE(info.is_direct()); 1268 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); 1269 1270 // Fake a proxy error. 1271 TestCompletionCallback callback2; 1272 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, 1273 net::ERR_PROXY_CONNECTION_FAILED, 1274 &info, callback2.callback(), NULL, 1275 NULL, BoundNetLog()); 1276 EXPECT_EQ(OK, rv); 1277 1278 // The first proxy is ignored, and the second one is selected. 1279 EXPECT_FALSE(info.is_direct()); 1280 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); 1281 1282 // Fake a PAC failure. 1283 ProxyInfo info2; 1284 TestCompletionCallback callback3; 1285 rv = service.ResolveProxy( 1286 url, net::LOAD_NORMAL, &info2, callback3.callback(), NULL, NULL, 1287 BoundNetLog()); 1288 EXPECT_EQ(ERR_IO_PENDING, rv); 1289 1290 ASSERT_EQ(1u, resolver->pending_requests().size()); 1291 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); 1292 1293 // This simulates a javascript runtime error in the PAC script. 1294 resolver->pending_requests()[0]->CompleteNow(ERR_FAILED); 1295 1296 // Although the resolver failed, the ProxyService will implicitly fall-back 1297 // to a DIRECT connection. 1298 EXPECT_EQ(OK, callback3.WaitForResult()); 1299 EXPECT_TRUE(info2.is_direct()); 1300 EXPECT_FALSE(info2.is_empty()); 1301 1302 // The PAC script will work properly next time and successfully return a 1303 // proxy list. Since we have not marked the configuration as bad, it should 1304 // "just work" the next time we call it. 1305 ProxyInfo info3; 1306 TestCompletionCallback callback4; 1307 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, 1308 net::ERR_PROXY_CONNECTION_FAILED, 1309 &info3, callback4.callback(), 1310 NULL, NULL, BoundNetLog()); 1311 EXPECT_EQ(ERR_IO_PENDING, rv); 1312 1313 ASSERT_EQ(1u, resolver->pending_requests().size()); 1314 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); 1315 1316 resolver->pending_requests()[0]->results()->UseNamedProxy( 1317 "foopy1:8080;foopy2:9090"); 1318 resolver->pending_requests()[0]->CompleteNow(OK); 1319 1320 // The first proxy is not there since the it was added to the bad proxies 1321 // list by the earlier ReconsiderProxyAfterError(). 1322 EXPECT_EQ(OK, callback4.WaitForResult()); 1323 EXPECT_FALSE(info3.is_direct()); 1324 EXPECT_EQ("foopy1:8080", info3.proxy_server().ToURI()); 1325 1326 EXPECT_FALSE(info.proxy_resolve_start_time().is_null()); 1327 EXPECT_FALSE(info.proxy_resolve_end_time().is_null()); 1328 EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time()); 1329 } 1330 1331 TEST_F(ProxyServiceTest, ProxyFallback_BadConfigMandatory) { 1332 // Test proxy failover when the configuration is bad. 1333 1334 ProxyConfig config( 1335 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac"))); 1336 1337 config.set_pac_mandatory(true); 1338 MockProxyConfigService* config_service = new MockProxyConfigService(config); 1339 1340 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; 1341 1342 ProxyService service(config_service, resolver, NULL); 1343 1344 GURL url("http://www.google.com/"); 1345 1346 // Get the proxy information. 1347 ProxyInfo info; 1348 TestCompletionCallback callback1; 1349 int rv = service.ResolveProxy( 1350 url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, 1351 BoundNetLog()); 1352 EXPECT_EQ(ERR_IO_PENDING, rv); 1353 1354 EXPECT_EQ(GURL("http://foopy/proxy.pac"), 1355 resolver->pending_set_pac_script_request()->script_data()->url()); 1356 resolver->pending_set_pac_script_request()->CompleteNow(OK); 1357 ASSERT_EQ(1u, resolver->pending_requests().size()); 1358 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); 1359 1360 resolver->pending_requests()[0]->results()->UseNamedProxy( 1361 "foopy1:8080;foopy2:9090"); 1362 resolver->pending_requests()[0]->CompleteNow(OK); 1363 1364 // The first item is valid. 1365 EXPECT_EQ(OK, callback1.WaitForResult()); 1366 EXPECT_FALSE(info.is_direct()); 1367 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); 1368 1369 // Fake a proxy error. 1370 TestCompletionCallback callback2; 1371 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, 1372 net::ERR_PROXY_CONNECTION_FAILED, 1373 &info, callback2.callback(), NULL, 1374 NULL, BoundNetLog()); 1375 EXPECT_EQ(OK, rv); 1376 1377 // The first proxy is ignored, and the second one is selected. 1378 EXPECT_FALSE(info.is_direct()); 1379 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); 1380 1381 // Fake a PAC failure. 1382 ProxyInfo info2; 1383 TestCompletionCallback callback3; 1384 rv = service.ResolveProxy( 1385 url, net::LOAD_NORMAL, &info2, callback3.callback(), NULL, NULL, 1386 BoundNetLog()); 1387 EXPECT_EQ(ERR_IO_PENDING, rv); 1388 1389 ASSERT_EQ(1u, resolver->pending_requests().size()); 1390 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); 1391 1392 // This simulates a javascript runtime error in the PAC script. 1393 resolver->pending_requests()[0]->CompleteNow(ERR_FAILED); 1394 1395 // Although the resolver failed, the ProxyService will NOT fall-back 1396 // to a DIRECT connection as it is configured as mandatory. 1397 EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED, 1398 callback3.WaitForResult()); 1399 EXPECT_FALSE(info2.is_direct()); 1400 EXPECT_TRUE(info2.is_empty()); 1401 1402 // The PAC script will work properly next time and successfully return a 1403 // proxy list. Since we have not marked the configuration as bad, it should 1404 // "just work" the next time we call it. 1405 ProxyInfo info3; 1406 TestCompletionCallback callback4; 1407 rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, 1408 net::ERR_PROXY_CONNECTION_FAILED, 1409 &info3, callback4.callback(), 1410 NULL, NULL, BoundNetLog()); 1411 EXPECT_EQ(ERR_IO_PENDING, rv); 1412 1413 ASSERT_EQ(1u, resolver->pending_requests().size()); 1414 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); 1415 1416 resolver->pending_requests()[0]->results()->UseNamedProxy( 1417 "foopy1:8080;foopy2:9090"); 1418 resolver->pending_requests()[0]->CompleteNow(OK); 1419 1420 // The first proxy is not there since the it was added to the bad proxies 1421 // list by the earlier ReconsiderProxyAfterError(). 1422 EXPECT_EQ(OK, callback4.WaitForResult()); 1423 EXPECT_FALSE(info3.is_direct()); 1424 EXPECT_EQ("foopy1:8080", info3.proxy_server().ToURI()); 1425 } 1426 1427 TEST_F(ProxyServiceTest, ProxyBypassList) { 1428 // Test that the proxy bypass rules are consulted. 1429 1430 TestCompletionCallback callback[2]; 1431 ProxyInfo info[2]; 1432 ProxyConfig config; 1433 config.proxy_rules().ParseFromString("foopy1:8080;foopy2:9090"); 1434 config.set_auto_detect(false); 1435 config.proxy_rules().bypass_rules.ParseFromString("*.org"); 1436 1437 ProxyService service( 1438 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL); 1439 1440 int rv; 1441 GURL url1("http://www.webkit.org"); 1442 GURL url2("http://www.webkit.com"); 1443 1444 // Request for a .org domain should bypass proxy. 1445 rv = service.ResolveProxy( 1446 url1, net::LOAD_NORMAL, &info[0], callback[0].callback(), NULL, NULL, 1447 BoundNetLog()); 1448 EXPECT_EQ(OK, rv); 1449 EXPECT_TRUE(info[0].is_direct()); 1450 1451 // Request for a .com domain hits the proxy. 1452 rv = service.ResolveProxy( 1453 url2, net::LOAD_NORMAL, &info[1], callback[1].callback(), NULL, NULL, 1454 BoundNetLog()); 1455 EXPECT_EQ(OK, rv); 1456 EXPECT_EQ("foopy1:8080", info[1].proxy_server().ToURI()); 1457 } 1458 1459 1460 TEST_F(ProxyServiceTest, PerProtocolProxyTests) { 1461 ProxyConfig config; 1462 config.proxy_rules().ParseFromString("http=foopy1:8080;https=foopy2:8080"); 1463 config.set_auto_detect(false); 1464 { 1465 ProxyService service( 1466 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL); 1467 GURL test_url("http://www.msn.com"); 1468 ProxyInfo info; 1469 TestCompletionCallback callback; 1470 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, 1471 callback.callback(), NULL, NULL, 1472 BoundNetLog()); 1473 EXPECT_EQ(OK, rv); 1474 EXPECT_FALSE(info.is_direct()); 1475 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); 1476 } 1477 { 1478 ProxyService service( 1479 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL); 1480 GURL test_url("ftp://ftp.google.com"); 1481 ProxyInfo info; 1482 TestCompletionCallback callback; 1483 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, 1484 callback.callback(), NULL, 1485 NULL, BoundNetLog()); 1486 EXPECT_EQ(OK, rv); 1487 EXPECT_TRUE(info.is_direct()); 1488 EXPECT_EQ("direct://", info.proxy_server().ToURI()); 1489 } 1490 { 1491 ProxyService service( 1492 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL); 1493 GURL test_url("https://webbranch.techcu.com"); 1494 ProxyInfo info; 1495 TestCompletionCallback callback; 1496 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, 1497 callback.callback(), NULL, 1498 NULL, BoundNetLog()); 1499 EXPECT_EQ(OK, rv); 1500 EXPECT_FALSE(info.is_direct()); 1501 EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI()); 1502 } 1503 { 1504 config.proxy_rules().ParseFromString("foopy1:8080"); 1505 ProxyService service( 1506 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL); 1507 GURL test_url("http://www.microsoft.com"); 1508 ProxyInfo info; 1509 TestCompletionCallback callback; 1510 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, 1511 callback.callback(), NULL, 1512 NULL, BoundNetLog()); 1513 EXPECT_EQ(OK, rv); 1514 EXPECT_FALSE(info.is_direct()); 1515 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); 1516 } 1517 } 1518 1519 TEST_F(ProxyServiceTest, ProxyConfigSourcePropagates) { 1520 // Test that the proxy config source is set correctly when resolving proxies 1521 // using manual proxy rules. Namely, the config source should only be set if 1522 // any of the rules were applied. 1523 { 1524 ProxyConfig config; 1525 config.set_source(PROXY_CONFIG_SOURCE_TEST); 1526 config.proxy_rules().ParseFromString("https=foopy2:8080"); 1527 ProxyService service( 1528 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL); 1529 GURL test_url("http://www.google.com"); 1530 ProxyInfo info; 1531 TestCompletionCallback callback; 1532 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, 1533 callback.callback(), NULL, 1534 NULL, BoundNetLog()); 1535 ASSERT_EQ(OK, rv); 1536 // Should be SOURCE_TEST, even if there are no HTTP proxies configured. 1537 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source()); 1538 } 1539 { 1540 ProxyConfig config; 1541 config.set_source(PROXY_CONFIG_SOURCE_TEST); 1542 config.proxy_rules().ParseFromString("https=foopy2:8080"); 1543 ProxyService service( 1544 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL); 1545 GURL test_url("https://www.google.com"); 1546 ProxyInfo info; 1547 TestCompletionCallback callback; 1548 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, 1549 callback.callback(), NULL, 1550 NULL, BoundNetLog()); 1551 ASSERT_EQ(OK, rv); 1552 // Used the HTTPS proxy. So source should be TEST. 1553 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source()); 1554 } 1555 { 1556 ProxyConfig config; 1557 config.set_source(PROXY_CONFIG_SOURCE_TEST); 1558 ProxyService service( 1559 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL); 1560 GURL test_url("http://www.google.com"); 1561 ProxyInfo info; 1562 TestCompletionCallback callback; 1563 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, 1564 callback.callback(), NULL, 1565 NULL, BoundNetLog()); 1566 ASSERT_EQ(OK, rv); 1567 // ProxyConfig is empty. Source should still be TEST. 1568 EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source()); 1569 } 1570 } 1571 1572 // If only HTTP and a SOCKS proxy are specified, check if ftp/https queries 1573 // fall back to the SOCKS proxy. 1574 TEST_F(ProxyServiceTest, DefaultProxyFallbackToSOCKS) { 1575 ProxyConfig config; 1576 config.proxy_rules().ParseFromString("http=foopy1:8080;socks=foopy2:1080"); 1577 config.set_auto_detect(false); 1578 EXPECT_EQ(ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, 1579 config.proxy_rules().type); 1580 1581 { 1582 ProxyService service( 1583 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL); 1584 GURL test_url("http://www.msn.com"); 1585 ProxyInfo info; 1586 TestCompletionCallback callback; 1587 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, 1588 callback.callback(), NULL, 1589 NULL, BoundNetLog()); 1590 EXPECT_EQ(OK, rv); 1591 EXPECT_FALSE(info.is_direct()); 1592 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); 1593 } 1594 { 1595 ProxyService service( 1596 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL); 1597 GURL test_url("ftp://ftp.google.com"); 1598 ProxyInfo info; 1599 TestCompletionCallback callback; 1600 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, 1601 callback.callback(), NULL, 1602 NULL, BoundNetLog()); 1603 EXPECT_EQ(OK, rv); 1604 EXPECT_FALSE(info.is_direct()); 1605 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI()); 1606 } 1607 { 1608 ProxyService service( 1609 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL); 1610 GURL test_url("https://webbranch.techcu.com"); 1611 ProxyInfo info; 1612 TestCompletionCallback callback; 1613 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, 1614 callback.callback(), NULL, 1615 NULL, BoundNetLog()); 1616 EXPECT_EQ(OK, rv); 1617 EXPECT_FALSE(info.is_direct()); 1618 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI()); 1619 } 1620 { 1621 ProxyService service( 1622 new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL); 1623 GURL test_url("unknown://www.microsoft.com"); 1624 ProxyInfo info; 1625 TestCompletionCallback callback; 1626 int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, 1627 callback.callback(), NULL, 1628 NULL, BoundNetLog()); 1629 EXPECT_EQ(OK, rv); 1630 EXPECT_FALSE(info.is_direct()); 1631 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI()); 1632 } 1633 } 1634 1635 // Test cancellation of an in-progress request. 1636 TEST_F(ProxyServiceTest, CancelInProgressRequest) { 1637 MockProxyConfigService* config_service = 1638 new MockProxyConfigService("http://foopy/proxy.pac"); 1639 1640 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; 1641 1642 ProxyService service(config_service, resolver, NULL); 1643 1644 // Start 3 requests. 1645 1646 ProxyInfo info1; 1647 TestCompletionCallback callback1; 1648 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL, 1649 &info1, callback1.callback(), NULL, NULL, 1650 BoundNetLog()); 1651 EXPECT_EQ(ERR_IO_PENDING, rv); 1652 1653 // Nothing has been sent to the proxy resolver yet, since the proxy 1654 // resolver has not been configured yet. 1655 ASSERT_EQ(0u, resolver->pending_requests().size()); 1656 1657 // Successfully initialize the PAC script. 1658 EXPECT_EQ(GURL("http://foopy/proxy.pac"), 1659 resolver->pending_set_pac_script_request()->script_data()->url()); 1660 resolver->pending_set_pac_script_request()->CompleteNow(OK); 1661 1662 ASSERT_EQ(1u, resolver->pending_requests().size()); 1663 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); 1664 1665 ProxyInfo info2; 1666 TestCompletionCallback callback2; 1667 ProxyService::PacRequest* request2; 1668 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2, 1669 callback2.callback(), &request2, NULL, 1670 BoundNetLog()); 1671 EXPECT_EQ(ERR_IO_PENDING, rv); 1672 ASSERT_EQ(2u, resolver->pending_requests().size()); 1673 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url()); 1674 1675 ProxyInfo info3; 1676 TestCompletionCallback callback3; 1677 rv = service.ResolveProxy(GURL("http://request3"), net::LOAD_NORMAL, &info3, 1678 callback3.callback(), NULL, NULL, BoundNetLog()); 1679 EXPECT_EQ(ERR_IO_PENDING, rv); 1680 ASSERT_EQ(3u, resolver->pending_requests().size()); 1681 EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[2]->url()); 1682 1683 // Cancel the second request 1684 service.CancelPacRequest(request2); 1685 1686 ASSERT_EQ(2u, resolver->pending_requests().size()); 1687 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); 1688 EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[1]->url()); 1689 1690 // Complete the two un-cancelled requests. 1691 // We complete the last one first, just to mix it up a bit. 1692 resolver->pending_requests()[1]->results()->UseNamedProxy("request3:80"); 1693 resolver->pending_requests()[1]->CompleteNow(OK); 1694 1695 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); 1696 resolver->pending_requests()[0]->CompleteNow(OK); 1697 1698 // Complete and verify that requests ran as expected. 1699 EXPECT_EQ(OK, callback1.WaitForResult()); 1700 EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); 1701 1702 EXPECT_FALSE(callback2.have_result()); // Cancelled. 1703 ASSERT_EQ(1u, resolver->cancelled_requests().size()); 1704 EXPECT_EQ(GURL("http://request2"), resolver->cancelled_requests()[0]->url()); 1705 1706 EXPECT_EQ(OK, callback3.WaitForResult()); 1707 EXPECT_EQ("request3:80", info3.proxy_server().ToURI()); 1708 } 1709 1710 // Test the initial PAC download for resolver that expects bytes. 1711 TEST_F(ProxyServiceTest, InitialPACScriptDownload) { 1712 MockProxyConfigService* config_service = 1713 new MockProxyConfigService("http://foopy/proxy.pac"); 1714 1715 MockAsyncProxyResolverExpectsBytes* resolver = 1716 new MockAsyncProxyResolverExpectsBytes; 1717 1718 ProxyService service(config_service, resolver, NULL); 1719 1720 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; 1721 service.SetProxyScriptFetchers(fetcher, 1722 new DoNothingDhcpProxyScriptFetcher()); 1723 1724 // Start 3 requests. 1725 1726 ProxyInfo info1; 1727 TestCompletionCallback callback1; 1728 ProxyService::PacRequest* request1; 1729 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL, 1730 &info1, callback1.callback(), &request1, NULL, 1731 BoundNetLog()); 1732 EXPECT_EQ(ERR_IO_PENDING, rv); 1733 1734 // The first request should have triggered download of PAC script. 1735 EXPECT_TRUE(fetcher->has_pending_request()); 1736 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); 1737 1738 ProxyInfo info2; 1739 TestCompletionCallback callback2; 1740 ProxyService::PacRequest* request2; 1741 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2, 1742 callback2.callback(), &request2, NULL, 1743 BoundNetLog()); 1744 EXPECT_EQ(ERR_IO_PENDING, rv); 1745 1746 ProxyInfo info3; 1747 TestCompletionCallback callback3; 1748 ProxyService::PacRequest* request3; 1749 rv = service.ResolveProxy(GURL("http://request3"), net::LOAD_NORMAL, &info3, 1750 callback3.callback(), &request3, NULL, 1751 BoundNetLog()); 1752 EXPECT_EQ(ERR_IO_PENDING, rv); 1753 1754 // Nothing has been sent to the resolver yet. 1755 EXPECT_TRUE(resolver->pending_requests().empty()); 1756 1757 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT, 1758 service.GetLoadState(request1)); 1759 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT, 1760 service.GetLoadState(request2)); 1761 EXPECT_EQ(LOAD_STATE_DOWNLOADING_PROXY_SCRIPT, 1762 service.GetLoadState(request3)); 1763 1764 // At this point the ProxyService should be waiting for the 1765 // ProxyScriptFetcher to invoke its completion callback, notifying it of 1766 // PAC script download completion. 1767 fetcher->NotifyFetchCompletion(OK, kValidPacScript1); 1768 1769 // Now that the PAC script is downloaded, it will have been sent to the proxy 1770 // resolver. 1771 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1), 1772 resolver->pending_set_pac_script_request()->script_data()->utf16()); 1773 resolver->pending_set_pac_script_request()->CompleteNow(OK); 1774 1775 ASSERT_EQ(3u, resolver->pending_requests().size()); 1776 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); 1777 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url()); 1778 EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[2]->url()); 1779 1780 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request1)); 1781 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request2)); 1782 EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request3)); 1783 1784 // Complete all the requests (in some order). 1785 // Note that as we complete requests, they shift up in |pending_requests()|. 1786 1787 resolver->pending_requests()[2]->results()->UseNamedProxy("request3:80"); 1788 resolver->pending_requests()[2]->CompleteNow(OK); 1789 1790 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); 1791 resolver->pending_requests()[0]->CompleteNow(OK); 1792 1793 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80"); 1794 resolver->pending_requests()[0]->CompleteNow(OK); 1795 1796 // Complete and verify that requests ran as expected. 1797 EXPECT_EQ(OK, callback1.WaitForResult()); 1798 EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); 1799 EXPECT_FALSE(info1.proxy_resolve_start_time().is_null()); 1800 EXPECT_FALSE(info1.proxy_resolve_end_time().is_null()); 1801 EXPECT_LE(info1.proxy_resolve_start_time(), info1.proxy_resolve_end_time()); 1802 1803 EXPECT_EQ(OK, callback2.WaitForResult()); 1804 EXPECT_EQ("request2:80", info2.proxy_server().ToURI()); 1805 EXPECT_FALSE(info2.proxy_resolve_start_time().is_null()); 1806 EXPECT_FALSE(info2.proxy_resolve_end_time().is_null()); 1807 EXPECT_LE(info2.proxy_resolve_start_time(), info2.proxy_resolve_end_time()); 1808 1809 EXPECT_EQ(OK, callback3.WaitForResult()); 1810 EXPECT_EQ("request3:80", info3.proxy_server().ToURI()); 1811 EXPECT_FALSE(info3.proxy_resolve_start_time().is_null()); 1812 EXPECT_FALSE(info3.proxy_resolve_end_time().is_null()); 1813 EXPECT_LE(info3.proxy_resolve_start_time(), info3.proxy_resolve_end_time()); 1814 } 1815 1816 // Test changing the ProxyScriptFetcher while PAC download is in progress. 1817 TEST_F(ProxyServiceTest, ChangeScriptFetcherWhilePACDownloadInProgress) { 1818 MockProxyConfigService* config_service = 1819 new MockProxyConfigService("http://foopy/proxy.pac"); 1820 1821 MockAsyncProxyResolverExpectsBytes* resolver = 1822 new MockAsyncProxyResolverExpectsBytes; 1823 1824 ProxyService service(config_service, resolver, NULL); 1825 1826 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; 1827 service.SetProxyScriptFetchers(fetcher, 1828 new DoNothingDhcpProxyScriptFetcher()); 1829 1830 // Start 2 requests. 1831 1832 ProxyInfo info1; 1833 TestCompletionCallback callback1; 1834 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL, 1835 &info1, callback1.callback(), NULL, NULL, 1836 BoundNetLog()); 1837 EXPECT_EQ(ERR_IO_PENDING, rv); 1838 1839 // The first request should have triggered download of PAC script. 1840 EXPECT_TRUE(fetcher->has_pending_request()); 1841 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); 1842 1843 ProxyInfo info2; 1844 TestCompletionCallback callback2; 1845 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2, 1846 callback2.callback(), NULL, NULL, BoundNetLog()); 1847 EXPECT_EQ(ERR_IO_PENDING, rv); 1848 1849 // At this point the ProxyService should be waiting for the 1850 // ProxyScriptFetcher to invoke its completion callback, notifying it of 1851 // PAC script download completion. 1852 1853 // We now change out the ProxyService's script fetcher. We should restart 1854 // the initialization with the new fetcher. 1855 1856 fetcher = new MockProxyScriptFetcher; 1857 service.SetProxyScriptFetchers(fetcher, 1858 new DoNothingDhcpProxyScriptFetcher()); 1859 1860 // Nothing has been sent to the resolver yet. 1861 EXPECT_TRUE(resolver->pending_requests().empty()); 1862 1863 fetcher->NotifyFetchCompletion(OK, kValidPacScript1); 1864 1865 // Now that the PAC script is downloaded, it will have been sent to the proxy 1866 // resolver. 1867 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1), 1868 resolver->pending_set_pac_script_request()->script_data()->utf16()); 1869 resolver->pending_set_pac_script_request()->CompleteNow(OK); 1870 1871 ASSERT_EQ(2u, resolver->pending_requests().size()); 1872 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); 1873 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url()); 1874 } 1875 1876 // Test cancellation of a request, while the PAC script is being fetched. 1877 TEST_F(ProxyServiceTest, CancelWhilePACFetching) { 1878 MockProxyConfigService* config_service = 1879 new MockProxyConfigService("http://foopy/proxy.pac"); 1880 1881 MockAsyncProxyResolverExpectsBytes* resolver = 1882 new MockAsyncProxyResolverExpectsBytes; 1883 1884 ProxyService service(config_service, resolver, NULL); 1885 1886 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; 1887 service.SetProxyScriptFetchers(fetcher, 1888 new DoNothingDhcpProxyScriptFetcher()); 1889 1890 // Start 3 requests. 1891 ProxyInfo info1; 1892 TestCompletionCallback callback1; 1893 ProxyService::PacRequest* request1; 1894 CapturingBoundNetLog log1; 1895 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL, 1896 &info1, callback1.callback(), &request1, NULL, 1897 log1.bound()); 1898 EXPECT_EQ(ERR_IO_PENDING, rv); 1899 1900 // The first request should have triggered download of PAC script. 1901 EXPECT_TRUE(fetcher->has_pending_request()); 1902 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); 1903 1904 ProxyInfo info2; 1905 TestCompletionCallback callback2; 1906 ProxyService::PacRequest* request2; 1907 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2, 1908 callback2.callback(), &request2, NULL, 1909 BoundNetLog()); 1910 EXPECT_EQ(ERR_IO_PENDING, rv); 1911 1912 ProxyInfo info3; 1913 TestCompletionCallback callback3; 1914 rv = service.ResolveProxy(GURL("http://request3"), net::LOAD_NORMAL, &info3, 1915 callback3.callback(), NULL, NULL, BoundNetLog()); 1916 EXPECT_EQ(ERR_IO_PENDING, rv); 1917 1918 // Nothing has been sent to the resolver yet. 1919 EXPECT_TRUE(resolver->pending_requests().empty()); 1920 1921 // Cancel the first 2 requests. 1922 service.CancelPacRequest(request1); 1923 service.CancelPacRequest(request2); 1924 1925 // At this point the ProxyService should be waiting for the 1926 // ProxyScriptFetcher to invoke its completion callback, notifying it of 1927 // PAC script download completion. 1928 fetcher->NotifyFetchCompletion(OK, kValidPacScript1); 1929 1930 // Now that the PAC script is downloaded, it will have been sent to the 1931 // proxy resolver. 1932 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1), 1933 resolver->pending_set_pac_script_request()->script_data()->utf16()); 1934 resolver->pending_set_pac_script_request()->CompleteNow(OK); 1935 1936 ASSERT_EQ(1u, resolver->pending_requests().size()); 1937 EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[0]->url()); 1938 1939 // Complete all the requests. 1940 resolver->pending_requests()[0]->results()->UseNamedProxy("request3:80"); 1941 resolver->pending_requests()[0]->CompleteNow(OK); 1942 1943 EXPECT_EQ(OK, callback3.WaitForResult()); 1944 EXPECT_EQ("request3:80", info3.proxy_server().ToURI()); 1945 1946 EXPECT_TRUE(resolver->cancelled_requests().empty()); 1947 1948 EXPECT_FALSE(callback1.have_result()); // Cancelled. 1949 EXPECT_FALSE(callback2.have_result()); // Cancelled. 1950 1951 CapturingNetLog::CapturedEntryList entries1; 1952 log1.GetEntries(&entries1); 1953 1954 // Check the NetLog for request 1 (which was cancelled) got filled properly. 1955 EXPECT_EQ(4u, entries1.size()); 1956 EXPECT_TRUE(LogContainsBeginEvent( 1957 entries1, 0, NetLog::TYPE_PROXY_SERVICE)); 1958 EXPECT_TRUE(LogContainsBeginEvent( 1959 entries1, 1, NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC)); 1960 // Note that TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC is never completed before 1961 // the cancellation occured. 1962 EXPECT_TRUE(LogContainsEvent( 1963 entries1, 2, NetLog::TYPE_CANCELLED, NetLog::PHASE_NONE)); 1964 EXPECT_TRUE(LogContainsEndEvent( 1965 entries1, 3, NetLog::TYPE_PROXY_SERVICE)); 1966 } 1967 1968 // Test that if auto-detect fails, we fall-back to the custom pac. 1969 TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomPac) { 1970 ProxyConfig config; 1971 config.set_auto_detect(true); 1972 config.set_pac_url(GURL("http://foopy/proxy.pac")); 1973 config.proxy_rules().ParseFromString("http=foopy:80"); // Won't be used. 1974 1975 MockProxyConfigService* config_service = new MockProxyConfigService(config); 1976 MockAsyncProxyResolverExpectsBytes* resolver = 1977 new MockAsyncProxyResolverExpectsBytes; 1978 ProxyService service(config_service, resolver, NULL); 1979 1980 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; 1981 service.SetProxyScriptFetchers(fetcher, 1982 new DoNothingDhcpProxyScriptFetcher()); 1983 1984 // Start 2 requests. 1985 1986 ProxyInfo info1; 1987 TestCompletionCallback callback1; 1988 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL, 1989 &info1, callback1.callback(), NULL, NULL, 1990 BoundNetLog()); 1991 EXPECT_EQ(ERR_IO_PENDING, rv); 1992 1993 ProxyInfo info2; 1994 TestCompletionCallback callback2; 1995 ProxyService::PacRequest* request2; 1996 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2, 1997 callback2.callback(), &request2, NULL, 1998 BoundNetLog()); 1999 EXPECT_EQ(ERR_IO_PENDING, rv); 2000 2001 // Check that nothing has been sent to the proxy resolver yet. 2002 ASSERT_EQ(0u, resolver->pending_requests().size()); 2003 2004 // It should be trying to auto-detect first -- FAIL the autodetect during 2005 // the script download. 2006 EXPECT_TRUE(fetcher->has_pending_request()); 2007 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url()); 2008 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string()); 2009 2010 // Next it should be trying the custom PAC url. 2011 EXPECT_TRUE(fetcher->has_pending_request()); 2012 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); 2013 fetcher->NotifyFetchCompletion(OK, kValidPacScript1); 2014 2015 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1), 2016 resolver->pending_set_pac_script_request()->script_data()->utf16()); 2017 resolver->pending_set_pac_script_request()->CompleteNow(OK); 2018 2019 // Now finally, the pending requests should have been sent to the resolver 2020 // (which was initialized with custom PAC script). 2021 2022 ASSERT_EQ(2u, resolver->pending_requests().size()); 2023 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); 2024 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url()); 2025 2026 // Complete the pending requests. 2027 resolver->pending_requests()[1]->results()->UseNamedProxy("request2:80"); 2028 resolver->pending_requests()[1]->CompleteNow(OK); 2029 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); 2030 resolver->pending_requests()[0]->CompleteNow(OK); 2031 2032 // Verify that requests ran as expected. 2033 EXPECT_EQ(OK, callback1.WaitForResult()); 2034 EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); 2035 EXPECT_FALSE(info1.proxy_resolve_start_time().is_null()); 2036 EXPECT_FALSE(info1.proxy_resolve_end_time().is_null()); 2037 EXPECT_LE(info1.proxy_resolve_start_time(), info1.proxy_resolve_end_time()); 2038 2039 EXPECT_EQ(OK, callback2.WaitForResult()); 2040 EXPECT_EQ("request2:80", info2.proxy_server().ToURI()); 2041 EXPECT_FALSE(info2.proxy_resolve_start_time().is_null()); 2042 EXPECT_FALSE(info2.proxy_resolve_end_time().is_null()); 2043 EXPECT_LE(info2.proxy_resolve_start_time(), info2.proxy_resolve_end_time()); 2044 } 2045 2046 // This is the same test as FallbackFromAutodetectToCustomPac, except 2047 // the auto-detect script fails parsing rather than downloading. 2048 TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomPac2) { 2049 ProxyConfig config; 2050 config.set_auto_detect(true); 2051 config.set_pac_url(GURL("http://foopy/proxy.pac")); 2052 config.proxy_rules().ParseFromString("http=foopy:80"); // Won't be used. 2053 2054 MockProxyConfigService* config_service = new MockProxyConfigService(config); 2055 MockAsyncProxyResolverExpectsBytes* resolver = 2056 new MockAsyncProxyResolverExpectsBytes; 2057 ProxyService service(config_service, resolver, NULL); 2058 2059 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; 2060 service.SetProxyScriptFetchers(fetcher, 2061 new DoNothingDhcpProxyScriptFetcher()); 2062 2063 // Start 2 requests. 2064 2065 ProxyInfo info1; 2066 TestCompletionCallback callback1; 2067 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL, 2068 &info1, callback1.callback(), NULL, NULL, 2069 BoundNetLog()); 2070 EXPECT_EQ(ERR_IO_PENDING, rv); 2071 2072 ProxyInfo info2; 2073 TestCompletionCallback callback2; 2074 ProxyService::PacRequest* request2; 2075 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2, 2076 callback2.callback(), &request2, NULL, 2077 BoundNetLog()); 2078 EXPECT_EQ(ERR_IO_PENDING, rv); 2079 2080 // Check that nothing has been sent to the proxy resolver yet. 2081 ASSERT_EQ(0u, resolver->pending_requests().size()); 2082 2083 // It should be trying to auto-detect first -- succeed the download. 2084 EXPECT_TRUE(fetcher->has_pending_request()); 2085 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url()); 2086 fetcher->NotifyFetchCompletion(OK, "invalid-script-contents"); 2087 2088 // The script contents passed failed basic verification step (since didn't 2089 // contain token FindProxyForURL), so it was never passed to the resolver. 2090 2091 // Next it should be trying the custom PAC url. 2092 EXPECT_TRUE(fetcher->has_pending_request()); 2093 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); 2094 fetcher->NotifyFetchCompletion(OK, kValidPacScript1); 2095 2096 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1), 2097 resolver->pending_set_pac_script_request()->script_data()->utf16()); 2098 resolver->pending_set_pac_script_request()->CompleteNow(OK); 2099 2100 // Now finally, the pending requests should have been sent to the resolver 2101 // (which was initialized with custom PAC script). 2102 2103 ASSERT_EQ(2u, resolver->pending_requests().size()); 2104 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); 2105 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url()); 2106 2107 // Complete the pending requests. 2108 resolver->pending_requests()[1]->results()->UseNamedProxy("request2:80"); 2109 resolver->pending_requests()[1]->CompleteNow(OK); 2110 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); 2111 resolver->pending_requests()[0]->CompleteNow(OK); 2112 2113 // Verify that requests ran as expected. 2114 EXPECT_EQ(OK, callback1.WaitForResult()); 2115 EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); 2116 2117 EXPECT_EQ(OK, callback2.WaitForResult()); 2118 EXPECT_EQ("request2:80", info2.proxy_server().ToURI()); 2119 } 2120 2121 // Test that if all of auto-detect, a custom PAC script, and manual settings 2122 // are given, then we will try them in that order. 2123 TEST_F(ProxyServiceTest, FallbackFromAutodetectToCustomToManual) { 2124 ProxyConfig config; 2125 config.set_auto_detect(true); 2126 config.set_pac_url(GURL("http://foopy/proxy.pac")); 2127 config.proxy_rules().ParseFromString("http=foopy:80"); 2128 2129 MockProxyConfigService* config_service = new MockProxyConfigService(config); 2130 MockAsyncProxyResolverExpectsBytes* resolver = 2131 new MockAsyncProxyResolverExpectsBytes; 2132 ProxyService service(config_service, resolver, NULL); 2133 2134 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; 2135 service.SetProxyScriptFetchers(fetcher, 2136 new DoNothingDhcpProxyScriptFetcher()); 2137 2138 // Start 2 requests. 2139 2140 ProxyInfo info1; 2141 TestCompletionCallback callback1; 2142 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL, 2143 &info1, callback1.callback(), NULL, NULL, 2144 BoundNetLog()); 2145 EXPECT_EQ(ERR_IO_PENDING, rv); 2146 2147 ProxyInfo info2; 2148 TestCompletionCallback callback2; 2149 ProxyService::PacRequest* request2; 2150 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2, 2151 callback2.callback(), &request2, NULL, 2152 BoundNetLog()); 2153 EXPECT_EQ(ERR_IO_PENDING, rv); 2154 2155 // Check that nothing has been sent to the proxy resolver yet. 2156 ASSERT_EQ(0u, resolver->pending_requests().size()); 2157 2158 // It should be trying to auto-detect first -- fail the download. 2159 EXPECT_TRUE(fetcher->has_pending_request()); 2160 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url()); 2161 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string()); 2162 2163 // Next it should be trying the custom PAC url -- fail the download. 2164 EXPECT_TRUE(fetcher->has_pending_request()); 2165 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); 2166 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string()); 2167 2168 // Since we never managed to initialize a ProxyResolver, nothing should have 2169 // been sent to it. 2170 ASSERT_EQ(0u, resolver->pending_requests().size()); 2171 2172 // Verify that requests ran as expected -- they should have fallen back to 2173 // the manual proxy configuration for HTTP urls. 2174 EXPECT_EQ(OK, callback1.WaitForResult()); 2175 EXPECT_EQ("foopy:80", info1.proxy_server().ToURI()); 2176 2177 EXPECT_EQ(OK, callback2.WaitForResult()); 2178 EXPECT_EQ("foopy:80", info2.proxy_server().ToURI()); 2179 } 2180 2181 // Test that the bypass rules are NOT applied when using autodetect. 2182 TEST_F(ProxyServiceTest, BypassDoesntApplyToPac) { 2183 ProxyConfig config; 2184 config.set_auto_detect(true); 2185 config.set_pac_url(GURL("http://foopy/proxy.pac")); 2186 config.proxy_rules().ParseFromString("http=foopy:80"); // Not used. 2187 config.proxy_rules().bypass_rules.ParseFromString("www.google.com"); 2188 2189 MockProxyConfigService* config_service = new MockProxyConfigService(config); 2190 MockAsyncProxyResolverExpectsBytes* resolver = 2191 new MockAsyncProxyResolverExpectsBytes; 2192 ProxyService service(config_service, resolver, NULL); 2193 2194 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; 2195 service.SetProxyScriptFetchers(fetcher, 2196 new DoNothingDhcpProxyScriptFetcher()); 2197 2198 // Start 1 requests. 2199 2200 ProxyInfo info1; 2201 TestCompletionCallback callback1; 2202 int rv = service.ResolveProxy( 2203 GURL("http://www.google.com"), net::LOAD_NORMAL, &info1, 2204 callback1.callback(), NULL, NULL, BoundNetLog()); 2205 EXPECT_EQ(ERR_IO_PENDING, rv); 2206 2207 // Check that nothing has been sent to the proxy resolver yet. 2208 ASSERT_EQ(0u, resolver->pending_requests().size()); 2209 2210 // It should be trying to auto-detect first -- succeed the download. 2211 EXPECT_TRUE(fetcher->has_pending_request()); 2212 EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url()); 2213 fetcher->NotifyFetchCompletion(OK, kValidPacScript1); 2214 2215 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1), 2216 resolver->pending_set_pac_script_request()->script_data()->utf16()); 2217 resolver->pending_set_pac_script_request()->CompleteNow(OK); 2218 2219 ASSERT_EQ(1u, resolver->pending_requests().size()); 2220 EXPECT_EQ(GURL("http://www.google.com"), 2221 resolver->pending_requests()[0]->url()); 2222 2223 // Complete the pending request. 2224 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); 2225 resolver->pending_requests()[0]->CompleteNow(OK); 2226 2227 // Verify that request ran as expected. 2228 EXPECT_EQ(OK, callback1.WaitForResult()); 2229 EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); 2230 2231 // Start another request, it should pickup the bypass item. 2232 ProxyInfo info2; 2233 TestCompletionCallback callback2; 2234 rv = service.ResolveProxy(GURL("http://www.google.com"), net::LOAD_NORMAL, 2235 &info2, callback2.callback(), NULL, NULL, 2236 BoundNetLog()); 2237 EXPECT_EQ(ERR_IO_PENDING, rv); 2238 2239 ASSERT_EQ(1u, resolver->pending_requests().size()); 2240 EXPECT_EQ(GURL("http://www.google.com"), 2241 resolver->pending_requests()[0]->url()); 2242 2243 // Complete the pending request. 2244 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80"); 2245 resolver->pending_requests()[0]->CompleteNow(OK); 2246 2247 EXPECT_EQ(OK, callback2.WaitForResult()); 2248 EXPECT_EQ("request2:80", info2.proxy_server().ToURI()); 2249 } 2250 2251 // Delete the ProxyService while InitProxyResolver has an outstanding 2252 // request to the script fetcher. When run under valgrind, should not 2253 // have any memory errors (used to be that the ProxyScriptFetcher was 2254 // being deleted prior to the InitProxyResolver). 2255 TEST_F(ProxyServiceTest, DeleteWhileInitProxyResolverHasOutstandingFetch) { 2256 ProxyConfig config = 2257 ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy/proxy.pac")); 2258 2259 MockProxyConfigService* config_service = new MockProxyConfigService(config); 2260 MockAsyncProxyResolverExpectsBytes* resolver = 2261 new MockAsyncProxyResolverExpectsBytes; 2262 ProxyService service(config_service, resolver, NULL); 2263 2264 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; 2265 service.SetProxyScriptFetchers(fetcher, 2266 new DoNothingDhcpProxyScriptFetcher()); 2267 2268 // Start 1 request. 2269 2270 ProxyInfo info1; 2271 TestCompletionCallback callback1; 2272 int rv = service.ResolveProxy(GURL("http://www.google.com"), net::LOAD_NORMAL, 2273 &info1, callback1.callback(), NULL, NULL, 2274 BoundNetLog()); 2275 EXPECT_EQ(ERR_IO_PENDING, rv); 2276 2277 // Check that nothing has been sent to the proxy resolver yet. 2278 ASSERT_EQ(0u, resolver->pending_requests().size()); 2279 2280 // InitProxyResolver should have issued a request to the ProxyScriptFetcher 2281 // and be waiting on that to complete. 2282 EXPECT_TRUE(fetcher->has_pending_request()); 2283 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); 2284 } 2285 2286 // Delete the ProxyService while InitProxyResolver has an outstanding 2287 // request to the proxy resolver. When run under valgrind, should not 2288 // have any memory errors (used to be that the ProxyResolver was 2289 // being deleted prior to the InitProxyResolver). 2290 TEST_F(ProxyServiceTest, DeleteWhileInitProxyResolverHasOutstandingSet) { 2291 MockProxyConfigService* config_service = 2292 new MockProxyConfigService("http://foopy/proxy.pac"); 2293 2294 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; 2295 2296 ProxyService service(config_service, resolver, NULL); 2297 2298 GURL url("http://www.google.com/"); 2299 2300 ProxyInfo info; 2301 TestCompletionCallback callback; 2302 int rv = service.ResolveProxy( 2303 url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL, 2304 BoundNetLog()); 2305 EXPECT_EQ(ERR_IO_PENDING, rv); 2306 2307 EXPECT_EQ(GURL("http://foopy/proxy.pac"), 2308 resolver->pending_set_pac_script_request()->script_data()->url()); 2309 } 2310 2311 TEST_F(ProxyServiceTest, ResetProxyConfigService) { 2312 ProxyConfig config1; 2313 config1.proxy_rules().ParseFromString("foopy1:8080"); 2314 config1.set_auto_detect(false); 2315 ProxyService service( 2316 new MockProxyConfigService(config1), 2317 new MockAsyncProxyResolverExpectsBytes, NULL); 2318 2319 ProxyInfo info; 2320 TestCompletionCallback callback1; 2321 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL, 2322 &info, callback1.callback(), NULL, NULL, 2323 BoundNetLog()); 2324 EXPECT_EQ(OK, rv); 2325 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); 2326 2327 ProxyConfig config2; 2328 config2.proxy_rules().ParseFromString("foopy2:8080"); 2329 config2.set_auto_detect(false); 2330 service.ResetConfigService(new MockProxyConfigService(config2)); 2331 TestCompletionCallback callback2; 2332 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info, 2333 callback2.callback(), NULL, NULL, BoundNetLog()); 2334 EXPECT_EQ(OK, rv); 2335 EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI()); 2336 } 2337 2338 // Test that when going from a configuration that required PAC to one 2339 // that does NOT, we unset the variable |should_use_proxy_resolver_|. 2340 TEST_F(ProxyServiceTest, UpdateConfigFromPACToDirect) { 2341 ProxyConfig config = ProxyConfig::CreateAutoDetect(); 2342 2343 MockProxyConfigService* config_service = new MockProxyConfigService(config); 2344 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; 2345 ProxyService service(config_service, resolver, NULL); 2346 2347 // Start 1 request. 2348 2349 ProxyInfo info1; 2350 TestCompletionCallback callback1; 2351 int rv = service.ResolveProxy(GURL("http://www.google.com"), net::LOAD_NORMAL, 2352 &info1, callback1.callback(), NULL, NULL, 2353 BoundNetLog()); 2354 EXPECT_EQ(ERR_IO_PENDING, rv); 2355 2356 // Check that nothing has been sent to the proxy resolver yet. 2357 ASSERT_EQ(0u, resolver->pending_requests().size()); 2358 2359 // Successfully set the autodetect script. 2360 EXPECT_EQ(ProxyResolverScriptData::TYPE_AUTO_DETECT, 2361 resolver->pending_set_pac_script_request()->script_data()->type()); 2362 resolver->pending_set_pac_script_request()->CompleteNow(OK); 2363 2364 // Complete the pending request. 2365 ASSERT_EQ(1u, resolver->pending_requests().size()); 2366 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); 2367 resolver->pending_requests()[0]->CompleteNow(OK); 2368 2369 // Verify that request ran as expected. 2370 EXPECT_EQ(OK, callback1.WaitForResult()); 2371 EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); 2372 2373 // Force the ProxyService to pull down a new proxy configuration. 2374 // (Even though the configuration isn't old/bad). 2375 // 2376 // This new configuration no longer has auto_detect set, so 2377 // requests should complete synchronously now as direct-connect. 2378 config_service->SetConfig(ProxyConfig::CreateDirect()); 2379 2380 // Start another request -- the effective configuration has changed. 2381 ProxyInfo info2; 2382 TestCompletionCallback callback2; 2383 rv = service.ResolveProxy(GURL("http://www.google.com"), net::LOAD_NORMAL, 2384 &info2, callback2.callback(), NULL, NULL, 2385 BoundNetLog()); 2386 EXPECT_EQ(OK, rv); 2387 2388 EXPECT_TRUE(info2.is_direct()); 2389 } 2390 2391 TEST_F(ProxyServiceTest, NetworkChangeTriggersPacRefetch) { 2392 MockProxyConfigService* config_service = 2393 new MockProxyConfigService("http://foopy/proxy.pac"); 2394 2395 MockAsyncProxyResolverExpectsBytes* resolver = 2396 new MockAsyncProxyResolverExpectsBytes; 2397 2398 CapturingNetLog log; 2399 2400 ProxyService service(config_service, resolver, &log); 2401 2402 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; 2403 service.SetProxyScriptFetchers(fetcher, 2404 new DoNothingDhcpProxyScriptFetcher()); 2405 2406 // Disable the "wait after IP address changes" hack, so this unit-test can 2407 // complete quickly. 2408 service.set_stall_proxy_auto_config_delay(base::TimeDelta()); 2409 2410 // Start 1 request. 2411 2412 ProxyInfo info1; 2413 TestCompletionCallback callback1; 2414 int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL, 2415 &info1, callback1.callback(), NULL, NULL, 2416 BoundNetLog()); 2417 EXPECT_EQ(ERR_IO_PENDING, rv); 2418 2419 // The first request should have triggered initial download of PAC script. 2420 EXPECT_TRUE(fetcher->has_pending_request()); 2421 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); 2422 2423 // Nothing has been sent to the resolver yet. 2424 EXPECT_TRUE(resolver->pending_requests().empty()); 2425 2426 // At this point the ProxyService should be waiting for the 2427 // ProxyScriptFetcher to invoke its completion callback, notifying it of 2428 // PAC script download completion. 2429 fetcher->NotifyFetchCompletion(OK, kValidPacScript1); 2430 2431 // Now that the PAC script is downloaded, the request will have been sent to 2432 // the proxy resolver. 2433 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1), 2434 resolver->pending_set_pac_script_request()->script_data()->utf16()); 2435 resolver->pending_set_pac_script_request()->CompleteNow(OK); 2436 2437 ASSERT_EQ(1u, resolver->pending_requests().size()); 2438 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); 2439 2440 // Complete the pending request. 2441 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); 2442 resolver->pending_requests()[0]->CompleteNow(OK); 2443 2444 // Wait for completion callback, and verify that the request ran as expected. 2445 EXPECT_EQ(OK, callback1.WaitForResult()); 2446 EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); 2447 2448 // Now simluate a change in the network. The ProxyConfigService is still 2449 // going to return the same PAC URL as before, but this URL needs to be 2450 // refetched on the new network. 2451 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests(); 2452 base::MessageLoop::current()->RunUntilIdle(); // Notification happens async. 2453 2454 // Start a second request. 2455 ProxyInfo info2; 2456 TestCompletionCallback callback2; 2457 rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2, 2458 callback2.callback(), NULL, NULL, BoundNetLog()); 2459 EXPECT_EQ(ERR_IO_PENDING, rv); 2460 2461 // This second request should have triggered the re-download of the PAC 2462 // script (since we marked the network as having changed). 2463 EXPECT_TRUE(fetcher->has_pending_request()); 2464 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); 2465 2466 // Nothing has been sent to the resolver yet. 2467 EXPECT_TRUE(resolver->pending_requests().empty()); 2468 2469 // Simulate the PAC script fetch as having completed (this time with 2470 // different data). 2471 fetcher->NotifyFetchCompletion(OK, kValidPacScript2); 2472 2473 // Now that the PAC script is downloaded, the second request will have been 2474 // sent to the proxy resolver. 2475 EXPECT_EQ(ASCIIToUTF16(kValidPacScript2), 2476 resolver->pending_set_pac_script_request()->script_data()->utf16()); 2477 resolver->pending_set_pac_script_request()->CompleteNow(OK); 2478 2479 ASSERT_EQ(1u, resolver->pending_requests().size()); 2480 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[0]->url()); 2481 2482 // Complete the pending second request. 2483 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80"); 2484 resolver->pending_requests()[0]->CompleteNow(OK); 2485 2486 // Wait for completion callback, and verify that the request ran as expected. 2487 EXPECT_EQ(OK, callback2.WaitForResult()); 2488 EXPECT_EQ("request2:80", info2.proxy_server().ToURI()); 2489 2490 // Check that the expected events were output to the log stream. In particular 2491 // PROXY_CONFIG_CHANGED should have only been emitted once (for the initial 2492 // setup), and NOT a second time when the IP address changed. 2493 CapturingNetLog::CapturedEntryList entries; 2494 log.GetEntries(&entries); 2495 2496 EXPECT_TRUE(LogContainsEntryWithType(entries, 0, 2497 NetLog::TYPE_PROXY_CONFIG_CHANGED)); 2498 ASSERT_EQ(9u, entries.size()); 2499 for (size_t i = 1; i < entries.size(); ++i) 2500 EXPECT_NE(NetLog::TYPE_PROXY_CONFIG_CHANGED, entries[i].type); 2501 } 2502 2503 // This test verifies that the PAC script specified by the settings is 2504 // periodically polled for changes. Specifically, if the initial fetch fails due 2505 // to a network error, we will eventually re-configure the service to use the 2506 // script once it becomes available. 2507 TEST_F(ProxyServiceTest, PACScriptRefetchAfterFailure) { 2508 // Change the retry policy to wait a mere 1 ms before retrying, so the test 2509 // runs quickly. 2510 ImmediatePollPolicy poll_policy; 2511 ProxyService::set_pac_script_poll_policy(&poll_policy); 2512 2513 MockProxyConfigService* config_service = 2514 new MockProxyConfigService("http://foopy/proxy.pac"); 2515 2516 MockAsyncProxyResolverExpectsBytes* resolver = 2517 new MockAsyncProxyResolverExpectsBytes; 2518 2519 ProxyService service(config_service, resolver, NULL); 2520 2521 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; 2522 service.SetProxyScriptFetchers(fetcher, 2523 new DoNothingDhcpProxyScriptFetcher()); 2524 2525 // Start 1 request. 2526 2527 ProxyInfo info1; 2528 TestCompletionCallback callback1; 2529 int rv = service.ResolveProxy( 2530 GURL("http://request1"), net::LOAD_NORMAL, &info1, callback1.callback(), 2531 NULL, NULL, BoundNetLog()); 2532 EXPECT_EQ(ERR_IO_PENDING, rv); 2533 2534 // The first request should have triggered initial download of PAC script. 2535 EXPECT_TRUE(fetcher->has_pending_request()); 2536 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); 2537 2538 // Nothing has been sent to the resolver yet. 2539 EXPECT_TRUE(resolver->pending_requests().empty()); 2540 2541 // At this point the ProxyService should be waiting for the 2542 // ProxyScriptFetcher to invoke its completion callback, notifying it of 2543 // PAC script download completion. 2544 // 2545 // We simulate a failed download attempt, the proxy service should now 2546 // fall-back to DIRECT connections. 2547 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string()); 2548 2549 ASSERT_TRUE(resolver->pending_requests().empty()); 2550 2551 // Wait for completion callback, and verify it used DIRECT. 2552 EXPECT_EQ(OK, callback1.WaitForResult()); 2553 EXPECT_TRUE(info1.is_direct()); 2554 2555 // At this point we have initialized the proxy service using a PAC script, 2556 // however it failed and fell-back to DIRECT. 2557 // 2558 // A background task to periodically re-check the PAC script for validity will 2559 // have been started. We will now wait for the next download attempt to start. 2560 // 2561 // Note that we shouldn't have to wait long here, since our test enables a 2562 // special unit-test mode. 2563 fetcher->WaitUntilFetch(); 2564 2565 ASSERT_TRUE(resolver->pending_requests().empty()); 2566 2567 // Make sure that our background checker is trying to download the expected 2568 // PAC script (same one as before). This time we will simulate a successful 2569 // download of the script. 2570 EXPECT_TRUE(fetcher->has_pending_request()); 2571 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); 2572 fetcher->NotifyFetchCompletion(OK, kValidPacScript1); 2573 2574 base::MessageLoop::current()->RunUntilIdle(); 2575 2576 // Now that the PAC script is downloaded, it should be used to initialize the 2577 // ProxyResolver. Simulate a successful parse. 2578 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1), 2579 resolver->pending_set_pac_script_request()->script_data()->utf16()); 2580 resolver->pending_set_pac_script_request()->CompleteNow(OK); 2581 2582 // At this point the ProxyService should have re-configured itself to use the 2583 // PAC script (thereby recovering from the initial fetch failure). We will 2584 // verify that the next Resolve request uses the resolver rather than 2585 // DIRECT. 2586 2587 // Start a second request. 2588 ProxyInfo info2; 2589 TestCompletionCallback callback2; 2590 rv = service.ResolveProxy( 2591 GURL("http://request2"), net::LOAD_NORMAL, &info2, callback2.callback(), 2592 NULL, NULL, BoundNetLog()); 2593 EXPECT_EQ(ERR_IO_PENDING, rv); 2594 2595 // Check that it was sent to the resolver. 2596 ASSERT_EQ(1u, resolver->pending_requests().size()); 2597 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[0]->url()); 2598 2599 // Complete the pending second request. 2600 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80"); 2601 resolver->pending_requests()[0]->CompleteNow(OK); 2602 2603 // Wait for completion callback, and verify that the request ran as expected. 2604 EXPECT_EQ(OK, callback2.WaitForResult()); 2605 EXPECT_EQ("request2:80", info2.proxy_server().ToURI()); 2606 } 2607 2608 // This test verifies that the PAC script specified by the settings is 2609 // periodically polled for changes. Specifically, if the initial fetch succeeds, 2610 // however at a later time its *contents* change, we will eventually 2611 // re-configure the service to use the new script. 2612 TEST_F(ProxyServiceTest, PACScriptRefetchAfterContentChange) { 2613 // Change the retry policy to wait a mere 1 ms before retrying, so the test 2614 // runs quickly. 2615 ImmediatePollPolicy poll_policy; 2616 ProxyService::set_pac_script_poll_policy(&poll_policy); 2617 2618 MockProxyConfigService* config_service = 2619 new MockProxyConfigService("http://foopy/proxy.pac"); 2620 2621 MockAsyncProxyResolverExpectsBytes* resolver = 2622 new MockAsyncProxyResolverExpectsBytes; 2623 2624 ProxyService service(config_service, resolver, NULL); 2625 2626 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; 2627 service.SetProxyScriptFetchers(fetcher, 2628 new DoNothingDhcpProxyScriptFetcher()); 2629 2630 // Start 1 request. 2631 2632 ProxyInfo info1; 2633 TestCompletionCallback callback1; 2634 int rv = service.ResolveProxy( 2635 GURL("http://request1"), net::LOAD_NORMAL, &info1, callback1.callback(), 2636 NULL, NULL, BoundNetLog()); 2637 EXPECT_EQ(ERR_IO_PENDING, rv); 2638 2639 // The first request should have triggered initial download of PAC script. 2640 EXPECT_TRUE(fetcher->has_pending_request()); 2641 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); 2642 2643 // Nothing has been sent to the resolver yet. 2644 EXPECT_TRUE(resolver->pending_requests().empty()); 2645 2646 // At this point the ProxyService should be waiting for the 2647 // ProxyScriptFetcher to invoke its completion callback, notifying it of 2648 // PAC script download completion. 2649 fetcher->NotifyFetchCompletion(OK, kValidPacScript1); 2650 2651 // Now that the PAC script is downloaded, the request will have been sent to 2652 // the proxy resolver. 2653 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1), 2654 resolver->pending_set_pac_script_request()->script_data()->utf16()); 2655 resolver->pending_set_pac_script_request()->CompleteNow(OK); 2656 2657 ASSERT_EQ(1u, resolver->pending_requests().size()); 2658 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); 2659 2660 // Complete the pending request. 2661 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); 2662 resolver->pending_requests()[0]->CompleteNow(OK); 2663 2664 // Wait for completion callback, and verify that the request ran as expected. 2665 EXPECT_EQ(OK, callback1.WaitForResult()); 2666 EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); 2667 2668 // At this point we have initialized the proxy service using a PAC script. 2669 // 2670 // A background task to periodically re-check the PAC script for validity will 2671 // have been started. We will now wait for the next download attempt to start. 2672 // 2673 // Note that we shouldn't have to wait long here, since our test enables a 2674 // special unit-test mode. 2675 fetcher->WaitUntilFetch(); 2676 2677 ASSERT_TRUE(resolver->pending_requests().empty()); 2678 2679 // Make sure that our background checker is trying to download the expected 2680 // PAC script (same one as before). This time we will simulate a successful 2681 // download of a DIFFERENT script. 2682 EXPECT_TRUE(fetcher->has_pending_request()); 2683 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); 2684 fetcher->NotifyFetchCompletion(OK, kValidPacScript2); 2685 2686 base::MessageLoop::current()->RunUntilIdle(); 2687 2688 // Now that the PAC script is downloaded, it should be used to initialize the 2689 // ProxyResolver. Simulate a successful parse. 2690 EXPECT_EQ(ASCIIToUTF16(kValidPacScript2), 2691 resolver->pending_set_pac_script_request()->script_data()->utf16()); 2692 resolver->pending_set_pac_script_request()->CompleteNow(OK); 2693 2694 // At this point the ProxyService should have re-configured itself to use the 2695 // new PAC script. 2696 2697 // Start a second request. 2698 ProxyInfo info2; 2699 TestCompletionCallback callback2; 2700 rv = service.ResolveProxy( 2701 GURL("http://request2"), net::LOAD_NORMAL, &info2, callback2.callback(), 2702 NULL, NULL, BoundNetLog()); 2703 EXPECT_EQ(ERR_IO_PENDING, rv); 2704 2705 // Check that it was sent to the resolver. 2706 ASSERT_EQ(1u, resolver->pending_requests().size()); 2707 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[0]->url()); 2708 2709 // Complete the pending second request. 2710 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80"); 2711 resolver->pending_requests()[0]->CompleteNow(OK); 2712 2713 // Wait for completion callback, and verify that the request ran as expected. 2714 EXPECT_EQ(OK, callback2.WaitForResult()); 2715 EXPECT_EQ("request2:80", info2.proxy_server().ToURI()); 2716 } 2717 2718 // This test verifies that the PAC script specified by the settings is 2719 // periodically polled for changes. Specifically, if the initial fetch succeeds 2720 // and so does the next poll, however the contents of the downloaded script 2721 // have NOT changed, then we do not bother to re-initialize the proxy resolver. 2722 TEST_F(ProxyServiceTest, PACScriptRefetchAfterContentUnchanged) { 2723 // Change the retry policy to wait a mere 1 ms before retrying, so the test 2724 // runs quickly. 2725 ImmediatePollPolicy poll_policy; 2726 ProxyService::set_pac_script_poll_policy(&poll_policy); 2727 2728 MockProxyConfigService* config_service = 2729 new MockProxyConfigService("http://foopy/proxy.pac"); 2730 2731 MockAsyncProxyResolverExpectsBytes* resolver = 2732 new MockAsyncProxyResolverExpectsBytes; 2733 2734 ProxyService service(config_service, resolver, NULL); 2735 2736 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; 2737 service.SetProxyScriptFetchers(fetcher, 2738 new DoNothingDhcpProxyScriptFetcher()); 2739 2740 // Start 1 request. 2741 2742 ProxyInfo info1; 2743 TestCompletionCallback callback1; 2744 int rv = service.ResolveProxy( 2745 GURL("http://request1"), net::LOAD_NORMAL, &info1, callback1.callback(), 2746 NULL, NULL, BoundNetLog()); 2747 EXPECT_EQ(ERR_IO_PENDING, rv); 2748 2749 // The first request should have triggered initial download of PAC script. 2750 EXPECT_TRUE(fetcher->has_pending_request()); 2751 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); 2752 2753 // Nothing has been sent to the resolver yet. 2754 EXPECT_TRUE(resolver->pending_requests().empty()); 2755 2756 // At this point the ProxyService should be waiting for the 2757 // ProxyScriptFetcher to invoke its completion callback, notifying it of 2758 // PAC script download completion. 2759 fetcher->NotifyFetchCompletion(OK, kValidPacScript1); 2760 2761 // Now that the PAC script is downloaded, the request will have been sent to 2762 // the proxy resolver. 2763 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1), 2764 resolver->pending_set_pac_script_request()->script_data()->utf16()); 2765 resolver->pending_set_pac_script_request()->CompleteNow(OK); 2766 2767 ASSERT_EQ(1u, resolver->pending_requests().size()); 2768 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); 2769 2770 // Complete the pending request. 2771 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); 2772 resolver->pending_requests()[0]->CompleteNow(OK); 2773 2774 // Wait for completion callback, and verify that the request ran as expected. 2775 EXPECT_EQ(OK, callback1.WaitForResult()); 2776 EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); 2777 2778 // At this point we have initialized the proxy service using a PAC script. 2779 // 2780 // A background task to periodically re-check the PAC script for validity will 2781 // have been started. We will now wait for the next download attempt to start. 2782 // 2783 // Note that we shouldn't have to wait long here, since our test enables a 2784 // special unit-test mode. 2785 fetcher->WaitUntilFetch(); 2786 2787 ASSERT_TRUE(resolver->pending_requests().empty()); 2788 2789 // Make sure that our background checker is trying to download the expected 2790 // PAC script (same one as before). We will simulate the same response as 2791 // last time (i.e. the script is unchanged). 2792 EXPECT_TRUE(fetcher->has_pending_request()); 2793 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); 2794 fetcher->NotifyFetchCompletion(OK, kValidPacScript1); 2795 2796 base::MessageLoop::current()->RunUntilIdle(); 2797 2798 ASSERT_FALSE(resolver->has_pending_set_pac_script_request()); 2799 2800 // At this point the ProxyService is still running the same PAC script as 2801 // before. 2802 2803 // Start a second request. 2804 ProxyInfo info2; 2805 TestCompletionCallback callback2; 2806 rv = service.ResolveProxy( 2807 GURL("http://request2"), net::LOAD_NORMAL, &info2, callback2.callback(), 2808 NULL, NULL, BoundNetLog()); 2809 EXPECT_EQ(ERR_IO_PENDING, rv); 2810 2811 // Check that it was sent to the resolver. 2812 ASSERT_EQ(1u, resolver->pending_requests().size()); 2813 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[0]->url()); 2814 2815 // Complete the pending second request. 2816 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80"); 2817 resolver->pending_requests()[0]->CompleteNow(OK); 2818 2819 // Wait for completion callback, and verify that the request ran as expected. 2820 EXPECT_EQ(OK, callback2.WaitForResult()); 2821 EXPECT_EQ("request2:80", info2.proxy_server().ToURI()); 2822 } 2823 2824 // This test verifies that the PAC script specified by the settings is 2825 // periodically polled for changes. Specifically, if the initial fetch succeeds, 2826 // however at a later time it starts to fail, we should re-configure the 2827 // ProxyService to stop using that PAC script. 2828 TEST_F(ProxyServiceTest, PACScriptRefetchAfterSuccess) { 2829 // Change the retry policy to wait a mere 1 ms before retrying, so the test 2830 // runs quickly. 2831 ImmediatePollPolicy poll_policy; 2832 ProxyService::set_pac_script_poll_policy(&poll_policy); 2833 2834 MockProxyConfigService* config_service = 2835 new MockProxyConfigService("http://foopy/proxy.pac"); 2836 2837 MockAsyncProxyResolverExpectsBytes* resolver = 2838 new MockAsyncProxyResolverExpectsBytes; 2839 2840 ProxyService service(config_service, resolver, NULL); 2841 2842 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; 2843 service.SetProxyScriptFetchers(fetcher, 2844 new DoNothingDhcpProxyScriptFetcher()); 2845 2846 // Start 1 request. 2847 2848 ProxyInfo info1; 2849 TestCompletionCallback callback1; 2850 int rv = service.ResolveProxy( 2851 GURL("http://request1"), net::LOAD_NORMAL, &info1, callback1.callback(), 2852 NULL, NULL, BoundNetLog()); 2853 EXPECT_EQ(ERR_IO_PENDING, rv); 2854 2855 // The first request should have triggered initial download of PAC script. 2856 EXPECT_TRUE(fetcher->has_pending_request()); 2857 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); 2858 2859 // Nothing has been sent to the resolver yet. 2860 EXPECT_TRUE(resolver->pending_requests().empty()); 2861 2862 // At this point the ProxyService should be waiting for the 2863 // ProxyScriptFetcher to invoke its completion callback, notifying it of 2864 // PAC script download completion. 2865 fetcher->NotifyFetchCompletion(OK, kValidPacScript1); 2866 2867 // Now that the PAC script is downloaded, the request will have been sent to 2868 // the proxy resolver. 2869 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1), 2870 resolver->pending_set_pac_script_request()->script_data()->utf16()); 2871 resolver->pending_set_pac_script_request()->CompleteNow(OK); 2872 2873 ASSERT_EQ(1u, resolver->pending_requests().size()); 2874 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); 2875 2876 // Complete the pending request. 2877 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); 2878 resolver->pending_requests()[0]->CompleteNow(OK); 2879 2880 // Wait for completion callback, and verify that the request ran as expected. 2881 EXPECT_EQ(OK, callback1.WaitForResult()); 2882 EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); 2883 2884 // At this point we have initialized the proxy service using a PAC script. 2885 // 2886 // A background task to periodically re-check the PAC script for validity will 2887 // have been started. We will now wait for the next download attempt to start. 2888 // 2889 // Note that we shouldn't have to wait long here, since our test enables a 2890 // special unit-test mode. 2891 fetcher->WaitUntilFetch(); 2892 2893 ASSERT_TRUE(resolver->pending_requests().empty()); 2894 2895 // Make sure that our background checker is trying to download the expected 2896 // PAC script (same one as before). This time we will simulate a failure 2897 // to download the script. 2898 EXPECT_TRUE(fetcher->has_pending_request()); 2899 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); 2900 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string()); 2901 2902 base::MessageLoop::current()->RunUntilIdle(); 2903 2904 // At this point the ProxyService should have re-configured itself to use 2905 // DIRECT connections rather than the given proxy resolver. 2906 2907 // Start a second request. 2908 ProxyInfo info2; 2909 TestCompletionCallback callback2; 2910 rv = service.ResolveProxy( 2911 GURL("http://request2"), net::LOAD_NORMAL, &info2, callback2.callback(), 2912 NULL, NULL, BoundNetLog()); 2913 EXPECT_EQ(OK, rv); 2914 EXPECT_TRUE(info2.is_direct()); 2915 } 2916 2917 // Tests that the code which decides at what times to poll the PAC 2918 // script follows the expected policy. 2919 TEST_F(ProxyServiceTest, PACScriptPollingPolicy) { 2920 // Retrieve the internal polling policy implementation used by ProxyService. 2921 scoped_ptr<ProxyService::PacPollPolicy> policy = 2922 ProxyService::CreateDefaultPacPollPolicy(); 2923 2924 int error; 2925 ProxyService::PacPollPolicy::Mode mode; 2926 const base::TimeDelta initial_delay = base::TimeDelta::FromMilliseconds(-1); 2927 base::TimeDelta delay = initial_delay; 2928 2929 // -------------------------------------------------- 2930 // Test the poll sequence in response to a failure. 2931 // -------------------------------------------------- 2932 error = ERR_NAME_NOT_RESOLVED; 2933 2934 // Poll #0 2935 mode = policy->GetNextDelay(error, initial_delay, &delay); 2936 EXPECT_EQ(8, delay.InSeconds()); 2937 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_USE_TIMER, mode); 2938 2939 // Poll #1 2940 mode = policy->GetNextDelay(error, delay, &delay); 2941 EXPECT_EQ(32, delay.InSeconds()); 2942 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode); 2943 2944 // Poll #2 2945 mode = policy->GetNextDelay(error, delay, &delay); 2946 EXPECT_EQ(120, delay.InSeconds()); 2947 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode); 2948 2949 // Poll #3 2950 mode = policy->GetNextDelay(error, delay, &delay); 2951 EXPECT_EQ(14400, delay.InSeconds()); 2952 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode); 2953 2954 // Poll #4 2955 mode = policy->GetNextDelay(error, delay, &delay); 2956 EXPECT_EQ(14400, delay.InSeconds()); 2957 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode); 2958 2959 // -------------------------------------------------- 2960 // Test the poll sequence in response to a success. 2961 // -------------------------------------------------- 2962 error = OK; 2963 2964 // Poll #0 2965 mode = policy->GetNextDelay(error, initial_delay, &delay); 2966 EXPECT_EQ(43200, delay.InSeconds()); 2967 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode); 2968 2969 // Poll #1 2970 mode = policy->GetNextDelay(error, delay, &delay); 2971 EXPECT_EQ(43200, delay.InSeconds()); 2972 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode); 2973 2974 // Poll #2 2975 mode = policy->GetNextDelay(error, delay, &delay); 2976 EXPECT_EQ(43200, delay.InSeconds()); 2977 EXPECT_EQ(ProxyService::PacPollPolicy::MODE_START_AFTER_ACTIVITY, mode); 2978 } 2979 2980 // This tests the polling of the PAC script. Specifically, it tests that 2981 // polling occurs in response to user activity. 2982 TEST_F(ProxyServiceTest, PACScriptRefetchAfterActivity) { 2983 ImmediateAfterActivityPollPolicy poll_policy; 2984 ProxyService::set_pac_script_poll_policy(&poll_policy); 2985 2986 MockProxyConfigService* config_service = 2987 new MockProxyConfigService("http://foopy/proxy.pac"); 2988 2989 MockAsyncProxyResolverExpectsBytes* resolver = 2990 new MockAsyncProxyResolverExpectsBytes; 2991 2992 ProxyService service(config_service, resolver, NULL); 2993 2994 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; 2995 service.SetProxyScriptFetchers(fetcher, 2996 new DoNothingDhcpProxyScriptFetcher()); 2997 2998 // Start 1 request. 2999 3000 ProxyInfo info1; 3001 TestCompletionCallback callback1; 3002 int rv = service.ResolveProxy( 3003 GURL("http://request1"), net::LOAD_NORMAL, &info1, callback1.callback(), 3004 NULL, NULL, BoundNetLog()); 3005 EXPECT_EQ(ERR_IO_PENDING, rv); 3006 3007 // The first request should have triggered initial download of PAC script. 3008 EXPECT_TRUE(fetcher->has_pending_request()); 3009 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); 3010 3011 // Nothing has been sent to the resolver yet. 3012 EXPECT_TRUE(resolver->pending_requests().empty()); 3013 3014 // At this point the ProxyService should be waiting for the 3015 // ProxyScriptFetcher to invoke its completion callback, notifying it of 3016 // PAC script download completion. 3017 fetcher->NotifyFetchCompletion(OK, kValidPacScript1); 3018 3019 // Now that the PAC script is downloaded, the request will have been sent to 3020 // the proxy resolver. 3021 EXPECT_EQ(ASCIIToUTF16(kValidPacScript1), 3022 resolver->pending_set_pac_script_request()->script_data()->utf16()); 3023 resolver->pending_set_pac_script_request()->CompleteNow(OK); 3024 3025 ASSERT_EQ(1u, resolver->pending_requests().size()); 3026 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); 3027 3028 // Complete the pending request. 3029 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); 3030 resolver->pending_requests()[0]->CompleteNow(OK); 3031 3032 // Wait for completion callback, and verify that the request ran as expected. 3033 EXPECT_EQ(OK, callback1.WaitForResult()); 3034 EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); 3035 3036 // At this point we have initialized the proxy service using a PAC script. 3037 // Our PAC poller is set to update ONLY in response to network activity, 3038 // (i.e. another call to ResolveProxy()). 3039 3040 ASSERT_FALSE(fetcher->has_pending_request()); 3041 ASSERT_TRUE(resolver->pending_requests().empty()); 3042 3043 // Start a second request. 3044 ProxyInfo info2; 3045 TestCompletionCallback callback2; 3046 rv = service.ResolveProxy( 3047 GURL("http://request2"), net::LOAD_NORMAL, &info2, callback2.callback(), 3048 NULL, NULL, BoundNetLog()); 3049 EXPECT_EQ(ERR_IO_PENDING, rv); 3050 3051 // This request should have sent work to the resolver; complete it. 3052 ASSERT_EQ(1u, resolver->pending_requests().size()); 3053 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[0]->url()); 3054 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80"); 3055 resolver->pending_requests()[0]->CompleteNow(OK); 3056 3057 EXPECT_EQ(OK, callback2.WaitForResult()); 3058 EXPECT_EQ("request2:80", info2.proxy_server().ToURI()); 3059 3060 // In response to getting that resolve request, the poller should have 3061 // started the next poll, and made it as far as to request the download. 3062 3063 EXPECT_TRUE(fetcher->has_pending_request()); 3064 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); 3065 3066 // This time we will fail the download, to simulate a PAC script change. 3067 fetcher->NotifyFetchCompletion(ERR_FAILED, std::string()); 3068 3069 // Drain the message loop, so ProxyService is notified of the change 3070 // and has a chance to re-configure itself. 3071 base::MessageLoop::current()->RunUntilIdle(); 3072 3073 // Start a third request -- this time we expect to get a direct connection 3074 // since the PAC script poller experienced a failure. 3075 ProxyInfo info3; 3076 TestCompletionCallback callback3; 3077 rv = service.ResolveProxy( 3078 GURL("http://request3"), net::LOAD_NORMAL, &info3, callback3.callback(), 3079 NULL, NULL, BoundNetLog()); 3080 EXPECT_EQ(OK, rv); 3081 EXPECT_TRUE(info3.is_direct()); 3082 } 3083 3084 } // namespace net 3085