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