url_request_ftp_job.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_ftp_job.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/message_loop.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/utf_string_conversions.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/auth.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/host_port_pair.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/load_flags.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/ftp/ftp_response_info.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/ftp/ftp_transaction_factory.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/http/http_response_headers.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/http/http_transaction_factory.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_context.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_error_job.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)URLRequestFtpJob::URLRequestFtpJob(
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    URLRequest* request,
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NetworkDelegate* network_delegate,
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FtpTransactionFactory* ftp_transaction_factory,
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FtpAuthCache* ftp_auth_cache)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : URLRequestJob(request, network_delegate),
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      priority_(DEFAULT_PRIORITY),
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      proxy_service_(request_->context()->proxy_service()),
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pac_request_(NULL),
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      http_response_info_(NULL),
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      read_in_progress_(false),
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_factory_(this),
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ftp_transaction_factory_(ftp_transaction_factory),
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ftp_auth_cache_(ftp_auth_cache) {
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(proxy_service_);
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(ftp_transaction_factory);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(ftp_auth_cache);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)URLRequestFtpJob::~URLRequestFtpJob() {
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (pac_request_)
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    proxy_service_->CancelPacRequest(pac_request_);
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)URLRequestJob* URLRequestFtpJob::Factory(URLRequest* request,
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         NetworkDelegate* network_delegate,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         const std::string& scheme) {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(scheme, "ftp");
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int port = request->url().IntPort();
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request->url().has_port() &&
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !IsPortAllowedByFtp(port) && !IsPortAllowedByOverride(port)) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new URLRequestErrorJob(request,
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  network_delegate,
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  ERR_UNSAFE_PORT);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new URLRequestFtpJob(request,
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              network_delegate,
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              request->context()->ftp_transaction_factory(),
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              request->context()->ftp_auth_cache());
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool URLRequestFtpJob::IsSafeRedirect(const GURL& location) {
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Disallow all redirects.
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool URLRequestFtpJob::GetMimeType(std::string* mime_type) const {
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (proxy_info_.is_direct()) {
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (ftp_transaction_->GetResponseInfo()->is_directory_listing) {
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *mime_type = "text/vnd.chromium.ftp-dir";
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // No special handling of MIME type is needed. As opposed to direct FTP
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // transaction, we do not get a raw directory listing to parse.
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return http_transaction_->GetResponseInfo()->
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        headers->GetMimeType(mime_type);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void URLRequestFtpJob::GetResponseInfo(HttpResponseInfo* info) {
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (http_response_info_)
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *info = *http_response_info_;
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HostPortPair URLRequestFtpJob::GetSocketAddress() const {
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (proxy_info_.is_direct()) {
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!ftp_transaction_)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return HostPortPair();
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return ftp_transaction_->GetResponseInfo()->socket_address;
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!http_transaction_)
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return HostPortPair();
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return http_transaction_->GetResponseInfo()->socket_address;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void URLRequestFtpJob::SetPriority(RequestPriority priority) {
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  priority_ = priority;
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (http_transaction_)
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    http_transaction_->SetPriority(priority);
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void URLRequestFtpJob::Start() {
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!pac_request_);
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!ftp_transaction_);
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!http_transaction_);
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int rv = OK;
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (request_->load_flags() & LOAD_BYPASS_PROXY) {
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    proxy_info_.UseDirect();
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK_EQ(request_->context()->proxy_service(), proxy_service_);
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    rv = proxy_service_->ResolveProxy(
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        request_->url(),
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &proxy_info_,
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&URLRequestFtpJob::OnResolveProxyComplete,
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   base::Unretained(this)),
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &pac_request_,
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        request_->net_log());
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (rv == ERR_IO_PENDING)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnResolveProxyComplete(rv);
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void URLRequestFtpJob::Kill() {
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (ftp_transaction_)
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ftp_transaction_.reset();
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (http_transaction_)
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    http_transaction_.reset();
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  URLRequestJob::Kill();
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  weak_factory_.InvalidateWeakPtrs();
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void URLRequestFtpJob::OnResolveProxyComplete(int result) {
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pac_request_ = NULL;
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (result != OK) {
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    OnStartCompletedAsync(result);
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Remove unsupported proxies from the list.
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  proxy_info_.RemoveProxiesWithoutScheme(
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ProxyServer::SCHEME_DIRECT |
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ProxyServer::SCHEME_HTTP |
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ProxyServer::SCHEME_HTTPS);
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(phajdan.jr): Implement proxy fallback, http://crbug.com/171495 .
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (proxy_info_.is_direct())
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    StartFtpTransaction();
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else if (proxy_info_.is_http() || proxy_info_.is_https())
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    StartHttpTransaction();
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    OnStartCompletedAsync(ERR_NO_SUPPORTED_PROXIES);
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void URLRequestFtpJob::StartFtpTransaction() {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a transaction.
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!ftp_transaction_);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ftp_request_info_.url = request_->url();
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ftp_transaction_.reset(ftp_transaction_factory_->CreateTransaction());
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No matter what, we want to report our status as IO pending since we will
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // be notifying our consumer asynchronously via OnStartCompleted.
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (ftp_transaction_) {
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rv = ftp_transaction_->Start(
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &ftp_request_info_,
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&URLRequestFtpJob::OnStartCompleted,
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   base::Unretained(this)),
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        request_->net_log());
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == ERR_IO_PENDING)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ERR_FAILED;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The transaction started synchronously, but we need to notify the
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // URLRequest delegate via the message loop.
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnStartCompletedAsync(rv);
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void URLRequestFtpJob::StartHttpTransaction() {
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create a transaction.
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!http_transaction_);
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Do not cache FTP responses sent through HTTP proxy.
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request_->set_load_flags(request_->load_flags() |
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           LOAD_DISABLE_CACHE |
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           LOAD_DO_NOT_SAVE_COOKIES |
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           LOAD_DO_NOT_SEND_COOKIES);
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  http_request_info_.url = request_->url();
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  http_request_info_.method = request_->method();
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  http_request_info_.load_flags = request_->load_flags();
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  http_request_info_.request_id = request_->identifier();
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int rv = request_->context()->http_transaction_factory()->CreateTransaction(
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      priority_, &http_transaction_, NULL);
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (rv == OK) {
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rv = http_transaction_->Start(
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &http_request_info_,
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&URLRequestFtpJob::OnStartCompleted,
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   base::Unretained(this)),
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        request_->net_log());
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (rv == ERR_IO_PENDING)
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The transaction started synchronously, but we need to notify the
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // URLRequest delegate via the message loop.
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnStartCompletedAsync(rv);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLRequestFtpJob::OnStartCompleted(int result) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Clear the IO_PENDING status
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStatus(URLRequestStatus());
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Note that ftp_transaction_ may be NULL due to a creation failure.
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (ftp_transaction_) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // FTP obviously doesn't have HTTP Content-Length header. We have to pass
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the content size information manually.
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    set_expected_content_size(
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ftp_transaction_->GetResponseInfo()->expected_content_size);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == OK) {
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (http_transaction_) {
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      http_response_info_ = http_transaction_->GetResponseInfo();
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (http_response_info_->headers->response_code() == 401 ||
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          http_response_info_->headers->response_code() == 407) {
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        HandleAuthNeededResponse();
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return;
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyHeadersComplete();
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (ftp_transaction_ &&
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             ftp_transaction_->GetResponseInfo()->needs_auth) {
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    HandleAuthNeededResponse();
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result));
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void URLRequestFtpJob::OnStartCompletedAsync(int result) {
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MessageLoop::current()->PostTask(
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&URLRequestFtpJob::OnStartCompleted,
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 weak_factory_.GetWeakPtr(), result));
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLRequestFtpJob::OnReadCompleted(int result) {
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_in_progress_ = false;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == 0) {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyDone(URLRequestStatus());
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (result < 0) {
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result));
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Clear the IO_PENDING status
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetStatus(URLRequestStatus());
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NotifyReadComplete(result);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLRequestFtpJob::RestartTransactionWithAuth() {
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(auth_data_ && auth_data_->state == AUTH_STATE_HAVE_AUTH);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No matter what, we want to report our status as IO pending since we will
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // be notifying our consumer asynchronously via OnStartCompleted.
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int rv;
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (proxy_info_.is_direct()) {
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    rv = ftp_transaction_->RestartWithAuth(
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        auth_data_->credentials,
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::Bind(&URLRequestFtpJob::OnStartCompleted,
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   base::Unretained(this)));
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    rv = http_transaction_->RestartWithAuth(
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        auth_data_->credentials,
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::Bind(&URLRequestFtpJob::OnStartCompleted,
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   base::Unretained(this)));
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnStartCompletedAsync(rv);
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LoadState URLRequestFtpJob::GetLoadState() const {
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (proxy_info_.is_direct()) {
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return ftp_transaction_ ?
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ftp_transaction_->GetLoadState() : LOAD_STATE_IDLE;
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return http_transaction_ ?
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        http_transaction_->GetLoadState() : LOAD_STATE_IDLE;
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool URLRequestFtpJob::NeedsAuth() {
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return auth_data_ && auth_data_->state == AUTH_STATE_NEED_AUTH;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLRequestFtpJob::GetAuthChallengeInfo(
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<AuthChallengeInfo>* result) {
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(NeedsAuth());
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (http_response_info_) {
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *result = http_response_info_->auth_challenge;
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<AuthChallengeInfo> auth_info(new AuthChallengeInfo);
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  auth_info->is_proxy = false;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  auth_info->challenger = HostPortPair::FromURL(request_->url());
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // scheme and realm are kept empty.
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(auth_info->scheme.empty());
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(auth_info->realm.empty());
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->swap(auth_info);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLRequestFtpJob::SetAuth(const AuthCredentials& credentials) {
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(ftp_transaction_ || http_transaction_);
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(NeedsAuth());
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  auth_data_->state = AUTH_STATE_HAVE_AUTH;
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  auth_data_->credentials = credentials;
341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (ftp_transaction_) {
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ftp_auth_cache_->Add(request_->url().GetOrigin(),
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                         auth_data_->credentials);
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RestartTransactionWithAuth();
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void URLRequestFtpJob::CancelAuth() {
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(ftp_transaction_ || http_transaction_);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(NeedsAuth());
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  auth_data_->state = AUTH_STATE_CANCELED;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Once the auth is cancelled, we proceed with the request as though
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // there were no auth.  Schedule this for later so that we don't cause
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // any recursing into the caller as a result of this call.
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnStartCompletedAsync(OK);
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UploadProgress URLRequestFtpJob::GetUploadProgress() const {
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return UploadProgress();
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool URLRequestFtpJob::ReadRawData(IOBuffer* buf,
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   int buf_size,
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   int *bytes_read) {
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(buf_size, 0);
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(bytes_read);
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!read_in_progress_);
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int rv;
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (proxy_info_.is_direct()) {
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rv = ftp_transaction_->Read(buf, buf_size,
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                base::Bind(&URLRequestFtpJob::OnReadCompleted,
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           base::Unretained(this)));
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rv = http_transaction_->Read(buf, buf_size,
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 base::Bind(&URLRequestFtpJob::OnReadCompleted,
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                            base::Unretained(this)));
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv >= 0) {
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *bytes_read = rv;
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING) {
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    read_in_progress_ = true;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv));
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void URLRequestFtpJob::HandleAuthNeededResponse() {
399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GURL origin = request_->url().GetOrigin();
400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (auth_data_) {
402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (auth_data_->state == AUTH_STATE_CANCELED) {
403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      NotifyHeadersComplete();
404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return;
405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (ftp_transaction_ && auth_data_->state == AUTH_STATE_HAVE_AUTH)
408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ftp_auth_cache_->Remove(origin, auth_data_->credentials);
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    auth_data_ = new AuthData;
411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  auth_data_->state = AUTH_STATE_NEED_AUTH;
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  FtpAuthCache::Entry* cached_auth = NULL;
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (ftp_transaction_ && ftp_transaction_->GetResponseInfo()->needs_auth)
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    cached_auth = ftp_auth_cache_->Lookup(origin);
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (cached_auth) {
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Retry using cached auth data.
419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SetAuth(cached_auth->credentials);
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Prompt for a username/password.
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    NotifyHeadersComplete();
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
427