// 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_fetcher_core.h"

#include <utility>

#include "base/bind.h"
#include "base/logging.h"
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "net/base/elements_upload_data_stream.h"
#include "net/base/io_buffer.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/base/request_priority.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/upload_data_stream.h"
#include "net/base/upload_file_element_reader.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/redirect_info.h"
#include "net/url_request/url_fetcher_delegate.h"
#include "net/url_request/url_fetcher_response_writer.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "net/url_request/url_request_throttler_manager.h"
#include "starboard/time.h"
#include "starboard/types.h"
#include "url/origin.h"

namespace {

#if defined(STARBOARD)
const SbTime kInformDownloadProgressInterval = 50 * kSbTimeMillisecond;
#else   // defined(STARBOARD)
const int kBufferSize = 4096;
#endif  // defined(STARBOARD)

const int kUploadProgressTimerInterval = 100;

bool g_ignore_certificate_requests = false;

#if defined(STARBOARD)
int GetIOBufferSizeByContentSize(int content_size) {
  // If |content_size| is unknown, use 64k as buffer size.
  if (content_size < 0) {
    return 64 * 1024;
  }
  // If the content is really small, use 4k anyway.
  if (content_size <= 4 * 1024) {
    return 4 * 1024;
  }
  // If the content is medium sized, use the size as buffer size.
  if (content_size < 64 * 1024) {
    return content_size;
  }
  // If the content is fairly large, use a much larger buffer size.
  if (content_size >= 512 * 1024) {
    return 256 * 1024;
  }
  // Otherwise use 64k as buffer size.
  return 64 * 1024;
}
#endif  // defined(STARBOARD)

}  // namespace

namespace net {

// URLFetcherCore::Registry ---------------------------------------------------

URLFetcherCore::Registry::Registry() = default;
URLFetcherCore::Registry::~Registry() = default;

void URLFetcherCore::Registry::AddURLFetcherCore(URLFetcherCore* core) {
  DCHECK(!base::ContainsKey(fetchers_, core));
  fetchers_.insert(core);
}

void URLFetcherCore::Registry::RemoveURLFetcherCore(URLFetcherCore* core) {
  DCHECK(base::ContainsKey(fetchers_, core));
  fetchers_.erase(core);
}

void URLFetcherCore::Registry::CancelAll() {
  while (!fetchers_.empty())
    (*fetchers_.begin())->CancelURLRequest(ERR_ABORTED);
}

// URLFetcherCore -------------------------------------------------------------

// static
base::LazyInstance<URLFetcherCore::Registry>::DestructorAtExit
    URLFetcherCore::g_registry = LAZY_INSTANCE_INITIALIZER;

URLFetcherCore::URLFetcherCore(
    URLFetcher* fetcher,
    const GURL& original_url,
    URLFetcher::RequestType request_type,
    URLFetcherDelegate* d,
    net::NetworkTrafficAnnotationTag traffic_annotation)
    : fetcher_(fetcher),
      original_url_(original_url),
      request_type_(request_type),
      delegate_(d),
      delegate_task_runner_(base::SequencedTaskRunnerHandle::Get()),
      load_flags_(LOAD_NORMAL),
      allow_credentials_(base::nullopt),
      response_code_(URLFetcher::RESPONSE_CODE_INVALID),
#if defined(STARBOARD)
      io_buffer_size_(GetIOBufferSizeByContentSize(-1)),
#endif  // defined(STARBOARD)
      url_request_data_key_(NULL),
      was_fetched_via_proxy_(false),
      was_cached_(false),
      received_response_content_length_(0),
      total_received_bytes_(0),
      upload_content_set_(false),
      upload_range_offset_(0),
      upload_range_length_(0),
      referrer_policy_(
          URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE),
      is_chunked_upload_(false),
      was_cancelled_(false),
      stop_on_redirect_(false),
      stopped_on_redirect_(false),
      automatically_retry_on_5xx_(true),
      num_retries_on_5xx_(0),
      max_retries_on_5xx_(0),
      num_retries_on_network_changes_(0),
      max_retries_on_network_changes_(0),
      current_upload_bytes_(-1),
      current_response_bytes_(0),
      total_response_bytes_(-1),
      traffic_annotation_(traffic_annotation) {
  CHECK(original_url_.is_valid());
  DCHECK(delegate_);

  const base::CommandLine& command_line =
      *base::CommandLine::ForCurrentProcess();
  const CobaltExtensionUrlFetcherObserverApi* observer_extension =
      static_cast<const CobaltExtensionUrlFetcherObserverApi*>(
          SbSystemGetExtension(kCobaltExtensionUrlFetcherObserverName));
  if (command_line.HasSwitch(URL_FETCHER_COMMAND_LINE_SWITCH) &&
      observer_extension &&
      strcmp(observer_extension->name,
                         kCobaltExtensionUrlFetcherObserverName) == 0 &&
      observer_extension->version >= 1) {
    observer_extension_ = observer_extension;
    observer_extension_->FetcherCreated(
        original_url_.spec()
            .substr(0, URL_FETCHER_OBSERVER_MAX_URL_SIZE)
            .c_str());
  } else {
    observer_extension_ = nullptr;
  }
}

void URLFetcherCore::Start() {
  DCHECK(delegate_task_runner_);
  DCHECK(request_context_getter_.get()) << "We need an URLRequestContext!";
  if (network_task_runner_.get()) {
    DCHECK_EQ(network_task_runner_,
              request_context_getter_->GetNetworkTaskRunner());
  } else {
    network_task_runner_ = request_context_getter_->GetNetworkTaskRunner();
  }
  DCHECK(network_task_runner_.get()) << "We need an IO task runner";

  network_task_runner_->PostTask(
      FROM_HERE, base::Bind(&URLFetcherCore::StartOnIOThread, this));
}

void URLFetcherCore::Stop() {
  if (delegate_task_runner_)  // May be NULL in tests.
    DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());

