// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/proxy/proxy_script_decider.h"

#include <utility>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/compiler_specific.h"
#include "base/format_macros.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "net/base/net_errors.h"
#include "net/proxy/dhcp_proxy_script_fetcher.h"
#include "net/proxy/dhcp_proxy_script_fetcher_factory.h"
#include "net/proxy/proxy_script_fetcher.h"
#include "net/url_request/url_request_context.h"

namespace net {

namespace {

bool LooksLikePacScript(const base::string16& script) {
  // Note: this is only an approximation! It may not always work correctly,
  // however it is very likely that legitimate scripts have this exact string,
  // since they must minimally define a function of this name. Conversely, a
  // file not containing the string is not likely to be a PAC script.
  //
  // An exact test would have to load the script in a javascript evaluator.
  return script.find(base::ASCIIToUTF16("FindProxyForURL")) !=
             base::string16::npos;
}

}

// This is the hard-coded location used by the DNS portion of web proxy
// auto-discovery.
//
// Note that we not use DNS devolution to find the WPAD host, since that could
// be dangerous should our top level domain registry  become out of date.
//
// Instead we directly resolve "wpad", and let the operating system apply the
// DNS suffix search paths. This is the same approach taken by Firefox, and
// compatibility hasn't been an issue.
//
// For more details, also check out this comment:
// http://code.google.com/p/chromium/issues/detail?id=18575#c20
namespace {
const char kWpadUrl[] = "http://wpad/wpad.dat";
const int kQuickCheckDelayMs = 1000;
};

scoped_ptr<base::Value> ProxyScriptDecider::PacSource::NetLogCallback(
    const GURL* effective_pac_url,
    NetLogCaptureMode /* capture_mode */) const {
  scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
  std::string source;
  switch (type) {
    case PacSource::WPAD_DHCP:
      source = "WPAD DHCP";
      break;
    case PacSource::WPAD_DNS:
      source = "WPAD DNS: ";
      source += effective_pac_url->possibly_invalid_spec();
      break;
    case PacSource::CUSTOM:
      source = "Custom PAC URL: ";
      source += effective_pac_url->possibly_invalid_spec();
      break;
  }
  dict->SetString("source", source);
  return std::move(dict);
}

ProxyScriptDecider::ProxyScriptDecider(
    ProxyScriptFetcher* proxy_script_fetcher,
    DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher,
    NetLog* net_log)
    : proxy_script_fetcher_(proxy_script_fetcher),
      dhcp_proxy_script_fetcher_(dhcp_proxy_script_fetcher),
      current_pac_source_index_(0u),
      pac_mandatory_(false),
      next_state_(STATE_NONE),
      net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_PROXY_SCRIPT_DECIDER)),
      fetch_pac_bytes_(false),
      quick_check_enabled_(true) {
  if (proxy_script_fetcher &&
      proxy_script_fetcher->GetRequestContext() &&
      proxy_script_fetcher->GetRequestContext()->host_resolver()) {
      host_resolver_.reset(new SingleRequestHostResolver(
          proxy_script_fetcher->GetRequestContext()->host_resolver()));
  }
}

ProxyScriptDecider::~ProxyScriptDecider() {
  if (next_state_ != STATE_NONE)
    Cancel();
}

int ProxyScriptDecider::Start(
    const ProxyConfig& config, const base::TimeDelta wait_delay,
    bool fetch_pac_bytes, const CompletionCallback& callback) {
  DCHECK_EQ(STATE_NONE, next_state_);
  DCHECK(!callback.is_null());
  DCHECK(config.HasAutomaticSettings());

  net_log_.BeginEvent(NetLog::TYPE_PROXY_SCRIPT_DECIDER);

  fetch_pac_bytes_ = fetch_pac_bytes;

  // Save the |wait_delay| as a non-negative value.
  wait_delay_ = wait_delay;
  if (wait_delay_ < base::TimeDelta())
    wait_delay_ = base::TimeDelta();

  pac_mandatory_ = config.pac_mandatory();
  have_custom_pac_url_ = config.has_pac_url();

  pac_sources_ = BuildPacSourcesFallbackList(config);
  DCHECK(!pac_sources_.empty());

  next_state_ = STATE_WAIT;

  int rv = DoLoop(OK);
  if (rv == ERR_IO_PENDING)
    callback_ = callback;
  else
    DidComplete();

  return rv;
}

