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