// 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/location.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
#include "base/thread_task_runner_handle.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::ThreadTaskRunnerHandle::Get()->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 {
  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) {
  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