const ProxyConfig& ProxyScriptDecider::effective_config() const {
  DCHECK_EQ(STATE_NONE, next_state_);
  return effective_config_;
}

const scoped_refptr<ProxyResolverScriptData>&
ProxyScriptDecider::script_data() const {
  DCHECK_EQ(STATE_NONE, next_state_);
  return script_data_;
}

// Initialize the fallback rules.
// (1) WPAD (DHCP).
// (2) WPAD (DNS).
// (3) Custom PAC URL.
ProxyScriptDecider::PacSourceList ProxyScriptDecider::
    BuildPacSourcesFallbackList(
    const ProxyConfig& config) const {
  PacSourceList pac_sources;
  if (config.auto_detect()) {
    pac_sources.push_back(PacSource(PacSource::WPAD_DHCP, GURL(kWpadUrl)));
    pac_sources.push_back(PacSource(PacSource::WPAD_DNS, GURL(kWpadUrl)));
  }
  if (config.has_pac_url())
    pac_sources.push_back(PacSource(PacSource::CUSTOM, config.pac_url()));
  return pac_sources;
}

void ProxyScriptDecider::OnIOCompletion(int result) {
  DCHECK_NE(STATE_NONE, next_state_);
  int rv = DoLoop(result);
  if (rv != ERR_IO_PENDING) {
    DidComplete();
    DoCallback(rv);
  }
}

int ProxyScriptDecider::DoLoop(int result) {
  DCHECK_NE(next_state_, STATE_NONE);
  int rv = result;
  do {
    State state = next_state_;
    next_state_ = STATE_NONE;
    switch (state) {
      case STATE_WAIT:
        DCHECK_EQ(OK, rv);
        rv = DoWait();
        break;
      case STATE_WAIT_COMPLETE:
        rv = DoWaitComplete(rv);
        break;
      case STATE_QUICK_CHECK:
        DCHECK_EQ(OK, rv);
        rv = DoQuickCheck();
        break;
      case STATE_QUICK_CHECK_COMPLETE:
        rv = DoQuickCheckComplete(rv);
        break;
      case STATE_FETCH_PAC_SCRIPT:
        DCHECK_EQ(OK, rv);
        rv = DoFetchPacScript();
        break;
      case STATE_FETCH_PAC_SCRIPT_COMPLETE:
        rv = DoFetchPacScriptComplete(rv);
        break;
      case STATE_VERIFY_PAC_SCRIPT:
        DCHECK_EQ(OK, rv);
        rv = DoVerifyPacScript();
        break;
      case STATE_VERIFY_PAC_SCRIPT_COMPLETE:
        rv = DoVerifyPacScriptComplete(rv);
        break;
      default:
        NOTREACHED() << "bad state";
        rv = ERR_UNEXPECTED;
        break;
    }
  } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
  return rv;
}

void ProxyScriptDecider::DoCallback(int result) {
  DCHECK_NE(ERR_IO_PENDING, result);
  DCHECK(!callback_.is_null());
  callback_.Run(result);
}

int ProxyScriptDecider::DoWait() {
  next_state_ = STATE_WAIT_COMPLETE;

  // If no waiting is required, continue on to the next state.
  if (wait_delay_.ToInternalValue() == 0)
    return OK;

  // Otherwise wait the specified amount of time.
  wait_timer_.Start(FROM_HERE, wait_delay_, this,
                    &ProxyScriptDecider::OnWaitTimerFired);
  net_log_.BeginEvent(NetLog::TYPE_PROXY_SCRIPT_DECIDER_WAIT);
  return ERR_IO_PENDING;
}

int ProxyScriptDecider::DoWaitComplete(int result) {
  DCHECK_EQ(OK, result);
  if (wait_delay_.ToInternalValue() != 0) {
    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_PROXY_SCRIPT_DECIDER_WAIT,
                                      result);
  }
  if (quick_check_enabled_ && current_pac_source().type == PacSource::WPAD_DNS)
    next_state_ = STATE_QUICK_CHECK;
  else
    next_state_ = GetStartState();
  return OK;
}

