// 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/threading/thread_task_runner_handle.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/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/fetch_interceptor_coordinator.h"
#include "cobalt/loader/fetcher_factory.h"
#include "cobalt/loader/url_fetcher_string_writer.h"
#include "cobalt/network/network_module.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 "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.
  web::WindowOrWorkerGlobalScope* window_or_worker_global_scope =
      environment_settings()->context()->GetWindowOrWorkerGlobalScope();
  if (window_or_worker_global_scope->IsWindow()) {
    xhr_impl_ = std::make_unique<DOMXMLHttpRequestImpl>(this);
  } else if (window_or_worker_global_scope->IsDedicatedWorker() ||
             window_or_worker_global_scope->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,
                                        /* request_done = */ false);
}
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),
      cors_policy_(xhr->environment_settings()
                       ->context()
                       ->fetcher_factory()
                       ->network_module()
                       ->network_delegate()
                       ->cors_policy()),
      is_data_url_(false),
      is_redirect_(false),
      method_(net::URLFetcher::GET),
      response_body_(new URLFetcherResponseWriter::Buffer(
          URLFetcherResponseWriter::Buffer::kString,
          xhr->environment_settings()
              ->context()
              ->web_settings()
              ->xhr_settings()
              .IsTryLockForProgressCheckEnabled())),
      response_type_(XMLHttpRequest::kDefault),
      state_(XMLHttpRequest::kUnsent),
      upload_listener_(false),
      with_credentials_(false),
      xhr_(xhr),
      will_destroy_current_message_loop_(false),
      active_requests_count_(0),
      http_status_(0),
      redirect_times_(0),
      sent_(false),
      settings_(xhr->environment_settings()),
      stop_timeout_(false),
      task_runner_(base::ThreadTaskRunnerHandle::Get()),
      timeout_ms_(0),
      upload_complete_(false) {
  DCHECK(environment_settings());
  base::MessageLoop::current()->AddDestructionObserver(this);
}

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) {
  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_ = environment_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) {
  // 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) {
  error_ = false;
  auto* context = environment_settings()->context();
  bool in_service_worker =
      context->GetWindowOrWorkerGlobalScope()->IsServiceWorker();
  bool has_active_service_worker =
      !in_service_worker && context->active_service_worker();
  if (has_active_service_worker && method_ == net::URLFetcher::GET) {
    loader::FetchInterceptorCoordinator::GetInstance()->TryIntercept(
        request_url_, /*main_resource=*/false, request_headers_, task_runner_,
        base::BindOnce(&XMLHttpRequestImpl::SendIntercepted, AsWeakPtr()),
        base::BindOnce(&XMLHttpRequestImpl::ReportLoadTimingInfo, AsWeakPtr()),
        base::BindOnce(&XMLHttpRequestImpl::SendFallback, AsWeakPtr(),
                       request_body, exception_state));
    return;
  }
  SendFallback(request_body, exception_state);
}

