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

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/debug/stack_trace.h"
#include "base/lazy_instance.h"
#include "base/memory/singleton.h"
#include "base/message_loop.h"
#include "base/metrics/stats_counters.h"
#include "base/stl_util.h"
#include "base/synchronization/lock.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_log.h"
#include "net/base/network_change_notifier.h"
#include "net/base/network_delegate.h"
#include "net/base/ssl_cert_request_info.h"
#include "net/base/upload_data_stream.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_error_job.h"
#include "net/url_request/url_request_job.h"
#include "net/url_request/url_request_job_manager.h"
#include "net/url_request/url_request_netlog_params.h"
#include "net/url_request/url_request_redirect_job.h"

using base::Time;
using std::string;

namespace net {

namespace {

// Max number of http redirects to follow.  Same number as gecko.
const int kMaxRedirects = 20;

// Discard headers which have meaning in POST (Content-Length, Content-Type,
// Origin).
void StripPostSpecificHeaders(HttpRequestHeaders* headers) {
  // These are headers that may be attached to a POST.
  headers->RemoveHeader(HttpRequestHeaders::kContentLength);
  headers->RemoveHeader(HttpRequestHeaders::kContentType);
  headers->RemoveHeader(HttpRequestHeaders::kOrigin);
}

// TODO(battre): Delete this, see http://crbug.com/89321:
// This counter keeps track of the identifiers used for URL requests so far.
// 0 is reserved to represent an invalid ID.
uint64 g_next_url_request_identifier = 1;

// This lock protects g_next_url_request_identifier.
base::LazyInstance<base::Lock>::Leaky
    g_next_url_request_identifier_lock = LAZY_INSTANCE_INITIALIZER;

// Returns an prior unused identifier for URL requests.
uint64 GenerateURLRequestIdentifier() {
  base::AutoLock lock(g_next_url_request_identifier_lock.Get());
  return g_next_url_request_identifier++;
}

// True once the first URLRequest was started.
bool g_url_requests_started = false;

// True if cookies are accepted by default.
bool g_default_can_use_cookies = true;

}  // namespace

URLRequest::ProtocolFactory*
URLRequest::Deprecated::RegisterProtocolFactory(const std::string& scheme,
                                                ProtocolFactory* factory) {
  return URLRequest::RegisterProtocolFactory(scheme, factory);
}

void URLRequest::Deprecated::RegisterRequestInterceptor(
    Interceptor* interceptor) {
  URLRequest::RegisterRequestInterceptor(interceptor);
}

void URLRequest::Deprecated::UnregisterRequestInterceptor(
    Interceptor* interceptor) {
  URLRequest::UnregisterRequestInterceptor(interceptor);
}

///////////////////////////////////////////////////////////////////////////////
// URLRequest::Interceptor

URLRequestJob* URLRequest::Interceptor::MaybeInterceptRedirect(
    URLRequest* request,
    NetworkDelegate* network_delegate,
    const GURL& location) {
  return NULL;
}

URLRequestJob* URLRequest::Interceptor::MaybeInterceptResponse(
    URLRequest* request, NetworkDelegate* network_delegate) {
  return NULL;
}

///////////////////////////////////////////////////////////////////////////////
// URLRequest::Delegate

void URLRequest::Delegate::OnReceivedRedirect(URLRequest* request,
                                              const GURL& new_url,
                                              bool* defer_redirect) {
}

void URLRequest::Delegate::OnAuthRequired(URLRequest* request,
                                          AuthChallengeInfo* auth_info) {
  request->CancelAuth();
}

void URLRequest::Delegate::OnCertificateRequested(
    URLRequest* request,
    SSLCertRequestInfo* cert_request_info) {
  request->Cancel();
}

void URLRequest::Delegate::OnSSLCertificateError(URLRequest* request,
                                                 const SSLInfo& ssl_info,
                                                 bool is_hsts_ok) {
  request->Cancel();
}

///////////////////////////////////////////////////////////////////////////////
// URLRequest

// TODO(shalev): Get rid of this constructor in favour of the one below it.
URLRequest::URLRequest(const GURL& url,
                       Delegate* delegate,
                       const URLRequestContext* context)
    : context_(context),
      network_delegate_(context->network_delegate()),
      net_log_(BoundNetLog::Make(context->net_log(),
                                 NetLog::SOURCE_URL_REQUEST)),
      url_chain_(1, url),
      method_("GET"),
      referrer_policy_(CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE),
      load_flags_(LOAD_NORMAL),
      delegate_(delegate),
      is_pending_(false),
      is_redirecting_(false),
      redirect_limit_(kMaxRedirects),
      priority_(LOWEST),
      identifier_(GenerateURLRequestIdentifier()),
      blocked_on_delegate_(false),
      ALLOW_THIS_IN_INITIALIZER_LIST(before_request_callback_(
          base::Bind(&URLRequest::BeforeRequestComplete,
                     base::Unretained(this)))),
      has_notified_completion_(false),
      received_response_content_length_(0),
      creation_time_(base::TimeTicks::Now()) {
  SIMPLE_STATS_COUNTER("URLRequestCount");

  // Sanity check out environment.
  DCHECK(MessageLoop::current()) << "The current MessageLoop must exist";

  DCHECK(MessageLoop::current()->IsType(MessageLoop::TYPE_IO)) << ""
      "The current MessageLoop must be TYPE_IO";

  CHECK(context);
  context->url_requests()->insert(this);

  net_log_.BeginEvent(NetLog::TYPE_REQUEST_ALIVE);
}

URLRequest::URLRequest(const GURL& url,
                       Delegate* delegate,
                       const URLRequestContext* context,
                       NetworkDelegate* network_delegate)
    : context_(context),
      network_delegate_(network_delegate),
      net_log_(BoundNetLog::Make(context->net_log(),
                                 NetLog::SOURCE_URL_REQUEST)),
      url_chain_(1, url),
      method_("GET"),
      referrer_policy_(CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE),
      load_flags_(LOAD_NORMAL),
      delegate_(delegate),
      is_pending_(false),
      is_redirecting_(false),
      redirect_limit_(kMaxRedirects),
      priority_(LOWEST),
      identifier_(GenerateURLRequestIdentifier()),
      blocked_on_delegate_(false),
      ALLOW_THIS_IN_INITIALIZER_LIST(before_request_callback_(
          base::Bind(&URLRequest::BeforeRequestComplete,
                     base::Unretained(this)))),
      has_notified_completion_(false),
      received_response_content_length_(0),
      creation_time_(base::TimeTicks::Now()) {
  SIMPLE_STATS_COUNTER("URLRequestCount");

  // Sanity check out environment.
  DCHECK(MessageLoop::current()) << "The current MessageLoop must exist";

  DCHECK(MessageLoop::current()->IsType(MessageLoop::TYPE_IO)) << ""
      "The current MessageLoop must be TYPE_IO";

  CHECK(context);
  context->url_requests()->insert(this);

  net_log_.BeginEvent(NetLog::TYPE_REQUEST_ALIVE);
}

URLRequest::~URLRequest() {
  Cancel();

  if (network_delegate_) {
    network_delegate_->NotifyURLRequestDestroyed(this);
    if (job_)
      job_->NotifyURLRequestDestroyed();
  }

  if (job_)
    OrphanJob();

  int deleted = context_->url_requests()->erase(this);
  CHECK_EQ(1, deleted);

  int net_error = OK;
  // Log error only on failure, not cancellation, as even successful requests
  // are "cancelled" on destruction.
  if (status_.status() == URLRequestStatus::FAILED)
    net_error = status_.error();
  net_log_.EndEventWithNetErrorCode(NetLog::TYPE_REQUEST_ALIVE, net_error);
}

// static
URLRequest::ProtocolFactory* URLRequest::RegisterProtocolFactory(
    const string& scheme, ProtocolFactory* factory) {
  return URLRequestJobManager::GetInstance()->RegisterProtocolFactory(scheme,
                                                                      factory);
}

// static
void URLRequest::RegisterRequestInterceptor(Interceptor* interceptor) {
  URLRequestJobManager::GetInstance()->RegisterRequestInterceptor(interceptor);
}

// static
void URLRequest::UnregisterRequestInterceptor(Interceptor* interceptor) {
  URLRequestJobManager::GetInstance()->UnregisterRequestInterceptor(
      interceptor);
}

void URLRequest::EnableChunkedUpload() {
  DCHECK(!upload_data_stream_ || upload_data_stream_->is_chunked());
  if (!upload_data_stream_) {
    upload_data_stream_.reset(
        new UploadDataStream(UploadDataStream::CHUNKED, 0));
  }
}

void URLRequest::AppendChunkToUpload(const char* bytes,
                                     int bytes_len,
                                     bool is_last_chunk) {
  DCHECK(upload_data_stream_);
  DCHECK(upload_data_stream_->is_chunked());
  DCHECK_GT(bytes_len, 0);
  upload_data_stream_->AppendChunk(bytes, bytes_len, is_last_chunk);
}

void URLRequest::set_upload(scoped_ptr<UploadDataStream> upload) {
  DCHECK(!upload->is_chunked());
  upload_data_stream_ = upload.Pass();
}

const UploadDataStream* URLRequest::get_upload() const {
  return upload_data_stream_.get();
}

bool URLRequest::has_upload() const {
  return upload_data_stream_.get() != NULL;
}

void URLRequest::SetExtraRequestHeaderById(int id, const string& value,
                                           bool overwrite) {
  DCHECK(!is_pending_ || is_redirecting_);
  NOTREACHED() << "implement me!";
}

void URLRequest::SetExtraRequestHeaderByName(const string& name,
                                             const string& value,
                                             bool overwrite) {
  DCHECK(!is_pending_ || is_redirecting_);
  if (overwrite) {
    extra_request_headers_.SetHeader(name, value);
  } else {
    extra_request_headers_.SetHeaderIfMissing(name, value);
  }
}

void URLRequest::RemoveRequestHeaderByName(const string& name) {
  DCHECK(!is_pending_ || is_redirecting_);
  extra_request_headers_.RemoveHeader(name);
}

void URLRequest::SetExtraRequestHeaders(
    const HttpRequestHeaders& headers) {
  DCHECK(!is_pending_);
  extra_request_headers_ = headers;

  // NOTE: This method will likely become non-trivial once the other setters
  // for request headers are implemented.
}

LoadStateWithParam URLRequest::GetLoadState() const {
  // Only return LOAD_STATE_WAITING_FOR_DELEGATE if there's a load state param.
  if (blocked_on_delegate_ && !load_state_param_.empty()) {
    return LoadStateWithParam(LOAD_STATE_WAITING_FOR_DELEGATE,
                              load_state_param_);
  }
  return LoadStateWithParam(job_ ? job_->GetLoadState() : LOAD_STATE_IDLE,
                            string16());
}

UploadProgress URLRequest::GetUploadProgress() const {
  if (!job_) {
    // We haven't started or the request was cancelled
    return UploadProgress();
  }
  if (final_upload_progress_.position()) {
    // The first job completed and none of the subsequent series of
    // GETs when following redirects will upload anything, so we return the
    // cached results from the initial job, the POST.
    return final_upload_progress_;
  }
  return job_->GetUploadProgress();
}

void URLRequest::GetResponseHeaderById(int id, string* value) {
  DCHECK(job_);
  NOTREACHED() << "implement me!";
}

void URLRequest::GetResponseHeaderByName(const string& name, string* value) {
  DCHECK(value);
  if (response_info_.headers) {
    response_info_.headers->GetNormalizedHeader(name, value);
  } else {
    value->clear();
  }
}

void URLRequest::GetAllResponseHeaders(string* headers) {
  DCHECK(headers);
  if (response_info_.headers) {
    response_info_.headers->GetNormalizedHeaders(headers);
  } else {
    headers->clear();
  }
}

HostPortPair URLRequest::GetSocketAddress() const {
  DCHECK(job_);
  return job_->GetSocketAddress();
}

HttpResponseHeaders* URLRequest::response_headers() const {
  return response_info_.headers.get();
}

bool URLRequest::GetResponseCookies(ResponseCookies* cookies) {
  DCHECK(job_);
  return job_->GetResponseCookies(cookies);
}

void URLRequest::GetMimeType(string* mime_type) {
  DCHECK(job_);
  job_->GetMimeType(mime_type);
}

void URLRequest::GetCharset(string* charset) {
  DCHECK(job_);
  job_->GetCharset(charset);
}

int URLRequest::GetResponseCode() {
  DCHECK(job_);
  return job_->GetResponseCode();
}

// static
void URLRequest::SetDefaultCookiePolicyToBlock() {
  CHECK(!g_url_requests_started);
  g_default_can_use_cookies = false;
}

// static
bool URLRequest::IsHandledProtocol(const std::string& scheme) {
  return URLRequestJobManager::GetInstance()->SupportsScheme(scheme);
}

// static
bool URLRequest::IsHandledURL(const GURL& url) {
  if (!url.is_valid()) {
    // We handle error cases.
    return true;
  }

  return IsHandledProtocol(url.scheme());
}

void URLRequest::set_first_party_for_cookies(
    const GURL& first_party_for_cookies) {
  first_party_for_cookies_ = first_party_for_cookies;
}

void URLRequest::set_method(const std::string& method) {
  DCHECK(!is_pending_);
  method_ = method;
}

void URLRequest::set_referrer(const std::string& referrer) {
  DCHECK(!is_pending_);
  referrer_ = referrer;
}

GURL URLRequest::GetSanitizedReferrer() const {
  GURL ret(referrer());

  // Ensure that we do not send username and password fields in the referrer.
  if (ret.has_username() || ret.has_password()) {
    GURL::Replacements referrer_mods;
    referrer_mods.ClearUsername();
    referrer_mods.ClearPassword();
    ret = ret.ReplaceComponents(referrer_mods);
  }

  return ret;
}

void URLRequest::set_referrer_policy(ReferrerPolicy referrer_policy) {
  DCHECK(!is_pending_);
  referrer_policy_ = referrer_policy;
}

void URLRequest::set_delegate(Delegate* delegate) {
  delegate_ = delegate;
}

void URLRequest::Start() {
  DCHECK_EQ(network_delegate_, context_->network_delegate());

  g_url_requests_started = true;
  response_info_.request_time = Time::Now();

  // Only notify the delegate for the initial request.
  if (network_delegate_) {
    int error = network_delegate_->NotifyBeforeURLRequest(
        this, before_request_callback_, &delegate_redirect_url_);
    if (error == net::ERR_IO_PENDING) {
      // Paused on the delegate, will invoke |before_request_callback_| later.
      SetBlockedOnDelegate();
    } else {
      BeforeRequestComplete(error);
    }
    return;
  }

  StartJob(URLRequestJobManager::GetInstance()->CreateJob(
      this, network_delegate_));
}

///////////////////////////////////////////////////////////////////////////////

void URLRequest::BeforeRequestComplete(int error) {
  DCHECK(!job_);
  DCHECK_NE(ERR_IO_PENDING, error);
  DCHECK_EQ(network_delegate_, context_->network_delegate());

  // Check that there are no callbacks to already canceled requests.
  DCHECK_NE(URLRequestStatus::CANCELED, status_.status());

  if (blocked_on_delegate_)
    SetUnblockedOnDelegate();

  if (error != OK) {
    std::string source("delegate");
    net_log_.AddEvent(NetLog::TYPE_CANCELLED,
                      NetLog::StringCallback("source", &source));
    StartJob(new URLRequestErrorJob(this, network_delegate_, error));
  } else if (!delegate_redirect_url_.is_empty()) {
    GURL new_url;
    new_url.Swap(&delegate_redirect_url_);

    URLRequestRedirectJob* job = new URLRequestRedirectJob(
        this, network_delegate_, new_url,
        // Use status code 307 to preserve the method, so POST requests work.
        URLRequestRedirectJob::REDIRECT_307_TEMPORARY_REDIRECT);
    StartJob(job);
  } else {
    StartJob(URLRequestJobManager::GetInstance()->CreateJob(
        this, network_delegate_));
  }
}

void URLRequest::StartJob(URLRequestJob* job) {
  DCHECK(!is_pending_);
  DCHECK(!job_);

  net_log_.BeginEvent(
      NetLog::TYPE_URL_REQUEST_START_JOB,
      base::Bind(&NetLogURLRequestStartCallback,
                 &url(), &method_, load_flags_, priority_,
                 upload_data_stream_ ? upload_data_stream_->identifier() : -1));

  job_ = job;
  job_->SetExtraRequestHeaders(extra_request_headers_);

  if (upload_data_stream_.get())
    job_->SetUpload(upload_data_stream_.get());

  is_pending_ = true;
  is_redirecting_ = false;

  response_info_.was_cached = false;

  // Don't allow errors to be sent from within Start().
  // TODO(brettw) this may cause NotifyDone to be sent synchronously,
  // we probably don't want this: they should be sent asynchronously so
  // the caller does not get reentered.
  job_->Start();
}

void URLRequest::Restart() {
  // Should only be called if the original job didn't make any progress.
  DCHECK(job_ && !job_->has_response_started());
  RestartWithJob(URLRequestJobManager::GetInstance()->CreateJob(
      this, network_delegate_));
}

void URLRequest::RestartWithJob(URLRequestJob *job) {
  DCHECK(job->request() == this);
  PrepareToRestart();
  StartJob(job);
}

void URLRequest::Cancel() {
  DoCancel(ERR_ABORTED, SSLInfo());
}

void URLRequest::CancelWithError(int error) {
  DoCancel(error, SSLInfo());
}

void URLRequest::CancelWithSSLError(int error, const SSLInfo& ssl_info) {
  // This should only be called on a started request.
  if (!is_pending_ || !job_ || job_->has_response_started()) {
    NOTREACHED();
    return;
  }
  DoCancel(error, ssl_info);
}

void URLRequest::DoCancel(int error, const SSLInfo& ssl_info) {
  DCHECK(error < 0);

  // If the URL request already has an error status, then canceling is a no-op.
  // Plus, we don't want to change the error status once it has been set.
  if (status_.is_success()) {
    status_.set_status(URLRequestStatus::CANCELED);
    status_.set_error(error);
    response_info_.ssl_info = ssl_info;

    // If the request hasn't already been completed, log a cancellation event.
    if (!has_notified_completion_) {
      // Don't log an error code on ERR_ABORTED, since that's redundant.
      net_log_.AddEventWithNetErrorCode(NetLog::TYPE_CANCELLED,
                                        error == ERR_ABORTED ? OK : error);
    }
  }

  if (is_pending_ && job_)
    job_->Kill();

  // We need to notify about the end of this job here synchronously. The
  // Job sends an asynchronous notification but by the time this is processed,
  // our |context_| is NULL.
  NotifyRequestCompleted();

  // The Job will call our NotifyDone method asynchronously.  This is done so
  // that the Delegate implementation can call Cancel without having to worry
  // about being called recursively.
}

bool URLRequest::Read(IOBuffer* dest, int dest_size, int* bytes_read) {
  DCHECK(job_);
  DCHECK(bytes_read);
  *bytes_read = 0;

  // This handles a cancel that happens while paused.
  // TODO(ahendrickson): DCHECK() that it is not done after
  // http://crbug.com/115705 is fixed.
  if (job_->is_done())
    return false;

  if (dest_size == 0) {
    // Caller is not too bright.  I guess we've done what they asked.
    return true;
  }

  // Once the request fails or is cancelled, read will just return 0 bytes
  // to indicate end of stream.
  if (!status_.is_success()) {
    return true;
  }

  bool rv = job_->Read(dest, dest_size, bytes_read);
  // If rv is false, the status cannot be success.
  DCHECK(rv || status_.status() != URLRequestStatus::SUCCESS);
  if (rv && *bytes_read <= 0 && status_.is_success())
    NotifyRequestCompleted();
  return rv;
}

void URLRequest::StopCaching() {
  DCHECK(job_);
  job_->StopCaching();
}

void URLRequest::NotifyReceivedRedirect(const GURL& location,
                                        bool* defer_redirect) {
  is_redirecting_ = true;

  URLRequestJob* job =
      URLRequestJobManager::GetInstance()->MaybeInterceptRedirect(
          this, network_delegate_, location);
  if (job) {
    RestartWithJob(job);
  } else if (delegate_) {
    delegate_->OnReceivedRedirect(this, location, defer_redirect);
    // |this| may be have been destroyed here.
  }
}

void URLRequest::NotifyResponseStarted() {
  int net_error = OK;
  if (!status_.is_success())
    net_error = status_.error();
  net_log_.EndEventWithNetErrorCode(NetLog::TYPE_URL_REQUEST_START_JOB,
                                    net_error);

  URLRequestJob* job =
      URLRequestJobManager::GetInstance()->MaybeInterceptResponse(
          this, network_delegate_);
  if (job) {
    RestartWithJob(job);
  } else {
    if (delegate_) {
      // In some cases (e.g. an event was canceled), we might have sent the
      // completion event and receive a NotifyResponseStarted() later.
      if (!has_notified_completion_ && status_.is_success()) {
        if (network_delegate_)
          network_delegate_->NotifyResponseStarted(this);
      }

      // Notify in case the entire URL Request has been finished.
      if (!has_notified_completion_ && !status_.is_success())
        NotifyRequestCompleted();

      delegate_->OnResponseStarted(this);
      // Nothing may appear below this line as OnResponseStarted may delete
      // |this|.
    }
  }
}

void URLRequest::FollowDeferredRedirect() {
  CHECK(job_);
  CHECK(status_.is_success());

  job_->FollowDeferredRedirect();
}

void URLRequest::SetAuth(const AuthCredentials& credentials) {
  DCHECK(job_);
  DCHECK(job_->NeedsAuth());

  job_->SetAuth(credentials);
}

void URLRequest::CancelAuth() {
  DCHECK(job_);
  DCHECK(job_->NeedsAuth());

  job_->CancelAuth();
}

void URLRequest::ContinueWithCertificate(X509Certificate* client_cert) {
  DCHECK(job_);

  job_->ContinueWithCertificate(client_cert);
}

void URLRequest::ContinueDespiteLastError() {
  DCHECK(job_);

  job_->ContinueDespiteLastError();
}

void URLRequest::PrepareToRestart() {
  DCHECK(job_);

  // Close the current URL_REQUEST_START_JOB, since we will be starting a new
  // one.
  net_log_.EndEvent(NetLog::TYPE_URL_REQUEST_START_JOB);

  OrphanJob();

  response_info_ = HttpResponseInfo();
  response_info_.request_time = Time::Now();
  status_ = URLRequestStatus();
  is_pending_ = false;
}

void URLRequest::OrphanJob() {
  // When calling this function, please check that URLRequestHttpJob is
  // not in between calling NetworkDelegate::NotifyHeadersReceived receiving
  // the call back. This is currently guaranteed by the following strategies:
  // - OrphanJob is called on JobRestart, in this case the URLRequestJob cannot
  //   be receiving any headers at that time.
  // - OrphanJob is called in ~URLRequest, in this case
  //   NetworkDelegate::NotifyURLRequestDestroyed notifies the NetworkDelegate
  //   that the callback becomes invalid.
  job_->Kill();
  job_->DetachRequest();  // ensures that the job will not call us again
  job_ = NULL;
}

int URLRequest::Redirect(const GURL& location, int http_status_code) {
  if (net_log_.IsLoggingAllEvents()) {
    net_log_.AddEvent(
        NetLog::TYPE_URL_REQUEST_REDIRECTED,
        NetLog::StringCallback("location", &location.possibly_invalid_spec()));
  }

  if (network_delegate_)
    network_delegate_->NotifyBeforeRedirect(this, location);

  if (redirect_limit_ <= 0) {
    DVLOG(1) << "disallowing redirect: exceeds limit";
    return ERR_TOO_MANY_REDIRECTS;
  }

  if (!location.is_valid())
    return ERR_INVALID_URL;

  if (!job_->IsSafeRedirect(location)) {
    DVLOG(1) << "disallowing redirect: unsafe protocol";
    return ERR_UNSAFE_REDIRECT;
  }

  if (!final_upload_progress_.position())
    final_upload_progress_ = job_->GetUploadProgress();
  PrepareToRestart();

  // For 303 redirects, all request methods except HEAD are converted to GET,
  // as per the latest httpbis draft.  The draft also allows POST requests to
  // be converted to GETs when following 301/302 redirects, for historical
  // reasons. Most major browsers do this and so shall we.  Both RFC 2616 and
  // the httpbis draft say to prompt the user to confirm the generation of new
  // requests, other than GET and HEAD requests, but IE omits these prompts and
  // so shall we.
  // See:  https://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-17#section-7.3
  bool was_post = method_ == "POST";
  if ((http_status_code == 303 && method_ != "HEAD") ||
      ((http_status_code == 301 || http_status_code == 302) && was_post)) {
    method_ = "GET";
    upload_data_stream_.reset();
    if (was_post) {
      // If being switched from POST to GET, must remove headers that were
      // specific to the POST and don't have meaning in GET. For example
      // the inclusion of a multipart Content-Type header in GET can cause
      // problems with some servers:
      // http://code.google.com/p/chromium/issues/detail?id=843
      StripPostSpecificHeaders(&extra_request_headers_);
    }
  }

  // Suppress the referrer if we're redirecting out of https.
  if (referrer_policy_ ==
          CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE &&
      GURL(referrer_).SchemeIsSecure() && !location.SchemeIsSecure()) {
    referrer_.clear();
  }

  url_chain_.push_back(location);
  --redirect_limit_;

  Start();
  return OK;
}

const URLRequestContext* URLRequest::context() const {
  return context_;
}

int64 URLRequest::GetExpectedContentSize() const {
  int64 expected_content_size = -1;
  if (job_)
    expected_content_size = job_->expected_content_size();

  return expected_content_size;
}

bool URLRequest::GetHSTSRedirect(GURL* redirect_url) const {
  const GURL& url = this->url();
  if (!url.SchemeIs("http"))
    return false;
  TransportSecurityState::DomainState domain_state;
  if (context()->transport_security_state() &&
      context()->transport_security_state()->GetDomainState(
          url.host(),
          SSLConfigService::IsSNIAvailable(context()->ssl_config_service()),
          &domain_state) &&
      domain_state.ShouldRedirectHTTPToHTTPS()) {
    url_canon::Replacements<char> replacements;
    const char kNewScheme[] = "https";
    replacements.SetScheme(kNewScheme,
                           url_parse::Component(0, strlen(kNewScheme)));
    *redirect_url = url.ReplaceComponents(replacements);
    return true;
  }
  return false;
}

void URLRequest::NotifyAuthRequired(AuthChallengeInfo* auth_info) {
  NetworkDelegate::AuthRequiredResponse rv =
      NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
  auth_info_ = auth_info;
  if (network_delegate_) {
    rv = network_delegate_->NotifyAuthRequired(
        this,
        *auth_info,
        base::Bind(&URLRequest::NotifyAuthRequiredComplete,
                   base::Unretained(this)),
        &auth_credentials_);
  }

  if (rv == NetworkDelegate::AUTH_REQUIRED_RESPONSE_IO_PENDING) {
    SetBlockedOnDelegate();
  } else {
    NotifyAuthRequiredComplete(rv);
  }
}

void URLRequest::NotifyAuthRequiredComplete(
    NetworkDelegate::AuthRequiredResponse result) {
  SetUnblockedOnDelegate();

  // Check that there are no callbacks to already canceled requests.
  DCHECK_NE(URLRequestStatus::CANCELED, status_.status());

  // NotifyAuthRequired may be called multiple times, such as
  // when an authentication attempt fails. Clear out the data
  // so it can be reset on another round.
  AuthCredentials credentials = auth_credentials_;
  auth_credentials_ = AuthCredentials();
  scoped_refptr<AuthChallengeInfo> auth_info;
  auth_info.swap(auth_info_);

  switch (result) {
    case NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION:
      // Defer to the URLRequest::Delegate, since the NetworkDelegate
      // didn't take an action.
      if (delegate_)
        delegate_->OnAuthRequired(this, auth_info.get());
      break;

    case NetworkDelegate::AUTH_REQUIRED_RESPONSE_SET_AUTH:
      SetAuth(credentials);
      break;

    case NetworkDelegate::AUTH_REQUIRED_RESPONSE_CANCEL_AUTH:
      CancelAuth();
      break;

    case NetworkDelegate::AUTH_REQUIRED_RESPONSE_IO_PENDING:
      NOTREACHED();
      break;
  }
}

void URLRequest::NotifyCertificateRequested(
    SSLCertRequestInfo* cert_request_info) {
  if (delegate_)
    delegate_->OnCertificateRequested(this, cert_request_info);
}

void URLRequest::NotifySSLCertificateError(const SSLInfo& ssl_info,
                                           bool fatal) {
  if (delegate_)
    delegate_->OnSSLCertificateError(this, ssl_info, fatal);
}

bool URLRequest::CanGetCookies(const CookieList& cookie_list) const {
  DCHECK(!(load_flags_ & LOAD_DO_NOT_SEND_COOKIES));
  if (network_delegate_) {
    return network_delegate_->CanGetCookies(*this, cookie_list);
  }
  return g_default_can_use_cookies;
}

bool URLRequest::CanSetCookie(const std::string& cookie_line,
                              CookieOptions* options) const {
  DCHECK(!(load_flags_ & LOAD_DO_NOT_SAVE_COOKIES));
  if (network_delegate_) {
    return network_delegate_->CanSetCookie(*this, cookie_line, options);
  }
  return g_default_can_use_cookies;
}


void URLRequest::NotifyReadCompleted(int bytes_read) {
  // Notify in case the entire URL Request has been finished.
  if (bytes_read <= 0)
    NotifyRequestCompleted();

  // Notify NetworkChangeNotifier that we just received network data.
  // This is to identify cases where the NetworkChangeNotifier thinks we
  // are off-line but we are still receiving network data (crbug.com/124069).
  if (bytes_read > 0 && !was_cached())
    NetworkChangeNotifier::NotifyDataReceived(url());

  if (delegate_)
    delegate_->OnReadCompleted(this, bytes_read);

  // Nothing below this line as OnReadCompleted may delete |this|.
}

void URLRequest::NotifyRequestCompleted() {
  // TODO(battre): Get rid of this check, according to willchan it should
  // not be needed.
  if (has_notified_completion_)
    return;

  is_pending_ = false;
  is_redirecting_ = false;
  has_notified_completion_ = true;
  if (network_delegate_)
    network_delegate_->NotifyCompleted(this, job_ != NULL);
}

void URLRequest::SetBlockedOnDelegate() {
  blocked_on_delegate_ = true;
  if (!load_state_param_.empty()) {
    net_log_.BeginEvent(NetLog::TYPE_URL_REQUEST_BLOCKED_ON_DELEGATE,
                        NetLog::StringCallback("delegate", &load_state_param_));
  } else {
    net_log_.BeginEvent(NetLog::TYPE_URL_REQUEST_BLOCKED_ON_DELEGATE);
  }
}

void URLRequest::SetUnblockedOnDelegate() {
  if (!blocked_on_delegate_)
    return;
  blocked_on_delegate_ = false;
  load_state_param_.clear();
  net_log_.EndEvent(NetLog::TYPE_URL_REQUEST_BLOCKED_ON_DELEGATE);
}

void URLRequest::set_stack_trace(const base::debug::StackTrace& stack_trace) {
  base::debug::StackTrace* stack_trace_copy =
      new base::debug::StackTrace(NULL, 0);
  *stack_trace_copy = stack_trace;
  stack_trace_.reset(stack_trace_copy);
}

const base::debug::StackTrace* URLRequest::stack_trace() const {
  return stack_trace_.get();
}

}  // namespace net
