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_script_decider.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/format_macros.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
12d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/metrics/histogram.h"
135e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/dhcp_proxy_script_fetcher.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/dhcp_proxy_script_fetcher_factory.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_script_fetcher.h"
20d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "net/url_request/url_request_context.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool LooksLikePacScript(const base::string16& script) {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: this is only an approximation! It may not always work correctly,
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // however it is very likely that legitimate scripts have this exact string,
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // since they must minimally define a function of this name. Conversely, a
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // file not containing the string is not likely to be a PAC script.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // An exact test would have to load the script in a javascript evaluator.
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return script.find(base::ASCIIToUTF16("FindProxyForURL")) !=
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)             base::string16::npos;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is the hard-coded location used by the DNS portion of web proxy
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// auto-discovery.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note that we not use DNS devolution to find the WPAD host, since that could
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be dangerous should our top level domain registry  become out of date.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Instead we directly resolve "wpad", and let the operating system apply the
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DNS suffix search paths. This is the same approach taken by Firefox, and
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// compatibility hasn't been an issue.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For more details, also check out this comment:
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://code.google.com/p/chromium/issues/detail?id=18575#c20
51d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace {
52d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)const char kWpadUrl[] = "http://wpad/wpad.dat";
53d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)const int kQuickCheckDelayMs = 1000;
54d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)};
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)base::Value* ProxyScriptDecider::PacSource::NetLogCallback(
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL* effective_pac_url,
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NetLog::LogLevel /* log_level */) const {
597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::DictionaryValue* dict = new base::DictionaryValue();
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string source;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PacSource::WPAD_DHCP:
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      source = "WPAD DHCP";
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PacSource::WPAD_DNS:
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      source = "WPAD DNS: ";
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      source += effective_pac_url->possibly_invalid_spec();
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PacSource::CUSTOM:
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      source = "Custom PAC URL: ";
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      source += effective_pac_url->possibly_invalid_spec();
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->SetString("source", source);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dict;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyScriptDecider::ProxyScriptDecider(
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProxyScriptFetcher* proxy_script_fetcher,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NetLog* net_log)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : resolver_(NULL),
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      proxy_script_fetcher_(proxy_script_fetcher),
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dhcp_proxy_script_fetcher_(dhcp_proxy_script_fetcher),
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      current_pac_source_index_(0u),
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pac_mandatory_(false),
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_state_(STATE_NONE),
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_(BoundNetLog::Make(
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          net_log, NetLog::SOURCE_PROXY_SCRIPT_DECIDER)),
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      fetch_pac_bytes_(false),
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      quick_check_enabled_(true) {
92d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (proxy_script_fetcher &&
93d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      proxy_script_fetcher->GetRequestContext() &&
94d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      proxy_script_fetcher->GetRequestContext()->host_resolver()) {
95d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      host_resolver_.reset(new SingleRequestHostResolver(
96d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          proxy_script_fetcher->GetRequestContext()->host_resolver()));
97d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyScriptDecider::~ProxyScriptDecider() {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (next_state_ != STATE_NONE)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Cancel();
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ProxyScriptDecider::Start(
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ProxyConfig& config, const base::TimeDelta wait_delay,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool fetch_pac_bytes, const CompletionCallback& callback) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_state_);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(config.HasAutomaticSettings());
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.BeginEvent(NetLog::TYPE_PROXY_SCRIPT_DECIDER);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetch_pac_bytes_ = fetch_pac_bytes;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Save the |wait_delay| as a non-negative value.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wait_delay_ = wait_delay;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (wait_delay_ < base::TimeDelta())
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wait_delay_ = base::TimeDelta();
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pac_mandatory_ = config.pac_mandatory();
122d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  have_custom_pac_url_ = config.has_pac_url();
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pac_sources_ = BuildPacSourcesFallbackList(config);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!pac_sources_.empty());
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_WAIT;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoLoop(OK);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback_ = callback;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DidComplete();
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ProxyConfig& ProxyScriptDecider::effective_config() const {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_state_);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return effective_config_;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(eroman): Return a const-pointer.
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyResolverScriptData* ProxyScriptDecider::script_data() const {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_state_);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return script_data_.get();
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Initialize the fallback rules.
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (1) WPAD (DHCP).
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (2) WPAD (DNS).
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (3) Custom PAC URL.
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyScriptDecider::PacSourceList ProxyScriptDecider::
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BuildPacSourcesFallbackList(
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ProxyConfig& config) const {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PacSourceList pac_sources;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (config.auto_detect()) {
158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    pac_sources.push_back(PacSource(PacSource::WPAD_DHCP, GURL(kWpadUrl)));
159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    pac_sources.push_back(PacSource(PacSource::WPAD_DNS, GURL(kWpadUrl)));
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (config.has_pac_url())
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pac_sources.push_back(PacSource(PacSource::CUSTOM, config.pac_url()));
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return pac_sources;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyScriptDecider::OnIOCompletion(int result) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(STATE_NONE, next_state_);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoLoop(result);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DidComplete();
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoCallback(rv);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ProxyScriptDecider::DoLoop(int result) {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(next_state_, STATE_NONE);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = result;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    State state = next_state_;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_NONE;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (state) {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_WAIT:
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoWait();
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_WAIT_COMPLETE:
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoWaitComplete(rv);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
189d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      case STATE_QUICK_CHECK:
190d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        DCHECK_EQ(OK, rv);
191d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        rv = DoQuickCheck();
192d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        break;
193d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      case STATE_QUICK_CHECK_COMPLETE:
194d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        rv = DoQuickCheckComplete(rv);
195d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        break;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_FETCH_PAC_SCRIPT:
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoFetchPacScript();
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_FETCH_PAC_SCRIPT_COMPLETE:
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoFetchPacScriptComplete(rv);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_VERIFY_PAC_SCRIPT:
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoVerifyPacScript();
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_VERIFY_PAC_SCRIPT_COMPLETE:
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoVerifyPacScriptComplete(rv);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTREACHED() << "bad state";
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = ERR_UNEXPECTED;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyScriptDecider::DoCallback(int result) {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(ERR_IO_PENDING, result);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback_.is_null());
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback_.Run(result);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ProxyScriptDecider::DoWait() {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_WAIT_COMPLETE;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If no waiting is required, continue on to the next state.
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (wait_delay_.ToInternalValue() == 0)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Otherwise wait the specified amount of time.
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wait_timer_.Start(FROM_HERE, wait_delay_, this,
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    &ProxyScriptDecider::OnWaitTimerFired);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.BeginEvent(NetLog::TYPE_PROXY_SCRIPT_DECIDER_WAIT);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ERR_IO_PENDING;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ProxyScriptDecider::DoWaitComplete(int result) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(OK, result);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (wait_delay_.ToInternalValue() != 0) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_PROXY_SCRIPT_DECIDER_WAIT,
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      result);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (quick_check_enabled_ && current_pac_source().type == PacSource::WPAD_DNS)
246f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    next_state_ = STATE_QUICK_CHECK;
247f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  else
248f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    next_state_ = GetStartState();
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
252d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int ProxyScriptDecider::DoQuickCheck() {
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(quick_check_enabled_);
254d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (host_resolver_.get() == NULL) {
255d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // If we have no resolver, skip QuickCheck altogether.
256d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    next_state_ = GetStartState();
257d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return OK;
258d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
259d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
260d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  quick_check_start_time_ = base::Time::Now();
261f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::string host = current_pac_source().url.host();
262f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  HostResolver::RequestInfo reqinfo(HostPortPair(host, 80));
263d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  reqinfo.set_host_resolver_flags(HOST_RESOLVER_SYSTEM_ONLY);
264d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  CompletionCallback callback = base::Bind(
265d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      &ProxyScriptDecider::OnIOCompletion,
266d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      base::Unretained(this));
267d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
268f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  next_state_ = STATE_QUICK_CHECK_COMPLETE;
269f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  quick_check_timer_.Start(FROM_HERE,
270f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                           base::TimeDelta::FromMilliseconds(
271f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                              kQuickCheckDelayMs),
272f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                           base::Bind(callback, ERR_NAME_NOT_RESOLVED));
273d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
274d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // We use HIGHEST here because proxy decision blocks doing any other requests.
275f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return host_resolver_->Resolve(reqinfo, HIGHEST, &wpad_addresses_,
276f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                 callback, net_log_);
277d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
278d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
279d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int ProxyScriptDecider::DoQuickCheckComplete(int result) {
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(quick_check_enabled_);
281d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  base::TimeDelta delta = base::Time::Now() - quick_check_start_time_;
282d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (result == OK)
283d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    UMA_HISTOGRAM_TIMES("Net.WpadQuickCheckSuccess", delta);
284d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  else
285d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    UMA_HISTOGRAM_TIMES("Net.WpadQuickCheckFailure", delta);
286d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  host_resolver_->Cancel();
287d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  quick_check_timer_.Stop();
288f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (result != OK)
289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return TryToFallbackPacSource(result);
290f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  next_state_ = GetStartState();
291d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return result;
292d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
293d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ProxyScriptDecider::DoFetchPacScript() {
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(fetch_pac_bytes_);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_FETCH_PAC_SCRIPT_COMPLETE;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const PacSource& pac_source = current_pac_source();
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL effective_pac_url;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DetermineURL(pac_source, &effective_pac_url);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.BeginEvent(NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT,
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      base::Bind(&PacSource::NetLogCallback,
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 base::Unretained(&pac_source),
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 &effective_pac_url));
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pac_source.type == PacSource::WPAD_DHCP) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!dhcp_proxy_script_fetcher_) {
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_.AddEvent(NetLog::TYPE_PROXY_SCRIPT_DECIDER_HAS_NO_FETCHER);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_UNEXPECTED;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return dhcp_proxy_script_fetcher_->Fetch(
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &pac_script_, base::Bind(&ProxyScriptDecider::OnIOCompletion,
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 base::Unretained(this)));
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!proxy_script_fetcher_) {
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.AddEvent(NetLog::TYPE_PROXY_SCRIPT_DECIDER_HAS_NO_FETCHER);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return proxy_script_fetcher_->Fetch(
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      effective_pac_url, &pac_script_,
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&ProxyScriptDecider::OnIOCompletion, base::Unretained(this)));
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ProxyScriptDecider::DoFetchPacScriptComplete(int result) {
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(fetch_pac_bytes_);
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.EndEventWithNetErrorCode(
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT, result);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != OK)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TryToFallbackPacSource(result);
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_VERIFY_PAC_SCRIPT;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ProxyScriptDecider::DoVerifyPacScript() {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_VERIFY_PAC_SCRIPT_COMPLETE;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is just a heuristic. Ideally we would try to parse the script.
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (fetch_pac_bytes_ && !LooksLikePacScript(pac_script_))
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_PAC_SCRIPT_FAILED;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ProxyScriptDecider::DoVerifyPacScriptComplete(int result) {
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != OK)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TryToFallbackPacSource(result);
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const PacSource& pac_source = current_pac_source();
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Extract the current script data.
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (fetch_pac_bytes_) {
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    script_data_ = ProxyResolverScriptData::FromUTF16(pac_script_);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    script_data_ = pac_source.type == PacSource::CUSTOM ?
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ProxyResolverScriptData::FromURL(pac_source.url) :
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ProxyResolverScriptData::ForAutoDetect();
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Let the caller know which automatic setting we ended up initializing the
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // resolver for (there may have been multiple fallbacks to choose from.)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (current_pac_source().type == PacSource::CUSTOM) {
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    effective_config_ =
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ProxyConfig::CreateFromCustomPacURL(current_pac_source().url);
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    effective_config_.set_pac_mandatory(pac_mandatory_);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fetch_pac_bytes_) {
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GURL auto_detected_url;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (current_pac_source().type) {
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case PacSource::WPAD_DHCP:
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          auto_detected_url = dhcp_proxy_script_fetcher_->GetPacURL();
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case PacSource::WPAD_DNS:
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          auto_detected_url = GURL(kWpadUrl);
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        default:
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NOTREACHED();
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      effective_config_ =
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ProxyConfig::CreateFromCustomPacURL(auto_detected_url);
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The resolver does its own resolution so we cannot know the
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // URL. Just do the best we can and state that the configuration
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // is to auto-detect proxy settings.
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      effective_config_ = ProxyConfig::CreateAutoDetect();
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ProxyScriptDecider::TryToFallbackPacSource(int error) {
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LT(error, 0);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (current_pac_source_index_ + 1 >= pac_sources_.size()) {
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Nothing left to fall back to.
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return error;
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Advance to next URL in our list.
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++current_pac_source_index_;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.AddEvent(
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NetLog::TYPE_PROXY_SCRIPT_DECIDER_FALLING_BACK_TO_NEXT_PAC_SOURCE);
4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (quick_check_enabled_ && current_pac_source().type == PacSource::WPAD_DNS)
417f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    next_state_ = STATE_QUICK_CHECK;
418f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  else
419f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    next_state_ = GetStartState();
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyScriptDecider::State ProxyScriptDecider::GetStartState() const {
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return fetch_pac_bytes_ ?  STATE_FETCH_PAC_SCRIPT : STATE_VERIFY_PAC_SCRIPT;
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyScriptDecider::DetermineURL(const PacSource& pac_source,
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      GURL* effective_pac_url) {
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(effective_pac_url);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (pac_source.type) {
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PacSource::WPAD_DHCP:
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PacSource::WPAD_DNS:
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *effective_pac_url = GURL(kWpadUrl);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PacSource::CUSTOM:
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *effective_pac_url = pac_source.url;
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ProxyScriptDecider::PacSource&
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProxyScriptDecider::current_pac_source() const {
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LT(current_pac_source_index_, pac_sources_.size());
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return pac_sources_[current_pac_source_index_];
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyScriptDecider::OnWaitTimerFired() {
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnIOCompletion(OK);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyScriptDecider::DidComplete() {
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.EndEvent(NetLog::TYPE_PROXY_SCRIPT_DECIDER);
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyScriptDecider::Cancel() {
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(STATE_NONE, next_state_);
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.AddEvent(NetLog::TYPE_CANCELLED);
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (next_state_) {
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case STATE_WAIT_COMPLETE:
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wait_timer_.Stop();
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case STATE_FETCH_PAC_SCRIPT_COMPLETE:
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      proxy_script_fetcher_->Cancel();
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is safe to call in any state.
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dhcp_proxy_script_fetcher_)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dhcp_proxy_script_fetcher_->Cancel();
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DidComplete();
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
483