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