diff options
author | ericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-04 22:43:12 +0000 |
---|---|---|
committer | ericroman@google.com <ericroman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-04 22:43:12 +0000 |
commit | 620f57148c311c4dc2cf680a4a5861fbdcd29993 (patch) | |
tree | 93408ed35ebbaccd8f45734c7267392c81d71ca9 /net/proxy/init_proxy_resolver.cc | |
parent | 289fdf862c649d17ddb2e08295304efb98f641f6 (diff) | |
download | chromium_src-620f57148c311c4dc2cf680a4a5861fbdcd29993.zip chromium_src-620f57148c311c4dc2cf680a4a5861fbdcd29993.tar.gz chromium_src-620f57148c311c4dc2cf680a4a5861fbdcd29993.tar.bz2 |
Better match IE's proxy settings.
* When BOTH autodetect and custom PAC script are given, try both.
* Use successful PAC parsing as the heuristic for determining when a script is valid (rather than first-request).
* Only apply the proxy bypass list when using non-PAC.
The high level explanation on how this works:
http://sites.google.com/a/chromium.org/dev/developers/design-documents/proxy-settings-fallback
BUG= http://crbug.com/18271, http://crbug.com/9985
TEST=unit tests.
Review URL: http://codereview.chromium.org/160510
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@22430 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/proxy/init_proxy_resolver.cc')
-rw-r--r-- | net/proxy/init_proxy_resolver.cc | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/net/proxy/init_proxy_resolver.cc b/net/proxy/init_proxy_resolver.cc new file mode 100644 index 0000000..7b98c4a --- /dev/null +++ b/net/proxy/init_proxy_resolver.cc @@ -0,0 +1,189 @@ +// Copyright (c) 2009 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/init_proxy_resolver.h" + +#include "base/compiler_specific.h" +#include "base/logging.h" +#include "net/base/net_errors.h" +#include "net/proxy/proxy_config.h" +#include "net/proxy/proxy_resolver.h" +#include "net/proxy/proxy_script_fetcher.h" + +namespace net { + +InitProxyResolver::InitProxyResolver(ProxyResolver* resolver, + ProxyScriptFetcher* proxy_script_fetcher) + : resolver_(resolver), + proxy_script_fetcher_(proxy_script_fetcher), + ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_( + this, &InitProxyResolver::OnIOCompletion)), + user_callback_(NULL), + current_pac_url_index_(0u), + next_state_(STATE_NONE) { +} + +InitProxyResolver::~InitProxyResolver() { + switch (next_state_) { + case STATE_FETCH_PAC_SCRIPT_COMPLETE: + proxy_script_fetcher_->Cancel(); + break; + case STATE_SET_PAC_SCRIPT_COMPLETE: + resolver_->CancelSetPacScript(); + break; + default: + break; + } +} + +int InitProxyResolver::Init(const ProxyConfig& config, + CompletionCallback* callback) { + DCHECK_EQ(STATE_NONE, next_state_); + DCHECK(callback); + DCHECK(config.MayRequirePACResolver()); + + pac_urls_ = BuildPacUrlsFallbackList(config); + DCHECK(!pac_urls_.empty()); + + next_state_ = GetStartState(); + + int rv = DoLoop(OK); + if (rv == ERR_IO_PENDING) + user_callback_ = callback; + return rv; +} + +// Initialize the fallback rules. +// (1) WPAD +// (2) Custom PAC URL. +InitProxyResolver::UrlList InitProxyResolver::BuildPacUrlsFallbackList( + const ProxyConfig& config) const { + UrlList pac_urls; + if (config.auto_detect) { + GURL pac_url = resolver_->expects_pac_bytes() ? + GURL("http://wpad/wpad.dat") : GURL(); + pac_urls.push_back(pac_url); + } + if (config.pac_url.is_valid()) + pac_urls.push_back(config.pac_url); + return pac_urls; +} + +void InitProxyResolver::OnIOCompletion(int result) { + DCHECK_NE(STATE_NONE, next_state_); + int rv = DoLoop(result); + if (rv != ERR_IO_PENDING) + DoCallback(rv); +} + +int InitProxyResolver::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_FETCH_PAC_SCRIPT: + DCHECK_EQ(OK, rv); + rv = DoFetchPacScript(); + break; + case STATE_FETCH_PAC_SCRIPT_COMPLETE: + rv = DoFetchPacScriptComplete(rv); + break; + case STATE_SET_PAC_SCRIPT: + DCHECK_EQ(OK, rv); + rv = DoSetPacScript(); + break; + case STATE_SET_PAC_SCRIPT_COMPLETE: + rv = DoSetPacScriptComplete(rv); + break; + default: + NOTREACHED() << "bad state"; + rv = ERR_UNEXPECTED; + break; + } + } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); + return rv; +} + +void InitProxyResolver::DoCallback(int result) { + DCHECK_NE(ERR_IO_PENDING, result); + DCHECK(user_callback_); + user_callback_->Run(result); +} + +int InitProxyResolver::DoFetchPacScript() { + DCHECK(resolver_->expects_pac_bytes()); + + next_state_ = STATE_FETCH_PAC_SCRIPT_COMPLETE; + + const GURL& pac_url = current_pac_url(); + + LOG(INFO) << "Starting fetch of PAC script " << pac_url; + + return proxy_script_fetcher_->Fetch(pac_url, &pac_bytes_, &io_callback_); +} + +int InitProxyResolver::DoFetchPacScriptComplete(int result) { + DCHECK(resolver_->expects_pac_bytes()); + + LOG(INFO) << "Completed PAC script fetch of " << current_pac_url() + << " with result " << ErrorToString(result) + << ". Fetched a total of " << pac_bytes_.size() << " bytes"; + + if (result != OK) + return TryToFallbackPacUrl(result); + + next_state_ = STATE_SET_PAC_SCRIPT; + return result; +} + +int InitProxyResolver::DoSetPacScript() { + const GURL& pac_url = current_pac_url(); + + next_state_ = STATE_SET_PAC_SCRIPT_COMPLETE; + + return resolver_->expects_pac_bytes() ? + resolver_->SetPacScriptByData(pac_bytes_, &io_callback_) : + resolver_->SetPacScriptByUrl(pac_url, &io_callback_); +} + +int InitProxyResolver::DoSetPacScriptComplete(int result) { + if (result != OK) { + LOG(INFO) << "Failed configuring PAC using " << current_pac_url() + << " with error " << ErrorToString(result); + return TryToFallbackPacUrl(result); + } + return result; +} + +int InitProxyResolver::TryToFallbackPacUrl(int error) { + DCHECK_LT(error, 0); + + if (current_pac_url_index_ + 1 >= pac_urls_.size()) { + // Nothing left to fall back to. + return error; + } + + // Advance to next URL in our list. + ++current_pac_url_index_; + + LOG(INFO) << "Falling back to next PAC URL..."; + + next_state_ = GetStartState(); + + return OK; +} + +InitProxyResolver::State InitProxyResolver::GetStartState() const { + return resolver_->expects_pac_bytes() ? + STATE_FETCH_PAC_SCRIPT : STATE_SET_PAC_SCRIPT; +} + +const GURL& InitProxyResolver::current_pac_url() const { + DCHECK_LT(current_pac_url_index_, pac_urls_.size()); + return pac_urls_[current_pac_url_index_]; +} + +} // namespace net |