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

Side by Side Diff: net/url_request/url_request_ftp_job.cc

Issue 12582012: Implement FTP auth through proxy (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fixes Created 7 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
« no previous file with comments | « net/url_request/url_request_ftp_job.h ('k') | net/url_request/url_request_ftp_job_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/url_request/url_request_ftp_job.h" 5 #include "net/url_request/url_request_ftp_job.h"
6 6
7 #include "base/compiler_specific.h" 7 #include "base/compiler_specific.h"
8 #include "base/message_loop.h" 8 #include "base/message_loop.h"
9 #include "base/utf_string_conversions.h" 9 #include "base/utf_string_conversions.h"
10 #include "net/base/auth.h" 10 #include "net/base/auth.h"
(...skipping 12 matching lines...) Expand all
23 namespace net { 23 namespace net {
24 24
25 URLRequestFtpJob::URLRequestFtpJob( 25 URLRequestFtpJob::URLRequestFtpJob(
26 URLRequest* request, 26 URLRequest* request,
27 NetworkDelegate* network_delegate, 27 NetworkDelegate* network_delegate,
28 FtpTransactionFactory* ftp_transaction_factory, 28 FtpTransactionFactory* ftp_transaction_factory,
29 FtpAuthCache* ftp_auth_cache) 29 FtpAuthCache* ftp_auth_cache)
30 : URLRequestJob(request, network_delegate), 30 : URLRequestJob(request, network_delegate),
31 priority_(DEFAULT_PRIORITY), 31 priority_(DEFAULT_PRIORITY),
32 pac_request_(NULL), 32 pac_request_(NULL),
33 response_info_(NULL), 33 http_response_info_(NULL),
34 read_in_progress_(false), 34 read_in_progress_(false),
35 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), 35 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
36 ftp_transaction_factory_(ftp_transaction_factory), 36 ftp_transaction_factory_(ftp_transaction_factory),
37 ftp_auth_cache_(ftp_auth_cache) { 37 ftp_auth_cache_(ftp_auth_cache) {
38 DCHECK(ftp_transaction_factory); 38 DCHECK(ftp_transaction_factory);
39 DCHECK(ftp_auth_cache); 39 DCHECK(ftp_auth_cache);
40 } 40 }
41 41
42 URLRequestFtpJob::~URLRequestFtpJob() { 42 URLRequestFtpJob::~URLRequestFtpJob() {
43 if (pac_request_) 43 if (pac_request_)
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 } else { 78 } else {
79 // No special handling of MIME type is needed. As opposed to direct FTP 79 // No special handling of MIME type is needed. As opposed to direct FTP
80 // transaction, we do not get a raw directory listing to parse. 80 // transaction, we do not get a raw directory listing to parse.
81 return http_transaction_->GetResponseInfo()-> 81 return http_transaction_->GetResponseInfo()->
82 headers->GetMimeType(mime_type); 82 headers->GetMimeType(mime_type);
83 } 83 }
84 return false; 84 return false;
85 } 85 }
86 86
87 void URLRequestFtpJob::GetResponseInfo(HttpResponseInfo* info) { 87 void URLRequestFtpJob::GetResponseInfo(HttpResponseInfo* info) {
88 if (response_info_) 88 if (http_response_info_)
89 *info = *response_info_; 89 *info = *http_response_info_;
90 } 90 }
91 91
92 HostPortPair URLRequestFtpJob::GetSocketAddress() const { 92 HostPortPair URLRequestFtpJob::GetSocketAddress() const {
93 if (proxy_info_.is_direct()) { 93 if (proxy_info_.is_direct()) {
94 if (!ftp_transaction_) 94 if (!ftp_transaction_)
95 return HostPortPair(); 95 return HostPortPair();
96 return ftp_transaction_->GetResponseInfo()->socket_address; 96 return ftp_transaction_->GetResponseInfo()->socket_address;
97 } else { 97 } else {
98 if (!http_transaction_) 98 if (!http_transaction_)
99 return HostPortPair(); 99 return HostPortPair();
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 // The transaction started synchronously, but we need to notify the 187 // The transaction started synchronously, but we need to notify the
188 // URLRequest delegate via the message loop. 188 // URLRequest delegate via the message loop.
189 OnStartCompletedAsync(rv); 189 OnStartCompletedAsync(rv);
190 } 190 }
191 191
192 void URLRequestFtpJob::StartHttpTransaction() { 192 void URLRequestFtpJob::StartHttpTransaction() {
193 // Create a transaction. 193 // Create a transaction.
194 DCHECK(!http_transaction_); 194 DCHECK(!http_transaction_);
195 195
196 // Do not cache FTP responses sent through HTTP proxy. 196 // Do not cache FTP responses sent through HTTP proxy.
197 // Do not send HTTP auth data because this is really FTP.
198 request_->set_load_flags(request_->load_flags() | 197 request_->set_load_flags(request_->load_flags() |
199 LOAD_DISABLE_CACHE | 198 LOAD_DISABLE_CACHE |
200 LOAD_DO_NOT_SAVE_COOKIES | 199 LOAD_DO_NOT_SAVE_COOKIES |
201 LOAD_DO_NOT_SEND_AUTH_DATA |
202 LOAD_DO_NOT_SEND_COOKIES); 200 LOAD_DO_NOT_SEND_COOKIES);
203 201
204 http_request_info_.url = request_->url(); 202 http_request_info_.url = request_->url();
205 http_request_info_.method = request_->method(); 203 http_request_info_.method = request_->method();
206 http_request_info_.load_flags = request_->load_flags(); 204 http_request_info_.load_flags = request_->load_flags();
207 http_request_info_.request_id = request_->identifier(); 205 http_request_info_.request_id = request_->identifier();
208 206
209 int rv = request_->context()->http_transaction_factory()->CreateTransaction( 207 int rv = request_->context()->http_transaction_factory()->CreateTransaction(
210 priority_, &http_transaction_, NULL); 208 priority_, &http_transaction_, NULL);
211 if (rv == OK) { 209 if (rv == OK) {
(...skipping 16 matching lines...) Expand all
228 226
229 // Note that ftp_transaction_ may be NULL due to a creation failure. 227 // Note that ftp_transaction_ may be NULL due to a creation failure.
230 if (ftp_transaction_) { 228 if (ftp_transaction_) {
231 // FTP obviously doesn't have HTTP Content-Length header. We have to pass 229 // FTP obviously doesn't have HTTP Content-Length header. We have to pass
232 // the content size information manually. 230 // the content size information manually.
233 set_expected_content_size( 231 set_expected_content_size(
234 ftp_transaction_->GetResponseInfo()->expected_content_size); 232 ftp_transaction_->GetResponseInfo()->expected_content_size);
235 } 233 }
236 234
237 if (result == OK) { 235 if (result == OK) {
238 if (http_transaction_) 236 if (http_transaction_) {
239 response_info_ = http_transaction_->GetResponseInfo(); 237 http_response_info_ = http_transaction_->GetResponseInfo();
238
239 if (http_response_info_->headers->response_code() == 401 ||
240 http_response_info_->headers->response_code() == 407) {
241 HandleAuthNeededResponse();
242 return;
243 }
244 }
240 NotifyHeadersComplete(); 245 NotifyHeadersComplete();
241 } else if (ftp_transaction_ && 246 } else if (ftp_transaction_ &&
242 ftp_transaction_->GetResponseInfo()->needs_auth) { 247 ftp_transaction_->GetResponseInfo()->needs_auth) {
243 GURL origin = request_->url().GetOrigin(); 248 HandleAuthNeededResponse();
244 if (server_auth_ && server_auth_->state == AUTH_STATE_HAVE_AUTH) { 249 return;
245 ftp_auth_cache_->Remove(origin, server_auth_->credentials);
246 } else if (!server_auth_) {
247 server_auth_ = new AuthData();
248 }
249 server_auth_->state = AUTH_STATE_NEED_AUTH;
250
251 FtpAuthCache::Entry* cached_auth = ftp_auth_cache_->Lookup(origin);
252 if (cached_auth) {
253 // Retry using cached auth data.
254 SetAuth(cached_auth->credentials);
255 } else {
256 // Prompt for a username/password.
257 NotifyHeadersComplete();
258 }
259 } else { 250 } else {
260 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result)); 251 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result));
261 } 252 }
262 } 253 }
263 254
264 void URLRequestFtpJob::OnStartCompletedAsync(int result) { 255 void URLRequestFtpJob::OnStartCompletedAsync(int result) {
265 MessageLoop::current()->PostTask( 256 MessageLoop::current()->PostTask(
266 FROM_HERE, 257 FROM_HERE,
267 base::Bind(&URLRequestFtpJob::OnStartCompleted, 258 base::Bind(&URLRequestFtpJob::OnStartCompleted,
268 weak_factory_.GetWeakPtr(), result)); 259 weak_factory_.GetWeakPtr(), result));
269 } 260 }
270 261
271 void URLRequestFtpJob::OnReadCompleted(int result) { 262 void URLRequestFtpJob::OnReadCompleted(int result) {
272 read_in_progress_ = false; 263 read_in_progress_ = false;
273 if (result == 0) { 264 if (result == 0) {
274 NotifyDone(URLRequestStatus()); 265 NotifyDone(URLRequestStatus());
275 } else if (result < 0) { 266 } else if (result < 0) {
276 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result)); 267 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result));
277 } else { 268 } else {
278 // Clear the IO_PENDING status 269 // Clear the IO_PENDING status
279 SetStatus(URLRequestStatus()); 270 SetStatus(URLRequestStatus());
280 } 271 }
281 NotifyReadComplete(result); 272 NotifyReadComplete(result);
282 } 273 }
283 274
284 void URLRequestFtpJob::RestartTransactionWithAuth() { 275 void URLRequestFtpJob::RestartTransactionWithAuth() {
285 DCHECK(ftp_transaction_); 276 DCHECK(auth_data_ && auth_data_->state == AUTH_STATE_HAVE_AUTH);
286 DCHECK(server_auth_ && server_auth_->state == AUTH_STATE_HAVE_AUTH);
287 277
288 // No matter what, we want to report our status as IO pending since we will 278 // No matter what, we want to report our status as IO pending since we will
289 // be notifying our consumer asynchronously via OnStartCompleted. 279 // be notifying our consumer asynchronously via OnStartCompleted.
290 SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); 280 SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
291 281
292 int rv = ftp_transaction_->RestartWithAuth( 282 int rv;
293 server_auth_->credentials, 283 if (proxy_info_.is_direct()) {
294 base::Bind(&URLRequestFtpJob::OnStartCompleted, 284 rv = ftp_transaction_->RestartWithAuth(
295 base::Unretained(this))); 285 auth_data_->credentials,
286 base::Bind(&URLRequestFtpJob::OnStartCompleted,
287 base::Unretained(this)));
288 } else {
289 rv = http_transaction_->RestartWithAuth(
290 auth_data_->credentials,
291 base::Bind(&URLRequestFtpJob::OnStartCompleted,
292 base::Unretained(this)));
293 }
296 if (rv == ERR_IO_PENDING) 294 if (rv == ERR_IO_PENDING)
297 return; 295 return;
298 296
299 OnStartCompletedAsync(rv); 297 OnStartCompletedAsync(rv);
300 } 298 }
301 299
302 LoadState URLRequestFtpJob::GetLoadState() const { 300 LoadState URLRequestFtpJob::GetLoadState() const {
303 if (proxy_info_.is_direct()) { 301 if (proxy_info_.is_direct()) {
304 return ftp_transaction_ ? 302 return ftp_transaction_ ?
305 ftp_transaction_->GetLoadState() : LOAD_STATE_IDLE; 303 ftp_transaction_->GetLoadState() : LOAD_STATE_IDLE;
306 } else { 304 } else {
307 return http_transaction_ ? 305 return http_transaction_ ?
308 http_transaction_->GetLoadState() : LOAD_STATE_IDLE; 306 http_transaction_->GetLoadState() : LOAD_STATE_IDLE;
309 } 307 }
310 } 308 }
311 309
312 bool URLRequestFtpJob::NeedsAuth() { 310 bool URLRequestFtpJob::NeedsAuth() {
313 // TODO(phajdan.jr): Implement proxy auth, http://crbug.com/171497 . 311 return auth_data_ && auth_data_->state == AUTH_STATE_NEED_AUTH;
314 if (!ftp_transaction_)
315 return false;
316
317 // Note that we only have to worry about cases where an actual FTP server
318 // requires auth (and not a proxy), because connecting to FTP via proxy
319 // effectively means the browser communicates via HTTP, and uses HTTP's
320 // Proxy-Authenticate protocol when proxy servers require auth.
321 return server_auth_ && server_auth_->state == AUTH_STATE_NEED_AUTH;
322 } 312 }
323 313
324 void URLRequestFtpJob::GetAuthChallengeInfo( 314 void URLRequestFtpJob::GetAuthChallengeInfo(
325 scoped_refptr<AuthChallengeInfo>* result) { 315 scoped_refptr<AuthChallengeInfo>* result) {
326 DCHECK((server_auth_ != NULL) && 316 DCHECK(NeedsAuth());
327 (server_auth_->state == AUTH_STATE_NEED_AUTH)); 317
318 if (http_response_info_) {
319 *result = http_response_info_->auth_challenge;
320 return;
321 }
322
328 scoped_refptr<AuthChallengeInfo> auth_info(new AuthChallengeInfo); 323 scoped_refptr<AuthChallengeInfo> auth_info(new AuthChallengeInfo);
329 auth_info->is_proxy = false; 324 auth_info->is_proxy = false;
330 auth_info->challenger = HostPortPair::FromURL(request_->url()); 325 auth_info->challenger = HostPortPair::FromURL(request_->url());
331 // scheme and realm are kept empty. 326 // scheme and realm are kept empty.
332 DCHECK(auth_info->scheme.empty()); 327 DCHECK(auth_info->scheme.empty());
333 DCHECK(auth_info->realm.empty()); 328 DCHECK(auth_info->realm.empty());
334 result->swap(auth_info); 329 result->swap(auth_info);
335 } 330 }
336 331
337 void URLRequestFtpJob::SetAuth(const AuthCredentials& credentials) { 332 void URLRequestFtpJob::SetAuth(const AuthCredentials& credentials) {
338 DCHECK(ftp_transaction_); 333 DCHECK(ftp_transaction_ || http_transaction_);
339 DCHECK(NeedsAuth()); 334 DCHECK(NeedsAuth());
340 server_auth_->state = AUTH_STATE_HAVE_AUTH;
341 server_auth_->credentials = credentials;
342 335
343 ftp_auth_cache_->Add(request_->url().GetOrigin(), server_auth_->credentials); 336 auth_data_->state = AUTH_STATE_HAVE_AUTH;
337 auth_data_->credentials = credentials;
338
339 if (ftp_transaction_) {
340 ftp_auth_cache_->Add(request_->url().GetOrigin(),
341 auth_data_->credentials);
342 }
344 343
345 RestartTransactionWithAuth(); 344 RestartTransactionWithAuth();
346 } 345 }
347 346
348 void URLRequestFtpJob::CancelAuth() { 347 void URLRequestFtpJob::CancelAuth() {
349 DCHECK(ftp_transaction_); 348 DCHECK(ftp_transaction_ || http_transaction_);
350 DCHECK(NeedsAuth()); 349 DCHECK(NeedsAuth());
351 server_auth_->state = AUTH_STATE_CANCELED; 350
351 auth_data_->state = AUTH_STATE_CANCELED;
352 352
353 // Once the auth is cancelled, we proceed with the request as though 353 // Once the auth is cancelled, we proceed with the request as though
354 // there were no auth. Schedule this for later so that we don't cause 354 // there were no auth. Schedule this for later so that we don't cause
355 // any recursing into the caller as a result of this call. 355 // any recursing into the caller as a result of this call.
356 OnStartCompletedAsync(OK); 356 OnStartCompletedAsync(OK);
357 } 357 }
358 358
359 UploadProgress URLRequestFtpJob::GetUploadProgress() const { 359 UploadProgress URLRequestFtpJob::GetUploadProgress() const {
360 return UploadProgress(); 360 return UploadProgress();
361 } 361 }
(...skipping 23 matching lines...) Expand all
385 385
386 if (rv == ERR_IO_PENDING) { 386 if (rv == ERR_IO_PENDING) {
387 read_in_progress_ = true; 387 read_in_progress_ = true;
388 SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); 388 SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
389 } else { 389 } else {
390 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv)); 390 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv));
391 } 391 }
392 return false; 392 return false;
393 } 393 }
394 394
395 void URLRequestFtpJob::HandleAuthNeededResponse() {
396 GURL origin = request_->url().GetOrigin();
397
398 if (auth_data_) {
399 if (auth_data_->state == AUTH_STATE_CANCELED) {
400 NotifyHeadersComplete();
401 return;
402 }
403
404 if (ftp_transaction_ && auth_data_->state == AUTH_STATE_HAVE_AUTH)
405 ftp_auth_cache_->Remove(origin, auth_data_->credentials);
406 } else {
407 auth_data_ = new AuthData;
408 }
409 auth_data_->state = AUTH_STATE_NEED_AUTH;
410
411 FtpAuthCache::Entry* cached_auth = NULL;
412 if (ftp_transaction_ && ftp_transaction_->GetResponseInfo()->needs_auth)
413 cached_auth = ftp_auth_cache_->Lookup(origin);
414 if (cached_auth) {
415 // Retry using cached auth data.
416 SetAuth(cached_auth->credentials);
417 } else {
418 // Prompt for a username/password.
419 NotifyHeadersComplete();
420 }
421 }
422
395 } // namespace net 423 } // namespace net
OLDNEW
« no previous file with comments | « net/url_request/url_request_ftp_job.h ('k') | net/url_request/url_request_ftp_job_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698