• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include "net/proxy/proxy_service.h"
6 
7 #include <vector>
8 
9 #include "base/format_macros.h"
10 #include "base/logging.h"
11 #include "base/string_util.h"
12 #include "googleurl/src/gurl.h"
13 #include "net/base/load_log.h"
14 #include "net/base/load_log_unittest.h"
15 #include "net/base/mock_network_change_notifier.h"
16 #include "net/base/net_errors.h"
17 #include "net/base/test_completion_callback.h"
18 #include "net/proxy/mock_proxy_resolver.h"
19 #include "net/proxy/proxy_config_service.h"
20 #include "net/proxy/proxy_resolver.h"
21 #include "net/proxy/proxy_script_fetcher.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 
24 // TODO(eroman): Write a test which exercises
25 //              ProxyService::SuspendAllPendingRequests().
26 namespace net {
27 namespace {
28 
29 class MockProxyConfigService: public ProxyConfigService {
30  public:
MockProxyConfigService()31   MockProxyConfigService() {}  // Direct connect.
MockProxyConfigService(const ProxyConfig & pc)32   explicit MockProxyConfigService(const ProxyConfig& pc) : config(pc) {}
MockProxyConfigService(const std::string & pac_url)33   explicit MockProxyConfigService(const std::string& pac_url) {
34     config.pac_url = GURL(pac_url);
35   }
36 
GetProxyConfig(ProxyConfig * results)37   virtual int GetProxyConfig(ProxyConfig* results) {
38     *results = config;
39     return OK;
40   }
41 
42   ProxyConfig config;
43 };
44 
45 }  // namespace
46 
47 // A mock ProxyScriptFetcher. No result will be returned to the fetch client
48 // until we call NotifyFetchCompletion() to set the results.
49 class MockProxyScriptFetcher : public ProxyScriptFetcher {
50  public:
MockProxyScriptFetcher()51   MockProxyScriptFetcher()
52       : pending_request_callback_(NULL), pending_request_bytes_(NULL) {
53   }
54 
55   // ProxyScriptFetcher implementation.
Fetch(const GURL & url,std::string * bytes,CompletionCallback * callback)56   virtual int Fetch(const GURL& url,
57                     std::string* bytes,
58                     CompletionCallback* callback) {
59     DCHECK(!has_pending_request());
60 
61     // Save the caller's information, and have them wait.
62     pending_request_url_ = url;
63     pending_request_callback_ = callback;
64     pending_request_bytes_ = bytes;
65     return ERR_IO_PENDING;
66   }
67 
NotifyFetchCompletion(int result,const std::string & bytes)68   void NotifyFetchCompletion(int result, const std::string& bytes) {
69     DCHECK(has_pending_request());
70     *pending_request_bytes_ = bytes;
71     CompletionCallback* callback = pending_request_callback_;
72     pending_request_callback_ = NULL;
73     callback->Run(result);
74   }
75 
Cancel()76   virtual void Cancel() {}
77 
pending_request_url() const78   const GURL& pending_request_url() const {
79     return pending_request_url_;
80   }
81 
has_pending_request() const82   bool has_pending_request() const {
83     return pending_request_callback_ != NULL;
84   }
85 
86  private:
87   GURL pending_request_url_;
88   CompletionCallback* pending_request_callback_;
89   std::string* pending_request_bytes_;
90 };
91 
TEST(ProxyServiceTest,Direct)92 TEST(ProxyServiceTest, Direct) {
93   MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
94   scoped_refptr<ProxyService> service(
95       new ProxyService(new MockProxyConfigService, resolver, NULL));
96 
97   GURL url("http://www.google.com/");
98 
99   ProxyInfo info;
100   TestCompletionCallback callback;
101   scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded));
102   int rv = service->ResolveProxy(url, &info, &callback, NULL, log);
103   EXPECT_EQ(OK, rv);
104   EXPECT_TRUE(resolver->pending_requests().empty());
105   EXPECT_TRUE(NULL == service->init_proxy_resolver_log());
106 
107   EXPECT_TRUE(info.is_direct());
108 
109   // Check the LoadLog was filled correctly.
110   EXPECT_EQ(5u, log->entries().size());
111   EXPECT_TRUE(LogContainsBeginEvent(*log, 0, LoadLog::TYPE_PROXY_SERVICE));
112   EXPECT_TRUE(LogContainsEndEvent(*log, 4, LoadLog::TYPE_PROXY_SERVICE));
113 }
114 
TEST(ProxyServiceTest,PAC)115 TEST(ProxyServiceTest, PAC) {
116   MockProxyConfigService* config_service =
117       new MockProxyConfigService("http://foopy/proxy.pac");
118 
119   MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
120 
121   scoped_refptr<ProxyService> service(
122       new ProxyService(config_service, resolver, NULL));
123 
124   GURL url("http://www.google.com/");
125 
126   ProxyInfo info;
127   TestCompletionCallback callback;
128   scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded));
129   int rv = service->ResolveProxy(url, &info, &callback, NULL, log);
130   EXPECT_EQ(ERR_IO_PENDING, rv);
131 
132   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
133             resolver->pending_set_pac_script_request()->pac_url());
134   EXPECT_FALSE(NULL == service->init_proxy_resolver_log());
135   resolver->pending_set_pac_script_request()->CompleteNow(OK);
136 
137   ASSERT_EQ(1u, resolver->pending_requests().size());
138   EXPECT_EQ(url, resolver->pending_requests()[0]->url());
139 
140   // Set the result in proxy resolver.
141   resolver->pending_requests()[0]->results()->UseNamedProxy("foopy");
142   resolver->pending_requests()[0]->CompleteNow(OK);
143 
144   EXPECT_EQ(OK, callback.WaitForResult());
145   EXPECT_FALSE(info.is_direct());
146   EXPECT_EQ("foopy:80", info.proxy_server().ToURI());
147 
148   // Check the LoadLog was filled correctly.
149   EXPECT_EQ(7u, log->entries().size());
150   EXPECT_TRUE(LogContainsBeginEvent(*log, 0, LoadLog::TYPE_PROXY_SERVICE));
151   EXPECT_TRUE(LogContainsBeginEvent(
152       *log, 3, LoadLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
153   EXPECT_TRUE(LogContainsEndEvent(
154       *log, 4, LoadLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
155   EXPECT_TRUE(LogContainsEndEvent(*log, 6, LoadLog::TYPE_PROXY_SERVICE));
156 }
157 
158 // Test that the proxy resolver does not see the URL's username/password
159 // or its reference section.
TEST(ProxyServiceTest,PAC_NoIdentityOrHash)160 TEST(ProxyServiceTest, PAC_NoIdentityOrHash) {
161   MockProxyConfigService* config_service =
162       new MockProxyConfigService("http://foopy/proxy.pac");
163 
164   MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
165 
166   scoped_refptr<ProxyService> service(
167       new ProxyService(config_service, resolver, NULL));
168 
169   GURL url("http://username:password@www.google.com/?ref#hash#hash");
170 
171   ProxyInfo info;
172   TestCompletionCallback callback;
173   int rv = service->ResolveProxy(url, &info, &callback, NULL, NULL);
174   EXPECT_EQ(ERR_IO_PENDING, rv);
175 
176   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
177             resolver->pending_set_pac_script_request()->pac_url());
178   resolver->pending_set_pac_script_request()->CompleteNow(OK);
179 
180   ASSERT_EQ(1u, resolver->pending_requests().size());
181   // The URL should have been simplified, stripping the username/password/hash.
182   EXPECT_EQ(GURL("http://www.google.com/?ref"),
183                  resolver->pending_requests()[0]->url());
184 
185   // We end here without ever completing the request -- destruction of
186   // ProxyService will cancel the outstanding request.
187 }
188 
TEST(ProxyServiceTest,PAC_FailoverWithoutDirect)189 TEST(ProxyServiceTest, PAC_FailoverWithoutDirect) {
190   MockProxyConfigService* config_service =
191       new MockProxyConfigService("http://foopy/proxy.pac");
192   MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
193 
194   scoped_refptr<ProxyService> service(
195       new ProxyService(config_service, resolver, NULL));
196 
197   GURL url("http://www.google.com/");
198 
199   ProxyInfo info;
200   TestCompletionCallback callback1;
201   int rv = service->ResolveProxy(url, &info, &callback1, NULL, NULL);
202   EXPECT_EQ(ERR_IO_PENDING, rv);
203 
204   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
205             resolver->pending_set_pac_script_request()->pac_url());
206   resolver->pending_set_pac_script_request()->CompleteNow(OK);
207 
208   ASSERT_EQ(1u, resolver->pending_requests().size());
209   EXPECT_EQ(url, resolver->pending_requests()[0]->url());
210 
211   // Set the result in proxy resolver.
212   resolver->pending_requests()[0]->results()->UseNamedProxy("foopy:8080");
213   resolver->pending_requests()[0]->CompleteNow(OK);
214 
215   EXPECT_EQ(OK, callback1.WaitForResult());
216   EXPECT_FALSE(info.is_direct());
217   EXPECT_EQ("foopy:8080", info.proxy_server().ToURI());
218 
219   // Now, imagine that connecting to foopy:8080 fails: there is nothing
220   // left to fallback to, since our proxy list was NOT terminated by
221   // DIRECT.
222   TestCompletionCallback callback2;
223   rv = service->ReconsiderProxyAfterError(url, &info, &callback2, NULL, NULL);
224   // ReconsiderProxyAfterError returns error indicating nothing left.
225   EXPECT_EQ(ERR_FAILED, rv);
226   EXPECT_TRUE(info.is_empty());
227 }
228 
229 // The proxy list could potentially contain the DIRECT fallback choice
230 // in a location other than the very end of the list, and could even
231 // specify it multiple times.
232 //
233 // This is not a typical usage, but we will obey it.
234 // (If we wanted to disallow this type of input, the right place to
235 // enforce it would be in parsing the PAC result string).
236 //
237 // This test will use the PAC result string:
238 //
239 //   "DIRECT ; PROXY foobar:10 ; DIRECT ; PROXY foobar:20"
240 //
241 // For which we expect it to try DIRECT, then foobar:10, then DIRECT again,
242 // then foobar:20, and then give up and error.
243 //
244 // The important check of this test is to make sure that DIRECT is not somehow
245 // cached as being a bad proxy.
TEST(ProxyServiceTest,PAC_FailoverAfterDirect)246 TEST(ProxyServiceTest, PAC_FailoverAfterDirect) {
247   MockProxyConfigService* config_service =
248       new MockProxyConfigService("http://foopy/proxy.pac");
249   MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
250 
251   scoped_refptr<ProxyService> service(
252       new ProxyService(config_service, resolver, NULL));
253 
254   GURL url("http://www.google.com/");
255 
256   ProxyInfo info;
257   TestCompletionCallback callback1;
258   int rv = service->ResolveProxy(url, &info, &callback1, NULL, NULL);
259   EXPECT_EQ(ERR_IO_PENDING, rv);
260 
261   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
262             resolver->pending_set_pac_script_request()->pac_url());
263   resolver->pending_set_pac_script_request()->CompleteNow(OK);
264 
265   ASSERT_EQ(1u, resolver->pending_requests().size());
266   EXPECT_EQ(url, resolver->pending_requests()[0]->url());
267 
268   // Set the result in proxy resolver.
269   resolver->pending_requests()[0]->results()->UsePacString(
270       "DIRECT ; PROXY foobar:10 ; DIRECT ; PROXY foobar:20");
271   resolver->pending_requests()[0]->CompleteNow(OK);
272 
273   EXPECT_EQ(OK, callback1.WaitForResult());
274   EXPECT_TRUE(info.is_direct());
275 
276   // Fallback 1.
277   TestCompletionCallback callback2;
278   rv = service->ReconsiderProxyAfterError(url, &info, &callback2, NULL, NULL);
279   EXPECT_EQ(OK, rv);
280   EXPECT_FALSE(info.is_direct());
281   EXPECT_EQ("foobar:10", info.proxy_server().ToURI());
282 
283   // Fallback 2.
284   TestCompletionCallback callback3;
285   rv = service->ReconsiderProxyAfterError(url, &info, &callback3, NULL, NULL);
286   EXPECT_EQ(OK, rv);
287   EXPECT_TRUE(info.is_direct());
288 
289   // Fallback 3.
290   TestCompletionCallback callback4;
291   rv = service->ReconsiderProxyAfterError(url, &info, &callback4, NULL, NULL);
292   EXPECT_EQ(OK, rv);
293   EXPECT_FALSE(info.is_direct());
294   EXPECT_EQ("foobar:20", info.proxy_server().ToURI());
295 
296   // Fallback 4 -- Nothing to fall back to!
297   TestCompletionCallback callback5;
298   rv = service->ReconsiderProxyAfterError(url, &info, &callback5, NULL, NULL);
299   EXPECT_EQ(ERR_FAILED, rv);
300   EXPECT_TRUE(info.is_empty());
301 }
302 
TEST(ProxyServiceTest,ProxyResolverFails)303 TEST(ProxyServiceTest, ProxyResolverFails) {
304   // Test what happens when the ProxyResolver fails. The download and setting
305   // of the PAC script have already succeeded, so this corresponds with a
306   // javascript runtime error while calling FindProxyForURL().
307 
308   MockProxyConfigService* config_service =
309       new MockProxyConfigService("http://foopy/proxy.pac");
310 
311   MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
312 
313   scoped_refptr<ProxyService> service(
314       new ProxyService(config_service, resolver, NULL));
315 
316   // Start first resolve request.
317   GURL url("http://www.google.com/");
318   ProxyInfo info;
319   TestCompletionCallback callback1;
320   int rv = service->ResolveProxy(url, &info, &callback1, NULL, NULL);
321   EXPECT_EQ(ERR_IO_PENDING, rv);
322 
323   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
324             resolver->pending_set_pac_script_request()->pac_url());
325   resolver->pending_set_pac_script_request()->CompleteNow(OK);
326 
327   ASSERT_EQ(1u, resolver->pending_requests().size());
328   EXPECT_EQ(url, resolver->pending_requests()[0]->url());
329 
330   // Fail the first resolve request in MockAsyncProxyResolver.
331   resolver->pending_requests()[0]->CompleteNow(ERR_FAILED);
332 
333   EXPECT_EQ(ERR_FAILED, callback1.WaitForResult());
334 
335   // The second resolve request will try to run through the proxy resolver,
336   // regardless of whether the first request failed in it.
337   TestCompletionCallback callback2;
338   rv = service->ResolveProxy(url, &info, &callback2, NULL, NULL);
339   EXPECT_EQ(ERR_IO_PENDING, rv);
340 
341   ASSERT_EQ(1u, resolver->pending_requests().size());
342   EXPECT_EQ(url, resolver->pending_requests()[0]->url());
343 
344   // This time we will have the resolver succeed (perhaps the PAC script has
345   // a dependency on the current time).
346   resolver->pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080");
347   resolver->pending_requests()[0]->CompleteNow(OK);
348 
349   EXPECT_EQ(OK, callback2.WaitForResult());
350   EXPECT_FALSE(info.is_direct());
351   EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI());
352 }
353 
TEST(ProxyServiceTest,ProxyFallback)354 TEST(ProxyServiceTest, ProxyFallback) {
355   // Test what happens when we specify multiple proxy servers and some of them
356   // are bad.
357 
358   MockProxyConfigService* config_service =
359       new MockProxyConfigService("http://foopy/proxy.pac");
360 
361   MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
362 
363   scoped_refptr<ProxyService> service(
364       new ProxyService(config_service, resolver, NULL));
365 
366   GURL url("http://www.google.com/");
367 
368   // Get the proxy information.
369   ProxyInfo info;
370   TestCompletionCallback callback1;
371   int rv = service->ResolveProxy(url, &info, &callback1, NULL, NULL);
372   EXPECT_EQ(ERR_IO_PENDING, rv);
373 
374   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
375             resolver->pending_set_pac_script_request()->pac_url());
376   resolver->pending_set_pac_script_request()->CompleteNow(OK);
377 
378   ASSERT_EQ(1u, resolver->pending_requests().size());
379   EXPECT_EQ(url, resolver->pending_requests()[0]->url());
380 
381   // Set the result in proxy resolver.
382   resolver->pending_requests()[0]->results()->UseNamedProxy(
383       "foopy1:8080;foopy2:9090");
384   resolver->pending_requests()[0]->CompleteNow(OK);
385 
386   // The first item is valid.
387   EXPECT_EQ(OK, callback1.WaitForResult());
388   EXPECT_FALSE(info.is_direct());
389   EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
390 
391   // Fake an error on the proxy.
392   TestCompletionCallback callback2;
393   rv = service->ReconsiderProxyAfterError(url, &info, &callback2, NULL, NULL);
394   EXPECT_EQ(OK, rv);
395 
396   // The second proxy should be specified.
397   EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
398 
399   TestCompletionCallback callback3;
400   rv = service->ResolveProxy(url, &info, &callback3, NULL, NULL);
401   EXPECT_EQ(ERR_IO_PENDING, rv);
402 
403   ASSERT_EQ(1u, resolver->pending_requests().size());
404   EXPECT_EQ(url, resolver->pending_requests()[0]->url());
405 
406   // Set the result in proxy resolver -- the second result is already known
407   // to be bad, so we will not try to use it initially.
408   resolver->pending_requests()[0]->results()->UseNamedProxy(
409       "foopy3:7070;foopy1:8080;foopy2:9090");
410   resolver->pending_requests()[0]->CompleteNow(OK);
411 
412   EXPECT_EQ(OK, callback3.WaitForResult());
413   EXPECT_FALSE(info.is_direct());
414   EXPECT_EQ("foopy3:7070", info.proxy_server().ToURI());
415 
416   // We fake another error. It should now try the third one.
417   TestCompletionCallback callback4;
418   rv = service->ReconsiderProxyAfterError(url, &info, &callback4, NULL, NULL);
419   EXPECT_EQ(OK, rv);
420   EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
421 
422   // We fake another error. At this point we have tried all of the
423   // proxy servers we thought were valid; next we try the proxy server
424   // that was in our bad proxies map (foopy1:8080).
425   TestCompletionCallback callback5;
426   rv = service->ReconsiderProxyAfterError(url, &info, &callback5, NULL, NULL);
427   EXPECT_EQ(OK, rv);
428   EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
429 
430   // Fake another error, the last proxy is gone, the list should now be empty,
431   // so there is nothing left to try.
432   TestCompletionCallback callback6;
433   rv = service->ReconsiderProxyAfterError(url, &info, &callback6, NULL, NULL);
434   EXPECT_EQ(ERR_FAILED, rv);
435   EXPECT_FALSE(info.is_direct());
436   EXPECT_TRUE(info.is_empty());
437 
438   // TODO(nsylvain): Test that the proxy can be retried after the delay.
439 }
440 
441 // This test is similar to ProxyFallback, but this time we have an explicit
442 // fallback choice to DIRECT.
TEST(ProxyServiceTest,ProxyFallbackToDirect)443 TEST(ProxyServiceTest, ProxyFallbackToDirect) {
444   MockProxyConfigService* config_service =
445       new MockProxyConfigService("http://foopy/proxy.pac");
446 
447   MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
448 
449   scoped_refptr<ProxyService> service(
450       new ProxyService(config_service, resolver, NULL));
451 
452   GURL url("http://www.google.com/");
453 
454   // Get the proxy information.
455   ProxyInfo info;
456   TestCompletionCallback callback1;
457   int rv = service->ResolveProxy(url, &info, &callback1, NULL, NULL);
458   EXPECT_EQ(ERR_IO_PENDING, rv);
459 
460   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
461             resolver->pending_set_pac_script_request()->pac_url());
462   resolver->pending_set_pac_script_request()->CompleteNow(OK);
463 
464   ASSERT_EQ(1u, resolver->pending_requests().size());
465   EXPECT_EQ(url, resolver->pending_requests()[0]->url());
466 
467   // Set the result in proxy resolver.
468   resolver->pending_requests()[0]->results()->UsePacString(
469       "PROXY foopy1:8080; PROXY foopy2:9090; DIRECT");
470   resolver->pending_requests()[0]->CompleteNow(OK);
471 
472   // Get the first result.
473   EXPECT_EQ(OK, callback1.WaitForResult());
474   EXPECT_FALSE(info.is_direct());
475   EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
476 
477   // Fake an error on the proxy.
478   TestCompletionCallback callback2;
479   rv = service->ReconsiderProxyAfterError(url, &info, &callback2, NULL, NULL);
480   EXPECT_EQ(OK, rv);
481 
482   // Now we get back the second proxy.
483   EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
484 
485   // Fake an error on this proxy as well.
486   TestCompletionCallback callback3;
487   rv = service->ReconsiderProxyAfterError(url, &info, &callback3, NULL, NULL);
488   EXPECT_EQ(OK, rv);
489 
490   // Finally, we get back DIRECT.
491   EXPECT_TRUE(info.is_direct());
492 
493   // Now we tell the proxy service that even DIRECT failed.
494   TestCompletionCallback callback4;
495   rv = service->ReconsiderProxyAfterError(url, &info, &callback4, NULL, NULL);
496   // There was nothing left to try after DIRECT, so we are out of
497   // choices.
498   EXPECT_EQ(ERR_FAILED, rv);
499 }
500 
TEST(ProxyServiceTest,ProxyFallback_NewSettings)501 TEST(ProxyServiceTest, ProxyFallback_NewSettings) {
502   // Test proxy failover when new settings are available.
503 
504   MockProxyConfigService* config_service =
505       new MockProxyConfigService("http://foopy/proxy.pac");
506 
507   MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
508 
509   scoped_refptr<ProxyService> service(
510       new ProxyService(config_service, resolver, NULL));
511 
512   GURL url("http://www.google.com/");
513 
514   // Get the proxy information.
515   ProxyInfo info;
516   TestCompletionCallback callback1;
517   int rv = service->ResolveProxy(url, &info, &callback1, NULL, NULL);
518   EXPECT_EQ(ERR_IO_PENDING, rv);
519 
520   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
521             resolver->pending_set_pac_script_request()->pac_url());
522   resolver->pending_set_pac_script_request()->CompleteNow(OK);
523 
524   ASSERT_EQ(1u, resolver->pending_requests().size());
525   EXPECT_EQ(url, resolver->pending_requests()[0]->url());
526 
527   // Set the result in proxy resolver.
528   resolver->pending_requests()[0]->results()->UseNamedProxy(
529       "foopy1:8080;foopy2:9090");
530   resolver->pending_requests()[0]->CompleteNow(OK);
531 
532   // The first item is valid.
533   EXPECT_EQ(OK, callback1.WaitForResult());
534   EXPECT_FALSE(info.is_direct());
535   EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
536 
537   // Fake an error on the proxy, and also a new configuration on the proxy.
538   config_service->config = ProxyConfig();
539   config_service->config.pac_url = GURL("http://foopy-new/proxy.pac");
540 
541   TestCompletionCallback callback2;
542   rv = service->ReconsiderProxyAfterError(url, &info, &callback2, NULL, NULL);
543   EXPECT_EQ(ERR_IO_PENDING, rv);
544 
545   EXPECT_EQ(GURL("http://foopy-new/proxy.pac"),
546             resolver->pending_set_pac_script_request()->pac_url());
547   resolver->pending_set_pac_script_request()->CompleteNow(OK);
548 
549   ASSERT_EQ(1u, resolver->pending_requests().size());
550   EXPECT_EQ(url, resolver->pending_requests()[0]->url());
551 
552   resolver->pending_requests()[0]->results()->UseNamedProxy(
553       "foopy1:8080;foopy2:9090");
554   resolver->pending_requests()[0]->CompleteNow(OK);
555 
556   // The first proxy is still there since the configuration changed.
557   EXPECT_EQ(OK, callback2.WaitForResult());
558   EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
559 
560   // We fake another error. It should now ignore the first one.
561   TestCompletionCallback callback3;
562   rv = service->ReconsiderProxyAfterError(url, &info, &callback3, NULL, NULL);
563   EXPECT_EQ(OK, rv);
564   EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
565 
566   // We simulate a new configuration.
567   config_service->config = ProxyConfig();
568   config_service->config.pac_url = GURL("http://foopy-new2/proxy.pac");
569 
570   // We fake another error. It should go back to the first proxy.
571   TestCompletionCallback callback4;
572   rv = service->ReconsiderProxyAfterError(url, &info, &callback4, NULL, NULL);
573   EXPECT_EQ(ERR_IO_PENDING, rv);
574 
575   EXPECT_EQ(GURL("http://foopy-new2/proxy.pac"),
576             resolver->pending_set_pac_script_request()->pac_url());
577   resolver->pending_set_pac_script_request()->CompleteNow(OK);
578 
579   ASSERT_EQ(1u, resolver->pending_requests().size());
580   EXPECT_EQ(url, resolver->pending_requests()[0]->url());
581 
582   resolver->pending_requests()[0]->results()->UseNamedProxy(
583       "foopy1:8080;foopy2:9090");
584   resolver->pending_requests()[0]->CompleteNow(OK);
585 
586   EXPECT_EQ(OK, callback4.WaitForResult());
587   EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
588 }
589 
TEST(ProxyServiceTest,ProxyFallback_BadConfig)590 TEST(ProxyServiceTest, ProxyFallback_BadConfig) {
591   // Test proxy failover when the configuration is bad.
592 
593   MockProxyConfigService* config_service =
594       new MockProxyConfigService("http://foopy/proxy.pac");
595 
596   MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
597 
598   scoped_refptr<ProxyService> service(
599       new ProxyService(config_service, resolver, NULL));
600 
601   GURL url("http://www.google.com/");
602 
603   // Get the proxy information.
604   ProxyInfo info;
605   TestCompletionCallback callback1;
606   int rv = service->ResolveProxy(url, &info, &callback1, NULL, NULL);
607   EXPECT_EQ(ERR_IO_PENDING, rv);
608 
609   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
610             resolver->pending_set_pac_script_request()->pac_url());
611   resolver->pending_set_pac_script_request()->CompleteNow(OK);
612   ASSERT_EQ(1u, resolver->pending_requests().size());
613   EXPECT_EQ(url, resolver->pending_requests()[0]->url());
614 
615   resolver->pending_requests()[0]->results()->UseNamedProxy(
616       "foopy1:8080;foopy2:9090");
617   resolver->pending_requests()[0]->CompleteNow(OK);
618 
619   // The first item is valid.
620   EXPECT_EQ(OK, callback1.WaitForResult());
621   EXPECT_FALSE(info.is_direct());
622   EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
623 
624   // Fake a proxy error.
625   TestCompletionCallback callback2;
626   rv = service->ReconsiderProxyAfterError(url, &info, &callback2, NULL, NULL);
627   EXPECT_EQ(OK, rv);
628 
629   // The first proxy is ignored, and the second one is selected.
630   EXPECT_FALSE(info.is_direct());
631   EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI());
632 
633   // Fake a PAC failure.
634   ProxyInfo info2;
635   TestCompletionCallback callback3;
636   rv = service->ResolveProxy(url, &info2, &callback3, NULL, NULL);
637   EXPECT_EQ(ERR_IO_PENDING, rv);
638 
639   ASSERT_EQ(1u, resolver->pending_requests().size());
640   EXPECT_EQ(url, resolver->pending_requests()[0]->url());
641 
642   // This simulates a javascript runtime error in the PAC script.
643   resolver->pending_requests()[0]->CompleteNow(ERR_FAILED);
644 
645   // No proxy servers are returned, since we failed.
646   EXPECT_EQ(ERR_FAILED, callback3.WaitForResult());
647   EXPECT_FALSE(info2.is_direct());
648   EXPECT_TRUE(info2.is_empty());
649 
650   // The PAC script will work properly next time and successfully return a
651   // proxy list. Since we have not marked the configuration as bad, it should
652   // "just work" the next time we call it.
653   ProxyInfo info3;
654   TestCompletionCallback callback4;
655   rv = service->ReconsiderProxyAfterError(url, &info3, &callback4, NULL, NULL);
656   EXPECT_EQ(ERR_IO_PENDING, rv);
657 
658   ASSERT_EQ(1u, resolver->pending_requests().size());
659   EXPECT_EQ(url, resolver->pending_requests()[0]->url());
660 
661   resolver->pending_requests()[0]->results()->UseNamedProxy(
662       "foopy1:8080;foopy2:9090");
663   resolver->pending_requests()[0]->CompleteNow(OK);
664 
665   // The first proxy is not there since the it was added to the bad proxies
666   // list by the earlier ReconsiderProxyAfterError().
667   EXPECT_EQ(OK, callback4.WaitForResult());
668   EXPECT_FALSE(info3.is_direct());
669   EXPECT_EQ("foopy1:8080", info3.proxy_server().ToURI());
670 }
671 
TEST(ProxyServiceTest,ProxyBypassList)672 TEST(ProxyServiceTest, ProxyBypassList) {
673   // Test what happens when a proxy bypass list is specified.
674 
675   ProxyInfo info;
676   ProxyConfig config;
677   config.proxy_rules.ParseFromString("foopy1:8080;foopy2:9090");
678   config.auto_detect = false;
679   config.proxy_bypass_local_names = true;
680 
681   {
682     scoped_refptr<ProxyService> service(new ProxyService(
683         new MockProxyConfigService(config),
684         new MockAsyncProxyResolver(),
685         NULL));
686     GURL url("http://www.google.com/");
687     // Get the proxy information.
688     TestCompletionCallback callback;
689     int rv = service->ResolveProxy(url, &info, &callback, NULL, NULL);
690     EXPECT_EQ(OK, rv);
691     EXPECT_FALSE(info.is_direct());
692   }
693 
694   {
695     scoped_refptr<ProxyService> service(new ProxyService(
696         new MockProxyConfigService(config),
697         new MockAsyncProxyResolver(),
698         NULL));
699     GURL test_url("http://local");
700     TestCompletionCallback callback;
701     int rv = service->ResolveProxy(test_url, &info, &callback, NULL, NULL);
702     EXPECT_EQ(OK, rv);
703     EXPECT_TRUE(info.is_direct());
704   }
705 
706   config.proxy_bypass.clear();
707   config.proxy_bypass.push_back("*.org");
708   config.proxy_bypass_local_names = true;
709   {
710     scoped_refptr<ProxyService> service(new ProxyService(
711         new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL));
712     GURL test_url("http://www.webkit.org");
713     TestCompletionCallback callback;
714     int rv = service->ResolveProxy(test_url, &info, &callback, NULL, NULL);
715     EXPECT_EQ(OK, rv);
716     EXPECT_TRUE(info.is_direct());
717   }
718 
719   config.proxy_bypass.clear();
720   config.proxy_bypass.push_back("*.org");
721   config.proxy_bypass.push_back("7*");
722   config.proxy_bypass_local_names = true;
723   {
724     scoped_refptr<ProxyService> service(new ProxyService(
725         new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL));
726     GURL test_url("http://74.125.19.147");
727     TestCompletionCallback callback;
728     int rv = service->ResolveProxy(test_url, &info, &callback, NULL, NULL);
729     EXPECT_EQ(OK, rv);
730     EXPECT_TRUE(info.is_direct());
731   }
732 
733   config.proxy_bypass.clear();
734   config.proxy_bypass.push_back("*.org");
735   config.proxy_bypass_local_names = true;
736   {
737     scoped_refptr<ProxyService> service(new ProxyService(
738         new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL));
739     GURL test_url("http://www.msn.com");
740     TestCompletionCallback callback;
741     int rv = service->ResolveProxy(test_url, &info, &callback, NULL, NULL);
742     EXPECT_EQ(OK, rv);
743     EXPECT_FALSE(info.is_direct());
744   }
745 
746   config.proxy_bypass.clear();
747   config.proxy_bypass.push_back("*.MSN.COM");
748   config.proxy_bypass_local_names = true;
749   {
750     scoped_refptr<ProxyService> service(new ProxyService(
751         new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL));
752     GURL test_url("http://www.msnbc.msn.com");
753     TestCompletionCallback callback;
754     int rv = service->ResolveProxy(test_url, &info, &callback, NULL, NULL);
755     EXPECT_EQ(OK, rv);
756     EXPECT_TRUE(info.is_direct());
757   }
758 
759   config.proxy_bypass.clear();
760   config.proxy_bypass.push_back("*.msn.com");
761   config.proxy_bypass_local_names = true;
762   {
763     scoped_refptr<ProxyService> service(new ProxyService(
764         new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL));
765     GURL test_url("HTTP://WWW.MSNBC.MSN.COM");
766     TestCompletionCallback callback;
767     int rv = service->ResolveProxy(test_url, &info, &callback, NULL, NULL);
768     EXPECT_EQ(OK, rv);
769     EXPECT_TRUE(info.is_direct());
770   }
771 }
772 
TEST(ProxyServiceTest,ProxyBypassListWithPorts)773 TEST(ProxyServiceTest, ProxyBypassListWithPorts) {
774   // Test port specification in bypass list entries.
775   ProxyInfo info;
776   ProxyConfig config;
777   config.proxy_rules.ParseFromString("foopy1:8080;foopy2:9090");
778   config.auto_detect = false;
779   config.proxy_bypass_local_names = false;
780 
781   config.proxy_bypass.clear();
782   config.proxy_bypass.push_back("*.example.com:99");
783   {
784     scoped_refptr<ProxyService> service(new ProxyService(
785         new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL));
786     {
787       GURL test_url("http://www.example.com:99");
788       TestCompletionCallback callback;
789       int rv = service->ResolveProxy(test_url, &info, &callback, NULL, NULL);
790       EXPECT_EQ(OK, rv);
791       EXPECT_TRUE(info.is_direct());
792     }
793     {
794       GURL test_url("http://www.example.com:100");
795       TestCompletionCallback callback;
796       int rv = service->ResolveProxy(test_url, &info, &callback, NULL, NULL);
797       EXPECT_EQ(OK, rv);
798       EXPECT_FALSE(info.is_direct());
799     }
800     {
801       GURL test_url("http://www.example.com");
802       TestCompletionCallback callback;
803       int rv = service->ResolveProxy(test_url, &info, &callback, NULL, NULL);
804       EXPECT_EQ(OK, rv);
805       EXPECT_FALSE(info.is_direct());
806     }
807   }
808 
809   config.proxy_bypass.clear();
810   config.proxy_bypass.push_back("*.example.com:80");
811   {
812     scoped_refptr<ProxyService> service(new ProxyService(
813         new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL));
814     GURL test_url("http://www.example.com");
815     TestCompletionCallback callback;
816     int rv = service->ResolveProxy(test_url, &info, &callback, NULL, NULL);
817     EXPECT_EQ(OK, rv);
818     EXPECT_TRUE(info.is_direct());
819   }
820 
821   config.proxy_bypass.clear();
822   config.proxy_bypass.push_back("*.example.com");
823   {
824     scoped_refptr<ProxyService> service(new ProxyService(
825         new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL));
826     GURL test_url("http://www.example.com:99");
827     TestCompletionCallback callback;
828     int rv = service->ResolveProxy(test_url, &info, &callback, NULL, NULL);
829     EXPECT_EQ(OK, rv);
830     EXPECT_TRUE(info.is_direct());
831   }
832 
833   // IPv6 with port.
834   config.proxy_bypass.clear();
835   config.proxy_bypass.push_back("[3ffe:2a00:100:7031::1]:99");
836   {
837     scoped_refptr<ProxyService> service(new ProxyService(
838         new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL));
839     {
840       GURL test_url("http://[3ffe:2a00:100:7031::1]:99/");
841       TestCompletionCallback callback;
842       int rv = service->ResolveProxy(test_url, &info, &callback, NULL, NULL);
843       EXPECT_EQ(OK, rv);
844       EXPECT_TRUE(info.is_direct());
845     }
846     {
847       GURL test_url("http://[3ffe:2a00:100:7031::1]/");
848       TestCompletionCallback callback;
849       int rv = service->ResolveProxy(test_url, &info, &callback, NULL, NULL);
850       EXPECT_EQ(OK, rv);
851       EXPECT_FALSE(info.is_direct());
852     }
853   }
854 
855   // IPv6 without port. The bypass entry ought to work without the
856   // brackets, but the bypass matching logic in ProxyService is
857   // currently limited.
858   config.proxy_bypass.clear();
859   config.proxy_bypass.push_back("[3ffe:2a00:100:7031::1]");
860   {
861     scoped_refptr<ProxyService> service(new ProxyService(
862         new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL));
863     {
864       GURL test_url("http://[3ffe:2a00:100:7031::1]:99/");
865       TestCompletionCallback callback;
866       int rv = service->ResolveProxy(test_url, &info, &callback, NULL, NULL);
867       EXPECT_EQ(OK, rv);
868       EXPECT_TRUE(info.is_direct());
869     }
870     {
871       GURL test_url("http://[3ffe:2a00:100:7031::1]/");
872       TestCompletionCallback callback;
873       int rv = service->ResolveProxy(test_url, &info, &callback, NULL, NULL);
874       EXPECT_EQ(OK, rv);
875       EXPECT_TRUE(info.is_direct());
876     }
877   }
878 }
879 
TEST(ProxyServiceTest,PerProtocolProxyTests)880 TEST(ProxyServiceTest, PerProtocolProxyTests) {
881   ProxyConfig config;
882   config.proxy_rules.ParseFromString("http=foopy1:8080;https=foopy2:8080");
883   config.auto_detect = false;
884   {
885     scoped_refptr<ProxyService> service(new ProxyService(
886         new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL));
887     GURL test_url("http://www.msn.com");
888     ProxyInfo info;
889     TestCompletionCallback callback;
890     int rv = service->ResolveProxy(test_url, &info, &callback, NULL, NULL);
891     EXPECT_EQ(OK, rv);
892     EXPECT_FALSE(info.is_direct());
893     EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
894   }
895   {
896     scoped_refptr<ProxyService> service(new ProxyService(
897         new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL));
898     GURL test_url("ftp://ftp.google.com");
899     ProxyInfo info;
900     TestCompletionCallback callback;
901     int rv = service->ResolveProxy(test_url, &info, &callback, NULL, NULL);
902     EXPECT_EQ(OK, rv);
903     EXPECT_TRUE(info.is_direct());
904     EXPECT_EQ("direct://", info.proxy_server().ToURI());
905   }
906   {
907     scoped_refptr<ProxyService> service(new ProxyService(
908         new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL));
909     GURL test_url("https://webbranch.techcu.com");
910     ProxyInfo info;
911     TestCompletionCallback callback;
912     int rv = service->ResolveProxy(test_url, &info, &callback, NULL, NULL);
913     EXPECT_EQ(OK, rv);
914     EXPECT_FALSE(info.is_direct());
915     EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI());
916   }
917   {
918     config.proxy_rules.ParseFromString("foopy1:8080");
919     scoped_refptr<ProxyService> service(new ProxyService(
920         new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL));
921     GURL test_url("http://www.microsoft.com");
922     ProxyInfo info;
923     TestCompletionCallback callback;
924     int rv = service->ResolveProxy(test_url, &info, &callback, NULL, NULL);
925     EXPECT_EQ(OK, rv);
926     EXPECT_FALSE(info.is_direct());
927     EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
928   }
929 }
930 
931 // If only HTTP and a SOCKS proxy are specified, check if ftp/https queries
932 // fall back to the SOCKS proxy.
TEST(ProxyServiceTest,DefaultProxyFallbackToSOCKS)933 TEST(ProxyServiceTest, DefaultProxyFallbackToSOCKS) {
934   ProxyConfig config;
935   config.proxy_rules.ParseFromString("http=foopy1:8080;socks=foopy2:1080");
936   config.auto_detect = false;
937   EXPECT_EQ(ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME,
938             config.proxy_rules.type);
939 
940   {
941     scoped_refptr<ProxyService> service(new ProxyService(
942         new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL));
943     GURL test_url("http://www.msn.com");
944     ProxyInfo info;
945     TestCompletionCallback callback;
946     int rv = service->ResolveProxy(test_url, &info, &callback, NULL, NULL);
947     EXPECT_EQ(OK, rv);
948     EXPECT_FALSE(info.is_direct());
949     EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
950   }
951   {
952     scoped_refptr<ProxyService> service(new ProxyService(
953         new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL));
954     GURL test_url("ftp://ftp.google.com");
955     ProxyInfo info;
956     TestCompletionCallback callback;
957     int rv = service->ResolveProxy(test_url, &info, &callback, NULL, NULL);
958     EXPECT_EQ(OK, rv);
959     EXPECT_FALSE(info.is_direct());
960     EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI());
961   }
962   {
963     scoped_refptr<ProxyService> service(new ProxyService(
964         new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL));
965     GURL test_url("https://webbranch.techcu.com");
966     ProxyInfo info;
967     TestCompletionCallback callback;
968     int rv = service->ResolveProxy(test_url, &info, &callback, NULL, NULL);
969     EXPECT_EQ(OK, rv);
970     EXPECT_FALSE(info.is_direct());
971     EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI());
972   }
973   {
974     scoped_refptr<ProxyService> service(new ProxyService(
975         new MockProxyConfigService(config), new MockAsyncProxyResolver, NULL));
976     GURL test_url("unknown://www.microsoft.com");
977     ProxyInfo info;
978     TestCompletionCallback callback;
979     int rv = service->ResolveProxy(test_url, &info, &callback, NULL, NULL);
980     EXPECT_EQ(OK, rv);
981     EXPECT_FALSE(info.is_direct());
982     EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI());
983   }
984 }
985 
986 // Test cancellation of an in-progress request.
TEST(ProxyServiceTest,CancelInProgressRequest)987 TEST(ProxyServiceTest, CancelInProgressRequest) {
988   MockProxyConfigService* config_service =
989       new MockProxyConfigService("http://foopy/proxy.pac");
990 
991   MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
992 
993   scoped_refptr<ProxyService> service(
994       new ProxyService(config_service, resolver, NULL));
995 
996   // Start 3 requests.
997 
998   ProxyInfo info1;
999   TestCompletionCallback callback1;
1000   int rv = service->ResolveProxy(
1001       GURL("http://request1"), &info1, &callback1, NULL, NULL);
1002   EXPECT_EQ(ERR_IO_PENDING, rv);
1003 
1004   // Nothing has been sent to the proxy resolver yet, since the proxy
1005   // resolver has not been configured yet.
1006   ASSERT_EQ(0u, resolver->pending_requests().size());
1007 
1008   // Successfully initialize the PAC script.
1009   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1010             resolver->pending_set_pac_script_request()->pac_url());
1011   resolver->pending_set_pac_script_request()->CompleteNow(OK);
1012 
1013   ASSERT_EQ(1u, resolver->pending_requests().size());
1014   EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
1015 
1016   ProxyInfo info2;
1017   TestCompletionCallback callback2;
1018   ProxyService::PacRequest* request2;
1019   rv = service->ResolveProxy(
1020       GURL("http://request2"), &info2, &callback2, &request2, NULL);
1021   EXPECT_EQ(ERR_IO_PENDING, rv);
1022   ASSERT_EQ(2u, resolver->pending_requests().size());
1023   EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url());
1024 
1025   ProxyInfo info3;
1026   TestCompletionCallback callback3;
1027   rv = service->ResolveProxy(
1028       GURL("http://request3"), &info3, &callback3, NULL, NULL);
1029   EXPECT_EQ(ERR_IO_PENDING, rv);
1030   ASSERT_EQ(3u, resolver->pending_requests().size());
1031   EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[2]->url());
1032 
1033   // Cancel the second request
1034   service->CancelPacRequest(request2);
1035 
1036   ASSERT_EQ(2u, resolver->pending_requests().size());
1037   EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
1038   EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[1]->url());
1039 
1040   // Complete the two un-cancelled requests.
1041   // We complete the last one first, just to mix it up a bit.
1042   resolver->pending_requests()[1]->results()->UseNamedProxy("request3:80");
1043   resolver->pending_requests()[1]->CompleteNow(OK);
1044 
1045   resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
1046   resolver->pending_requests()[0]->CompleteNow(OK);
1047 
1048   // Complete and verify that requests ran as expected.
1049   EXPECT_EQ(OK, callback1.WaitForResult());
1050   EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
1051 
1052   EXPECT_FALSE(callback2.have_result());  // Cancelled.
1053   ASSERT_EQ(1u, resolver->cancelled_requests().size());
1054   EXPECT_EQ(GURL("http://request2"), resolver->cancelled_requests()[0]->url());
1055 
1056   EXPECT_EQ(OK, callback3.WaitForResult());
1057   EXPECT_EQ("request3:80", info3.proxy_server().ToURI());
1058 }
1059 
1060 // Test the initial PAC download for resolver that expects bytes.
TEST(ProxyServiceTest,InitialPACScriptDownload)1061 TEST(ProxyServiceTest, InitialPACScriptDownload) {
1062   MockProxyConfigService* config_service =
1063       new MockProxyConfigService("http://foopy/proxy.pac");
1064 
1065   MockAsyncProxyResolverExpectsBytes* resolver =
1066       new MockAsyncProxyResolverExpectsBytes;
1067 
1068   scoped_refptr<ProxyService> service(
1069       new ProxyService(config_service, resolver, NULL));
1070 
1071   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1072   service->SetProxyScriptFetcher(fetcher);
1073 
1074   // Start 3 requests.
1075 
1076   ProxyInfo info1;
1077   TestCompletionCallback callback1;
1078   int rv = service->ResolveProxy(
1079       GURL("http://request1"), &info1, &callback1, NULL, NULL);
1080   EXPECT_EQ(ERR_IO_PENDING, rv);
1081 
1082   // The first request should have triggered download of PAC script.
1083   EXPECT_TRUE(fetcher->has_pending_request());
1084   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1085 
1086   ProxyInfo info2;
1087   TestCompletionCallback callback2;
1088   rv = service->ResolveProxy(
1089       GURL("http://request2"), &info2, &callback2, NULL, NULL);
1090   EXPECT_EQ(ERR_IO_PENDING, rv);
1091 
1092   ProxyInfo info3;
1093   TestCompletionCallback callback3;
1094   rv = service->ResolveProxy(
1095       GURL("http://request3"), &info3, &callback3, NULL, NULL);
1096   EXPECT_EQ(ERR_IO_PENDING, rv);
1097 
1098   // Nothing has been sent to the resolver yet.
1099   EXPECT_TRUE(resolver->pending_requests().empty());
1100 
1101   // At this point the ProxyService should be waiting for the
1102   // ProxyScriptFetcher to invoke its completion callback, notifying it of
1103   // PAC script download completion.
1104   fetcher->NotifyFetchCompletion(OK, "pac-v1");
1105 
1106   // Now that the PAC script is downloaded, it will have been sent to the proxy
1107   // resolver.
1108   EXPECT_EQ("pac-v1", resolver->pending_set_pac_script_request()->pac_bytes());
1109   resolver->pending_set_pac_script_request()->CompleteNow(OK);
1110 
1111   ASSERT_EQ(3u, resolver->pending_requests().size());
1112   EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
1113   EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url());
1114   EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[2]->url());
1115 
1116   // Complete all the requests (in some order).
1117   // Note that as we complete requests, they shift up in |pending_requests()|.
1118 
1119   resolver->pending_requests()[2]->results()->UseNamedProxy("request3:80");
1120   resolver->pending_requests()[2]->CompleteNow(OK);
1121 
1122   resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
1123   resolver->pending_requests()[0]->CompleteNow(OK);
1124 
1125   resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80");
1126   resolver->pending_requests()[0]->CompleteNow(OK);
1127 
1128   // Complete and verify that requests ran as expected.
1129   EXPECT_EQ(OK, callback1.WaitForResult());
1130   EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
1131 
1132   EXPECT_EQ(OK, callback2.WaitForResult());
1133   EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
1134 
1135   EXPECT_EQ(OK, callback3.WaitForResult());
1136   EXPECT_EQ("request3:80", info3.proxy_server().ToURI());
1137 }
1138 
1139 // Test changing the ProxyScriptFetcher while PAC download is in progress.
TEST(ProxyServiceTest,ChangeScriptFetcherWhilePACDownloadInProgress)1140 TEST(ProxyServiceTest, ChangeScriptFetcherWhilePACDownloadInProgress) {
1141   MockProxyConfigService* config_service =
1142       new MockProxyConfigService("http://foopy/proxy.pac");
1143 
1144   MockAsyncProxyResolverExpectsBytes* resolver =
1145       new MockAsyncProxyResolverExpectsBytes;
1146 
1147   scoped_refptr<ProxyService> service(
1148       new ProxyService(config_service, resolver, NULL));
1149 
1150   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1151   service->SetProxyScriptFetcher(fetcher);
1152 
1153   // Start 2 requests.
1154 
1155   ProxyInfo info1;
1156   TestCompletionCallback callback1;
1157   int rv = service->ResolveProxy(
1158       GURL("http://request1"), &info1, &callback1, NULL, NULL);
1159   EXPECT_EQ(ERR_IO_PENDING, rv);
1160 
1161   // The first request should have triggered download of PAC script.
1162   EXPECT_TRUE(fetcher->has_pending_request());
1163   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1164 
1165   ProxyInfo info2;
1166   TestCompletionCallback callback2;
1167   rv = service->ResolveProxy(
1168       GURL("http://request2"), &info2, &callback2, NULL, NULL);
1169   EXPECT_EQ(ERR_IO_PENDING, rv);
1170 
1171   // At this point the ProxyService should be waiting for the
1172   // ProxyScriptFetcher to invoke its completion callback, notifying it of
1173   // PAC script download completion.
1174 
1175   // We now change out the ProxyService's script fetcher. We should restart
1176   // the initialization with the new fetcher.
1177 
1178   fetcher = new MockProxyScriptFetcher;
1179   service->SetProxyScriptFetcher(fetcher);
1180 
1181   // Nothing has been sent to the resolver yet.
1182   EXPECT_TRUE(resolver->pending_requests().empty());
1183 
1184   fetcher->NotifyFetchCompletion(OK, "pac-v1");
1185 
1186   // Now that the PAC script is downloaded, it will have been sent to the proxy
1187   // resolver.
1188   EXPECT_EQ("pac-v1", resolver->pending_set_pac_script_request()->pac_bytes());
1189   resolver->pending_set_pac_script_request()->CompleteNow(OK);
1190 
1191   ASSERT_EQ(2u, resolver->pending_requests().size());
1192   EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
1193   EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url());
1194 }
1195 
1196 // Test cancellation of a request, while the PAC script is being fetched.
TEST(ProxyServiceTest,CancelWhilePACFetching)1197 TEST(ProxyServiceTest, CancelWhilePACFetching) {
1198   MockProxyConfigService* config_service =
1199       new MockProxyConfigService("http://foopy/proxy.pac");
1200 
1201   MockAsyncProxyResolverExpectsBytes* resolver =
1202       new MockAsyncProxyResolverExpectsBytes;
1203 
1204   scoped_refptr<ProxyService> service(
1205       new ProxyService(config_service, resolver, NULL));
1206 
1207   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1208   service->SetProxyScriptFetcher(fetcher);
1209 
1210   // Start 3 requests.
1211   ProxyInfo info1;
1212   TestCompletionCallback callback1;
1213   ProxyService::PacRequest* request1;
1214   scoped_refptr<LoadLog> log1(new LoadLog(LoadLog::kUnbounded));
1215   int rv = service->ResolveProxy(
1216       GURL("http://request1"), &info1, &callback1, &request1, log1);
1217   EXPECT_EQ(ERR_IO_PENDING, rv);
1218 
1219   // The first request should have triggered download of PAC script.
1220   EXPECT_TRUE(fetcher->has_pending_request());
1221   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1222 
1223   ProxyInfo info2;
1224   TestCompletionCallback callback2;
1225   ProxyService::PacRequest* request2;
1226   rv = service->ResolveProxy(
1227       GURL("http://request2"), &info2, &callback2, &request2, NULL);
1228   EXPECT_EQ(ERR_IO_PENDING, rv);
1229 
1230   ProxyInfo info3;
1231   TestCompletionCallback callback3;
1232   rv = service->ResolveProxy(
1233       GURL("http://request3"), &info3, &callback3, NULL, NULL);
1234   EXPECT_EQ(ERR_IO_PENDING, rv);
1235 
1236   // Nothing has been sent to the resolver yet.
1237   EXPECT_TRUE(resolver->pending_requests().empty());
1238 
1239   // Cancel the first 2 requests.
1240   service->CancelPacRequest(request1);
1241   service->CancelPacRequest(request2);
1242 
1243   // At this point the ProxyService should be waiting for the
1244   // ProxyScriptFetcher to invoke its completion callback, notifying it of
1245   // PAC script download completion.
1246   fetcher->NotifyFetchCompletion(OK, "pac-v1");
1247 
1248   // Now that the PAC script is downloaded, it will have been sent to the
1249   // proxy resolver.
1250   EXPECT_EQ("pac-v1", resolver->pending_set_pac_script_request()->pac_bytes());
1251   resolver->pending_set_pac_script_request()->CompleteNow(OK);
1252 
1253   ASSERT_EQ(1u, resolver->pending_requests().size());
1254   EXPECT_EQ(GURL("http://request3"), resolver->pending_requests()[0]->url());
1255 
1256   // Complete all the requests.
1257   resolver->pending_requests()[0]->results()->UseNamedProxy("request3:80");
1258   resolver->pending_requests()[0]->CompleteNow(OK);
1259 
1260   EXPECT_EQ(OK, callback3.WaitForResult());
1261   EXPECT_EQ("request3:80", info3.proxy_server().ToURI());
1262 
1263   EXPECT_TRUE(resolver->cancelled_requests().empty());
1264 
1265   EXPECT_FALSE(callback1.have_result());  // Cancelled.
1266   EXPECT_FALSE(callback2.have_result());  // Cancelled.
1267 
1268   // Check the LoadLog for request 1 (which was cancelled) got filled properly.
1269   EXPECT_EQ(6u, log1->entries().size());
1270   EXPECT_TRUE(LogContainsBeginEvent(*log1, 0, LoadLog::TYPE_PROXY_SERVICE));
1271   EXPECT_TRUE(LogContainsBeginEvent(
1272       *log1, 3, LoadLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC));
1273   // Note that TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC is never completed before
1274   // the cancellation occured.
1275   EXPECT_TRUE(LogContainsEvent(
1276       *log1, 4, LoadLog::TYPE_CANCELLED, LoadLog::PHASE_NONE));
1277   EXPECT_TRUE(LogContainsEndEvent(*log1, 5, LoadLog::TYPE_PROXY_SERVICE));
1278 }
1279 
1280 // Test that if auto-detect fails, we fall-back to the custom pac.
TEST(ProxyServiceTest,FallbackFromAutodetectToCustomPac)1281 TEST(ProxyServiceTest, FallbackFromAutodetectToCustomPac) {
1282   ProxyConfig config;
1283   config.auto_detect = true;
1284   config.pac_url = GURL("http://foopy/proxy.pac");
1285   config.proxy_rules.ParseFromString("http=foopy:80");  // Won't be used.
1286 
1287   MockProxyConfigService* config_service = new MockProxyConfigService(config);
1288   MockAsyncProxyResolverExpectsBytes* resolver =
1289       new MockAsyncProxyResolverExpectsBytes;
1290   scoped_refptr<ProxyService> service(
1291       new ProxyService(config_service, resolver, NULL));
1292 
1293   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1294   service->SetProxyScriptFetcher(fetcher);
1295 
1296   // Start 2 requests.
1297 
1298   ProxyInfo info1;
1299   TestCompletionCallback callback1;
1300   int rv = service->ResolveProxy(
1301       GURL("http://request1"), &info1, &callback1, NULL, NULL);
1302   EXPECT_EQ(ERR_IO_PENDING, rv);
1303 
1304   ProxyInfo info2;
1305   TestCompletionCallback callback2;
1306   ProxyService::PacRequest* request2;
1307   rv = service->ResolveProxy(
1308       GURL("http://request2"), &info2, &callback2, &request2, NULL);
1309   EXPECT_EQ(ERR_IO_PENDING, rv);
1310 
1311   // Check that nothing has been sent to the proxy resolver yet.
1312   ASSERT_EQ(0u, resolver->pending_requests().size());
1313 
1314   // It should be trying to auto-detect first -- FAIL the autodetect during
1315   // the script download.
1316   EXPECT_TRUE(fetcher->has_pending_request());
1317   EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
1318   fetcher->NotifyFetchCompletion(ERR_FAILED, "");
1319 
1320   // Next it should be trying the custom PAC url.
1321   EXPECT_TRUE(fetcher->has_pending_request());
1322   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1323   fetcher->NotifyFetchCompletion(OK, "custom-pac-script");
1324 
1325   EXPECT_EQ("custom-pac-script",
1326             resolver->pending_set_pac_script_request()->pac_bytes());
1327   resolver->pending_set_pac_script_request()->CompleteNow(OK);
1328 
1329   // Now finally, the pending requests should have been sent to the resolver
1330   // (which was initialized with custom PAC script).
1331 
1332   ASSERT_EQ(2u, resolver->pending_requests().size());
1333   EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
1334   EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url());
1335 
1336   // Complete the pending requests.
1337   resolver->pending_requests()[1]->results()->UseNamedProxy("request2:80");
1338   resolver->pending_requests()[1]->CompleteNow(OK);
1339   resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
1340   resolver->pending_requests()[0]->CompleteNow(OK);
1341 
1342   // Verify that requests ran as expected.
1343   EXPECT_EQ(OK, callback1.WaitForResult());
1344   EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
1345 
1346   EXPECT_EQ(OK, callback2.WaitForResult());
1347   EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
1348 }
1349 
1350 // This is the same test as FallbackFromAutodetectToCustomPac, except
1351 // the auto-detect script fails parsing rather than downloading.
TEST(ProxyServiceTest,FallbackFromAutodetectToCustomPac2)1352 TEST(ProxyServiceTest, FallbackFromAutodetectToCustomPac2) {
1353   ProxyConfig config;
1354   config.auto_detect = true;
1355   config.pac_url = GURL("http://foopy/proxy.pac");
1356   config.proxy_rules.ParseFromString("http=foopy:80");  // Won't be used.
1357 
1358   MockProxyConfigService* config_service = new MockProxyConfigService(config);
1359   MockAsyncProxyResolverExpectsBytes* resolver =
1360       new MockAsyncProxyResolverExpectsBytes;
1361   scoped_refptr<ProxyService> service(
1362       new ProxyService(config_service, resolver, NULL));
1363 
1364   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1365   service->SetProxyScriptFetcher(fetcher);
1366 
1367   // Start 2 requests.
1368 
1369   ProxyInfo info1;
1370   TestCompletionCallback callback1;
1371   int rv = service->ResolveProxy(
1372       GURL("http://request1"), &info1, &callback1, NULL, NULL);
1373   EXPECT_EQ(ERR_IO_PENDING, rv);
1374 
1375   ProxyInfo info2;
1376   TestCompletionCallback callback2;
1377   ProxyService::PacRequest* request2;
1378   rv = service->ResolveProxy(
1379       GURL("http://request2"), &info2, &callback2, &request2, NULL);
1380   EXPECT_EQ(ERR_IO_PENDING, rv);
1381 
1382   // Check that nothing has been sent to the proxy resolver yet.
1383   ASSERT_EQ(0u, resolver->pending_requests().size());
1384 
1385   // It should be trying to auto-detect first -- succeed the download.
1386   EXPECT_TRUE(fetcher->has_pending_request());
1387   EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
1388   fetcher->NotifyFetchCompletion(OK, "invalid-script-contents");
1389 
1390   // Simulate a parse error.
1391   EXPECT_EQ("invalid-script-contents",
1392             resolver->pending_set_pac_script_request()->pac_bytes());
1393   resolver->pending_set_pac_script_request()->CompleteNow(
1394       ERR_PAC_SCRIPT_FAILED);
1395 
1396   // Next it should be trying the custom PAC url.
1397   EXPECT_TRUE(fetcher->has_pending_request());
1398   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1399   fetcher->NotifyFetchCompletion(OK, "custom-pac-script");
1400 
1401   EXPECT_EQ("custom-pac-script",
1402             resolver->pending_set_pac_script_request()->pac_bytes());
1403   resolver->pending_set_pac_script_request()->CompleteNow(OK);
1404 
1405   // Now finally, the pending requests should have been sent to the resolver
1406   // (which was initialized with custom PAC script).
1407 
1408   ASSERT_EQ(2u, resolver->pending_requests().size());
1409   EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
1410   EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[1]->url());
1411 
1412   // Complete the pending requests.
1413   resolver->pending_requests()[1]->results()->UseNamedProxy("request2:80");
1414   resolver->pending_requests()[1]->CompleteNow(OK);
1415   resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
1416   resolver->pending_requests()[0]->CompleteNow(OK);
1417 
1418   // Verify that requests ran as expected.
1419   EXPECT_EQ(OK, callback1.WaitForResult());
1420   EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
1421 
1422   EXPECT_EQ(OK, callback2.WaitForResult());
1423   EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
1424 }
1425 
1426 // Test that if all of auto-detect, a custom PAC script, and manual settings
1427 // are given, then we will try them in that order.
TEST(ProxyServiceTest,FallbackFromAutodetectToCustomToManual)1428 TEST(ProxyServiceTest, FallbackFromAutodetectToCustomToManual) {
1429   ProxyConfig config;
1430   config.auto_detect = true;
1431   config.pac_url = GURL("http://foopy/proxy.pac");
1432   config.proxy_rules.ParseFromString("http=foopy:80");
1433 
1434   MockProxyConfigService* config_service = new MockProxyConfigService(config);
1435   MockAsyncProxyResolverExpectsBytes* resolver =
1436       new MockAsyncProxyResolverExpectsBytes;
1437   scoped_refptr<ProxyService> service(
1438       new ProxyService(config_service, resolver, NULL));
1439 
1440   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1441   service->SetProxyScriptFetcher(fetcher);
1442 
1443   // Start 2 requests.
1444 
1445   ProxyInfo info1;
1446   TestCompletionCallback callback1;
1447   int rv = service->ResolveProxy(
1448       GURL("http://request1"), &info1, &callback1, NULL, NULL);
1449   EXPECT_EQ(ERR_IO_PENDING, rv);
1450 
1451   ProxyInfo info2;
1452   TestCompletionCallback callback2;
1453   ProxyService::PacRequest* request2;
1454   rv = service->ResolveProxy(
1455       GURL("http://request2"), &info2, &callback2, &request2, NULL);
1456   EXPECT_EQ(ERR_IO_PENDING, rv);
1457 
1458   // Check that nothing has been sent to the proxy resolver yet.
1459   ASSERT_EQ(0u, resolver->pending_requests().size());
1460 
1461   // It should be trying to auto-detect first -- fail the download.
1462   EXPECT_TRUE(fetcher->has_pending_request());
1463   EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
1464   fetcher->NotifyFetchCompletion(ERR_FAILED, "");
1465 
1466   // Next it should be trying the custom PAC url -- fail the download.
1467   EXPECT_TRUE(fetcher->has_pending_request());
1468   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1469   fetcher->NotifyFetchCompletion(ERR_FAILED, "");
1470 
1471   // Since we never managed to initialize a ProxyResolver, nothing should have
1472   // been sent to it.
1473   ASSERT_EQ(0u, resolver->pending_requests().size());
1474 
1475   // Verify that requests ran as expected -- they should have fallen back to
1476   // the manual proxy configuration for HTTP urls.
1477   EXPECT_EQ(OK, callback1.WaitForResult());
1478   EXPECT_EQ("foopy:80", info1.proxy_server().ToURI());
1479 
1480   EXPECT_EQ(OK, callback2.WaitForResult());
1481   EXPECT_EQ("foopy:80", info2.proxy_server().ToURI());
1482 }
1483 
1484 // Test that the bypass rules are NOT applied when using autodetect.
TEST(ProxyServiceTest,BypassDoesntApplyToPac)1485 TEST(ProxyServiceTest, BypassDoesntApplyToPac) {
1486   ProxyConfig config;
1487   config.auto_detect = true;
1488   config.pac_url = GURL("http://foopy/proxy.pac");
1489   config.proxy_rules.ParseFromString("http=foopy:80");  // Not used.
1490   config.proxy_bypass.push_back("www.google.com");
1491 
1492   MockProxyConfigService* config_service = new MockProxyConfigService(config);
1493   MockAsyncProxyResolverExpectsBytes* resolver =
1494       new MockAsyncProxyResolverExpectsBytes;
1495   scoped_refptr<ProxyService> service(
1496       new ProxyService(config_service, resolver, NULL));
1497 
1498   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1499   service->SetProxyScriptFetcher(fetcher);
1500 
1501   // Start 1 requests.
1502 
1503   ProxyInfo info1;
1504   TestCompletionCallback callback1;
1505   int rv = service->ResolveProxy(
1506       GURL("http://www.google.com"), &info1, &callback1, NULL, NULL);
1507   EXPECT_EQ(ERR_IO_PENDING, rv);
1508 
1509   // Check that nothing has been sent to the proxy resolver yet.
1510   ASSERT_EQ(0u, resolver->pending_requests().size());
1511 
1512   // It should be trying to auto-detect first -- succeed the download.
1513   EXPECT_TRUE(fetcher->has_pending_request());
1514   EXPECT_EQ(GURL("http://wpad/wpad.dat"), fetcher->pending_request_url());
1515   fetcher->NotifyFetchCompletion(OK, "auto-detect");
1516 
1517   EXPECT_EQ("auto-detect",
1518             resolver->pending_set_pac_script_request()->pac_bytes());
1519   resolver->pending_set_pac_script_request()->CompleteNow(OK);
1520 
1521   ASSERT_EQ(1u, resolver->pending_requests().size());
1522   EXPECT_EQ(GURL("http://www.google.com"),
1523             resolver->pending_requests()[0]->url());
1524 
1525   // Complete the pending request.
1526   resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
1527   resolver->pending_requests()[0]->CompleteNow(OK);
1528 
1529   // Verify that request ran as expected.
1530   EXPECT_EQ(OK, callback1.WaitForResult());
1531   EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
1532 
1533   // Start another request, it should pickup the bypass item.
1534   ProxyInfo info2;
1535   TestCompletionCallback callback2;
1536   rv = service->ResolveProxy(
1537       GURL("http://www.google.com"), &info2, &callback2, NULL, NULL);
1538   EXPECT_EQ(ERR_IO_PENDING, rv);
1539 
1540   ASSERT_EQ(1u, resolver->pending_requests().size());
1541   EXPECT_EQ(GURL("http://www.google.com"),
1542             resolver->pending_requests()[0]->url());
1543 
1544   // Complete the pending request.
1545   resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80");
1546   resolver->pending_requests()[0]->CompleteNow(OK);
1547 
1548   EXPECT_EQ(OK, callback2.WaitForResult());
1549   EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
1550 }
1551 
1552 // Delete the ProxyService while InitProxyResolver has an outstanding
1553 // request to the script fetcher. When run under valgrind, should not
1554 // have any memory errors (used to be that the ProxyScriptFetcher was
1555 // being deleted prior to the InitProxyResolver).
TEST(ProxyServiceTest,DeleteWhileInitProxyResolverHasOutstandingFetch)1556 TEST(ProxyServiceTest, DeleteWhileInitProxyResolverHasOutstandingFetch) {
1557   ProxyConfig config;
1558   config.pac_url = GURL("http://foopy/proxy.pac");
1559 
1560   MockProxyConfigService* config_service = new MockProxyConfigService(config);
1561   MockAsyncProxyResolverExpectsBytes* resolver =
1562       new MockAsyncProxyResolverExpectsBytes;
1563   scoped_refptr<ProxyService> service(
1564       new ProxyService(config_service, resolver, NULL));
1565 
1566   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1567   service->SetProxyScriptFetcher(fetcher);
1568 
1569   // Start 1 request.
1570 
1571   ProxyInfo info1;
1572   TestCompletionCallback callback1;
1573   int rv = service->ResolveProxy(
1574       GURL("http://www.google.com"), &info1, &callback1, NULL, NULL);
1575   EXPECT_EQ(ERR_IO_PENDING, rv);
1576 
1577   // Check that nothing has been sent to the proxy resolver yet.
1578   ASSERT_EQ(0u, resolver->pending_requests().size());
1579 
1580   // InitProxyResolver should have issued a request to the ProxyScriptFetcher
1581   // and be waiting on that to complete.
1582   EXPECT_TRUE(fetcher->has_pending_request());
1583   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1584 
1585   // Delete the ProxyService
1586   service = NULL;
1587 }
1588 
1589 // Delete the ProxyService while InitProxyResolver has an outstanding
1590 // request to the proxy resolver. When run under valgrind, should not
1591 // have any memory errors (used to be that the ProxyResolver was
1592 // being deleted prior to the InitProxyResolver).
TEST(ProxyServiceTest,DeleteWhileInitProxyResolverHasOutstandingSet)1593 TEST(ProxyServiceTest, DeleteWhileInitProxyResolverHasOutstandingSet) {
1594   MockProxyConfigService* config_service =
1595       new MockProxyConfigService("http://foopy/proxy.pac");
1596 
1597   MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
1598 
1599   scoped_refptr<ProxyService> service(
1600       new ProxyService(config_service, resolver, NULL));
1601 
1602   GURL url("http://www.google.com/");
1603 
1604   ProxyInfo info;
1605   TestCompletionCallback callback;
1606   int rv = service->ResolveProxy(url, &info, &callback, NULL, NULL);
1607   EXPECT_EQ(ERR_IO_PENDING, rv);
1608 
1609   EXPECT_EQ(GURL("http://foopy/proxy.pac"),
1610             resolver->pending_set_pac_script_request()->pac_url());
1611 
1612   // Delete the ProxyService.
1613   service = NULL;
1614 }
1615 
TEST(ProxyServiceTest,ResetProxyConfigService)1616 TEST(ProxyServiceTest, ResetProxyConfigService) {
1617   ProxyConfig config1;
1618   config1.proxy_rules.ParseFromString("foopy1:8080");
1619   config1.auto_detect = false;
1620   scoped_refptr<ProxyService> service(new ProxyService(
1621       new MockProxyConfigService(config1),
1622       new MockAsyncProxyResolverExpectsBytes,
1623       NULL));
1624 
1625   ProxyInfo info;
1626   TestCompletionCallback callback1;
1627   int rv = service->ResolveProxy(
1628       GURL("http://request1"), &info, &callback1, NULL, NULL);
1629   EXPECT_EQ(OK, rv);
1630   EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI());
1631 
1632   ProxyConfig config2;
1633   config2.proxy_rules.ParseFromString("foopy2:8080");
1634   config2.auto_detect = false;
1635   service->ResetConfigService(new MockProxyConfigService(config2));
1636   TestCompletionCallback callback2;
1637   rv = service->ResolveProxy(
1638       GURL("http://request2"), &info, &callback2, NULL, NULL);
1639   EXPECT_EQ(OK, rv);
1640   EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI());
1641 }
1642 
TEST(ProxyServiceTest,IsLocalName)1643 TEST(ProxyServiceTest, IsLocalName) {
1644   const struct {
1645     const char* url;
1646     bool expected_is_local;
1647   } tests[] = {
1648     // Single-component hostnames are considered local.
1649     {"http://localhost/x", true},
1650     {"http://www", true},
1651 
1652     // IPv4 loopback interface.
1653     {"http://127.0.0.1/x", true},
1654     {"http://127.0.0.1:80/x", true},
1655 
1656     // IPv6 loopback interface.
1657     {"http://[::1]:80/x", true},
1658     {"http://[0:0::1]:6233/x", true},
1659     {"http://[0:0:0:0:0:0:0:1]/x", true},
1660 
1661     // Non-local URLs.
1662     {"http://foo.com/", false},
1663     {"http://localhost.i/", false},
1664     {"http://www.google.com/", false},
1665     {"http://192.168.0.1/", false},
1666 
1667     // Try with different protocols.
1668     {"ftp://127.0.0.1/x", true},
1669     {"ftp://foobar.com/x", false},
1670 
1671     // This is a bit of a gray-area, but GURL does not strip trailing dots
1672     // in host-names, so the following are considered non-local.
1673     {"http://www./x", false},
1674     {"http://localhost./x", false},
1675   };
1676 
1677   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
1678     SCOPED_TRACE(StringPrintf("Test[%" PRIuS "]: %s", i, tests[i].url));
1679     bool is_local = ProxyService::IsLocalName(GURL(tests[i].url));
1680     EXPECT_EQ(tests[i].expected_is_local, is_local);
1681   }
1682 }
1683 
1684 // Check that after we have done the auto-detect test, and the configuration
1685 // is updated (with no change), we don't re-try the autodetect test.
1686 // Regression test for http://crbug.com/18526 -- the configuration was being
1687 // mutated to cancel out the automatic settings, which meant UpdateConfig()
1688 // thought it had received a new configuration.
TEST(ProxyServiceTest,UpdateConfigAfterFailedAutodetect)1689 TEST(ProxyServiceTest, UpdateConfigAfterFailedAutodetect) {
1690   ProxyConfig config;
1691   config.auto_detect = true;
1692 
1693   MockProxyConfigService* config_service = new MockProxyConfigService(config);
1694   MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
1695   scoped_refptr<ProxyService> service(
1696       new ProxyService(config_service, resolver, NULL));
1697 
1698   // Start 1 requests.
1699 
1700   ProxyInfo info1;
1701   TestCompletionCallback callback1;
1702   int rv = service->ResolveProxy(
1703       GURL("http://www.google.com"), &info1, &callback1, NULL, NULL);
1704   EXPECT_EQ(ERR_IO_PENDING, rv);
1705 
1706   // Check that nothing has been sent to the proxy resolver yet.
1707   ASSERT_EQ(0u, resolver->pending_requests().size());
1708 
1709   // Fail the setting of autodetect script.
1710   EXPECT_EQ(GURL(), resolver->pending_set_pac_script_request()->pac_url());
1711   resolver->pending_set_pac_script_request()->CompleteNow(ERR_FAILED);
1712 
1713   // Verify that request ran as expected -- should have fallen back to direct.
1714   EXPECT_EQ(OK, callback1.WaitForResult());
1715   EXPECT_TRUE(info1.is_direct());
1716 
1717   // Force the ProxyService to pull down a new proxy configuration.
1718   // (Even though the configuration isn't old/bad).
1719   service->UpdateConfig(NULL);
1720 
1721   // Start another request -- the effective configuration has not
1722   // changed, so we shouldn't re-run the autodetect step.
1723   // Rather, it should complete synchronously as direct-connect.
1724   ProxyInfo info2;
1725   TestCompletionCallback callback2;
1726   rv = service->ResolveProxy(
1727       GURL("http://www.google.com"), &info2, &callback2, NULL, NULL);
1728   EXPECT_EQ(OK, rv);
1729 
1730   EXPECT_TRUE(info2.is_direct());
1731 }
1732 
1733 // Test that when going from a configuration that required PAC to one
1734 // that does NOT, we unset the variable |should_use_proxy_resolver_|.
TEST(ProxyServiceTest,UpdateConfigFromPACToDirect)1735 TEST(ProxyServiceTest, UpdateConfigFromPACToDirect) {
1736   ProxyConfig config;
1737   config.auto_detect = true;
1738 
1739   MockProxyConfigService* config_service = new MockProxyConfigService(config);
1740   MockAsyncProxyResolver* resolver = new MockAsyncProxyResolver;
1741   scoped_refptr<ProxyService> service(
1742       new ProxyService(config_service, resolver, NULL));
1743 
1744   // Start 1 request.
1745 
1746   ProxyInfo info1;
1747   TestCompletionCallback callback1;
1748   int rv = service->ResolveProxy(
1749       GURL("http://www.google.com"), &info1, &callback1, NULL, NULL);
1750   EXPECT_EQ(ERR_IO_PENDING, rv);
1751 
1752   // Check that nothing has been sent to the proxy resolver yet.
1753   ASSERT_EQ(0u, resolver->pending_requests().size());
1754 
1755   // Successfully set the autodetect script.
1756   EXPECT_EQ(GURL(), resolver->pending_set_pac_script_request()->pac_url());
1757   resolver->pending_set_pac_script_request()->CompleteNow(OK);
1758 
1759   // Complete the pending request.
1760   ASSERT_EQ(1u, resolver->pending_requests().size());
1761   resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
1762   resolver->pending_requests()[0]->CompleteNow(OK);
1763 
1764   // Verify that request ran as expected.
1765   EXPECT_EQ(OK, callback1.WaitForResult());
1766   EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
1767 
1768   // Force the ProxyService to pull down a new proxy configuration.
1769   // (Even though the configuration isn't old/bad).
1770   //
1771   // This new configuration no longer has auto_detect set, so
1772   // requests should complete synchronously now as direct-connect.
1773   config.auto_detect = false;
1774   config_service->config = config;
1775   service->UpdateConfig(NULL);
1776 
1777   // Start another request -- the effective configuration has changed.
1778   ProxyInfo info2;
1779   TestCompletionCallback callback2;
1780   rv = service->ResolveProxy(
1781       GURL("http://www.google.com"), &info2, &callback2, NULL, NULL);
1782   EXPECT_EQ(OK, rv);
1783 
1784   EXPECT_TRUE(info2.is_direct());
1785 }
1786 
TEST(ProxyServiceTest,NetworkChangeTriggersPacRefetch)1787 TEST(ProxyServiceTest, NetworkChangeTriggersPacRefetch) {
1788   MockProxyConfigService* config_service =
1789       new MockProxyConfigService("http://foopy/proxy.pac");
1790 
1791   MockAsyncProxyResolverExpectsBytes* resolver =
1792       new MockAsyncProxyResolverExpectsBytes;
1793 
1794   MockNetworkChangeNotifier network_change_notifier;
1795 
1796   scoped_refptr<ProxyService> service(
1797       new ProxyService(config_service, resolver, &network_change_notifier));
1798 
1799   MockProxyScriptFetcher* fetcher = new MockProxyScriptFetcher;
1800   service->SetProxyScriptFetcher(fetcher);
1801 
1802   // Start 1 request.
1803 
1804   ProxyInfo info1;
1805   TestCompletionCallback callback1;
1806   int rv = service->ResolveProxy(
1807       GURL("http://request1"), &info1, &callback1, NULL, NULL);
1808   EXPECT_EQ(ERR_IO_PENDING, rv);
1809 
1810   // The first request should have triggered initial download of PAC script.
1811   EXPECT_TRUE(fetcher->has_pending_request());
1812   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1813 
1814   // Nothing has been sent to the resolver yet.
1815   EXPECT_TRUE(resolver->pending_requests().empty());
1816 
1817   // At this point the ProxyService should be waiting for the
1818   // ProxyScriptFetcher to invoke its completion callback, notifying it of
1819   // PAC script download completion.
1820   fetcher->NotifyFetchCompletion(OK, "pac-v1");
1821 
1822   // Now that the PAC script is downloaded, the request will have been sent to
1823   // the proxy resolver.
1824   EXPECT_EQ("pac-v1", resolver->pending_set_pac_script_request()->pac_bytes());
1825   resolver->pending_set_pac_script_request()->CompleteNow(OK);
1826 
1827   ASSERT_EQ(1u, resolver->pending_requests().size());
1828   EXPECT_EQ(GURL("http://request1"), resolver->pending_requests()[0]->url());
1829 
1830   // Complete the pending request.
1831   resolver->pending_requests()[0]->results()->UseNamedProxy("request1:80");
1832   resolver->pending_requests()[0]->CompleteNow(OK);
1833 
1834   // Wait for completion callback, and verify that the request ran as expected.
1835   EXPECT_EQ(OK, callback1.WaitForResult());
1836   EXPECT_EQ("request1:80", info1.proxy_server().ToURI());
1837 
1838   // Now simluate a change in the network. The ProxyConfigService is still
1839   // going to return the same PAC URL as before, but this URL needs to be
1840   // refetched on the new network.
1841 
1842   network_change_notifier.NotifyIPAddressChange();
1843 
1844   // Start a second request.
1845   ProxyInfo info2;
1846   TestCompletionCallback callback2;
1847   rv = service->ResolveProxy(
1848       GURL("http://request2"), &info2, &callback2, NULL, NULL);
1849   EXPECT_EQ(ERR_IO_PENDING, rv);
1850 
1851   // This second request should have triggered the re-download of the PAC
1852   // script (since we marked the network as having changed).
1853   EXPECT_TRUE(fetcher->has_pending_request());
1854   EXPECT_EQ(GURL("http://foopy/proxy.pac"), fetcher->pending_request_url());
1855 
1856   // Nothing has been sent to the resolver yet.
1857   EXPECT_TRUE(resolver->pending_requests().empty());
1858 
1859   // Simulate the PAC script fetch as having completed (this time with
1860   // different data).
1861   fetcher->NotifyFetchCompletion(OK, "pac-v2");
1862 
1863   // Now that the PAC script is downloaded, the second request will have been
1864   // sent to the proxy resolver.
1865   EXPECT_EQ("pac-v2", resolver->pending_set_pac_script_request()->pac_bytes());
1866   resolver->pending_set_pac_script_request()->CompleteNow(OK);
1867 
1868   ASSERT_EQ(1u, resolver->pending_requests().size());
1869   EXPECT_EQ(GURL("http://request2"), resolver->pending_requests()[0]->url());
1870 
1871   // Complete the pending second request.
1872   resolver->pending_requests()[0]->results()->UseNamedProxy("request2:80");
1873   resolver->pending_requests()[0]->CompleteNow(OK);
1874 
1875   // Wait for completion callback, and verify that the request ran as expected.
1876   EXPECT_EQ(OK, callback2.WaitForResult());
1877   EXPECT_EQ("request2:80", info2.proxy_server().ToURI());
1878 }
1879 
1880 }  // namespace net
1881