void XMLHttpRequestImpl::SendIntercepted(
    std::unique_ptr<std::string> response) {
  if (will_destroy_current_message_loop_.load()) {
    return;
  }
  if (task_runner_ != base::ThreadTaskRunnerHandle::Get()) {
    task_runner_->PostTask(FROM_HERE,
                           base::BindOnce(&XMLHttpRequestImpl::SendIntercepted,
                                          AsWeakPtr(), std::move(response)));
    return;
  }
  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.
  // TODO: consider deduplicating code from |Send()|,
  //       |OnURLFetchDownloadProgress()|, and |OnURLFetchComplete()|.

  // Send().
  IncrementActiveRequests();
  FireProgressEvent(xhr_, base::Tokens::loadstart());
  if (!upload_complete_) {
    FireProgressEvent(upload_, base::Tokens::loadstart());
  }

  // OnURLFetchResponseStarted().
  http_status_ = 200;
  http_response_headers_ = new net::HttpResponseHeaders("");
  ChangeState(XMLHttpRequest::kHeadersReceived);

  // OnURLFetchDownloadProgress().
  ChangeState(XMLHttpRequest::kLoading);
  const auto& xhr_settings =
      environment_settings()->context()->web_settings()->xhr_settings();
  response_body_ = new URLFetcherResponseWriter::Buffer(
      URLFetcherResponseWriter::Buffer::kString,
      xhr_settings.IsTryLockForProgressCheckEnabled());
  response_body_->Write(response->data(), response->size());
  if (fetch_callback_) {
    script::Handle<script::Uint8Array> data =
        script::Uint8Array::New(settings_->context()->global_environment(),
                                response->data(), response->size());
    fetch_callback_->value().Run(data);
  }

  // OnURLFetchComplete().
  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);
  size_t received_length = response->size();
  FireProgressEvent(xhr_, base::Tokens::load(), received_length,
                    received_length,
                    /*length_computable=*/true);
  FireProgressEvent(xhr_, base::Tokens::loadend(), received_length,
                    received_length,
                    /*length_computable=*/true);
  // Undo the ref we added in Send()
  DecrementActiveRequests();

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

void XMLHttpRequestImpl::SendFallback(
    const base::Optional<XMLHttpRequest::RequestBodyType>& request_body,
    script::ExceptionState* exception_state) {
  if (will_destroy_current_message_loop_.load()) {
    return;
  }
  if (task_runner_ != base::ThreadTaskRunnerHandle::Get()) {
    task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(&XMLHttpRequestImpl::SendFallback,
                       base::Unretained(this), request_body, exception_state));
    return;
  }
  // 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;

  // 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_ = environment_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(environment_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_, cors_policy_)) {
      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*/, bool request_done) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK_NE(state_, XMLHttpRequest::kDone);

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

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

  if (fetch_callback_) {
    if (response_body_->type() == URLFetcherResponseWriter::Buffer::kString) {
      std::string downloaded_data;
      response_body_->GetAndResetDataAndDownloadProgress(&downloaded_data);
      script::Handle<script::Uint8Array> data = script::Uint8Array::New(
          environment_settings()->context()->global_environment(),
          downloaded_data.data(), downloaded_data.size());
      fetch_callback_->value().Run(data);
    } else {
      DCHECK_EQ(response_body_->type(),
                URLFetcherResponseWriter::Buffer::kBufferPool);
      std::vector<script::PreallocatedArrayBufferData> downloaded_buffers;
      response_body_->GetAndResetDataAndDownloadProgress(request_done,
                                                         &downloaded_buffers);
      for (auto& downloaded_buffer : downloaded_buffers) {
        auto array_buffer =
            script::ArrayBuffer::New(settings_->context()->global_environment(),
                                     std::move(downloaded_buffer));
        script::Handle<script::Uint8Array> data = script::Uint8Array::New(
            settings_->context()->global_environment(), array_buffer, 0,
            array_buffer->ByteLength());
        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, /* request_done = */ true);

    // 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) {
  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_, cors_policy_)) {
      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::WillDestroyCurrentMessageLoop() {
  will_destroy_current_message_loop_.store(true);
}

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 {
  return environment_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(
                                  environment_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() {
  // 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.
    script::PreallocatedArrayBufferData downloaded_data;
    response_body_->GetAndResetData(&downloaded_data);
    auto array_buffer = script::ArrayBuffer::New(
        environment_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) {
  const auto& xhr_settings =
      environment_settings()->context()->web_settings()->xhr_settings();
  const bool fetch_buffer_pool_enabled =
      xhr_settings.IsFetchBufferPoolEnabled().value_or(false);

  if (fetch_callback_ && fetch_buffer_pool_enabled) {
    LOG(INFO) << "Fetching (backed by BufferPool): "
              << ClipUrl(request_url_, 200);
  } else {
    LOG(INFO) << "Fetching: " << ClipUrl(request_url_, 200);
  }

  response_array_buffer_reference_.reset();

  network::NetworkModule* network_module =
      environment_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_) {
    // FetchBufferPool is by default disabled, but can be explicitly overridden.
    if (fetch_buffer_pool_enabled) {
      response_body_ = new URLFetcherResponseWriter::Buffer(
          URLFetcherResponseWriter::Buffer::kBufferPool,
          xhr_settings.IsTryLockForProgressCheckEnabled(),
          xhr_settings.GetDefaultFetchBufferSize());
    } else {
      response_body_ = new URLFetcherResponseWriter::Buffer(
          URLFetcherResponseWriter::Buffer::kString,
          xhr_settings.IsTryLockForProgressCheckEnabled());
      response_body_->DisablePreallocate();
    }
  } else {
    if (response_type_ == XMLHttpRequest::kArrayBuffer) {
      response_body_ = new URLFetcherResponseWriter::Buffer(
          URLFetcherResponseWriter::Buffer::kArrayBuffer,
          xhr_settings.IsTryLockForProgressCheckEnabled());
    } else {
      response_body_ = new URLFetcherResponseWriter::Buffer(
          URLFetcherResponseWriter::Buffer::kString,
          xhr_settings.IsTryLockForProgressCheckEnabled());
    }
  }
  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());
  network_module->AddClientHintHeaders(*url_fetcher_, network::kCallTypeXHR);

  // 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)),
        environment_settings()
            ->context()
            ->GetWindowOrWorkerGlobalScope()
            ->get_preflight_cache()));
    corspreflight_->set_headers(request_headers_);
    corspreflight_->set_cors_policy(cors_policy_);
    // 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(environment_settings()->context()->network_module());
    StartURLFetcher(environment_settings()
                        ->context()
                        ->network_module()
                        ->max_network_delay_usec(),
                    url_fetcher_generation_);
  }
}

