proxy_service.cc revision 116680a4aac90f2aa7413d9095a592090648e557
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_service.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h"
14ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/metrics/histogram.h"
17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/metrics/sparse_histogram.h"
185e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/thread_task_runner_handle.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/completion_callback.h"
22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/base/load_flags.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/dhcp_proxy_script_fetcher.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/multi_threaded_proxy_resolver.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/network_delegate_error_observer.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_config_service_fixed.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_resolver.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_script_decider.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_script_fetcher.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_context.h"
347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_config_service_win.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_resolver_winhttp.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_IOS)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_config_service_ios.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_resolver_mac.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_MACOSX)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_config_service_mac.h"
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_resolver_mac.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_LINUX) && !defined(OS_CHROMEOS)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_config_service_linux.h"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_ANDROID)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_config_service_android.h"
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeTicks;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// When the IP address changes we don't immediately re-run proxy auto-config.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Instead, we  wait for |kDelayAfterNetworkChangesMs| before
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// attempting to re-valuate proxy auto-config.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// During this time window, any resolve requests sent to the ProxyService will
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be queued. Once we have waited the required amount of them, the proxy
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// auto-config step will be run, and the queued requests resumed.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The reason we play this game is that our signal for detecting network
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// changes (NetworkChangeNotifier) may fire *before* the system's networking
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// dependencies are fully configured. This is a problem since it means if
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we were to run proxy auto-config right away, it could fail due to spurious
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DNS failures. (see http://crbug.com/50779 for more details.)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// By adding the wait window, we give things a better chance to get properly
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// set up. Network failures can happen at any time though, so we additionally
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// poll the PAC script for changes, which will allow us to recover from these
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sorts of problems.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int64 kDelayAfterNetworkChangesMs = 2000;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is the default policy for polling the PAC script.
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In response to a failure, the poll intervals are:
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    0: 8 seconds  (scheduled on timer)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    1: 32 seconds
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    2: 2 minutes
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    3+: 4 hours
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In response to a success, the poll intervals are:
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    0+: 12 hours
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Only the 8 second poll is scheduled on a timer, the rest happen in response
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to network activity (and hence will take longer than the written time).
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Explanation for these values:
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(eroman): These values are somewhat arbitrary, and need to be tuned
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// using some histograms data. Trying to be conservative so as not to break
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// existing setups when deployed. A simple exponential retry scheme would be
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// more elegant, but places more load on server.
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The motivation for trying quickly after failures (8 seconds) is to recover
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from spurious network failures, which are common after the IP address has
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// just changed (like DNS failing to resolve). The next 32 second boundary is
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to try and catch other VPN weirdness which anecdotally I have seen take
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 10+ seconds for some users.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The motivation for re-trying after a success is to check for possible
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// content changes to the script, or to the WPAD auto-discovery results. We are
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not very aggressive with these checks so as to minimize the risk of
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// overloading existing PAC setups. Moreover it is unlikely that PAC scripts
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// change very frequently in existing setups. More research is needed to
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// motivate what safe values are here, and what other user agents do.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Comparison to other browsers:
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In Firefox the PAC URL is re-tried on failures according to
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// network.proxy.autoconfig_retry_interval_min and
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// network.proxy.autoconfig_retry_interval_max. The defaults are 5 seconds and
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 5 minutes respectively. It doubles the interval at each attempt.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(eroman): Figure out what Internet Explorer does.
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DefaultPollPolicy : public ProxyService::PacPollPolicy {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DefaultPollPolicy() {}
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual Mode GetNextDelay(int initial_error,
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            TimeDelta current_delay,
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            TimeDelta* next_delay) const OVERRIDE {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (initial_error != OK) {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Re-try policy for failures.
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int kDelay1Seconds = 8;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int kDelay2Seconds = 32;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int kDelay3Seconds = 2 * 60;  // 2 minutes
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const int kDelay4Seconds = 4 * 60 * 60;  // 4 Hours
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Initial poll.
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (current_delay < TimeDelta()) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *next_delay = TimeDelta::FromSeconds(kDelay1Seconds);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return MODE_USE_TIMER;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (current_delay.InSeconds()) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case kDelay1Seconds:
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          *next_delay = TimeDelta::FromSeconds(kDelay2Seconds);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return MODE_START_AFTER_ACTIVITY;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case kDelay2Seconds:
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          *next_delay = TimeDelta::FromSeconds(kDelay3Seconds);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return MODE_START_AFTER_ACTIVITY;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        default:
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          *next_delay = TimeDelta::FromSeconds(kDelay4Seconds);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return MODE_START_AFTER_ACTIVITY;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Re-try policy for succeses.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *next_delay = TimeDelta::FromHours(12);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return MODE_START_AFTER_ACTIVITY;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DefaultPollPolicy);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Config getter that always returns direct settings.
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ProxyConfigServiceDirect : public ProxyConfigService {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ProxyConfigService implementation:
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void AddObserver(Observer* observer) OVERRIDE {}
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RemoveObserver(Observer* observer) OVERRIDE {}
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ConfigAvailability GetLatestProxyConfig(ProxyConfig* config)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OVERRIDE {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *config = ProxyConfig::CreateDirect();
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    config->set_source(PROXY_CONFIG_SOURCE_UNKNOWN);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return CONFIG_VALID;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Proxy resolver that fails every time.
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ProxyResolverNull : public ProxyResolver {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyResolverNull() : ProxyResolver(false /*expects_pac_bytes*/) {}
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ProxyResolver implementation.
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int GetProxyForURL(const GURL& url,
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             ProxyInfo* results,
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const CompletionCallback& callback,
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             RequestHandle* request,
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const BoundNetLog& net_log) OVERRIDE {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_NOT_IMPLEMENTED;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void CancelRequest(RequestHandle request) OVERRIDE {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return LOAD_STATE_IDLE;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void CancelSetPacScript() OVERRIDE {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int SetPacScript(
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const scoped_refptr<ProxyResolverScriptData>& /*script_data*/,
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const CompletionCallback& /*callback*/) OVERRIDE {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_NOT_IMPLEMENTED;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ProxyResolver that simulates a PAC script which returns
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |pac_string| for every single URL.
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ProxyResolverFromPacString : public ProxyResolver {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit ProxyResolverFromPacString(const std::string& pac_string)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : ProxyResolver(false /*expects_pac_bytes*/),
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pac_string_(pac_string) {}
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int GetProxyForURL(const GURL& url,
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             ProxyInfo* results,
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const CompletionCallback& callback,
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             RequestHandle* request,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const BoundNetLog& net_log) OVERRIDE {
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    results->UsePacString(pac_string_);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void CancelRequest(RequestHandle request) OVERRIDE {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return LOAD_STATE_IDLE;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void CancelSetPacScript() OVERRIDE {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int SetPacScript(
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const scoped_refptr<ProxyResolverScriptData>& pac_script,
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const CompletionCallback& callback) OVERRIDE {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string pac_string_;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates ProxyResolvers using a platform-specific implementation.
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ProxyResolverFactoryForSystem : public ProxyResolverFactory {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyResolverFactoryForSystem()
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : ProxyResolverFactory(false /*expects_pac_bytes*/) {}
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ProxyResolver* CreateProxyResolver() OVERRIDE {
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(IsSupported());
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new ProxyResolverWinHttp();
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_MACOSX)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new ProxyResolverMac();
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool IsSupported() {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) || defined(OS_MACOSX)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns NetLog parameters describing a proxy configuration change.
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::Value* NetLogProxyConfigChangedCallback(
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ProxyConfig* old_config,
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ProxyConfig* new_config,
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NetLog::LogLevel /* log_level */) {
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue* dict = new base::DictionaryValue();
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The "old_config" is optional -- the first notification will not have
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // any "previous" configuration.
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (old_config->is_valid())
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->Set("old_config", old_config->ToValue());
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->Set("new_config", new_config->ToValue());
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dict;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::Value* NetLogBadProxyListCallback(const ProxyRetryInfoMap* retry_info,
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        NetLog::LogLevel /* log_level */) {
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue* dict = new base::DictionaryValue();
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ListValue* list = new base::ListValue();
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ProxyRetryInfoMap::const_iterator iter = retry_info->begin();
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != retry_info->end(); ++iter) {
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    list->Append(new base::StringValue(iter->first));
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->Set("bad_proxy_list", list);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dict;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns NetLog parameters on a successfuly proxy resolution.
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::Value* NetLogFinishedResolvingProxyCallback(
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ProxyInfo* result,
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NetLog::LogLevel /* log_level */) {
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue* dict = new base::DictionaryValue();
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->SetString("pac_string", result->ToPacString());
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dict;
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class UnsetProxyConfigService : public ProxyConfigService {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UnsetProxyConfigService() {}
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~UnsetProxyConfigService() {}
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void AddObserver(Observer* observer) OVERRIDE {}
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RemoveObserver(Observer* observer) OVERRIDE {}
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ConfigAvailability GetLatestProxyConfig(
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ProxyConfig* config) OVERRIDE {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return CONFIG_UNSET;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ProxyService::InitProxyResolver --------------------------------------------
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This glues together two asynchronous steps:
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   (1) ProxyScriptDecider -- try to fetch/validate a sequence of PAC scripts
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//       to figure out what we should configure against.
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   (2) Feed the fetched PAC script into the ProxyResolver.
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// InitProxyResolver is a single-use class which encapsulates cancellation as
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// part of its destructor. Start() or StartSkipDecider() should be called just
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// once. The instance can be destroyed at any time, and the request will be
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cancelled.
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ProxyService::InitProxyResolver {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitProxyResolver()
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : proxy_resolver_(NULL),
3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        next_state_(STATE_NONE),
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        quick_check_enabled_(true) {
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~InitProxyResolver() {
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note that the destruction of ProxyScriptDecider will automatically cancel
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // any outstanding work.
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (next_state_ == STATE_SET_PAC_SCRIPT_COMPLETE) {
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      proxy_resolver_->CancelSetPacScript();
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Begins initializing the proxy resolver; calls |callback| when done.
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int Start(ProxyResolver* proxy_resolver,
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ProxyScriptFetcher* proxy_script_fetcher,
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher,
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            NetLog* net_log,
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            const ProxyConfig& config,
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            TimeDelta wait_delay,
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            const CompletionCallback& callback) {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(STATE_NONE, next_state_);
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proxy_resolver_ = proxy_resolver;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    decider_.reset(new ProxyScriptDecider(
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        proxy_script_fetcher, dhcp_proxy_script_fetcher, net_log));
3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    decider_->set_quick_check_enabled(quick_check_enabled_);
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    config_ = config;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wait_delay_ = wait_delay;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback_ = callback;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_DECIDE_PROXY_SCRIPT;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return DoLoop(OK);
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Similar to Start(), however it skips the ProxyScriptDecider stage. Instead
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |effective_config|, |decider_result| and |script_data| will be used as the
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // inputs for initializing the ProxyResolver.
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int StartSkipDecider(ProxyResolver* proxy_resolver,
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const ProxyConfig& effective_config,
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       int decider_result,
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       ProxyResolverScriptData* script_data,
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const CompletionCallback& callback) {
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(STATE_NONE, next_state_);
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proxy_resolver_ = proxy_resolver;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    effective_config_ = effective_config;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    script_data_ = script_data;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback_ = callback;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (decider_result != OK)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return decider_result;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_SET_PAC_SCRIPT;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return DoLoop(OK);
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the proxy configuration that was selected by ProxyScriptDecider.
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Should only be called upon completion of the initialization.
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ProxyConfig& effective_config() const {
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(STATE_NONE, next_state_);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return effective_config_;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the PAC script data that was selected by ProxyScriptDecider.
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Should only be called upon completion of the initialization.
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyResolverScriptData* script_data() {
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(STATE_NONE, next_state_);
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return script_data_.get();
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LoadState GetLoadState() const {
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (next_state_ == STATE_DECIDE_PROXY_SCRIPT_COMPLETE) {
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // In addition to downloading, this state may also include the stall time
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // after network change events (kDelayAfterNetworkChangesMs).
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return LOAD_STATE_DOWNLOADING_PROXY_SCRIPT;
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return LOAD_STATE_RESOLVING_PROXY_FOR_URL;
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void set_quick_check_enabled(bool enabled) { quick_check_enabled_ = enabled; }
4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool quick_check_enabled() const { return quick_check_enabled_; }
4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum State {
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STATE_NONE,
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STATE_DECIDE_PROXY_SCRIPT,
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STATE_DECIDE_PROXY_SCRIPT_COMPLETE,
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STATE_SET_PAC_SCRIPT,
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STATE_SET_PAC_SCRIPT_COMPLETE,
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoLoop(int result) {
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_NE(next_state_, STATE_NONE);
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = result;
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    do {
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      State state = next_state_;
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_state_ = STATE_NONE;
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (state) {
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case STATE_DECIDE_PROXY_SCRIPT:
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DCHECK_EQ(OK, rv);
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rv = DoDecideProxyScript();
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case STATE_DECIDE_PROXY_SCRIPT_COMPLETE:
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rv = DoDecideProxyScriptComplete(rv);
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case STATE_SET_PAC_SCRIPT:
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DCHECK_EQ(OK, rv);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rv = DoSetPacScript();
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case STATE_SET_PAC_SCRIPT_COMPLETE:
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rv = DoSetPacScriptComplete(rv);
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        default:
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NOTREACHED() << "bad state: " << state;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rv = ERR_UNEXPECTED;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoDecideProxyScript() {
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_DECIDE_PROXY_SCRIPT_COMPLETE;
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return decider_->Start(
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        config_, wait_delay_, proxy_resolver_->expects_pac_bytes(),
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&InitProxyResolver::OnIOCompletion, base::Unretained(this)));
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoDecideProxyScriptComplete(int result) {
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result != OK)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return result;
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    effective_config_ = decider_->effective_config();
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    script_data_ = decider_->script_data();
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_SET_PAC_SCRIPT;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoSetPacScript() {
486868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(script_data_.get());
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(eroman): Should log this latency to the NetLog.
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_SET_PAC_SCRIPT_COMPLETE;
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return proxy_resolver_->SetPacScript(
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        script_data_,
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&InitProxyResolver::OnIOCompletion, base::Unretained(this)));
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoSetPacScriptComplete(int result) {
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnIOCompletion(int result) {
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_NE(STATE_NONE, next_state_);
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = DoLoop(result);
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != ERR_IO_PENDING)
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DoCallback(rv);
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DoCallback(int result) {
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_NE(ERR_IO_PENDING, result);
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback_.Run(result);
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyConfig config_;
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyConfig effective_config_;
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<ProxyResolverScriptData> script_data_;
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeDelta wait_delay_;
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ProxyScriptDecider> decider_;
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyResolver* proxy_resolver_;
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallback callback_;
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  State next_state_;
5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool quick_check_enabled_;
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(InitProxyResolver);
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ProxyService::ProxyScriptDeciderPoller -------------------------------------
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This helper class encapsulates the logic to schedule and run periodic
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// background checks to see if the PAC script (or effective proxy configuration)
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// has changed. If a change is detected, then the caller will be notified via
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the ChangeCallback.
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ProxyService::ProxyScriptDeciderPoller {
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef base::Callback<void(int, ProxyResolverScriptData*,
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const ProxyConfig&)> ChangeCallback;
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Builds a poller helper, and starts polling for updates. Whenever a change
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is observed, |callback| will be invoked with the details.
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   |config| specifies the (unresolved) proxy configuration to poll.
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   |proxy_resolver_expects_pac_bytes| the type of proxy resolver we expect
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                                      to use the resulting script data with
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                                      (so it can choose the right format).
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   |proxy_script_fetcher| this pointer must remain alive throughout our
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                          lifetime. It is the dependency that will be used
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                          for downloading proxy scripts.
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   |dhcp_proxy_script_fetcher| similar to |proxy_script_fetcher|, but for
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                               the DHCP dependency.
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   |init_net_error| This is the initial network error (possibly success)
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                    encountered by the first PAC fetch attempt. We use it
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                    to schedule updates more aggressively if the initial
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                    fetch resulted in an error.
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   |init_script_data| the initial script data from the PAC fetch attempt.
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                      This is the baseline used to determine when the
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                      script's contents have changed.
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   |net_log| the NetLog to log progress into.
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyScriptDeciderPoller(ChangeCallback callback,
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const ProxyConfig& config,
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           bool proxy_resolver_expects_pac_bytes,
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           ProxyScriptFetcher* proxy_script_fetcher,
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher,
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           int init_net_error,
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           ProxyResolverScriptData* init_script_data,
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           NetLog* net_log)
562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : weak_factory_(this),
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        change_callback_(callback),
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        config_(config),
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        proxy_resolver_expects_pac_bytes_(proxy_resolver_expects_pac_bytes),
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        proxy_script_fetcher_(proxy_script_fetcher),
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dhcp_proxy_script_fetcher_(dhcp_proxy_script_fetcher),
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        last_error_(init_net_error),
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        last_script_data_(init_script_data),
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        last_poll_time_(TimeTicks::Now()) {
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Set the initial poll delay.
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_poll_mode_ = poll_policy()->GetNextDelay(
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        last_error_, TimeDelta::FromSeconds(-1), &next_poll_delay_);
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TryToStartNextPoll(false);
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnLazyPoll() {
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We have just been notified of network activity. Use this opportunity to
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // see if we can start our next poll.
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TryToStartNextPoll(true);
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const PacPollPolicy* set_policy(const PacPollPolicy* policy) {
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PacPollPolicy* prev = poll_policy_;
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    poll_policy_ = policy;
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return prev;
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void set_quick_check_enabled(bool enabled) { quick_check_enabled_ = enabled; }
5905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool quick_check_enabled() const { return quick_check_enabled_; }
5915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the effective poll policy (the one injected by unit-tests, or the
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // default).
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const PacPollPolicy* poll_policy() {
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (poll_policy_)
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return poll_policy_;
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &default_poll_policy_;
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartPollTimer() {
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!decider_.get());
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
60490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::MessageLoop::current()->PostDelayedTask(
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&ProxyScriptDeciderPoller::DoPoll,
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_factory_.GetWeakPtr()),
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        next_poll_delay_);
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void TryToStartNextPoll(bool triggered_by_activity) {
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (next_poll_mode_) {
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PacPollPolicy::MODE_USE_TIMER:
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!triggered_by_activity)
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          StartPollTimer();
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PacPollPolicy::MODE_START_AFTER_ACTIVITY:
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (triggered_by_activity && !decider_.get()) {
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          TimeDelta elapsed_time = TimeTicks::Now() - last_poll_time_;
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (elapsed_time >= next_poll_delay_)
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            DoPoll();
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DoPoll() {
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_poll_time_ = TimeTicks::Now();
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Start the proxy script decider to see if anything has changed.
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(eroman): Pass a proper NetLog rather than NULL.
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    decider_.reset(new ProxyScriptDecider(
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        proxy_script_fetcher_, dhcp_proxy_script_fetcher_, NULL));
6355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    decider_->set_quick_check_enabled(quick_check_enabled_);
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int result = decider_->Start(
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        config_, TimeDelta(), proxy_resolver_expects_pac_bytes_,
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&ProxyScriptDeciderPoller::OnProxyScriptDeciderCompleted,
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   base::Unretained(this)));
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result != ERR_IO_PENDING)
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OnProxyScriptDeciderCompleted(result);
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnProxyScriptDeciderCompleted(int result) {
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (HasScriptDataChanged(result, decider_->script_data())) {
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Something has changed, we must notify the ProxyService so it can
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // re-initialize its ProxyResolver. Note that we post a notification task
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // rather than calling it directly -- this is done to avoid an ugly
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // destruction sequence, since |this| might be destroyed as a result of
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the notification.
65290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::MessageLoop::current()->PostTask(
65390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          FROM_HERE,
65490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          base::Bind(&ProxyScriptDeciderPoller::NotifyProxyServiceOfChange,
65590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     weak_factory_.GetWeakPtr(),
65690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     result,
65790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     make_scoped_refptr(decider_->script_data()),
65890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                     decider_->effective_config()));
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    decider_.reset();
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Decide when the next poll should take place, and possibly start the
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // next timer.
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_poll_mode_ = poll_policy()->GetNextDelay(
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        last_error_, next_poll_delay_, &next_poll_delay_);
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TryToStartNextPoll(false);
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool HasScriptDataChanged(int result, ProxyResolverScriptData* script_data) {
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result != last_error_) {
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Something changed -- it was failing before and now it succeeded, or
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // conversely it succeeded before and now it failed. Or it failed in
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // both cases, however the specific failure error codes differ.
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result != OK) {
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If it failed last time and failed again with the same error code this
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // time, then nothing has actually changed.
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Otherwise if it succeeded both this time and last time, we need to look
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // closer and see if we ended up downloading different content for the PAC
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // script.
688868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return !script_data->Equals(last_script_data_.get());
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void NotifyProxyServiceOfChange(
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int result,
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const scoped_refptr<ProxyResolverScriptData>& script_data,
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const ProxyConfig& effective_config) {
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note that |this| may be deleted after calling into the ProxyService.
696868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    change_callback_.Run(result, script_data.get(), effective_config);
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtrFactory<ProxyScriptDeciderPoller> weak_factory_;
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChangeCallback change_callback_;
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyConfig config_;
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool proxy_resolver_expects_pac_bytes_;
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyScriptFetcher* proxy_script_fetcher_;
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher_;
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int last_error_;
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<ProxyResolverScriptData> last_script_data_;
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ProxyScriptDecider> decider_;
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeDelta next_poll_delay_;
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PacPollPolicy::Mode next_poll_mode_;
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeTicks last_poll_time_;
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Polling policy injected by unit-tests. Otherwise this is NULL and the
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // default policy will be used.
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const PacPollPolicy* poll_policy_;
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const DefaultPollPolicy default_poll_policy_;
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool quick_check_enabled_;
7235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ProxyScriptDeciderPoller);
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ProxyService::PacPollPolicy*
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProxyService::ProxyScriptDeciderPoller::poll_policy_ = NULL;
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ProxyService::PacRequest ---------------------------------------------------
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ProxyService::PacRequest
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public base::RefCounted<ProxyService::PacRequest> {
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PacRequest(ProxyService* service,
7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               const GURL& url,
738116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch               int load_flags,
739116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch               NetworkDelegate* network_delegate,
7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               ProxyInfo* results,
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               const net::CompletionCallback& user_callback,
7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               const BoundNetLog& net_log)
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : service_(service),
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        user_callback_(user_callback),
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        results_(results),
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        url_(url),
747116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        load_flags_(load_flags),
748116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        network_delegate_(network_delegate),
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        resolve_job_(NULL),
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        config_id_(ProxyConfig::kInvalidConfigID),
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        config_source_(PROXY_CONFIG_SOURCE_UNKNOWN),
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net_log_(net_log) {
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!user_callback.is_null());
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Starts the resolve proxy request.
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int Start() {
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!was_cancelled());
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!is_started());
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(service_->config_.is_valid());
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    config_id_ = service_->config_.id();
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    config_source_ = service_->config_.source();
7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    proxy_resolve_start_time_ = TimeTicks::Now();
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return resolver()->GetProxyForURL(
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        url_, results_,
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PacRequest::QueryComplete, base::Unretained(this)),
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &resolve_job_, net_log_);
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_started() const {
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note that !! casts to bool. (VS gives a warning otherwise).
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return !!resolve_job_;
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartAndCompleteCheckingForSynchronous() {
779116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int rv = service_->TryToCompleteSynchronously(url_, load_flags_,
780116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                  network_delegate_, results_);
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == ERR_IO_PENDING)
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = Start();
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != ERR_IO_PENDING)
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      QueryComplete(rv);
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CancelResolveJob() {
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(is_started());
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The request may already be running in the resolver.
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    resolver()->CancelRequest(resolve_job_);
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    resolve_job_ = NULL;
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!is_started());
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Cancel() {
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.AddEvent(NetLog::TYPE_CANCELLED);
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (is_started())
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CancelResolveJob();
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Mark as cancelled, to prevent accessing this again later.
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_ = NULL;
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_callback_.Reset();
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    results_ = NULL;
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEvent(NetLog::TYPE_PROXY_SERVICE);
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if Cancel() has been called.
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool was_cancelled() const {
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return user_callback_.is_null();
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Helper to call after ProxyResolver completion (both synchronous and
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // asynchronous). Fixes up the result that is to be returned to user.
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int QueryDidComplete(int result_code) {
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!was_cancelled());
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note that DidFinishResolvingProxy might modify |results_|.
820116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int rv = service_->DidFinishResolvingProxy(url_, load_flags_,
821116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                               network_delegate_, results_,
822116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                               result_code, net_log_);
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Make a note in the results which configuration was in use at the
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // time of the resolve.
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    results_->config_id_ = config_id_;
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    results_->config_source_ = config_source_;
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    results_->did_use_pac_script_ = true;
8292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    results_->proxy_resolve_start_time_ = proxy_resolve_start_time_;
8302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    results_->proxy_resolve_end_time_ = TimeTicks::Now();
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Reset the state associated with in-progress-resolve.
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    resolve_job_ = NULL;
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    config_id_ = ProxyConfig::kInvalidConfigID;
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    config_source_ = PROXY_CONFIG_SOURCE_UNKNOWN;
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BoundNetLog* net_log() { return &net_log_; }
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoadState GetLoadState() const {
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (is_started())
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return resolver()->GetLoadState(resolve_job_);
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return LOAD_STATE_RESOLVING_PROXY_FOR_URL;
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class base::RefCounted<ProxyService::PacRequest>;
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~PacRequest() {}
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Callback for when the ProxyResolver request has completed.
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void QueryComplete(int result_code) {
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result_code = QueryDidComplete(result_code);
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Remove this completed PacRequest from the service's pending list.
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /// (which will probably cause deletion of |this|).
8592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!user_callback_.is_null()) {
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::CompletionCallback callback = user_callback_;
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      service_->RemovePendingRequest(this);
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.Run(result_code);
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyResolver* resolver() const { return service_->resolver_.get(); }
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that we don't hold a reference to the ProxyService. Outstanding
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // requests are cancelled during ~ProxyService, so this is guaranteed
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to be valid throughout our lifetime.
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyService* service_;
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::CompletionCallback user_callback_;
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyInfo* results_;
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url_;
875116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int load_flags_;
876116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  NetworkDelegate* network_delegate_;
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyResolver::RequestHandle resolve_job_;
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyConfig::ID config_id_;  // The config id when the resolve was started.
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyConfigSource config_source_;  // The source of proxy settings.
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BoundNetLog net_log_;
8812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Time when the PAC is started.  Cached here since resetting ProxyInfo also
8822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // clears the proxy times.
8832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TimeTicks proxy_resolve_start_time_;
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ProxyService ---------------------------------------------------------------
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyService::ProxyService(ProxyConfigService* config_service,
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           ProxyResolver* resolver,
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           NetLog* net_log)
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : resolver_(resolver),
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_config_id_(1),
893116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      current_state_(STATE_NONE),
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_(net_log),
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      stall_proxy_auto_config_delay_(TimeDelta::FromMilliseconds(
8965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          kDelayAfterNetworkChangesMs)),
8975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      quick_check_enabled_(true) {
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NetworkChangeNotifier::AddIPAddressObserver(this);
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NetworkChangeNotifier::AddDNSObserver(this);
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetConfigService(config_service);
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyService* ProxyService::CreateUsingSystemProxyResolver(
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProxyConfigService* proxy_config_service,
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t num_pac_threads,
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NetLog* net_log) {
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(proxy_config_service);
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ProxyResolverFactoryForSystem::IsSupported()) {
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "PAC support disabled because there is no "
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "system implementation";
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return CreateWithoutProxyResolver(proxy_config_service, net_log);
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (num_pac_threads == 0)
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    num_pac_threads = kDefaultNumPacThreads;
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyResolver* proxy_resolver = new MultiThreadedProxyResolver(
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new ProxyResolverFactoryForSystem(), num_pac_threads);
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new ProxyService(proxy_config_service, proxy_resolver, net_log);
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyService* ProxyService::CreateWithoutProxyResolver(
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProxyConfigService* proxy_config_service,
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NetLog* net_log) {
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new ProxyService(proxy_config_service,
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          new ProxyResolverNull(),
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          net_log);
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyService* ProxyService::CreateFixed(const ProxyConfig& pc) {
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(eroman): This isn't quite right, won't work if |pc| specifies
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //               a PAC script.
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CreateUsingSystemProxyResolver(new ProxyConfigServiceFixed(pc),
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        0, NULL);
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyService* ProxyService::CreateFixed(const std::string& proxy) {
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::ProxyConfig proxy_config;
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxy_config.proxy_rules().ParseFromString(proxy);
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ProxyService::CreateFixed(proxy_config);
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyService* ProxyService::CreateDirect() {
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CreateDirectWithNetLog(NULL);
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyService* ProxyService::CreateDirectWithNetLog(NetLog* net_log) {
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use direct connections.
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new ProxyService(new ProxyConfigServiceDirect, new ProxyResolverNull,
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          net_log);
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyService* ProxyService::CreateFixedFromPacResult(
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& pac_string) {
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We need the settings to contain an "automatic" setting, otherwise the
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ProxyResolver dependency we give it will never be used.
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ProxyConfigService> proxy_config_service(
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new ProxyConfigServiceFixed(ProxyConfig::CreateAutoDetect()));
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ProxyResolver> proxy_resolver(
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new ProxyResolverFromPacString(pac_string));
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new ProxyService(proxy_config_service.release(),
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          proxy_resolver.release(),
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          NULL);
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ProxyService::ResolveProxy(const GURL& raw_url,
978116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                               int load_flags,
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               ProxyInfo* result,
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const net::CompletionCallback& callback,
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               PacRequest** pac_request,
982116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                               NetworkDelegate* network_delegate,
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const BoundNetLog& net_log) {
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log.BeginEvent(NetLog::TYPE_PROXY_SERVICE);
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Notify our polling-based dependencies that a resolve is taking place.
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This way they can schedule their polls in response to network activity.
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_service_->OnLazyPoll();
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (script_poller_.get())
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     script_poller_->OnLazyPoll();
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (current_state_ == STATE_NONE)
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ApplyProxyConfigIfAvailable();
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Strip away any reference fragments and the username/password, as they
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // are not relevant to proxy resolution.
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url = SimplifyUrlForRequest(raw_url);
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if the request can be completed right away. (This is the case when
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // using a direct connection for example).
1004116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int rv = TryToCompleteSynchronously(url, load_flags,
1005116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                      network_delegate, result);
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING)
1007116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return DidFinishResolvingProxy(url, load_flags, network_delegate,
1008116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                   result, rv, net_log);
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<PacRequest> req(
1011116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      new PacRequest(this, url, load_flags, network_delegate,
1012116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                     result, callback, net_log));
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (current_state_ == STATE_READY) {
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Start the resolve request.
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = req->Start();
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != ERR_IO_PENDING)
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return req->QueryDidComplete(rv);
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    req->net_log()->BeginEvent(NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC);
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(ERR_IO_PENDING, rv);
1024868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!ContainsPendingRequest(req.get()));
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_requests_.push_back(req);
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Completion will be notified through |callback|, unless the caller cancels
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the request using |pac_request|.
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pac_request)
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *pac_request = req.get();
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;  // ERR_IO_PENDING
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ProxyService::TryToCompleteSynchronously(const GURL& url,
1035116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                             int load_flags,
1036116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                             NetworkDelegate* network_delegate,
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             ProxyInfo* result) {
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(STATE_NONE, current_state_);
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (current_state_ != STATE_READY)
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;  // Still initializing.
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(config_.id(), ProxyConfig::kInvalidConfigID);
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If it was impossible to fetch or parse the PAC script, we cannot complete
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the request here and bail out.
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (permanent_error_ != OK)
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return permanent_error_;
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (config_.HasAutomaticSettings())
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;  // Must submit the request to the proxy resolver.
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use the manual proxy settings.
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.proxy_rules().Apply(url, result);
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->config_source_ = config_.source();
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->config_id_ = config_.id();
1057116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyService::~ProxyService() {
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NetworkChangeNotifier::RemoveIPAddressObserver(this);
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NetworkChangeNotifier::RemoveDNSObserver(this);
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_service_->RemoveObserver(this);
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cancel any inprogress requests.
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PendingRequests::iterator it = pending_requests_.begin();
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != pending_requests_.end();
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++it) {
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*it)->Cancel();
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::SuspendAllPendingRequests() {
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PendingRequests::iterator it = pending_requests_.begin();
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != pending_requests_.end();
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++it) {
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PacRequest* req = it->get();
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (req->is_started()) {
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      req->CancelResolveJob();
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      req->net_log()->BeginEvent(
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC);
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::SetReady() {
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!init_proxy_resolver_.get());
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current_state_ = STATE_READY;
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make a copy in case |this| is deleted during the synchronous completion
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of one of the requests. If |this| is deleted then all of the PacRequest
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // instances will be Cancel()-ed.
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingRequests pending_copy = pending_requests_;
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PendingRequests::iterator it = pending_copy.begin();
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != pending_copy.end();
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++it) {
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PacRequest* req = it->get();
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!req->is_started() && !req->was_cancelled()) {
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      req->net_log()->EndEvent(NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC);
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Note that we re-check for synchronous completion, in case we are
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // no longer using a ProxyResolver (can happen if we fell-back to manual).
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      req->StartAndCompleteCheckingForSynchronous();
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::ApplyProxyConfigIfAvailable() {
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, current_state_);
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_service_->OnLazyPoll();
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we have already fetched the configuration, start applying it.
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (fetched_config_.is_valid()) {
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitializeUsingLastFetchedConfig();
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Otherwise we need to first fetch the configuration.
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current_state_ = STATE_WAITING_FOR_PROXY_CONFIG;
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Retrieve the current proxy configuration from the ProxyConfigService.
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If a configuration is not available yet, we will get called back later
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // by our ProxyConfigService::Observer once it changes.
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyConfig config;
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyConfigService::ConfigAvailability availability =
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      config_service_->GetLatestProxyConfig(&config);
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (availability != ProxyConfigService::CONFIG_PENDING)
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnProxyConfigChanged(config, availability);
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::OnInitProxyResolverComplete(int result) {
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_WAITING_FOR_INIT_PROXY_RESOLVER, current_state_);
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(init_proxy_resolver_.get());
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(fetched_config_.HasAutomaticSettings());
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_ = init_proxy_resolver_->effective_config();
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // At this point we have decided which proxy settings to use (i.e. which PAC
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // script if any). We start up a background poller to periodically revisit
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this decision. If the contents of the PAC script change, or if the
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // result of proxy auto-discovery changes, this poller will notice it and
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // will trigger a re-initialization using the newly discovered PAC.
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  script_poller_.reset(new ProxyScriptDeciderPoller(
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&ProxyService::InitializeUsingDecidedConfig,
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)),
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fetched_config_,
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      resolver_->expects_pac_bytes(),
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      proxy_script_fetcher_.get(),
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dhcp_proxy_script_fetcher_.get(),
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result,
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      init_proxy_resolver_->script_data(),
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NULL));
11565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  script_poller_->set_quick_check_enabled(quick_check_enabled_);
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_proxy_resolver_.reset();
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != OK) {
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fetched_config_.pac_mandatory()) {
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VLOG(1) << "Failed configuring with mandatory PAC script, blocking all "
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 "traffic.";
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      config_ = fetched_config_;
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = ERR_MANDATORY_PROXY_CONFIGURATION_FAILED;
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VLOG(1) << "Failed configuring with PAC script, falling-back to manual "
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 "proxy servers.";
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      config_ = fetched_config_;
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      config_.ClearAutomaticSettings();
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = OK;
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  permanent_error_ = result;
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(eroman): Make this ID unique in the case where configuration changed
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //               due to ProxyScriptDeciderPoller.
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.set_id(fetched_config_.id());
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.set_source(fetched_config_.source());
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Resume any requests which we had to defer until the PAC script was
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // downloaded.
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetReady();
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ProxyService::ReconsiderProxyAfterError(const GURL& url,
1187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                            int load_flags,
1188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                            int net_error,
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            ProxyInfo* result,
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            const CompletionCallback& callback,
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            PacRequest** pac_request,
1192116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                            NetworkDelegate* network_delegate,
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            const BoundNetLog& net_log) {
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check to see if we have a new config since ResolveProxy was called.  We
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // want to re-run ResolveProxy in two cases: 1) we have a new config, or 2) a
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // direct connection failed and we never tried the current config.
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool re_resolve = result->config_id_ != config_.id();
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (re_resolve) {
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we have a new config or the config was never tried, we delete the
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // list of bad proxies and we try again.
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proxy_retry_info_.clear();
1206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return ResolveProxy(url, load_flags, result, callback, pac_request,
1207116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                        network_delegate, net_log);
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1210f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#if defined(SPDY_PROXY_AUTH_ORIGIN)
1211f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (result->proxy_server().isDataReductionProxy()) {
1212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    RecordDataReductionProxyBypassInfo(
1213116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        true, false, result->proxy_server(), NETWORK_ERROR);
1214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    RecordDataReductionProxyBypassOnNetworkError(
1215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        true, result->proxy_server(), net_error);
1216f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } else if (result->proxy_server().isDataReductionProxyFallback()) {
1217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    RecordDataReductionProxyBypassInfo(
1218116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        false, false, result->proxy_server(), NETWORK_ERROR);
1219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    RecordDataReductionProxyBypassOnNetworkError(
1220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        false, result->proxy_server(), net_error);
1221f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif
1223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't have new proxy settings to try, try to fallback to the next proxy
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in the list.
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool did_fallback = result->Fallback(net_log);
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Return synchronous failure if there is nothing left to fall-back to.
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(eroman): This is a yucky API, clean it up.
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return did_fallback ? OK : ERR_FAILED;
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1233a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool ProxyService::MarkProxiesAsBadUntil(
12345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const ProxyInfo& result,
12355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::TimeDelta retry_delay,
12365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const ProxyServer& another_bad_proxy,
12375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const BoundNetLog& net_log) {
12381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  result.proxy_list_.UpdateRetryInfoOnFallback(&proxy_retry_info_, retry_delay,
1239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                               false,
12405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                               another_bad_proxy,
12411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                               net_log);
1242a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (another_bad_proxy.is_valid())
1243a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return result.proxy_list_.size() > 2;
1244a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  else
1245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return result.proxy_list_.size() > 1;
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::ReportSuccess(const ProxyInfo& result) {
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ProxyRetryInfoMap& new_retry_info = result.proxy_retry_info();
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (new_retry_info.empty())
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ProxyRetryInfoMap::const_iterator iter = new_retry_info.begin();
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != new_retry_info.end(); ++iter) {
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProxyRetryInfoMap::iterator existing = proxy_retry_info_.find(iter->first);
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (existing == proxy_retry_info_.end())
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      proxy_retry_info_[iter->first] = iter->second;
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (existing->second.bad_until < iter->second.bad_until)
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      existing->second.bad_until = iter->second.bad_until;
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (net_log_) {
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_->AddGlobalEntry(
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NetLog::TYPE_BAD_PROXY_LIST_REPORTED,
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&NetLogBadProxyListCallback, &new_retry_info));
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::CancelPacRequest(PacRequest* req) {
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(req);
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  req->Cancel();
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RemovePendingRequest(req);
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LoadState ProxyService::GetLoadState(const PacRequest* req) const {
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(req);
12792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (current_state_ == STATE_WAITING_FOR_INIT_PROXY_RESOLVER)
12802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return init_proxy_resolver_->GetLoadState();
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return req->GetLoadState();
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProxyService::ContainsPendingRequest(PacRequest* req) {
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingRequests::iterator it = std::find(
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_requests_.begin(), pending_requests_.end(), req);
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return pending_requests_.end() != it;
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::RemovePendingRequest(PacRequest* req) {
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(ContainsPendingRequest(req));
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingRequests::iterator it = std::find(
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_requests_.begin(), pending_requests_.end(), req);
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_requests_.erase(it);
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1297116680a4aac90f2aa7413d9095a592090648e557Ben Murdochint ProxyService::DidFinishResolvingProxy(const GURL& url,
1298116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                          int load_flags,
1299116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                          NetworkDelegate* network_delegate,
1300116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                          ProxyInfo* result,
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          int result_code,
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const BoundNetLog& net_log) {
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Log the result of the proxy resolution.
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result_code == OK) {
1305116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // Allow the network delegate to interpose on the resolution decision,
1306116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // possibly modifying the ProxyInfo.
1307116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (network_delegate)
1308116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      network_delegate->NotifyResolveProxy(url, load_flags, result);
1309116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // When logging all events is enabled, dump the proxy list.
1311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (net_log.IsLogging()) {
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log.AddEvent(
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NetLog::TYPE_PROXY_SERVICE_RESOLVED_PROXY_LIST,
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&NetLogFinishedResolvingProxyCallback, result));
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result->DeprioritizeBadProxies(proxy_retry_info_);
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log.AddEventWithNetErrorCode(
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NetLog::TYPE_PROXY_SERVICE_RESOLVED_PROXY_LIST, result_code);
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!config_.pac_mandatory()) {
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Fall-back to direct when the proxy resolver fails. This corresponds
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // with a javascript runtime error in the PAC script.
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This implicit fall-back to direct matches Firefox 3.5 and
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Internet Explorer 8. For more information, see:
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // http://www.chromium.org/developers/design-documents/proxy-settings-fallback
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result->UseDirect();
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result_code = OK;
1331116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1332116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // Allow the network delegate to interpose on the resolution decision,
1333116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // possibly modifying the ProxyInfo.
1334116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      if (network_delegate)
1335116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        network_delegate->NotifyResolveProxy(url, load_flags, result);
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result_code = ERR_MANDATORY_PROXY_CONFIGURATION_FAILED;
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log.EndEvent(NetLog::TYPE_PROXY_SERVICE);
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result_code;
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::SetProxyScriptFetchers(
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProxyScriptFetcher* proxy_script_fetcher,
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher) {
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  State previous_state = ResetProxyConfig(false);
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxy_script_fetcher_.reset(proxy_script_fetcher);
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dhcp_proxy_script_fetcher_.reset(dhcp_proxy_script_fetcher);
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (previous_state != STATE_NONE)
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ApplyProxyConfigIfAvailable();
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyScriptFetcher* ProxyService::GetProxyScriptFetcher() const {
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return proxy_script_fetcher_.get();
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyService::State ProxyService::ResetProxyConfig(bool reset_fetched_config) {
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  State previous_state = current_state_;
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  permanent_error_ = OK;
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxy_retry_info_.clear();
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  script_poller_.reset();
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_proxy_resolver_.reset();
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SuspendAllPendingRequests();
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_ = ProxyConfig();
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (reset_fetched_config)
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fetched_config_ = ProxyConfig();
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current_state_ = STATE_NONE;
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return previous_state;
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::ResetConfigService(
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProxyConfigService* new_proxy_config_service) {
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  State previous_state = ResetProxyConfig(true);
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Release the old configuration service.
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (config_service_.get())
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    config_service_->RemoveObserver(this);
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the new configuration service.
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_service_.reset(new_proxy_config_service);
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_service_->AddObserver(this);
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (previous_state != STATE_NONE)
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ApplyProxyConfigIfAvailable();
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::ForceReloadProxyConfig() {
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetProxyConfig(false);
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ApplyProxyConfigIfAvailable();
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyConfigService* ProxyService::CreateSystemProxyConfigService(
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SingleThreadTaskRunner* io_thread_task_runner,
140490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::MessageLoop* file_loop) {
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new ProxyConfigServiceWin();
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_IOS)
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new ProxyConfigServiceIOS();
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_MACOSX)
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new ProxyConfigServiceMac(io_thread_task_runner);
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_CHROMEOS)
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(ERROR) << "ProxyConfigService for ChromeOS should be created in "
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << "profile_io_data.cc::CreateProxyConfigService and this should "
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << "be used only for examples.";
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new UnsetProxyConfigService;
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_LINUX)
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyConfigServiceLinux* linux_config_service =
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new ProxyConfigServiceLinux();
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Assume we got called on the thread that runs the default glib
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // main loop, so the current thread is where we should be running
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // gconf calls from.
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<base::SingleThreadTaskRunner> glib_thread_task_runner =
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::ThreadTaskRunnerHandle::Get();
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The file loop should be a MessageLoopForIO on Linux.
142790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_EQ(base::MessageLoop::TYPE_IO, file_loop->type());
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Synchronously fetch the current proxy config (since we are
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // running on glib_default_loop). Additionally register for
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // notifications (delivered in either |glib_default_loop| or
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |file_loop|) to keep us updated when the proxy config changes.
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  linux_config_service->SetupAndFetchInitialConfig(
1434868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      glib_thread_task_runner.get(),
143590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      io_thread_task_runner,
143690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      static_cast<base::MessageLoopForIO*>(file_loop));
14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return linux_config_service;
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_ANDROID)
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new ProxyConfigServiceAndroid(
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      io_thread_task_runner,
144290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::MessageLoop::current()->message_loop_proxy());
14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(WARNING) << "Failed to choose a system proxy settings fetcher "
14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  "for this platform.";
14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new ProxyConfigServiceDirect();
14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ProxyService::PacPollPolicy* ProxyService::set_pac_script_poll_policy(
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PacPollPolicy* policy) {
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ProxyScriptDeciderPoller::set_policy(policy);
14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<ProxyService::PacPollPolicy>
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyService::CreateDefaultPacPollPolicy() {
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return scoped_ptr<PacPollPolicy>(new DefaultPollPolicy());
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1462f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ProxyService::RecordDataReductionProxyBypassInfo(
1463f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool is_primary,
1464116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    bool bypass_all,
1465f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const ProxyServer& proxy_server,
1466116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    DataReductionProxyBypassType bypass_type) const {
1467f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Only record UMA if the proxy isn't already on the retry list.
1468f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (proxy_retry_info_.find(proxy_server.ToURI()) != proxy_retry_info_.end())
1469f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
1470f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1471116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (bypass_all) {
1472116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (is_primary) {
1473116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      UMA_HISTOGRAM_ENUMERATION("DataReductionProxy.BlockTypePrimary",
1474116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                bypass_type, BYPASS_EVENT_TYPE_MAX);
1475116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    } else {
1476116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      UMA_HISTOGRAM_ENUMERATION("DataReductionProxy.BlockTypeFallback",
1477116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                bypass_type, BYPASS_EVENT_TYPE_MAX);
1478116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
1479f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } else {
1480116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (is_primary) {
1481116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      UMA_HISTOGRAM_ENUMERATION("DataReductionProxy.BypassTypePrimary",
1482116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                bypass_type, BYPASS_EVENT_TYPE_MAX);
1483116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    } else {
1484116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      UMA_HISTOGRAM_ENUMERATION("DataReductionProxy.BypassTypeFallback",
1485116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                bypass_type, BYPASS_EVENT_TYPE_MAX);
1486116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
1487f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1488f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
1489cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1490cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ProxyService::RecordDataReductionProxyBypassOnNetworkError(
1491cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    bool is_primary,
1492cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const ProxyServer& proxy_server,
1493cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int net_error) {
1494cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Only record UMA if the proxy isn't already on the retry list.
1495cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (proxy_retry_info_.find(proxy_server.ToURI()) != proxy_retry_info_.end())
1496cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
1497cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1498cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (is_primary) {
1499cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    UMA_HISTOGRAM_SPARSE_SLOWLY(
1500cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        "DataReductionProxy.BypassOnNetworkErrorPrimary",
1501cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        std::abs(net_error));
1502cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
1503cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
1504cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  UMA_HISTOGRAM_SPARSE_SLOWLY(
1505cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      "DataReductionProxy.BypassOnNetworkErrorFallback",
1506cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      std::abs(net_error));
1507cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
1508f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::OnProxyConfigChanged(
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ProxyConfig& config,
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProxyConfigService::ConfigAvailability availability) {
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Retrieve the current proxy configuration from the ProxyConfigService.
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If a configuration is not available yet, we will get called back later
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // by our ProxyConfigService::Observer once it changes.
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyConfig effective_config;
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (availability) {
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ProxyConfigService::CONFIG_PENDING:
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // ProxyConfigService implementors should never pass CONFIG_PENDING.
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED() << "Proxy config change with CONFIG_PENDING availability!";
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ProxyConfigService::CONFIG_VALID:
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      effective_config = config;
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ProxyConfigService::CONFIG_UNSET:
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      effective_config = ProxyConfig::CreateDirect();
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Emit the proxy settings change to the NetLog stream.
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (net_log_) {
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_->AddGlobalEntry(
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net::NetLog::TYPE_PROXY_CONFIG_CHANGED,
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&NetLogProxyConfigChangedCallback,
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   &fetched_config_, &effective_config));
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the new configuration as the most recently fetched one.
15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetched_config_ = effective_config;
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetched_config_.set_id(1);  // Needed for a later DCHECK of is_valid().
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitializeUsingLastFetchedConfig();
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::InitializeUsingLastFetchedConfig() {
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetProxyConfig(false);
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(fetched_config_.is_valid());
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Increment the ID to reflect that the config has changed.
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetched_config_.set_id(next_config_id_++);
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!fetched_config_.HasAutomaticSettings()) {
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    config_ = fetched_config_;
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetReady();
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start downloading + testing the PAC scripts for this new configuration.
15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current_state_ = STATE_WAITING_FOR_INIT_PROXY_RESOLVER;
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we changed networks recently, we should delay running proxy auto-config.
15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeDelta wait_delay =
15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      stall_proxy_autoconfig_until_ - TimeTicks::Now();
15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_proxy_resolver_.reset(new InitProxyResolver());
15665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  init_proxy_resolver_->set_quick_check_enabled(quick_check_enabled_);
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = init_proxy_resolver_->Start(
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      resolver_.get(),
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      proxy_script_fetcher_.get(),
15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dhcp_proxy_script_fetcher_.get(),
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_,
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fetched_config_,
15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wait_delay,
15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&ProxyService::OnInitProxyResolverComplete,
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING)
15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnInitProxyResolverComplete(rv);
15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::InitializeUsingDecidedConfig(
15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int decider_result,
15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProxyResolverScriptData* script_data,
15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ProxyConfig& effective_config) {
15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(fetched_config_.is_valid());
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(fetched_config_.HasAutomaticSettings());
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetProxyConfig(false);
15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current_state_ = STATE_WAITING_FOR_INIT_PROXY_RESOLVER;
15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_proxy_resolver_.reset(new InitProxyResolver());
15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = init_proxy_resolver_->StartSkipDecider(
15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      resolver_.get(),
15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      effective_config,
15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      decider_result,
15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      script_data,
15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&ProxyService::OnInitProxyResolverComplete,
15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING)
16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnInitProxyResolverComplete(rv);
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::OnIPAddressChanged() {
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See the comment block by |kDelayAfterNetworkChangesMs| for info.
16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stall_proxy_autoconfig_until_ =
16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TimeTicks::Now() + stall_proxy_auto_config_delay_;
16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  State previous_state = ResetProxyConfig(false);
16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (previous_state != STATE_NONE)
16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ApplyProxyConfigIfAvailable();
16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::OnDNSChanged() {
16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnIPAddressChanged();
16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
1620