// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/url_request/url_request_ftp_job.h"

#include "base/compiler_specific.h"
#include "base/message_loop/message_loop.h"
#include "base/profiler/scoped_tracker.h"
#include "base/strings/utf_string_conversions.h"
#include "net/base/auth.h"
#include "net/base/host_port_pair.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/base/net_util.h"
#include "net/ftp/ftp_auth_cache.h"
#include "net/ftp/ftp_response_info.h"
#include "net/ftp/ftp_transaction_factory.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_transaction_factory.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_error_job.h"

namespace net {

URLRequestFtpJob::URLRequestFtpJob(
    URLRequest* request,
    NetworkDelegate* network_delegate,
    FtpTransactionFactory* ftp_transaction_factory,
    FtpAuthCache* ftp_auth_cache)
    : URLRequestJob(request, network_delegate),
      priority_(DEFAULT_PRIORITY),
      proxy_service_(request_->context()->proxy_service()),
      pac_request_(NULL),
      http_response_info_(NULL),
      read_in_progress_(false),
      ftp_transaction_factory_(ftp_transaction_factory),
      ftp_auth_cache_(ftp_auth_cache),
      weak_factory_(this) {
  DCHECK(proxy_service_);
  DCHECK(ftp_transaction_factory);
  DCHECK(ftp_auth_cache);
}

URLRequestFtpJob::~URLRequestFtpJob() {
  if (pac_request_)
    proxy_service_->CancelPacRequest(pac_request_);
}

bool URLRequestFtpJob::IsSafeRedirect(const GURL& location) {
  // Disallow all redirects.
  return false;
}

bool URLRequestFtpJob::GetMimeType(std::string* mime_type) const {
  if (proxy_info_.is_direct()) {
    if (ftp_transaction_->GetResponseInfo()->is_directory_listing) {
      *mime_type = "text/vnd.chromium.ftp-dir";
      return true;
    }
  } else {
    // No special handling of MIME type is needed. As opposed to direct FTP
    // transaction, we do not get a raw directory listing to parse.
    return http_transaction_->GetResponseInfo()->
        headers->GetMimeType(mime_type);
  }
  return false;
}

void URLRequestFtpJob::GetResponseInfo(HttpResponseInfo* info) {
  if (http_response_info_)
    *info = *http_response_info_;
}

HostPortPair URLRequestFtpJob::GetSocketAddress() const {
  if (proxy_info_.is_direct()) {
    if (!ftp_transaction_)
      return HostPortPair();
    return ftp_transaction_->GetResponseInfo()->socket_address;
  } else {
    if (!http_transaction_)
      return HostPortPair();
    return http_transaction_->GetResponseInfo()->socket_address;
  }
}

void URLRequestFtpJob::SetPriority(RequestPriority priority) {
  priority_ = priority;
  if (http_transaction_)
    http_transaction_->SetPriority(priority);
}

void URLRequestFtpJob::Start() {
  DCHECK(!pac_request_);
  DCHECK(!ftp_transaction_);
  DCHECK(!http_transaction_);

  int rv = OK;
  if (request_->load_flags() & LOAD_BYPASS_PROXY) {
    proxy_info_.UseDirect();
  } else {
    DCHECK_EQ(request_->context()->proxy_service(), proxy_service_);
    rv = proxy_service_->ResolveProxy(
        request_->url(),
        request_->load_flags(),
        &proxy_info_,
        base::Bind(&URLRequestFtpJob::OnResolveProxyComplete,
                   base::Unretained(this)),
        &pac_request_,
        NULL,
        request_->net_log());

    if (rv == ERR_IO_PENDING)
      return;
  }
  OnResolveProxyComplete(rv);
}

void URLRequestFtpJob::Kill() {
  if (ftp_transaction_)
    ftp_transaction_.reset();
  if (http_transaction_)
    http_transaction_.reset();
  URLRequestJob::Kill();
  weak_factory_.InvalidateWeakPtrs();
}

void URLRequestFtpJob::OnResolveProxyComplete(int result) {
  pac_request_ = NULL;

  if (result != OK) {
    OnStartCompletedAsync(result);
    return;
  }

  // Remove unsupported proxies from the list.
  proxy_info_.RemoveProxiesWithoutScheme(
      ProxyServer::SCHEME_DIRECT |
      ProxyServer::SCHEME_HTTP |
      ProxyServer::SCHEME_HTTPS);

  // TODO(phajdan.jr): Implement proxy fallback, http://crbug.com/171495 .
  if (proxy_info_.is_direct())
    StartFtpTransaction();
  else if (proxy_info_.is_http() || proxy_info_.is_https())
    StartHttpTransaction();
  else
    OnStartCompletedAsync(ERR_NO_SUPPORTED_PROXIES);
}

void URLRequestFtpJob::StartFtpTransaction() {
  // Create a transaction.
  DCHECK(!ftp_transaction_);

  ftp_request_info_.url = request_->url();
  ftp_transaction_.reset(ftp_transaction_factory_->CreateTransaction());

  // No matter what, we want to report our status as IO pending since we will
  // be notifying our consumer asynchronously via OnStartCompleted.
  SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
  int rv;
  if (ftp_transaction_) {
    rv = ftp_transaction_->Start(
        &ftp_request_info_,
        base::Bind(&URLRequestFtpJob::OnStartCompleted,
                   base::Unretained(this)),
        request_->net_log());
    if (rv == ERR_IO_PENDING)
      return;
  } else {
    rv = ERR_FAILED;
  }
  // The transaction started synchronously, but we need to notify the
  // URLRequest delegate via the message loop.
  OnStartCompletedAsync(rv);
}

void URLRequestFtpJob::StartHttpTransaction() {
  // Create a transaction.
  DCHECK(!http_transaction_);

  // Do not cache FTP responses sent through HTTP proxy.
  request_->SetLoadFlags(request_->load_flags() |
                         LOAD_DISABLE_CACHE |
                         LOAD_DO_NOT_SAVE_COOKIES |
                         LOAD_DO_NOT_SEND_COOKIES);

  http_request_info_.url = request_->url();
  http_request_info_.method = request_->method();
  http_request_info_.load_flags = request_->load_flags();

  int rv = request_->context()->http_transaction_factory()->CreateTransaction(
      priority_, &http_transaction_);
  if (rv == OK) {
    rv = http_transaction_->Start(
        &http_request_info_,
        base::Bind(&URLRequestFtpJob::OnStartCompleted,
                  base::Unretained(this)),
        request_->net_log());
    if (rv == ERR_IO_PENDING)
      return;
  }
  // The transaction started synchronously, but we need to notify the
  // URLRequest delegate via the message loop.
  OnStartCompletedAsync(rv);
}

void URLRequestFtpJob::OnStartCompleted(int result) {
  // Clear the IO_PENDING status
  SetStatus(URLRequestStatus());

  // Note that ftp_transaction_ may be NULL due to a creation failure.
  if (ftp_transaction_) {
    // FTP obviously doesn't have HTTP Content-Length header. We have to pass
    // the content size information manually.
    set_expected_content_size(
        ftp_transaction_->GetResponseInfo()->expected_content_size);
  }

  if (result == OK) {
    if (http_transaction_) {
      http_response_info_ = http_transaction_->GetResponseInfo();
      SetProxyServer(http_response_info_->proxy_server);

      if (http_response_info_->headers->response_code() == 401 ||
          http_response_info_->headers->response_code() == 407) {
        HandleAuthNeededResponse();
        return;
      }
    }
    NotifyHeadersComplete();
  } else if (ftp_transaction_ &&
             ftp_transaction_->GetResponseInfo()->needs_auth) {
    HandleAuthNeededResponse();
    return;
  } else {
    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result));
  }
}

