// Copyright 2015 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/xhr/xml_http_request.h"

#include <algorithm>
#include <memory>
#include <utility>

#include "base/compiler_specific.h"
#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/task_runner.h"
#include "base/time/time.h"
#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/base/source_location.h"
#include "cobalt/base/tokens.h"
#include "cobalt/dom/dom_settings.h"
#include "cobalt/dom/performance.h"
#include "cobalt/dom/progress_event.h"
#include "cobalt/dom/window.h"
#include "cobalt/dom/xml_document.h"
#include "cobalt/dom_parser/xml_decoder.h"
#include "cobalt/loader/cors_preflight.h"
#include "cobalt/loader/fetcher_factory.h"
#include "cobalt/loader/url_fetcher_string_writer.h"
#include "cobalt/script/global_environment.h"
#include "cobalt/script/javascript_engine.h"
#include "cobalt/web/context.h"
#include "cobalt/web/csp_delegate.h"
#include "cobalt/web/environment_settings.h"
#include "cobalt/xhr/global_stats.h"
#include "cobalt/xhr/xhr_modify_headers.h"
#include "nb/memory_scope.h"
#include "net/http/http_util.h"

namespace cobalt {
namespace xhr {

using web::DOMException;

namespace {

// How many milliseconds must elapse between each progress event notification.
const int kProgressPeriodMs = 50;

const char* kResponseTypes[] = {
    "",             // kDefault
    "text",         // kText
    "json",         // kJson
    "document",     // kDocument
    "blob",         // kBlob
    "arraybuffer",  // kArrayBuffer
};

const char* kForbiddenMethods[] = {
    "connect", "trace", "track",
};

// https://www.w3.org/TR/resource-timing-1/#dom-performanceresourcetiming-initiatortype
const char* kPerformanceResourceTimingInitiatorType = "xmlhttprequest";

bool MethodNameToRequestType(const std::string& method,
                             net::URLFetcher::RequestType* request_type) {
  if (base::LowerCaseEqualsASCII(method, "get")) {
    *request_type = net::URLFetcher::GET;
  } else if (base::LowerCaseEqualsASCII(method, "post")) {
    *request_type = net::URLFetcher::POST;
  } else if (base::LowerCaseEqualsASCII(method, "head")) {
    *request_type = net::URLFetcher::HEAD;
  } else if (base::LowerCaseEqualsASCII(method, "delete")) {
    *request_type = net::URLFetcher::DELETE_REQUEST;
  } else if (base::LowerCaseEqualsASCII(method, "put")) {
    *request_type = net::URLFetcher::PUT;
  } else {
    return false;
  }
  return true;
}

#if !defined(COBALT_BUILD_TYPE_GOLD)
const char* kStateNames[] = {"Unsent", "Opened", "HeadersReceived", "Loading",
                             "Done"};
const char* kMethodNames[] = {"GET", "POST", "HEAD", "DELETE", "PUT"};

#if __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wtautological-compare"
#endif
const char* RequestTypeToMethodName(net::URLFetcher::RequestType request_type) {
  if (request_type >= 0 && request_type < arraysize(kMethodNames)) {
    return kMethodNames[request_type];
  } else {
    NOTREACHED();
    return "";
  }
}

const char* StateName(XMLHttpRequest::State state) {
  if (state >= 0 && state < arraysize(kStateNames)) {
    return kStateNames[state];
  } else {
    NOTREACHED();
    return "";
  }
}
#if __clang__
#pragma clang diagnostic push
#endif
#endif  // defined(COBALT_BUILD_TYPE_GOLD)

bool IsForbiddenMethod(const std::string& method) {
  for (size_t i = 0; i < arraysize(kForbiddenMethods); ++i) {
    if (base::LowerCaseEqualsASCII(method, kForbiddenMethods[i])) {
      return true;
    }
  }
  return false;
}

base::Token RequestErrorTypeName(XMLHttpRequest::RequestErrorType type) {
  switch (type) {
    case XMLHttpRequest::kNetworkError:
      return base::Tokens::error();
    case XMLHttpRequest::kTimeoutError:
      return base::Tokens::timeout();
    case XMLHttpRequest::kAbortError:
      return base::Tokens::abort();
  }
  NOTREACHED();
  return base::Token();
}

void FireProgressEvent(XMLHttpRequestEventTarget* target,
                       base::Token event_name) {
  if (!target) {
    return;
  }
  target->DispatchEvent(new dom::ProgressEvent(event_name));
}

void FireProgressEvent(XMLHttpRequestEventTarget* target,
                       base::Token event_name, uint64 loaded, uint64 total,
                       bool length_computable) {
  if (!target) {
    return;
  }
  target->DispatchEvent(
      new dom::ProgressEvent(event_name, loaded, total, length_computable));
}

#if !defined(COBALT_BUILD_TYPE_GOLD)
int s_xhr_sequence_num_ = 0;
#endif  // !defined(COBALT_BUILD_TYPE_GOLD)
// https://fetch.spec.whatwg.org/#concept-http-redirect-fetch
// 5. If request's redirect count is twenty, return a network error.
const int kRedirectLimit = 20;

std::string ClipUrl(const GURL& url, size_t length) {
  const std::string& spec = url.possibly_invalid_spec();
  if (spec.size() < length) {
    return spec;
  }

  size_t remain = length - 5;
  size_t head = remain / 2;
  size_t tail = remain - head;

  return spec.substr(0, head) + "[...]" + spec.substr(spec.size() - tail);
}
}  // namespace

bool XMLHttpRequestImpl::verbose_ = false;

XMLHttpRequest::XMLHttpRequest(script::EnvironmentSettings* settings)
    : XMLHttpRequestEventTarget(settings) {
  // Determine which implementation of XHR to use based on being in a window or
  // worker.
  if (environment_settings()
          ->context()
          ->GetWindowOrWorkerGlobalScope()
          ->IsWindow()) {
    xhr_impl_ = std::make_unique<DOMXMLHttpRequestImpl>(this);
  } else if (environment_settings()
                 ->context()
                 ->GetWindowOrWorkerGlobalScope()
                 ->IsDedicatedWorker() ||
             environment_settings()
                 ->context()
                 ->GetWindowOrWorkerGlobalScope()
                 ->IsServiceWorker()) {
    xhr_impl_ = std::make_unique<XMLHttpRequestImpl>(this);
  }
  xhr::GlobalStats::GetInstance()->Add(this);
#if !defined(COBALT_BUILD_TYPE_GOLD)
  xhr_id_ = ++s_xhr_sequence_num_;
#endif  // !defined(COBALT_BUILD_TYPE_GOLD)
}

XMLHttpRequest::~XMLHttpRequest() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  xhr::GlobalStats::GetInstance()->Remove(this);
}

void XMLHttpRequest::Abort() { xhr_impl_->Abort(); }
void XMLHttpRequest::Open(const std::string& method, const std::string& url,
                          bool async,
                          const base::Optional<std::string>& username,
                          const base::Optional<std::string>& password,
                          script::ExceptionState* exception_state) {
  xhr_impl_->Open(method, url, async, username, password, exception_state);
}

// Must be called after open(), but before send().
void XMLHttpRequest::SetRequestHeader(const std::string& header,
                                      const std::string& value,
                                      script::ExceptionState* exception_state) {
  xhr_impl_->SetRequestHeader(header, value, exception_state);
}

// Override the MIME type returned by the server.
// Call before Send(), otherwise throws InvalidStateError.
void XMLHttpRequest::OverrideMimeType(const std::string& mime_type,
                                      script::ExceptionState* exception_state) {
  xhr_impl_->OverrideMimeType(mime_type, exception_state);
}

void XMLHttpRequest::Send(const base::Optional<RequestBodyType>& request_body,
                          script::ExceptionState* exception_state) {
  xhr_impl_->Send(request_body, exception_state);
}

void XMLHttpRequest::Fetch(const FetchUpdateCallbackArg& fetch_callback,
                           const FetchModeCallbackArg& fetch_mode_callback,
                           const base::Optional<RequestBodyType>& request_body,
                           script::ExceptionState* exception_state) {
  xhr_impl_->Fetch(fetch_callback, fetch_mode_callback, request_body,
                   exception_state);
}

base::Optional<std::string> XMLHttpRequest::GetResponseHeader(
    const std::string& header) {
  return xhr_impl_->GetResponseHeader(header);
}
std::string XMLHttpRequest::GetAllResponseHeaders() {
  return xhr_impl_->GetAllResponseHeaders();
}

const std::string& XMLHttpRequest::response_text(
    script::ExceptionState* exception_state) {
  return xhr_impl_->response_text(exception_state);
}
scoped_refptr<dom::Document> XMLHttpRequest::response_xml(
    script::ExceptionState* exception_state) {
  return xhr_impl_->response_xml(exception_state);
}
base::Optional<XMLHttpRequest::ResponseType> XMLHttpRequest::response(
    script::ExceptionState* exception_state) {
  return xhr_impl_->response(exception_state);
}

int XMLHttpRequest::ready_state() const { return xhr_impl_->ready_state(); }
int XMLHttpRequest::status() const { return xhr_impl_->status(); }
std::string XMLHttpRequest::status_text() { return xhr_impl_->status_text(); }
void XMLHttpRequest::set_response_type(
    const std::string& response_type, script::ExceptionState* exception_state) {
  xhr_impl_->set_response_type(response_type, exception_state);
}
std::string XMLHttpRequest::response_type(
    script::ExceptionState* exception_state) const {
  return xhr_impl_->response_type(exception_state);
}

uint32 XMLHttpRequest::timeout() const { return xhr_impl_->timeout(); }
void XMLHttpRequest::set_timeout(uint32 timeout) {
  xhr_impl_->set_timeout(timeout);
}
bool XMLHttpRequest::with_credentials(
    script::ExceptionState* exception_state) const {
  return xhr_impl_->with_credentials(exception_state);
}
void XMLHttpRequest::set_with_credentials(
    bool b, script::ExceptionState* exception_state) {
  xhr_impl_->set_with_credentials(b, exception_state);
}

scoped_refptr<XMLHttpRequestUpload> XMLHttpRequest::upload() {
  return xhr_impl_->upload();
}

void XMLHttpRequest::set_verbose(bool verbose) {
  XMLHttpRequestImpl::set_verbose(verbose);
}
bool XMLHttpRequest::verbose() { return XMLHttpRequestImpl::verbose(); }

// net::URLFetcherDelegate interface
void XMLHttpRequest::OnURLFetchResponseStarted(const net::URLFetcher* source) {
  xhr_impl_->OnURLFetchResponseStarted(source);
}
void XMLHttpRequest::OnURLFetchDownloadProgress(const net::URLFetcher* source,
                                                int64_t current, int64_t total,
                                                int64_t current_network_bytes) {
  xhr_impl_->OnURLFetchDownloadProgress(source, current, total,
                                        current_network_bytes);
}
void XMLHttpRequest::OnURLFetchComplete(const net::URLFetcher* source) {
  xhr_impl_->OnURLFetchComplete(source);
}

void XMLHttpRequest::OnURLFetchUploadProgress(const net::URLFetcher* source,
                                              int64 current, int64 total) {
  xhr_impl_->OnURLFetchUploadProgress(source, current, total);
}
void XMLHttpRequest::OnRedirect(const net::HttpResponseHeaders& headers) {
  xhr_impl_->OnRedirect(headers);
}

// Called from bindings layer to tie objects' lifetimes to this XHR instance.
XMLHttpRequestUpload* XMLHttpRequest::upload_or_null() {
  return xhr_impl_->upload_or_null();
}

void XMLHttpRequest::ReportLoadTimingInfo(
    const net::LoadTimingInfo& timing_info) {
  xhr_impl_->ReportLoadTimingInfo(timing_info);
}
// Create Performance Resource Timing entry for XMLHttpRequest.
void XMLHttpRequest::GetLoadTimingInfoAndCreateResourceTiming() {
  xhr_impl_->GetLoadTimingInfoAndCreateResourceTiming();
}

void XMLHttpRequest::TraceMembers(script::Tracer* tracer) {
  XMLHttpRequestEventTarget::TraceMembers(tracer);
  xhr_impl_->TraceMembers(tracer);
}

XMLHttpRequestImpl::XMLHttpRequestImpl(XMLHttpRequest* xhr)
    : error_(false),
      is_cross_origin_(false),
      is_data_url_(false),
      is_redirect_(false),
      method_(net::URLFetcher::GET),
      response_body_(new URLFetcherResponseWriter::Buffer(
          URLFetcherResponseWriter::Buffer::kString)),
      response_type_(XMLHttpRequest::kDefault),
      state_(XMLHttpRequest::kUnsent),
      upload_listener_(false),
      with_credentials_(false),
      xhr_(xhr),
      active_requests_count_(0),
      http_status_(0),
      redirect_times_(0),
      sent_(false),
      settings_(xhr->environment_settings()),
      stop_timeout_(false),
      timeout_ms_(0),
      upload_complete_(false) {
  DCHECK(settings_);
}

void XMLHttpRequestImpl::Abort() {
  // https://www.w3.org/TR/2014/WD-XMLHttpRequest-20140130/#the-abort()-method
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  // Cancel any in-flight request and set error flag.
  TerminateRequest();
  bool abort_is_no_op = state_ == XMLHttpRequest::kUnsent ||
                        state_ == XMLHttpRequest::kDone ||
                        (state_ == XMLHttpRequest::kOpened && !sent_);
  if (!abort_is_no_op) {
    sent_ = false;
    HandleRequestError(XMLHttpRequest::kAbortError);
  }
  ChangeState(XMLHttpRequest::kUnsent);

  response_body_->Clear();
  response_array_buffer_reference_.reset();
}

// https://www.w3.org/TR/2014/WD-XMLHttpRequest-20140130/#the-open()-method
void XMLHttpRequestImpl::Open(const std::string& method, const std::string& url,
                              bool async,
                              const base::Optional<std::string>& username,
                              const base::Optional<std::string>& password,
                              script::ExceptionState* exception_state) {
  TRACK_MEMORY_SCOPE("XHR");

  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  XMLHttpRequest::State previous_state = state_;

  // Cancel any outstanding request.
  TerminateRequest();
  state_ = XMLHttpRequest::kUnsent;

  if (!async) {
    DLOG(ERROR) << "synchronous XHR is not supported";
    web::DOMException::Raise(web::DOMException::kInvalidStateErr,
                             exception_state);
    return;
  }

  base_url_ = settings_->base_url();

  if (IsForbiddenMethod(method)) {
    web::DOMException::Raise(web::DOMException::kSecurityErr, exception_state);
    return;
  }

  if (!MethodNameToRequestType(method, &method_)) {
    web::DOMException::Raise(web::DOMException::kSyntaxErr, exception_state);
    return;
  }

  request_url_ = base_url_.Resolve(url);
  if (!request_url_.is_valid()) {
    web::DOMException::Raise(web::DOMException::kSyntaxErr, exception_state);
    return;
  }

  web::CspDelegate* csp = csp_delegate();
  if (csp && !csp->CanLoad(web::CspDelegate::kXhr, request_url_, false)) {
    web::DOMException::Raise(web::DOMException::kSecurityErr, exception_state);
    return;
  }

  sent_ = false;
  stop_timeout_ = false;

  PrepareForNewRequest();

  // Check previous state to avoid dispatching readyState event when calling
  // open several times in a row.
  if (previous_state != XMLHttpRequest::kOpened) {
    ChangeState(XMLHttpRequest::kOpened);
  } else {
    state_ = XMLHttpRequest::kOpened;
  }
}

void XMLHttpRequestImpl::SetRequestHeader(
    const std::string& header, const std::string& value,
    script::ExceptionState* exception_state) {
  TRACK_MEMORY_SCOPE("XHR");
  // https://www.w3.org/TR/2014/WD-XMLHttpRequest-20140130/#dom-xmlhttprequest-setrequestheader
  if (state_ != XMLHttpRequest::kOpened || sent_) {
    web::DOMException::Raise(web::DOMException::kInvalidStateErr,
                             exception_state);
    return;
  }

  if (!net::HttpUtil::IsValidHeaderName(header) ||
      !net::HttpUtil::IsValidHeaderValue(value)) {
    DLOG(WARNING) << "Rejecting invalid header " << header << " : " << value;
    return;
  }

  if (!net::HttpUtil::IsSafeHeader(header)) {
    DLOG(WARNING) << "Rejecting unsafe header " << header;
    return;
  }

  // Write the header if it is not set.
  // If it is, append it to the existing one.
  std::string cur_value;
  if (request_headers_.GetHeader(header, &cur_value)) {
    cur_value += ", " + value;
    request_headers_.SetHeader(header, cur_value);
  } else {
    request_headers_.SetHeader(header, value);
  }
}

void XMLHttpRequestImpl::OverrideMimeType(
    const std::string& override_mime, script::ExceptionState* exception_state) {
  // https://www.w3.org/TR/2014/WD-XMLHttpRequest-20140130/#dom-xmlhttprequest-overridemimetype
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  if (state_ == XMLHttpRequest::kLoading || state_ == XMLHttpRequest::kDone) {
    web::DOMException::Raise(web::DOMException::kInvalidStateErr,
                             exception_state);
    return;
  }

  // Try to parse the given override. If it fails, throw an exception.
  // Otherwise, we'll replace the content-type header in the response headers
  // once we have them.
  std::string mime_type;
  std::string charset;
  bool had_charset = false;
  net::HttpUtil::ParseContentType(override_mime, &mime_type, &charset,
                                  &had_charset, NULL);
  if (!mime_type.length()) {
    web::DOMException::Raise(web::DOMException::kSyntaxErr, exception_state);
    return;
  }
  mime_type_override_ = mime_type;
}

void XMLHttpRequestImpl::Send(
    const base::Optional<XMLHttpRequest::RequestBodyType>& request_body,
    script::ExceptionState* exception_state) {
  TRACK_MEMORY_SCOPE("XHR");
  // https://www.w3.org/TR/2014/WD-XMLHttpRequest-20140130/#the-send()-method
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  // Step 1
  if (state_ != XMLHttpRequest::kOpened) {
    web::DOMException::Raise(web::DOMException::kInvalidStateErr,
                             exception_state);
    return;
  }
  // Step 2
  if (sent_) {
    web::DOMException::Raise(web::DOMException::kInvalidStateErr,
                             exception_state);
    return;
  }

  // Step 3 - 7
  error_ = false;
  upload_complete_ = false;

#if defined(COBALT_ENABLE_XHR_HEADER_FILTERING)
  CobaltXhrModifyHeader(request_url_, &request_headers_);
#endif

  // Add request body, if appropriate.
  if ((method_ == net::URLFetcher::POST || method_ == net::URLFetcher::PUT) &&
      request_body) {
    bool has_content_type =
        request_headers_.HasHeader(net::HttpRequestHeaders::kContentType);
    if (request_body->IsType<std::string>()) {
      request_body_text_.assign(request_body->AsType<std::string>());
      if (!has_content_type) {
        // We're assuming that request_body is UTF-8 encoded.
        request_headers_.SetHeader(net::HttpRequestHeaders::kContentType,
                                   "text/plain;charset=UTF-8");
      }
    } else if (request_body
                   ->IsType<script::Handle<script::ArrayBufferView> >()) {
      script::Handle<script::ArrayBufferView> view =
          request_body->AsType<script::Handle<script::ArrayBufferView> >();
      if (view->ByteLength()) {
        const char* start = reinterpret_cast<const char*>(view->RawData());
        request_body_text_.assign(start + view->ByteOffset(),
                                  view->ByteLength());
      }
    } else if (request_body->IsType<script::Handle<script::ArrayBuffer> >()) {
      script::Handle<script::ArrayBuffer> array_buffer =
          request_body->AsType<script::Handle<script::ArrayBuffer> >();
      if (array_buffer->ByteLength()) {
        const char* start = reinterpret_cast<const char*>(array_buffer->Data());
        request_body_text_.assign(start, array_buffer->ByteLength());
      }
    }
  } else {
    upload_complete_ = true;
  }
  // Step 8
  if (upload_) {
    upload_listener_ = upload_->HasOneOrMoreAttributeEventListener();
  }
  origin_ = loader::Origin(settings_->GetOrigin());
  // Step 9
  sent_ = true;
  // Now that a send is happening, prevent this object
  // from being collected until it's complete or aborted
  // if no currently active request has called it before.
  IncrementActiveRequests();
  FireProgressEvent(xhr_, base::Tokens::loadstart());
  if (!upload_complete_) {
    FireProgressEvent(upload_, base::Tokens::loadstart());
  }

  // The loadstart callback may abort or modify the XHR request in some way.
  // 11.3. If state is not opened or the send() flag is unset, then return.
  if (state_ == XMLHttpRequest::kOpened && sent_) {
    this->StartRequest(request_body_text_);

    // Start the timeout timer running, if applicable.
    send_start_time_ = base::TimeTicks::Now();
    if (timeout_ms_) {
      StartTimer(base::TimeDelta());
    }
    // Timer for throttling progress events.
    upload_last_progress_time_ = base::TimeTicks();
    last_progress_time_ = base::TimeTicks();
  }
}

void XMLHttpRequestImpl::Fetch(
    const FetchUpdateCallbackArg& fetch_callback,
    const FetchModeCallbackArg& fetch_mode_callback,
    const base::Optional<XMLHttpRequest::RequestBodyType>& request_body,
    script::ExceptionState* exception_state) {
  fetch_callback_.reset(
      new FetchUpdateCallbackArg::Reference(xhr_, fetch_callback));
  fetch_mode_callback_.reset(
      new FetchModeCallbackArg::Reference(xhr_, fetch_mode_callback));
  Send(request_body, exception_state);
}

base::Optional<std::string> XMLHttpRequestImpl::GetResponseHeader(
    const std::string& header) {
  // https://www.w3.org/TR/2014/WD-XMLHttpRequest-20140130/#the-getresponseheader()-method
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  if (state_ == XMLHttpRequest::kUnsent || state_ == XMLHttpRequest::kOpened ||
      error_) {
    return base::nullopt;
  }

  // Set-Cookie should be stripped from the response headers in OnDone().
  if (base::LowerCaseEqualsASCII(header, "set-cookie") ||
      base::LowerCaseEqualsASCII(header, "set-cookie2")) {
    return base::nullopt;
  }

  bool found;
  std::string value;
  if (net::HttpUtil::IsNonCoalescingHeader(header)) {
    // A non-coalescing header may contain commas in the value, e.g. Date:
    found = http_response_headers_->EnumerateHeader(NULL, header, &value);
  } else {
    found = http_response_headers_->GetNormalizedHeader(header, &value);
  }
  return found ? base::make_optional(value) : base::nullopt;
}

std::string XMLHttpRequestImpl::GetAllResponseHeaders() {
  // https://www.w3.org/TR/2014/WD-XMLHttpRequest-20140130/#the-getallresponseheaders()-method
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  std::string output;

  if (state_ == XMLHttpRequest::kUnsent || state_ == XMLHttpRequest::kOpened ||
      error_) {
    return output;
  }

  size_t iter = 0;
  std::string name;
  std::string value;

  while (http_response_headers_->EnumerateHeaderLines(&iter, &name, &value)) {
    output += name;
    output += ": ";
    output += value;
    output += "\r\n";
  }
  return output;
}

const std::string& XMLHttpRequestImpl::response_text(
    script::ExceptionState* exception_state) {
  // https://www.w3.org/TR/2014/WD-XMLHttpRequest-20140130/#the-responsetext-attribute
  if (response_type_ != XMLHttpRequest::kDefault &&
      response_type_ != XMLHttpRequest::kText) {
    web::DOMException::Raise(web::DOMException::kInvalidStateErr,
                             exception_state);
  }
  if (error_ ||
      (state_ != XMLHttpRequest::kLoading && state_ != XMLHttpRequest::kDone)) {
    return base::EmptyString();
  }

  // Note that the conversion from |response_body_| to std::string when |state_|
  // isn't kDone isn't efficient for large responses.  Fortunately this feature
  // is rarely used.
  if (state_ == XMLHttpRequest::kLoading) {
    LOG_ONCE(WARNING)
        << "Retrieving responseText while loading can be inefficient.";
    return response_body_->GetTemporaryReferenceOfString();
  }
  return response_body_->GetReferenceOfStringAndSeal();
}

// https://www.w3.org/TR/2014/WD-XMLHttpRequest-20140130/#the-responsexml-attribute
scoped_refptr<dom::Document> XMLHttpRequestImpl::response_xml(
    script::ExceptionState* exception_state) {
  // Workers don't have access to DOM APIs, including Document objects. Nothing
  // to do.
  // https://www.w3.org/TR/2012/CR-workers-20120501/#apis-available-to-workers
  return NULL;
}

base::Optional<XMLHttpRequest::ResponseType> XMLHttpRequestImpl::response(
    script::ExceptionState* exception_state) {
  // https://www.w3.org/TR/2014/WD-XMLHttpRequest-20140130/#response
  switch (response_type_) {
    case XMLHttpRequest::kDefault:
    case XMLHttpRequest::kText:
      return XMLHttpRequest::ResponseType(response_text(exception_state));
    case XMLHttpRequest::kArrayBuffer: {
      script::Handle<script::ArrayBuffer> maybe_array_buffer_response =
          response_array_buffer();
      if (maybe_array_buffer_response.IsEmpty()) {
        return base::nullopt;
      }
      return XMLHttpRequest::ResponseType(maybe_array_buffer_response);
    }
    case XMLHttpRequest::kJson:
    case XMLHttpRequest::kDocument:
    case XMLHttpRequest::kBlob:
    case XMLHttpRequest::kResponseTypeCodeMax:
      NOTIMPLEMENTED() << "Unsupported response_type_ "
                       << response_type(exception_state);
  }
  return base::nullopt;
}

int XMLHttpRequestImpl::status() const {
  // https://www.w3.org/TR/2014/WD-XMLHttpRequest-20140130/#the-status-attribute
  if (state_ == XMLHttpRequest::kUnsent || state_ == XMLHttpRequest::kOpened ||
      error_) {
    return 0;
  } else {
    return http_status_;
  }
}

std::string XMLHttpRequestImpl::status_text() {
  // https://www.w3.org/TR/2014/WD-XMLHttpRequest-20140130/#the-statustext-attribute
  if (state_ == XMLHttpRequest::kUnsent || state_ == XMLHttpRequest::kOpened ||
      error_) {
    return std::string();
  }

  return http_response_headers_->GetStatusText();
}

void XMLHttpRequestImpl::set_response_type(
    const std::string& response_type, script::ExceptionState* exception_state) {
  if (state_ == XMLHttpRequest::kLoading || state_ == XMLHttpRequest::kDone) {
    web::DOMException::Raise(web::DOMException::kInvalidStateErr,
                             exception_state);
    return;
  }
  for (size_t i = 0; i < arraysize(kResponseTypes); ++i) {
    if (response_type == kResponseTypes[i]) {
      DCHECK_LT(i, XMLHttpRequest::kResponseTypeCodeMax);
      response_type_ = static_cast<XMLHttpRequest::ResponseTypeCode>(i);
      return;
    }
  }

  DLOG(WARNING) << "Unexpected response type " << response_type;
}

std::string XMLHttpRequestImpl::response_type(
    script::ExceptionState* unused) const {
  // https://www.w3.org/TR/2014/WD-XMLHttpRequest-20140130/#the-responsetype-attribute
  DCHECK_LT(response_type_, arraysize(kResponseTypes));
  return kResponseTypes[response_type_];
}

void XMLHttpRequestImpl::set_timeout(uint32 timeout) {
  // https://www.w3.org/TR/2014/WD-XMLHttpRequest-20140130/#the-timeout-attribute
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  timeout_ms_ = timeout;
  if (timeout_ms_ == 0) {
    stop_timeout_ = true;
    timer_.Stop();
  } else if (sent_) {
    // Timeout was set while request was in flight. Timeout is relative to
    // the start of the request.
    StartTimer(base::TimeTicks::Now() - send_start_time_);
  }
}

bool XMLHttpRequestImpl::with_credentials(
    script::ExceptionState* unused) const {
  return with_credentials_;
}

void XMLHttpRequestImpl::set_with_credentials(
    bool with_credentials, script::ExceptionState* exception_state) {
  // https://www.w3.org/TR/2014/WD-XMLHttpRequest-20140130/#the-withcredentials-attribute
  if ((state_ != XMLHttpRequest::kUnsent &&
       state_ != XMLHttpRequest::kOpened) ||
      sent_) {
    web::DOMException::Raise(web::DOMException::kInvalidStateErr,
                             exception_state);
    return;
  }
  with_credentials_ = with_credentials;
}

scoped_refptr<XMLHttpRequestUpload> XMLHttpRequestImpl::upload() {
  if (!upload_) {
    upload_ = new XMLHttpRequestUpload(settings_);
  }
  return upload_;
}

void XMLHttpRequestImpl::OnURLFetchResponseStarted(
    const net::URLFetcher* source) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  http_status_ = source->GetResponseCode();
  // Don't handle a response without headers.
  if (!source->GetResponseHeaders()) {
    HandleRequestError(XMLHttpRequest::kNetworkError);
    return;
  }
  // Copy the response headers from the fetcher. It's not safe for us to
  // modify the existing ones as they may be in use on the network thread.
  http_response_headers_ =
      new net::HttpResponseHeaders(source->GetResponseHeaders()->raw_headers());

