| 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 <vector> |
| 6 |
| 7 #include "base/logging.h" |
| 6 #include "googleurl/src/gurl.h" | 8 #include "googleurl/src/gurl.h" |
| 7 #include "net/base/net_errors.h" | 9 #include "net/base/net_errors.h" |
| 10 #include "net/base/test_completion_callback.h" |
| 8 #include "net/proxy/proxy_config_service.h" | 11 #include "net/proxy/proxy_config_service.h" |
| 9 #include "net/proxy/proxy_resolver.h" | 12 #include "net/proxy/proxy_resolver.h" |
| 10 #include "net/proxy/proxy_script_fetcher.h" | 13 #include "net/proxy/proxy_script_fetcher.h" |
| 11 #include "net/proxy/proxy_service.h" | 14 #include "net/proxy/proxy_service.h" |
| 12 #include "net/proxy/single_threaded_proxy_resolver.h" | |
| 13 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
| 14 | 16 |
| 15 namespace { | 17 namespace { |
| 16 | 18 |
| 17 class MockProxyConfigService: public net::ProxyConfigService { | 19 class MockProxyConfigService: public net::ProxyConfigService { |
| 18 public: | 20 public: |
| 19 MockProxyConfigService() {} // Direct connect. | 21 MockProxyConfigService() {} // Direct connect. |
| 20 explicit MockProxyConfigService(const net::ProxyConfig& pc) : config(pc) {} | 22 explicit MockProxyConfigService(const net::ProxyConfig& pc) : config(pc) {} |
| 21 explicit MockProxyConfigService(const std::string& pac_url) { | 23 explicit MockProxyConfigService(const std::string& pac_url) { |
| 22 config.pac_url = GURL(pac_url); | 24 config.pac_url = GURL(pac_url); |
| 23 } | 25 } |
| 24 | 26 |
| 25 virtual int GetProxyConfig(net::ProxyConfig* results) { | 27 virtual int GetProxyConfig(net::ProxyConfig* results) { |
| 26 *results = config; | 28 *results = config; |
| 27 return net::OK; | 29 return net::OK; |
| 28 } | 30 } |
| 29 | 31 |
| 30 net::ProxyConfig config; | 32 net::ProxyConfig config; |
| 31 }; | 33 }; |
| 32 | 34 |
| 33 class SyncMockProxyResolver : public net::ProxyResolver { | 35 // Asynchronous mock proxy resolver. All requests complete asynchronously, |
| 36 // user must call Request::CompleteNow() on a pending request to signal it. |
| 37 class MockAsyncProxyResolverBase : public net::ProxyResolver { |
| 34 public: | 38 public: |
| 35 SyncMockProxyResolver() : net::ProxyResolver(false /*expects_pac_bytes*/), | 39 class Request : public base::RefCounted<Request> { |
| 36 fail_get_proxy_for_url(false) { | 40 public: |
| 41 Request(MockAsyncProxyResolverBase* resolver, |
| 42 const GURL& url, |
| 43 net::ProxyInfo* results, |
| 44 net::CompletionCallback* callback) |
| 45 : resolver_(resolver), |
| 46 url_(url), |
| 47 results_(results), |
| 48 callback_(callback), |
| 49 origin_loop_(MessageLoop::current()) { |
| 50 } |
| 51 |
| 52 const GURL& url() const { return url_; } |
| 53 net::ProxyInfo* results() const { return results_; } |
| 54 net::CompletionCallback* callback() const { return callback_; } |
| 55 |
| 56 void CompleteNow(int rv) { |
| 57 net::CompletionCallback* callback = callback_; |
| 58 |
| 59 // May delete |this|. |
| 60 resolver_->RemovePendingRequest(this); |
| 61 |
| 62 callback->Run(rv); |
| 63 } |
| 64 |
| 65 private: |
| 66 MockAsyncProxyResolverBase* resolver_; |
| 67 const GURL url_; |
| 68 net::ProxyInfo* results_; |
| 69 net::CompletionCallback* callback_; |
| 70 MessageLoop* origin_loop_; |
| 71 }; |
| 72 |
| 73 typedef std::vector<scoped_refptr<Request> > RequestsList; |
| 74 |
| 75 // ProxyResolver implementation: |
| 76 virtual int GetProxyForURL(const GURL& url, |
| 77 net::ProxyInfo* results, |
| 78 net::CompletionCallback* callback, |
| 79 RequestHandle* request_handle) { |
| 80 scoped_refptr<Request> request = new Request(this, url, results, callback); |
| 81 pending_requests_.push_back(request); |
| 82 |
| 83 if (request_handle) |
| 84 *request_handle = reinterpret_cast<RequestHandle>(request.get()); |
| 85 |
| 86 // Test code completes the request by calling request->CompleteNow(). |
| 87 return net::ERR_IO_PENDING; |
| 37 } | 88 } |
| 38 | 89 |
| 39 // ProxyResolver implementation: | 90 virtual void CancelRequest(RequestHandle request_handle) { |
| 40 virtual int GetProxyForURL(const GURL& query_url, | 91 scoped_refptr<Request> request = reinterpret_cast<Request*>(request_handle); |
| 41 net::ProxyInfo* results, | 92 cancelled_requests_.push_back(request); |
| 42 net::CompletionCallback* callback, | 93 RemovePendingRequest(request); |
| 43 RequestHandle* request) { | |
| 44 if (fail_get_proxy_for_url) | |
| 45 return net::ERR_FAILED; | |
| 46 if (GURL(query_url).host() == info_predicate_query_host) { | |
| 47 results->Use(info); | |
| 48 } else { | |
| 49 results->UseDirect(); | |
| 50 } | |
| 51 return net::OK; | |
| 52 } | 94 } |
| 53 | 95 |
| 54 virtual void CancelRequest(RequestHandle request) { | 96 virtual void SetPacScriptByUrlInternal(const GURL& pac_url) { |
| 55 NOTREACHED(); | 97 pac_url_ = pac_url; |
| 56 } | |
| 57 | |
| 58 virtual void SetPacScriptByUrlInternal(const GURL& pac_url) {} | |
| 59 | |
| 60 | |
| 61 net::ProxyInfo info; | |
| 62 | |
| 63 // info is only returned if query_url in GetProxyForURL matches this: | |
| 64 std::string info_predicate_query_host; | |
| 65 | |
| 66 // If true, then GetProxyForURL will fail, which simulates failure to | |
| 67 // download or execute the PAC file. | |
| 68 bool fail_get_proxy_for_url; | |
| 69 }; | |
| 70 | |
| 71 class MockProxyResolver : public net::SingleThreadedProxyResolver { | |
| 72 public: | |
| 73 MockProxyResolver() | |
| 74 : net::SingleThreadedProxyResolver(new SyncMockProxyResolver) { | |
| 75 x = reinterpret_cast<SyncMockProxyResolver*>(resolver()); | |
| 76 } | |
| 77 | |
| 78 // TODO(eroman): cleanup. | |
| 79 SyncMockProxyResolver* x; | |
| 80 }; | |
| 81 | |
| 82 // ResultFuture is a handle to get at the result from | |
| 83 // ProxyService::ResolveProxyForURL() that ran on another thread. | |
| 84 class ResultFuture : public base::RefCountedThreadSafe<ResultFuture> { | |
| 85 public: | |
| 86 // |service| is the ProxyService to issue requests on, and |io_message_loop| | |
| 87 // is the message loop where ProxyService lives. | |
| 88 ResultFuture(MessageLoop* io_message_loop, | |
| 89 net::ProxyService* service) | |
| 90 : io_message_loop_(io_message_loop), | |
| 91 service_(service), | |
| 92 request_(NULL), | |
| 93 ALLOW_THIS_IN_INITIALIZER_LIST( | |
| 94 callback_(this, &ResultFuture::OnCompletion)), | |
| 95 completion_(true, false), | |
| 96 cancelled_(false, false), | |
| 97 started_(false, false), | |
| 98 did_complete_(false) { | |
| 99 } | |
| 100 | |
| 101 // Block until the request has completed, then return the result. | |
| 102 int GetResultCode() { | |
| 103 DCHECK(MessageLoop::current() != io_message_loop_); | |
| 104 WaitUntilCompleted(); | |
| 105 return result_code_; | |
| 106 } | |
| 107 | |
| 108 // Block until the request has completed, then return the result. | |
| 109 const net::ProxyInfo& GetProxyInfo() { | |
| 110 DCHECK(MessageLoop::current() != io_message_loop_); | |
| 111 WaitUntilCompleted(); | |
| 112 return proxy_info_; | |
| 113 } | |
| 114 | |
| 115 // Cancel this request (wait until the cancel has been issued before | |
| 116 // returning). | |
| 117 void Cancel() { | |
| 118 DCHECK(MessageLoop::current() != io_message_loop_); | |
| 119 io_message_loop_->PostTask(FROM_HERE, NewRunnableMethod( | |
| 120 this, &ResultFuture::DoCancel)); | |
| 121 cancelled_.Wait(); | |
| 122 } | |
| 123 | |
| 124 // Return true if the request has already completed. | |
| 125 bool IsCompleted() { | |
| 126 DCHECK(MessageLoop::current() != io_message_loop_); | |
| 127 return did_complete_; | |
| 128 } | |
| 129 | |
| 130 // Wait until the ProxyService completes this request. | |
| 131 void WaitUntilCompleted() { | |
| 132 DCHECK(MessageLoop::current() != io_message_loop_); | |
| 133 completion_.Wait(); | |
| 134 DCHECK(did_complete_); | |
| 135 } | |
| 136 | |
| 137 private: | |
| 138 friend class ProxyServiceWithFutures; | |
| 139 | |
| 140 typedef int (net::ProxyService::*RequestMethod)(const GURL&, net::ProxyInfo*, | |
| 141 net::CompletionCallback*, net::ProxyService::PacRequest**); | |
| 142 | |
| 143 void StartResolve(const GURL& url) { | |
| 144 StartRequest(url, &net::ProxyService::ResolveProxy); | |
| 145 } | |
| 146 | |
| 147 // |proxy_info| is the *previous* result (that we are reconsidering). | |
| 148 void StartReconsider(const GURL& url, const net::ProxyInfo& proxy_info) { | |
| 149 proxy_info_ = proxy_info; | |
| 150 StartRequest(url, &net::ProxyService::ReconsiderProxyAfterError); | |
| 151 } | |
| 152 | |
| 153 // Start the request. Return once ProxyService::GetProxyForURL() or | |
| 154 // ProxyService::ReconsiderProxyAfterError() returns. | |
| 155 void StartRequest(const GURL& url, RequestMethod method) { | |
| 156 DCHECK(MessageLoop::current() != io_message_loop_); | |
| 157 io_message_loop_->PostTask(FROM_HERE, NewRunnableMethod( | |
| 158 this, &ResultFuture::DoStartRequest, url, method)); | |
| 159 started_.Wait(); | |
| 160 } | |
| 161 | |
| 162 void StartResetConfigService( | |
| 163 net::ProxyConfigService* new_proxy_config_service) { | |
| 164 DCHECK(MessageLoop::current() != io_message_loop_); | |
| 165 io_message_loop_->PostTask(FROM_HERE, NewRunnableMethod( | |
| 166 this, &ResultFuture::DoResetConfigService, new_proxy_config_service)); | |
| 167 started_.Wait(); | |
| 168 } | |
| 169 | |
| 170 // Called on |io_message_loop_|. | |
| 171 void DoStartRequest(const GURL& url, RequestMethod method) { | |
| 172 DCHECK(MessageLoop::current() == io_message_loop_); | |
| 173 int rv = (service_->*method)(url, &proxy_info_, &callback_, &request_); | |
| 174 if (rv != net::ERR_IO_PENDING) { | |
| 175 // Completed synchronously. | |
| 176 OnCompletion(rv); | |
| 177 } | |
| 178 started_.Signal(); | |
| 179 } | |
| 180 | |
| 181 // Called on |io_message_loop_|. | |
| 182 void DoResetConfigService(net::ProxyConfigService* new_proxy_config_service) { | |
| 183 DCHECK(MessageLoop::current() == io_message_loop_); | |
| 184 service_->ResetConfigService(new_proxy_config_service); | |
| 185 started_.Signal(); | |
| 186 OnCompletion(0); | |
| 187 } | |
| 188 | |
| 189 // Called on |io_message_loop_|. | |
| 190 void DoCancel() { | |
| 191 DCHECK(MessageLoop::current() == io_message_loop_); | |
| 192 if (!did_complete_) | |
| 193 service_->CancelPacRequest(request_); | |
| 194 cancelled_.Signal(); | |
| 195 } | |
| 196 | |
| 197 // Called on |io_message_loop_|. | |
| 198 void OnCompletion(int result) { | |
| 199 DCHECK(MessageLoop::current() == io_message_loop_); | |
| 200 DCHECK(!did_complete_); | |
| 201 did_complete_ = true; | |
| 202 result_code_ = result; | |
| 203 request_ = NULL; | |
| 204 completion_.Signal(); | |
| 205 } | |
| 206 | |
| 207 // The message loop where the ProxyService lives. | |
| 208 MessageLoop* io_message_loop_; | |
| 209 | |
| 210 // The proxy service that started this request. | |
| 211 net::ProxyService* service_; | |
| 212 | |
| 213 // The in-progress request. | |
| 214 net::ProxyService::PacRequest* request_; | |
| 215 | |
| 216 net::CompletionCallbackImpl<ResultFuture> callback_; | |
| 217 base::WaitableEvent completion_; | |
| 218 base::WaitableEvent cancelled_; | |
| 219 base::WaitableEvent started_; | |
| 220 bool did_complete_; | |
| 221 | |
| 222 // Results from the request. | |
| 223 int result_code_; | |
| 224 net::ProxyInfo proxy_info_; | |
| 225 }; | |
| 226 | |
| 227 // Wraps a ProxyService running on its own IO thread. | |
| 228 class ProxyServiceWithFutures { | |
| 229 public: | |
| 230 ProxyServiceWithFutures(net::ProxyConfigService* config_service, | |
| 231 net::ProxyResolver* resolver) | |
| 232 : io_thread_("IO_Thread"), | |
| 233 io_thread_state_(new IOThreadState) { | |
| 234 base::Thread::Options options; | |
| 235 options.message_loop_type = MessageLoop::TYPE_IO; | |
| 236 io_thread_.StartWithOptions(options); | |
| 237 | |
| 238 // Initialize state that lives on |io_thread_|. | |
| 239 io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | |
| 240 io_thread_state_.get(), &IOThreadState::DoInit, | |
| 241 config_service, resolver)); | |
| 242 io_thread_state_->event.Wait(); | |
| 243 } | |
| 244 | |
| 245 ~ProxyServiceWithFutures() { | |
| 246 // Destroy state that lives on |io_thread_|. | |
| 247 io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | |
| 248 io_thread_state_.get(), &IOThreadState::DoDestroy)); | |
| 249 io_thread_state_->event.Wait(); | |
| 250 } | |
| 251 | |
| 252 // Start the request on |io_thread_|, and return a handle that can be | |
| 253 // used to access the results. The caller is responsible for freeing | |
| 254 // the ResultFuture. | |
| 255 void ResolveProxy(scoped_refptr<ResultFuture>* result, const GURL& url) { | |
| 256 *result = new ResultFuture(io_thread_.message_loop(), | |
| 257 io_thread_state_->service); | |
| 258 (*result)->StartResolve(url); | |
| 259 } | |
| 260 | |
| 261 // Same as above, but for "ReconsiderProxyAfterError()". | |
| 262 void ReconsiderProxyAfterError(scoped_refptr<ResultFuture>* result, | |
| 263 const GURL& url, | |
| 264 const net::ProxyInfo& proxy_info) { | |
| 265 *result = new ResultFuture(io_thread_.message_loop(), | |
| 266 io_thread_state_->service); | |
| 267 (*result)->StartReconsider(url, proxy_info); | |
| 268 } | |
| 269 | |
| 270 void ResetConfigService(scoped_refptr<ResultFuture>* result, | |
| 271 net::ProxyConfigService* new_proxy_config_service) { | |
| 272 *result = new ResultFuture(io_thread_.message_loop(), | |
| 273 io_thread_state_->service); | |
| 274 (*result)->StartResetConfigService(new_proxy_config_service); | |
| 275 } | |
| 276 | |
| 277 void SetProxyScriptFetcher(net::ProxyScriptFetcher* proxy_script_fetcher) { | |
| 278 io_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | |
| 279 io_thread_state_.get(), &IOThreadState::DoSetProxyScriptFetcher, | |
| 280 proxy_script_fetcher)); | |
| 281 io_thread_state_->event.Wait(); | |
| 282 } | |
| 283 | |
| 284 private: | |
| 285 // Class that encapsulates the state living on IO thread. It needs to be | |
| 286 // ref-counted for posting tasks. | |
| 287 class IOThreadState : public base::RefCountedThreadSafe<IOThreadState> { | |
| 288 public: | |
| 289 IOThreadState() : event(false, false), service(NULL) {} | |
| 290 | |
| 291 void DoInit(net::ProxyConfigService* config_service, | |
| 292 net::ProxyResolver* resolver) { | |
| 293 service = new net::ProxyService(config_service, resolver); | |
| 294 event.Signal(); | |
| 295 } | |
| 296 | |
| 297 void DoDestroy() { | |
| 298 delete service; | |
| 299 service = NULL; | |
| 300 event.Signal(); | |
| 301 } | |
| 302 | |
| 303 void DoSetProxyScriptFetcher( | |
| 304 net::ProxyScriptFetcher* proxy_script_fetcher) { | |
| 305 service->SetProxyScriptFetcher(proxy_script_fetcher); | |
| 306 event.Signal(); | |
| 307 } | |
| 308 | |
| 309 base::WaitableEvent event; | |
| 310 net::ProxyService* service; | |
| 311 }; | |
| 312 | |
| 313 base::Thread io_thread_; | |
| 314 scoped_refptr<IOThreadState> io_thread_state_; // Lives on |io_thread_|. | |
| 315 }; | |
| 316 | |
| 317 // Wrapper around ProxyServiceWithFutures to do one request at a time. | |
| 318 class SyncProxyService { | |
| 319 public: | |
| 320 SyncProxyService(net::ProxyConfigService* config_service, | |
| 321 net::ProxyResolver* resolver) | |
| 322 : service_(config_service, resolver) { | |
| 323 } | |
| 324 | |
| 325 int ResolveProxy(const GURL& url, net::ProxyInfo* proxy_info) { | |
| 326 scoped_refptr<ResultFuture> result; | |
| 327 service_.ResolveProxy(&result, url); | |
| 328 *proxy_info = result->GetProxyInfo(); | |
| 329 return result->GetResultCode(); | |
| 330 } | |
| 331 | |
| 332 int ReconsiderProxyAfterError(const GURL& url, net::ProxyInfo* proxy_info) { | |
| 333 scoped_refptr<ResultFuture> result; | |
| 334 service_.ReconsiderProxyAfterError(&result, url, *proxy_info); | |
| 335 *proxy_info = result->GetProxyInfo(); | |
| 336 return result->GetResultCode(); | |
| 337 } | |
| 338 | |
| 339 int ResetConfigService(net::ProxyConfigService* new_proxy_config_service) { | |
| 340 scoped_refptr<ResultFuture> result; | |
| 341 service_.ResetConfigService(&result, new_proxy_config_service); | |
| 342 return result->GetResultCode(); | |
| 343 } | |
| 344 | |
| 345 private: | |
| 346 ProxyServiceWithFutures service_; | |
| 347 }; | |
| 348 | |
| 349 // A ProxyResolver which can be set to block upon reaching GetProxyForURL. | |
| 350 class SyncBlockableProxyResolver : public net::ProxyResolver { | |
| 351 public: | |
| 352 SyncBlockableProxyResolver() | |
| 353 : net::ProxyResolver(false /*expects_pac_bytes*/), | |
| 354 should_block_(false), | |
| 355 unblocked_(true, true), | |
| 356 blocked_(true, false) { | |
| 357 } | |
| 358 | |
| 359 void Block() { | |
| 360 should_block_ = true; | |
| 361 unblocked_.Reset(); | |
| 362 } | |
| 363 | |
| 364 void Unblock() { | |
| 365 should_block_ = false; | |
| 366 blocked_.Reset(); | |
| 367 unblocked_.Signal(); | |
| 368 } | |
| 369 | |
| 370 void WaitUntilBlocked() { | |
| 371 blocked_.Wait(); | |
| 372 } | |
| 373 | |
| 374 // net::ProxyResolver implementation: | |
| 375 virtual int GetProxyForURL(const GURL& query_url, | |
| 376 net::ProxyInfo* results, | |
| 377 net::CompletionCallback* callback, | |
| 378 RequestHandle* request) { | |
| 379 if (should_block_) { | |
| 380 blocked_.Signal(); | |
| 381 unblocked_.Wait(); | |
| 382 } | |
| 383 | |
| 384 results->UseNamedProxy(query_url.host()); | |
| 385 return net::OK; | |
| 386 } | |
| 387 | |
| 388 virtual void CancelRequest(RequestHandle request) { | |
| 389 NOTREACHED(); | |
| 390 } | |
| 391 | |
| 392 virtual void SetPacScriptByUrlInternal(const GURL& pac_url) {} | |
| 393 | |
| 394 private: | |
| 395 bool should_block_; | |
| 396 base::WaitableEvent unblocked_; | |
| 397 base::WaitableEvent blocked_; | |
| 398 }; | |
| 399 | |
| 400 class BlockableProxyResolver : public net::SingleThreadedProxyResolver { | |
| 401 public: | |
| 402 BlockableProxyResolver() | |
| 403 : net::SingleThreadedProxyResolver(new SyncBlockableProxyResolver) { | |
| 404 x = reinterpret_cast<SyncBlockableProxyResolver*>(resolver()); | |
| 405 } | |
| 406 | |
| 407 // TODO(eroman): cleanup. | |
| 408 SyncBlockableProxyResolver* x; | |
| 409 }; | |
| 410 | |
| 411 // A mock ProxyResolverWithoutFetch which concatenates the query's host with | |
| 412 // the last download PAC contents. This way the result describes what the last | |
| 413 // downloaded PAC script's contents were, in addition to the query url itself. | |
| 414 class SyncMockProxyResolverWithoutFetch : public net::ProxyResolver { | |
| 415 public: | |
| 416 SyncMockProxyResolverWithoutFetch() | |
| 417 : net::ProxyResolver(true /*expects_pac_bytes*/), | |
| 418 last_pac_contents_("NONE") {} | |
| 419 | |
| 420 // net::ProxyResolver implementation: | |
| 421 virtual int GetProxyForURL(const GURL& query_url, | |
| 422 net::ProxyInfo* results, | |
| 423 net::CompletionCallback* callback, | |
| 424 RequestHandle* request) { | |
| 425 results->UseNamedProxy(last_pac_contents_ + "." + query_url.host()); | |
| 426 return net::OK; | |
| 427 } | 98 } |
| 428 | 99 |
| 429 virtual void SetPacScriptByDataInternal(const std::string& bytes) { | 100 virtual void SetPacScriptByDataInternal(const std::string& bytes) { |
| 430 last_pac_contents_ = bytes; | 101 pac_bytes_ = bytes; |
| 431 } | 102 } |
| 432 | 103 |
| 433 virtual void CancelRequest(RequestHandle request) { | 104 const RequestsList& pending_requests() const { |
| 434 NOTREACHED(); | 105 return pending_requests_; |
| 435 } | 106 } |
| 436 | 107 |
| 108 const RequestsList& cancelled_requests() const { |
| 109 return cancelled_requests_; |
| 110 } |
| 111 |
| 112 const GURL& pac_url() const { |
| 113 return pac_url_; |
| 114 } |
| 115 |
| 116 const std::string& pac_bytes() const { |
| 117 return pac_bytes_; |
| 118 } |
| 119 |
| 120 void RemovePendingRequest(Request* request) { |
| 121 RequestsList::iterator it = std::find( |
| 122 pending_requests_.begin(), pending_requests_.end(), request); |
| 123 DCHECK(it != pending_requests_.end()); |
| 124 pending_requests_.erase(it); |
| 125 } |
| 126 |
| 127 protected: |
| 128 explicit MockAsyncProxyResolverBase(bool expects_pac_bytes) |
| 129 : net::ProxyResolver(expects_pac_bytes) {} |
| 130 |
| 437 private: | 131 private: |
| 438 std::string last_pac_contents_; | 132 RequestsList pending_requests_; |
| 133 RequestsList cancelled_requests_; |
| 134 GURL pac_url_; |
| 135 std::string pac_bytes_; |
| 439 }; | 136 }; |
| 440 | 137 |
| 441 class MockProxyResolverWithoutFetch : public net::SingleThreadedProxyResolver { | 138 class MockAsyncProxyResolver : public MockAsyncProxyResolverBase { |
| 442 public: | 139 public: |
| 443 MockProxyResolverWithoutFetch() | 140 MockAsyncProxyResolver() |
| 444 : net::SingleThreadedProxyResolver( | 141 : MockAsyncProxyResolverBase(false /*expects_pac_bytes*/) {} |
| 445 new SyncMockProxyResolverWithoutFetch) { | |
| 446 x = reinterpret_cast<SyncMockProxyResolverWithoutFetch*>(resolver()); | |
| 447 } | |
| 448 | |
| 449 // TODO(eroman): cleanup. | |
| 450 SyncMockProxyResolverWithoutFetch* x; | |
| 451 }; | 142 }; |
| 452 | 143 |
| 144 class MockAsyncProxyResolverExpectsBytes : public MockAsyncProxyResolverBase { |
| 145 public: |
| 146 MockAsyncProxyResolverExpectsBytes() |
| 147 : MockAsyncProxyResolverBase(true /*expects_pac_bytes*/) {} |
| 148 }; |
| 453 | 149 |
| 454 } // namespace | 150 } // namespace |
| 455 | 151 |
| 456 // A mock ProxyScriptFetcher. No result will be returned to the fetch client | 152 // A mock ProxyScriptFetcher. No result will be returned to the fetch client |
| 457 // until we call NotifyFetchCompletion() to set the results. | 153 // until we call NotifyFetchCompletion() to set the results. |
| 458 class MockProxyScriptFetcher : public net::ProxyScriptFetcher { | 154 class MockProxyScriptFetcher : public net::ProxyScriptFetcher { |
| 459 public: | 155 public: |
| 460 MockProxyScriptFetcher() : pending_request_loop_(NULL), | 156 MockProxyScriptFetcher() |
| 461 pending_request_callback_(NULL), pending_request_bytes_(NULL) {} | 157 : pending_request_callback_(NULL), pending_request_bytes_(NULL) { |
| 158 } |
| 462 | 159 |
| 463 // net::ProxyScriptFetcher implementation. | 160 // net::ProxyScriptFetcher implementation. |
| 464 virtual void Fetch(const GURL& url, std::string* bytes, | 161 virtual void Fetch(const GURL& url, |
| 162 std::string* bytes, |
| 465 net::CompletionCallback* callback) { | 163 net::CompletionCallback* callback) { |
| 466 DCHECK(!HasPendingRequest()); | 164 DCHECK(!has_pending_request()); |
| 467 | 165 |
| 468 // Save the caller's information, and have them wait. | 166 // Save the caller's information, and have them wait. |
| 469 pending_request_loop_ = MessageLoop::current(); | |
| 470 pending_request_url_ = url; | 167 pending_request_url_ = url; |
| 471 pending_request_callback_ = callback; | 168 pending_request_callback_ = callback; |
| 472 pending_request_bytes_ = bytes; | 169 pending_request_bytes_ = bytes; |
| 473 } | 170 } |
| 474 | 171 |
| 475 void NotifyFetchCompletion(int result, const std::string& bytes) { | 172 void NotifyFetchCompletion(int result, const std::string& bytes) { |
| 476 DCHECK(HasPendingRequest()); | 173 DCHECK(has_pending_request()); |
| 477 pending_request_loop_->PostTask(FROM_HERE, NewRunnableMethod( | 174 *pending_request_bytes_ = bytes; |
| 478 this, &MockProxyScriptFetcher::DoNotifyFetchCompletion, result, bytes)); | 175 pending_request_callback_->Run(result); |
| 479 } | 176 } |
| 480 | 177 |
| 481 virtual void Cancel() {} | 178 virtual void Cancel() {} |
| 482 | 179 |
| 483 private: | 180 const GURL& pending_request_url() const { |
| 484 // Runs on |pending_request_loop_|. | 181 return pending_request_url_; |
| 485 void DoNotifyFetchCompletion(int result, const std::string& bytes) { | |
| 486 DCHECK(HasPendingRequest()); | |
| 487 *pending_request_bytes_ = bytes; | |
| 488 pending_request_callback_->Run(result); | |
| 489 } | 182 } |
| 490 | 183 |
| 491 bool HasPendingRequest() const { | 184 bool has_pending_request() const { |
| 492 return pending_request_loop_ != NULL; | 185 return pending_request_callback_ != NULL; |
| 493 } | 186 } |
| 494 | 187 |
| 495 MessageLoop* pending_request_loop_; | 188 private: |
| 496 GURL pending_request_url_; | 189 GURL pending_request_url_; |
| 497 net::CompletionCallback* pending_request_callback_; | 190 net::CompletionCallback* pending_request_callback_; |
| 498 std::string* pending_request_bytes_; | 191 std::string* pending_request_bytes_; |
| 499 }; | 192 }; |
| 500 | 193 |
| 501 // Template specialization so MockProxyScriptFetcher does not have to be | 194 // Template specialization so MockProxyScriptFetcher does not have to be |
| 502 // refcounted. | 195 // refcounted. |
| 503 template<> | 196 template<> |
| 504 void RunnableMethodTraits<MockProxyScriptFetcher>::RetainCallee( | 197 void RunnableMethodTraits<MockProxyScriptFetcher>::RetainCallee( |
| 505 MockProxyScriptFetcher* remover) {} | 198 MockProxyScriptFetcher* remover) {} |
| 506 template<> | 199 template<> |
| 507 void RunnableMethodTraits<MockProxyScriptFetcher>::ReleaseCallee( | 200 void RunnableMethodTraits<MockProxyScriptFetcher>::ReleaseCallee( |
| 508 MockProxyScriptFetcher* remover) {} | 201 MockProxyScriptFetcher* remover) {} |
| 509 | 202 |
| 510 TEST(ProxyServiceTest, Direct) { | 203 TEST(ProxyServiceTest, Direct) { |
| 511 SyncProxyService service(new MockProxyConfigService, | 204 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; |
| 512 new MockProxyResolver); | 205 net::ProxyService service(new MockProxyConfigService, resolver); |
| 513 | 206 |
| 514 GURL url("http://www.google.com/"); | 207 GURL url("http://www.google.com/"); |
| 515 | 208 |
| 516 net::ProxyInfo info; | 209 net::ProxyInfo info; |
| 517 int rv = service.ResolveProxy(url, &info); | 210 TestCompletionCallback callback; |
| 518 EXPECT_EQ(rv, net::OK); | 211 int rv = service.ResolveProxy(url, &info, &callback, NULL); |
| 212 EXPECT_EQ(net::OK, rv); |
| 213 EXPECT_TRUE(resolver->pending_requests().empty()); |
| 214 |
| 519 EXPECT_TRUE(info.is_direct()); | 215 EXPECT_TRUE(info.is_direct()); |
| 520 } | 216 } |
| 521 | 217 |
| 522 TEST(ProxyServiceTest, PAC) { | 218 TEST(ProxyServiceTest, PAC) { |
| 523 MockProxyConfigService* config_service = | 219 MockProxyConfigService* config_service = |
| 524 new MockProxyConfigService("http://foopy/proxy.pac"); | 220 new MockProxyConfigService("http://foopy/proxy.pac"); |
| 525 | 221 |
| 526 MockProxyResolver* resolver = new MockProxyResolver; | 222 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; |
| 527 resolver->x->info.UseNamedProxy("foopy"); | |
| 528 resolver->x->info_predicate_query_host = "www.google.com"; | |
| 529 | 223 |
| 530 SyncProxyService service(config_service, resolver); | 224 net::ProxyService service(config_service, resolver); |
| 531 | 225 |
| 532 GURL url("http://www.google.com/"); | 226 GURL url("http://www.google.com/"); |
| 533 | 227 |
| 534 net::ProxyInfo info; | 228 net::ProxyInfo info; |
| 535 int rv = service.ResolveProxy(url, &info); | 229 TestCompletionCallback callback; |
| 536 EXPECT_EQ(rv, net::OK); | 230 int rv = service.ResolveProxy(url, &info, &callback, NULL); |
| 231 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 232 |
| 233 EXPECT_EQ(GURL("http://foopy/proxy.pac"), resolver->pac_url()); |
| 234 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 235 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); |
| 236 |
| 237 // Set the result in proxy resolver. |
| 238 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy"); |
| 239 resolver->pending_requests()[0]->CompleteNow(net::OK); |
| 240 |
| 241 EXPECT_EQ(net::OK, callback.WaitForResult()); |
| 537 EXPECT_FALSE(info.is_direct()); | 242 EXPECT_FALSE(info.is_direct()); |
| 538 EXPECT_EQ("foopy:80", info.proxy_server().ToURI()); | 243 EXPECT_EQ("foopy:80", info.proxy_server().ToURI()); |
| 539 } | 244 } |
| 540 | 245 |
| 541 TEST(ProxyServiceTest, PAC_FailoverToDirect) { | 246 TEST(ProxyServiceTest, PAC_FailoverToDirect) { |
| 542 MockProxyConfigService* config_service = | 247 MockProxyConfigService* config_service = |
| 543 new MockProxyConfigService("http://foopy/proxy.pac"); | 248 new MockProxyConfigService("http://foopy/proxy.pac"); |
| 249 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; |
| 544 | 250 |
| 545 MockProxyResolver* resolver = new MockProxyResolver; | 251 net::ProxyService service(config_service, resolver); |
| 546 resolver->x->info.UseNamedProxy("foopy:8080"); | |
| 547 resolver->x->info_predicate_query_host = "www.google.com"; | |
| 548 | |
| 549 SyncProxyService service(config_service, resolver); | |
| 550 | 252 |
| 551 GURL url("http://www.google.com/"); | 253 GURL url("http://www.google.com/"); |
| 552 | 254 |
| 553 net::ProxyInfo info; | 255 net::ProxyInfo info; |
| 554 int rv = service.ResolveProxy(url, &info); | 256 TestCompletionCallback callback1; |
| 555 EXPECT_EQ(rv, net::OK); | 257 int rv = service.ResolveProxy(url, &info, &callback1, NULL); |
| 258 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 259 |
| 260 EXPECT_EQ(GURL("http://foopy/proxy.pac"), resolver->pac_url()); |
| 261 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 262 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); |
| 263 |
| 264 // Set the result in proxy resolver. |
| 265 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy:8080"); |
| 266 resolver->pending_requests()[0]->CompleteNow(net::OK); |
| 267 |
| 268 EXPECT_EQ(net::OK, callback1.WaitForResult()); |
| 556 EXPECT_FALSE(info.is_direct()); | 269 EXPECT_FALSE(info.is_direct()); |
| 557 EXPECT_EQ("foopy:8080", info.proxy_server().ToURI()); | 270 EXPECT_EQ("foopy:8080", info.proxy_server().ToURI()); |
| 558 | 271 |
| 559 // Now, imagine that connecting to foopy:8080 fails. | 272 // Now, imagine that connecting to foopy:8080 fails. |
| 560 rv = service.ReconsiderProxyAfterError(url, &info); | 273 TestCompletionCallback callback2; |
| 561 EXPECT_EQ(rv, net::OK); | 274 rv = service.ReconsiderProxyAfterError(url, &info, &callback2, NULL); |
| 275 EXPECT_EQ(net::OK, rv); |
| 562 EXPECT_TRUE(info.is_direct()); | 276 EXPECT_TRUE(info.is_direct()); |
| 563 } | 277 } |
| 564 | 278 |
| 565 TEST(ProxyServiceTest, PAC_FailsToDownload) { | 279 TEST(ProxyServiceTest, ProxyResolverFails) { |
| 566 // Test what happens when we fail to download the PAC URL. | 280 // Test what happens when the ProxyResolver fails (this could represent |
| 281 // a failure to download the PAC script in the case of ProxyResolvers which |
| 282 // do the fetch internally.) |
| 567 | 283 |
| 568 MockProxyConfigService* config_service = | 284 MockProxyConfigService* config_service = |
| 569 new MockProxyConfigService("http://foopy/proxy.pac"); | 285 new MockProxyConfigService("http://foopy/proxy.pac"); |
| 570 | 286 |
| 571 MockProxyResolver* resolver = new MockProxyResolver; | 287 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; |
| 572 resolver->x->info.UseNamedProxy("foopy:8080"); | |
| 573 resolver->x->info_predicate_query_host = "www.google.com"; | |
| 574 resolver->x->fail_get_proxy_for_url = true; | |
| 575 | 288 |
| 576 SyncProxyService service(config_service, resolver); | 289 net::ProxyService service(config_service, resolver); |
| 577 | 290 |
| 578 // The first resolve fails in the MockProxyResolver. | 291 // Start first resolve request. |
| 579 GURL url("http://www.google.com/"); | 292 GURL url("http://www.google.com/"); |
| 580 net::ProxyInfo info; | 293 net::ProxyInfo info; |
| 581 int rv = service.ResolveProxy(url, &info); | 294 TestCompletionCallback callback1; |
| 582 EXPECT_EQ(rv, net::ERR_FAILED); | 295 int rv = service.ResolveProxy(url, &info, &callback1, NULL); |
| 296 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 297 |
| 298 EXPECT_EQ(GURL("http://foopy/proxy.pac"), resolver->pac_url()); |
| 299 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 300 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); |
| 301 |
| 302 // Fail the first resolve request in MockAsyncProxyResolver. |
| 303 resolver->pending_requests()[0]->CompleteNow(net::ERR_FAILED); |
| 304 |
| 305 EXPECT_EQ(net::ERR_FAILED, callback1.WaitForResult()); |
| 583 | 306 |
| 584 // The second resolve request will automatically select direct connect, | 307 // The second resolve request will automatically select direct connect, |
| 585 // because it has cached the configuration as being bad. | 308 // because it has cached the configuration as being bad. |
| 586 rv = service.ResolveProxy(url, &info); | 309 TestCompletionCallback callback2; |
| 587 EXPECT_EQ(rv, net::OK); | 310 rv = service.ResolveProxy(url, &info, &callback2, NULL); |
| 311 EXPECT_EQ(net::OK, rv); |
| 588 EXPECT_TRUE(info.is_direct()); | 312 EXPECT_TRUE(info.is_direct()); |
| 589 | 313 EXPECT_TRUE(resolver->pending_requests().empty()); |
| 590 resolver->x->fail_get_proxy_for_url = false; | |
| 591 resolver->x->info.UseNamedProxy("foopy_valid:8080"); | |
| 592 | 314 |
| 593 // But, if that fails, then we should give the proxy config another shot | 315 // But, if that fails, then we should give the proxy config another shot |
| 594 // since we have never tried it with this URL before. | 316 // since we have never tried it with this URL before. |
| 595 rv = service.ReconsiderProxyAfterError(url, &info); | 317 TestCompletionCallback callback3; |
| 596 EXPECT_EQ(rv, net::OK); | 318 rv = service.ReconsiderProxyAfterError(url, &info, &callback3, NULL); |
| 319 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 320 |
| 321 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 322 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); |
| 323 |
| 324 // Set the result in proxy resolver. |
| 325 resolver->pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080"); |
| 326 resolver->pending_requests()[0]->CompleteNow(net::OK); |
| 327 |
| 328 EXPECT_EQ(net::OK, callback3.WaitForResult()); |
| 597 EXPECT_FALSE(info.is_direct()); | 329 EXPECT_FALSE(info.is_direct()); |
| 598 EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI()); | 330 EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI()); |
| 599 } | 331 } |
| 600 | 332 |
| 601 TEST(ProxyServiceTest, ProxyFallback) { | 333 TEST(ProxyServiceTest, ProxyFallback) { |
| 602 // Test what happens when we specify multiple proxy servers and some of them | 334 // Test what happens when we specify multiple proxy servers and some of them |
| 603 // are bad. | 335 // are bad. |
| 604 | 336 |
| 605 MockProxyConfigService* config_service = | 337 MockProxyConfigService* config_service = |
| 606 new MockProxyConfigService("http://foopy/proxy.pac"); | 338 new MockProxyConfigService("http://foopy/proxy.pac"); |
| 607 | 339 |
| 608 MockProxyResolver* resolver = new MockProxyResolver; | 340 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; |
| 609 resolver->x->info.UseNamedProxy("foopy1:8080;foopy2:9090"); | |
| 610 resolver->x->info_predicate_query_host = "www.google.com"; | |
| 611 resolver->x->fail_get_proxy_for_url = false; | |
| 612 | 341 |
| 613 SyncProxyService service(config_service, resolver); | 342 net::ProxyService service(config_service, resolver); |
| 614 | 343 |
| 615 GURL url("http://www.google.com/"); | 344 GURL url("http://www.google.com/"); |
| 616 | 345 |
| 617 // Get the proxy information. | 346 // Get the proxy information. |
| 618 net::ProxyInfo info; | 347 net::ProxyInfo info; |
| 619 int rv = service.ResolveProxy(url, &info); | 348 TestCompletionCallback callback1; |
| 620 EXPECT_EQ(rv, net::OK); | 349 int rv = service.ResolveProxy(url, &info, &callback1, NULL); |
| 621 EXPECT_FALSE(info.is_direct()); | 350 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 351 |
| 352 EXPECT_EQ(GURL("http://foopy/proxy.pac"), resolver->pac_url()); |
| 353 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 354 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); |
| 355 |
| 356 // Set the result in proxy resolver. |
| 357 resolver->pending_requests()[0]->results()->UseNamedProxy( |
| 358 "foopy1:8080;foopy2:9090"); |
| 359 resolver->pending_requests()[0]->CompleteNow(net::OK); |
| 622 | 360 |
| 623 // The first item is valid. | 361 // The first item is valid. |
| 362 EXPECT_EQ(net::OK, callback1.WaitForResult()); |
| 363 EXPECT_FALSE(info.is_direct()); |
| 624 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); | 364 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); |
| 625 | 365 |
| 626 // Fake an error on the proxy. | 366 // Fake an error on the proxy. |
| 627 rv = service.ReconsiderProxyAfterError(url, &info); | 367 TestCompletionCallback callback2; |
| 628 EXPECT_EQ(rv, net::OK); | 368 rv = service.ReconsiderProxyAfterError(url, &info, &callback2, NULL); |
| 369 EXPECT_EQ(net::OK, rv); |
| 629 | 370 |
| 630 // The second proxy should be specified. | 371 // The second proxy should be specified. |
| 631 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); | 372 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); |
| 632 | 373 |
| 633 // Create a new resolver that returns 3 proxies. The second one is already | 374 TestCompletionCallback callback3; |
| 634 // known to be bad. | 375 rv = service.ResolveProxy(url, &info, &callback3, NULL); |
| 635 config_service->config.pac_url = GURL("http://foopy/proxy.pac"); | 376 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 636 resolver->x->info.UseNamedProxy("foopy3:7070;foopy1:8080;foopy2:9090"); | |
| 637 resolver->x->info_predicate_query_host = "www.google.com"; | |
| 638 resolver->x->fail_get_proxy_for_url = false; | |
| 639 | 377 |
| 640 rv = service.ResolveProxy(url, &info); | 378 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 641 EXPECT_EQ(rv, net::OK); | 379 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); |
| 380 |
| 381 // Set the result in proxy resolver -- the second result is already known |
| 382 // to be bad. |
| 383 resolver->pending_requests()[0]->results()->UseNamedProxy( |
| 384 "foopy3:7070;foopy1:8080;foopy2:9090"); |
| 385 resolver->pending_requests()[0]->CompleteNow(net::OK); |
| 386 |
| 387 EXPECT_EQ(net::OK, callback3.WaitForResult()); |
| 642 EXPECT_FALSE(info.is_direct()); | 388 EXPECT_FALSE(info.is_direct()); |
| 643 EXPECT_EQ("foopy3:7070", info.proxy_server().ToURI()); | 389 EXPECT_EQ("foopy3:7070", info.proxy_server().ToURI()); |
| 644 | 390 |
| 645 // We fake another error. It should now try the third one. | 391 // We fake another error. It should now try the third one. |
| 646 rv = service.ReconsiderProxyAfterError(url, &info); | 392 TestCompletionCallback callback4; |
| 647 EXPECT_EQ(rv, net::OK); | 393 rv = service.ReconsiderProxyAfterError(url, &info, &callback4, NULL); |
| 394 EXPECT_EQ(net::OK, rv); |
| 648 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); | 395 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); |
| 649 | 396 |
| 650 // Fake another error, the last proxy is gone, the list should now be empty. | 397 // Fake another error, the last proxy is gone, the list should now be empty. |
| 651 rv = service.ReconsiderProxyAfterError(url, &info); | 398 TestCompletionCallback callback5; |
| 652 EXPECT_EQ(rv, net::OK); // We try direct. | 399 rv = service.ReconsiderProxyAfterError(url, &info, &callback5, NULL); |
| 400 EXPECT_EQ(net::OK, rv); // We try direct. |
| 653 EXPECT_TRUE(info.is_direct()); | 401 EXPECT_TRUE(info.is_direct()); |
| 654 | 402 |
| 655 // If it fails again, we don't have anything else to try. | 403 // If it fails again, we don't have anything else to try. |
| 656 rv = service.ReconsiderProxyAfterError(url, &info); | 404 TestCompletionCallback callback6; |
| 657 EXPECT_EQ(rv, net::ERR_FAILED); // We try direct. | 405 rv = service.ReconsiderProxyAfterError(url, &info, &callback6, NULL); |
| 406 EXPECT_EQ(net::ERR_FAILED, rv); |
| 658 | 407 |
| 659 // TODO(nsylvain): Test that the proxy can be retried after the delay. | 408 // TODO(nsylvain): Test that the proxy can be retried after the delay. |
| 660 } | 409 } |
| 661 | 410 |
| 662 TEST(ProxyServiceTest, ProxyFallback_NewSettings) { | 411 TEST(ProxyServiceTest, ProxyFallback_NewSettings) { |
| 663 // Test proxy failover when new settings are available. | 412 // Test proxy failover when new settings are available. |
| 664 | 413 |
| 665 MockProxyConfigService* config_service = | 414 MockProxyConfigService* config_service = |
| 666 new MockProxyConfigService("http://foopy/proxy.pac"); | 415 new MockProxyConfigService("http://foopy/proxy.pac"); |
| 667 | 416 |
| 668 MockProxyResolver* resolver = new MockProxyResolver; | 417 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; |
| 669 resolver->x->info.UseNamedProxy("foopy1:8080;foopy2:9090"); | |
| 670 resolver->x->info_predicate_query_host = "www.google.com"; | |
| 671 resolver->x->fail_get_proxy_for_url = false; | |
| 672 | 418 |
| 673 SyncProxyService service(config_service, resolver); | 419 net::ProxyService service(config_service, resolver); |
| 674 | 420 |
| 675 GURL url("http://www.google.com/"); | 421 GURL url("http://www.google.com/"); |
| 676 | 422 |
| 677 // Get the proxy information. | 423 // Get the proxy information. |
| 678 net::ProxyInfo info; | 424 net::ProxyInfo info; |
| 679 int rv = service.ResolveProxy(url, &info); | 425 TestCompletionCallback callback1; |
| 680 EXPECT_EQ(rv, net::OK); | 426 int rv = service.ResolveProxy(url, &info, &callback1, NULL); |
| 681 EXPECT_FALSE(info.is_direct()); | 427 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 428 |
| 429 EXPECT_EQ(GURL("http://foopy/proxy.pac"), resolver->pac_url()); |
| 430 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 431 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); |
| 432 |
| 433 // Set the result in proxy resolver. |
| 434 resolver->pending_requests()[0]->results()->UseNamedProxy( |
| 435 "foopy1:8080;foopy2:9090"); |
| 436 resolver->pending_requests()[0]->CompleteNow(net::OK); |
| 682 | 437 |
| 683 // The first item is valid. | 438 // The first item is valid. |
| 439 EXPECT_EQ(net::OK, callback1.WaitForResult()); |
| 440 EXPECT_FALSE(info.is_direct()); |
| 684 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); | 441 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); |
| 685 | 442 |
| 686 // Fake an error on the proxy, and also a new configuration on the proxy. | 443 // Fake an error on the proxy, and also a new configuration on the proxy. |
| 687 config_service->config = net::ProxyConfig(); | 444 config_service->config = net::ProxyConfig(); |
| 688 config_service->config.pac_url = GURL("http://foopy-new/proxy.pac"); | 445 config_service->config.pac_url = GURL("http://foopy-new/proxy.pac"); |
| 689 | 446 |
| 690 rv = service.ReconsiderProxyAfterError(url, &info); | 447 TestCompletionCallback callback2; |
| 691 EXPECT_EQ(rv, net::OK); | 448 rv = service.ReconsiderProxyAfterError(url, &info, &callback2, NULL); |
| 449 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 450 |
| 451 EXPECT_EQ(GURL("http://foopy-new/proxy.pac"), resolver->pac_url()); |
| 452 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 453 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); |
| 454 |
| 455 resolver->pending_requests()[0]->results()->UseNamedProxy( |
| 456 "foopy1:8080;foopy2:9090"); |
| 457 resolver->pending_requests()[0]->CompleteNow(net::OK); |
| 692 | 458 |
| 693 // The first proxy is still there since the configuration changed. | 459 // The first proxy is still there since the configuration changed. |
| 460 EXPECT_EQ(net::OK, callback2.WaitForResult()); |
| 694 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); | 461 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); |
| 695 | 462 |
| 696 // We fake another error. It should now ignore the first one. | 463 // We fake another error. It should now ignore the first one. |
| 697 rv = service.ReconsiderProxyAfterError(url, &info); | 464 TestCompletionCallback callback3; |
| 698 EXPECT_EQ(rv, net::OK); | 465 rv = service.ReconsiderProxyAfterError(url, &info, &callback3, NULL); |
| 466 EXPECT_EQ(net::OK, rv); |
| 699 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); | 467 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); |
| 700 | 468 |
| 701 // We simulate a new configuration. | 469 // We simulate a new configuration. |
| 702 config_service->config = net::ProxyConfig(); | 470 config_service->config = net::ProxyConfig(); |
| 703 config_service->config.pac_url = GURL("http://foopy-new2/proxy.pac"); | 471 config_service->config.pac_url = GURL("http://foopy-new2/proxy.pac"); |
| 704 | 472 |
| 705 // We fake anothe error. It should go back to the first proxy. | 473 // We fake another error. It should go back to the first proxy. |
| 706 rv = service.ReconsiderProxyAfterError(url, &info); | 474 TestCompletionCallback callback4; |
| 707 EXPECT_EQ(rv, net::OK); | 475 rv = service.ReconsiderProxyAfterError(url, &info, &callback4, NULL); |
| 476 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 477 |
| 478 EXPECT_EQ(GURL("http://foopy-new2/proxy.pac"), resolver->pac_url()); |
| 479 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 480 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); |
| 481 |
| 482 resolver->pending_requests()[0]->results()->UseNamedProxy( |
| 483 "foopy1:8080;foopy2:9090"); |
| 484 resolver->pending_requests()[0]->CompleteNow(net::OK); |
| 485 |
| 486 EXPECT_EQ(net::OK, callback4.WaitForResult()); |
| 708 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); | 487 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); |
| 709 } | 488 } |
| 710 | 489 |
| 711 TEST(ProxyServiceTest, ProxyFallback_BadConfig) { | 490 TEST(ProxyServiceTest, ProxyFallback_BadConfig) { |
| 712 // Test proxy failover when the configuration is bad. | 491 // Test proxy failover when the configuration is bad. |
| 713 | 492 |
| 714 MockProxyConfigService* config_service = | 493 MockProxyConfigService* config_service = |
| 715 new MockProxyConfigService("http://foopy/proxy.pac"); | 494 new MockProxyConfigService("http://foopy/proxy.pac"); |
| 716 | 495 |
| 717 MockProxyResolver* resolver = new MockProxyResolver; | 496 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; |
| 718 resolver->x->info.UseNamedProxy("foopy1:8080;foopy2:9090"); | |
| 719 resolver->x->info_predicate_query_host = "www.google.com"; | |
| 720 resolver->x->fail_get_proxy_for_url = false; | |
| 721 | 497 |
| 722 SyncProxyService service(config_service, resolver); | 498 net::ProxyService service(config_service, resolver); |
| 723 | 499 |
| 724 GURL url("http://www.google.com/"); | 500 GURL url("http://www.google.com/"); |
| 725 | 501 |
| 726 // Get the proxy information. | 502 // Get the proxy information. |
| 727 net::ProxyInfo info; | 503 net::ProxyInfo info; |
| 728 int rv = service.ResolveProxy(url, &info); | 504 TestCompletionCallback callback1; |
| 729 EXPECT_EQ(rv, net::OK); | 505 int rv = service.ResolveProxy(url, &info, &callback1, NULL); |
| 730 EXPECT_FALSE(info.is_direct()); | 506 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 507 |
| 508 EXPECT_EQ(GURL("http://foopy/proxy.pac"), resolver->pac_url()); |
| 509 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 510 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); |
| 511 |
| 512 resolver->pending_requests()[0]->results()->UseNamedProxy( |
| 513 "foopy1:8080;foopy2:9090"); |
| 514 resolver->pending_requests()[0]->CompleteNow(net::OK); |
| 731 | 515 |
| 732 // The first item is valid. | 516 // The first item is valid. |
| 517 EXPECT_EQ(net::OK, callback1.WaitForResult()); |
| 518 EXPECT_FALSE(info.is_direct()); |
| 733 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); | 519 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); |
| 734 | 520 |
| 735 // Fake a proxy error. | 521 // Fake a proxy error. |
| 736 rv = service.ReconsiderProxyAfterError(url, &info); | 522 TestCompletionCallback callback2; |
| 737 EXPECT_EQ(rv, net::OK); | 523 rv = service.ReconsiderProxyAfterError(url, &info, &callback2, NULL); |
| 524 EXPECT_EQ(net::OK, rv); |
| 738 | 525 |
| 739 // The first proxy is ignored, and the second one is selected. | 526 // The first proxy is ignored, and the second one is selected. |
| 740 EXPECT_FALSE(info.is_direct()); | 527 EXPECT_FALSE(info.is_direct()); |
| 741 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); | 528 EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); |
| 742 | 529 |
| 743 // Fake a PAC failure. | 530 // Fake a PAC failure. |
| 744 net::ProxyInfo info2; | 531 net::ProxyInfo info2; |
| 745 resolver->x->fail_get_proxy_for_url = true; | 532 TestCompletionCallback callback3; |
| 746 rv = service.ResolveProxy(url, &info2); | 533 rv = service.ResolveProxy(url, &info2, &callback3, NULL); |
| 747 EXPECT_EQ(rv, net::ERR_FAILED); | 534 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 535 |
| 536 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 537 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); |
| 538 |
| 539 resolver->pending_requests()[0]->CompleteNow(net::ERR_FAILED); |
| 748 | 540 |
| 749 // No proxy servers are returned. It's a direct connection. | 541 // No proxy servers are returned. It's a direct connection. |
| 542 EXPECT_EQ(net::ERR_FAILED, callback3.WaitForResult()); |
| 750 EXPECT_TRUE(info2.is_direct()); | 543 EXPECT_TRUE(info2.is_direct()); |
| 751 | 544 |
| 752 // The PAC is now fixed and will return a proxy server. | 545 // The PAC will now be fixed and will return a proxy server. |
| 753 // It should also clear the list of bad proxies. | 546 // It should also clear the list of bad proxies. |
| 754 resolver->x->fail_get_proxy_for_url = false; | |
| 755 | 547 |
| 756 // Try to resolve, it will still return "direct" because we have no reason | 548 // Try to resolve, it will still return "direct" because we have no reason |
| 757 // to check the config since everything works. | 549 // to check the config since everything works. |
| 758 net::ProxyInfo info3; | 550 net::ProxyInfo info3; |
| 759 rv = service.ResolveProxy(url, &info3); | 551 TestCompletionCallback callback4; |
| 760 EXPECT_EQ(rv, net::OK); | 552 rv = service.ResolveProxy(url, &info3, &callback4, NULL); |
| 553 EXPECT_EQ(net::OK, rv); |
| 761 EXPECT_TRUE(info3.is_direct()); | 554 EXPECT_TRUE(info3.is_direct()); |
| 762 | 555 |
| 763 // But if the direct connection fails, we check if the ProxyInfo tried to | 556 // But if the direct connection fails, we check if the ProxyInfo tried to |
| 764 // resolve the proxy before, and if not (like in this case), we give the | 557 // resolve the proxy before, and if not (like in this case), we give the |
| 765 // PAC another try. | 558 // PAC another try. |
| 766 rv = service.ReconsiderProxyAfterError(url, &info3); | 559 TestCompletionCallback callback5; |
| 767 EXPECT_EQ(rv, net::OK); | 560 rv = service.ReconsiderProxyAfterError(url, &info3, &callback5, NULL); |
| 561 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 562 |
| 563 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 564 EXPECT_EQ(url, resolver->pending_requests()[0]->url()); |
| 565 |
| 566 resolver->pending_requests()[0]->results()->UseNamedProxy( |
| 567 "foopy1:8080;foopy2:9090"); |
| 568 resolver->pending_requests()[0]->CompleteNow(net::OK); |
| 768 | 569 |
| 769 // The first proxy is still there since the list of bad proxies got cleared. | 570 // The first proxy is still there since the list of bad proxies got cleared. |
| 571 EXPECT_EQ(net::OK, callback5.WaitForResult()); |
| 770 EXPECT_FALSE(info3.is_direct()); | 572 EXPECT_FALSE(info3.is_direct()); |
| 771 EXPECT_EQ("foopy1:8080", info3.proxy_server().ToURI()); | 573 EXPECT_EQ("foopy1:8080", info3.proxy_server().ToURI()); |
| 772 } | 574 } |
| 773 | 575 |
| 774 TEST(ProxyServiceTest, ProxyBypassList) { | 576 TEST(ProxyServiceTest, ProxyBypassList) { |
| 775 // Test what happens when a proxy bypass list is specified. | 577 // Test what happens when a proxy bypass list is specified. |
| 776 | 578 |
| 777 net::ProxyInfo info; | 579 net::ProxyInfo info; |
| 778 net::ProxyConfig config; | 580 net::ProxyConfig config; |
| 779 config.proxy_rules.ParseFromString("foopy1:8080;foopy2:9090"); | 581 config.proxy_rules.ParseFromString("foopy1:8080;foopy2:9090"); |
| 780 config.auto_detect = false; | 582 config.auto_detect = false; |
| 781 config.proxy_bypass_local_names = true; | 583 config.proxy_bypass_local_names = true; |
| 782 | 584 |
| 783 { | 585 { |
| 784 SyncProxyService service(new MockProxyConfigService(config), | 586 net::ProxyService service(new MockProxyConfigService(config), |
| 785 new MockProxyResolver()); | 587 new MockAsyncProxyResolver()); |
| 786 GURL url("http://www.google.com/"); | 588 GURL url("http://www.google.com/"); |
| 787 // Get the proxy information. | 589 // Get the proxy information. |
| 788 int rv = service.ResolveProxy(url, &info); | 590 TestCompletionCallback callback; |
| 789 EXPECT_EQ(rv, net::OK); | 591 int rv = service.ResolveProxy(url, &info, &callback, NULL); |
| 592 EXPECT_EQ(net::OK, rv); |
| 790 EXPECT_FALSE(info.is_direct()); | 593 EXPECT_FALSE(info.is_direct()); |
| 791 } | 594 } |
| 792 | 595 |
| 793 { | 596 { |
| 794 SyncProxyService service(new MockProxyConfigService(config), | 597 net::ProxyService service(new MockProxyConfigService(config), |
| 795 new MockProxyResolver()); | 598 new MockAsyncProxyResolver()); |
| 796 GURL test_url("local"); | 599 GURL test_url("local"); |
| 797 int rv = service.ResolveProxy(test_url, &info); | 600 TestCompletionCallback callback; |
| 798 EXPECT_EQ(rv, net::OK); | 601 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 602 EXPECT_EQ(net::OK, rv); |
| 799 EXPECT_TRUE(info.is_direct()); | 603 EXPECT_TRUE(info.is_direct()); |
| 800 } | 604 } |
| 801 | 605 |
| 802 config.proxy_bypass.clear(); | 606 config.proxy_bypass.clear(); |
| 803 config.proxy_bypass.push_back("*.org"); | 607 config.proxy_bypass.push_back("*.org"); |
| 804 config.proxy_bypass_local_names = true; | 608 config.proxy_bypass_local_names = true; |
| 805 { | 609 { |
| 806 SyncProxyService service(new MockProxyConfigService(config), | 610 net::ProxyService service(new MockProxyConfigService(config), |
| 807 new MockProxyResolver); | 611 new MockAsyncProxyResolver); |
| 808 GURL test_url("http://www.webkit.org"); | 612 GURL test_url("http://www.webkit.org"); |
| 809 int rv = service.ResolveProxy(test_url, &info); | 613 TestCompletionCallback callback; |
| 810 EXPECT_EQ(rv, net::OK); | 614 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 615 EXPECT_EQ(net::OK, rv); |
| 811 EXPECT_TRUE(info.is_direct()); | 616 EXPECT_TRUE(info.is_direct()); |
| 812 } | 617 } |
| 813 | 618 |
| 814 config.proxy_bypass.clear(); | 619 config.proxy_bypass.clear(); |
| 815 config.proxy_bypass.push_back("*.org"); | 620 config.proxy_bypass.push_back("*.org"); |
| 816 config.proxy_bypass.push_back("7*"); | 621 config.proxy_bypass.push_back("7*"); |
| 817 config.proxy_bypass_local_names = true; | 622 config.proxy_bypass_local_names = true; |
| 818 { | 623 { |
| 819 SyncProxyService service(new MockProxyConfigService(config), | 624 net::ProxyService service(new MockProxyConfigService(config), |
| 820 new MockProxyResolver); | 625 new MockAsyncProxyResolver); |
| 821 GURL test_url("http://74.125.19.147"); | 626 GURL test_url("http://74.125.19.147"); |
| 822 int rv = service.ResolveProxy(test_url, &info); | 627 TestCompletionCallback callback; |
| 823 EXPECT_EQ(rv, net::OK); | 628 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 629 EXPECT_EQ(net::OK, rv); |
| 824 EXPECT_TRUE(info.is_direct()); | 630 EXPECT_TRUE(info.is_direct()); |
| 825 } | 631 } |
| 826 | 632 |
| 827 config.proxy_bypass.clear(); | 633 config.proxy_bypass.clear(); |
| 828 config.proxy_bypass.push_back("*.org"); | 634 config.proxy_bypass.push_back("*.org"); |
| 829 config.proxy_bypass_local_names = true; | 635 config.proxy_bypass_local_names = true; |
| 830 { | 636 { |
| 831 SyncProxyService service(new MockProxyConfigService(config), | 637 net::ProxyService service(new MockProxyConfigService(config), |
| 832 new MockProxyResolver); | 638 new MockAsyncProxyResolver); |
| 833 GURL test_url("http://www.msn.com"); | 639 GURL test_url("http://www.msn.com"); |
| 834 int rv = service.ResolveProxy(test_url, &info); | 640 TestCompletionCallback callback; |
| 835 EXPECT_EQ(rv, net::OK); | 641 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 642 EXPECT_EQ(net::OK, rv); |
| 836 EXPECT_FALSE(info.is_direct()); | 643 EXPECT_FALSE(info.is_direct()); |
| 837 } | 644 } |
| 838 | 645 |
| 839 config.proxy_bypass.clear(); | 646 config.proxy_bypass.clear(); |
| 840 config.proxy_bypass.push_back("*.MSN.COM"); | 647 config.proxy_bypass.push_back("*.MSN.COM"); |
| 841 config.proxy_bypass_local_names = true; | 648 config.proxy_bypass_local_names = true; |
| 842 { | 649 { |
| 843 SyncProxyService service(new MockProxyConfigService(config), | 650 net::ProxyService service(new MockProxyConfigService(config), |
| 844 new MockProxyResolver); | 651 new MockAsyncProxyResolver); |
| 845 GURL test_url("http://www.msnbc.msn.com"); | 652 GURL test_url("http://www.msnbc.msn.com"); |
| 846 int rv = service.ResolveProxy(test_url, &info); | 653 TestCompletionCallback callback; |
| 847 EXPECT_EQ(rv, net::OK); | 654 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 655 EXPECT_EQ(net::OK, rv); |
| 848 EXPECT_TRUE(info.is_direct()); | 656 EXPECT_TRUE(info.is_direct()); |
| 849 } | 657 } |
| 850 | 658 |
| 851 config.proxy_bypass.clear(); | 659 config.proxy_bypass.clear(); |
| 852 config.proxy_bypass.push_back("*.msn.com"); | 660 config.proxy_bypass.push_back("*.msn.com"); |
| 853 config.proxy_bypass_local_names = true; | 661 config.proxy_bypass_local_names = true; |
| 854 { | 662 { |
| 855 SyncProxyService service(new MockProxyConfigService(config), | 663 net::ProxyService service(new MockProxyConfigService(config), |
| 856 new MockProxyResolver); | 664 new MockAsyncProxyResolver); |
| 857 GURL test_url("HTTP://WWW.MSNBC.MSN.COM"); | 665 GURL test_url("HTTP://WWW.MSNBC.MSN.COM"); |
| 858 int rv = service.ResolveProxy(test_url, &info); | 666 TestCompletionCallback callback; |
| 859 EXPECT_EQ(rv, net::OK); | 667 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 668 EXPECT_EQ(net::OK, rv); |
| 860 EXPECT_TRUE(info.is_direct()); | 669 EXPECT_TRUE(info.is_direct()); |
| 861 } | 670 } |
| 862 } | 671 } |
| 863 | 672 |
| 864 TEST(ProxyServiceTest, ProxyBypassListWithPorts) { | 673 TEST(ProxyServiceTest, ProxyBypassListWithPorts) { |
| 865 // Test port specification in bypass list entries. | 674 // Test port specification in bypass list entries. |
| 866 net::ProxyInfo info; | 675 net::ProxyInfo info; |
| 867 net::ProxyConfig config; | 676 net::ProxyConfig config; |
| 868 config.proxy_rules.ParseFromString("foopy1:8080;foopy2:9090"); | 677 config.proxy_rules.ParseFromString("foopy1:8080;foopy2:9090"); |
| 869 config.auto_detect = false; | 678 config.auto_detect = false; |
| 870 config.proxy_bypass_local_names = false; | 679 config.proxy_bypass_local_names = false; |
| 871 | 680 |
| 872 config.proxy_bypass.clear(); | 681 config.proxy_bypass.clear(); |
| 873 config.proxy_bypass.push_back("*.example.com:99"); | 682 config.proxy_bypass.push_back("*.example.com:99"); |
| 874 { | 683 { |
| 875 SyncProxyService service(new MockProxyConfigService(config), | 684 net::ProxyService service(new MockProxyConfigService(config), |
| 876 new MockProxyResolver); | 685 new MockAsyncProxyResolver); |
| 877 { | 686 { |
| 878 GURL test_url("http://www.example.com:99"); | 687 GURL test_url("http://www.example.com:99"); |
| 879 int rv = service.ResolveProxy(test_url, &info); | 688 TestCompletionCallback callback; |
| 880 EXPECT_EQ(rv, net::OK); | 689 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 690 EXPECT_EQ(net::OK, rv); |
| 881 EXPECT_TRUE(info.is_direct()); | 691 EXPECT_TRUE(info.is_direct()); |
| 882 } | 692 } |
| 883 { | 693 { |
| 884 GURL test_url("http://www.example.com:100"); | 694 GURL test_url("http://www.example.com:100"); |
| 885 int rv = service.ResolveProxy(test_url, &info); | 695 TestCompletionCallback callback; |
| 886 EXPECT_EQ(rv, net::OK); | 696 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 697 EXPECT_EQ(net::OK, rv); |
| 887 EXPECT_FALSE(info.is_direct()); | 698 EXPECT_FALSE(info.is_direct()); |
| 888 } | 699 } |
| 889 { | 700 { |
| 890 GURL test_url("http://www.example.com"); | 701 GURL test_url("http://www.example.com"); |
| 891 int rv = service.ResolveProxy(test_url, &info); | 702 TestCompletionCallback callback; |
| 892 EXPECT_EQ(rv, net::OK); | 703 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 704 EXPECT_EQ(net::OK, rv); |
| 893 EXPECT_FALSE(info.is_direct()); | 705 EXPECT_FALSE(info.is_direct()); |
| 894 } | 706 } |
| 895 } | 707 } |
| 896 | 708 |
| 897 config.proxy_bypass.clear(); | 709 config.proxy_bypass.clear(); |
| 898 config.proxy_bypass.push_back("*.example.com:80"); | 710 config.proxy_bypass.push_back("*.example.com:80"); |
| 899 { | 711 { |
| 900 SyncProxyService service(new MockProxyConfigService(config), | 712 net::ProxyService service(new MockProxyConfigService(config), |
| 901 new MockProxyResolver); | 713 new MockAsyncProxyResolver); |
| 902 GURL test_url("http://www.example.com"); | 714 GURL test_url("http://www.example.com"); |
| 903 int rv = service.ResolveProxy(test_url, &info); | 715 TestCompletionCallback callback; |
| 904 EXPECT_EQ(rv, net::OK); | 716 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 717 EXPECT_EQ(net::OK, rv); |
| 905 EXPECT_TRUE(info.is_direct()); | 718 EXPECT_TRUE(info.is_direct()); |
| 906 } | 719 } |
| 907 | 720 |
| 908 config.proxy_bypass.clear(); | 721 config.proxy_bypass.clear(); |
| 909 config.proxy_bypass.push_back("*.example.com"); | 722 config.proxy_bypass.push_back("*.example.com"); |
| 910 { | 723 { |
| 911 SyncProxyService service(new MockProxyConfigService(config), | 724 net::ProxyService service(new MockProxyConfigService(config), |
| 912 new MockProxyResolver); | 725 new MockAsyncProxyResolver); |
| 913 GURL test_url("http://www.example.com:99"); | 726 GURL test_url("http://www.example.com:99"); |
| 914 int rv = service.ResolveProxy(test_url, &info); | 727 TestCompletionCallback callback; |
| 915 EXPECT_EQ(rv, net::OK); | 728 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 729 EXPECT_EQ(net::OK, rv); |
| 916 EXPECT_TRUE(info.is_direct()); | 730 EXPECT_TRUE(info.is_direct()); |
| 917 } | 731 } |
| 918 | 732 |
| 919 // IPv6 with port. | 733 // IPv6 with port. |
| 920 config.proxy_bypass.clear(); | 734 config.proxy_bypass.clear(); |
| 921 config.proxy_bypass.push_back("[3ffe:2a00:100:7031::1]:99"); | 735 config.proxy_bypass.push_back("[3ffe:2a00:100:7031::1]:99"); |
| 922 { | 736 { |
| 923 SyncProxyService service(new MockProxyConfigService(config), | 737 net::ProxyService service(new MockProxyConfigService(config), |
| 924 new MockProxyResolver); | 738 new MockAsyncProxyResolver); |
| 925 { | 739 { |
| 926 GURL test_url("http://[3ffe:2a00:100:7031::1]:99/"); | 740 GURL test_url("http://[3ffe:2a00:100:7031::1]:99/"); |
| 927 int rv = service.ResolveProxy(test_url, &info); | 741 TestCompletionCallback callback; |
| 928 EXPECT_EQ(rv, net::OK); | 742 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 743 EXPECT_EQ(net::OK, rv); |
| 929 EXPECT_TRUE(info.is_direct()); | 744 EXPECT_TRUE(info.is_direct()); |
| 930 } | 745 } |
| 931 { | 746 { |
| 932 GURL test_url("http://[3ffe:2a00:100:7031::1]/"); | 747 GURL test_url("http://[3ffe:2a00:100:7031::1]/"); |
| 933 int rv = service.ResolveProxy(test_url, &info); | 748 TestCompletionCallback callback; |
| 934 EXPECT_EQ(rv, net::OK); | 749 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 750 EXPECT_EQ(net::OK, rv); |
| 935 EXPECT_FALSE(info.is_direct()); | 751 EXPECT_FALSE(info.is_direct()); |
| 936 } | 752 } |
| 937 } | 753 } |
| 938 | 754 |
| 939 // IPv6 without port. The bypass entry ought to work without the | 755 // IPv6 without port. The bypass entry ought to work without the |
| 940 // brackets, but the bypass matching logic in ProxyService is | 756 // brackets, but the bypass matching logic in ProxyService is |
| 941 // currently limited. | 757 // currently limited. |
| 942 config.proxy_bypass.clear(); | 758 config.proxy_bypass.clear(); |
| 943 config.proxy_bypass.push_back("[3ffe:2a00:100:7031::1]"); | 759 config.proxy_bypass.push_back("[3ffe:2a00:100:7031::1]"); |
| 944 { | 760 { |
| 945 SyncProxyService service(new MockProxyConfigService(config), | 761 net::ProxyService service(new MockProxyConfigService(config), |
| 946 new MockProxyResolver); | 762 new MockAsyncProxyResolver); |
| 947 { | 763 { |
| 948 GURL test_url("http://[3ffe:2a00:100:7031::1]:99/"); | 764 GURL test_url("http://[3ffe:2a00:100:7031::1]:99/"); |
| 949 int rv = service.ResolveProxy(test_url, &info); | 765 TestCompletionCallback callback; |
| 950 EXPECT_EQ(rv, net::OK); | 766 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 767 EXPECT_EQ(net::OK, rv); |
| 951 EXPECT_TRUE(info.is_direct()); | 768 EXPECT_TRUE(info.is_direct()); |
| 952 } | 769 } |
| 953 { | 770 { |
| 954 GURL test_url("http://[3ffe:2a00:100:7031::1]/"); | 771 GURL test_url("http://[3ffe:2a00:100:7031::1]/"); |
| 955 int rv = service.ResolveProxy(test_url, &info); | 772 TestCompletionCallback callback; |
| 956 EXPECT_EQ(rv, net::OK); | 773 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 774 EXPECT_EQ(net::OK, rv); |
| 957 EXPECT_TRUE(info.is_direct()); | 775 EXPECT_TRUE(info.is_direct()); |
| 958 } | 776 } |
| 959 } | 777 } |
| 960 } | 778 } |
| 961 | 779 |
| 962 TEST(ProxyServiceTest, PerProtocolProxyTests) { | 780 TEST(ProxyServiceTest, PerProtocolProxyTests) { |
| 963 net::ProxyConfig config; | 781 net::ProxyConfig config; |
| 964 config.proxy_rules.ParseFromString("http=foopy1:8080;https=foopy2:8080"); | 782 config.proxy_rules.ParseFromString("http=foopy1:8080;https=foopy2:8080"); |
| 965 config.auto_detect = false; | 783 config.auto_detect = false; |
| 966 | 784 { |
| 967 SyncProxyService service1(new MockProxyConfigService(config), | 785 net::ProxyService service(new MockProxyConfigService(config), |
| 968 new MockProxyResolver); | 786 new MockAsyncProxyResolver); |
| 969 GURL test_url1("http://www.msn.com"); | 787 GURL test_url("http://www.msn.com"); |
| 970 net::ProxyInfo info1; | 788 net::ProxyInfo info; |
| 971 int rv = service1.ResolveProxy(test_url1, &info1); | 789 TestCompletionCallback callback; |
| 972 EXPECT_EQ(rv, net::OK); | 790 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 973 EXPECT_FALSE(info1.is_direct()); | 791 EXPECT_EQ(net::OK, rv); |
| 974 EXPECT_EQ("foopy1:8080", info1.proxy_server().ToURI()); | 792 EXPECT_FALSE(info.is_direct()); |
| 975 | 793 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); |
| 976 SyncProxyService service2(new MockProxyConfigService(config), | 794 } |
| 977 new MockProxyResolver); | 795 { |
| 978 GURL test_url2("ftp://ftp.google.com"); | 796 net::ProxyService service(new MockProxyConfigService(config), |
| 979 net::ProxyInfo info2; | 797 new MockAsyncProxyResolver); |
| 980 rv = service2.ResolveProxy(test_url2, &info2); | 798 GURL test_url("ftp://ftp.google.com"); |
| 981 EXPECT_EQ(rv, net::OK); | 799 net::ProxyInfo info; |
| 982 EXPECT_TRUE(info2.is_direct()); | 800 TestCompletionCallback callback; |
| 983 EXPECT_EQ("direct://", info2.proxy_server().ToURI()); | 801 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 984 | 802 EXPECT_EQ(net::OK, rv); |
| 985 SyncProxyService service3(new MockProxyConfigService(config), | 803 EXPECT_TRUE(info.is_direct()); |
| 986 new MockProxyResolver); | 804 EXPECT_EQ("direct://", info.proxy_server().ToURI()); |
| 987 GURL test_url3("https://webbranch.techcu.com"); | 805 } |
| 988 net::ProxyInfo info3; | 806 { |
| 989 rv = service3.ResolveProxy(test_url3, &info3); | 807 net::ProxyService service(new MockProxyConfigService(config), |
| 990 EXPECT_EQ(rv, net::OK); | 808 new MockAsyncProxyResolver); |
| 991 EXPECT_FALSE(info3.is_direct()); | 809 GURL test_url("https://webbranch.techcu.com"); |
| 992 EXPECT_EQ("foopy2:8080", info3.proxy_server().ToURI()); | 810 net::ProxyInfo info; |
| 993 | 811 TestCompletionCallback callback; |
| 994 config.proxy_rules.ParseFromString("foopy1:8080"); | 812 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 995 SyncProxyService service4(new MockProxyConfigService(config), | 813 EXPECT_EQ(net::OK, rv); |
| 996 new MockProxyResolver); | 814 EXPECT_FALSE(info.is_direct()); |
| 997 GURL test_url4("www.microsoft.com"); | 815 EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI()); |
| 998 net::ProxyInfo info4; | 816 } |
| 999 rv = service4.ResolveProxy(test_url4, &info4); | 817 { |
| 1000 EXPECT_EQ(rv, net::OK); | 818 config.proxy_rules.ParseFromString("foopy1:8080"); |
| 1001 EXPECT_FALSE(info4.is_direct()); | 819 net::ProxyService service(new MockProxyConfigService(config), |
| 1002 EXPECT_EQ("foopy1:8080", info4.proxy_server().ToURI()); | 820 new MockAsyncProxyResolver); |
| 821 GURL test_url("www.microsoft.com"); |
| 822 net::ProxyInfo info; |
| 823 TestCompletionCallback callback; |
| 824 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 825 EXPECT_EQ(net::OK, rv); |
| 826 EXPECT_FALSE(info.is_direct()); |
| 827 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); |
| 828 } |
| 1003 } | 829 } |
| 1004 | 830 |
| 1005 // If only HTTP and a SOCKS proxy are specified, check if ftp/https queries | 831 // If only HTTP and a SOCKS proxy are specified, check if ftp/https queries |
| 1006 // fall back to the SOCKS proxy. | 832 // fall back to the SOCKS proxy. |
| 1007 TEST(ProxyServiceTest, DefaultProxyFallbackToSOCKS) { | 833 TEST(ProxyServiceTest, DefaultProxyFallbackToSOCKS) { |
| 1008 net::ProxyConfig config; | 834 net::ProxyConfig config; |
| 1009 config.proxy_rules.ParseFromString("http=foopy1:8080;socks=foopy2:1080"); | 835 config.proxy_rules.ParseFromString("http=foopy1:8080;socks=foopy2:1080"); |
| 1010 config.auto_detect = false; | 836 config.auto_detect = false; |
| 1011 EXPECT_EQ(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, | 837 EXPECT_EQ(net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME, |
| 1012 config.proxy_rules.type); | 838 config.proxy_rules.type); |
| 1013 | 839 |
| 1014 SyncProxyService service1(new MockProxyConfigService(config), | 840 { |
| 1015 new MockProxyResolver); | 841 net::ProxyService service(new MockProxyConfigService(config), |
| 1016 GURL test_url1("http://www.msn.com"); | 842 new MockAsyncProxyResolver); |
| 1017 net::ProxyInfo info1; | 843 GURL test_url("http://www.msn.com"); |
| 1018 int rv = service1.ResolveProxy(test_url1, &info1); | 844 net::ProxyInfo info; |
| 1019 EXPECT_EQ(net::OK, rv); | 845 TestCompletionCallback callback; |
| 1020 EXPECT_FALSE(info1.is_direct()); | 846 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 1021 EXPECT_EQ("foopy1:8080", info1.proxy_server().ToURI()); | 847 EXPECT_EQ(net::OK, rv); |
| 1022 | 848 EXPECT_FALSE(info.is_direct()); |
| 1023 SyncProxyService service2(new MockProxyConfigService(config), | 849 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); |
| 1024 new MockProxyResolver); | 850 } |
| 1025 GURL test_url2("ftp://ftp.google.com"); | 851 { |
| 1026 net::ProxyInfo info2; | 852 net::ProxyService service(new MockProxyConfigService(config), |
| 1027 rv = service2.ResolveProxy(test_url2, &info2); | 853 new MockAsyncProxyResolver); |
| 1028 EXPECT_EQ(net::OK, rv); | 854 GURL test_url("ftp://ftp.google.com"); |
| 1029 EXPECT_FALSE(info2.is_direct()); | 855 net::ProxyInfo info; |
| 1030 EXPECT_EQ("socks4://foopy2:1080", info2.proxy_server().ToURI()); | 856 TestCompletionCallback callback; |
| 1031 | 857 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 1032 SyncProxyService service3(new MockProxyConfigService(config), | 858 EXPECT_EQ(net::OK, rv); |
| 1033 new MockProxyResolver); | 859 EXPECT_FALSE(info.is_direct()); |
| 1034 GURL test_url3("https://webbranch.techcu.com"); | 860 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI()); |
| 1035 net::ProxyInfo info3; | 861 } |
| 1036 rv = service3.ResolveProxy(test_url3, &info3); | 862 { |
| 1037 EXPECT_EQ(net::OK, rv); | 863 net::ProxyService service(new MockProxyConfigService(config), |
| 1038 EXPECT_FALSE(info3.is_direct()); | 864 new MockAsyncProxyResolver); |
| 1039 EXPECT_EQ("socks4://foopy2:1080", info3.proxy_server().ToURI()); | 865 GURL test_url("https://webbranch.techcu.com"); |
| 1040 | 866 net::ProxyInfo info; |
| 1041 SyncProxyService service4(new MockProxyConfigService(config), | 867 TestCompletionCallback callback; |
| 1042 new MockProxyResolver); | 868 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 1043 GURL test_url4("www.microsoft.com"); | 869 EXPECT_EQ(net::OK, rv); |
| 1044 net::ProxyInfo info4; | 870 EXPECT_FALSE(info.is_direct()); |
| 1045 rv = service4.ResolveProxy(test_url4, &info4); | 871 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI()); |
| 1046 EXPECT_EQ(net::OK, rv); | 872 } |
| 1047 EXPECT_FALSE(info4.is_direct()); | 873 { |
| 1048 EXPECT_EQ("socks4://foopy2:1080", info4.proxy_server().ToURI()); | 874 net::ProxyService service(new MockProxyConfigService(config), |
| 875 new MockAsyncProxyResolver); |
| 876 GURL test_url("www.microsoft.com"); |
| 877 net::ProxyInfo info; |
| 878 TestCompletionCallback callback; |
| 879 int rv = service.ResolveProxy(test_url, &info, &callback, NULL); |
| 880 EXPECT_EQ(net::OK, rv); |
| 881 EXPECT_FALSE(info.is_direct()); |
| 882 EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI()); |
| 883 } |
| 1049 } | 884 } |
| 1050 | 885 |
| 1051 // Test cancellation of a queued request. | 886 // Test cancellation of an in-progress request. |
| 1052 TEST(ProxyServiceTest, CancelQueuedRequest) { | 887 TEST(ProxyServiceTest, CancelInProgressRequest) { |
| 1053 MockProxyConfigService* config_service = | 888 MockProxyConfigService* config_service = |
| 1054 new MockProxyConfigService("http://foopy/proxy.pac"); | 889 new MockProxyConfigService("http://foopy/proxy.pac"); |
| 1055 | 890 |
| 1056 BlockableProxyResolver* resolver = new BlockableProxyResolver; | 891 MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver; |
| 1057 | 892 |
| 1058 ProxyServiceWithFutures service(config_service, resolver); | 893 net::ProxyService service(config_service, resolver); |
| 1059 | |
| 1060 // Cause requests to pile up, by having them block in the PAC thread. | |
| 1061 resolver->x->Block(); | |
| 1062 | 894 |
| 1063 // Start 3 requests. | 895 // Start 3 requests. |
| 1064 scoped_refptr<ResultFuture> result1; | |
| 1065 service.ResolveProxy(&result1, GURL("http://request1")); | |
| 1066 | 896 |
| 1067 scoped_refptr<ResultFuture> result2; | 897 net::ProxyInfo info1; |
| 1068 service.ResolveProxy(&result2, GURL("http://request2")); | 898 TestCompletionCallback callback1; |
| 899 int rv = service.ResolveProxy( |
| 900 GURL("http://request1"), &info1, &callback1, NULL); |
| 901 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 902 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 903 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); |
| 1069 | 904 |
| 1070 scoped_refptr<ResultFuture> result3; | 905 net::ProxyInfo info2; |
| 1071 service.ResolveProxy(&result3, GURL("http://request3")); | 906 TestCompletionCallback callback2; |
| 907 net::ProxyService::PacRequest* request2; |
| 908 rv = service.ResolveProxy( |
| 909 GURL("http://request2"), &info2, &callback2, &request2); |
| 910 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 911 ASSERT_EQ(2u, resolver->pending_requests().size()); |
| 912 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url()); |
| 1072 | 913 |
| 1073 // Wait until the first request has become blocked in the PAC thread. | 914 net::ProxyInfo info3; |
| 1074 resolver->x->WaitUntilBlocked(); | 915 TestCompletionCallback callback3; |
| 916 rv = service.ResolveProxy( |
| 917 GURL("http://request3"), &info3, &callback3, NULL); |
| 918 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 919 ASSERT_EQ(3u, resolver->pending_requests().size()); |
| 920 EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[2]->url()); |
| 1075 | 921 |
| 1076 // Cancel the second request | 922 // Cancel the second request |
| 1077 result2->Cancel(); | 923 service.CancelPacRequest(request2); |
| 1078 | 924 |
| 1079 // Unblock the PAC thread. | 925 ASSERT_EQ(2u, resolver->pending_requests().size()); |
| 1080 resolver->x->Unblock(); | 926 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); |
| 927 EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[1]->url()); |
| 1081 | 928 |
| 1082 // Wait for the final request to complete. | 929 // Complete the two un-cancelled requests. |
| 1083 result3->WaitUntilCompleted(); | 930 // We complete the last one first, just to mix it up a bit. |
| 931 resolver->pending_requests()[1]->results()->UseNamedProxy("request3:80"); |
| 932 resolver->pending_requests()[1]->CompleteNow(net::OK); |
| 1084 | 933 |
| 1085 // Verify that requests ran as expected. | 934 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); |
| 935 resolver->pending_requests()[0]->CompleteNow(net::OK); |
| 1086 | 936 |
| 1087 EXPECT_TRUE(result1->IsCompleted()); | 937 // Complete and verify that requests ran as expected. |
| 1088 EXPECT_EQ(net::OK, result1->GetResultCode()); | 938 EXPECT_EQ(net::OK, callback1.WaitForResult()); |
| 1089 EXPECT_EQ("request1:80", result1->GetProxyInfo().proxy_server().ToURI()); | 939 EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); |
| 1090 | 940 |
| 1091 EXPECT_FALSE(result2->IsCompleted()); // Cancelled. | 941 EXPECT_FALSE(callback2.have_result()); // Cancelled. |
| 942 ASSERT_EQ(1u, resolver->cancelled_requests().size()); |
| 943 EXPECT_EQ(GURL("http://request2"), resolver->cancelled_requests()[0]->url()); |
| 1092 | 944 |
| 1093 EXPECT_TRUE(result3->IsCompleted()); | 945 EXPECT_EQ(net::OK, callback3.WaitForResult()); |
| 1094 EXPECT_EQ(net::OK, result3->GetResultCode()); | 946 EXPECT_EQ("request3:80", info3.proxy_server().ToURI()); |
| 1095 EXPECT_EQ("request3:80", result3->GetProxyInfo().proxy_server().ToURI()); | |
| 1096 } | |
| 1097 | |
| 1098 // Test cancellation of an in-progress request. | |
| 1099 TEST(ProxyServiceTest, CancelInprogressRequest) { | |
| 1100 MockProxyConfigService* config_service = | |
| 1101 new MockProxyConfigService("http://foopy/proxy.pac"); | |
| 1102 | |
| 1103 BlockableProxyResolver* resolver = new BlockableProxyResolver; | |
| 1104 | |
| 1105 ProxyServiceWithFutures service(config_service, resolver); | |
| 1106 | |
| 1107 // Cause requests to pile up, by having them block in the PAC thread. | |
| 1108 resolver->x->Block(); | |
| 1109 | |
| 1110 // Start 3 requests. | |
| 1111 scoped_refptr<ResultFuture> result1; | |
| 1112 service.ResolveProxy(&result1, GURL("http://request1")); | |
| 1113 | |
| 1114 scoped_refptr<ResultFuture> result2; | |
| 1115 service.ResolveProxy(&result2, GURL("http://request2")); | |
| 1116 | |
| 1117 scoped_refptr<ResultFuture> result3; | |
| 1118 service.ResolveProxy(&result3, GURL("http://request3")); | |
| 1119 | |
| 1120 // Wait until the first request has become blocked in the PAC thread. | |
| 1121 resolver->x->WaitUntilBlocked(); | |
| 1122 | |
| 1123 // Cancel the first request | |
| 1124 result1->Cancel(); | |
| 1125 | |
| 1126 // Unblock the PAC thread. | |
| 1127 resolver->x->Unblock(); | |
| 1128 | |
| 1129 // Wait for the final request to complete. | |
| 1130 result3->WaitUntilCompleted(); | |
| 1131 | |
| 1132 // Verify that requests ran as expected. | |
| 1133 | |
| 1134 EXPECT_FALSE(result1->IsCompleted()); // Cancelled. | |
| 1135 | |
| 1136 EXPECT_TRUE(result2->IsCompleted()); | |
| 1137 EXPECT_EQ(net::OK, result2->GetResultCode()); | |
| 1138 EXPECT_EQ("request2:80", result2->GetProxyInfo().proxy_server().ToURI()); | |
| 1139 | |
| 1140 EXPECT_TRUE(result3->IsCompleted()); | |
| 1141 EXPECT_EQ(net::OK, result3->GetResultCode()); | |
| 1142 EXPECT_EQ("request3:80", result3->GetProxyInfo().proxy_server().ToURI()); | |
| 1143 } | 947 } |
| 1144 | 948 |
| 1145 // Test the initial PAC download for ProxyResolverWithoutFetch. | 949 // Test the initial PAC download for ProxyResolverWithoutFetch. |
| 1146 TEST(ProxyServiceTest, InitialPACScriptDownload) { | 950 TEST(ProxyServiceTest, InitialPACScriptDownload) { |
| 1147 MockProxyConfigService* config_service = | 951 MockProxyConfigService* config_service = |
| 1148 new MockProxyConfigService("http://foopy/proxy.pac"); | 952 new MockProxyConfigService("http://foopy/proxy.pac"); |
| 1149 | 953 |
| 1150 MockProxyResolverWithoutFetch* resolver = new MockProxyResolverWithoutFetch; | 954 MockAsyncProxyResolverExpectsBytes* resolver = |
| 955 new MockAsyncProxyResolverExpectsBytes; |
| 1151 | 956 |
| 1152 ProxyServiceWithFutures service(config_service, resolver); | 957 net::ProxyService service(config_service, resolver); |
| 1153 | 958 |
| 1154 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; | 959 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; |
| 1155 service.SetProxyScriptFetcher(fetcher); | 960 service.SetProxyScriptFetcher(fetcher); |
| 1156 | 961 |
| 1157 // Start 3 requests. | 962 // Start 3 requests. |
| 1158 scoped_refptr<ResultFuture> result1; | |
| 1159 service.ResolveProxy(&result1, GURL("http://request1")); | |
| 1160 | 963 |
| 1161 scoped_refptr<ResultFuture> result2; | 964 net::ProxyInfo info1; |
| 1162 service.ResolveProxy(&result2, GURL("http://request2")); | 965 TestCompletionCallback callback1; |
| 966 int rv = service.ResolveProxy( |
| 967 GURL("http://request1"), &info1, &callback1, NULL); |
| 968 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 1163 | 969 |
| 1164 scoped_refptr<ResultFuture> result3; | 970 // The first request should have triggered download of PAC script. |
| 1165 service.ResolveProxy(&result3, GURL("http://request3")); | 971 EXPECT_TRUE(fetcher->has_pending_request()); |
| 972 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); |
| 973 |
| 974 net::ProxyInfo info2; |
| 975 TestCompletionCallback callback2; |
| 976 rv = service.ResolveProxy( |
| 977 GURL("http://request2"), &info2, &callback2, NULL); |
| 978 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 979 |
| 980 net::ProxyInfo info3; |
| 981 TestCompletionCallback callback3; |
| 982 rv = service.ResolveProxy( |
| 983 GURL("http://request3"), &info3, &callback3, NULL); |
| 984 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 985 |
| 986 // Nothing has been sent to the resolver yet. |
| 987 EXPECT_TRUE(resolver->pending_requests().empty()); |
| 1166 | 988 |
| 1167 // At this point the ProxyService should be waiting for the | 989 // At this point the ProxyService should be waiting for the |
| 1168 // ProxyScriptFetcher to invoke its completion callback, notifying it of | 990 // ProxyScriptFetcher to invoke its completion callback, notifying it of |
| 1169 // PAC script download completion. | 991 // PAC script download completion. |
| 1170 fetcher->NotifyFetchCompletion(net::OK, "pac-v1"); | 992 fetcher->NotifyFetchCompletion(net::OK, "pac-v1"); |
| 1171 | 993 |
| 1172 // Complete all the requests. | 994 // Now that the PAC script is downloaded, everything should have been sent |
| 1173 result3->WaitUntilCompleted(); | 995 // over to the proxy resolver. |
| 996 EXPECT_EQ("pac-v1", resolver->pac_bytes()); |
| 997 ASSERT_EQ(3u, resolver->pending_requests().size()); |
| 998 EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url()); |
| 999 EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url()); |
| 1000 EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[2]->url()); |
| 1174 | 1001 |
| 1175 EXPECT_TRUE(result1->IsCompleted()); | 1002 // Complete all the requests (in some order). |
| 1176 EXPECT_EQ(net::OK, result1->GetResultCode()); | 1003 // Note that as we complete requests, they shift up in |pending_requests()|. |
| 1177 EXPECT_EQ("pac-v1.request1:80", | |
| 1178 result1->GetProxyInfo().proxy_server().ToURI()); | |
| 1179 | 1004 |
| 1180 EXPECT_TRUE(result2->IsCompleted()); | 1005 resolver->pending_requests()[2]->results()->UseNamedProxy("request3:80"); |
| 1181 EXPECT_EQ(net::OK, result2->GetResultCode()); | 1006 resolver->pending_requests()[2]->CompleteNow(net::OK); |
| 1182 EXPECT_EQ("pac-v1.request2:80", | |
| 1183 result2->GetProxyInfo().proxy_server().ToURI()); | |
| 1184 | 1007 |
| 1185 EXPECT_TRUE(result3->IsCompleted()); | 1008 resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80"); |
| 1186 EXPECT_EQ(net::OK, result3->GetResultCode()); | 1009 resolver->pending_requests()[0]->CompleteNow(net::OK); |
| 1187 EXPECT_EQ("pac-v1.request3:80", | 1010 |
| 1188 result3->GetProxyInfo().proxy_server().ToURI()); | 1011 resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80"); |
| 1012 resolver->pending_requests()[0]->CompleteNow(net::OK); |
| 1013 |
| 1014 // Complete and verify that requests ran as expected. |
| 1015 EXPECT_EQ(net::OK, callback1.WaitForResult()); |
| 1016 EXPECT_EQ("request1:80", info1.proxy_server().ToURI()); |
| 1017 |
| 1018 EXPECT_EQ(net::OK, callback2.WaitForResult()); |
| 1019 EXPECT_EQ("request2:80", info2.proxy_server().ToURI()); |
| 1020 |
| 1021 EXPECT_EQ(net::OK, callback3.WaitForResult()); |
| 1022 EXPECT_EQ("request3:80", info3.proxy_server().ToURI()); |
| 1189 } | 1023 } |
| 1190 | 1024 |
| 1191 // Test cancellation of a request, while the PAC script is being fetched. | 1025 // Test cancellation of a request, while the PAC script is being fetched. |
| 1192 TEST(ProxyServiceTest, CancelWhilePACFetching) { | 1026 TEST(ProxyServiceTest, CancelWhilePACFetching) { |
| 1193 MockProxyConfigService* config_service = | 1027 MockProxyConfigService* config_service = |
| 1194 new MockProxyConfigService("http://foopy/proxy.pac"); | 1028 new MockProxyConfigService("http://foopy/proxy.pac"); |
| 1195 | 1029 |
| 1196 MockProxyResolverWithoutFetch* resolver = new MockProxyResolverWithoutFetch; | 1030 MockAsyncProxyResolverExpectsBytes* resolver = |
| 1031 new MockAsyncProxyResolverExpectsBytes; |
| 1197 | 1032 |
| 1198 ProxyServiceWithFutures service(config_service, resolver); | 1033 net::ProxyService service(config_service, resolver); |
| 1199 | 1034 |
| 1200 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; | 1035 MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher; |
| 1201 service.SetProxyScriptFetcher(fetcher); | 1036 service.SetProxyScriptFetcher(fetcher); |
| 1202 | 1037 |
| 1203 // Start 3 requests. | 1038 // Start 3 requests. |
| 1204 scoped_refptr<ResultFuture> result1; | 1039 net::ProxyInfo info1; |
| 1205 service.ResolveProxy(&result1, GURL("http://request1")); | 1040 TestCompletionCallback callback1; |
| 1041 net::ProxyService::PacRequest* request1; |
| 1042 int rv = service.ResolveProxy( |
| 1043 GURL("http://request1"), &info1, &callback1, &request1); |
| 1044 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 1206 | 1045 |
| 1207 scoped_refptr<ResultFuture> result2; | 1046 // The first request should have triggered download of PAC script. |
| 1208 service.ResolveProxy(&result2, GURL("http://request2")); | 1047 EXPECT_TRUE(fetcher->has_pending_request()); |
| 1048 EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url()); |
| 1209 | 1049 |
| 1210 scoped_refptr<ResultFuture> result3; | 1050 net::ProxyInfo info2; |
| 1211 service.ResolveProxy(&result3, GURL("http://request3")); | 1051 TestCompletionCallback callback2; |
| 1052 net::ProxyService::PacRequest* request2; |
| 1053 rv = service.ResolveProxy( |
| 1054 GURL("http://request2"), &info2, &callback2, &request2); |
| 1055 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 1056 |
| 1057 net::ProxyInfo info3; |
| 1058 TestCompletionCallback callback3; |
| 1059 rv = service.ResolveProxy( |
| 1060 GURL("http://request3"), &info3, &callback3, NULL); |
| 1061 EXPECT_EQ(net::ERR_IO_PENDING, rv); |
| 1062 |
| 1063 // Nothing has been sent to the resolver yet. |
| 1064 EXPECT_TRUE(resolver->pending_requests().empty()); |
| 1212 | 1065 |
| 1213 // Cancel the first 2 requests. | 1066 // Cancel the first 2 requests. |
| 1214 result1->Cancel(); | 1067 service.CancelPacRequest(request1); |
| 1215 result2->Cancel(); | 1068 service.CancelPacRequest(request2); |
| 1216 | 1069 |
| 1217 // At this point the ProxyService should be waiting for the | 1070 // At this point the ProxyService should be waiting for the |
| 1218 // ProxyScriptFetcher to invoke its completion callback, notifying it of | 1071 // ProxyScriptFetcher to invoke its completion callback, notifying it of |
| 1219 // PAC script download completion. | 1072 // PAC script download completion. |
| 1220 fetcher->NotifyFetchCompletion(net::OK, "pac-v1"); | 1073 fetcher->NotifyFetchCompletion(net::OK, "pac-v1"); |
| 1221 | 1074 |
| 1075 // Now that the PAC script is downloaded, everything should have been sent |
| 1076 // over to the proxy resolver. |
| 1077 EXPECT_EQ("pac-v1", resolver->pac_bytes()); |
| 1078 ASSERT_EQ(1u, resolver->pending_requests().size()); |
| 1079 EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[0]->url()); |
| 1080 |
| 1222 // Complete all the requests. | 1081 // Complete all the requests. |
| 1223 result3->WaitUntilCompleted(); | 1082 resolver->pending_requests()[0]->results()->UseNamedProxy("request3:80"); |
| 1083 resolver->pending_requests()[0]->CompleteNow(net::OK); |
| 1224 | 1084 |
| 1225 EXPECT_FALSE(result1->IsCompleted()); // Cancelled. | 1085 EXPECT_EQ(net::OK, callback3.WaitForResult()); |
| 1226 EXPECT_FALSE(result2->IsCompleted()); // Cancelled. | 1086 EXPECT_EQ("request3:80", info3.proxy_server().ToURI()); |
| 1227 | 1087 |
| 1228 EXPECT_TRUE(result3->IsCompleted()); | 1088 EXPECT_TRUE(resolver->cancelled_requests().empty()); |
| 1229 EXPECT_EQ(net::OK, result3->GetResultCode()); | 1089 |
| 1230 EXPECT_EQ("pac-v1.request3:80", | 1090 EXPECT_FALSE(callback1.have_result()); // Cancelled. |
| 1231 result3->GetProxyInfo().proxy_server().ToURI()); | 1091 EXPECT_FALSE(callback2.have_result()); // Cancelled. |
| 1232 } | 1092 } |
| 1233 | 1093 |
| 1234 TEST(ProxyServiceTest, ResetProxyConfigService) { | 1094 TEST(ProxyServiceTest, ResetProxyConfigService) { |
| 1235 net::ProxyConfig config1; | 1095 net::ProxyConfig config1; |
| 1236 config1.proxy_rules.ParseFromString("foopy1:8080"); | 1096 config1.proxy_rules.ParseFromString("foopy1:8080"); |
| 1237 config1.auto_detect = false; | 1097 config1.auto_detect = false; |
| 1238 scoped_ptr<SyncProxyService> service( | 1098 net::ProxyService service(new MockProxyConfigService(config1), |
| 1239 new SyncProxyService(new MockProxyConfigService(config1), | 1099 new MockAsyncProxyResolverExpectsBytes); |
| 1240 new MockProxyResolverWithoutFetch)); | |
| 1241 | 1100 |
| 1242 net::ProxyInfo info; | 1101 net::ProxyInfo info; |
| 1243 service->ResolveProxy(GURL("http://request1"), &info); | 1102 TestCompletionCallback callback1; |
| 1103 int rv = service.ResolveProxy( |
| 1104 GURL("http://request1"), &info, &callback1, NULL); |
| 1105 EXPECT_EQ(net::OK, rv); |
| 1244 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); | 1106 EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); |
| 1245 | 1107 |
| 1246 net::ProxyConfig config2; | 1108 net::ProxyConfig config2; |
| 1247 config2.proxy_rules.ParseFromString("foopy2:8080"); | 1109 config2.proxy_rules.ParseFromString("foopy2:8080"); |
| 1248 config2.auto_detect = false; | 1110 config2.auto_detect = false; |
| 1249 int result = service->ResetConfigService(new MockProxyConfigService(config2)); | 1111 service.ResetConfigService(new MockProxyConfigService(config2)); |
| 1250 DCHECK(result == 0); | 1112 TestCompletionCallback callback2; |
| 1251 service->ResolveProxy(GURL("http://request2"), &info); | 1113 rv = service.ResolveProxy(GURL("http://request2"), &info, &callback2, NULL); |
| 1114 EXPECT_EQ(net::OK, rv); |
| 1252 EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI()); | 1115 EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI()); |
| 1253 } | 1116 } |
| OLD | NEW |