void URLRequestFtpJob::OnStartCompletedAsync(int result) {
  base::MessageLoop::current()->PostTask(
      FROM_HERE,
      base::Bind(&URLRequestFtpJob::OnStartCompleted,
                 weak_factory_.GetWeakPtr(), result));
}

void URLRequestFtpJob::OnReadCompleted(int result) {
  read_in_progress_ = false;
  if (result == 0) {
    NotifyDone(URLRequestStatus());
  } else if (result < 0) {
    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result));
  } else {
    // Clear the IO_PENDING status
    SetStatus(URLRequestStatus());
  }
  NotifyReadComplete(result);
}

void URLRequestFtpJob::RestartTransactionWithAuth() {
  DCHECK(auth_data_.get() && auth_data_->state == AUTH_STATE_HAVE_AUTH);

  // No matter what, we want to report our status as IO pending since we will
  // be notifying our consumer asynchronously via OnStartCompleted.
  SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));

  int rv;
  if (proxy_info_.is_direct()) {
    rv = ftp_transaction_->RestartWithAuth(
        auth_data_->credentials,
        base::Bind(&URLRequestFtpJob::OnStartCompleted,
                   base::Unretained(this)));
  } else {
    rv = http_transaction_->RestartWithAuth(
        auth_data_->credentials,
        base::Bind(&URLRequestFtpJob::OnStartCompleted,
                   base::Unretained(this)));
  }
  if (rv == ERR_IO_PENDING)
    return;

  OnStartCompletedAsync(rv);
}

