Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |