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" |
19 | 20 |
20 namespace net { | 21 namespace net { |
21 | 22 |
(...skipping 18 matching lines...) Expand all Loading... | |
40 // be dangerous should our top level domain registry become out of date. | 41 // be dangerous should our top level domain registry become out of date. |
41 // | 42 // |
42 // Instead we directly resolve "wpad", and let the operating system apply the | 43 // 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 | 44 // DNS suffix search paths. This is the same approach taken by Firefox, and |
44 // compatibility hasn't been an issue. | 45 // compatibility hasn't been an issue. |
45 // | 46 // |
46 // For more details, also check out this comment: | 47 // For more details, also check out this comment: |
47 // http://code.google.com/p/chromium/issues/detail?id=18575#c20 | 48 // http://code.google.com/p/chromium/issues/detail?id=18575#c20 |
48 static const char kWpadUrl[] = "http://wpad/wpad.dat"; | 49 static const char kWpadUrl[] = "http://wpad/wpad.dat"; |
49 | 50 |
51 static const int kQuickCheckDelayMs = 1000; | |
52 | |
50 base::Value* ProxyScriptDecider::PacSource::NetLogCallback( | 53 base::Value* ProxyScriptDecider::PacSource::NetLogCallback( |
51 const GURL* effective_pac_url, | 54 const GURL* effective_pac_url, |
52 NetLog::LogLevel /* log_level */) const { | 55 NetLog::LogLevel /* log_level */) const { |
53 base::DictionaryValue* dict = new base::DictionaryValue(); | 56 base::DictionaryValue* dict = new base::DictionaryValue(); |
54 std::string source; | 57 std::string source; |
55 switch (type) { | 58 switch (type) { |
56 case PacSource::WPAD_DHCP: | 59 case PacSource::WPAD_DHCP: |
57 source = "WPAD DHCP"; | 60 source = "WPAD DHCP"; |
58 break; | 61 break; |
59 case PacSource::WPAD_DNS: | 62 case PacSource::WPAD_DNS: |
(...skipping 14 matching lines...) Expand all Loading... | |
74 DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher, | 77 DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher, |
75 NetLog* net_log) | 78 NetLog* net_log) |
76 : resolver_(NULL), | 79 : resolver_(NULL), |
77 proxy_script_fetcher_(proxy_script_fetcher), | 80 proxy_script_fetcher_(proxy_script_fetcher), |
78 dhcp_proxy_script_fetcher_(dhcp_proxy_script_fetcher), | 81 dhcp_proxy_script_fetcher_(dhcp_proxy_script_fetcher), |
79 current_pac_source_index_(0u), | 82 current_pac_source_index_(0u), |
80 pac_mandatory_(false), | 83 pac_mandatory_(false), |
81 next_state_(STATE_NONE), | 84 next_state_(STATE_NONE), |
82 net_log_(BoundNetLog::Make( | 85 net_log_(BoundNetLog::Make( |
83 net_log, NetLog::SOURCE_PROXY_SCRIPT_DECIDER)), | 86 net_log, NetLog::SOURCE_PROXY_SCRIPT_DECIDER)), |
84 fetch_pac_bytes_(false) { | 87 fetch_pac_bytes_(false), |
88 underlying_host_resolver_( | |
89 HostResolver::CreateDefaultResolver(net_log)), | |
90 host_resolver_(underlying_host_resolver_.get()) { | |
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) { |
95 DCHECK_EQ(STATE_NONE, next_state_); | 101 DCHECK_EQ(STATE_NONE, next_state_); |
96 DCHECK(!callback.is_null()); | 102 DCHECK(!callback.is_null()); |
97 DCHECK(config.HasAutomaticSettings()); | 103 DCHECK(config.HasAutomaticSettings()); |
98 | 104 |
99 net_log_.BeginEvent(NetLog::TYPE_PROXY_SCRIPT_DECIDER); | 105 net_log_.BeginEvent(NetLog::TYPE_PROXY_SCRIPT_DECIDER); |
100 | 106 |
101 fetch_pac_bytes_ = fetch_pac_bytes; | 107 fetch_pac_bytes_ = fetch_pac_bytes; |
102 | 108 |
103 // Save the |wait_delay| as a non-negative value. | 109 // Save the |wait_delay| as a non-negative value. |
104 wait_delay_ = wait_delay; | 110 wait_delay_ = wait_delay; |
105 if (wait_delay_ < base::TimeDelta()) | 111 if (wait_delay_ < base::TimeDelta()) |
106 wait_delay_ = base::TimeDelta(); | 112 wait_delay_ = base::TimeDelta(); |
107 | 113 |
108 pac_mandatory_ = config.pac_mandatory(); | 114 pac_mandatory_ = config.pac_mandatory(); |
109 | 115 |
110 pac_sources_ = BuildPacSourcesFallbackList(config); | 116 pac_sources_ = BuildPacSourcesFallbackList(config); |
111 DCHECK(!pac_sources_.empty()); | 117 DCHECK(!pac_sources_.empty()); |
112 | 118 |
113 next_state_ = STATE_WAIT; | 119 next_state_ = STATE_QUICK_CHECK; |
114 | 120 |
115 int rv = DoLoop(OK); | 121 int rv = DoLoop(OK); |
116 if (rv == ERR_IO_PENDING) | 122 if (rv == ERR_IO_PENDING) |
117 callback_ = callback; | 123 callback_ = callback; |
118 else | 124 else |
119 DidComplete(); | 125 DidComplete(); |
120 | 126 |
121 return rv; | 127 return rv; |
122 } | 128 } |
123 | 129 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
158 } | 164 } |
159 } | 165 } |
160 | 166 |
161 int ProxyScriptDecider::DoLoop(int result) { | 167 int ProxyScriptDecider::DoLoop(int result) { |
162 DCHECK_NE(next_state_, STATE_NONE); | 168 DCHECK_NE(next_state_, STATE_NONE); |
163 int rv = result; | 169 int rv = result; |
164 do { | 170 do { |
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) { |
174 case STATE_QUICK_CHECK: | |
175 rv = DoQuickCheck(); | |
176 break; | |
szym
2013/08/22 19:06:41
To be compatible with the DoLoop state machine you
| |
168 case STATE_WAIT: | 177 case STATE_WAIT: |
169 DCHECK_EQ(OK, rv); | 178 DCHECK_EQ(OK, rv); |
170 rv = DoWait(); | 179 rv = DoWait(); |
171 break; | 180 break; |
172 case STATE_WAIT_COMPLETE: | 181 case STATE_WAIT_COMPLETE: |
173 rv = DoWaitComplete(rv); | 182 rv = DoWaitComplete(rv); |
174 break; | 183 break; |
175 case STATE_FETCH_PAC_SCRIPT: | 184 case STATE_FETCH_PAC_SCRIPT: |
176 DCHECK_EQ(OK, rv); | 185 DCHECK_EQ(OK, rv); |
177 rv = DoFetchPacScript(); | 186 rv = DoFetchPacScript(); |
178 break; | 187 break; |
179 case STATE_FETCH_PAC_SCRIPT_COMPLETE: | 188 case STATE_FETCH_PAC_SCRIPT_COMPLETE: |
180 rv = DoFetchPacScriptComplete(rv); | 189 rv = DoFetchPacScriptComplete(rv); |
181 break; | 190 break; |
182 case STATE_VERIFY_PAC_SCRIPT: | 191 case STATE_VERIFY_PAC_SCRIPT: |
183 DCHECK_EQ(OK, rv); | 192 DCHECK_EQ(OK, rv); |
184 rv = DoVerifyPacScript(); | 193 rv = DoVerifyPacScript(); |
185 break; | 194 break; |
186 case STATE_VERIFY_PAC_SCRIPT_COMPLETE: | 195 case STATE_VERIFY_PAC_SCRIPT_COMPLETE: |
187 rv = DoVerifyPacScriptComplete(rv); | 196 rv = DoVerifyPacScriptComplete(rv); |
188 break; | 197 break; |
198 case STATE_FAILED: | |
199 break; | |
189 default: | 200 default: |
190 NOTREACHED() << "bad state"; | 201 NOTREACHED() << "bad state"; |
191 rv = ERR_UNEXPECTED; | 202 rv = ERR_UNEXPECTED; |
192 break; | 203 break; |
193 } | 204 } |
194 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); | 205 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); |
195 return rv; | 206 return rv; |
196 } | 207 } |
197 | 208 |
198 void ProxyScriptDecider::DoCallback(int result) { | 209 void ProxyScriptDecider::DoCallback(int result) { |
199 DCHECK_NE(ERR_IO_PENDING, result); | 210 DCHECK_NE(ERR_IO_PENDING, result); |
200 DCHECK(!callback_.is_null()); | 211 DCHECK(!callback_.is_null()); |
201 callback_.Run(result); | 212 callback_.Run(result); |
202 } | 213 } |
203 | 214 |
215 int ProxyScriptDecider::DoQuickCheck() { | |
216 | |
217 HostResolver::RequestInfo reqinfo(HostPortPair("wpad", 80)); | |
218 | |
szym
2013/08/22 16:38:24
If you do
CompletionCallback callback = base::Bind
| |
219 int rv = host_resolver_.Resolve(reqinfo, HIGHEST, // we block startup... | |
220 &wpad_addrs_, | |
221 base::Bind( | |
222 &ProxyScriptDecider::OnQuickCheckComplete, | |
szym
2013/08/22 19:06:41
To be compatible with the DoLoop state machine you
| |
223 base::Unretained(this), | |
224 base::Time::Now()), | |
225 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_WAIT; | |
234 return OK; | |
235 } else if (rv != ERR_IO_PENDING) { | |
236 // already in cache and invalid, bail now | |
237 next_state_ = STATE_FAILED; | |
238 return rv; | |
239 } | |
240 | |
241 quick_check_timer_.Start(FROM_HERE, | |
242 base::TimeDelta::FromMilliseconds( | |
243 kQuickCheckDelayMs), | |
244 base::Bind( | |
245 &ProxyScriptDecider::OnQuickCheckComplete, | |
246 base::Unretained(this), | |
247 base::Time::Now(), | |
szym
2013/08/22 16:38:24
... you can just pass: base::Bind(callback, ERR_NA
| |
248 ERR_NAME_NOT_RESOLVED)); | |
249 | |
250 next_state_ = STATE_QUICK_CHECK; | |
251 return ERR_IO_PENDING; | |
252 } | |
253 | |
254 void ProxyScriptDecider::OnQuickCheckComplete(base::Time started, int result) { | |
255 base::TimeDelta delta = base::Time::Now() - started; | |
256 UMA_HISTOGRAM_TIMES("Net.WpadQuickCheck", delta); | |
257 host_resolver_.Cancel(); | |
258 quick_check_timer_.Stop(); | |
259 if (result == OK) | |
260 next_state_ = STATE_WAIT; | |
261 else | |
262 next_state_ = STATE_FAILED; | |
263 OnIOCompletion(result); | |
264 } | |
265 | |
204 int ProxyScriptDecider::DoWait() { | 266 int ProxyScriptDecider::DoWait() { |
205 next_state_ = STATE_WAIT_COMPLETE; | 267 next_state_ = STATE_WAIT_COMPLETE; |
206 | 268 |
207 // If no waiting is required, continue on to the next state. | 269 // If no waiting is required, continue on to the next state. |
208 if (wait_delay_.ToInternalValue() == 0) | 270 if (wait_delay_.ToInternalValue() == 0) |
209 return OK; | 271 return OK; |
210 | 272 |
211 // Otherwise wait the specified amount of time. | 273 // Otherwise wait the specified amount of time. |
212 wait_timer_.Start(FROM_HERE, wait_delay_, this, | 274 wait_timer_.Start(FROM_HERE, wait_delay_, this, |
213 &ProxyScriptDecider::OnWaitTimerFired); | 275 &ProxyScriptDecider::OnWaitTimerFired); |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
392 | 454 |
393 net_log_.AddEvent(NetLog::TYPE_CANCELLED); | 455 net_log_.AddEvent(NetLog::TYPE_CANCELLED); |
394 | 456 |
395 switch (next_state_) { | 457 switch (next_state_) { |
396 case STATE_WAIT_COMPLETE: | 458 case STATE_WAIT_COMPLETE: |
397 wait_timer_.Stop(); | 459 wait_timer_.Stop(); |
398 break; | 460 break; |
399 case STATE_FETCH_PAC_SCRIPT_COMPLETE: | 461 case STATE_FETCH_PAC_SCRIPT_COMPLETE: |
400 proxy_script_fetcher_->Cancel(); | 462 proxy_script_fetcher_->Cancel(); |
401 break; | 463 break; |
464 case STATE_FAILED: | |
465 break; | |
402 default: | 466 default: |
403 NOTREACHED(); | 467 NOTREACHED(); |
404 break; | 468 break; |
405 } | 469 } |
406 | 470 |
407 // This is safe to call in any state. | 471 // This is safe to call in any state. |
408 if (dhcp_proxy_script_fetcher_) | 472 if (dhcp_proxy_script_fetcher_) |
409 dhcp_proxy_script_fetcher_->Cancel(); | 473 dhcp_proxy_script_fetcher_->Cancel(); |
410 | 474 |
411 DidComplete(); | 475 DidComplete(); |
412 } | 476 } |
413 | 477 |
414 } // namespace net | 478 } // namespace net |
OLD | NEW |