  delegate_ = NULL;
  fetcher_ = NULL;
  if (!network_task_runner_.get())
    return;
  if (network_task_runner_->RunsTasksInCurrentSequence()) {
    CancelURLRequest(ERR_ABORTED);
  } else {
    network_task_runner_->PostTask(
        FROM_HERE,
        base::Bind(&URLFetcherCore::CancelURLRequest, this, ERR_ABORTED));
  }
}

void URLFetcherCore::SetUploadData(const std::string& upload_content_type,
                                   const std::string& upload_content) {
  AssertHasNoUploadData();
  DCHECK(!is_chunked_upload_);
  DCHECK(upload_content_type_.empty());

// Cobalt manages the content type header itself.
#if !defined(STARBOARD)
  // Empty |upload_content_type| is allowed iff the |upload_content| is empty.
  DCHECK(upload_content.empty() || !upload_content_type.empty());
#endif

  upload_content_type_ = upload_content_type;
  upload_content_ = upload_content;
  upload_content_set_ = true;
}

void URLFetcherCore::SetUploadFilePath(
    const std::string& upload_content_type,
    const base::FilePath& file_path,
    uint64_t range_offset,
    uint64_t range_length,
    scoped_refptr<base::TaskRunner> file_task_runner) {
  AssertHasNoUploadData();
  DCHECK(!is_chunked_upload_);
  DCHECK_EQ(upload_range_offset_, 0ULL);
  DCHECK_EQ(upload_range_length_, 0ULL);
  DCHECK(upload_content_type_.empty());
  DCHECK(!upload_content_type.empty());

  upload_content_type_ = upload_content_type;
  upload_file_path_ = file_path;
  upload_range_offset_ = range_offset;
  upload_range_length_ = range_length;
  upload_file_task_runner_ = file_task_runner;
  upload_content_set_ = true;
}

void URLFetcherCore::SetUploadStreamFactory(
    const std::string& upload_content_type,
    const URLFetcher::CreateUploadStreamCallback& factory) {
  AssertHasNoUploadData();
  DCHECK(!is_chunked_upload_);
  DCHECK(upload_content_type_.empty());

  upload_content_type_ = upload_content_type;
  upload_stream_factory_ = factory;
  upload_content_set_ = true;
}

void URLFetcherCore::SetChunkedUpload(const std::string& content_type) {
  if (!is_chunked_upload_) {
    AssertHasNoUploadData();
    DCHECK(upload_content_type_.empty());
  }

  // Empty |content_type| is not allowed here, because it is impossible
  // to ensure non-empty upload content as it is not yet supplied.
  DCHECK(!content_type.empty());

  upload_content_type_ = content_type;
  base::STLClearObject(&upload_content_);
  is_chunked_upload_ = true;
}

void URLFetcherCore::AppendChunkToUpload(const std::string& content,
                                         bool is_last_chunk) {
  DCHECK(delegate_task_runner_);
  DCHECK(network_task_runner_.get());
  DCHECK(is_chunked_upload_);
  network_task_runner_->PostTask(
      FROM_HERE,
      base::Bind(&URLFetcherCore::CompleteAddingUploadDataChunk, this, content,
                 is_last_chunk));
}

void URLFetcherCore::SetLoadFlags(int load_flags) {
  load_flags_ = load_flags;
}

void URLFetcherCore::SetAllowCredentials(bool allow_credentials) {
  allow_credentials_ = base::make_optional<bool>(allow_credentials);
}

int URLFetcherCore::GetLoadFlags() const {
  return load_flags_;
}

void URLFetcherCore::SetReferrer(const std::string& referrer) {
  referrer_ = referrer;
}

void URLFetcherCore::SetReferrerPolicy(
    URLRequest::ReferrerPolicy referrer_policy) {
  referrer_policy_ = referrer_policy;
}

void URLFetcherCore::SetExtraRequestHeaders(
    const std::string& extra_request_headers) {
  extra_request_headers_.Clear();
  extra_request_headers_.AddHeadersFromString(extra_request_headers);
}