int ProxyScriptDecider::DoQuickCheck() {
  DCHECK(quick_check_enabled_);
  if (host_resolver_.get() == NULL) {
    // If we have no resolver, skip QuickCheck altogether.
    next_state_ = GetStartState();
    return OK;
  }

  quick_check_start_time_ = base::Time::Now();
  std::string host = current_pac_source().url.host();
  HostResolver::RequestInfo reqinfo(HostPortPair(host, 80));
  reqinfo.set_host_resolver_flags(HOST_RESOLVER_SYSTEM_ONLY);
  CompletionCallback callback = base::Bind(
      &ProxyScriptDecider::OnIOCompletion,
      base::Unretained(this));

  next_state_ = STATE_QUICK_CHECK_COMPLETE;
  quick_check_timer_.Start(FROM_HERE,
                           base::TimeDelta::FromMilliseconds(
                              kQuickCheckDelayMs),
                           base::Bind(callback, ERR_NAME_NOT_RESOLVED));

  // We use HIGHEST here because proxy decision blocks doing any other requests.
  return host_resolver_->Resolve(reqinfo, HIGHEST, &wpad_addresses_,
                                 callback, net_log_);
}

int ProxyScriptDecider::DoQuickCheckComplete(int result) {
  DCHECK(quick_check_enabled_);
  base::TimeDelta delta = base::Time::Now() - quick_check_start_time_;
  if (result == OK)
    UMA_HISTOGRAM_TIMES("Net.WpadQuickCheckSuccess", delta);
  else
    UMA_HISTOGRAM_TIMES("Net.WpadQuickCheckFailure", delta);
  host_resolver_->Cancel();
  quick_check_timer_.Stop();
  if (result != OK)
    return TryToFallbackPacSource(result);
  next_state_ = GetStartState();
  return result;
}

int ProxyScriptDecider::DoFetchPacScript() {
  DCHECK(fetch_pac_bytes_);

  next_state_ = STATE_FETCH_PAC_SCRIPT_COMPLETE;

  const PacSource& pac_source = current_pac_source();

  GURL effective_pac_url;
  DetermineURL(pac_source, &effective_pac_url);

  net_log_.BeginEvent(NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT,
                      base::Bind(&PacSource::NetLogCallback,
                                 base::Unretained(&pac_source),
                                 &effective_pac_url));

  if (pac_source.type == PacSource::WPAD_DHCP) {
    if (!dhcp_proxy_script_fetcher_) {
      net_log_.AddEvent(NetLog::TYPE_PROXY_SCRIPT_DECIDER_HAS_NO_FETCHER);
      return ERR_UNEXPECTED;
    }

    return dhcp_proxy_script_fetcher_->Fetch(
        &pac_script_, base::Bind(&ProxyScriptDecider::OnIOCompletion,
                                 base::Unretained(this)));
  }

  if (!proxy_script_fetcher_) {
    net_log_.AddEvent(NetLog::TYPE_PROXY_SCRIPT_DECIDER_HAS_NO_FETCHER);
    return ERR_UNEXPECTED;
  }

  return proxy_script_fetcher_->Fetch(
      effective_pac_url, &pac_script_,
      base::Bind(&ProxyScriptDecider::OnIOCompletion, base::Unretained(this)));
}

int ProxyScriptDecider::DoFetchPacScriptComplete(int result) {
  DCHECK(fetch_pac_bytes_);

  net_log_.EndEventWithNetErrorCode(
      NetLog::TYPE_PROXY_SCRIPT_DECIDER_FETCH_PAC_SCRIPT, result);
  if (result != OK)
    return TryToFallbackPacSource(result);

  next_state_ = STATE_VERIFY_PAC_SCRIPT;
  return result;
}

int ProxyScriptDecider::DoVerifyPacScript() {
  next_state_ = STATE_VERIFY_PAC_SCRIPT_COMPLETE;

  // This is just a heuristic. Ideally we would try to parse the script.
  if (fetch_pac_bytes_ && !LooksLikePacScript(pac_script_))
    return ERR_PAC_SCRIPT_FAILED;

  return OK;
}