LoadState URLRequestFtpJob::GetLoadState() const {
  // TODO(pkasting): Remove ScopedTracker below once crbug.com/455952 is
  // fixed.
  tracked_objects::ScopedTracker tracking_profile(
      FROM_HERE_WITH_EXPLICIT_FUNCTION(
          "455952 URLRequestFtpJob::GetLoadState"));
  if (proxy_info_.is_direct()) {
    return ftp_transaction_ ?
        ftp_transaction_->GetLoadState() : LOAD_STATE_IDLE;
  } else {
    return http_transaction_ ?
        http_transaction_->GetLoadState() : LOAD_STATE_IDLE;
  }
}

bool URLRequestFtpJob::NeedsAuth() {
  return auth_data_.get() && auth_data_->state == AUTH_STATE_NEED_AUTH;
}

void URLRequestFtpJob::GetAuthChallengeInfo(
    scoped_refptr<AuthChallengeInfo>* result) {
  DCHECK(NeedsAuth());

  if (http_response_info_) {
    *result = http_response_info_->auth_challenge;
    return;
  }

  scoped_refptr<AuthChallengeInfo> auth_info(new AuthChallengeInfo);
  auth_info->is_proxy = false;
  auth_info->challenger = HostPortPair::FromURL(request_->url());
  // scheme and realm are kept empty.
  DCHECK(auth_info->scheme.empty());
  DCHECK(auth_info->realm.empty());
  result->swap(auth_info);
}

void URLRequestFtpJob::SetAuth(const AuthCredentials& credentials) {
  DCHECK(ftp_transaction_ || http_transaction_);
  DCHECK(NeedsAuth());

  auth_data_->state = AUTH_STATE_HAVE_AUTH;
  auth_data_->credentials = credentials;

  if (ftp_transaction_) {
    ftp_auth_cache_->Add(request_->url().GetOrigin(),
                         auth_data_->credentials);
  }

  RestartTransactionWithAuth();
}

void URLRequestFtpJob::CancelAuth() {
  DCHECK(ftp_transaction_ || http_transaction_);
  DCHECK(NeedsAuth());

  auth_data_->state = AUTH_STATE_CANCELED;

  // Once the auth is cancelled, we proceed with the request as though
  // there were no auth.  Schedule this for later so that we don't cause
  // any recursing into the caller as a result of this call.
  OnStartCompletedAsync(OK);
}

UploadProgress URLRequestFtpJob::GetUploadProgress() const {
  return UploadProgress();
}

bool URLRequestFtpJob::ReadRawData(IOBuffer* buf,
                                   int buf_size,
                                   int *bytes_read) {
  // TODO(vadimt): Remove ScopedTracker below once crbug.com/423948 is fixed.
  tracked_objects::ScopedTracker tracking_profile(
      FROM_HERE_WITH_EXPLICIT_FUNCTION("423948 URLRequestFtpJob::ReadRawData"));

  DCHECK_NE(buf_size, 0);
  DCHECK(bytes_read);
  DCHECK(!read_in_progress_);

  int rv;
  if (proxy_info_.is_direct()) {
    rv = ftp_transaction_->Read(buf, buf_size,
                                base::Bind(&URLRequestFtpJob::OnReadCompleted,
                                           base::Unretained(this)));
  } else {
    rv = http_transaction_->Read(buf, buf_size,
                                 base::Bind(&URLRequestFtpJob::OnReadCompleted,
                                            base::Unretained(this)));
  }

  if (rv >= 0) {
    *bytes_read = rv;
    return true;
  }

  if (rv == ERR_IO_PENDING) {
    read_in_progress_ = true;
    SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
  } else {
    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv));
  }
  return false;
}

void URLRequestFtpJob::HandleAuthNeededResponse() {
  GURL origin = request_->url().GetOrigin();

  if (auth_data_.get()) {
    if (auth_data_->state == AUTH_STATE_CANCELED) {
      NotifyHeadersComplete();
      return;
    }

    if (ftp_transaction_ && auth_data_->state == AUTH_STATE_HAVE_AUTH)
      ftp_auth_cache_->Remove(origin, auth_data_->credentials);
  } else {
    auth_data_ = new AuthData;
  }
  auth_data_->state = AUTH_STATE_NEED_AUTH;

  FtpAuthCache::Entry* cached_auth = NULL;
  if (ftp_transaction_ && ftp_transaction_->GetResponseInfo()->needs_auth)
    cached_auth = ftp_auth_cache_->Lookup(origin);
  if (cached_auth) {
    // Retry using cached auth data.
    SetAuth(cached_auth->credentials);
  } else {
    // Prompt for a username/password.
    NotifyHeadersComplete();
  }
}

}  // namespace net
