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. |
29 // | 31 // |
30 // An exact test would have to load the script in a javascript evaluator. | 32 // An exact test would have to load the script in a javascript evaluator. |
31 return script.find(ASCIIToUTF16("FindProxyForURL")) != base::string16::npos; | 33 return script.find(ASCIIToUTF16("FindProxyForURL")) != base::string16::npos; |
32 } | 34 } |
33 | 35 |
34 } | 36 } |
35 | 37 |
36 // This is the hard-coded location used by the DNS portion of web proxy | 38 // This is the hard-coded location used by the DNS portion of web proxy |
37 // auto-discovery. | 39 // auto-discovery. |
38 // | 40 // |
39 // Note that we not use DNS devolution to find the WPAD host, since that could | 41 // Note that we not use DNS devolution to find the WPAD host, since that could |
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 namespace { |
51 const char kWpadUrl[] = "http://wpad/wpad.dat"; | |
52 const int kQuickCheckDelayMs = 1000; | |
53 }; | |
49 | 54 |
50 base::Value* ProxyScriptDecider::PacSource::NetLogCallback( | 55 base::Value* ProxyScriptDecider::PacSource::NetLogCallback( |
51 const GURL* effective_pac_url, | 56 const GURL* effective_pac_url, |
52 NetLog::LogLevel /* log_level */) const { | 57 NetLog::LogLevel /* log_level */) const { |
53 base::DictionaryValue* dict = new base::DictionaryValue(); | 58 base::DictionaryValue* dict = new base::DictionaryValue(); |
54 std::string source; | 59 std::string source; |
55 switch (type) { | 60 switch (type) { |
56 case PacSource::WPAD_DHCP: | 61 case PacSource::WPAD_DHCP: |
57 source = "WPAD DHCP"; | 62 source = "WPAD DHCP"; |
58 break; | 63 break; |
(...skipping 16 matching lines...) Expand all Loading... | |
75 NetLog* net_log) | 80 NetLog* net_log) |
76 : resolver_(NULL), | 81 : resolver_(NULL), |
77 proxy_script_fetcher_(proxy_script_fetcher), | 82 proxy_script_fetcher_(proxy_script_fetcher), |
78 dhcp_proxy_script_fetcher_(dhcp_proxy_script_fetcher), | 83 dhcp_proxy_script_fetcher_(dhcp_proxy_script_fetcher), |
79 current_pac_source_index_(0u), | 84 current_pac_source_index_(0u), |
80 pac_mandatory_(false), | 85 pac_mandatory_(false), |
81 next_state_(STATE_NONE), | 86 next_state_(STATE_NONE), |
82 net_log_(BoundNetLog::Make( | 87 net_log_(BoundNetLog::Make( |
83 net_log, NetLog::SOURCE_PROXY_SCRIPT_DECIDER)), | 88 net_log, NetLog::SOURCE_PROXY_SCRIPT_DECIDER)), |
84 fetch_pac_bytes_(false) { | 89 fetch_pac_bytes_(false) { |
90 if (proxy_script_fetcher && | |
91 proxy_script_fetcher->GetRequestContext() && | |
92 proxy_script_fetcher->GetRequestContext()->host_resolver()) { | |
93 host_resolver_.reset(new SingleRequestHostResolver( | |
94 proxy_script_fetcher->GetRequestContext()->host_resolver())); | |
95 } | |
85 } | 96 } |
86 | 97 |
87 ProxyScriptDecider::~ProxyScriptDecider() { | 98 ProxyScriptDecider::~ProxyScriptDecider() { |
88 if (next_state_ != STATE_NONE) | 99 if (next_state_ != STATE_NONE) |
89 Cancel(); | 100 Cancel(); |
90 } | 101 } |
91 | 102 |
92 int ProxyScriptDecider::Start( | 103 int ProxyScriptDecider::Start( |
93 const ProxyConfig& config, const base::TimeDelta wait_delay, | 104 const ProxyConfig& config, const base::TimeDelta wait_delay, |
94 bool fetch_pac_bytes, const CompletionCallback& callback) { | 105 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_; | 176 State state = next_state_; |
166 next_state_ = STATE_NONE; | 177 next_state_ = STATE_NONE; |
167 switch (state) { | 178 switch (state) { |
168 case STATE_WAIT: | 179 case STATE_WAIT: |
169 DCHECK_EQ(OK, rv); | 180 DCHECK_EQ(OK, rv); |
170 rv = DoWait(); | 181 rv = DoWait(); |
171 break; | 182 break; |
172 case STATE_WAIT_COMPLETE: | 183 case STATE_WAIT_COMPLETE: |
173 rv = DoWaitComplete(rv); | 184 rv = DoWaitComplete(rv); |
174 break; | 185 break; |
186 case STATE_QUICK_CHECK: | |
187 DCHECK_EQ(OK, rv); | |
188 rv = DoQuickCheck(); | |
189 break; | |
190 case STATE_QUICK_CHECK_COMPLETE: | |
191 rv = DoQuickCheckComplete(rv); | |
192 break; | |
175 case STATE_FETCH_PAC_SCRIPT: | 193 case STATE_FETCH_PAC_SCRIPT: |
176 DCHECK_EQ(OK, rv); | 194 DCHECK_EQ(OK, rv); |
177 rv = DoFetchPacScript(); | 195 rv = DoFetchPacScript(); |
178 break; | 196 break; |
179 case STATE_FETCH_PAC_SCRIPT_COMPLETE: | 197 case STATE_FETCH_PAC_SCRIPT_COMPLETE: |
180 rv = DoFetchPacScriptComplete(rv); | 198 rv = DoFetchPacScriptComplete(rv); |
181 break; | 199 break; |
182 case STATE_VERIFY_PAC_SCRIPT: | 200 case STATE_VERIFY_PAC_SCRIPT: |
183 DCHECK_EQ(OK, rv); | 201 DCHECK_EQ(OK, rv); |
184 rv = DoVerifyPacScript(); | 202 rv = DoVerifyPacScript(); |
(...skipping 29 matching lines...) Expand all Loading... | |
214 net_log_.BeginEvent(NetLog::TYPE_PROXY_SCRIPT_DECIDER_WAIT); | 232 net_log_.BeginEvent(NetLog::TYPE_PROXY_SCRIPT_DECIDER_WAIT); |
215 return ERR_IO_PENDING; | 233 return ERR_IO_PENDING; |
216 } | 234 } |
217 | 235 |
218 int ProxyScriptDecider::DoWaitComplete(int result) { | 236 int ProxyScriptDecider::DoWaitComplete(int result) { |
219 DCHECK_EQ(OK, result); | 237 DCHECK_EQ(OK, result); |
220 if (wait_delay_.ToInternalValue() != 0) { | 238 if (wait_delay_.ToInternalValue() != 0) { |
221 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_PROXY_SCRIPT_DECIDER_WAIT, | 239 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_PROXY_SCRIPT_DECIDER_WAIT, |
222 result); | 240 result); |
223 } | 241 } |
224 next_state_ = GetStartState(); | 242 next_state_ = STATE_QUICK_CHECK; |
225 return OK; | 243 return OK; |
226 } | 244 } |
227 | 245 |
246 int ProxyScriptDecider::DoQuickCheck() { | |
247 if (host_resolver_.get() == NULL) { | |
248 // If we have no resolver, skip QuickCheck altogether. | |
249 next_state_ = GetStartState(); | |
250 return OK; | |
251 } | |
252 | |
253 quick_check_start_time_ = base::Time::Now(); | |
254 HostResolver::RequestInfo reqinfo(HostPortPair("wpad", 80)); | |
255 CompletionCallback callback = base::Bind( | |
256 &ProxyScriptDecider::OnIOCompletion, | |
257 base::Unretained(this)); | |
258 | |
259 HostResolverFlags flags = reqinfo.host_resolver_flags(); | |
260 flags |= HOST_RESOLVER_SYSTEM_ONLY; | |
261 reqinfo.set_host_resolver_flags(flags); | |
szym
2013/09/16 22:15:54
This is unnecessary. The default flags are 0.
req
Elly Fong-Jones
2013/09/17 19:20:23
Done.
| |
262 | |
263 // We use HIGHEST here because proxy decision blocks doing any other requests. | |
264 int rv = host_resolver_->Resolve(reqinfo, HIGHEST, &wpad_addresses_, | |
265 callback, net_log_); | |
266 | |
267 // We can't get an error response - the name is known to be valid, and we | |
268 // don't cache negative dns responses. | |
269 DCHECK(rv == OK || rv == ERR_IO_PENDING); | |
270 | |
271 if (rv == OK) { | |
272 next_state_ = GetStartState(); | |
273 } else { | |
274 quick_check_timer_.Start(FROM_HERE, | |
275 base::TimeDelta::FromMilliseconds( | |
276 kQuickCheckDelayMs), | |
277 base::Bind(callback, ERR_NAME_NOT_RESOLVED)); | |
278 next_state_ = STATE_QUICK_CHECK_COMPLETE; | |
279 } | |
280 return rv; | |
281 } | |
282 | |
283 int ProxyScriptDecider::DoQuickCheckComplete(int result) { | |
284 base::TimeDelta delta = base::Time::Now() - quick_check_start_time_; | |
285 if (result == OK) | |
286 UMA_HISTOGRAM_TIMES("Net.WpadQuickCheckSuccess", delta); | |
287 else | |
288 UMA_HISTOGRAM_TIMES("Net.WpadQuickCheckFailure", delta); | |
289 host_resolver_->Cancel(); | |
290 quick_check_timer_.Stop(); | |
291 if (result == OK) | |
292 next_state_ = GetStartState(); | |
293 return result; | |
294 } | |
295 | |
228 int ProxyScriptDecider::DoFetchPacScript() { | 296 int ProxyScriptDecider::DoFetchPacScript() { |
229 DCHECK(fetch_pac_bytes_); | 297 DCHECK(fetch_pac_bytes_); |
230 | 298 |
231 next_state_ = STATE_FETCH_PAC_SCRIPT_COMPLETE; | 299 next_state_ = STATE_FETCH_PAC_SCRIPT_COMPLETE; |
232 | 300 |
233 const PacSource& pac_source = current_pac_source(); | 301 const PacSource& pac_source = current_pac_source(); |
234 | 302 |
235 GURL effective_pac_url; | 303 GURL effective_pac_url; |
236 DetermineURL(pac_source, &effective_pac_url); | 304 DetermineURL(pac_source, &effective_pac_url); |
237 | 305 |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
405 } | 473 } |
406 | 474 |
407 // This is safe to call in any state. | 475 // This is safe to call in any state. |
408 if (dhcp_proxy_script_fetcher_) | 476 if (dhcp_proxy_script_fetcher_) |
409 dhcp_proxy_script_fetcher_->Cancel(); | 477 dhcp_proxy_script_fetcher_->Cancel(); |
410 | 478 |
411 DidComplete(); | 479 DidComplete(); |
412 } | 480 } |
413 | 481 |
414 } // namespace net | 482 } // namespace net |
OLD | NEW |