Index: net/proxy/proxy_script_decider.cc |
diff --git a/net/proxy/proxy_script_decider.cc b/net/proxy/proxy_script_decider.cc |
index 38bf751cd4da3e3c89ccdacbe079854911e1c058..f6316a02159a17473e2d7b2c8dc62d6cd3fe85b5 100644 |
--- a/net/proxy/proxy_script_decider.cc |
+++ b/net/proxy/proxy_script_decider.cc |
@@ -9,6 +9,7 @@ |
#include "base/compiler_specific.h" |
#include "base/format_macros.h" |
#include "base/logging.h" |
+#include "base/metrics/histogram.h" |
#include "base/strings/string_util.h" |
#include "base/strings/utf_string_conversions.h" |
#include "base/values.h" |
@@ -16,6 +17,7 @@ |
#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 { |
@@ -45,7 +47,10 @@ bool LooksLikePacScript(const base::string16& script) { |
// |
// For more details, also check out this comment: |
// http://code.google.com/p/chromium/issues/detail?id=18575#c20 |
-static const char kWpadUrl[] = "http://wpad/wpad.dat"; |
+namespace { |
+const char kWpadUrl[] = "http://wpad/wpad.dat"; |
+const int kQuickCheckDelayMs = 1000; |
+}; |
base::Value* ProxyScriptDecider::PacSource::NetLogCallback( |
const GURL* effective_pac_url, |
@@ -82,6 +87,12 @@ ProxyScriptDecider::ProxyScriptDecider( |
net_log_(BoundNetLog::Make( |
net_log, NetLog::SOURCE_PROXY_SCRIPT_DECIDER)), |
fetch_pac_bytes_(false) { |
+ 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() { |
@@ -106,6 +117,7 @@ int ProxyScriptDecider::Start( |
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()); |
@@ -172,6 +184,13 @@ int ProxyScriptDecider::DoLoop(int result) { |
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(); |
@@ -221,10 +240,64 @@ int ProxyScriptDecider::DoWaitComplete(int result) { |
net_log_.EndEventWithNetErrorCode(NetLog::TYPE_PROXY_SCRIPT_DECIDER_WAIT, |
result); |
} |
- next_state_ = GetStartState(); |
+ next_state_ = STATE_QUICK_CHECK; |
return OK; |
} |
+int ProxyScriptDecider::DoQuickCheck() { |
+ if (host_resolver_.get() == NULL) { |
+ // If we have no resolver, skip QuickCheck altogether. |
+ next_state_ = GetStartState(); |
+ return OK; |
+ } |
+ |
+ if (have_custom_pac_url_) { |
+ // If there's a custom URL, skip QuickCheck. |
+ next_state_ = GetStartState(); |
+ return OK; |
+ } |
+ |
+ quick_check_start_time_ = base::Time::Now(); |
+ HostResolver::RequestInfo reqinfo(HostPortPair("wpad", 80)); |
+ reqinfo.set_host_resolver_flags(HOST_RESOLVER_SYSTEM_ONLY); |
+ CompletionCallback callback = base::Bind( |
+ &ProxyScriptDecider::OnIOCompletion, |
+ base::Unretained(this)); |
+ |
+ |
+ // We use HIGHEST here because proxy decision blocks doing any other requests. |
+ int rv = host_resolver_->Resolve(reqinfo, HIGHEST, &wpad_addresses_, |
+ callback, net_log_); |
+ |
+ // We can't get an error response - the name is known to be valid, and we |
+ // don't cache negative dns responses. |
+ DCHECK(rv == OK || rv == ERR_IO_PENDING); |
+ |
+ if (rv == OK) { |
+ next_state_ = GetStartState(); |
+ } else { |
+ quick_check_timer_.Start(FROM_HERE, |
+ base::TimeDelta::FromMilliseconds( |
+ kQuickCheckDelayMs), |
+ base::Bind(callback, ERR_NAME_NOT_RESOLVED)); |
+ next_state_ = STATE_QUICK_CHECK_COMPLETE; |
+ } |
+ return rv; |
+} |
+ |
+int ProxyScriptDecider::DoQuickCheckComplete(int result) { |
+ 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) |
+ next_state_ = GetStartState(); |
+ return result; |
+} |
+ |
int ProxyScriptDecider::DoFetchPacScript() { |
DCHECK(fetch_pac_bytes_); |