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

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: Fix memory leaks in unit test. 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) 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"
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 pac_mandatory_(false), 47 pac_mandatory_(false),
43 next_state_(STATE_NONE), 48 next_state_(STATE_NONE),
44 net_log_(BoundNetLog::Make( 49 net_log_(BoundNetLog::Make(
45 net_log, NetLog::SOURCE_INIT_PROXY_RESOLVER)), 50 net_log, NetLog::SOURCE_INIT_PROXY_RESOLVER)),
46 effective_config_(NULL) { 51 effective_config_(NULL) {
47 } 52 }
48 53
49 InitProxyResolver::~InitProxyResolver() { 54 InitProxyResolver::~InitProxyResolver() {
50 if (next_state_ != STATE_NONE) 55 if (next_state_ != STATE_NONE)
51 Cancel(); 56 Cancel();
(...skipping 11 matching lines...) Expand all
63 68
64 // Save the |wait_delay| as a non-negative value. 69 // Save the |wait_delay| as a non-negative value.
65 wait_delay_ = wait_delay; 70 wait_delay_ = wait_delay;
66 if (wait_delay_ < base::TimeDelta()) 71 if (wait_delay_ < base::TimeDelta())
67 wait_delay_ = base::TimeDelta(); 72 wait_delay_ = base::TimeDelta();
68 73
69 effective_config_ = effective_config; 74 effective_config_ = effective_config;
70 75
71 pac_mandatory_ = config.pac_mandatory(); 76 pac_mandatory_ = config.pac_mandatory();
72 77
73 pac_urls_ = BuildPacUrlsFallbackList(config); 78 pac_sources_ = BuildPacSourcesFallbackList(config);
74 DCHECK(!pac_urls_.empty()); 79 DCHECK(!pac_sources_.empty());
75 80
76 next_state_ = STATE_WAIT; 81 next_state_ = STATE_WAIT;
77 82
78 int rv = DoLoop(OK); 83 int rv = DoLoop(OK);
79 if (rv == ERR_IO_PENDING) 84 if (rv == ERR_IO_PENDING)
80 user_callback_ = callback; 85 user_callback_ = callback;
81 else 86 else
82 DidCompleteInit(); 87 DidCompleteInit();
83 88
84 return rv; 89 return rv;
85 } 90 }
86 91
87 // Initialize the fallback rules. 92 // Initialize the fallback rules.
88 // (1) WPAD (DNS). 93 // (1) WPAD (DHCP).
89 // (2) Custom PAC URL. 94 // (2) WPAD (DNS).
90 InitProxyResolver::UrlList InitProxyResolver::BuildPacUrlsFallbackList( 95 // (3) Custom PAC URL.
96 InitProxyResolver::PacSourceList InitProxyResolver::BuildPacSourcesFallbackList(
91 const ProxyConfig& config) const { 97 const ProxyConfig& config) const {
92 UrlList pac_urls; 98 PacSourceList pac_sources;
93 if (config.auto_detect()) 99 if (config.auto_detect()) {
94 pac_urls.push_back(PacURL(true, GURL())); 100 pac_sources.push_back(PacSource(PacSource::WPAD_DHCP, GURL()));
101 pac_sources.push_back(PacSource(PacSource::WPAD_DNS, GURL()));
102 }
95 if (config.has_pac_url()) 103 if (config.has_pac_url())
96 pac_urls.push_back(PacURL(false, config.pac_url())); 104 pac_sources.push_back(PacSource(PacSource::CUSTOM, config.pac_url()));
97 return pac_urls; 105 return pac_sources;
98 } 106 }
99 107
100 void InitProxyResolver::OnIOCompletion(int result) { 108 void InitProxyResolver::OnIOCompletion(int result) {
101 DCHECK_NE(STATE_NONE, next_state_); 109 DCHECK_NE(STATE_NONE, next_state_);
102 int rv = DoLoop(result); 110 int rv = DoLoop(result);
103 if (rv != ERR_IO_PENDING) { 111 if (rv != ERR_IO_PENDING) {
104 DidCompleteInit(); 112 DidCompleteInit();
105 DoCallback(rv); 113 DoCallback(rv);
106 } 114 }
107 } 115 }
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 } 178 }
171 next_state_ = GetStartState(); 179 next_state_ = GetStartState();
172 return OK; 180 return OK;
173 } 181 }
174 182
175 int InitProxyResolver::DoFetchPacScript() { 183 int InitProxyResolver::DoFetchPacScript() {
176 DCHECK(resolver_->expects_pac_bytes()); 184 DCHECK(resolver_->expects_pac_bytes());
177 185
178 next_state_ = STATE_FETCH_PAC_SCRIPT_COMPLETE; 186 next_state_ = STATE_FETCH_PAC_SCRIPT_COMPLETE;
179 187
180 const PacURL& pac_url = current_pac_url(); 188 const PacSource& pac_source = current_pac_source();
181 189
182 const GURL effective_pac_url = 190 GURL effective_pac_url;
183 pac_url.auto_detect ? GURL(kWpadUrl) : pac_url.url; 191 NetLogStringParameter* log_parameter =
192 CreateNetLogParameterAndDetermineURL(pac_source, &effective_pac_url);
184 193
185 net_log_.BeginEvent( 194 net_log_.BeginEvent(
186 NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT, 195 NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT,
187 make_scoped_refptr(new NetLogStringParameter( 196 make_scoped_refptr(log_parameter));
188 "url", effective_pac_url.possibly_invalid_spec()))); 197
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 }
189 206
190 if (!proxy_script_fetcher_) { 207 if (!proxy_script_fetcher_) {
191 net_log_.AddEvent(NetLog::TYPE_INIT_PROXY_RESOLVER_HAS_NO_FETCHER, NULL); 208 net_log_.AddEvent(NetLog::TYPE_INIT_PROXY_RESOLVER_HAS_NO_FETCHER, NULL);
192 return ERR_UNEXPECTED; 209 return ERR_UNEXPECTED;
193 } 210 }
194 211
195 return proxy_script_fetcher_->Fetch(effective_pac_url, 212 return proxy_script_fetcher_->Fetch(
196 &pac_script_, 213 effective_pac_url, &pac_script_, &io_callback_);
197 &io_callback_);
198 } 214 }
199 215
200 int InitProxyResolver::DoFetchPacScriptComplete(int result) { 216 int InitProxyResolver::DoFetchPacScriptComplete(int result) {
201 DCHECK(resolver_->expects_pac_bytes()); 217 DCHECK(resolver_->expects_pac_bytes());
202 218
203 net_log_.EndEventWithNetErrorCode( 219 net_log_.EndEventWithNetErrorCode(
204 NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT, result); 220 NetLog::TYPE_INIT_PROXY_RESOLVER_FETCH_PAC_SCRIPT, result);
205 if (result != OK) 221 if (result != OK)
206 return TryToFallbackPacUrl(result); 222 return TryToFallbackPacSource(result);
207 223
208 next_state_ = STATE_SET_PAC_SCRIPT; 224 next_state_ = STATE_SET_PAC_SCRIPT;
209 return result; 225 return result;
210 } 226 }
211 227
212 int InitProxyResolver::DoSetPacScript() { 228 int InitProxyResolver::DoSetPacScript() {
213 net_log_.BeginEvent(NetLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT, NULL); 229 net_log_.BeginEvent(NetLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT, NULL);
214 230
215 const PacURL& pac_url = current_pac_url(); 231 const PacSource& pac_source = current_pac_source();
216 232
217 next_state_ = STATE_SET_PAC_SCRIPT_COMPLETE; 233 next_state_ = STATE_SET_PAC_SCRIPT_COMPLETE;
218 234
219 scoped_refptr<ProxyResolverScriptData> script_data; 235 scoped_refptr<ProxyResolverScriptData> script_data;
220 236
221 if (resolver_->expects_pac_bytes()) { 237 if (resolver_->expects_pac_bytes()) {
222 script_data = ProxyResolverScriptData::FromUTF16(pac_script_); 238 script_data = ProxyResolverScriptData::FromUTF16(pac_script_);
223 } else { 239 } else {
224 script_data = pac_url.auto_detect ? 240 script_data = pac_source.type == PacSource::CUSTOM ?
225 ProxyResolverScriptData::ForAutoDetect() : 241 ProxyResolverScriptData::FromURL(pac_source.url) :
226 ProxyResolverScriptData::FromURL(pac_url.url); 242 ProxyResolverScriptData::ForAutoDetect();
227 } 243 }
228 244
229 return resolver_->SetPacScript(script_data, &io_callback_); 245 return resolver_->SetPacScript(script_data, &io_callback_);
230 } 246 }
231 247
232 int InitProxyResolver::DoSetPacScriptComplete(int result) { 248 int InitProxyResolver::DoSetPacScriptComplete(int result) {
233 net_log_.EndEventWithNetErrorCode( 249 net_log_.EndEventWithNetErrorCode(
234 NetLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT, result); 250 NetLog::TYPE_INIT_PROXY_RESOLVER_SET_PAC_SCRIPT, result);
235 if (result != OK) 251 if (result != OK)
236 return TryToFallbackPacUrl(result); 252 return TryToFallbackPacSource(result);
237 253
238 // Let the caller know which automatic setting we ended up initializing the 254 // Let the caller know which automatic setting we ended up initializing the
239 // resolver for (there may have been multiple fallbacks to choose from.) 255 // resolver for (there may have been multiple fallbacks to choose from.)
240 if (effective_config_) { 256 if (effective_config_) {
241 if (current_pac_url().auto_detect && resolver_->expects_pac_bytes()) { 257 if (current_pac_source().type == PacSource::CUSTOM) {
242 *effective_config_ = 258 *effective_config_ =
243 ProxyConfig::CreateFromCustomPacURL(GURL(kWpadUrl)); 259 ProxyConfig::CreateFromCustomPacURL(current_pac_source().url);
244 } else if (current_pac_url().auto_detect) { 260 effective_config_->set_pac_mandatory(pac_mandatory_);
245 *effective_config_ = ProxyConfig::CreateAutoDetect();
246 } else { 261 } else {
247 *effective_config_ = 262 if (resolver_->expects_pac_bytes()) {
248 ProxyConfig::CreateFromCustomPacURL(current_pac_url().url); 263 GURL auto_detected_url;
249 effective_config_->set_pac_mandatory(pac_mandatory_); 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 }
250 } 286 }
251 } 287 }
252 288
253 return result; 289 return result;
254 } 290 }
255 291
256 int InitProxyResolver::TryToFallbackPacUrl(int error) { 292 int InitProxyResolver::TryToFallbackPacSource(int error) {
257 DCHECK_LT(error, 0); 293 DCHECK_LT(error, 0);
258 294
259 if (current_pac_url_index_ + 1 >= pac_urls_.size()) { 295 if (current_pac_source_index_ + 1 >= pac_sources_.size()) {
260 // Nothing left to fall back to. 296 // Nothing left to fall back to.
261 return error; 297 return error;
262 } 298 }
263 299
264 // Advance to next URL in our list. 300 // Advance to next URL in our list.
265 ++current_pac_url_index_; 301 ++current_pac_source_index_;
266 302
267 net_log_.AddEvent( 303 net_log_.AddEvent(
268 NetLog::TYPE_INIT_PROXY_RESOLVER_FALLING_BACK_TO_NEXT_PAC_URL, NULL); 304 NetLog::TYPE_INIT_PROXY_RESOLVER_FALLING_BACK_TO_NEXT_PAC_SOURCE, NULL);
269 305
270 next_state_ = GetStartState(); 306 next_state_ = GetStartState();
271 307
272 return OK; 308 return OK;
273 } 309 }
274 310
275 InitProxyResolver::State InitProxyResolver::GetStartState() const { 311 InitProxyResolver::State InitProxyResolver::GetStartState() const {
276 return resolver_->expects_pac_bytes() ? 312 return resolver_->expects_pac_bytes() ?
277 STATE_FETCH_PAC_SCRIPT : STATE_SET_PAC_SCRIPT; 313 STATE_FETCH_PAC_SCRIPT : STATE_SET_PAC_SCRIPT;
278 } 314 }
279 315
280 const InitProxyResolver::PacURL& InitProxyResolver::current_pac_url() const { 316 NetLogStringParameter* InitProxyResolver::CreateNetLogParameterAndDetermineURL(
281 DCHECK_LT(current_pac_url_index_, pac_urls_.size()); 317 const PacSource& pac_source,
282 return pac_urls_[current_pac_url_index_]; 318 GURL* effective_pac_url) {
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_];
283 } 344 }
284 345
285 void InitProxyResolver::OnWaitTimerFired() { 346 void InitProxyResolver::OnWaitTimerFired() {
286 OnIOCompletion(OK); 347 OnIOCompletion(OK);
287 } 348 }
288 349
289 void InitProxyResolver::DidCompleteInit() { 350 void InitProxyResolver::DidCompleteInit() {
290 net_log_.EndEvent(NetLog::TYPE_INIT_PROXY_RESOLVER, NULL); 351 net_log_.EndEvent(NetLog::TYPE_INIT_PROXY_RESOLVER, NULL);
291 } 352 }
292 353
(...skipping 14 matching lines...) Expand all
307 break; 368 break;
308 default: 369 default:
309 NOTREACHED(); 370 NOTREACHED();
310 break; 371 break;
311 } 372 }
312 373
313 DidCompleteInit(); 374 DidCompleteInit();
314 } 375 }
315 376
316 } // namespace net 377 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698