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

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

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

Powered by Google App Engine
This is Rietveld 408576698