  // Perform a CORS Check on response headers at their arrival and raise
  // Network Error when the Check fails.
  if (is_cross_origin_) {
    if (!loader::CORSPreflight::CORSCheck(*http_response_headers_,
                                          origin_.SerializedOrigin(),
                                          with_credentials_)) {
      HandleRequestError(XMLHttpRequest::kNetworkError);
      return;
    }
  }

  // Discard these as required by XHR spec.
  http_response_headers_->RemoveHeader("Set-Cookie2");
  http_response_headers_->RemoveHeader("Set-Cookie");

  http_response_headers_->GetMimeType(&response_mime_type_);

  if (mime_type_override_.length()) {
    http_response_headers_->RemoveHeader("Content-Type");
    http_response_headers_->AddHeader(std::string("Content-Type: ") +
                                      mime_type_override_);
  }

  if (fetch_mode_callback_) {
    fetch_mode_callback_->value().Run(is_cross_origin_);
  }

  // Further filter response headers as XHR's mode is cors
  if (is_cross_origin_) {
    size_t iter = 0;
    std::string name, value;
    std::vector<std::pair<std::string, std::string> > header_names_to_discard;
    std::vector<std::string> expose_headers;
    loader::CORSPreflight::GetServerAllowedHeaders(*http_response_headers_,
                                                   &expose_headers);
    while (http_response_headers_->EnumerateHeaderLines(&iter, &name, &value)) {
      if (!loader::CORSPreflight::IsSafeResponseHeader(name, expose_headers,
                                                       with_credentials_)) {
        header_names_to_discard.push_back(std::make_pair(name, value));
      }
    }
    for (const auto& header : header_names_to_discard) {
      http_response_headers_->RemoveHeaderLine(header.first, header.second);
    }
  }

  if (is_data_url_) {
    size_t iter = 0;
    std::string name, value;
    std::vector<std::pair<std::string, std::string> > header_names_to_discard;
    while (http_response_headers_->EnumerateHeaderLines(&iter, &name, &value)) {
      if (name != net::HttpRequestHeaders::kContentType) {
        header_names_to_discard.push_back(std::make_pair(name, value));
      }
    }
    for (const auto& header : header_names_to_discard) {
      http_response_headers_->RemoveHeaderLine(header.first, header.second);
    }
  }

  ChangeState(XMLHttpRequest::kHeadersReceived);

  UpdateProgress(0);
}

void XMLHttpRequestImpl::OnURLFetchDownloadProgress(
    const net::URLFetcher* source, int64_t current, int64_t total,
    int64_t current_network_bytes) {
  TRACK_MEMORY_SCOPE("XHR");
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK_NE(state_, XMLHttpRequest::kDone);

  if (response_body_->HasProgressSinceLastGetAndReset() == 0) {
    return;
  }

  // Signal to JavaScript that new data is now available.
  ChangeState(XMLHttpRequest::kLoading);

  if (fetch_callback_) {
    std::string downloaded_data;
    response_body_->GetAndResetDataAndDownloadProgress(&downloaded_data);
    script::Handle<script::Uint8Array> data =
        script::Uint8Array::New(settings_->context()->global_environment(),
                                downloaded_data.data(), downloaded_data.size());
    fetch_callback_->value().Run(data);
  }

  // Send a progress notification if at least 50ms have elapsed.
  const base::TimeTicks now = base::TimeTicks::Now();
  const base::TimeDelta elapsed(now - last_progress_time_);
  if (elapsed > base::TimeDelta::FromMilliseconds(kProgressPeriodMs)) {
    last_progress_time_ = now;
    if (fetch_callback_) {
      // TODO: Investigate if we have to fire progress event with 0 loaded bytes
      //       when used as Fetch API.
      UpdateProgress(0);
    } else {
      UpdateProgress(response_body_->GetAndResetDownloadProgress());
    }
  }
}


void XMLHttpRequestImpl::OnURLFetchComplete(const net::URLFetcher* source) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  if (source->GetResponseHeaders()) {
    if (source->GetResponseHeaders()->IsRedirect(NULL)) {
      // To do CORS Check and Send potential preflight, we used
      // SetStopOnRedirect to terminate request on redirect and OnRedict
      // function will deal with the early termination and send preflight if
      // needed.
      OnRedirect(*source->GetResponseHeaders());
      return;
    }
    // Create Performance Resource Timing entry after fetch complete.
    this->GetLoadTimingInfoAndCreateResourceTiming();
  }

  const net::URLRequestStatus& status = source->GetStatus();
  if (status.is_success()) {
    stop_timeout_ = true;
    if (error_) {
      // Ensure the fetch callbacks are reset when URL fetch is complete,
      // regardless of error status.
      fetch_callback_.reset();
      fetch_mode_callback_.reset();
      return;
    }

    // Ensure all fetched data is read and transferred to this XHR. This should
    // only be done for successful and error-free fetches.
    OnURLFetchDownloadProgress(source, 0, 0, 0);

    // The request may have completed too quickly, before URLFetcher's upload
    // progress timer had a chance to inform us upload is finished.
    if (!upload_complete_ && upload_listener_) {
      upload_complete_ = true;
      FireProgressEvent(upload_, base::Tokens::progress());
      FireProgressEvent(upload_, base::Tokens::load());
      FireProgressEvent(upload_, base::Tokens::loadend());
    }
    ChangeState(XMLHttpRequest::kDone);
    UpdateProgress(response_body_->GetAndResetDownloadProgress());
    // Undo the ref we added in Send()
    DecrementActiveRequests();
  } else {
    HandleRequestError(XMLHttpRequest::kNetworkError);
  }

  fetch_callback_.reset();
  fetch_mode_callback_.reset();
}

void XMLHttpRequestImpl::OnURLFetchUploadProgress(const net::URLFetcher* source,
                                                  int64 current_val,
                                                  int64 total_val) {
  TRACK_MEMORY_SCOPE("XHR");
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  if (upload_complete_) {
    return;
  }

  uint64 current = static_cast<uint64>(current_val);
  uint64 total = static_cast<uint64>(total_val);
  if (current == total) {
    upload_complete_ = true;
  }

  // Fire a progress event if either the upload just completed, or if enough
  // time has elapsed since we sent the last one.

  // https://xhr.spec.whatwg.org/#dom-xmlhttprequest-send step 11.4.
  // To process request body for request, run these subsubsteps:
  // 1.not roughly 50ms have passed since these subsubsteps were last invoked,
  // terminate these subsubsteps.
  // 2. If upload listener flag is set, then fire a progress event named
  // progress on the XMLHttpRequestUpload object with request's body's
  // transmitted bytes and request's body's total bytes.
  if (!upload_listener_) {
    return;
  }
  const base::TimeTicks now = base::TimeTicks::Now();
  const base::TimeDelta elapsed(now - upload_last_progress_time_);
  if (upload_complete_ ||
      (elapsed > base::TimeDelta::FromMilliseconds(kProgressPeriodMs))) {
    FireProgressEvent(upload_, base::Tokens::progress(), current, total,
                      total != 0);
    upload_last_progress_time_ = now;
  }

  // To process request end-of-body for request, run these subsubsteps:
  // 2. if upload listener flag is unset, then terminate these subsubsteps.
  if (upload_complete_) {
    FireProgressEvent(upload_, base::Tokens::load(), current, total,
                      total != 0);
    FireProgressEvent(upload_, base::Tokens::loadend(), current, total,
                      total != 0);
  }
}

