Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1049)

Side by Side Diff: net/proxy/proxy_script_decider.cc

Issue 23181010: Fast-fail WPAD detection. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Move STATE_QUICK_CHECK after STATE_WAIT Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/proxy/proxy_script_decider.h" 5 #include "net/proxy/proxy_script_decider.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/compiler_specific.h" 9 #include "base/compiler_specific.h"
10 #include "base/format_macros.h" 10 #include "base/format_macros.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/metrics/histogram.h"
12 #include "base/strings/string_util.h" 13 #include "base/strings/string_util.h"
13 #include "base/strings/utf_string_conversions.h" 14 #include "base/strings/utf_string_conversions.h"
14 #include "base/values.h" 15 #include "base/values.h"
15 #include "net/base/net_errors.h" 16 #include "net/base/net_errors.h"
16 #include "net/proxy/dhcp_proxy_script_fetcher.h" 17 #include "net/proxy/dhcp_proxy_script_fetcher.h"
17 #include "net/proxy/dhcp_proxy_script_fetcher_factory.h" 18 #include "net/proxy/dhcp_proxy_script_fetcher_factory.h"
18 #include "net/proxy/proxy_script_fetcher.h" 19 #include "net/proxy/proxy_script_fetcher.h"
20 #include "net/url_request/url_request_context.h"
19 21
20 namespace net { 22 namespace net {
21 23
22 namespace { 24 namespace {
23 25
24 bool LooksLikePacScript(const base::string16& script) { 26 bool LooksLikePacScript(const base::string16& script) {
25 // Note: this is only an approximation! It may not always work correctly, 27 // Note: this is only an approximation! It may not always work correctly,
26 // however it is very likely that legitimate scripts have this exact string, 28 // however it is very likely that legitimate scripts have this exact string,
27 // since they must minimally define a function of this name. Conversely, a 29 // since they must minimally define a function of this name. Conversely, a
28 // file not containing the string is not likely to be a PAC script. 30 // file not containing the string is not likely to be a PAC script.
(...skipping 11 matching lines...) Expand all
40 // be dangerous should our top level domain registry become out of date. 42 // be dangerous should our top level domain registry become out of date.
41 // 43 //
42 // Instead we directly resolve "wpad", and let the operating system apply the 44 // Instead we directly resolve "wpad", and let the operating system apply the
43 // DNS suffix search paths. This is the same approach taken by Firefox, and 45 // DNS suffix search paths. This is the same approach taken by Firefox, and
44 // compatibility hasn't been an issue. 46 // compatibility hasn't been an issue.
45 // 47 //
46 // For more details, also check out this comment: 48 // For more details, also check out this comment:
47 // http://code.google.com/p/chromium/issues/detail?id=18575#c20 49 // http://code.google.com/p/chromium/issues/detail?id=18575#c20
48 static const char kWpadUrl[] = "http://wpad/wpad.dat"; 50 static const char kWpadUrl[] = "http://wpad/wpad.dat";
49 51
52 static const int kQuickCheckDelayMs = 1000;
53
50 base::Value* ProxyScriptDecider::PacSource::NetLogCallback( 54 base::Value* ProxyScriptDecider::PacSource::NetLogCallback(
51 const GURL* effective_pac_url, 55 const GURL* effective_pac_url,
52 NetLog::LogLevel /* log_level */) const { 56 NetLog::LogLevel /* log_level */) const {
53 base::DictionaryValue* dict = new base::DictionaryValue(); 57 base::DictionaryValue* dict = new base::DictionaryValue();
54 std::string source; 58 std::string source;
55 switch (type) { 59 switch (type) {
56 case PacSource::WPAD_DHCP: 60 case PacSource::WPAD_DHCP:
57 source = "WPAD DHCP"; 61 source = "WPAD DHCP";
58 break; 62 break;
59 case PacSource::WPAD_DNS: 63 case PacSource::WPAD_DNS:
(...skipping 14 matching lines...) Expand all
74 DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher, 78 DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher,
75 NetLog* net_log) 79 NetLog* net_log)
76 : resolver_(NULL), 80 : resolver_(NULL),
77 proxy_script_fetcher_(proxy_script_fetcher), 81 proxy_script_fetcher_(proxy_script_fetcher),
78 dhcp_proxy_script_fetcher_(dhcp_proxy_script_fetcher), 82 dhcp_proxy_script_fetcher_(dhcp_proxy_script_fetcher),
79 current_pac_source_index_(0u), 83 current_pac_source_index_(0u),
80 pac_mandatory_(false), 84 pac_mandatory_(false),
81 next_state_(STATE_NONE), 85 next_state_(STATE_NONE),
82 net_log_(BoundNetLog::Make( 86 net_log_(BoundNetLog::Make(
83 net_log, NetLog::SOURCE_PROXY_SCRIPT_DECIDER)), 87 net_log, NetLog::SOURCE_PROXY_SCRIPT_DECIDER)),
84 fetch_pac_bytes_(false) { 88 fetch_pac_bytes_(false),
89 host_resolver_(
90 proxy_script_fetcher->GetRequestContext()->host_resolver()) {
85 } 91 }
86 92
87 ProxyScriptDecider::~ProxyScriptDecider() { 93 ProxyScriptDecider::~ProxyScriptDecider() {
88 if (next_state_ != STATE_NONE) 94 if (next_state_ != STATE_NONE)
89 Cancel(); 95 Cancel();
90 } 96 }
91 97
92 int ProxyScriptDecider::Start( 98 int ProxyScriptDecider::Start(
93 const ProxyConfig& config, const base::TimeDelta wait_delay, 99 const ProxyConfig& config, const base::TimeDelta wait_delay,
94 bool fetch_pac_bytes, const CompletionCallback& callback) { 100 bool fetch_pac_bytes, const CompletionCallback& callback) {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 State state = next_state_; 171 State state = next_state_;
166 next_state_ = STATE_NONE; 172 next_state_ = STATE_NONE;
167 switch (state) { 173 switch (state) {
168 case STATE_WAIT: 174 case STATE_WAIT:
169 DCHECK_EQ(OK, rv); 175 DCHECK_EQ(OK, rv);
170 rv = DoWait(); 176 rv = DoWait();
171 break; 177 break;
172 case STATE_WAIT_COMPLETE: 178 case STATE_WAIT_COMPLETE:
173 rv = DoWaitComplete(rv); 179 rv = DoWaitComplete(rv);
174 break; 180 break;
181 case STATE_QUICK_CHECK:
182 DCHECK_EQ(OK, rv);
183 rv = DoQuickCheck();
184 break;
185 case STATE_QUICK_CHECK_COMPLETE:
186 rv = DoQuickCheckComplete(rv);
187 break;
175 case STATE_FETCH_PAC_SCRIPT: 188 case STATE_FETCH_PAC_SCRIPT:
176 DCHECK_EQ(OK, rv); 189 DCHECK_EQ(OK, rv);
177 rv = DoFetchPacScript(); 190 rv = DoFetchPacScript();
178 break; 191 break;
179 case STATE_FETCH_PAC_SCRIPT_COMPLETE: 192 case STATE_FETCH_PAC_SCRIPT_COMPLETE:
180 rv = DoFetchPacScriptComplete(rv); 193 rv = DoFetchPacScriptComplete(rv);
181 break; 194 break;
182 case STATE_VERIFY_PAC_SCRIPT: 195 case STATE_VERIFY_PAC_SCRIPT:
183 DCHECK_EQ(OK, rv); 196 DCHECK_EQ(OK, rv);
184 rv = DoVerifyPacScript(); 197 rv = DoVerifyPacScript();
185 break; 198 break;
186 case STATE_VERIFY_PAC_SCRIPT_COMPLETE: 199 case STATE_VERIFY_PAC_SCRIPT_COMPLETE:
187 rv = DoVerifyPacScriptComplete(rv); 200 rv = DoVerifyPacScriptComplete(rv);
188 break; 201 break;
189 default: 202 default:
190 NOTREACHED() << "bad state"; 203 NOTREACHED() << "bad state";
191 rv = ERR_UNEXPECTED; 204 rv = ERR_UNEXPECTED;
192 break; 205 break;
193 } 206 }
194 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); 207 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
195 return rv; 208 return rv;
196 } 209 }
197 210
198 void ProxyScriptDecider::DoCallback(int result) { 211 void ProxyScriptDecider::DoCallback(int result) {
199 DCHECK_NE(ERR_IO_PENDING, result); 212 DCHECK_NE(ERR_IO_PENDING, result);
200 DCHECK(!callback_.is_null()); 213 DCHECK(!callback_.is_null());
201 callback_.Run(result); 214 callback_.Run(result);
202 } 215 }
203 216
217 int ProxyScriptDecider::DoQuickCheck() {
szym 2013/08/23 20:45:57 nit: Move both after DoWait() (to match my nit reg
Elly Fong-Jones 2013/08/26 15:17:29 Done.
218 quick_check_started_ = base::Time::Now();
219 HostResolver::RequestInfo reqinfo(HostPortPair("wpad", 80));
220 CompletionCallback callback = base::Bind(
221 &ProxyScriptDecider::OnIOCompletion,
222 base::Unretained(this));
223
224 int rv = host_resolver_.Resolve(reqinfo, HIGHEST, // we block startup...
szym 2013/08/23 20:45:57 nit: suggest putting this comment above this line.
Elly Fong-Jones 2013/08/26 15:17:29 Done.
225 &wpad_addrs_, callback, net_log_);
226
227 // we can't get an error response - the name is known to be valid, and we
228 // don't cache negative dns responses.
229 CHECK(rv == OK || rv == ERR_IO_PENDING);
230
231 if (rv == OK) {
232 // already in cache or something and valid, we're golden
233 next_state_ = STATE_FETCH_PAC_SCRIPT;
szym 2013/08/23 20:45:57 Perhaps this should be GetStartState()... ... but
234 return OK;
235 }
236
237 quick_check_timer_.Start(FROM_HERE,
238 base::TimeDelta::FromMilliseconds(
239 kQuickCheckDelayMs),
240 base::Bind(callback, ERR_NAME_NOT_RESOLVED));
241
242 next_state_ = STATE_QUICK_CHECK_COMPLETE;
243 return ERR_IO_PENDING;
244 }
245
246 int ProxyScriptDecider::DoQuickCheckComplete(int result) {
247 base::TimeDelta delta = base::Time::Now()
248 - quick_check_started_;
249 UMA_HISTOGRAM_TIMES("Net.WpadQuickCheck", delta);
250 host_resolver_.Cancel();
251 quick_check_timer_.Stop();
252 next_state_ = result == OK ? GetStartState() : STATE_NONE;
253 return result;
254 }
255
204 int ProxyScriptDecider::DoWait() { 256 int ProxyScriptDecider::DoWait() {
205 next_state_ = STATE_WAIT_COMPLETE; 257 next_state_ = STATE_WAIT_COMPLETE;
206 258
207 // If no waiting is required, continue on to the next state. 259 // If no waiting is required, continue on to the next state.
208 if (wait_delay_.ToInternalValue() == 0) 260 if (wait_delay_.ToInternalValue() == 0)
209 return OK; 261 return OK;
210 262
211 // Otherwise wait the specified amount of time. 263 // Otherwise wait the specified amount of time.
212 wait_timer_.Start(FROM_HERE, wait_delay_, this, 264 wait_timer_.Start(FROM_HERE, wait_delay_, this,
213 &ProxyScriptDecider::OnWaitTimerFired); 265 &ProxyScriptDecider::OnWaitTimerFired);
214 net_log_.BeginEvent(NetLog::TYPE_PROXY_SCRIPT_DECIDER_WAIT); 266 net_log_.BeginEvent(NetLog::TYPE_PROXY_SCRIPT_DECIDER_WAIT);
215 return ERR_IO_PENDING; 267 return ERR_IO_PENDING;
216 } 268 }
217 269
218 int ProxyScriptDecider::DoWaitComplete(int result) { 270 int ProxyScriptDecider::DoWaitComplete(int result) {
219 DCHECK_EQ(OK, result); 271 DCHECK_EQ(OK, result);
220 if (wait_delay_.ToInternalValue() != 0) { 272 if (wait_delay_.ToInternalValue() != 0) {
221 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_PROXY_SCRIPT_DECIDER_WAIT, 273 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_PROXY_SCRIPT_DECIDER_WAIT,
222 result); 274 result);
223 } 275 }
224 next_state_ = GetStartState(); 276 next_state_ = STATE_QUICK_CHECK;
225 return OK; 277 return OK;
226 } 278 }
227 279
228 int ProxyScriptDecider::DoFetchPacScript() { 280 int ProxyScriptDecider::DoFetchPacScript() {
229 DCHECK(fetch_pac_bytes_); 281 DCHECK(fetch_pac_bytes_);
230 282
231 next_state_ = STATE_FETCH_PAC_SCRIPT_COMPLETE; 283 next_state_ = STATE_FETCH_PAC_SCRIPT_COMPLETE;
232 284
233 const PacSource& pac_source = current_pac_source(); 285 const PacSource& pac_source = current_pac_source();
234 286
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 444
393 net_log_.AddEvent(NetLog::TYPE_CANCELLED); 445 net_log_.AddEvent(NetLog::TYPE_CANCELLED);
394 446
395 switch (next_state_) { 447 switch (next_state_) {
396 case STATE_WAIT_COMPLETE: 448 case STATE_WAIT_COMPLETE:
397 wait_timer_.Stop(); 449 wait_timer_.Stop();
398 break; 450 break;
399 case STATE_FETCH_PAC_SCRIPT_COMPLETE: 451 case STATE_FETCH_PAC_SCRIPT_COMPLETE:
400 proxy_script_fetcher_->Cancel(); 452 proxy_script_fetcher_->Cancel();
401 break; 453 break;
454 case STATE_FAILED:
455 break;
402 default: 456 default:
403 NOTREACHED(); 457 NOTREACHED();
404 break; 458 break;
405 } 459 }
406 460
407 // This is safe to call in any state. 461 // This is safe to call in any state.
408 if (dhcp_proxy_script_fetcher_) 462 if (dhcp_proxy_script_fetcher_)
409 dhcp_proxy_script_fetcher_->Cancel(); 463 dhcp_proxy_script_fetcher_->Cancel();
410 464
411 DidComplete(); 465 DidComplete();
412 } 466 }
413 467
414 } // namespace net 468 } // namespace net
OLDNEW
« net/proxy/proxy_script_decider.h ('K') | « net/proxy/proxy_script_decider.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698