OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/init_proxy_resolver.h" | 5 #include "net/proxy/init_proxy_resolver.h" |
6 | 6 |
7 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
8 #include "base/format_macros.h" | 8 #include "base/format_macros.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
11 #include "net/base/net_log.h" | 11 #include "net/base/net_log.h" |
12 #include "net/base/net_errors.h" | 12 #include "net/base/net_errors.h" |
13 #include "net/proxy/dhcp_proxy_script_fetcher.h" | |
14 #include "net/proxy/dhcp_proxy_script_fetcher_factory.h" | |
15 #include "net/proxy/proxy_config.h" | 13 #include "net/proxy/proxy_config.h" |
16 #include "net/proxy/proxy_resolver.h" | 14 #include "net/proxy/proxy_resolver.h" |
17 #include "net/proxy/proxy_script_fetcher.h" | 15 #include "net/proxy/proxy_script_fetcher.h" |
18 | 16 |
19 namespace net { | 17 namespace net { |
20 | 18 |
21 // This is the hard-coded location used by the DNS portion of web proxy | 19 // This is the hard-coded location used by the DNS portion of web proxy |
22 // auto-discovery. | 20 // auto-discovery. |
23 // | 21 // |
24 // Note that we not use DNS devolution to find the WPAD host, since that could | 22 // Note that we not use DNS devolution to find the WPAD host, since that could |
25 // be dangerous should our top level domain registry become out of date. | 23 // be dangerous should our top level domain registry become out of date. |
26 // | 24 // |
27 // Instead we directly resolve "wpad", and let the operating system apply the | 25 // Instead we directly resolve "wpad", and let the operating system apply the |
28 // DNS suffix search paths. This is the same approach taken by Firefox, and | 26 // DNS suffix search paths. This is the same approach taken by Firefox, and |
29 // compatibility hasn't been an issue. | 27 // compatibility hasn't been an issue. |
30 // | 28 // |
31 // For more details, also check out this comment: | 29 // For more details, also check out this comment: |
32 // http://code.google.com/p/chromium/issues/detail?id=18575#c20 | 30 // http://code.google.com/p/chromium/issues/detail?id=18575#c20 |
33 static const char kWpadUrl[] = "http://wpad/wpad.dat"; | 31 static const char kWpadUrl[] = "http://wpad/wpad.dat"; |
34 | 32 |
35 InitProxyResolver::InitProxyResolver( | 33 InitProxyResolver::InitProxyResolver(ProxyResolver* resolver, |
36 ProxyResolver* resolver, | 34 ProxyScriptFetcher* proxy_script_fetcher, |
37 ProxyScriptFetcher* proxy_script_fetcher, | 35 NetLog* net_log) |
38 DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher, | |
39 NetLog* net_log) | |
40 : resolver_(resolver), | 36 : resolver_(resolver), |
41 proxy_script_fetcher_(proxy_script_fetcher), | 37 proxy_script_fetcher_(proxy_script_fetcher), |
42 dhcp_proxy_script_fetcher_(dhcp_proxy_script_fetcher), | |
43 ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_( | 38 ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_( |
44 this, &InitProxyResolver::OnIOCompletion)), | 39 this, &InitProxyResolver::OnIOCompletion)), |
45 user_callback_(NULL), | 40 user_callback_(NULL), |
46 current_pac_source_index_(0u), | 41 current_pac_url_index_(0u), |
47 pac_mandatory_(false), | 42 pac_mandatory_(false), |
48 next_state_(STATE_NONE), | 43 next_state_(STATE_NONE), |
49 net_log_(BoundNetLog::Make( | 44 net_log_(BoundNetLog::Make( |
50 net_log, NetLog::SOURCE_INIT_PROXY_RESOLVER)), | 45 net_log, NetLog::SOURCE_INIT_PROXY_RESOLVER)), |
51 effective_config_(NULL) { | 46 effective_config_(NULL) { |
52 } | 47 } |
53 | 48 |
54 InitProxyResolver::~InitProxyResolver() { | 49 InitProxyResolver::~InitProxyResolver() { |
55 if (next_state_ != STATE_NONE) | 50 if (next_state_ != STATE_NONE) |
56 Cancel(); | 51 Cancel(); |
(...skipping 11 matching lines...) Expand all Loading... |
68 | 63 |
69 // Save the |wait_delay| as a non-negative value. | 64 // Save the |wait_delay| as a non-negative value. |
70 wait_delay_ = wait_delay; | 65 wait_delay_ = wait_delay; |
71 if (wait_delay_ < base::TimeDelta()) | 66 if (wait_delay_ < base::TimeDelta()) |
72 wait_delay_ = base::TimeDelta(); | 67 wait_delay_ = base::TimeDelta(); |
73 | 68 |
74 effective_config_ = effective_config; | 69 effective_config_ = effective_config; |
75 | 70 |
76 pac_mandatory_ = config.pac_mandatory(); | 71 pac_mandatory_ = config.pac_mandatory(); |
77 | 72 |
78 pac_sources_ = BuildPacSourcesFallbackList(config); | 73 pac_urls_ = BuildPacUrlsFallbackList(config); |
79 DCHECK(!pac_sources_.empty()); | 74 DCHECK(!pac_urls_.empty()); |
80 | 75 |
81 next_state_ = STATE_WAIT; | 76 next_state_ = STATE_WAIT; |
82 | 77 |
83 int rv = DoLoop(OK); | 78 int rv = DoLoop(OK); |
84 if (rv == ERR_IO_PENDING) | 79 if (rv == ERR_IO_PENDING) |
85 user_callback_ = callback; | 80 user_callback_ = callback; |
86 else | 81 else |
87 DidCompleteInit(); | 82 DidCompleteInit(); |
88 | 83 |
89 return rv; | 84 return rv; |
90 } | 85 } |
91 | 86 |
92 // Initialize the fallback rules. | 87 // Initialize the fallback rules. |
93 // (1) WPAD (DHCP). | 88 // (1) WPAD (DNS). |
94 // (2) WPAD (DNS). | 89 // (2) Custom PAC URL. |
95 // (3) Custom PAC URL. | 90 InitProxyResolver::UrlList InitProxyResolver::BuildPacUrlsFallbackList( |
96 InitProxyResolver::PacSourceList InitProxyResolver::BuildPacSourcesFallbackList( | |
97 const ProxyConfig& config) const { | 91 const ProxyConfig& config) const { |
98 PacSourceList pac_sources; | 92 UrlList pac_urls; |
99 if (config.auto_detect()) { | 93 if (config.auto_detect()) |
100 pac_sources.push_back(PacSource(PacSource::WPAD_DHCP, GURL())); | 94 pac_urls.push_back(PacURL(true, GURL())); |
101 pac_sources.push_back(PacSource(PacSource::WPAD_DNS, GURL())); | |
102 } | |
103 if (config.has_pac_url()) | 95 if (config.has_pac_url()) |
104 pac_sources.push_back(PacSource(PacSource::CUSTOM, config.pac_url())); | 96 pac_urls.push_back(PacURL(false, config.pac_url())); |
105 return pac_sources; | 97 return pac_urls; |
106 } | 98 } |
107 | 99 |
108 void InitProxyResolver::OnIOCompletion(int result) { | 100 void InitProxyResolver::OnIOCompletion(int result) { |
109 DCHECK_NE(STATE_NONE, next_state_); | 101 DCHECK_NE(STATE_NONE, next_state_); |
110 int rv = DoLoop(result); | 102 int rv = DoLoop(result); |
111 if (rv != ERR_IO_PENDING) { | 103 if (rv != ERR_IO_PENDING) { |
112 DidCompleteInit(); | 104 DidCompleteInit(); |
113 DoCallback(rv); | 105 DoCallback(rv); |
114 } | 106 } |
115 } | 107 } |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 } | 170 } |
179 next_state_ = GetStartState(); | 171 next_state_ = GetStartState(); |
180 return OK; | 172 return OK; |
181 } | 173 } |
182 | 174 |
183 int InitProxyResolver::DoFetchPacScript() { | 175 int InitProxyResolver::DoFetchPacScript() { |
184 DCHECK(resolver_->expects_pac_bytes()); | 176 DCHECK(resolver_->expects_pac_bytes()); |
185 | 177 |
186 next_state_ = STATE_FETCH_PAC_SCRIPT_COMPLETE; | 178 next_state_ = STATE_FETCH_PAC_SCRIPT_COMPLETE; |
187 | 179 |
188 const PacSource& pac_source = current_pac_source(); | 180 const PacURL& pac_url = current_pac_url(); |
189 | 181 |
190 GURL effective_pac_url; | 182 const GURL effective_pac_url = |
191 NetLogStringParameter* log_parameter = | 183 pac_url.auto_detect ? GURL(kWpadUrl) : pac_url.url; |
192 CreateNetLogParameterAndDetermineURL(pac_source, &effective_pac_url); | |
193 | 184 |
194 net_log_.BeginEvent( | 185 net_log_.BeginEvent( |
195 NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT, | 186 NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT, |
196 make_scoped_refptr(log_parameter)); | 187 make_scoped_refptr(new NetLogStringParameter( |
197 | 188 "url", effective_pac_url.possibly_invalid_spec()))); |
198 if (pac_source.type == PacSource::WPAD_DHCP) { | |
199 if (!dhcp_proxy_script_fetcher_) { | |
200 net_log_.AddEvent(NetLog::TYPE_INIT_PROXY_RESOLVER_HAS_NO_FETCHER, NULL); | |
201 return ERR_UNEXPECTED; | |
202 } | |
203 | |
204 return dhcp_proxy_script_fetcher_->Fetch(&pac_script_, &io_callback_); | |
205 } | |
206 | 189 |
207 if (!proxy_script_fetcher_) { | 190 if (!proxy_script_fetcher_) { |
208 net_log_.AddEvent(NetLog::TYPE_INIT_PROXY_RESOLVER_HAS_NO_FETCHER, NULL); | 191 net_log_.AddEvent(NetLog::TYPE_INIT_PROXY_RESOLVER_HAS_NO_FETCHER, NULL); |
209 return ERR_UNEXPECTED; | 192 return ERR_UNEXPECTED; |
210 } | 193 } |
211 | 194 |
212 return proxy_script_fetcher_->Fetch( | 195 return proxy_script_fetcher_->Fetch(effective_pac_url, |
213 effective_pac_url, &pac_script_, &io_callback_); | 196 &pac_script_, |
| 197 &io_callback_); |
214 } | 198 } |
215 | 199 |
216 int InitProxyResolver::DoFetchPacScriptComplete(int result) { | 200 int InitProxyResolver::DoFetchPacScriptComplete(int result) { |
217 DCHECK(resolver_->expects_pac_bytes()); | 201 DCHECK(resolver_->expects_pac_bytes()); |
218 | 202 |
219 net_log_.EndEventWithNetErrorCode( | 203 net_log_.EndEventWithNetErrorCode( |
220 NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT, result); | 204 NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT, result); |
221 if (result != OK) | 205 if (result != OK) |
222 return TryToFallbackPacSource(result); | 206 return TryToFallbackPacUrl(result); |
223 | 207 |
224 next_state_ = STATE_SET_PAC_SCRIPT; | 208 next_state_ = STATE_SET_PAC_SCRIPT; |
225 return result; | 209 return result; |
226 } | 210 } |
227 | 211 |
228 int InitProxyResolver::DoSetPacScript() { | 212 int InitProxyResolver::DoSetPacScript() { |
229 net_log_.BeginEvent(NetLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT, NULL); | 213 net_log_.BeginEvent(NetLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT, NULL); |
230 | 214 |
231 const PacSource& pac_source = current_pac_source(); | 215 const PacURL& pac_url = current_pac_url(); |
232 | 216 |
233 next_state_ = STATE_SET_PAC_SCRIPT_COMPLETE; | 217 next_state_ = STATE_SET_PAC_SCRIPT_COMPLETE; |
234 | 218 |
235 scoped_refptr<ProxyResolverScriptData> script_data; | 219 scoped_refptr<ProxyResolverScriptData> script_data; |
236 | 220 |
237 if (resolver_->expects_pac_bytes()) { | 221 if (resolver_->expects_pac_bytes()) { |
238 script_data = ProxyResolverScriptData::FromUTF16(pac_script_); | 222 script_data = ProxyResolverScriptData::FromUTF16(pac_script_); |
239 } else { | 223 } else { |
240 script_data = pac_source.type == PacSource::CUSTOM ? | 224 script_data = pac_url.auto_detect ? |
241 ProxyResolverScriptData::FromURL(pac_source.url) : | 225 ProxyResolverScriptData::ForAutoDetect() : |
242 ProxyResolverScriptData::ForAutoDetect(); | 226 ProxyResolverScriptData::FromURL(pac_url.url); |
243 } | 227 } |
244 | 228 |
245 return resolver_->SetPacScript(script_data, &io_callback_); | 229 return resolver_->SetPacScript(script_data, &io_callback_); |
246 } | 230 } |
247 | 231 |
248 int InitProxyResolver::DoSetPacScriptComplete(int result) { | 232 int InitProxyResolver::DoSetPacScriptComplete(int result) { |
249 net_log_.EndEventWithNetErrorCode( | 233 net_log_.EndEventWithNetErrorCode( |
250 NetLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT, result); | 234 NetLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT, result); |
251 if (result != OK) | 235 if (result != OK) |
252 return TryToFallbackPacSource(result); | 236 return TryToFallbackPacUrl(result); |
253 | 237 |
254 // Let the caller know which automatic setting we ended up initializing the | 238 // Let the caller know which automatic setting we ended up initializing the |
255 // resolver for (there may have been multiple fallbacks to choose from.) | 239 // resolver for (there may have been multiple fallbacks to choose from.) |
256 if (effective_config_) { | 240 if (effective_config_) { |
257 if (current_pac_source().type == PacSource::CUSTOM) { | 241 if (current_pac_url().auto_detect && resolver_->expects_pac_bytes()) { |
258 *effective_config_ = | 242 *effective_config_ = |
259 ProxyConfig::CreateFromCustomPacURL(current_pac_source().url); | 243 ProxyConfig::CreateFromCustomPacURL(GURL(kWpadUrl)); |
| 244 } else if (current_pac_url().auto_detect) { |
| 245 *effective_config_ = ProxyConfig::CreateAutoDetect(); |
| 246 } else { |
| 247 *effective_config_ = |
| 248 ProxyConfig::CreateFromCustomPacURL(current_pac_url().url); |
260 effective_config_->set_pac_mandatory(pac_mandatory_); | 249 effective_config_->set_pac_mandatory(pac_mandatory_); |
261 } else { | |
262 if (resolver_->expects_pac_bytes()) { | |
263 GURL auto_detected_url; | |
264 | |
265 switch (current_pac_source().type) { | |
266 case PacSource::WPAD_DHCP: | |
267 auto_detected_url = dhcp_proxy_script_fetcher_->GetPacURL(); | |
268 break; | |
269 | |
270 case PacSource::WPAD_DNS: | |
271 auto_detected_url = GURL(kWpadUrl); | |
272 break; | |
273 | |
274 default: | |
275 NOTREACHED(); | |
276 } | |
277 | |
278 *effective_config_ = | |
279 ProxyConfig::CreateFromCustomPacURL(auto_detected_url); | |
280 } else { | |
281 // The resolver does its own resolution so we cannot know the | |
282 // URL. Just do the best we can and state that the configuration | |
283 // is to auto-detect proxy settings. | |
284 *effective_config_ = ProxyConfig::CreateAutoDetect(); | |
285 } | |
286 } | 250 } |
287 } | 251 } |
288 | 252 |
289 return result; | 253 return result; |
290 } | 254 } |
291 | 255 |
292 int InitProxyResolver::TryToFallbackPacSource(int error) { | 256 int InitProxyResolver::TryToFallbackPacUrl(int error) { |
293 DCHECK_LT(error, 0); | 257 DCHECK_LT(error, 0); |
294 | 258 |
295 if (current_pac_source_index_ + 1 >= pac_sources_.size()) { | 259 if (current_pac_url_index_ + 1 >= pac_urls_.size()) { |
296 // Nothing left to fall back to. | 260 // Nothing left to fall back to. |
297 return error; | 261 return error; |
298 } | 262 } |
299 | 263 |
300 // Advance to next URL in our list. | 264 // Advance to next URL in our list. |
301 ++current_pac_source_index_; | 265 ++current_pac_url_index_; |
302 | 266 |
303 net_log_.AddEvent( | 267 net_log_.AddEvent( |
304 NetLog::TYPE_INIT_PROXY_RESOLVER_FALLING_BACK_TO_NEXT_PAC_SOURCE, NULL); | 268 NetLog::TYPE_INIT_PROXY_RESOLVER_FALLING_BACK_TO_NEXT_PAC_URL, NULL); |
305 | 269 |
306 next_state_ = GetStartState(); | 270 next_state_ = GetStartState(); |
307 | 271 |
308 return OK; | 272 return OK; |
309 } | 273 } |
310 | 274 |
311 InitProxyResolver::State InitProxyResolver::GetStartState() const { | 275 InitProxyResolver::State InitProxyResolver::GetStartState() const { |
312 return resolver_->expects_pac_bytes() ? | 276 return resolver_->expects_pac_bytes() ? |
313 STATE_FETCH_PAC_SCRIPT : STATE_SET_PAC_SCRIPT; | 277 STATE_FETCH_PAC_SCRIPT : STATE_SET_PAC_SCRIPT; |
314 } | 278 } |
315 | 279 |
316 NetLogStringParameter* InitProxyResolver::CreateNetLogParameterAndDetermineURL( | 280 const InitProxyResolver::PacURL& InitProxyResolver::current_pac_url() const { |
317 const PacSource& pac_source, | 281 DCHECK_LT(current_pac_url_index_, pac_urls_.size()); |
318 GURL* effective_pac_url) { | 282 return pac_urls_[current_pac_url_index_]; |
319 DCHECK(effective_pac_url); | |
320 | |
321 std::string source_field; | |
322 switch (pac_source.type) { | |
323 case PacSource::WPAD_DHCP: | |
324 source_field = "WPAD DHCP"; | |
325 break; | |
326 case PacSource::WPAD_DNS: | |
327 *effective_pac_url = GURL(kWpadUrl); | |
328 source_field = "WPAD DNS: "; | |
329 source_field += effective_pac_url->possibly_invalid_spec(); | |
330 break; | |
331 case PacSource::CUSTOM: | |
332 *effective_pac_url = pac_source.url; | |
333 source_field = "Custom PAC URL: "; | |
334 source_field += effective_pac_url->possibly_invalid_spec(); | |
335 break; | |
336 } | |
337 return new NetLogStringParameter("source", source_field); | |
338 } | |
339 | |
340 const InitProxyResolver::PacSource& | |
341 InitProxyResolver::current_pac_source() const { | |
342 DCHECK_LT(current_pac_source_index_, pac_sources_.size()); | |
343 return pac_sources_[current_pac_source_index_]; | |
344 } | 283 } |
345 | 284 |
346 void InitProxyResolver::OnWaitTimerFired() { | 285 void InitProxyResolver::OnWaitTimerFired() { |
347 OnIOCompletion(OK); | 286 OnIOCompletion(OK); |
348 } | 287 } |
349 | 288 |
350 void InitProxyResolver::DidCompleteInit() { | 289 void InitProxyResolver::DidCompleteInit() { |
351 net_log_.EndEvent(NetLog::TYPE_INIT_PROXY_RESOLVER, NULL); | 290 net_log_.EndEvent(NetLog::TYPE_INIT_PROXY_RESOLVER, NULL); |
352 } | 291 } |
353 | 292 |
(...skipping 14 matching lines...) Expand all Loading... |
368 break; | 307 break; |
369 default: | 308 default: |
370 NOTREACHED(); | 309 NOTREACHED(); |
371 break; | 310 break; |
372 } | 311 } |
373 | 312 |
374 DidCompleteInit(); | 313 DidCompleteInit(); |
375 } | 314 } |
376 | 315 |
377 } // namespace net | 316 } // namespace net |
OLD | NEW |