void URLFetcherCore::AddExtraRequestHeader(const std::string& header_line) {
  extra_request_headers_.AddHeaderFromString(header_line);
}

void URLFetcherCore::SetRequestContext(
    URLRequestContextGetter* request_context_getter) {
  DCHECK(!request_context_getter_.get());
  DCHECK(request_context_getter);
  request_context_getter_ = request_context_getter;
}

void URLFetcherCore::SetInitiator(
    const base::Optional<url::Origin>& initiator) {
  DCHECK(!initiator_.has_value());
  initiator_ = initiator;
}

void URLFetcherCore::SetURLRequestUserData(
    const void* key,
    const URLFetcher::CreateDataCallback& create_data_callback) {
  DCHECK(key);
  DCHECK(!create_data_callback.is_null());
  url_request_data_key_ = key;
  url_request_create_data_callback_ = create_data_callback;
}

void URLFetcherCore::SetStopOnRedirect(bool stop_on_redirect) {
  stop_on_redirect_ = stop_on_redirect;
}

void URLFetcherCore::SetAutomaticallyRetryOn5xx(bool retry) {
  automatically_retry_on_5xx_ = retry;
}

void URLFetcherCore::SetMaxRetriesOn5xx(int max_retries) {
  max_retries_on_5xx_ = max_retries;
}

int URLFetcherCore::GetMaxRetriesOn5xx() const {
  return max_retries_on_5xx_;
}

base::TimeDelta URLFetcherCore::GetBackoffDelay() const {
  return backoff_delay_;
}

void URLFetcherCore::SetAutomaticallyRetryOnNetworkChanges(int max_retries) {
  max_retries_on_network_changes_ = max_retries;
}

void URLFetcherCore::SaveResponseToFileAtPath(
    const base::FilePath& file_path,
    scoped_refptr<base::SequencedTaskRunner> file_task_runner) {
  DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());
  SaveResponseWithWriter(std::unique_ptr<URLFetcherResponseWriter>(
      new URLFetcherFileWriter(file_task_runner, file_path)));
}

void URLFetcherCore::SaveResponseToTemporaryFile(
    scoped_refptr<base::SequencedTaskRunner> file_task_runner) {
  DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());
  SaveResponseWithWriter(std::unique_ptr<URLFetcherResponseWriter>(
      new URLFetcherFileWriter(file_task_runner, base::FilePath())));
}

void URLFetcherCore::SaveResponseWithWriter(
    std::unique_ptr<URLFetcherResponseWriter> response_writer) {
  DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());
  response_writer_ = std::move(response_writer);
}

HttpResponseHeaders* URLFetcherCore::GetResponseHeaders() const {
  return response_headers_.get();
}

// TODO(panayiotis): socket_address_ is written in the IO thread,
// if this is accessed in the UI thread, this could result in a race.
// Same for response_headers_ above and was_fetched_via_proxy_ below.
HostPortPair URLFetcherCore::GetSocketAddress() const {
  return socket_address_;
}

const ProxyServer& URLFetcherCore::ProxyServerUsed() const {
  return proxy_server_;
}

bool URLFetcherCore::WasFetchedViaProxy() const {
  return was_fetched_via_proxy_;
}

bool URLFetcherCore::WasCached() const {
  return was_cached_;
}

int64_t URLFetcherCore::GetReceivedResponseContentLength() const {
  return received_response_content_length_;
}

int64_t URLFetcherCore::GetTotalReceivedBytes() const {
  return total_received_bytes_;
}

const GURL& URLFetcherCore::GetOriginalURL() const {
  return original_url_;
}

const GURL& URLFetcherCore::GetURL() const {
  return url_;
}

const URLRequestStatus& URLFetcherCore::GetStatus() const {
  return status_;
}

int URLFetcherCore::GetResponseCode() const {
  return response_code_;
}

void URLFetcherCore::ReceivedContentWasMalformed() {
  DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());
  if (network_task_runner_.get()) {
    network_task_runner_->PostTask(
        FROM_HERE, base::Bind(&URLFetcherCore::NotifyMalformedContent, this));
  }
}

bool URLFetcherCore::GetResponseAsString(
    std::string* out_response_string) const {
  URLFetcherStringWriter* string_writer =
      response_writer_ ? response_writer_->AsStringWriter() : NULL;
  if (!string_writer)
    return false;

  *out_response_string = string_writer->data();
  return true;
}

bool URLFetcherCore::GetResponseAsFilePath(bool take_ownership,
                                           base::FilePath* out_response_path) {
  DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());

  URLFetcherFileWriter* file_writer =
      response_writer_ ? response_writer_->AsFileWriter() : NULL;
  if (!file_writer)
    return false;

  *out_response_path = file_writer->file_path();

  if (take_ownership) {
    // Intentionally calling a file_writer_ method directly without posting
    // the task to network_task_runner_.
    //
    // This is for correctly handling the case when file_writer_->DisownFile()
    // is soon followed by URLFetcherCore::Stop(). We have to make sure that
    // DisownFile takes effect before Stop deletes file_writer_.
    //
    // This direct call should be thread-safe, since DisownFile itself does no
    // file operation. It just flips the state to be referred in destruction.
    file_writer->DisownFile();
  }
  return true;
}

