| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/compiler_specific.h" |
| 5 #include "googleurl/src/gurl.h" | 6 #include "googleurl/src/gurl.h" |
| 6 #include "net/base/net_errors.h" | 7 #include "net/base/net_errors.h" |
| 7 #include "net/proxy/proxy_service.h" | 8 #include "net/proxy/proxy_service.h" |
| 8 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
| 9 | 10 |
| 10 namespace { | 11 namespace { |
| 11 | 12 |
| 12 class MockProxyConfigService: public net::ProxyConfigService { | 13 class MockProxyConfigService: public net::ProxyConfigService { |
| 13 public: | 14 public: |
| 14 MockProxyConfigService() {} // Direct connect. | 15 MockProxyConfigService() {} // Direct connect. |
| 15 explicit MockProxyConfigService(const net::ProxyConfig& pc) : config(pc) {} | 16 explicit MockProxyConfigService(const net::ProxyConfig& pc) : config(pc) {} |
| 16 explicit MockProxyConfigService(const std::string& pac_url) { | 17 explicit MockProxyConfigService(const std::string& pac_url) { |
| 17 config.pac_url = GURL(pac_url); | 18 config.pac_url = GURL(pac_url); |
| 18 } | 19 } |
| 19 | 20 |
| 20 virtual int GetProxyConfig(net::ProxyConfig* results) { | 21 virtual int GetProxyConfig(net::ProxyConfig* results) { |
| 21 *results = config; | 22 *results = config; |
| 22 return net::OK; | 23 return net::OK; |
| 23 } | 24 } |
| 24 | 25 |
| 25 net::ProxyConfig config; | 26 net::ProxyConfig config; |
| 26 }; | 27 }; |
| 27 | 28 |
| 28 class MockProxyResolver : public net::ProxyResolver { | 29 class MockProxyResolver : public net::ProxyResolver { |
| 29 public: | 30 public: |
| 30 MockProxyResolver() : fail_get_proxy_for_url(false) { | 31 MockProxyResolver() : net::ProxyResolver(true), |
| 32 fail_get_proxy_for_url(false) { |
| 31 } | 33 } |
| 32 | 34 |
| 33 virtual int GetProxyForURL(const GURL& query_url, | 35 virtual int GetProxyForURL(const GURL& query_url, |
| 34 const GURL& pac_url, | 36 const GURL& pac_url, |
| 35 net::ProxyInfo* results) { | 37 net::ProxyInfo* results) { |
| 36 if (fail_get_proxy_for_url) | 38 if (fail_get_proxy_for_url) |
| 37 return net::ERR_FAILED; | 39 return net::ERR_FAILED; |
| 38 if (GURL(query_url).host() == info_predicate_query_host) { | 40 if (GURL(query_url).host() == info_predicate_query_host) { |
| 39 results->Use(info); | 41 results->Use(info); |
| 40 } else { | 42 } else { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 int ReconsiderProxyAfterError(const GURL& url, net::ProxyInfo* proxy_info) { | 75 int ReconsiderProxyAfterError(const GURL& url, net::ProxyInfo* proxy_info) { |
| 74 return sync_proxy_service_->ReconsiderProxyAfterError(url, proxy_info); | 76 return sync_proxy_service_->ReconsiderProxyAfterError(url, proxy_info); |
| 75 } | 77 } |
| 76 | 78 |
| 77 private: | 79 private: |
| 78 base::Thread io_thread_; | 80 base::Thread io_thread_; |
| 79 net::ProxyService service_; | 81 net::ProxyService service_; |
| 80 scoped_refptr<net::SyncProxyServiceHelper> sync_proxy_service_; | 82 scoped_refptr<net::SyncProxyServiceHelper> sync_proxy_service_; |
| 81 }; | 83 }; |
| 82 | 84 |
| 85 // ResultFuture is a handle to get at the result from |
| 86 // ProxyService::ResolveProxyForURL() that ran on another thread. |
| 87 class ResultFuture : public base::RefCountedThreadSafe<ResultFuture> { |
| 88 public: |
| 89 // |service| is the ProxyService to issue requests on, and |io_message_loop| |
| 90 // is the message loop where ProxyService lives. |
| 91 ResultFuture(MessageLoop* io_message_loop, |
| 92 net::ProxyService* service) |
| 93 : io_message_loop_(io_message_loop), |
| 94 service_(service), |
| 95 request_(NULL), |
| 96 ALLOW_THIS_IN_INITIALIZER_LIST( |
| 97 callback_(this, &ResultFuture::OnCompletion)), |
| 98 completion_(true, false), |
| 99 cancelled_(false, false), |
| 100 started_(false, false), |
| 101 did_complete_(false) { |
| 102 } |
| 103 |
| 104 // Block until the request has completed, then return the result. |
| 105 int GetResultCode() { |
| 106 DCHECK(MessageLoop::current() != io_message_loop_); |
| 107 WaitUntilCompleted(); |
| 108 return result_code_; |
| 109 } |
| 110 |
| 111 // Block until the request has completed, then return the result. |
| 112 const net::ProxyInfo& GetProxyInfo() { |
| 113 DCHECK(MessageLoop::current() != io_message_loop_); |
| 114 WaitUntilCompleted(); |
| 115 return proxy_info_; |
| 116 } |
| 117 |
| 118 // Cancel this request (wait until the cancel has been issued before |
| 119 // returning). |
| 120 void Cancel() { |
| 121 DCHECK(MessageLoop::current() != io_message_loop_); |
| 122 io_message_loop_->PostTask(FROM_HERE, NewRunnableMethod( |
| 123 this, &ResultFuture::DoCancel)); |
| 124 cancelled_.Wait(); |
| 125 } |
| 126 |
| 127 // Return true if the request has already completed. |
| 128 bool IsCompleted() { |
| 129 DCHECK(MessageLoop::current() != io_message_loop_); |
| 130 return did_complete_; |
| 131 } |
| 132 |
| 133 // Wait until the ProxyService completes this request. |
| 134 void WaitUntilCompleted() { |
| 135 DCHECK(MessageLoop::current() != io_message_loop_); |
| 136 completion_.Wait(); |
| 137 DCHECK(did_complete_); |
| 138 } |
| 139 |
| 140 private: |
| 141 friend class ProxyServiceWithFutures; |
| 142 |
| 143 // Start the request. Return once ProxyService::GetProxyForURL() returns. |
| 144 void StartResolve(const GURL& url) { |
| 145 DCHECK(MessageLoop::current() != io_message_loop_); |
| 146 io_message_loop_->PostTask(FROM_HERE, NewRunnableMethod( |
| 147 this, &ResultFuture::DoStartResolve, url)); |
| 148 started_.Wait(); |
| 149 } |
| 150 |
| 151 // Called on |io_message_loop_|. |
| 152 void DoStartResolve(const GURL& url) { |
| 153 DCHECK(MessageLoop::current() == io_message_loop_); |
| 154 int rv = service_->ResolveProxy(url, &proxy_info_, &callback_, &request_); |
| 155 if (rv != net::ERR_IO_PENDING) { |
| 156 // Completed synchronously. |
| 157 OnCompletion(rv); |
| 158 } |
| 159 started_.Signal(); |
| 160 } |
| 161 |
| 162 // Called on |io_message_loop_|. |
| 163 void DoCancel() { |
| 164 DCHECK(MessageLoop::current() == io_message_loop_); |
| 165 if (!did_complete_) |
| 166 service_->CancelPacRequest(request_); |
| 167 cancelled_.Signal(); |
| 168 } |
| 169 |
| 170 // Called on |io_message_loop_|. |
| 171 void OnCompletion(int result) { |
| 172 DCHECK(MessageLoop::current() == io_message_loop_); |
| 173 DCHECK(!did_complete_); |
| 174 did_complete_ = true; |
| 175 result_code_ = result; |
| 176 request_ = NULL; |
| 177 completion_.Signal(); |
| 178 } |
| 179 |
| 180 // The message loop where the ProxyService lives. |
| 181 MessageLoop* io_message_loop_; |
| 182 |
| 183 // The proxy service that started this request. |
| 184 net::ProxyService* service_; |
| 185 |
| 186 // The in-progress request. |
| 187 net::ProxyService::PacRequest* request_; |
| 188 |
| 189 net::CompletionCallbackImpl<ResultFuture> callback_; |
| 190 base::WaitableEvent completion_; |
| 191 base::WaitableEvent cancelled_; |
| 192 base::WaitableEvent started_; |
| 193 bool did_complete_; |
| 194 |
| 195 // Results from the request. |
| 196 int result_code_; |
| 197 net::ProxyInfo proxy_info_; |
| 198 }; |
| 199 |
| 200 // Wraps a ProxyService running on its own IO thread. |
| 201 class ProxyServiceWithFutures { |
| 202 public: |
| 203 ProxyServiceWithFutures(net::ProxyConfigService* config_service, |
| 204 net::ProxyResolver* resolver) |
| 205 : io_thread_("IO_Thread"), |
| 206 service_(config_service, resolver) { |
| 207 base::Thread::Options options; |
| 208 options.message_loop_type = MessageLoop::TYPE_IO; |
| 209 io_thread_.StartWithOptions(options); |
| 210 } |
| 211 |
| 212 // Start the request on |io_thread_|, and return a handle that can be |
| 213 // used to access the results. The caller is responsible for freeing |
| 214 // the ResultFuture. |
| 215 void ResolveProxy(scoped_refptr<ResultFuture>* result, const GURL& url) { |
| 216 (*result) = new ResultFuture(io_thread_.message_loop(), &service_); |
| 217 (*result)->StartResolve(url); |
| 218 } |
| 219 |
| 220 void SetProxyScriptFetcher(net::ProxyScriptFetcher* proxy_script_fetcher) { |
| 221 service_.SetProxyScriptFetcher(proxy_script_fetcher); |
| 222 } |
| 223 |
| 224 private: |
| 225 base::Thread io_thread_; |
| 226 net::ProxyService service_; |
| 227 }; |
| 228 |
| 229 // A ProxyResolver which can be set to block upon reaching GetProxyForURL. |
| 230 class BlockableProxyResolver : public net::ProxyResolver { |
| 231 public: |
| 232 BlockableProxyResolver() : net::ProxyResolver(true), |
| 233 should_block_(false), |
| 234 unblocked_(true, true), |
| 235 blocked_(true, false) { |
| 236 } |
| 237 |
| 238 void Block() { |
| 239 should_block_ = true; |
| 240 unblocked_.Reset(); |
| 241 } |
| 242 |
| 243 void Unblock() { |
| 244 should_block_ = false; |
| 245 blocked_.Reset(); |
| 246 unblocked_.Signal(); |
| 247 } |
| 248 |
| 249 void WaitUntilBlocked() { |
| 250 blocked_.Wait(); |
| 251 } |
| 252 |
| 253 // net::ProxyResolver implementation: |
| 254 virtual int GetProxyForURL(const GURL& query_url, |
| 255 const GURL& pac_url, |
| 256 net::ProxyInfo* results) { |
| 257 if (should_block_) { |
| 258 blocked_.Signal(); |
| 259 unblocked_.Wait(); |
| 260 } |
| 261 |
| 262 results->UseNamedProxy(query_url.host()); |
| 263 return net::OK; |
| 264 } |
| 265 |
| 266 private: |
| 267 bool should_block_; |
| 268 base::WaitableEvent unblocked_; |
| 269 base::WaitableEvent blocked_; |
| 270 }; |
| 271 |
| 272 // A mock ProxyResolverWithoutFetch which concatenates the query's host with |
| 273 // the last download PAC contents. This way the result describes what the last |
| 274 // downloaded PAC script's contents were, in addition to the query url itself. |
| 275 class MockProxyResolverWithoutFetch : public net::ProxyResolver { |
| 276 public: |
| 277 MockProxyResolverWithoutFetch() : net::ProxyResolver(false), |
| 278 last_pac_contents_("NONE") {} |
| 279 |
| 280 // net::ProxyResolver implementation: |
| 281 virtual int GetProxyForURL(const GURL& query_url, |
| 282 const GURL& pac_url, |
| 283 net::ProxyInfo* results) { |
| 284 results->UseNamedProxy(last_pac_contents_ + "." + query_url.host()); |
| 285 return net::OK; |
| 286 } |
| 287 |
| 288 virtual void SetPacScript(const std::string& bytes) { |
| 289 last_pac_contents_ = bytes; |
| 290 } |
| 291 |
| 292 private: |
| 293 std::string last_pac_contents_; |
| 294 }; |
| 295 |
| 83 } // namespace | 296 } // namespace |
| 84 | 297 |
| 298 // A mock ProxyScriptFetcher. No result will be returned to the fetch client |
| 299 // until we call NotifyFetchCompletion() to set the results. |
| 300 class MockProxyScriptFetcher : public net::ProxyScriptFetcher { |
| 301 public: |
| 302 MockProxyScriptFetcher() : pending_request_loop_(NULL), |
| 303 pending_request_callback_(NULL), pending_request_bytes_(NULL) {} |
| 304 |
| 305 // net::ProxyScriptFetcher implementation. |
| 306 virtual void Fetch(const GURL& url, std::string* bytes, |
| 307 net::CompletionCallback* callback) { |
| 308 DCHECK(!HasPendingRequest()); |
| 309 |
| 310 // Save the caller's information, and have them wait. |
| 311 pending_request_loop_ = MessageLoop::current(); |
| 312 pending_request_url_ = url; |
| 313 pending_request_callback_ = callback; |
| 314 pending_request_bytes_ = bytes; |
| 315 } |
| 316 |
| 317 void NotifyFetchCompletion(int result, const std::string& bytes) { |
| 318 DCHECK(HasPendingRequest()); |
| 319 pending_request_loop_->PostTask(FROM_HERE, NewRunnableMethod( |
| 320 this, &MockProxyScriptFetcher::DoNotifyFetchCompletion, result, bytes)); |
| 321 } |
| 322 |
| 323 virtual void Cancel() {} |
| 324 |
| 325 private: |
| 326 // Runs on |pending_request_loop_|. |
| 327 void DoNotifyFetchCompletion(int result, const std::string& bytes) { |
| 328 DCHECK(HasPendingRequest()); |
| 329 *pending_request_bytes_ = bytes; |
| 330 pending_request_callback_->Run(result); |
| 331 } |
| 332 |
| 333 bool HasPendingRequest() const { |
| 334 return pending_request_loop_ != NULL; |
| 335 } |
| 336 |
| 337 MessageLoop* pending_request_loop_; |
| 338 GURL pending_request_url_; |
| 339 net::CompletionCallback* pending_request_callback_; |
| 340 std::string* pending_request_bytes_; |
| 341 }; |
| 342 |
| 343 // Template specialization so MockProxyScriptFetcher does not have to be refcoun
ted. |
| 344 template<> |
| 345 void RunnableMethodTraits<MockProxyScriptFetcher>::RetainCallee( |
| 346 MockProxyScriptFetcher* remover) {} |
| 347 template<> |
| 348 void RunnableMethodTraits<MockProxyScriptFetcher>::ReleaseCallee( |
| 349 MockProxyScriptFetcher* remover) {} |
| 350 |
| 85 // Test parsing from a PAC string. | 351 // Test parsing from a PAC string. |
| 86 TEST(ProxyListTest, SetFromPacString) { | 352 TEST(ProxyListTest, SetFromPacString) { |
| 87 const struct { | 353 const struct { |
| 88 const char* pac_input; | 354 const char* pac_input; |
| 89 const char* pac_output; | 355 const char* pac_output; |
| 90 } tests[] = { | 356 } tests[] = { |
| 91 // Valid inputs: | 357 // Valid inputs: |
| 92 { "PROXY foopy:10", | 358 { "PROXY foopy:10", |
| 93 "PROXY foopy:10", | 359 "PROXY foopy:10", |
| 94 }, | 360 }, |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 412 EXPECT_EQ("foopy1:8080", info3.proxy_server().ToURI()); | 678 EXPECT_EQ("foopy1:8080", info3.proxy_server().ToURI()); |
| 413 } | 679 } |
| 414 | 680 |
| 415 TEST(ProxyServiceTest, ProxyBypassList) { | 681 TEST(ProxyServiceTest, ProxyBypassList) { |
| 416 // Test what happens when a proxy bypass list is specified. | 682 // Test what happens when a proxy bypass list is specified. |
| 417 | 683 |
| 418 net::ProxyConfig config; | 684 net::ProxyConfig config; |
| 419 config.proxy_rules = "foopy1:8080;foopy2:9090"; | 685 config.proxy_rules = "foopy1:8080;foopy2:9090"; |
| 420 config.auto_detect = false; | 686 config.auto_detect = false; |
| 421 config.proxy_bypass_local_names = true; | 687 config.proxy_bypass_local_names = true; |
| 422 | 688 |
| 423 SyncProxyService service(new MockProxyConfigService(config), | 689 SyncProxyService service(new MockProxyConfigService(config), |
| 424 new MockProxyResolver()); | 690 new MockProxyResolver()); |
| 425 GURL url("http://www.google.com/"); | 691 GURL url("http://www.google.com/"); |
| 426 // Get the proxy information. | 692 // Get the proxy information. |
| 427 net::ProxyInfo info; | 693 net::ProxyInfo info; |
| 428 int rv = service.ResolveProxy(url, &info); | 694 int rv = service.ResolveProxy(url, &info); |
| 429 EXPECT_EQ(rv, net::OK); | 695 EXPECT_EQ(rv, net::OK); |
| 430 EXPECT_FALSE(info.is_direct()); | 696 EXPECT_FALSE(info.is_direct()); |
| 431 | 697 |
| 432 SyncProxyService service1(new MockProxyConfigService(config), | 698 SyncProxyService service1(new MockProxyConfigService(config), |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 530 SyncProxyService service4(new MockProxyConfigService(config), | 796 SyncProxyService service4(new MockProxyConfigService(config), |
| 531 new MockProxyResolver); | 797 new MockProxyResolver); |
| 532 GURL test_url4("www.microsoft.com"); | 798 GURL test_url4("www.microsoft.com"); |
| 533 net::ProxyInfo info4; | 799 net::ProxyInfo info4; |
| 534 rv = service4.ResolveProxy(test_url4, &info4); | 800 rv = service4.ResolveProxy(test_url4, &info4); |
| 535 EXPECT_EQ(rv, net::OK); | 801 EXPECT_EQ(rv, net::OK); |
| 536 EXPECT_FALSE(info4.is_direct()); | 802 EXPECT_FALSE(info4.is_direct()); |
| 537 EXPECT_EQ("foopy1:8080", info4.proxy_server().ToURI()); | 803 EXPECT_EQ("foopy1:8080", info4.proxy_server().ToURI()); |
| 538 } | 804 } |
| 539 | 805 |
| 806 // Test cancellation of a queued request. |
| 807 TEST(ProxyServiceTest, CancelQueuedRequest) { |
| 808 MockProxyConfigService* config_service = |
| 809 new MockProxyConfigService("http://foopy/proxy.pac"); |
| 810 |
| 811 BlockableProxyResolver* resolver = new BlockableProxyResolver; |
| 812 |
| 813 ProxyServiceWithFutures service(config_service, resolver); |
| 814 |
| 815 // Cause requests to pile up, by having them block in the PAC thread. |
| 816 resolver->Block(); |
| 817 |
| 818 // Start 3 requests. |
| 819 scoped_refptr<ResultFuture> result1; |
| 820 service.ResolveProxy(&result1, GURL("http://request1")); |
| 821 |
| 822 scoped_refptr<ResultFuture> result2; |
| 823 service.ResolveProxy(&result2, GURL("http://request2")); |
| 824 |
| 825 scoped_refptr<ResultFuture> result3; |
| 826 service.ResolveProxy(&result3, GURL("http://request3")); |
| 827 |
| 828 // Wait until the first request has become blocked in the PAC thread. |
| 829 resolver->WaitUntilBlocked(); |
| 830 |
| 831 // Cancel the second request |
| 832 result2->Cancel(); |
| 833 |
| 834 // Unblock the PAC thread. |
| 835 resolver->Unblock(); |
| 836 |
| 837 // Wait for the final request to complete. |
| 838 result3->WaitUntilCompleted(); |
| 839 |
| 840 // Verify that requests ran as expected. |
| 841 |
| 842 EXPECT_TRUE(result1->IsCompleted()); |
| 843 EXPECT_EQ(net::OK, result1->GetResultCode()); |
| 844 EXPECT_EQ("request1:80", result1->GetProxyInfo().proxy_server().ToURI()); |
| 845 |
| 846 EXPECT_FALSE(result2->IsCompleted()); // Cancelled. |
| 847 |
| 848 EXPECT_TRUE(result3->IsCompleted()); |
| 849 EXPECT_EQ(net::OK, result3->GetResultCode()); |
| 850 EXPECT_EQ("request3:80", result3->GetProxyInfo().proxy_server().ToURI()); |
| 851 } |
| 852 |
| 853 // Test cancellation of an in-progress request. |
| 854 TEST(ProxyServiceTest, CancelInprogressRequest) { |
| 855 MockProxyConfigService* config_service = |
| 856 new MockProxyConfigService("http://foopy/proxy.pac"); |
| 857 |
| 858 BlockableProxyResolver* resolver = new BlockableProxyResolver; |
| 859 |
| 860 ProxyServiceWithFutures service(config_service, resolver); |
| 861 |
| 862 // Cause requests to pile up, by having them block in the PAC thread. |
| 863 resolver->Block(); |
| 864 |
| 865 // Start 3 requests. |
| 866 scoped_refptr<ResultFuture> result1; |
| 867 service.ResolveProxy(&result1, GURL("http://request1")); |
| 868 |
| 869 scoped_refptr<ResultFuture> result2; |
| 870 service.ResolveProxy(&result2, GURL("http://request2")); |
| 871 |
| 872 scoped_refptr<ResultFuture> result3; |
| 873 service.ResolveProxy(&result3, GURL("http://request3")); |
| 874 |
| 875 // Wait until the first request has become blocked in the PAC thread. |
| 876 resolver->WaitUntilBlocked(); |
| 877 |
| 878 // Cancel the first request |
| 879 result1->Cancel(); |
| 880 |
| 881 // Unblock the PAC thread. |
| 882 resolver->Unblock(); |
| 883 |
| 884 // Wait for the final request to complete. |
| 885 result3->WaitUntilCompleted(); |
| 886 |
| 887 // Verify that requests ran as expected. |
| 888 |
| 889 EXPECT_FALSE(result1->IsCompleted()); // Cancelled. |
| 890 |
| 891 EXPECT_TRUE(result2->IsCompleted()); |
| 892 EXPECT_EQ(net::OK, result2->GetResultCode()); |
| 893 EXPECT_EQ("request2:80", result2->GetProxyInfo().proxy_server().ToURI()); |
| 894 |
| 895 EXPECT_TRUE(result3->IsCompleted()); |
| 896 EXPECT_EQ(net::OK, result3->GetResultCode()); |
| 897 EXPECT_EQ("request3:80", result3->GetProxyInfo().proxy_server().ToURI()); |
| 898 } |
| 899 |
| 900 // Test the initial PAC download for ProxyResolverWithoutFetch. |
| 901 TEST(ProxyServiceTest, InitialPACScriptDownload) { |
| 902 MockProxyConfigService* config_service = |
| 903 new MockProxyConfigService("http://foopy/proxy.pac"); |
| 904 |
| 905 MockProxyResolverWithoutFetch* resolver = new MockProxyResolverWithoutFetch; |
| 906 |
| 907 ProxyServiceWithFutures service(config_service, resolver); |
| 908 |
| 909 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; |
| 910 service.SetProxyScriptFetcher(fetcher); |
| 911 |
| 912 // Start 3 requests. |
| 913 scoped_refptr<ResultFuture> result1; |
| 914 service.ResolveProxy(&result1, GURL("http://request1")); |
| 915 |
| 916 scoped_refptr<ResultFuture> result2; |
| 917 service.ResolveProxy(&result2, GURL("http://request2")); |
| 918 |
| 919 scoped_refptr<ResultFuture> result3; |
| 920 service.ResolveProxy(&result3, GURL("http://request3")); |
| 921 |
| 922 // At this point the ProxyService should be waiting for the |
| 923 // ProxyScriptFetcher to invoke its completion callback, notifying it of |
| 924 // PAC script download completion. |
| 925 fetcher->NotifyFetchCompletion(net::OK, "pac-v1"); |
| 926 |
| 927 // Complete all the requests. |
| 928 result3->WaitUntilCompleted(); |
| 929 |
| 930 EXPECT_TRUE(result1->IsCompleted()); |
| 931 EXPECT_EQ(net::OK, result1->GetResultCode()); |
| 932 EXPECT_EQ("pac-v1.request1:80", |
| 933 result1->GetProxyInfo().proxy_server().ToURI()); |
| 934 |
| 935 EXPECT_TRUE(result2->IsCompleted()); |
| 936 EXPECT_EQ(net::OK, result2->GetResultCode()); |
| 937 EXPECT_EQ("pac-v1.request2:80", |
| 938 result2->GetProxyInfo().proxy_server().ToURI()); |
| 939 |
| 940 EXPECT_TRUE(result3->IsCompleted()); |
| 941 EXPECT_EQ(net::OK, result3->GetResultCode()); |
| 942 EXPECT_EQ("pac-v1.request3:80", |
| 943 result3->GetProxyInfo().proxy_server().ToURI()); |
| 944 } |
| 945 |
| 946 // Test cancellation of a request, while the PAC script is being fetched. |
| 947 TEST(ProxyServiceTest, CancelWhilePACFetching) { |
| 948 MockProxyConfigService* config_service = |
| 949 new MockProxyConfigService("http://foopy/proxy.pac"); |
| 950 |
| 951 MockProxyResolverWithoutFetch* resolver = new MockProxyResolverWithoutFetch; |
| 952 |
| 953 ProxyServiceWithFutures service(config_service, resolver); |
| 954 |
| 955 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; |
| 956 service.SetProxyScriptFetcher(fetcher); |
| 957 |
| 958 // Start 3 requests. |
| 959 scoped_refptr<ResultFuture> result1; |
| 960 service.ResolveProxy(&result1, GURL("http://request1")); |
| 961 |
| 962 scoped_refptr<ResultFuture> result2; |
| 963 service.ResolveProxy(&result2, GURL("http://request2")); |
| 964 |
| 965 scoped_refptr<ResultFuture> result3; |
| 966 service.ResolveProxy(&result3, GURL("http://request3")); |
| 967 |
| 968 // Cancel the first 2 requests. |
| 969 result1->Cancel(); |
| 970 result2->Cancel(); |
| 971 |
| 972 // At this point the ProxyService should be waiting for the |
| 973 // ProxyScriptFetcher to invoke its completion callback, notifying it of |
| 974 // PAC script download completion. |
| 975 fetcher->NotifyFetchCompletion(net::OK, "pac-v1"); |
| 976 |
| 977 // Complete all the requests. |
| 978 result3->WaitUntilCompleted(); |
| 979 |
| 980 EXPECT_FALSE(result1->IsCompleted()); // Cancelled. |
| 981 EXPECT_FALSE(result2->IsCompleted()); // Cancelled. |
| 982 |
| 983 EXPECT_TRUE(result3->IsCompleted()); |
| 984 EXPECT_EQ(net::OK, result3->GetResultCode()); |
| 985 EXPECT_EQ("pac-v1.request3:80", |
| 986 result3->GetProxyInfo().proxy_server().ToURI()); |
| 987 } |
| 988 |
| OLD | NEW |