int ProxyScriptDecider::DoVerifyPacScriptComplete(int result) {
  if (result != OK)
    return TryToFallbackPacSource(result);

  const PacSource& pac_source = current_pac_source();

  // Extract the current script data.
  if (fetch_pac_bytes_) {
    script_data_ = ProxyResolverScriptData::FromUTF16(pac_script_);
  } else {
    script_data_ = pac_source.type == PacSource::CUSTOM ?
        ProxyResolverScriptData::FromURL(pac_source.url) :
        ProxyResolverScriptData::ForAutoDetect();
  }

  // Let the caller know which automatic setting we ended up initializing the
  // resolver for (there may have been multiple fallbacks to choose from.)
  if (current_pac_source().type == PacSource::CUSTOM) {
    effective_config_ =
        ProxyConfig::CreateFromCustomPacURL(current_pac_source().url);
    effective_config_.set_pac_mandatory(pac_mandatory_);
  } else {
    if (fetch_pac_bytes_) {
      GURL auto_detected_url;

      switch (current_pac_source().type) {
        case PacSource::WPAD_DHCP:
          auto_detected_url = dhcp_proxy_script_fetcher_->GetPacURL();
          break;

        case PacSource::WPAD_DNS:
          auto_detected_url = GURL(kWpadUrl);
          break;

        default:
          NOTREACHED();
      }

      effective_config_ =
          ProxyConfig::CreateFromCustomPacURL(auto_detected_url);
    } else {
      // The resolver does its own resolution so we cannot know the
      // URL. Just do the best we can and state that the configuration
      // is to auto-detect proxy settings.
      effective_config_ = ProxyConfig::CreateAutoDetect();
    }
  }

  return OK;
}

int ProxyScriptDecider::TryToFallbackPacSource(int error) {
  DCHECK_LT(error, 0);

  if (current_pac_source_index_ + 1 >= pac_sources_.size()) {
    // Nothing left to fall back to.
    return error;
  }

  // Advance to next URL in our list.
  ++current_pac_source_index_;

  net_log_.AddEvent(
      NetLog::TYPE_PROXY_SCRIPT_DECIDER_FALLING_BACK_TO_NEXT_PAC_SOURCE);
  if (quick_check_enabled_ && current_pac_source().type == PacSource::WPAD_DNS)
    next_state_ = STATE_QUICK_CHECK;
  else
    next_state_ = GetStartState();

  return OK;
}

ProxyScriptDecider::State ProxyScriptDecider::GetStartState() const {
  return fetch_pac_bytes_ ?  STATE_FETCH_PAC_SCRIPT : STATE_VERIFY_PAC_SCRIPT;
}

void ProxyScriptDecider::DetermineURL(const PacSource& pac_source,
                                      GURL* effective_pac_url) {
  DCHECK(effective_pac_url);

  switch (pac_source.type) {
    case PacSource::WPAD_DHCP:
      break;
    case PacSource::WPAD_DNS:
      *effective_pac_url = GURL(kWpadUrl);
      break;
    case PacSource::CUSTOM:
      *effective_pac_url = pac_source.url;
      break;
  }
}

const ProxyScriptDecider::PacSource&
    ProxyScriptDecider::current_pac_source() const {
  DCHECK_LT(current_pac_source_index_, pac_sources_.size());
  return pac_sources_[current_pac_source_index_];
}

void ProxyScriptDecider::OnWaitTimerFired() {
  OnIOCompletion(OK);
}

void ProxyScriptDecider::DidComplete() {
  net_log_.EndEvent(NetLog::TYPE_PROXY_SCRIPT_DECIDER);
}

void ProxyScriptDecider::Cancel() {
  DCHECK_NE(STATE_NONE, next_state_);

  net_log_.AddEvent(NetLog::TYPE_CANCELLED);

  switch (next_state_) {
    case STATE_WAIT_COMPLETE:
      wait_timer_.Stop();
      break;
    case STATE_FETCH_PAC_SCRIPT_COMPLETE:
      proxy_script_fetcher_->Cancel();
      break;
    default:
      break;
  }

  // This is safe to call in any state.
  if (dhcp_proxy_script_fetcher_)
    dhcp_proxy_script_fetcher_->Cancel();

  DidComplete();
}

}  // namespace net