void URLFetcherCore::OnReceivedRedirect(URLRequest* request,
                                        const RedirectInfo& redirect_info,
                                        bool* defer_redirect) {
  DCHECK_EQ(request, request_.get());
  DCHECK(network_task_runner_->BelongsToCurrentThread());
  if (stop_on_redirect_) {
    stopped_on_redirect_ = true;
    url_ = redirect_info.new_url;
    response_code_ = request_->GetResponseCode();
#if defined(COBALT)
    // Cobalt needs header information for CORS check between redirects.
    response_headers_ = request_->response_headers();
#endif
    proxy_server_ = request_->proxy_server();
    was_fetched_via_proxy_ = request_->was_fetched_via_proxy();
    was_cached_ = request_->was_cached();
    total_received_bytes_ += request_->GetTotalReceivedBytes();
    int result = request->Cancel();
    OnReadCompleted(request, result);
  }
}

void URLFetcherCore::OnResponseStarted(URLRequest* request, int net_error) {
  DCHECK_EQ(request, request_.get());
  DCHECK(network_task_runner_->BelongsToCurrentThread());
  DCHECK_NE(ERR_IO_PENDING, net_error);

  if (net_error == OK) {
    response_code_ = request_->GetResponseCode();
    response_headers_ = request_->response_headers();
    socket_address_ = request_->GetSocketAddress();
    proxy_server_ = request_->proxy_server();
    was_fetched_via_proxy_ = request_->was_fetched_via_proxy();
    was_cached_ = request_->was_cached();
    total_response_bytes_ = request_->GetExpectedContentSize();
  }

  DCHECK(!buffer_);
#if defined(STARBOARD)
  if (request_type_ != URLFetcher::HEAD) {
    response_writer_->OnResponseStarted(total_response_bytes_);
    io_buffer_size_ = GetIOBufferSizeByContentSize(total_response_bytes_);
    buffer_ = base::MakeRefCounted<IOBuffer>(io_buffer_size_);
  }

  // We update this earlier than OnReadCompleted(), so that the delegate
  // can know about it if they call GetURL() in any callback.
  if (!stopped_on_redirect_) {
    url_ = request_->url();
  }
  InformDelegateResponseStarted();
#else   // defined(STARBOARD)
  if (request_type_ != URLFetcher::HEAD)
    buffer_ = base::MakeRefCounted<IOBuffer>(kBufferSize);
#endif  // defined(STARBOARD)
  ReadResponse();
}

void URLFetcherCore::OnCertificateRequested(
    URLRequest* request,
    SSLCertRequestInfo* cert_request_info) {
  DCHECK_EQ(request, request_.get());
  DCHECK(network_task_runner_->BelongsToCurrentThread());

  if (g_ignore_certificate_requests) {
    request->ContinueWithCertificate(nullptr, nullptr);
  } else {
    request->Cancel();
  }
}

void URLFetcherCore::OnReadCompleted(URLRequest* request,
                                     int bytes_read) {
  DCHECK_EQ(request, request_.get());
  DCHECK(network_task_runner_->BelongsToCurrentThread());

  if (!stopped_on_redirect_)
    url_ = request->url();
  URLRequestThrottlerManager* throttler_manager =
      request->context()->throttler_manager();
  if (throttler_manager)
    url_throttler_entry_ = throttler_manager->RegisterRequestUrl(url_);

#if defined(STARBOARD)
  // Prime it to the current time so it is only called after the loop, or every
  // time when the loop takes |kInformDownloadProgressInterval|.
  SbTime download_progress_informed_at = SbTimeGetMonotonicNow();
  bool did_read_after_inform_download_progress = false;

  while (bytes_read > 0) {
    current_response_bytes_ += bytes_read;
    did_read_after_inform_download_progress = true;
    auto now = SbTimeGetMonotonicNow();
    if (now - download_progress_informed_at > kInformDownloadProgressInterval) {
      InformDelegateDownloadProgress();
      download_progress_informed_at = now;
      did_read_after_inform_download_progress = false;
    }

    const int result = WriteBuffer(
        base::MakeRefCounted<DrainableIOBuffer>(buffer_, bytes_read));
    if (result < 0) {
      // Write failed or waiting for write completion.
      return;
    }
    bytes_read = request_->Read(buffer_.get(), io_buffer_size_);
  }

  if (did_read_after_inform_download_progress) {
    InformDelegateDownloadProgress();
  }
#else   // defined(STARBOARD)
  while (bytes_read > 0) {
    current_response_bytes_ += bytes_read;
    InformDelegateDownloadProgress();

    const int result = WriteBuffer(
        base::MakeRefCounted<DrainableIOBuffer>(buffer_, bytes_read));
    if (result < 0) {
      // Write failed or waiting for write completion.
      return;
    }
    bytes_read = request_->Read(buffer_.get(), kBufferSize);
  }
#endif  // defined(STARBOARD)

  // See comments re: HEAD requests in ReadResponse().
  if (bytes_read != ERR_IO_PENDING || request_type_ == URLFetcher::HEAD) {
    status_ = URLRequestStatus::FromError(bytes_read);
    received_response_content_length_ =
        request_->received_response_content_length();
    total_received_bytes_ += request_->GetTotalReceivedBytes();
    ReleaseRequest();

    // No more data to write.
    const int result = response_writer_->Finish(
        bytes_read > 0 ? OK : bytes_read,
        base::Bind(&URLFetcherCore::DidFinishWriting, this));
    if (result != ERR_IO_PENDING)
      DidFinishWriting(result);
  }
}