void XMLHttpRequestImpl::OnRedirect(const net::HttpResponseHeaders& headers) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  GURL new_url = url_fetcher_->GetURL();
  // Since we moved redirect from url_request to here, we also need to
  // handle redirecting too many times.
  if (redirect_times_ >= kRedirectLimit) {
    DLOG(INFO) << "XHR's redirect times hit limit, aborting request.";
    HandleRequestError(XMLHttpRequest::kNetworkError);
    return;
  }

  // This function is designed to be called by url_fetcher_core::
  // OnReceivedRedirect
  // https://fetch.spec.whatwg.org/#concept-http-redirect-fetch
  // 7. If request’s mode is "cors", request’s origin is not same origin
  // with actualResponse’s location URL’s origin, and actualResponse’s
  // location URL includes credentials, then return a network error.
  // 8. If CORS flag is set and actualResponse’s location URL includes
  // credentials, then return a network error.
  if (new_url.has_username() || new_url.has_password()) {
    if (loader::Origin(new_url) != loader::Origin(request_url_)) {
      DLOG(INFO) << "XHR is redirected to cross-origin url with credentials, "
                    "aborting request for security reasons.";
      HandleRequestError(XMLHttpRequest::kNetworkError);
      return;
    } else if (is_cross_origin_) {
      DLOG(INFO) << "XHR is redirected with credentials and cors_flag set, "
                    "aborting request for security reasons.";
      HandleRequestError(XMLHttpRequest::kNetworkError);
      return;
    }
  }
  if (!new_url.is_valid()) {
    HandleRequestError(XMLHttpRequest::kNetworkError);
    return;
  }
  // This is a redirect. Re-check the CSP.
  web::CspDelegate* csp = csp_delegate();
  if (csp &&
      !csp->CanLoad(web::CspDelegate::kXhr, new_url, true /* is_redirect */)) {
    HandleRequestError(XMLHttpRequest::kNetworkError);
    return;
  }
  // CORS check for the received response
  if (is_cross_origin_) {
    if (!loader::CORSPreflight::CORSCheck(headers, origin_.SerializedOrigin(),
                                          with_credentials_)) {
      HandleRequestError(XMLHttpRequest::kNetworkError);
      return;
    }
  }
  is_redirect_ = true;
  // If CORS flag is set and actualResponse’s location URL’s origin is not
  // same origin with request’s current url’s origin, then set request’s
  // origin to a unique opaque origin.
  if (loader::Origin(new_url) != loader::Origin(request_url_)) {
    if (is_cross_origin_) {
      origin_ = loader::Origin();
    } else {
      origin_ = loader::Origin(request_url_);
      is_cross_origin_ = true;
    }
  }
  // Send out preflight if needed
  int http_status_code = headers.response_code();
  if ((http_status_code == 303) ||
      ((http_status_code == 301 || http_status_code == 302) &&
       (method_ == net::URLFetcher::POST))) {
    method_ = net::URLFetcher::GET;
    request_body_text_.clear();
  }
  request_url_ = new_url;
  redirect_times_++;
  this->StartRequest(request_body_text_);
}

void XMLHttpRequestImpl::ReportLoadTimingInfo(
    const net::LoadTimingInfo& timing_info) {
  load_timing_info_ = timing_info;
}

void XMLHttpRequestImpl::GetLoadTimingInfoAndCreateResourceTiming() {
  // Performance info is only available through window currently. Not available
  // in workers.
  return;
}

void XMLHttpRequestImpl::TraceMembers(script::Tracer* tracer) {
  tracer->Trace(upload_);
}

web::CspDelegate* XMLHttpRequestImpl::csp_delegate() const {
  DCHECK(settings_);
  DCHECK(settings_->context());
  DCHECK(settings_->context()->GetWindowOrWorkerGlobalScope());
  return settings_->context()->GetWindowOrWorkerGlobalScope()->csp_delegate();
}

void XMLHttpRequestImpl::TerminateRequest() {
  error_ = true;
  corspreflight_.reset(NULL);
  url_fetcher_.reset(NULL);
}

void XMLHttpRequestImpl::HandleRequestError(
    XMLHttpRequest::RequestErrorType request_error_type) {
  // https://www.w3.org/TR/XMLHttpRequest/#timeout-error
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DLOG_IF(INFO, verbose())
      << __FUNCTION__ << " (" << RequestErrorTypeName(request_error_type)
      << ") " << *xhr_ << std::endl
      << script::StackTraceToString(
             settings_->context()->global_environment()->GetStackTrace(
                 0 /*max_frames*/));
  stop_timeout_ = true;
  // Step 1
  TerminateRequest();
  // Steps 2-4
  // Change state and fire readystatechange event.
  ChangeState(XMLHttpRequest::kDone);

  base::Token error_name = RequestErrorTypeName(request_error_type);
  // Step 5
  if (!upload_complete_) {
    upload_complete_ = true;
    FireProgressEvent(upload_, base::Tokens::progress());
    FireProgressEvent(upload_, error_name);
    FireProgressEvent(upload_, base::Tokens::loadend());
  }

  // Steps 6-8
  FireProgressEvent(xhr_, base::Tokens::progress());
  FireProgressEvent(xhr_, error_name);
  FireProgressEvent(xhr_, base::Tokens::loadend());

  fetch_callback_.reset();
  fetch_mode_callback_.reset();
  DecrementActiveRequests();
}

void XMLHttpRequestImpl::OnTimeout() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  if (!stop_timeout_) {
    HandleRequestError(XMLHttpRequest::kTimeoutError);
  }
}

void XMLHttpRequestImpl::StartTimer(base::TimeDelta time_since_send) {
  // Subtract any time that has already elapsed from the timeout.
  // This is in case the user has set a timeout after send() was already in
  // flight.
  base::TimeDelta delay = std::max(
      base::TimeDelta(),
      base::TimeDelta::FromMilliseconds(timeout_ms_) - time_since_send);

  // Queue the callback even if delay ends up being zero, to preserve the
  // previous semantics.
  timer_.Start(FROM_HERE, delay, this, &XMLHttpRequestImpl::OnTimeout);
}

void XMLHttpRequestImpl::ChangeState(XMLHttpRequest::State new_state) {
  // Always dispatch state change events for LOADING, also known as
  // INTERACTIVE, so that clients can get partial data (XHR streaming).
  // This is to match the behavior of Chrome (which took it from Firefox).
  if (state_ == new_state && new_state != XMLHttpRequest::kLoading) {
    return;
  }

  state_ = new_state;
  if (state_ != XMLHttpRequest::kUnsent) {
    xhr_->DispatchEvent(new web::Event(base::Tokens::readystatechange()));
  }
}

