proxy_service.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/message_loop.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/message_loop_proxy.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/string_util.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/thread_task_runner_handle.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "googleurl/src/gurl.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/completion_callback.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/dhcp_proxy_script_fetcher.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/multi_threaded_proxy_resolver.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/network_delegate_error_observer.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_config_service_fixed.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_resolver.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_script_decider.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_script_fetcher.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/sync_host_resolver_bridge.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_context.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_config_service_win.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_resolver_winhttp.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_IOS)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_config_service_ios.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_resolver_mac.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_MACOSX)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_config_service_mac.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_resolver_mac.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_LINUX) && !defined(OS_CHROMEOS)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_config_service_linux.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_ANDROID)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_config_service_android.h"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeTicks;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kMaxNumNetLogEntries = 100;
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 LoadState GetLoadStateThreadSafe(
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RequestHandle request) const OVERRIDE {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return LOAD_STATE_IDLE;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void CancelSetPacScript() OVERRIDE {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int SetPacScript(
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const scoped_refptr<ProxyResolverScriptData>& /*script_data*/,
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const CompletionCallback& /*callback*/) OVERRIDE {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_NOT_IMPLEMENTED;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ProxyResolver that simulates a PAC script which returns
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |pac_string| for every single URL.
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ProxyResolverFromPacString : public ProxyResolver {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyResolverFromPacString(const std::string& pac_string)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : ProxyResolver(false /*expects_pac_bytes*/),
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pac_string_(pac_string) {}
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int GetProxyForURL(const GURL& url,
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             ProxyInfo* results,
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const CompletionCallback& callback,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             RequestHandle* request,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const BoundNetLog& net_log) OVERRIDE {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    results->UsePacString(pac_string_);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void CancelRequest(RequestHandle request) OVERRIDE {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return LOAD_STATE_IDLE;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual LoadState GetLoadStateThreadSafe(
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RequestHandle request) const OVERRIDE {
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return LOAD_STATE_IDLE;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void CancelSetPacScript() OVERRIDE {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int SetPacScript(
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const scoped_refptr<ProxyResolverScriptData>& pac_script,
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const CompletionCallback& callback) OVERRIDE {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string pac_string_;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates ProxyResolvers using a platform-specific implementation.
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ProxyResolverFactoryForSystem : public ProxyResolverFactory {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyResolverFactoryForSystem()
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : ProxyResolverFactory(false /*expects_pac_bytes*/) {}
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ProxyResolver* CreateProxyResolver() OVERRIDE {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(IsSupported());
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new ProxyResolverWinHttp();
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_MACOSX)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new ProxyResolverMac();
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool IsSupported() {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) || defined(OS_MACOSX)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns NetLog parameters describing a proxy configuration change.
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Value* NetLogProxyConfigChangedCallback(const ProxyConfig* old_config,
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        const ProxyConfig* new_config,
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        NetLog::LogLevel /* log_level */) {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue* dict = new DictionaryValue();
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The "old_config" is optional -- the first notification will not have
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // any "previous" configuration.
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (old_config->is_valid())
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dict->Set("old_config", old_config->ToValue());
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->Set("new_config", new_config->ToValue());
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dict;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Value* NetLogBadProxyListCallback(const ProxyRetryInfoMap* retry_info,
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  NetLog::LogLevel /* log_level */) {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue* dict = new DictionaryValue();
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListValue* list = new ListValue();
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ProxyRetryInfoMap::const_iterator iter = retry_info->begin();
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != retry_info->end(); ++iter) {
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    list->Append(Value::CreateStringValue(iter->first));
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->Set("bad_proxy_list", list);
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dict;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns NetLog parameters on a successfuly proxy resolution.
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Value* NetLogFinishedResolvingProxyCallback(ProxyInfo* result,
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            NetLog::LogLevel /* log_level */) {
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue* dict = new DictionaryValue();
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->SetString("pac_string", result->ToPacString());
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dict;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class UnsetProxyConfigService : public ProxyConfigService {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UnsetProxyConfigService() {}
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~UnsetProxyConfigService() {}
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void AddObserver(Observer* observer) OVERRIDE {}
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RemoveObserver(Observer* observer) OVERRIDE {}
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ConfigAvailability GetLatestProxyConfig(
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ProxyConfig* config) OVERRIDE {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return CONFIG_UNSET;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ProxyService::InitProxyResolver --------------------------------------------
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This glues together two asynchronous steps:
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   (1) ProxyScriptDecider -- try to fetch/validate a sequence of PAC scripts
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//       to figure out what we should configure against.
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   (2) Feed the fetched PAC script into the ProxyResolver.
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// InitProxyResolver is a single-use class which encapsulates cancellation as
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// part of its destructor. Start() or StartSkipDecider() should be called just
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// once. The instance can be destroyed at any time, and the request will be
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cancelled.
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ProxyService::InitProxyResolver {
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitProxyResolver()
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : proxy_resolver_(NULL),
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        next_state_(STATE_NONE) {
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~InitProxyResolver() {
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note that the destruction of ProxyScriptDecider will automatically cancel
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // any outstanding work.
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (next_state_ == STATE_SET_PAC_SCRIPT_COMPLETE) {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      proxy_resolver_->CancelSetPacScript();
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Begins initializing the proxy resolver; calls |callback| when done.
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int Start(ProxyResolver* proxy_resolver,
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ProxyScriptFetcher* proxy_script_fetcher,
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher,
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            NetLog* net_log,
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            const ProxyConfig& config,
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            TimeDelta wait_delay,
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            const CompletionCallback& callback) {
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(STATE_NONE, next_state_);
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proxy_resolver_ = proxy_resolver;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    decider_.reset(new ProxyScriptDecider(
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        proxy_script_fetcher, dhcp_proxy_script_fetcher, net_log));
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    config_ = config;
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wait_delay_ = wait_delay;
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback_ = callback;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_DECIDE_PROXY_SCRIPT;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return DoLoop(OK);
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Similar to Start(), however it skips the ProxyScriptDecider stage. Instead
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |effective_config|, |decider_result| and |script_data| will be used as the
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // inputs for initializing the ProxyResolver.
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int StartSkipDecider(ProxyResolver* proxy_resolver,
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const ProxyConfig& effective_config,
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       int decider_result,
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       ProxyResolverScriptData* script_data,
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const CompletionCallback& callback) {
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(STATE_NONE, next_state_);
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proxy_resolver_ = proxy_resolver;
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    effective_config_ = effective_config;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    script_data_ = script_data;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback_ = callback;
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (decider_result != OK)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return decider_result;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_SET_PAC_SCRIPT;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return DoLoop(OK);
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the proxy configuration that was selected by ProxyScriptDecider.
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Should only be called upon completion of the initialization.
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ProxyConfig& effective_config() const {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(STATE_NONE, next_state_);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return effective_config_;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the PAC script data that was selected by ProxyScriptDecider.
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Should only be called upon completion of the initialization.
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyResolverScriptData* script_data() {
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(STATE_NONE, next_state_);
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return script_data_.get();
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum State {
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STATE_NONE,
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STATE_DECIDE_PROXY_SCRIPT,
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STATE_DECIDE_PROXY_SCRIPT_COMPLETE,
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STATE_SET_PAC_SCRIPT,
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STATE_SET_PAC_SCRIPT_COMPLETE,
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoLoop(int result) {
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_NE(next_state_, STATE_NONE);
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = result;
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    do {
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      State state = next_state_;
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_state_ = STATE_NONE;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (state) {
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case STATE_DECIDE_PROXY_SCRIPT:
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DCHECK_EQ(OK, rv);
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rv = DoDecideProxyScript();
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case STATE_DECIDE_PROXY_SCRIPT_COMPLETE:
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rv = DoDecideProxyScriptComplete(rv);
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case STATE_SET_PAC_SCRIPT:
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DCHECK_EQ(OK, rv);
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rv = DoSetPacScript();
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case STATE_SET_PAC_SCRIPT_COMPLETE:
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rv = DoSetPacScriptComplete(rv);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        default:
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NOTREACHED() << "bad state: " << state;
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          rv = ERR_UNEXPECTED;
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoDecideProxyScript() {
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_DECIDE_PROXY_SCRIPT_COMPLETE;
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return decider_->Start(
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        config_, wait_delay_, proxy_resolver_->expects_pac_bytes(),
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&InitProxyResolver::OnIOCompletion, base::Unretained(this)));
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoDecideProxyScriptComplete(int result) {
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result != OK)
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return result;
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    effective_config_ = decider_->effective_config();
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    script_data_ = decider_->script_data();
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_SET_PAC_SCRIPT;
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoSetPacScript() {
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(script_data_);
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(eroman): Should log this latency to the NetLog.
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_SET_PAC_SCRIPT_COMPLETE;
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return proxy_resolver_->SetPacScript(
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        script_data_,
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&InitProxyResolver::OnIOCompletion, base::Unretained(this)));
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int DoSetPacScriptComplete(int result) {
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnIOCompletion(int result) {
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_NE(STATE_NONE, next_state_);
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = DoLoop(result);
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != ERR_IO_PENDING)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DoCallback(rv);
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DoCallback(int result) {
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_NE(ERR_IO_PENDING, result);
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback_.Run(result);
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyConfig config_;
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyConfig effective_config_;
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<ProxyResolverScriptData> script_data_;
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeDelta wait_delay_;
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ProxyScriptDecider> decider_;
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyResolver* proxy_resolver_;
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallback callback_;
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  State next_state_;
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(InitProxyResolver);
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ProxyService::ProxyScriptDeciderPoller -------------------------------------
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This helper class encapsulates the logic to schedule and run periodic
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// background checks to see if the PAC script (or effective proxy configuration)
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// has changed. If a change is detected, then the caller will be notified via
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the ChangeCallback.
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ProxyService::ProxyScriptDeciderPoller {
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef base::Callback<void(int, ProxyResolverScriptData*,
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const ProxyConfig&)> ChangeCallback;
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Builds a poller helper, and starts polling for updates. Whenever a change
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is observed, |callback| will be invoked with the details.
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   |config| specifies the (unresolved) proxy configuration to poll.
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   |proxy_resolver_expects_pac_bytes| the type of proxy resolver we expect
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                                      to use the resulting script data with
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                                      (so it can choose the right format).
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   |proxy_script_fetcher| this pointer must remain alive throughout our
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                          lifetime. It is the dependency that will be used
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                          for downloading proxy scripts.
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   |dhcp_proxy_script_fetcher| similar to |proxy_script_fetcher|, but for
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                               the DHCP dependency.
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   |init_net_error| This is the initial network error (possibly success)
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                    encountered by the first PAC fetch attempt. We use it
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                    to schedule updates more aggressively if the initial
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                    fetch resulted in an error.
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   |init_script_data| the initial script data from the PAC fetch attempt.
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                      This is the baseline used to determine when the
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                      script's contents have changed.
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   |net_log| the NetLog to log progress into.
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyScriptDeciderPoller(ChangeCallback callback,
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const ProxyConfig& config,
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           bool proxy_resolver_expects_pac_bytes,
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           ProxyScriptFetcher* proxy_script_fetcher,
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher,
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           int init_net_error,
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           ProxyResolverScriptData* init_script_data,
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           NetLog* net_log)
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        change_callback_(callback),
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        config_(config),
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        proxy_resolver_expects_pac_bytes_(proxy_resolver_expects_pac_bytes),
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        proxy_script_fetcher_(proxy_script_fetcher),
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dhcp_proxy_script_fetcher_(dhcp_proxy_script_fetcher),
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        last_error_(init_net_error),
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        last_script_data_(init_script_data),
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        last_poll_time_(TimeTicks::Now()) {
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Set the initial poll delay.
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_poll_mode_ = poll_policy()->GetNextDelay(
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        last_error_, TimeDelta::FromSeconds(-1), &next_poll_delay_);
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TryToStartNextPoll(false);
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnLazyPoll() {
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We have just been notified of network activity. Use this opportunity to
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // see if we can start our next poll.
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TryToStartNextPoll(true);
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const PacPollPolicy* set_policy(const PacPollPolicy* policy) {
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PacPollPolicy* prev = poll_policy_;
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    poll_policy_ = policy;
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return prev;
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the effective poll policy (the one injected by unit-tests, or the
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // default).
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const PacPollPolicy* poll_policy() {
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (poll_policy_)
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return poll_policy_;
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &default_poll_policy_;
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartPollTimer() {
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!decider_.get());
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MessageLoop::current()->PostDelayedTask(
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&ProxyScriptDeciderPoller::DoPoll,
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_factory_.GetWeakPtr()),
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        next_poll_delay_);
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void TryToStartNextPoll(bool triggered_by_activity) {
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (next_poll_mode_) {
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PacPollPolicy::MODE_USE_TIMER:
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!triggered_by_activity)
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          StartPollTimer();
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PacPollPolicy::MODE_START_AFTER_ACTIVITY:
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (triggered_by_activity && !decider_.get()) {
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          TimeDelta elapsed_time = TimeTicks::Now() - last_poll_time_;
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (elapsed_time >= next_poll_delay_)
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            DoPoll();
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DoPoll() {
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_poll_time_ = TimeTicks::Now();
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Start the proxy script decider to see if anything has changed.
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(eroman): Pass a proper NetLog rather than NULL.
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    decider_.reset(new ProxyScriptDecider(
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        proxy_script_fetcher_, dhcp_proxy_script_fetcher_, NULL));
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int result = decider_->Start(
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        config_, TimeDelta(), proxy_resolver_expects_pac_bytes_,
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&ProxyScriptDeciderPoller::OnProxyScriptDeciderCompleted,
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   base::Unretained(this)));
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result != ERR_IO_PENDING)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OnProxyScriptDeciderCompleted(result);
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnProxyScriptDeciderCompleted(int result) {
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (HasScriptDataChanged(result, decider_->script_data())) {
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Something has changed, we must notify the ProxyService so it can
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // re-initialize its ProxyResolver. Note that we post a notification task
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // rather than calling it directly -- this is done to avoid an ugly
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // destruction sequence, since |this| might be destroyed as a result of
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the notification.
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MessageLoop::current()->PostTask(
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            &ProxyScriptDeciderPoller::NotifyProxyServiceOfChange,
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            weak_factory_.GetWeakPtr(),
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            result,
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            make_scoped_refptr(decider_->script_data()),
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            decider_->effective_config()));
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    decider_.reset();
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Decide when the next poll should take place, and possibly start the
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // next timer.
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_poll_mode_ = poll_policy()->GetNextDelay(
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        last_error_, next_poll_delay_, &next_poll_delay_);
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TryToStartNextPoll(false);
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool HasScriptDataChanged(int result, ProxyResolverScriptData* script_data) {
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result != last_error_) {
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Something changed -- it was failing before and now it succeeded, or
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // conversely it succeeded before and now it failed. Or it failed in
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // both cases, however the specific failure error codes differ.
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result != OK) {
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If it failed last time and failed again with the same error code this
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // time, then nothing has actually changed.
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Otherwise if it succeeded both this time and last time, we need to look
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // closer and see if we ended up downloading different content for the PAC
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // script.
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return !script_data->Equals(last_script_data_);
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void NotifyProxyServiceOfChange(
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int result,
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const scoped_refptr<ProxyResolverScriptData>& script_data,
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const ProxyConfig& effective_config) {
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note that |this| may be deleted after calling into the ProxyService.
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    change_callback_.Run(result, script_data, effective_config);
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtrFactory<ProxyScriptDeciderPoller> weak_factory_;
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChangeCallback change_callback_;
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyConfig config_;
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool proxy_resolver_expects_pac_bytes_;
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyScriptFetcher* proxy_script_fetcher_;
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher_;
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int last_error_;
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<ProxyResolverScriptData> last_script_data_;
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ProxyScriptDecider> decider_;
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeDelta next_poll_delay_;
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PacPollPolicy::Mode next_poll_mode_;
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeTicks last_poll_time_;
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Polling policy injected by unit-tests. Otherwise this is NULL and the
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // default policy will be used.
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const PacPollPolicy* poll_policy_;
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const DefaultPollPolicy default_poll_policy_;
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ProxyScriptDeciderPoller);
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ProxyService::PacPollPolicy*
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProxyService::ProxyScriptDeciderPoller::poll_policy_ = NULL;
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ProxyService::PacRequest ---------------------------------------------------
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ProxyService::PacRequest
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public base::RefCounted<ProxyService::PacRequest> {
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PacRequest(ProxyService* service,
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             const GURL& url,
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             ProxyInfo* results,
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             const net::CompletionCallback& user_callback,
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             const BoundNetLog& net_log)
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : service_(service),
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        user_callback_(user_callback),
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        results_(results),
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        url_(url),
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        resolve_job_(NULL),
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        config_id_(ProxyConfig::kInvalidConfigID),
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        config_source_(PROXY_CONFIG_SOURCE_UNKNOWN),
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net_log_(net_log) {
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!user_callback.is_null());
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Starts the resolve proxy request.
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int Start() {
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!was_cancelled());
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!is_started());
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(service_->config_.is_valid());
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    config_id_ = service_->config_.id();
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    config_source_ = service_->config_.source();
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return resolver()->GetProxyForURL(
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        url_, results_,
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&PacRequest::QueryComplete, base::Unretained(this)),
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &resolve_job_, net_log_);
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_started() const {
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note that !! casts to bool. (VS gives a warning otherwise).
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return !!resolve_job_;
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartAndCompleteCheckingForSynchronous() {
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = service_->TryToCompleteSynchronously(url_, results_);
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == ERR_IO_PENDING)
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = Start();
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != ERR_IO_PENDING)
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      QueryComplete(rv);
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CancelResolveJob() {
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(is_started());
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The request may already be running in the resolver.
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    resolver()->CancelRequest(resolve_job_);
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    resolve_job_ = NULL;
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!is_started());
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Cancel() {
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.AddEvent(NetLog::TYPE_CANCELLED);
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (is_started())
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CancelResolveJob();
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Mark as cancelled, to prevent accessing this again later.
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_ = NULL;
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_callback_.Reset();
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    results_ = NULL;
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEvent(NetLog::TYPE_PROXY_SERVICE);
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if Cancel() has been called.
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool was_cancelled() const {
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return user_callback_.is_null();
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Helper to call after ProxyResolver completion (both synchronous and
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // asynchronous). Fixes up the result that is to be returned to user.
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int QueryDidComplete(int result_code) {
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!was_cancelled());
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note that DidFinishResolvingProxy might modify |results_|.
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = service_->DidFinishResolvingProxy(results_, result_code, net_log_);
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Make a note in the results which configuration was in use at the
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // time of the resolve.
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    results_->config_id_ = config_id_;
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    results_->config_source_ = config_source_;
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    results_->did_use_pac_script_ = true;
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Reset the state associated with in-progress-resolve.
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    resolve_job_ = NULL;
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    config_id_ = ProxyConfig::kInvalidConfigID;
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    config_source_ = PROXY_CONFIG_SOURCE_UNKNOWN;
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BoundNetLog* net_log() { return &net_log_; }
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoadState GetLoadState() const {
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (is_started())
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return resolver()->GetLoadState(resolve_job_);
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return LOAD_STATE_RESOLVING_PROXY_FOR_URL;
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class base::RefCounted<ProxyService::PacRequest>;
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~PacRequest() {}
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Callback for when the ProxyResolver request has completed.
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void QueryComplete(int result_code) {
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result_code = QueryDidComplete(result_code);
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Remove this completed PacRequest from the service's pending list.
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /// (which will probably cause deletion of |this|).
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!user_callback_.is_null()){
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::CompletionCallback callback = user_callback_;
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      service_->RemovePendingRequest(this);
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback.Run(result_code);
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyResolver* resolver() const { return service_->resolver_.get(); }
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that we don't hold a reference to the ProxyService. Outstanding
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // requests are cancelled during ~ProxyService, so this is guaranteed
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to be valid throughout our lifetime.
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyService* service_;
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::CompletionCallback user_callback_;
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyInfo* results_;
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url_;
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyResolver::RequestHandle resolve_job_;
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyConfig::ID config_id_;  // The config id when the resolve was started.
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyConfigSource config_source_;  // The source of proxy settings.
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BoundNetLog net_log_;
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ProxyService ---------------------------------------------------------------
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyService::ProxyService(ProxyConfigService* config_service,
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           ProxyResolver* resolver,
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           NetLog* net_log)
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : resolver_(resolver),
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_config_id_(1),
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      current_state_(STATE_NONE) ,
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_(net_log),
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      stall_proxy_auto_config_delay_(TimeDelta::FromMilliseconds(
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          kDelayAfterNetworkChangesMs)) {
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NetworkChangeNotifier::AddIPAddressObserver(this);
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NetworkChangeNotifier::AddDNSObserver(this);
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetConfigService(config_service);
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyService* ProxyService::CreateUsingSystemProxyResolver(
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProxyConfigService* proxy_config_service,
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t num_pac_threads,
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NetLog* net_log) {
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(proxy_config_service);
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ProxyResolverFactoryForSystem::IsSupported()) {
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "PAC support disabled because there is no "
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "system implementation";
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return CreateWithoutProxyResolver(proxy_config_service, net_log);
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (num_pac_threads == 0)
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    num_pac_threads = kDefaultNumPacThreads;
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyResolver* proxy_resolver = new MultiThreadedProxyResolver(
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new ProxyResolverFactoryForSystem(), num_pac_threads);
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new ProxyService(proxy_config_service, proxy_resolver, net_log);
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyService* ProxyService::CreateWithoutProxyResolver(
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProxyConfigService* proxy_config_service,
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NetLog* net_log) {
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new ProxyService(proxy_config_service,
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          new ProxyResolverNull(),
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          net_log);
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyService* ProxyService::CreateFixed(const ProxyConfig& pc) {
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(eroman): This isn't quite right, won't work if |pc| specifies
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //               a PAC script.
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CreateUsingSystemProxyResolver(new ProxyConfigServiceFixed(pc),
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        0, NULL);
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyService* ProxyService::CreateFixed(const std::string& proxy) {
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::ProxyConfig proxy_config;
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxy_config.proxy_rules().ParseFromString(proxy);
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ProxyService::CreateFixed(proxy_config);
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyService* ProxyService::CreateDirect() {
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CreateDirectWithNetLog(NULL);
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyService* ProxyService::CreateDirectWithNetLog(NetLog* net_log) {
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use direct connections.
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new ProxyService(new ProxyConfigServiceDirect, new ProxyResolverNull,
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          net_log);
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyService* ProxyService::CreateFixedFromPacResult(
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& pac_string) {
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We need the settings to contain an "automatic" setting, otherwise the
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ProxyResolver dependency we give it will never be used.
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ProxyConfigService> proxy_config_service(
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new ProxyConfigServiceFixed(ProxyConfig::CreateAutoDetect()));
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ProxyResolver> proxy_resolver(
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new ProxyResolverFromPacString(pac_string));
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new ProxyService(proxy_config_service.release(),
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          proxy_resolver.release(),
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          NULL);
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ProxyService::ResolveProxy(const GURL& raw_url,
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               ProxyInfo* result,
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const net::CompletionCallback& callback,
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               PacRequest** pac_request,
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const BoundNetLog& net_log) {
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log.BeginEvent(NetLog::TYPE_PROXY_SERVICE);
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Notify our polling-based dependencies that a resolve is taking place.
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This way they can schedule their polls in response to network activity.
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_service_->OnLazyPoll();
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (script_poller_.get())
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     script_poller_->OnLazyPoll();
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (current_state_ == STATE_NONE)
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ApplyProxyConfigIfAvailable();
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Strip away any reference fragments and the username/password, as they
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // are not relevant to proxy resolution.
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url = SimplifyUrlForRequest(raw_url);
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if the request can be completed right away. (This is the case when
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // using a direct connection for example).
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = TryToCompleteSynchronously(url, result);
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING)
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return DidFinishResolvingProxy(result, rv, net_log);
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<PacRequest> req(
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new PacRequest(this, url, result, callback, net_log));
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (current_state_ == STATE_READY) {
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Start the resolve request.
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = req->Start();
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != ERR_IO_PENDING)
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return req->QueryDidComplete(rv);
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    req->net_log()->BeginEvent(NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC);
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(ERR_IO_PENDING, rv);
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!ContainsPendingRequest(req));
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_requests_.push_back(req);
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Completion will be notified through |callback|, unless the caller cancels
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the request using |pac_request|.
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pac_request)
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *pac_request = req.get();
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;  // ERR_IO_PENDING
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ProxyService::TryToCompleteSynchronously(const GURL& url,
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             ProxyInfo* result) {
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(STATE_NONE, current_state_);
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (current_state_ != STATE_READY)
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;  // Still initializing.
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(config_.id(), ProxyConfig::kInvalidConfigID);
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If it was impossible to fetch or parse the PAC script, we cannot complete
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the request here and bail out.
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (permanent_error_ != OK)
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return permanent_error_;
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (config_.HasAutomaticSettings())
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;  // Must submit the request to the proxy resolver.
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use the manual proxy settings.
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.proxy_rules().Apply(url, result);
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->config_source_ = config_.source();
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->config_id_ = config_.id();
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyService::~ProxyService() {
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NetworkChangeNotifier::RemoveIPAddressObserver(this);
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NetworkChangeNotifier::RemoveDNSObserver(this);
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_service_->RemoveObserver(this);
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cancel any inprogress requests.
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PendingRequests::iterator it = pending_requests_.begin();
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != pending_requests_.end();
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++it) {
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*it)->Cancel();
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::SuspendAllPendingRequests() {
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PendingRequests::iterator it = pending_requests_.begin();
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != pending_requests_.end();
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++it) {
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PacRequest* req = it->get();
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (req->is_started()) {
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      req->CancelResolveJob();
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      req->net_log()->BeginEvent(
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC);
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::SetReady() {
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!init_proxy_resolver_.get());
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current_state_ = STATE_READY;
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make a copy in case |this| is deleted during the synchronous completion
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of one of the requests. If |this| is deleted then all of the PacRequest
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // instances will be Cancel()-ed.
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingRequests pending_copy = pending_requests_;
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PendingRequests::iterator it = pending_copy.begin();
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != pending_copy.end();
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++it) {
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PacRequest* req = it->get();
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!req->is_started() && !req->was_cancelled()) {
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      req->net_log()->EndEvent(NetLog::TYPE_PROXY_SERVICE_WAITING_FOR_INIT_PAC);
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Note that we re-check for synchronous completion, in case we are
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // no longer using a ProxyResolver (can happen if we fell-back to manual).
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      req->StartAndCompleteCheckingForSynchronous();
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::ApplyProxyConfigIfAvailable() {
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, current_state_);
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_service_->OnLazyPoll();
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we have already fetched the configuration, start applying it.
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (fetched_config_.is_valid()) {
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitializeUsingLastFetchedConfig();
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Otherwise we need to first fetch the configuration.
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current_state_ = STATE_WAITING_FOR_PROXY_CONFIG;
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Retrieve the current proxy configuration from the ProxyConfigService.
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If a configuration is not available yet, we will get called back later
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // by our ProxyConfigService::Observer once it changes.
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyConfig config;
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyConfigService::ConfigAvailability availability =
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      config_service_->GetLatestProxyConfig(&config);
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (availability != ProxyConfigService::CONFIG_PENDING)
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnProxyConfigChanged(config, availability);
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::OnInitProxyResolverComplete(int result) {
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_WAITING_FOR_INIT_PROXY_RESOLVER, current_state_);
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(init_proxy_resolver_.get());
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(fetched_config_.HasAutomaticSettings());
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_ = init_proxy_resolver_->effective_config();
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // At this point we have decided which proxy settings to use (i.e. which PAC
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // script if any). We start up a background poller to periodically revisit
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this decision. If the contents of the PAC script change, or if the
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // result of proxy auto-discovery changes, this poller will notice it and
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // will trigger a re-initialization using the newly discovered PAC.
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  script_poller_.reset(new ProxyScriptDeciderPoller(
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&ProxyService::InitializeUsingDecidedConfig,
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)),
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fetched_config_,
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      resolver_->expects_pac_bytes(),
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      proxy_script_fetcher_.get(),
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dhcp_proxy_script_fetcher_.get(),
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result,
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      init_proxy_resolver_->script_data(),
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NULL));
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_proxy_resolver_.reset();
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != OK) {
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fetched_config_.pac_mandatory()) {
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VLOG(1) << "Failed configuring with mandatory PAC script, blocking all "
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 "traffic.";
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      config_ = fetched_config_;
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = ERR_MANDATORY_PROXY_CONFIGURATION_FAILED;
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VLOG(1) << "Failed configuring with PAC script, falling-back to manual "
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 "proxy servers.";
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      config_ = fetched_config_;
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      config_.ClearAutomaticSettings();
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result = OK;
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  permanent_error_ = result;
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(eroman): Make this ID unique in the case where configuration changed
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //               due to ProxyScriptDeciderPoller.
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.set_id(fetched_config_.id());
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_.set_source(fetched_config_.source());
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Resume any requests which we had to defer until the PAC script was
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // downloaded.
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetReady();
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ProxyService::ReconsiderProxyAfterError(const GURL& url,
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            ProxyInfo* result,
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            const CompletionCallback& callback,
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            PacRequest** pac_request,
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            const BoundNetLog& net_log) {
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check to see if we have a new config since ResolveProxy was called.  We
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // want to re-run ResolveProxy in two cases: 1) we have a new config, or 2) a
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // direct connection failed and we never tried the current config.
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool re_resolve = result->config_id_ != config_.id();
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (re_resolve) {
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we have a new config or the config was never tried, we delete the
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // list of bad proxies and we try again.
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proxy_retry_info_.clear();
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ResolveProxy(url, result, callback, pac_request, net_log);
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't have new proxy settings to try, try to fallback to the next proxy
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in the list.
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool did_fallback = result->Fallback(net_log);
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Return synchronous failure if there is nothing left to fall-back to.
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(eroman): This is a yucky API, clean it up.
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return did_fallback ? OK : ERR_FAILED;
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProxyService::MarkProxyAsBad(const ProxyInfo& result,
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const BoundNetLog& net_log) {
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result.proxy_list_.UpdateRetryInfoOnFallback(&proxy_retry_info_, net_log);
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result.proxy_list_.HasUntriedProxies(proxy_retry_info_);
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::ReportSuccess(const ProxyInfo& result) {
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ProxyRetryInfoMap& new_retry_info = result.proxy_retry_info();
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (new_retry_info.empty())
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (ProxyRetryInfoMap::const_iterator iter = new_retry_info.begin();
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != new_retry_info.end(); ++iter) {
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProxyRetryInfoMap::iterator existing = proxy_retry_info_.find(iter->first);
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (existing == proxy_retry_info_.end())
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      proxy_retry_info_[iter->first] = iter->second;
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (existing->second.bad_until < iter->second.bad_until)
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      existing->second.bad_until = iter->second.bad_until;
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (net_log_) {
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_->AddGlobalEntry(
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NetLog::TYPE_BAD_PROXY_LIST_REPORTED,
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&NetLogBadProxyListCallback, &new_retry_info));
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::CancelPacRequest(PacRequest* req) {
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(req);
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  req->Cancel();
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RemovePendingRequest(req);
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LoadState ProxyService::GetLoadState(const PacRequest* req) const {
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(req);
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return req->GetLoadState();
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProxyService::ContainsPendingRequest(PacRequest* req) {
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingRequests::iterator it = std::find(
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_requests_.begin(), pending_requests_.end(), req);
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return pending_requests_.end() != it;
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::RemovePendingRequest(PacRequest* req) {
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(ContainsPendingRequest(req));
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingRequests::iterator it = std::find(
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_requests_.begin(), pending_requests_.end(), req);
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_requests_.erase(it);
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ProxyService::DidFinishResolvingProxy(ProxyInfo* result,
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          int result_code,
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const BoundNetLog& net_log) {
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Log the result of the proxy resolution.
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result_code == OK) {
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // When logging all events is enabled, dump the proxy list.
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (net_log.IsLoggingAllEvents()) {
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log.AddEvent(
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NetLog::TYPE_PROXY_SERVICE_RESOLVED_PROXY_LIST,
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&NetLogFinishedResolvingProxyCallback, result));
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result->DeprioritizeBadProxies(proxy_retry_info_);
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log.AddEventWithNetErrorCode(
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NetLog::TYPE_PROXY_SERVICE_RESOLVED_PROXY_LIST, result_code);
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!config_.pac_mandatory()) {
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Fall-back to direct when the proxy resolver fails. This corresponds
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // with a javascript runtime error in the PAC script.
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This implicit fall-back to direct matches Firefox 3.5 and
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Internet Explorer 8. For more information, see:
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // http://www.chromium.org/developers/design-documents/proxy-settings-fallback
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result->UseDirect();
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result_code = OK;
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result_code = ERR_MANDATORY_PROXY_CONFIGURATION_FAILED;
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log.EndEvent(NetLog::TYPE_PROXY_SERVICE);
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result_code;
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::SetProxyScriptFetchers(
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProxyScriptFetcher* proxy_script_fetcher,
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher) {
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  State previous_state = ResetProxyConfig(false);
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxy_script_fetcher_.reset(proxy_script_fetcher);
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dhcp_proxy_script_fetcher_.reset(dhcp_proxy_script_fetcher);
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (previous_state != STATE_NONE)
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ApplyProxyConfigIfAvailable();
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyScriptFetcher* ProxyService::GetProxyScriptFetcher() const {
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return proxy_script_fetcher_.get();
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyService::State ProxyService::ResetProxyConfig(bool reset_fetched_config) {
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  State previous_state = current_state_;
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  permanent_error_ = OK;
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  proxy_retry_info_.clear();
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  script_poller_.reset();
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_proxy_resolver_.reset();
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SuspendAllPendingRequests();
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_ = ProxyConfig();
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (reset_fetched_config)
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fetched_config_ = ProxyConfig();
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current_state_ = STATE_NONE;
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return previous_state;
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::ResetConfigService(
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProxyConfigService* new_proxy_config_service) {
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  State previous_state = ResetProxyConfig(true);
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Release the old configuration service.
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (config_service_.get())
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    config_service_->RemoveObserver(this);
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the new configuration service.
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_service_.reset(new_proxy_config_service);
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  config_service_->AddObserver(this);
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (previous_state != STATE_NONE)
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ApplyProxyConfigIfAvailable();
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::PurgeMemory() {
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (resolver_.get())
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    resolver_->PurgeMemory();
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::ForceReloadProxyConfig() {
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(CalledOnValidThread());
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetProxyConfig(false);
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ApplyProxyConfigIfAvailable();
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyConfigService* ProxyService::CreateSystemProxyConfigService(
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SingleThreadTaskRunner* io_thread_task_runner,
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MessageLoop* file_loop) {
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new ProxyConfigServiceWin();
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_IOS)
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new ProxyConfigServiceIOS();
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_MACOSX)
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new ProxyConfigServiceMac(io_thread_task_runner);
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_CHROMEOS)
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(ERROR) << "ProxyConfigService for ChromeOS should be created in "
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << "profile_io_data.cc::CreateProxyConfigService and this should "
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << "be used only for examples.";
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new UnsetProxyConfigService;
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_LINUX)
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyConfigServiceLinux* linux_config_service =
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new ProxyConfigServiceLinux();
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Assume we got called on the thread that runs the default glib
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // main loop, so the current thread is where we should be running
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // gconf calls from.
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<base::SingleThreadTaskRunner> glib_thread_task_runner =
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::ThreadTaskRunnerHandle::Get();
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The file loop should be a MessageLoopForIO on Linux.
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(MessageLoop::TYPE_IO, file_loop->type());
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Synchronously fetch the current proxy config (since we are
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // running on glib_default_loop). Additionally register for
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // notifications (delivered in either |glib_default_loop| or
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |file_loop|) to keep us updated when the proxy config changes.
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  linux_config_service->SetupAndFetchInitialConfig(
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      glib_thread_task_runner, io_thread_task_runner,
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<MessageLoopForIO*>(file_loop));
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return linux_config_service;
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_ANDROID)
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new ProxyConfigServiceAndroid(
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      io_thread_task_runner,
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MessageLoop::current()->message_loop_proxy());
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(WARNING) << "Failed to choose a system proxy settings fetcher "
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  "for this platform.";
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new ProxyConfigServiceDirect();
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ProxyService::PacPollPolicy* ProxyService::set_pac_script_poll_policy(
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PacPollPolicy* policy) {
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ProxyScriptDeciderPoller::set_policy(policy);
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<ProxyService::PacPollPolicy>
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyService::CreateDefaultPacPollPolicy() {
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return scoped_ptr<PacPollPolicy>(new DefaultPollPolicy());
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::OnProxyConfigChanged(
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ProxyConfig& config,
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProxyConfigService::ConfigAvailability availability) {
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Retrieve the current proxy configuration from the ProxyConfigService.
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If a configuration is not available yet, we will get called back later
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // by our ProxyConfigService::Observer once it changes.
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyConfig effective_config;
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (availability) {
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ProxyConfigService::CONFIG_PENDING:
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // ProxyConfigService implementors should never pass CONFIG_PENDING.
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED() << "Proxy config change with CONFIG_PENDING availability!";
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ProxyConfigService::CONFIG_VALID:
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      effective_config = config;
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ProxyConfigService::CONFIG_UNSET:
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      effective_config = ProxyConfig::CreateDirect();
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Emit the proxy settings change to the NetLog stream.
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (net_log_) {
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_->AddGlobalEntry(
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net::NetLog::TYPE_PROXY_CONFIG_CHANGED,
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&NetLogProxyConfigChangedCallback,
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   &fetched_config_, &effective_config));
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set the new configuration as the most recently fetched one.
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetched_config_ = effective_config;
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetched_config_.set_id(1);  // Needed for a later DCHECK of is_valid().
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitializeUsingLastFetchedConfig();
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::InitializeUsingLastFetchedConfig() {
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetProxyConfig(false);
14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(fetched_config_.is_valid());
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Increment the ID to reflect that the config has changed.
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetched_config_.set_id(next_config_id_++);
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!fetched_config_.HasAutomaticSettings()) {
14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    config_ = fetched_config_;
14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetReady();
14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start downloading + testing the PAC scripts for this new configuration.
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current_state_ = STATE_WAITING_FOR_INIT_PROXY_RESOLVER;
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we changed networks recently, we should delay running proxy auto-config.
14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeDelta wait_delay =
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      stall_proxy_autoconfig_until_ - TimeTicks::Now();
14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_proxy_resolver_.reset(new InitProxyResolver());
14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = init_proxy_resolver_->Start(
14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      resolver_.get(),
14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      proxy_script_fetcher_.get(),
14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dhcp_proxy_script_fetcher_.get(),
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_,
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fetched_config_,
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wait_delay,
14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&ProxyService::OnInitProxyResolverComplete,
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING)
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnInitProxyResolverComplete(rv);
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::InitializeUsingDecidedConfig(
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int decider_result,
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProxyResolverScriptData* script_data,
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ProxyConfig& effective_config) {
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(fetched_config_.is_valid());
14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(fetched_config_.HasAutomaticSettings());
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResetProxyConfig(false);
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current_state_ = STATE_WAITING_FOR_INIT_PROXY_RESOLVER;
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  init_proxy_resolver_.reset(new InitProxyResolver());
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = init_proxy_resolver_->StartSkipDecider(
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      resolver_.get(),
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      effective_config,
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      decider_result,
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      script_data,
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&ProxyService::OnInitProxyResolverComplete,
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING)
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnInitProxyResolverComplete(rv);
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::OnIPAddressChanged() {
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See the comment block by |kDelayAfterNetworkChangesMs| for info.
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stall_proxy_autoconfig_until_ =
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TimeTicks::Now() + stall_proxy_auto_config_delay_;
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  State previous_state = ResetProxyConfig(false);
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (previous_state != STATE_NONE)
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ApplyProxyConfigIfAvailable();
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyService::OnDNSChanged() {
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnIPAddressChanged();
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncProxyServiceHelper::SyncProxyServiceHelper(MessageLoop* io_message_loop,
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               ProxyService* proxy_service)
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : io_message_loop_(io_message_loop),
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      proxy_service_(proxy_service),
15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event_(false, false),
15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ALLOW_THIS_IN_INITIALIZER_LIST(callback_(
15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&SyncProxyServiceHelper::OnCompletion,
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     base::Unretained(this)))) {
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(io_message_loop_ != MessageLoop::current());
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SyncProxyServiceHelper::ResolveProxy(const GURL& url,
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         ProxyInfo* proxy_info,
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const BoundNetLog& net_log) {
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(io_message_loop_ != MessageLoop::current());
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io_message_loop_->PostTask(
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&SyncProxyServiceHelper::StartAsyncResolve, this, url,
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 net_log));
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_.Wait();
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result_ == net::OK) {
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *proxy_info = proxy_info_;
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result_;
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SyncProxyServiceHelper::ReconsiderProxyAfterError(
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url, ProxyInfo* proxy_info, const BoundNetLog& net_log) {
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(io_message_loop_ != MessageLoop::current());
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io_message_loop_->PostTask(
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&SyncProxyServiceHelper::StartAsyncReconsider, this, url,
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 net_log));
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_.Wait();
15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result_ == net::OK) {
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *proxy_info = proxy_info_;
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result_;
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncProxyServiceHelper::~SyncProxyServiceHelper() {}
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncProxyServiceHelper::StartAsyncResolve(const GURL& url,
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               const BoundNetLog& net_log) {
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result_ = proxy_service_->ResolveProxy(
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      url, &proxy_info_, callback_, NULL, net_log);
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result_ != net::ERR_IO_PENDING) {
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnCompletion(result_);
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncProxyServiceHelper::StartAsyncReconsider(const GURL& url,
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  const BoundNetLog& net_log) {
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result_ = proxy_service_->ReconsiderProxyAfterError(
15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      url, &proxy_info_, callback_, NULL, net_log);
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result_ != net::ERR_IO_PENDING) {
15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnCompletion(result_);
15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncProxyServiceHelper::OnCompletion(int rv) {
15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result_ = rv;
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_.Signal();
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
1571