void URLFetcherCore::OnContextShuttingDown() {
  DCHECK(request_);
  CancelRequestAndInformDelegate(ERR_CONTEXT_SHUT_DOWN);
}

void URLFetcherCore::CancelAll() {
  g_registry.Get().CancelAll();
}

int URLFetcherCore::GetNumFetcherCores() {
  return g_registry.Get().size();
}

void URLFetcherCore::SetIgnoreCertificateRequests(bool ignored) {
  g_ignore_certificate_requests = ignored;
}

URLFetcherCore::~URLFetcherCore() {
  if (observer_extension_ != nullptr) {
    observer_extension_->FetcherDestroyed(
        original_url_.spec()
            .substr(0, URL_FETCHER_OBSERVER_MAX_URL_SIZE)
            .c_str());
  }
  // |request_| should be NULL. If not, it's unsafe to delete it here since we
  // may not be on the IO thread.
  DCHECK(!request_.get());
}

void URLFetcherCore::StartOnIOThread() {
  DCHECK(network_task_runner_->BelongsToCurrentThread());

  // Create ChunkedUploadDataStream, if needed, so the consumer can start
  // appending data.  Have to do it here because StartURLRequest() may be called
  // asynchonously.
  if (is_chunked_upload_) {
    chunked_stream_.reset(new ChunkedUploadDataStream(0));
    chunked_stream_writer_ = chunked_stream_->CreateWriter();
  }

  if (!response_writer_)
    response_writer_.reset(new URLFetcherStringWriter);

  const int result = response_writer_->Initialize(
      base::Bind(&URLFetcherCore::DidInitializeWriter, this));
  if (result != ERR_IO_PENDING)
    DidInitializeWriter(result);
}