void XMLHttpRequestImpl::IncrementActiveRequests() {
  if (active_requests_count_ == 0) {
    prevent_gc_until_send_complete_.reset(
        new script::GlobalEnvironment::ScopedPreventGarbageCollection(
            environment_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 int64_t max_artificial_delay_usec, const int url_fetcher_generation) {
  if (max_artificial_delay_usec > 0) {
    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
        FROM_HERE,
        base::Bind(&XMLHttpRequestImpl::StartURLFetcher, base::Unretained(this),
                   0, url_fetcher_generation_),
        base::TimeDelta::FromMicroseconds(base::RandUint64() %
                                          max_artificial_delay_usec));
    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(environment_settings()->context()->network_module());
  StartURLFetcher(environment_settings()
                      ->context()
                      ->network_module()
                      ->max_network_delay_usec(),
                  url_fetcher_generation_);
}

DOMXMLHttpRequestImpl::DOMXMLHttpRequestImpl(XMLHttpRequest* xhr)
    : XMLHttpRequestImpl(xhr) {
  DCHECK(environment_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() {
  web::WindowOrWorkerGlobalScope* window_or_worker_global_scope =
      environment_settings()->context()->GetWindowOrWorkerGlobalScope();
  if (!window_or_worker_global_scope->IsWindow()) return;
  if (window_or_worker_global_scope->AsWindow()->performance() == nullptr)
    return;
  window_or_worker_global_scope->AsWindow()
      ->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);
  if (!environment_settings()
           ->context()
           ->GetWindowOrWorkerGlobalScope()
           ->IsWindow()) {
    return nullptr;
  }

  // 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 nullptr;
  }

  // 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(environment_settings()
                               ->context()
                               ->GetWindowOrWorkerGlobalScope()
                               ->AsWindow()
                               ->html_element_context());
  dom_parser::XMLDecoder xml_decoder(
      xml_document, xml_document, NULL,
      base::polymorphic_downcast<dom::DOMSettings*>(environment_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