script::Handle<script::ArrayBuffer>
XMLHttpRequestImpl::response_array_buffer() {
  TRACK_MEMORY_SCOPE("XHR");
  // https://www.w3.org/TR/XMLHttpRequest/#response-entity-body
  if (error_ || state_ != XMLHttpRequest::kDone) {
    // Return a handle holding a nullptr.
    return script::Handle<script::ArrayBuffer>();
  }
  if (!response_array_buffer_reference_) {
    // The request is done so it is safe to only keep the ArrayBuffer and clear
    // |response_body_|.  As |response_body_| will not be used unless the
    // request is re-opened.
    std::unique_ptr<script::PreallocatedArrayBufferData> downloaded_data(
        new script::PreallocatedArrayBufferData());
    response_body_->GetAndResetData(downloaded_data.get());
    auto array_buffer = script::ArrayBuffer::New(
        settings_->context()->global_environment(), std::move(downloaded_data));
    response_array_buffer_reference_.reset(
        new script::ScriptValue<script::ArrayBuffer>::Reference(xhr_,
                                                                array_buffer));
    return array_buffer;
  } else {
    return script::Handle<script::ArrayBuffer>(
        *response_array_buffer_reference_);
  }
}

void XMLHttpRequestImpl::UpdateProgress(int64_t received_length) {
  DCHECK(http_response_headers_);
  const int64 content_length = http_response_headers_->GetContentLength();
  const bool length_computable =
      content_length > 0 && received_length <= content_length;
  const uint64 total =
      length_computable ? static_cast<uint64>(content_length) : 0;

  DLOG_IF(INFO, verbose()) << __FUNCTION__ << " (" << received_length << " / "
                           << total << ") " << *xhr_;

  if (state_ == XMLHttpRequest::kDone) {
    FireProgressEvent(xhr_, base::Tokens::load(),
                      static_cast<uint64>(received_length), total,
                      length_computable);
    FireProgressEvent(xhr_, base::Tokens::loadend(),
                      static_cast<uint64>(received_length), total,
                      length_computable);
  } else {
    FireProgressEvent(xhr_, base::Tokens::progress(),
                      static_cast<uint64>(received_length), total,
                      length_computable);
  }
}

void XMLHttpRequestImpl::StartRequest(const std::string& request_body) {
  TRACK_MEMORY_SCOPE("XHR");
  LOG(INFO) << "Fetching: " << ClipUrl(request_url_, 200);

  response_array_buffer_reference_.reset();

  network::NetworkModule* network_module =
      settings_->context()->fetcher_factory()->network_module();
  url_fetcher_ = net::URLFetcher::Create(request_url_, method_, xhr_);
  ++url_fetcher_generation_;
  url_fetcher_->SetRequestContext(network_module->url_request_context_getter());
  if (fetch_callback_) {
    response_body_ = new URLFetcherResponseWriter::Buffer(
        URLFetcherResponseWriter::Buffer::kString);
    response_body_->DisablePreallocate();
  } else {
    response_body_ = new URLFetcherResponseWriter::Buffer(
        response_type_ == XMLHttpRequest::kArrayBuffer
            ? URLFetcherResponseWriter::Buffer::kArrayBuffer
            : URLFetcherResponseWriter::Buffer::kString);
  }
  std::unique_ptr<net::URLFetcherResponseWriter> download_data_writer(
      new URLFetcherResponseWriter(response_body_));
  url_fetcher_->SaveResponseWithWriter(std::move(download_data_writer));
  // Don't retry, let the caller deal with it.
  url_fetcher_->SetAutomaticallyRetryOn5xx(false);
  url_fetcher_->SetExtraRequestHeaders(request_headers_.ToString());

  // We want to do cors check and preflight during redirects
  url_fetcher_->SetStopOnRedirect(true);

  if (request_body.size()) {
    // If applicable, the request body Content-Type is already set in
    // request_headers.
    url_fetcher_->SetUploadData("", request_body);
  }

  // We let data url fetch resources freely but with no response headers.
  is_data_url_ = is_data_url_ || request_url_.SchemeIs("data");
  is_cross_origin_ = (is_redirect_ && is_cross_origin_) ||
                     (origin_ != loader::Origin(request_url_) && !is_data_url_);
  is_redirect_ = false;
  // If the CORS flag is set, httpRequest’s method is neither `GET` nor `HEAD`
  // or httpRequest’s mode is "websocket", then append `Origin`/httpRequest’s
  // origin, serialized and UTF-8 encoded, to httpRequest’s header list.
  if (is_cross_origin_ ||
      (method_ != net::URLFetcher::GET && method_ != net::URLFetcher::HEAD)) {
    url_fetcher_->AddExtraRequestHeader("Origin:" + origin_.SerializedOrigin());
  }
  bool dopreflight = false;
  if (is_cross_origin_) {
    corspreflight_.reset(new cobalt::loader::CORSPreflight(
        request_url_, method_, network_module,
        base::Bind(&DOMXMLHttpRequestImpl::CORSPreflightSuccessCallback,
                   base::Unretained(this)),
        origin_.SerializedOrigin(),
        base::Bind(&DOMXMLHttpRequestImpl::CORSPreflightErrorCallback,
                   base::Unretained(this)),
        settings_->context()
            ->GetWindowOrWorkerGlobalScope()
            ->get_preflight_cache()));
    corspreflight_->set_headers(request_headers_);
    // For cross-origin requests, don't send or save auth data / cookies unless
    // withCredentials was set.
    // To make a cross-origin request, add origin, referrer source, credentials,
    // omit credentials flag, force preflight flag
    if (!with_credentials_) {
      const uint32 kDisableCookiesLoadFlags =
          net::LOAD_NORMAL | net::LOAD_DO_NOT_SAVE_COOKIES |
          net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SEND_AUTH_DATA;
      url_fetcher_->SetLoadFlags(kDisableCookiesLoadFlags);
    } else {
      // For credentials mode: If the withCredentials attribute value is true,
      // "include", and "same-origin" otherwise.
      corspreflight_->set_credentials_mode_is_include(true);
    }
    corspreflight_->set_force_preflight(upload_listener_);
    dopreflight = corspreflight_->Send();
  }
  DLOG_IF(INFO, verbose()) << __FUNCTION__ << *xhr_;
  if (!dopreflight) {
    DCHECK(settings_->context()->network_module());
    StartURLFetcher(settings_->context()->network_module()->max_network_delay(),
                    url_fetcher_generation_);
  }
}

void XMLHttpRequestImpl::IncrementActiveRequests() {
  if (active_requests_count_ == 0) {
    DCHECK(settings_);
    DCHECK(settings_->context());
    prevent_gc_until_send_complete_.reset(
        new script::GlobalEnvironment::ScopedPreventGarbageCollection(
            settings_->context()->global_environment(), xhr_));
  }
  active_requests_count_++;
}

void XMLHttpRequestImpl::DecrementActiveRequests() {
  DCHECK_GT(active_requests_count_, 0);
  active_requests_count_--;
  if (active_requests_count_ == 0) {
    bool is_active = (state_ == XMLHttpRequest::kOpened && sent_) ||
                     state_ == XMLHttpRequest::kHeadersReceived ||
                     state_ == XMLHttpRequest::kLoading;
    bool has_event_listeners =
        xhr_->GetAttributeEventListener(base::Tokens::readystatechange()) ||
        xhr_->GetAttributeEventListener(base::Tokens::progress()) ||
        xhr_->GetAttributeEventListener(base::Tokens::abort()) ||
        xhr_->GetAttributeEventListener(base::Tokens::error()) ||
        xhr_->GetAttributeEventListener(base::Tokens::load()) ||
        xhr_->GetAttributeEventListener(base::Tokens::timeout()) ||
        xhr_->GetAttributeEventListener(base::Tokens::loadend());

    DCHECK_EQ((is_active && has_event_listeners), false);

    prevent_gc_until_send_complete_.reset();
  }
}