void URLFetcherCore::StartURLRequest() {
  DCHECK(network_task_runner_->BelongsToCurrentThread());

  if (observer_extension_ != nullptr) {
    observer_extension_->StartURLRequest(
        original_url_.spec()
            .substr(0, URL_FETCHER_OBSERVER_MAX_URL_SIZE)
            .c_str());
  }
  if (was_cancelled_) {
    // Since StartURLRequest() is posted as a *delayed* task, it may
    // run after the URLFetcher was already stopped.
    return;
  }

  DCHECK(request_context_getter_);
  if (!request_context_getter_->GetURLRequestContext()) {
    CancelRequestAndInformDelegate(ERR_CONTEXT_SHUT_DOWN);
    return;
  }

  DCHECK(!request_.get());

  g_registry.Get().AddURLFetcherCore(this);
  current_response_bytes_ = 0;
  request_context_getter_->AddObserver(this);
  request_ = request_context_getter_->GetURLRequestContext()->CreateRequest(
      original_url_, DEFAULT_PRIORITY, this, traffic_annotation_);
  int flags = request_->load_flags() | load_flags_;

  // TODO(mmenke): This should really be with the other code to set the upload
  // body, below.
  if (chunked_stream_)
    request_->set_upload(std::move(chunked_stream_));

  request_->SetLoadFlags(flags);
  if (allow_credentials_) {
    request_->set_allow_credentials(allow_credentials_.value());
  }
  request_->SetReferrer(referrer_);
  request_->set_referrer_policy(referrer_policy_);
  request_->set_site_for_cookies(initiator_.has_value() &&
#if defined(STARBOARD)
                                         // This is not a Cobalt change, but due
                                         // to a mismatch between src/net and
                                         // src/url version.
                                         !initiator_.value().unique()
#else
                                         !initiator_.value().opaque()
#endif
                                     ? initiator_.value().GetURL()
                                     : original_url_);
  request_->set_initiator(initiator_);
  if (url_request_data_key_ && !url_request_create_data_callback_.is_null()) {
    request_->SetUserData(url_request_data_key_,
                          url_request_create_data_callback_.Run());
  }

  switch (request_type_) {
    case URLFetcher::GET:
      break;

    case URLFetcher::POST:
    case URLFetcher::PUT:
    case URLFetcher::PATCH: {
// Cobalt sometimes does not have a request body for post request.
#if !defined(STARBOARD)
      // Upload content must be set.
      DCHECK(is_chunked_upload_ || upload_content_set_);
#endif

      request_->set_method(
          request_type_ == URLFetcher::POST ? "POST" :
          request_type_ == URLFetcher::PUT ? "PUT" : "PATCH");
      if (!upload_content_type_.empty()) {
        extra_request_headers_.SetHeader(HttpRequestHeaders::kContentType,
                                         upload_content_type_);
      }
      if (!upload_content_.empty()) {
        std::unique_ptr<UploadElementReader> reader(
            new UploadBytesElementReader(upload_content_.data(),
                                         upload_content_.size()));
        request_->set_upload(
            ElementsUploadDataStream::CreateWithReader(std::move(reader), 0));
      } else if (!upload_file_path_.empty()) {
        std::unique_ptr<UploadElementReader> reader(new UploadFileElementReader(
            upload_file_task_runner_.get(), upload_file_path_,
            upload_range_offset_, upload_range_length_, base::Time()));
        request_->set_upload(
            ElementsUploadDataStream::CreateWithReader(std::move(reader), 0));
      } else if (!upload_stream_factory_.is_null()) {
        std::unique_ptr<UploadDataStream> stream = upload_stream_factory_.Run();
        DCHECK(stream);
        request_->set_upload(std::move(stream));
      }

      current_upload_bytes_ = -1;
      // TODO(kinaba): http://crbug.com/118103. Implement upload callback in the
      //  layer and avoid using timer here.
      upload_progress_checker_timer_.reset(new base::RepeatingTimer());
      upload_progress_checker_timer_->Start(
          FROM_HERE,
          base::TimeDelta::FromMilliseconds(kUploadProgressTimerInterval),
          this,
          &URLFetcherCore::InformDelegateUploadProgress);
      break;
    }

    case URLFetcher::HEAD:
      request_->set_method("HEAD");
      break;

    case URLFetcher::DELETE_REQUEST:
      request_->set_method("DELETE");
      break;

#if defined(COBALT)
    // Cobalt needs OPTIONS method to send CORS-Preflight requests.
    case URLFetcher::OPTIONS:
      request_->set_method("OPTIONS");
      break;
#endif

    default:
      NOTREACHED();
  }

  if (!extra_request_headers_.IsEmpty())
    request_->SetExtraRequestHeaders(extra_request_headers_);

  request_->SetLoadTimingInfoCallback(base::Bind(&URLFetcherCore::GetLoadTimingInfo,
      base::Unretained(this)));
  request_->Start();
}

void URLFetcherCore::DidInitializeWriter(int result) {
  if (result != OK) {
    CancelRequestAndInformDelegate(result);
    return;
  }
  StartURLRequestWhenAppropriate();
}

void URLFetcherCore::StartURLRequestWhenAppropriate() {
  DCHECK(network_task_runner_->BelongsToCurrentThread());

  if (was_cancelled_)
    return;

  DCHECK(request_context_getter_.get());

  // Check if the request should be delayed, and if so, post a task to start it
  // after the delay has expired.  Otherwise, start it now.

  URLRequestContext* context = request_context_getter_->GetURLRequestContext();
  // If the context has been shut down, or there's no ThrottlerManager, just
  // start the request.  In the former case, StartURLRequest() will just inform
  // the URLFetcher::Delegate the request has been canceled.
  if (context && context->throttler_manager()) {
    if (!original_url_throttler_entry_.get()) {
      original_url_throttler_entry_ =
          context->throttler_manager()->RegisterRequestUrl(original_url_);
    }

    if (original_url_throttler_entry_.get()) {
      int64_t delay =
          original_url_throttler_entry_->ReserveSendingTimeForNextRequest(
              GetBackoffReleaseTime());
      if (delay != 0) {
        network_task_runner_->PostDelayedTask(
            FROM_HERE, base::Bind(&URLFetcherCore::StartURLRequest, this),
            base::TimeDelta::FromMilliseconds(delay));
        return;
      }
    }
  }

  StartURLRequest();
}

void URLFetcherCore::CancelURLRequest(int error) {
  DCHECK(network_task_runner_->BelongsToCurrentThread());

  if (request_.get()) {
    request_->CancelWithError(error);
    ReleaseRequest();
  }

  // Set the error manually.
  // Normally, calling URLRequest::CancelWithError() results in calling
  // OnReadCompleted() with bytes_read = -1 via an asynchronous task posted by
  // URLRequestJob::NotifyDone(). But, because the request was released
  // immediately after being canceled, the request could not call
  // OnReadCompleted() which overwrites |status_| with the error status.
  status_ = URLRequestStatus(URLRequestStatus::CANCELED, error);

  // Release the reference to the request context. There could be multiple
  // references to URLFetcher::Core at this point so it may take a while to
  // delete the object, but we cannot delay the destruction of the request
  // context.
  request_context_getter_ = NULL;
  initiator_.reset();
  url_request_data_key_ = NULL;
  url_request_create_data_callback_.Reset();
  was_cancelled_ = true;
}

