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