// Reset some variables in case the XHR object is reused.
void XMLHttpRequestImpl::PrepareForNewRequest() {
  request_headers_.Clear();
  // Below are variables used for CORS.
  request_body_text_.clear();
  is_cross_origin_ = false;
  redirect_times_ = 0;
  is_data_url_ = false;
  upload_listener_ = false;
  is_redirect_ = false;
}

void XMLHttpRequestImpl::StartURLFetcher(const SbTime max_artificial_delay,
                                         const int url_fetcher_generation) {
  if (max_artificial_delay > 0) {
    base::MessageLoop::current()->task_runner()->PostDelayedTask(
        FROM_HERE,
        base::Bind(&XMLHttpRequestImpl::StartURLFetcher, base::Unretained(this),
                   0, url_fetcher_generation_),
        base::TimeDelta::FromMicroseconds(base::RandUint64() %
                                          max_artificial_delay));
    return;
  }

  // Note: Checking that "url_fetcher_generation_" != "url_fetcher_generation"
  // is to verify the "url_fetcher_" is currently the same one that was present
  // upon a delayed url fetch. This works because the incoming parameter
  // "url_fetcher_generation" will hold the value at the time of the initial
  // call, and if a delayed binding has waited while a new "url_fetcher_" has
  // changed state, "url_fetcher_generation_" will have incremented.
  if (nullptr != url_fetcher_ &&
      url_fetcher_generation == url_fetcher_generation_) {
    url_fetcher_->Start();
  }
}

void XMLHttpRequestImpl::CORSPreflightErrorCallback() {
  HandleRequestError(XMLHttpRequest::kNetworkError);
}

void XMLHttpRequestImpl::CORSPreflightSuccessCallback() {
  DCHECK(settings_->context()->network_module());
  StartURLFetcher(settings_->context()->network_module()->max_network_delay(),
                  url_fetcher_generation_);
}

DOMXMLHttpRequestImpl::DOMXMLHttpRequestImpl(XMLHttpRequest* xhr)
    : XMLHttpRequestImpl(xhr),
      settings_(base::polymorphic_downcast<dom::DOMSettings*>(
          xhr->environment_settings())) {
  DCHECK(settings_);
}

// https://www.w3.org/TR/2014/WD-XMLHttpRequest-20140130/#the-responsexml-attribute
scoped_refptr<dom::Document> DOMXMLHttpRequestImpl::response_xml(
    script::ExceptionState* exception_state) {
  // 1. If responseType is not the empty string or "document", throw an
  // "InvalidStateError" exception.
  if (response_type_ != XMLHttpRequest::kDefault &&
      response_type_ != XMLHttpRequest::kDocument) {
    web::DOMException::Raise(web::DOMException::kInvalidStateErr,
                             exception_state);
    return NULL;
  }

  // 2. If the state is not DONE, return null.
  if (state_ != XMLHttpRequest::kDone) {
    return NULL;
  }

  // 3. If the error flag is set, return null.
  if (error_) {
    return NULL;
  }

  // 4. Return the document response entity body.
  return GetDocumentResponseEntityBody();
}

void DOMXMLHttpRequestImpl::GetLoadTimingInfoAndCreateResourceTiming() {
  if (settings_->window()->performance() == nullptr) return;
  settings_->window()->performance()->CreatePerformanceResourceTiming(
      load_timing_info_, kPerformanceResourceTimingInitiatorType,
      request_url_.spec());
}

// https://www.w3.org/TR/2014/WD-XMLHttpRequest-20140130/#document-response-entity-body
scoped_refptr<dom::Document>
DOMXMLHttpRequestImpl::GetDocumentResponseEntityBody() {
  DCHECK_EQ(state_, XMLHttpRequest::kDone);

  // Step 1..5
  const std::string final_mime_type =
      mime_type_override_.empty() ? response_mime_type_ : mime_type_override_;
  if (final_mime_type != "text/xml" && final_mime_type != "application/xml") {
    return NULL;
  }

  // 6. Otherwise, let document be a document that represents the result of
  // parsing the response entity body following the rules set forth in the XML
  // specifications. If that fails (unsupported character encoding, namespace
  // well-formedness error, etc.), return null.
  scoped_refptr<dom::XMLDocument> xml_document =
      new dom::XMLDocument(settings_->window()->html_element_context());
  dom_parser::XMLDecoder xml_decoder(
      xml_document, xml_document, NULL, settings_->max_dom_element_depth(),
      base::SourceLocation("[object XMLHttpRequest]", 1, 1),
      base::Bind(&DOMXMLHttpRequestImpl::XMLDecoderLoadCompleteCallback,
                 base::Unretained(this)));
  has_xml_decoder_error_ = false;
  xml_decoder.DecodeChunk(response_body_->GetReferenceOfStringAndSeal().c_str(),
                          response_body_->GetReferenceOfStringAndSeal().size());
  xml_decoder.Finish();
  if (has_xml_decoder_error_) {
    return NULL;
  }

  // Step 7..11 Not needed by Cobalt.

  // 12. Return document.
  return xml_document;
}

void DOMXMLHttpRequestImpl::XMLDecoderLoadCompleteCallback(
    const base::Optional<std::string>& error) {
  if (error) has_xml_decoder_error_ = true;
}

std::ostream& operator<<(std::ostream& out, const XMLHttpRequest& xhr) {
#if !defined(COBALT_BUILD_TYPE_GOLD)
  base::StringPiece response_text("");
  if ((xhr.xhr_impl_->state_ == XMLHttpRequest::kDone) &&
      (xhr.xhr_impl_->response_type_ == XMLHttpRequest::kDefault ||
       xhr.xhr_impl_->response_type_ == XMLHttpRequest::kText)) {
    size_t kMaxSize = 4096;
    const auto& response_body =
        xhr.xhr_impl_->response_body_->GetTemporaryReferenceOfString();
    response_text =
        base::StringPiece(reinterpret_cast<const char*>(response_body.data()),
                          std::min(kMaxSize, response_body.size()));
  }

  std::string xhr_out = base::StringPrintf(
      " XHR:\n"
      "\tid:    %d\n"
      "\trequest_url: %s\n"
      "\tstate: %s\n"
      "\tresponse_type: %s\n"
      "\ttimeout_ms: %d\n"
      "\tmethod: %s\n"
      "\thttp_status: %d\n"
      "\twith_credentials: %s\n"
      "\terror: %s\n"
      "\tsent: %s\n"
      "\tstop_timeout: %s\n"
      "\tresponse_body: %s\n",
      xhr.xhr_id_, xhr.xhr_impl_->request_url_.spec().c_str(),
      StateName(xhr.xhr_impl_->state_), xhr.response_type(NULL).c_str(),
      xhr.xhr_impl_->timeout_ms_,
      RequestTypeToMethodName(xhr.xhr_impl_->method_),
      xhr.xhr_impl_->http_status_,
      xhr.xhr_impl_->with_credentials_ ? "true" : "false",
      xhr.xhr_impl_->error_ ? "true" : "false",
      xhr.xhr_impl_->sent_ ? "true" : "false",
      xhr.xhr_impl_->stop_timeout_ ? "true" : "false",
      response_text.as_string().c_str());
  out << xhr_out;
#else
#endif
  return out;
}

}  // namespace xhr
}  // namespace cobalt