void URLFetcherCore::OnCompletedURLRequest(
    base::TimeDelta backoff_delay) {
  DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());
  // Save the status and backoff_delay so that delegates can read it.
  if (delegate_) {
    backoff_delay_ = backoff_delay;
    InformDelegateFetchIsComplete();
  }
}

void URLFetcherCore::InformDelegateFetchIsComplete() {
  DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());
  if (delegate_) {
    delegate_->OnURLFetchComplete(fetcher_);
  }
}

void URLFetcherCore::NotifyMalformedContent() {
  DCHECK(network_task_runner_->BelongsToCurrentThread());
  if (url_throttler_entry_.get()) {
    int status_code = response_code_;
    if (status_code == URLFetcher::RESPONSE_CODE_INVALID) {
      // The status code will generally be known by the time clients
      // call the |ReceivedContentWasMalformed()| function (which ends up
      // calling the current function) but if it's not, we need to assume
      // the response was successful so that the total failure count
      // used to calculate exponential back-off goes up.
      status_code = 200;
    }
    url_throttler_entry_->ReceivedContentWasMalformed(status_code);
  }
}

void URLFetcherCore::DidFinishWriting(int result) {
  if (result != OK) {
    CancelRequestAndInformDelegate(result);
    return;
  }
  // If the file was successfully closed, then the URL request is complete.
  RetryOrCompleteUrlFetch();
}

void URLFetcherCore::RetryOrCompleteUrlFetch() {
  DCHECK(network_task_runner_->BelongsToCurrentThread());
  base::TimeDelta backoff_delay;

  // Checks the response from server.
  if (response_code_ >= 500 ||
      status_.error() == ERR_TEMPORARILY_THROTTLED) {
    // When encountering a server error, we will send the request again
    // after backoff time.
    ++num_retries_on_5xx_;

    // Note that backoff_delay may be 0 because (a) the
    // URLRequestThrottlerManager and related code does not
    // necessarily back off on the first error, (b) it only backs off
    // on some of the 5xx status codes, (c) not all URLRequestContexts
    // have a throttler manager.
    base::TimeTicks backoff_release_time = GetBackoffReleaseTime();
    backoff_delay = backoff_release_time - base::TimeTicks::Now();
    if (backoff_delay < base::TimeDelta())
      backoff_delay = base::TimeDelta();

    if (automatically_retry_on_5xx_ &&
        num_retries_on_5xx_ <= max_retries_on_5xx_) {
      StartOnIOThread();
      return;
    }
  } else {
    backoff_delay = base::TimeDelta();
  }

  // Retry if the request failed due to network changes.
  if (status_.error() == ERR_NETWORK_CHANGED &&
      num_retries_on_network_changes_ < max_retries_on_network_changes_) {
    ++num_retries_on_network_changes_;

    // Retry soon, after flushing all the current tasks which may include
    // further network change observers.
    network_task_runner_->PostTask(
        FROM_HERE, base::Bind(&URLFetcherCore::StartOnIOThread, this));
    return;
  }

  request_context_getter_ = NULL;
  initiator_.reset();
  url_request_data_key_ = NULL;
  url_request_create_data_callback_.Reset();
  bool posted = delegate_task_runner_->PostTask(
      FROM_HERE,
      base::Bind(&URLFetcherCore::OnCompletedURLRequest, this, backoff_delay));

  // If the delegate message loop does not exist any more, then the delegate
  // should be gone too.
  DCHECK(posted || !delegate_);
}

void URLFetcherCore::CancelRequestAndInformDelegate(int result) {
  CancelURLRequest(result);
  delegate_task_runner_->PostTask(
      FROM_HERE,
      base::Bind(&URLFetcherCore::InformDelegateFetchIsComplete, this));
}

void URLFetcherCore::ReleaseRequest() {
  request_context_getter_->RemoveObserver(this);
  upload_progress_checker_timer_.reset();
  request_.reset();
  buffer_ = nullptr;
  g_registry.Get().RemoveURLFetcherCore(this);
}

base::TimeTicks URLFetcherCore::GetBackoffReleaseTime() {
  DCHECK(network_task_runner_->BelongsToCurrentThread());

  if (!original_url_throttler_entry_.get())
    return base::TimeTicks();

  base::TimeTicks original_url_backoff =
      original_url_throttler_entry_->GetExponentialBackoffReleaseTime();
  base::TimeTicks destination_url_backoff;
  if (url_throttler_entry_.get() &&
      original_url_throttler_entry_.get() != url_throttler_entry_.get()) {
    destination_url_backoff =
        url_throttler_entry_->GetExponentialBackoffReleaseTime();
  }

  return original_url_backoff > destination_url_backoff ?
      original_url_backoff : destination_url_backoff;
}

void URLFetcherCore::CompleteAddingUploadDataChunk(
    const std::string& content, bool is_last_chunk) {
  DCHECK(is_chunked_upload_);
  DCHECK(!content.empty());
  chunked_stream_writer_->AppendData(
      content.data(), static_cast<int>(content.length()), is_last_chunk);
}

