Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(171)

Side by Side Diff: net/proxy/proxy_service_unittest.cc

Issue 160155: Clean-up proxy_service_unittest.cc, to remove dependency on SingleThreadedPro... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Fixe header order Created 11 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698