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

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: Responding to review comments. Created 9 years, 7 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 ProxyScriptFetcher* proxy_script_fetcher,
38 DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher,
39 NetLog* net_log)
36 : resolver_(resolver), 40 : resolver_(resolver),
37 proxy_script_fetcher_(proxy_script_fetcher), 41 proxy_script_fetcher_(proxy_script_fetcher),
42 dhcp_proxy_script_fetcher_(dhcp_proxy_script_fetcher),
38 ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_( 43 ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_(
39 this, &InitProxyResolver::OnIOCompletion)), 44 this, &InitProxyResolver::OnIOCompletion)),
40 user_callback_(NULL), 45 user_callback_(NULL),
41 current_pac_url_index_(0u), 46 current_pac_source_index_(0u),
42 next_state_(STATE_NONE), 47 next_state_(STATE_NONE),
43 net_log_(BoundNetLog::Make( 48 net_log_(BoundNetLog::Make(
44 net_log, NetLog::SOURCE_INIT_PROXY_RESOLVER)), 49 net_log, NetLog::SOURCE_INIT_PROXY_RESOLVER)),
45 effective_config_(NULL) { 50 effective_config_(NULL) {
46 } 51 }
47 52
48 InitProxyResolver::~InitProxyResolver() { 53 InitProxyResolver::~InitProxyResolver() {
49 if (next_state_ != STATE_NONE) 54 if (next_state_ != STATE_NONE)
50 Cancel(); 55 Cancel();
51 } 56 }
52 57
53 int InitProxyResolver::Init(const ProxyConfig& config, 58 int InitProxyResolver::Init(const ProxyConfig& config,
54 const base::TimeDelta wait_delay, 59 const base::TimeDelta wait_delay,
55 ProxyConfig* effective_config, 60 ProxyConfig* effective_config,
56 CompletionCallback* callback) { 61 CompletionCallback* callback) {
57 DCHECK_EQ(STATE_NONE, next_state_); 62 DCHECK_EQ(STATE_NONE, next_state_);
58 DCHECK(callback); 63 DCHECK(callback);
59 DCHECK(config.HasAutomaticSettings()); 64 DCHECK(config.HasAutomaticSettings());
60 65
61 net_log_.BeginEvent(NetLog::TYPE_INIT_PROXY_RESOLVER, NULL); 66 net_log_.BeginEvent(NetLog::TYPE_INIT_PROXY_RESOLVER, NULL);
62 67
63 // Save the |wait_delay| as a non-negative value. 68 // Save the |wait_delay| as a non-negative value.
64 wait_delay_ = wait_delay; 69 wait_delay_ = wait_delay;
65 if (wait_delay_ < base::TimeDelta()) 70 if (wait_delay_ < base::TimeDelta())
66 wait_delay_ = base::TimeDelta(); 71 wait_delay_ = base::TimeDelta();
67 72
68 effective_config_ = effective_config; 73 effective_config_ = effective_config;
69 74
70 pac_urls_ = BuildPacUrlsFallbackList(config); 75 pac_sources_ = BuildPacSourcesFallbackList(config);
71 DCHECK(!pac_urls_.empty()); 76 DCHECK(!pac_sources_.empty());
72 77
73 next_state_ = STATE_WAIT; 78 next_state_ = STATE_WAIT;
74 79
75 int rv = DoLoop(OK); 80 int rv = DoLoop(OK);
76 if (rv == ERR_IO_PENDING) 81 if (rv == ERR_IO_PENDING)
77 user_callback_ = callback; 82 user_callback_ = callback;
78 else 83 else
79 DidCompleteInit(); 84 DidCompleteInit();
80 85
81 return rv; 86 return rv;
82 } 87 }
83 88
84 // Initialize the fallback rules. 89 // Initialize the fallback rules.
85 // (1) WPAD (DNS). 90 // (1) WPAD (DHCP).
86 // (2) Custom PAC URL. 91 // (2) WPAD (DNS).
87 InitProxyResolver::UrlList InitProxyResolver::BuildPacUrlsFallbackList( 92 // (3) Custom PAC URL.
93 InitProxyResolver::PacSourceList InitProxyResolver::BuildPacSourcesFallbackList(
88 const ProxyConfig& config) const { 94 const ProxyConfig& config) const {
89 UrlList pac_urls; 95 PacSourceList pac_sources;
90 if (config.auto_detect()) 96 if (config.auto_detect()) {
91 pac_urls.push_back(PacURL(true, GURL())); 97 pac_sources.push_back(PacSource(PacSource::WPAD_DHCP, GURL()));
98 pac_sources.push_back(PacSource(PacSource::WPAD_DNS, GURL()));
99 }
92 if (config.has_pac_url()) 100 if (config.has_pac_url())
93 pac_urls.push_back(PacURL(false, config.pac_url())); 101 pac_sources.push_back(PacSource(PacSource::CUSTOM, config.pac_url()));
94 return pac_urls; 102 return pac_sources;
95 } 103 }
96 104
97 void InitProxyResolver::OnIOCompletion(int result) { 105 void InitProxyResolver::OnIOCompletion(int result) {
98 DCHECK_NE(STATE_NONE, next_state_); 106 DCHECK_NE(STATE_NONE, next_state_);
99 int rv = DoLoop(result); 107 int rv = DoLoop(result);
100 if (rv != ERR_IO_PENDING) { 108 if (rv != ERR_IO_PENDING) {
101 DidCompleteInit(); 109 DidCompleteInit();
102 DoCallback(rv); 110 DoCallback(rv);
103 } 111 }
104 } 112 }
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 } 175 }
168 next_state_ = GetStartState(); 176 next_state_ = GetStartState();
169 return OK; 177 return OK;
170 } 178 }
171 179
172 int InitProxyResolver::DoFetchPacScript() { 180 int InitProxyResolver::DoFetchPacScript() {
173 DCHECK(resolver_->expects_pac_bytes()); 181 DCHECK(resolver_->expects_pac_bytes());
174 182
175 next_state_ = STATE_FETCH_PAC_SCRIPT_COMPLETE; 183 next_state_ = STATE_FETCH_PAC_SCRIPT_COMPLETE;
176 184
177 const PacURL& pac_url = current_pac_url(); 185 const PacSource& pac_source = current_pac_source();
178 186
179 const GURL effective_pac_url = 187 GURL effective_pac_url;
180 pac_url.auto_detect ? GURL(kWpadUrl) : pac_url.url; 188 NetLogStringParameter* log_parameter =
189 CreateNetLogParameterForSource(pac_source, &effective_pac_url);
181 190
182 net_log_.BeginEvent( 191 net_log_.BeginEvent(
183 NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT, 192 NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT,
184 make_scoped_refptr(new NetLogStringParameter( 193 make_scoped_refptr(log_parameter));
185 "url", effective_pac_url.possibly_invalid_spec())));
186 194
187 if (!proxy_script_fetcher_) { 195 if (pac_source.type == PacSource::WPAD_DHCP) {
188 net_log_.AddEvent(NetLog::TYPE_INIT_PROXY_RESOLVER_HAS_NO_FETCHER, NULL); 196 if (!dhcp_proxy_script_fetcher_) {
189 return ERR_UNEXPECTED; 197 net_log_.AddEvent(NetLog::TYPE_INIT_PROXY_RESOLVER_HAS_NO_FETCHER, NULL);
198 return ERR_UNEXPECTED;
199 }
200
201 return dhcp_proxy_script_fetcher_->Fetch(&pac_script_, &io_callback_);
202 } else {
203 if (!proxy_script_fetcher_) {
204 net_log_.AddEvent(NetLog::TYPE_INIT_PROXY_RESOLVER_HAS_NO_FETCHER, NULL);
205 return ERR_UNEXPECTED;
206 }
207
208 return proxy_script_fetcher_->Fetch(
209 effective_pac_url, &pac_script_, &io_callback_);
190 } 210 }
191
192 return proxy_script_fetcher_->Fetch(effective_pac_url,
193 &pac_script_,
194 &io_callback_);
195 } 211 }
196 212
197 int InitProxyResolver::DoFetchPacScriptComplete(int result) { 213 int InitProxyResolver::DoFetchPacScriptComplete(int result) {
198 DCHECK(resolver_->expects_pac_bytes()); 214 DCHECK(resolver_->expects_pac_bytes());
199 215
200 net_log_.EndEventWithNetErrorCode( 216 net_log_.EndEventWithNetErrorCode(
201 NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT, result); 217 NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT, result);
202 if (result != OK) 218 if (result != OK)
203 return TryToFallbackPacUrl(result); 219 return TryToFallbackPacSource(result);
204 220
205 next_state_ = STATE_SET_PAC_SCRIPT; 221 next_state_ = STATE_SET_PAC_SCRIPT;
206 return result; 222 return result;
207 } 223 }
208 224
209 int InitProxyResolver::DoSetPacScript() { 225 int InitProxyResolver::DoSetPacScript() {
210 net_log_.BeginEvent(NetLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT, NULL); 226 net_log_.BeginEvent(NetLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT, NULL);
211 227
212 const PacURL& pac_url = current_pac_url(); 228 const PacSource& pac_source = current_pac_source();
213 229
214 next_state_ = STATE_SET_PAC_SCRIPT_COMPLETE; 230 next_state_ = STATE_SET_PAC_SCRIPT_COMPLETE;
215 231
216 scoped_refptr<ProxyResolverScriptData> script_data; 232 scoped_refptr<ProxyResolverScriptData> script_data;
217 233
218 if (resolver_->expects_pac_bytes()) { 234 if (resolver_->expects_pac_bytes()) {
219 script_data = ProxyResolverScriptData::FromUTF16(pac_script_); 235 script_data = ProxyResolverScriptData::FromUTF16(pac_script_);
220 } else { 236 } else {
221 script_data = pac_url.auto_detect ? 237 script_data = pac_source.type == PacSource::CUSTOM ?
222 ProxyResolverScriptData::ForAutoDetect() : 238 ProxyResolverScriptData::FromURL(pac_source.url) :
223 ProxyResolverScriptData::FromURL(pac_url.url); 239 ProxyResolverScriptData::ForAutoDetect();
224 } 240 }
225 241
226 return resolver_->SetPacScript(script_data, &io_callback_); 242 return resolver_->SetPacScript(script_data, &io_callback_);
227 } 243 }
228 244
229 int InitProxyResolver::DoSetPacScriptComplete(int result) { 245 int InitProxyResolver::DoSetPacScriptComplete(int result) {
230 net_log_.EndEventWithNetErrorCode( 246 net_log_.EndEventWithNetErrorCode(
231 NetLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT, result); 247 NetLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT, result);
232 if (result != OK) 248 if (result != OK)
233 return TryToFallbackPacUrl(result); 249 return TryToFallbackPacSource(result);
234 250
235 // Let the caller know which automatic setting we ended up initializing the 251 // Let the caller know which automatic setting we ended up initializing the
236 // resolver for (there may have been multiple fallbacks to choose from.) 252 // resolver for (there may have been multiple fallbacks to choose from.)
237 if (effective_config_) { 253 if (effective_config_) {
238 if (current_pac_url().auto_detect && resolver_->expects_pac_bytes()) { 254 if (current_pac_source().type == PacSource::CUSTOM) {
239 *effective_config_ = 255 *effective_config_ =
240 ProxyConfig::CreateFromCustomPacURL(GURL(kWpadUrl)); 256 ProxyConfig::CreateFromCustomPacURL(current_pac_source().url);
241 } else if (current_pac_url().auto_detect) {
242 *effective_config_ = ProxyConfig::CreateAutoDetect();
243 } else { 257 } else {
244 *effective_config_ = 258 if (resolver_->expects_pac_bytes()) {
245 ProxyConfig::CreateFromCustomPacURL(current_pac_url().url); 259 GURL auto_detected_url;
260
261 switch (current_pac_source().type) {
262 case PacSource::WPAD_DHCP:
263 auto_detected_url = dhcp_proxy_script_fetcher_->GetPacURL();
264 break;
265
266 case PacSource::WPAD_DNS:
267 auto_detected_url = GURL(kWpadUrl);
268 break;
269
270 default:
271 NOTREACHED();
272 }
273
274 *effective_config_ =
275 ProxyConfig::CreateFromCustomPacURL(auto_detected_url);
276 } else {
277 // The resolver does its own resolution so we cannot know the
278 // URL. Just do the best we can and state that the configuration
279 // is to auto-detect proxy settings.
280 *effective_config_ = ProxyConfig::CreateAutoDetect();
281 }
246 } 282 }
247 } 283 }
248 284
249 return result; 285 return result;
250 } 286 }
251 287
252 int InitProxyResolver::TryToFallbackPacUrl(int error) { 288 int InitProxyResolver::TryToFallbackPacSource(int error) {
253 DCHECK_LT(error, 0); 289 DCHECK_LT(error, 0);
254 290
255 if (current_pac_url_index_ + 1 >= pac_urls_.size()) { 291 if (current_pac_source_index_ + 1 >= pac_sources_.size()) {
256 // Nothing left to fall back to. 292 // Nothing left to fall back to.
257 return error; 293 return error;
258 } 294 }
259 295
260 // Advance to next URL in our list. 296 // Advance to next URL in our list.
261 ++current_pac_url_index_; 297 ++current_pac_source_index_;
262 298
263 net_log_.AddEvent( 299 net_log_.AddEvent(
264 NetLog::TYPE_INIT_PROXY_RESOLVER_FALLING_BACK_TO_NEXT_PAC_URL, NULL); 300 NetLog::TYPE_INIT_PROXY_RESOLVER_FALLING_BACK_TO_NEXT_PAC_SOURCE, NULL);
265 301
266 next_state_ = GetStartState(); 302 next_state_ = GetStartState();
267 303
268 return OK; 304 return OK;
269 } 305 }
270 306
271 InitProxyResolver::State InitProxyResolver::GetStartState() const { 307 InitProxyResolver::State InitProxyResolver::GetStartState() const {
272 return resolver_->expects_pac_bytes() ? 308 return resolver_->expects_pac_bytes() ?
273 STATE_FETCH_PAC_SCRIPT : STATE_SET_PAC_SCRIPT; 309 STATE_FETCH_PAC_SCRIPT : STATE_SET_PAC_SCRIPT;
274 } 310 }
275 311
276 const InitProxyResolver::PacURL& InitProxyResolver::current_pac_url() const { 312 NetLogStringParameter* InitProxyResolver::CreateNetLogParameterForSource(
277 DCHECK_LT(current_pac_url_index_, pac_urls_.size()); 313 const PacSource& pac_source,
278 return pac_urls_[current_pac_url_index_]; 314 GURL* effective_pac_url) {
315 DCHECK(effective_pac_url);
316
317 std::string source_field;
318 switch (pac_source.type) {
319 case PacSource::WPAD_DHCP:
320 source_field = "WPAD DHCP";
321 break;
322 case PacSource::WPAD_DNS:
323 *effective_pac_url = GURL(kWpadUrl);
324 source_field = "WPAD DNS: ";
325 source_field += effective_pac_url->possibly_invalid_spec();
326 break;
327 case PacSource::CUSTOM:
328 *effective_pac_url = pac_source.url;
329 source_field = "Custom PAC URL: ";
330 source_field += effective_pac_url->possibly_invalid_spec();
331 break;
332 }
333 return new NetLogStringParameter("source", source_field);
334 }
335
336 const InitProxyResolver::PacSource&
337 InitProxyResolver::current_pac_source() const {
338 DCHECK_LT(current_pac_source_index_, pac_sources_.size());
339 return pac_sources_[current_pac_source_index_];
279 } 340 }
280 341
281 void InitProxyResolver::OnWaitTimerFired() { 342 void InitProxyResolver::OnWaitTimerFired() {
282 OnIOCompletion(OK); 343 OnIOCompletion(OK);
283 } 344 }
284 345
285 void InitProxyResolver::DidCompleteInit() { 346 void InitProxyResolver::DidCompleteInit() {
286 net_log_.EndEvent(NetLog::TYPE_INIT_PROXY_RESOLVER, NULL); 347 net_log_.EndEvent(NetLog::TYPE_INIT_PROXY_RESOLVER, NULL);
287 } 348 }
288 349
(...skipping 14 matching lines...) Expand all
303 break; 364 break;
304 default: 365 default:
305 NOTREACHED(); 366 NOTREACHED();
306 break; 367 break;
307 } 368 }
308 369
309 DidCompleteInit(); 370 DidCompleteInit();
310 } 371 }
311 372
312 } // namespace net 373 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698