int URLFetcherCore::WriteBuffer(scoped_refptr<DrainableIOBuffer> data) {
  while (data->BytesRemaining() > 0) {
    const int result = response_writer_->Write(
        data.get(),
        data->BytesRemaining(),
        base::Bind(&URLFetcherCore::DidWriteBuffer, this, data));
    if (result < 0) {
      if (result != ERR_IO_PENDING)
        DidWriteBuffer(data, result);
      return result;
    }
    data->DidConsume(result);
  }
  return OK;
}

void URLFetcherCore::DidWriteBuffer(scoped_refptr<DrainableIOBuffer> data,
                                    int result) {
  if (result < 0) {  // Handle errors.
    response_writer_->Finish(result, base::DoNothing());
    CancelRequestAndInformDelegate(result);
    return;
  }

  // Continue writing.
  data->DidConsume(result);
  if (WriteBuffer(data) < 0)
    return;

  // Finished writing buffer_. Read some more, unless the request has been
  // cancelled and deleted.
  DCHECK_EQ(0, data->BytesRemaining());
  if (request_.get())
    ReadResponse();
}

void URLFetcherCore::ReadResponse() {
  // Some servers may treat HEAD requests as GET requests. To free up the
  // network connection as soon as possible, signal that the request has
  // completed immediately, without trying to read any data back (all we care
  // about is the response code and headers, which we already have).
  int bytes_read = 0;
#if defined(STARBOARD)
  if (request_type_ != URLFetcher::HEAD)
    bytes_read = request_->Read(buffer_.get(), io_buffer_size_);
#else   // defined(STARBOARD)
  if (request_type_ != URLFetcher::HEAD)
    bytes_read = request_->Read(buffer_.get(), kBufferSize);
#endif  // defined(STARBOARD)

  OnReadCompleted(request_.get(), bytes_read);
}

#if defined(STARBOARD)

void URLFetcherCore::InformDelegateResponseStarted() {
  DCHECK(network_task_runner_->BelongsToCurrentThread());
  DCHECK(request_);

  delegate_task_runner_->PostTask(
      FROM_HERE,
      base::Bind(&URLFetcherCore::InformDelegateResponseStartedInDelegateThread,
                 this));
}

void URLFetcherCore::InformDelegateResponseStartedInDelegateThread() {
  if (delegate_) {
    delegate_->OnURLFetchResponseStarted(fetcher_);
  }
}

#endif  // defined(STARBOARD)

void URLFetcherCore::InformDelegateUploadProgress() {
  DCHECK(network_task_runner_->BelongsToCurrentThread());
  if (request_.get()) {
    int64_t current = request_->GetUploadProgress().position();
    if (current_upload_bytes_ != current) {
      current_upload_bytes_ = current;
      int64_t total = -1;
      if (!is_chunked_upload_) {
        total = static_cast<int64_t>(request_->GetUploadProgress().size());
        // Total may be zero if the UploadDataStream::Init has not been called
        // yet. Don't send the upload progress until the size is initialized.
        if (!total)
          return;
      }
      delegate_task_runner_->PostTask(
          FROM_HERE,
          base::Bind(
              &URLFetcherCore::InformDelegateUploadProgressInDelegateSequence,
              this, current, total));
    }
  }
}

void URLFetcherCore::InformDelegateUploadProgressInDelegateSequence(
    int64_t current,
    int64_t total) {
  DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());
  if (delegate_)
    delegate_->OnURLFetchUploadProgress(fetcher_, current, total);
}

void URLFetcherCore::InformDelegateDownloadProgress() {
  DCHECK(network_task_runner_->BelongsToCurrentThread());
  delegate_task_runner_->PostTask(
      FROM_HERE,
      base::Bind(
          &URLFetcherCore::InformDelegateDownloadProgressInDelegateSequence,
          this, current_response_bytes_, total_response_bytes_,
          request_->GetTotalReceivedBytes()));
}

void URLFetcherCore::InformDelegateDownloadProgressInDelegateSequence(
    int64_t current,
    int64_t total,
    int64_t current_network_bytes) {
  DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());
  if (delegate_)
    delegate_->OnURLFetchDownloadProgress(fetcher_, current, total,
                                          current_network_bytes);
}

void URLFetcherCore::AssertHasNoUploadData() const {
  DCHECK(!upload_content_set_);
  DCHECK(upload_content_.empty());
  DCHECK(upload_file_path_.empty());
  DCHECK(upload_stream_factory_.is_null());
}

#if defined(STARBOARD)
void URLFetcherCore::GetLoadTimingInfo(
    const net::LoadTimingInfo& timing_info) {
  // Check if the URLFetcherCore has been stopped before.
  if (delegate_) {
    delegate_->ReportLoadTimingInfo(timing_info);
  }
}
#endif  // defined(STARBOARD)

}  // namespace net
