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