/*
 *  Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved.
 *  Copyright (C) 2005-2007 Alexey Proskuryakov <ap@webkit.org>
 *  Copyright (C) 2007, 2008 Julien Chaffraix <jchaffraix@webkit.org>
 *  Copyright (C) 2008, 2011 Google Inc. All rights reserved.
 *  Copyright (C) 2012 Intel Corporation
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "core/xmlhttprequest/XMLHttpRequest.h"

#include "bindings/core/v8/ArrayBufferOrArrayBufferViewOrBlobOrDocumentOrStringOrFormData.h"
#include "bindings/core/v8/ArrayBufferOrArrayBufferViewOrBlobOrUSVString.h"
#include "bindings/core/v8/DOMWrapperWorld.h"
#include "bindings/core/v8/ExceptionState.h"
#include "bindings/core/v8/ScriptState.h"
#include "core/dom/DOMArrayBuffer.h"
#include "core/dom/DOMArrayBufferView.h"
#include "core/dom/DOMException.h"
#include "core/dom/DOMImplementation.h"
#include "core/dom/DOMTypedArray.h"
#include "core/dom/DocumentInit.h"
#include "core/dom/DocumentParser.h"
#include "core/dom/ExceptionCode.h"
#include "core/dom/ExecutionContext.h"
#include "core/dom/XMLDocument.h"
#include "core/editing/serializers/Serialization.h"
#include "core/events/Event.h"
#include "core/events/ProgressEvent.h"
#include "core/fetch/CrossOriginAccessControl.h"
#include "core/fetch/FetchInitiatorTypeNames.h"
#include "core/fetch/FetchUtils.h"
#include "core/fetch/ResourceLoaderOptions.h"
#include "core/fileapi/Blob.h"
#include "core/fileapi/File.h"
#include "core/fileapi/FileReaderLoader.h"
#include "core/fileapi/FileReaderLoaderClient.h"
#include "core/frame/Deprecation.h"
#include "core/frame/Settings.h"
#include "core/frame/csp/ContentSecurityPolicy.h"
#include "core/html/FormData.h"
#include "core/html/HTMLDocument.h"
#include "core/html/parser/TextResourceDecoder.h"
#include "core/inspector/ConsoleMessage.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/inspector/InspectorTraceEvents.h"
#include "core/loader/ThreadableLoader.h"
#include "core/page/ChromeClient.h"
#include "core/page/Page.h"
#include "core/streams/Stream.h"
#include "core/xmlhttprequest/XMLHttpRequestUpload.h"
#include "platform/FileMetadata.h"
#include "platform/HTTPNames.h"
#include "platform/Histogram.h"
#include "platform/Logging.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/SharedBuffer.h"
#include "platform/blob/BlobData.h"
#include "platform/network/HTTPParsers.h"
#include "platform/network/ParsedContentType.h"
#include "platform/network/ResourceError.h"
#include "platform/network/ResourceRequest.h"
#include "public/platform/WebURLRequest.h"
#include "wtf/Assertions.h"
#include "wtf/StdLibExtras.h"
#include "wtf/text/CString.h"

namespace blink {

namespace {

// This class protects the wrapper of the associated XMLHttpRequest object
// via hasPendingActivity method which returns true if
// m_eventDispatchRecursionLevel is positive.
class ScopedEventDispatchProtect final {
public:
    explicit ScopedEventDispatchProtect(int* level) : m_level(level)
    {
        ++*m_level;
    }
    ~ScopedEventDispatchProtect()
    {
        ASSERT(*m_level > 0);
        --*m_level;
    }

private:
    int* const m_level;
};

void replaceCharsetInMediaType(String& mediaType, const String& charsetValue)
{
    unsigned pos = 0, len = 0;

    findCharsetInMediaType(mediaType, pos, len);

    if (!len) {
        // When no charset found, do nothing.
        return;
    }

    // Found at least one existing charset, replace all occurrences with new charset.
    while (len) {
        mediaType.replace(pos, len, charsetValue);
        unsigned start = pos + charsetValue.length();
        findCharsetInMediaType(mediaType, pos, len, start);
    }
}

void logConsoleError(ExecutionContext* context, const String& message)
{
    if (!context)
        return;
    // FIXME: It's not good to report the bad usage without indicating what source line it came from.
    // We should pass additional parameters so we can tell the console where the mistake occurred.
    ConsoleMessage* consoleMessage = ConsoleMessage::create(JSMessageSource, ErrorMessageLevel, message);
    context->addConsoleMessage(consoleMessage);
}

enum HeaderValueCategoryByRFC7230 {
    HeaderValueInvalid,
    HeaderValueAffectedByNormalization,
    HeaderValueValid,
    HeaderValueCategoryByRFC7230End
};

} // namespace

class XMLHttpRequest::BlobLoader final : public GarbageCollectedFinalized<XMLHttpRequest::BlobLoader>, public FileReaderLoaderClient {
public:
    static BlobLoader* create(XMLHttpRequest* xhr, PassRefPtr<BlobDataHandle> handle)
    {
        return new BlobLoader(xhr, handle);
    }

    // FileReaderLoaderClient functions.
    void didStartLoading() override {}
    void didReceiveDataForClient(const char* data, unsigned length) override
    {
        ASSERT(length <= INT_MAX);
        m_xhr->didReceiveData(data, length);
    }
    void didFinishLoading() override
    {
        m_xhr->didFinishLoadingFromBlob();
    }
    void didFail(FileError::ErrorCode error) override
    {
        m_xhr->didFailLoadingFromBlob();
    }

    void cancel()
    {
        m_loader.cancel();
    }

    DEFINE_INLINE_TRACE()
    {
        visitor->trace(m_xhr);
    }

private:
    BlobLoader(XMLHttpRequest* xhr, PassRefPtr<BlobDataHandle> handle)
        : m_xhr(xhr)
        , m_loader(FileReaderLoader::ReadByClient, this)
    {
        m_loader.start(m_xhr->getExecutionContext(), handle);
    }

    Member<XMLHttpRequest> m_xhr;
    FileReaderLoader m_loader;
};

XMLHttpRequest* XMLHttpRequest::create(ScriptState* scriptState)
{
    ExecutionContext* context = scriptState->getExecutionContext();
    DOMWrapperWorld& world = scriptState->world();
    RefPtr<SecurityOrigin> isolatedWorldSecurityOrigin = world.isIsolatedWorld() ? world.isolatedWorldSecurityOrigin() : nullptr;
    XMLHttpRequest* xmlHttpRequest = new XMLHttpRequest(context, isolatedWorldSecurityOrigin);
    xmlHttpRequest->suspendIfNeeded();

    return xmlHttpRequest;
}

XMLHttpRequest* XMLHttpRequest::create(ExecutionContext* context)
{
    XMLHttpRequest* xmlHttpRequest = new XMLHttpRequest(context, nullptr);
    xmlHttpRequest->suspendIfNeeded();

    return xmlHttpRequest;
}

XMLHttpRequest::XMLHttpRequest(ExecutionContext* context, PassRefPtr<SecurityOrigin> isolatedWorldSecurityOrigin)
    : ActiveScriptWrappable(this)
    , ActiveDOMObject(context)
    , m_timeoutMilliseconds(0)
    , m_state(UNSENT)
    , m_lengthDownloadedToFile(0)
    , m_receivedLength(0)
    , m_exceptionCode(0)
    , m_progressEventThrottle(XMLHttpRequestProgressEventThrottle::create(this))
    , m_responseTypeCode(ResponseTypeDefault)
    , m_isolatedWorldSecurityOrigin(isolatedWorldSecurityOrigin)
    , m_eventDispatchRecursionLevel(0)
    , m_async(true)
    , m_includeCredentials(false)
    , m_parsedResponse(false)
    , m_error(false)
    , m_uploadEventsAllowed(true)
    , m_uploadComplete(false)
    , m_sameOriginRequest(true)
    , m_downloadingToFile(false)
    , m_responseTextOverflow(false)
{
}

XMLHttpRequest::~XMLHttpRequest()
{
}

Document* XMLHttpRequest::document() const
{
    ASSERT(getExecutionContext()->isDocument());
    return toDocument(getExecutionContext());
}

SecurityOrigin* XMLHttpRequest::getSecurityOrigin() const
{
    return m_isolatedWorldSecurityOrigin ? m_isolatedWorldSecurityOrigin.get() : getExecutionContext()->getSecurityOrigin();
}

XMLHttpRequest::State XMLHttpRequest::readyState() const
{
    return m_state;
}

ScriptString XMLHttpRequest::responseText(ExceptionState& exceptionState)
{
    if (m_responseTypeCode != ResponseTypeDefault && m_responseTypeCode != ResponseTypeText) {
        exceptionState.throwDOMException(InvalidStateError, "The value is only accessible if the object's 'responseType' is '' or 'text' (was '" + responseType() + "').");
        return ScriptString();
    }
    if (m_error || (m_state != LOADING && m_state != DONE))
        return ScriptString();
    return m_responseText;
}

ScriptString XMLHttpRequest::responseJSONSource()
{
    ASSERT(m_responseTypeCode == ResponseTypeJSON);

    if (m_error || m_state != DONE)
        return ScriptString();
    return m_responseText;
}

void XMLHttpRequest::initResponseDocument()
{
    // The W3C spec requires the final MIME type to be some valid XML type, or text/html.
    // If it is text/html, then the responseType of "document" must have been supplied explicitly.
    bool isHTML = responseIsHTML();
    if ((m_response.isHTTP() && !responseIsXML() && !isHTML)
        || (isHTML && m_responseTypeCode == ResponseTypeDefault)
        || getExecutionContext()->isWorkerGlobalScope()) {
        m_responseDocument = nullptr;
        return;
    }

    DocumentInit init = DocumentInit::fromContext(document()->contextDocument(), m_url);
    if (isHTML)
        m_responseDocument = HTMLDocument::create(init);
    else
        m_responseDocument = XMLDocument::create(init);

    // FIXME: Set Last-Modified.
    m_responseDocument->setSecurityOrigin(getSecurityOrigin());
    m_responseDocument->setContextFeatures(document()->contextFeatures());
    m_responseDocument->setMimeType(finalResponseMIMETypeWithFallback());
}

Document* XMLHttpRequest::responseXML(ExceptionState& exceptionState)
{
    if (m_responseTypeCode != ResponseTypeDefault && m_responseTypeCode != ResponseTypeDocument) {
        exceptionState.throwDOMException(InvalidStateError, "The value is only accessible if the object's 'responseType' is '' or 'document' (was '" + responseType() + "').");
        return nullptr;
    }

    if (m_error || m_state != DONE)
        return nullptr;

    if (!m_parsedResponse) {
        initResponseDocument();
        if (!m_responseDocument)
            return nullptr;

        m_responseDocument->setContent(m_responseText.flattenToString());
        if (!m_responseDocument->wellFormed())
            m_responseDocument = nullptr;

        m_parsedResponse = true;
    }

    return m_responseDocument.get();
}

Blob* XMLHttpRequest::responseBlob()
{
    ASSERT(m_responseTypeCode == ResponseTypeBlob);

    // We always return null before DONE.
    if (m_error || m_state != DONE)
        return nullptr;

    if (!m_responseBlob) {
        if (m_downloadingToFile) {
            ASSERT(!m_binaryResponseBuilder);

            // When responseType is set to "blob", we redirect the downloaded
            // data to a file-handle directly in the browser process. We get
            // the file-path from the ResourceResponse directly instead of
            // copying the bytes between the browser and the renderer.
            m_responseBlob = Blob::create(createBlobDataHandleFromResponse());
        } else {
            OwnPtr<BlobData> blobData = BlobData::create();
            size_t size = 0;
            if (m_binaryResponseBuilder && m_binaryResponseBuilder->size()) {
                size = m_binaryResponseBuilder->size();
                blobData->appendBytes(m_binaryResponseBuilder->data(), size);
                blobData->setContentType(finalResponseMIMETypeWithFallback().lower());
                m_binaryResponseBuilder.clear();
            }
            m_responseBlob = Blob::create(BlobDataHandle::create(std::move(blobData), size));
        }
    }

    return m_responseBlob;
}

DOMArrayBuffer* XMLHttpRequest::responseArrayBuffer()
{
    ASSERT(m_responseTypeCode == ResponseTypeArrayBuffer);

    if (m_error || m_state != DONE)
        return nullptr;

    if (!m_responseArrayBuffer) {
        if (m_binaryResponseBuilder && m_binaryResponseBuilder->size()) {
            DOMArrayBuffer* buffer = DOMArrayBuffer::createUninitialized(m_binaryResponseBuilder->size(), 1);
            if (!m_binaryResponseBuilder->getAsBytes(buffer->data(), static_cast<size_t>(buffer->byteLength()))) {
                // m_binaryResponseBuilder failed to allocate an ArrayBuffer.
                // We need to crash the renderer since there's no way defined in
                // the spec to tell this to the user.
                CRASH();
            }
            m_responseArrayBuffer = buffer;
            m_binaryResponseBuilder.clear();
        } else {
            m_responseArrayBuffer = DOMArrayBuffer::create(nullptr, 0);
        }
    }

    return m_responseArrayBuffer.get();
}

Stream* XMLHttpRequest::responseLegacyStream()
{
    ASSERT(m_responseTypeCode == ResponseTypeLegacyStream);

    if (m_error || (m_state != LOADING && m_state != DONE))
        return nullptr;

    return m_responseLegacyStream;
}

void XMLHttpRequest::setTimeout(unsigned timeout, ExceptionState& exceptionState)
{
    // FIXME: Need to trigger or update the timeout Timer here, if needed. http://webkit.org/b/98156
    // XHR2 spec, 4.7.3. "This implies that the timeout attribute can be set while fetching is in progress. If that occurs it will still be measured relative to the start of fetching."
    if (getExecutionContext()->isDocument() && !m_async) {
        exceptionState.throwDOMException(InvalidAccessError, "Timeouts cannot be set for synchronous requests made from a document.");
        return;
    }

    m_timeoutMilliseconds = timeout;

    // From http://www.w3.org/TR/XMLHttpRequest/#the-timeout-attribute:
    // Note: This implies that the timeout attribute can be set while fetching is in progress. If
    // that occurs it will still be measured relative to the start of fetching.
    //
    // The timeout may be overridden after send.
    if (m_loader)
        m_loader->overrideTimeout(timeout);
}

void XMLHttpRequest::setResponseType(const String& responseType, ExceptionState& exceptionState)
{
    if (m_state >= LOADING) {
        exceptionState.throwDOMException(InvalidStateError, "The response type cannot be set if the object's state is LOADING or DONE.");
        return;
    }

    // Newer functionality is not available to synchronous requests in window contexts, as a spec-mandated
    // attempt to discourage synchronous XHR use. responseType is one such piece of functionality.
    if (!m_async && getExecutionContext()->isDocument()) {
        exceptionState.throwDOMException(InvalidAccessError, "The response type cannot be changed for synchronous requests made from a document.");
        return;
    }

    if (responseType == "") {
        m_responseTypeCode = ResponseTypeDefault;
    } else if (responseType == "text") {
        m_responseTypeCode = ResponseTypeText;
    } else if (responseType == "json") {
        m_responseTypeCode = ResponseTypeJSON;
    } else if (responseType == "document") {
        m_responseTypeCode = ResponseTypeDocument;
    } else if (responseType == "blob") {
        m_responseTypeCode = ResponseTypeBlob;
    } else if (responseType == "arraybuffer") {
        m_responseTypeCode = ResponseTypeArrayBuffer;
    } else if (responseType == "legacystream") {
        if (RuntimeEnabledFeatures::experimentalStreamEnabled())
            m_responseTypeCode = ResponseTypeLegacyStream;
        else
            return;
    } else {
        ASSERT_NOT_REACHED();
    }
}

String XMLHttpRequest::responseType()
{
    switch (m_responseTypeCode) {
    case ResponseTypeDefault:
        return "";
    case ResponseTypeText:
        return "text";
    case ResponseTypeJSON:
        return "json";
    case ResponseTypeDocument:
        return "document";
    case ResponseTypeBlob:
        return "blob";
    case ResponseTypeArrayBuffer:
        return "arraybuffer";
    case ResponseTypeLegacyStream:
        return "legacystream";
    }
    return "";
}

String XMLHttpRequest::responseURL()
{
    KURL responseURL(m_response.url());
    if (!responseURL.isNull())
        responseURL.removeFragmentIdentifier();
    return responseURL.getString();
}

XMLHttpRequestUpload* XMLHttpRequest::upload()
{
    if (!m_upload)
        m_upload = XMLHttpRequestUpload::create(this);
    return m_upload.get();
}

void XMLHttpRequest::trackProgress(long long length)
{
    m_receivedLength += length;

    changeState(LOADING);
    if (m_async) {
        // readyStateChange event is fired as well.
        dispatchProgressEventFromSnapshot(EventTypeNames::progress);
    }
}

void XMLHttpRequest::changeState(State newState)
{
    if (m_state != newState) {
        m_state = newState;
        dispatchReadyStateChangeEvent();
    }
}

void XMLHttpRequest::dispatchReadyStateChangeEvent()
{
    if (!getExecutionContext())
        return;

    ScopedEventDispatchProtect protect(&m_eventDispatchRecursionLevel);
    if (m_async || (m_state <= OPENED || m_state == DONE)) {
        TRACE_EVENT1("devtools.timeline", "XHRReadyStateChange", "data", InspectorXhrReadyStateChangeEvent::data(getExecutionContext(), this));
        XMLHttpRequestProgressEventThrottle::DeferredEventAction action = XMLHttpRequestProgressEventThrottle::Ignore;
        if (m_state == DONE) {
            if (m_error)
                action = XMLHttpRequestProgressEventThrottle::Clear;
            else
                action = XMLHttpRequestProgressEventThrottle::Flush;
        }
        m_progressEventThrottle->dispatchReadyStateChangeEvent(Event::create(EventTypeNames::readystatechange), action);
        TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", TRACE_EVENT_SCOPE_THREAD, "data", InspectorUpdateCountersEvent::data());
    }

    if (m_state == DONE && !m_error) {
        TRACE_EVENT1("devtools.timeline", "XHRLoad", "data", InspectorXhrLoadEvent::data(getExecutionContext(), this));
        dispatchProgressEventFromSnapshot(EventTypeNames::load);
        dispatchProgressEventFromSnapshot(EventTypeNames::loadend);
        TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", TRACE_EVENT_SCOPE_THREAD, "data", InspectorUpdateCountersEvent::data());
    }
}

void XMLHttpRequest::setWithCredentials(bool value, ExceptionState& exceptionState)
{
    if (m_state > OPENED || m_loader) {
        exceptionState.throwDOMException(InvalidStateError,  "The value may only be set if the object's state is UNSENT or OPENED.");
        return;
    }

    // FIXME: According to XMLHttpRequest Level 2 we should throw InvalidAccessError exception here.
    // However for time being only print warning message to warn web developers.
    if (!m_async)
        Deprecation::countDeprecation(getExecutionContext(), UseCounter::SyncXHRWithCredentials);

    m_includeCredentials = value;
}

void XMLHttpRequest::open(const AtomicString& method, const String& urlString, ExceptionState& exceptionState)
{
    open(method, getExecutionContext()->completeURL(urlString), true, exceptionState);
}

void XMLHttpRequest::open(const AtomicString& method, const String& urlString, bool async, const String& username, const String& password, ExceptionState& exceptionState)
{
    KURL url(getExecutionContext()->completeURL(urlString));
    if (!username.isNull())
        url.setUser(username);
    if (!password.isNull())
        url.setPass(password);

    open(method, url, async, exceptionState);
}

void XMLHttpRequest::open(const AtomicString& method, const KURL& url, bool async, ExceptionState& exceptionState)
{
    WTF_LOG(Network, "XMLHttpRequest %p open('%s', '%s', %d)", this, method.utf8().data(), url.elidedString().utf8().data(), async);

    if (!internalAbort())
        return;

    State previousState = m_state;
    m_state = UNSENT;
    m_error = false;
    m_uploadComplete = false;

    if (!isValidHTTPToken(method)) {
        exceptionState.throwDOMException(SyntaxError, "'" + method + "' is not a valid HTTP method.");
        return;
    }

    if (FetchUtils::isForbiddenMethod(method)) {
        exceptionState.throwSecurityError("'" + method + "' HTTP method is unsupported.");
        return;
    }

    if (!ContentSecurityPolicy::shouldBypassMainWorld(getExecutionContext()) && !getExecutionContext()->contentSecurityPolicy()->allowConnectToSource(url)) {
        // We can safely expose the URL to JavaScript, as these checks happen synchronously before redirection. JavaScript receives no new information.
        exceptionState.throwSecurityError("Refused to connect to '" + url.elidedString() + "' because it violates the document's Content Security Policy.");
        return;
    }

    if (!async && getExecutionContext()->isDocument()) {
        if (document()->settings() && !document()->settings()->syncXHRInDocumentsEnabled()) {
            exceptionState.throwDOMException(InvalidAccessError, "Synchronous requests are disabled for this page.");
            return;
        }

        // Newer functionality is not available to synchronous requests in window contexts, as a spec-mandated
        // attempt to discourage synchronous XHR use. responseType is one such piece of functionality.
        if (m_responseTypeCode != ResponseTypeDefault) {
            exceptionState.throwDOMException(InvalidAccessError, "Synchronous requests from a document must not set a response type.");
            return;
        }

        // Similarly, timeouts are disabled for synchronous requests as well.
        if (m_timeoutMilliseconds > 0) {
            exceptionState.throwDOMException(InvalidAccessError, "Synchronous requests must not set a timeout.");
            return;
        }

        // Here we just warn that firing sync XHR's may affect responsiveness.
        // Eventually sync xhr will be deprecated and an "InvalidAccessError" exception thrown.
        // Refer : https://xhr.spec.whatwg.org/#sync-warning
        // Use count for XHR synchronous requests on main thread only.
        if (!document()->processingBeforeUnload())
            Deprecation::countDeprecation(getExecutionContext(), UseCounter::XMLHttpRequestSynchronousInNonWorkerOutsideBeforeUnload);
    }

    m_method = FetchUtils::normalizeMethod(method);

    m_url = url;

    m_async = async;

    ASSERT(!m_loader);

    // Check previous state to avoid dispatching readyState event
    // when calling open several times in a row.
    if (previousState != OPENED)
        changeState(OPENED);
    else
        m_state = OPENED;
}

bool XMLHttpRequest::initSend(ExceptionState& exceptionState)
{
    if (!getExecutionContext())
        return false;

    if (m_state != OPENED || m_loader) {
        exceptionState.throwDOMException(InvalidStateError, "The object's state must be OPENED.");
        return false;
    }

    if (!m_async && exceptionState.isolate() && v8::MicrotasksScope::IsRunningMicrotasks(exceptionState.isolate())) {
        Deprecation::countDeprecation(getExecutionContext(), UseCounter::During_Microtask_SyncXHR);
        if (RuntimeEnabledFeatures::disableBlockingMethodsDuringMicrotasksEnabled()) {
            exceptionState.throwDOMException(InvalidAccessError, "Cannot send() synchronous requests during microtask execution.");
            return false;
        }
    }


    m_error = false;
    return true;
}

void XMLHttpRequest::send(const ArrayBufferOrArrayBufferViewOrBlobOrDocumentOrStringOrFormData& body, ExceptionState& exceptionState)
{
    InspectorInstrumentation::willSendXMLHttpOrFetchNetworkRequest(getExecutionContext(), url());

    if (body.isNull()) {
        send(String(), exceptionState);
        return;
    }

    if (body.isArrayBuffer()) {
        send(body.getAsArrayBuffer(), exceptionState);
        return;
    }

    if (body.isArrayBufferView()) {
        send(body.getAsArrayBufferView(), exceptionState);
        return;
    }

    if (body.isBlob()) {
        send(body.getAsBlob(), exceptionState);
        return;
    }

    if (body.isDocument()) {
        send(body.getAsDocument(), exceptionState);
        return;
    }

    if (body.isFormData()) {
        send(body.getAsFormData(), exceptionState);
        return;
    }

    ASSERT(body.isString());
    send(body.getAsString(), exceptionState);
}

bool XMLHttpRequest::areMethodAndURLValidForSend()
{
    return m_method != HTTPNames::GET && m_method != HTTPNames::HEAD && m_url.protocolIsInHTTPFamily();
}

void XMLHttpRequest::send(Document* document, ExceptionState& exceptionState)
{
    WTF_LOG(Network, "XMLHttpRequest %p send() Document %p", this, document);

    ASSERT(document);

    if (!initSend(exceptionState))
        return;

    RefPtr<EncodedFormData> httpBody;

    if (areMethodAndURLValidForSend()) {
        // FIXME: Per https://xhr.spec.whatwg.org/#dom-xmlhttprequest-send the
        // Content-Type header and whether to serialize as HTML or XML should
        // depend on |document->isHTMLDocument()|.
        if (getRequestHeader(HTTPNames::Content_Type).isEmpty())
            setRequestHeaderInternal(HTTPNames::Content_Type, "application/xml;charset=UTF-8");

        String body = createMarkup(document);

        httpBody = EncodedFormData::create(UTF8Encoding().encode(body, WTF::EntitiesForUnencodables));
    }

    createRequest(httpBody.release(), exceptionState);
}

void XMLHttpRequest::send(const String& body, ExceptionState& exceptionState)
{
    WTF_LOG(Network, "XMLHttpRequest %p send() String '%s'", this, body.utf8().data());

    if (!initSend(exceptionState))
        return;

    RefPtr<EncodedFormData> httpBody;

    if (!body.isNull() && areMethodAndURLValidForSend()) {
        String contentType = getRequestHeader(HTTPNames::Content_Type);
        if (contentType.isEmpty()) {
            setRequestHeaderInternal(HTTPNames::Content_Type, "text/plain;charset=UTF-8");
        } else {
            replaceCharsetInMediaType(contentType, "UTF-8");
            m_requestHeaders.set(HTTPNames::Content_Type, AtomicString(contentType));
        }

        httpBody = EncodedFormData::create(UTF8Encoding().encode(body, WTF::EntitiesForUnencodables));
    }

    createRequest(httpBody.release(), exceptionState);
}

void XMLHttpRequest::send(Blob* body, ExceptionState& exceptionState)
{
    WTF_LOG(Network, "XMLHttpRequest %p send() Blob '%s'", this, body->uuid().utf8().data());

    if (!initSend(exceptionState))
        return;

    RefPtr<EncodedFormData> httpBody;

    if (areMethodAndURLValidForSend()) {
        if (getRequestHeader(HTTPNames::Content_Type).isEmpty()) {
            const String& blobType = body->type();
            if (!blobType.isEmpty() && isValidContentType(blobType)) {
                setRequestHeaderInternal(HTTPNames::Content_Type, AtomicString(blobType));
            }
        }

        // FIXME: add support for uploading bundles.
        httpBody = EncodedFormData::create();
        if (body->hasBackingFile()) {
            File* file = toFile(body);
            if (!file->path().isEmpty())
                httpBody->appendFile(file->path());
            else if (!file->fileSystemURL().isEmpty())
                httpBody->appendFileSystemURL(file->fileSystemURL());
            else
                ASSERT_NOT_REACHED();
        } else {
            httpBody->appendBlob(body->uuid(), body->blobDataHandle());
        }
    }

    createRequest(httpBody.release(), exceptionState);
}

void XMLHttpRequest::send(FormData* body, ExceptionState& exceptionState)
{
    WTF_LOG(Network, "XMLHttpRequest %p send() FormData %p", this, body);

    if (!initSend(exceptionState))
        return;

    RefPtr<EncodedFormData> httpBody;

    if (areMethodAndURLValidForSend()) {
        httpBody = body->encodeMultiPartFormData();

        if (getRequestHeader(HTTPNames::Content_Type).isEmpty()) {
            AtomicString contentType = AtomicString("multipart/form-data; boundary=") + httpBody->boundary().data();
            setRequestHeaderInternal(HTTPNames::Content_Type, contentType);
        }
    }

    createRequest(httpBody.release(), exceptionState);
}

void XMLHttpRequest::send(DOMArrayBuffer* body, ExceptionState& exceptionState)
{
    WTF_LOG(Network, "XMLHttpRequest %p send() ArrayBuffer %p", this, body);

    sendBytesData(body->data(), body->byteLength(), exceptionState);
}

void XMLHttpRequest::send(DOMArrayBufferView* body, ExceptionState& exceptionState)
{
    WTF_LOG(Network, "XMLHttpRequest %p send() ArrayBufferView %p", this, body);

    sendBytesData(body->baseAddress(), body->byteLength(), exceptionState);
}

void XMLHttpRequest::sendBytesData(const void* data, size_t length, ExceptionState& exceptionState)
{
    if (!initSend(exceptionState))
        return;

    RefPtr<EncodedFormData> httpBody;

    if (areMethodAndURLValidForSend()) {
        httpBody = EncodedFormData::create(data, length);
    }

    createRequest(httpBody.release(), exceptionState);
}

void XMLHttpRequest::sendForInspectorXHRReplay(PassRefPtr<EncodedFormData> formData, ExceptionState& exceptionState)
{
    createRequest(formData ? formData->deepCopy() : nullptr, exceptionState);
    m_exceptionCode = exceptionState.code();
}

void XMLHttpRequest::throwForLoadFailureIfNeeded(ExceptionState& exceptionState, const String& reason)
{
    if (m_error && !m_exceptionCode)
        m_exceptionCode = NetworkError;

    if (!m_exceptionCode)
        return;

    String message = "Failed to load '" + m_url.elidedString() + "'";
    if (reason.isNull()) {
        message.append(".");
    } else {
        message.append(": ");
        message.append(reason);
    }

    exceptionState.throwDOMException(m_exceptionCode, message);
}

void XMLHttpRequest::createRequest(PassRefPtr<EncodedFormData> httpBody, ExceptionState& exceptionState)
{
    // Only GET request is supported for blob URL.
    if (m_url.protocolIs("blob") && m_method != HTTPNames::GET) {
        handleNetworkError();

        if (!m_async) {
            throwForLoadFailureIfNeeded(exceptionState, "'GET' is the only method allowed for 'blob:' URLs.");
        }
        return;
    }

    ASSERT(getExecutionContext());
    ExecutionContext& executionContext = *this->getExecutionContext();

    // The presence of upload event listeners forces us to use preflighting because POSTing to an URL that does not
    // permit cross origin requests should look exactly like POSTing to an URL that does not respond at all.
    // Also, only async requests support upload progress events.
    bool uploadEvents = false;
    if (m_async) {
        InspectorInstrumentation::asyncTaskScheduled(&executionContext, "XMLHttpRequest.send", this, true);
        dispatchProgressEvent(EventTypeNames::loadstart, 0, 0);
        if (httpBody && m_upload) {
            uploadEvents = m_upload->hasEventListeners();
            m_upload->dispatchEvent(ProgressEvent::create(EventTypeNames::loadstart, false, 0, 0));
        }
    }

    m_sameOriginRequest = getSecurityOrigin()->canRequestNoSuborigin(m_url);

    if (!m_sameOriginRequest && m_includeCredentials)
        UseCounter::count(&executionContext, UseCounter::XMLHttpRequestCrossOriginWithCredentials);

    // We also remember whether upload events should be allowed for this request in case the upload listeners are
    // added after the request is started.
    m_uploadEventsAllowed = m_sameOriginRequest || uploadEvents || !FetchUtils::isSimpleRequest(m_method, m_requestHeaders);

    ResourceRequest request(m_url);
    request.setHTTPMethod(m_method);
    request.setRequestContext(WebURLRequest::RequestContextXMLHttpRequest);
    request.setFetchCredentialsMode(m_includeCredentials ? WebURLRequest::FetchCredentialsModeInclude : WebURLRequest::FetchCredentialsModeSameOrigin);
    request.setSkipServiceWorker(m_isolatedWorldSecurityOrigin);
    request.setExternalRequestStateFromRequestorAddressSpace(executionContext.securityContext().addressSpace());

    InspectorInstrumentation::willLoadXHR(&executionContext, this, this, m_method, m_url, m_async, httpBody ? httpBody->deepCopy() : nullptr, m_requestHeaders, m_includeCredentials);

    if (httpBody) {
        ASSERT(m_method != HTTPNames::GET);
        ASSERT(m_method != HTTPNames::HEAD);
        request.setHTTPBody(httpBody);
    }

    if (m_requestHeaders.size() > 0)
        request.addHTTPHeaderFields(m_requestHeaders);

    ThreadableLoaderOptions options;
    options.preflightPolicy = uploadEvents ? ForcePreflight : ConsiderPreflight;
    options.crossOriginRequestPolicy = UseAccessControl;
    options.initiator = FetchInitiatorTypeNames::xmlhttprequest;
    options.contentSecurityPolicyEnforcement = ContentSecurityPolicy::shouldBypassMainWorld(&executionContext) ? DoNotEnforceContentSecurityPolicy : EnforceContentSecurityPolicy;
    options.timeoutMilliseconds = m_timeoutMilliseconds;

    ResourceLoaderOptions resourceLoaderOptions;
    resourceLoaderOptions.allowCredentials = (m_sameOriginRequest || m_includeCredentials) ? AllowStoredCredentials : DoNotAllowStoredCredentials;
    resourceLoaderOptions.credentialsRequested = m_includeCredentials ? ClientRequestedCredentials : ClientDidNotRequestCredentials;
    resourceLoaderOptions.securityOrigin = getSecurityOrigin();

    // When responseType is set to "blob", we redirect the downloaded data to a
    // file-handle directly.
    m_downloadingToFile = getResponseTypeCode() == ResponseTypeBlob;
    if (m_downloadingToFile) {
        request.setDownloadToFile(true);
        resourceLoaderOptions.dataBufferingPolicy = DoNotBufferData;
    }

    m_exceptionCode = 0;
    m_error = false;

    if (m_async) {
        UseCounter::count(&executionContext, UseCounter::XMLHttpRequestAsynchronous);
        if (m_upload)
            request.setReportUploadProgress(true);

        ASSERT(!m_loader);
        m_loader = ThreadableLoader::create(executionContext, this, options, resourceLoaderOptions);
        m_loader->start(request);

        return;
    }

    // Use count for XHR synchronous requests.
    UseCounter::count(&executionContext, UseCounter::XMLHttpRequestSynchronous);
    ThreadableLoader::loadResourceSynchronously(executionContext, request, *this, options, resourceLoaderOptions);

    throwForLoadFailureIfNeeded(exceptionState, String());
}

void XMLHttpRequest::abort()
{
    WTF_LOG(Network, "XMLHttpRequest %p abort()", this);

    // internalAbort() clears |m_loader|. Compute |sendFlag| now.
    //
    // |sendFlag| corresponds to "the send() flag" defined in the XHR spec.
    //
    // |sendFlag| is only set when we have an active, asynchronous loader.
    // Don't use it as "the send() flag" when the XHR is in sync mode.
    bool sendFlag = m_loader.get();

    // internalAbort() clears the response. Save the data needed for
    // dispatching ProgressEvents.
    long long expectedLength = m_response.expectedContentLength();
    long long receivedLength = m_receivedLength;

    if (!internalAbort())
        return;

    // The script never gets any chance to call abort() on a sync XHR between
    // send() call and transition to the DONE state. It's because a sync XHR
    // doesn't dispatch any event between them. So, if |m_async| is false, we
    // can skip the "request error steps" (defined in the XHR spec) without any
    // state check.
    //
    // FIXME: It's possible open() is invoked in internalAbort() and |m_async|
    // becomes true by that. We should implement more reliable treatment for
    // nested method invocations at some point.
    if (m_async) {
        if ((m_state == OPENED && sendFlag) || m_state == HEADERS_RECEIVED || m_state == LOADING) {
            ASSERT(!m_loader);
            handleRequestError(0, EventTypeNames::abort, receivedLength, expectedLength);
        }
    }
    m_state = UNSENT;
}

void XMLHttpRequest::clearVariablesForLoading()
{
    if (m_blobLoader) {
        m_blobLoader->cancel();
        m_blobLoader = nullptr;
    }

    m_decoder.reset();

    if (m_responseDocumentParser) {
        m_responseDocumentParser->removeClient(this);
        m_responseDocumentParser->detach();
        m_responseDocumentParser = nullptr;
    }

    m_finalResponseCharset = String();
}

bool XMLHttpRequest::internalAbort()
{
    m_error = true;

    if (m_responseDocumentParser && !m_responseDocumentParser->isStopped())
        m_responseDocumentParser->stopParsing();

    clearVariablesForLoading();

    if (m_responseLegacyStream && m_state != DONE)
        m_responseLegacyStream->abort();

    clearResponse();
    clearRequest();

    if (!m_loader)
        return true;

    // Cancelling the ThreadableLoader m_loader may result in calling
    // window.onload synchronously. If such an onload handler contains open()
    // call on the same XMLHttpRequest object, reentry happens.
    //
    // If, window.onload contains open() and send(), m_loader will be set to
    // non 0 value. So, we cannot continue the outer open(). In such case,
    // just abort the outer open() by returning false.
    OwnPtr<ThreadableLoader> loader = std::move(m_loader);
    loader->cancel();

    // If abort() called internalAbort() and a nested open() ended up
    // clearing the error flag, but didn't send(), make sure the error
    // flag is still set.
    bool newLoadStarted = m_loader.get();
    if (!newLoadStarted)
        m_error = true;

    return !newLoadStarted;
}

void XMLHttpRequest::clearResponse()
{
    // FIXME: when we add the support for multi-part XHR, we will have to
    // be careful with this initialization.
    m_receivedLength = 0;

    m_response = ResourceResponse();

    m_responseText.clear();

    m_parsedResponse = false;
    m_responseDocument = nullptr;

    m_responseBlob = nullptr;

    m_downloadingToFile = false;
    m_lengthDownloadedToFile = 0;

    m_responseLegacyStream = nullptr;

    // These variables may referred by the response accessors. So, we can clear
    // this only when we clear the response holder variables above.
    m_binaryResponseBuilder.clear();
    m_responseArrayBuffer.clear();
}

void XMLHttpRequest::clearRequest()
{
    m_requestHeaders.clear();
}

void XMLHttpRequest::dispatchProgressEvent(const AtomicString& type, long long receivedLength, long long expectedLength)
{
    bool lengthComputable = expectedLength > 0 && receivedLength <= expectedLength;
    unsigned long long loaded = receivedLength >= 0 ? static_cast<unsigned long long>(receivedLength) : 0;
    unsigned long long total = lengthComputable ? static_cast<unsigned long long>(expectedLength) : 0;

    ExecutionContext* context = getExecutionContext();
    InspectorInstrumentation::AsyncTask asyncTask(context, this, m_async);
    m_progressEventThrottle->dispatchProgressEvent(type, lengthComputable, loaded, total);
    if (m_async && type == EventTypeNames::loadend)
        InspectorInstrumentation::asyncTaskCanceled(context, this);
}

void XMLHttpRequest::dispatchProgressEventFromSnapshot(const AtomicString& type)
{
    dispatchProgressEvent(type, m_receivedLength, m_response.expectedContentLength());
}

void XMLHttpRequest::handleNetworkError()
{
    WTF_LOG(Network, "XMLHttpRequest %p handleNetworkError()", this);

    // Response is cleared next, save needed progress event data.
    long long expectedLength = m_response.expectedContentLength();
    long long receivedLength = m_receivedLength;

    if (!internalAbort())
        return;

    handleRequestError(NetworkError, EventTypeNames::error, receivedLength, expectedLength);
}

void XMLHttpRequest::handleDidCancel()
{
    WTF_LOG(Network, "XMLHttpRequest %p handleDidCancel()", this);

    // Response is cleared next, save needed progress event data.
    long long expectedLength = m_response.expectedContentLength();
    long long receivedLength = m_receivedLength;

    if (!internalAbort())
        return;

    handleRequestError(AbortError, EventTypeNames::abort, receivedLength, expectedLength);
}

void XMLHttpRequest::handleRequestError(ExceptionCode exceptionCode, const AtomicString& type, long long receivedLength, long long expectedLength)
{
    WTF_LOG(Network, "XMLHttpRequest %p handleRequestError()", this);

    InspectorInstrumentation::didFailXHRLoading(getExecutionContext(), this, this, m_method, m_url);

    if (!m_async) {
        ASSERT(exceptionCode);
        m_state = DONE;
        m_exceptionCode = exceptionCode;
        return;
    }

    // With m_error set, the state change steps are minimal: any pending
    // progress event is flushed + a readystatechange is dispatched.
    // No new progress events dispatched; as required, that happens at
    // the end here.
    ASSERT(m_error);
    changeState(DONE);

    if (!m_uploadComplete) {
        m_uploadComplete = true;
        if (m_upload && m_uploadEventsAllowed)
            m_upload->handleRequestError(type);
    }

    // Note: The below event dispatch may be called while |hasPendingActivity() == false|,
    // when |handleRequestError| is called after |internalAbort()|.
    // This is safe, however, as |this| will be kept alive from a strong ref |Event::m_target|.
    dispatchProgressEvent(EventTypeNames::progress, receivedLength, expectedLength);
    dispatchProgressEvent(type, receivedLength, expectedLength);
    dispatchProgressEvent(EventTypeNames::loadend, receivedLength, expectedLength);
}

void XMLHttpRequest::overrideMimeType(const AtomicString& mimeType, ExceptionState& exceptionState)
{
    if (m_state == LOADING || m_state == DONE) {
        exceptionState.throwDOMException(InvalidStateError, "MimeType cannot be overridden when the state is LOADING or DONE.");
        return;
    }

    m_mimeTypeOverride = mimeType;
}

void XMLHttpRequest::setRequestHeader(const AtomicString& name, const AtomicString& value, ExceptionState& exceptionState)
{
    if (m_state != OPENED || m_loader) {
        exceptionState.throwDOMException(InvalidStateError, "The object's state must be OPENED.");
        return;
    }

    if (!isValidHTTPToken(name)) {
        exceptionState.throwDOMException(SyntaxError, "'" + name + "' is not a valid HTTP header field name.");
        return;
    }

    if (!isValidHTTPHeaderValue(value)) {
        exceptionState.throwDOMException(SyntaxError, "'" + value + "' is not a valid HTTP header field value.");
        return;
    }

    // No script (privileged or not) can set unsafe headers.
    if (FetchUtils::isForbiddenHeaderName(name)) {
        logConsoleError(getExecutionContext(), "Refused to set unsafe header \"" + name + "\"");
        return;
    }

    setRequestHeaderInternal(name, value);
}

void XMLHttpRequest::setRequestHeaderInternal(const AtomicString& name, const AtomicString& value)
{
    HeaderValueCategoryByRFC7230 headerValueCategory = HeaderValueValid;

    HTTPHeaderMap::AddResult result = m_requestHeaders.add(name, value);
    if (!result.isNewEntry) {
        AtomicString newValue = result.storedValue->value + ", " + value;

        // Without normalization at XHR level here, the actual header value
        // sent to the network is |newValue| with leading/trailing whitespaces
        // stripped (i.e. |normalizeHeaderValue(newValue)|).
        // With normalization at XHR level here as the spec requires, the
        // actual header value sent to the network is |normalizedNewValue|.
        // If these two are different, introducing normalization here affects
        // the header value sent to the network.
        String normalizedNewValue = FetchUtils::normalizeHeaderValue(result.storedValue->value) + ", " + FetchUtils::normalizeHeaderValue(value);
        if (FetchUtils::normalizeHeaderValue(newValue) != normalizedNewValue)
            headerValueCategory = HeaderValueAffectedByNormalization;

        result.storedValue->value = newValue;
    }

    String normalizedValue = FetchUtils::normalizeHeaderValue(value);
    if (!normalizedValue.isEmpty() && !isValidHTTPFieldContentRFC7230(normalizedValue))
        headerValueCategory = HeaderValueInvalid;

    DEFINE_THREAD_SAFE_STATIC_LOCAL(EnumerationHistogram, headerValueCategoryHistogram, new EnumerationHistogram("Blink.XHR.setRequestHeader.HeaderValueCategoryInRFC7230", HeaderValueCategoryByRFC7230End));
    headerValueCategoryHistogram.count(headerValueCategory);
}

const AtomicString& XMLHttpRequest::getRequestHeader(const AtomicString& name) const
{
    return m_requestHeaders.get(name);
}

String XMLHttpRequest::getAllResponseHeaders() const
{
    if (m_state < HEADERS_RECEIVED || m_error)
        return "";

    StringBuilder stringBuilder;

    HTTPHeaderSet accessControlExposeHeaderSet;
    extractCorsExposedHeaderNamesList(m_response, accessControlExposeHeaderSet);

    HTTPHeaderMap::const_iterator end = m_response.httpHeaderFields().end();
    for (HTTPHeaderMap::const_iterator it = m_response.httpHeaderFields().begin(); it!= end; ++it) {
        // Hide any headers whose name is a forbidden response-header name.
        // This is required for all kinds of filtered responses.
        //
        // TODO: Consider removing canLoadLocalResources() call.
        // crbug.com/567527
        if (FetchUtils::isForbiddenResponseHeaderName(it->key) && !getSecurityOrigin()->canLoadLocalResources())
            continue;

        if (!m_sameOriginRequest && !isOnAccessControlResponseHeaderWhitelist(it->key) && !accessControlExposeHeaderSet.contains(it->key))
            continue;

        stringBuilder.append(it->key);
        stringBuilder.append(':');
        stringBuilder.append(' ');
        stringBuilder.append(it->value);
        stringBuilder.append('\r');
        stringBuilder.append('\n');
    }

    return stringBuilder.toString();
}

const AtomicString& XMLHttpRequest::getResponseHeader(const AtomicString& name) const
{
    if (m_state < HEADERS_RECEIVED || m_error)
        return nullAtom;

    // See comment in getAllResponseHeaders above.
    if (FetchUtils::isForbiddenResponseHeaderName(name) && !getSecurityOrigin()->canLoadLocalResources()) {
        logConsoleError(getExecutionContext(), "Refused to get unsafe header \"" + name + "\"");
        return nullAtom;
    }

    HTTPHeaderSet accessControlExposeHeaderSet;
    extractCorsExposedHeaderNamesList(m_response, accessControlExposeHeaderSet);

    if (!m_sameOriginRequest && !isOnAccessControlResponseHeaderWhitelist(name) && !accessControlExposeHeaderSet.contains(name)) {
        logConsoleError(getExecutionContext(), "Refused to get unsafe header \"" + name + "\"");
        return nullAtom;
    }
    return m_response.httpHeaderField(name);
}

AtomicString XMLHttpRequest::finalResponseMIMEType() const
{
    AtomicString overriddenType = extractMIMETypeFromMediaType(m_mimeTypeOverride);
    if (!overriddenType.isEmpty())
        return overriddenType;

    if (m_response.isHTTP())
        return extractMIMETypeFromMediaType(m_response.httpHeaderField(HTTPNames::Content_Type));

    return m_response.mimeType();
}

AtomicString XMLHttpRequest::finalResponseMIMETypeWithFallback() const
{
    AtomicString finalType = finalResponseMIMEType();
    if (!finalType.isEmpty())
        return finalType;

    // FIXME: This fallback is not specified in the final MIME type algorithm
    // of the XHR spec. Move this to more appropriate place.
    return AtomicString("text/xml");
}

bool XMLHttpRequest::responseIsXML() const
{
    return DOMImplementation::isXMLMIMEType(finalResponseMIMETypeWithFallback());
}

bool XMLHttpRequest::responseIsHTML() const
{
    return equalIgnoringCase(finalResponseMIMEType(), "text/html");
}

int XMLHttpRequest::status() const
{
    if (m_state == UNSENT || m_state == OPENED || m_error)
        return 0;

    if (m_response.httpStatusCode())
        return m_response.httpStatusCode();

    return 0;
}

String XMLHttpRequest::statusText() const
{
    if (m_state == UNSENT || m_state == OPENED || m_error)
        return String();

    if (!m_response.httpStatusText().isNull())
        return m_response.httpStatusText();

    return String();
}

void XMLHttpRequest::didFail(const ResourceError& error)
{
    WTF_LOG(Network, "XMLHttpRequest %p didFail()", this);
    ScopedEventDispatchProtect protect(&m_eventDispatchRecursionLevel);

    // If we are already in an error state, for instance we called abort(), bail out early.
    if (m_error)
        return;

    if (error.isCancellation()) {
        handleDidCancel();
        // Now the XMLHttpRequest instance may be dead.
        return;
    }

    if (error.isTimeout()) {
        handleDidTimeout();
        // Now the XMLHttpRequest instance may be dead.
        return;
    }

    // Network failures are already reported to Web Inspector by ResourceLoader.
    if (error.domain() == errorDomainBlinkInternal)
        logConsoleError(getExecutionContext(), "XMLHttpRequest cannot load " + error.failingURL() + ". " + error.localizedDescription());

    handleNetworkError();
    // Now the XMLHttpRequest instance may be dead.
}

void XMLHttpRequest::didFailRedirectCheck()
{
    WTF_LOG(Network, "XMLHttpRequest %p didFailRedirectCheck()", this);
    ScopedEventDispatchProtect protect(&m_eventDispatchRecursionLevel);

    handleNetworkError();
    // Now the XMLHttpRequest instance may be dead.
}

void XMLHttpRequest::didFinishLoading(unsigned long identifier, double)
{
    WTF_LOG(Network, "XMLHttpRequest %p didFinishLoading(%lu)", this, identifier);
    ScopedEventDispatchProtect protect(&m_eventDispatchRecursionLevel);

    if (m_error)
        return;

    if (m_state < HEADERS_RECEIVED)
        changeState(HEADERS_RECEIVED);

    if (m_downloadingToFile && m_responseTypeCode != ResponseTypeBlob && m_lengthDownloadedToFile) {
        ASSERT(m_state == LOADING);
        // In this case, we have sent the request with DownloadToFile true,
        // but the user changed the response type after that. Hence we need to
        // read the response data and provide it to this object.
        m_blobLoader = BlobLoader::create(this, createBlobDataHandleFromResponse());
    } else {
        didFinishLoadingInternal();
    }
}

void XMLHttpRequest::didFinishLoadingInternal()
{
    if (m_responseDocumentParser) {
        // |DocumentParser::finish()| tells the parser that we have reached end of the data.
        // When using |HTMLDocumentParser|, which works asynchronously, we do not have the
        // complete document just after the |DocumentParser::finish()| call.
        // Wait for the parser to call us back in |notifyParserStopped| to progress state.
        m_responseDocumentParser->finish();
        ASSERT(m_responseDocument);
        return;
    }

    if (m_decoder) {
        auto text = m_decoder->flush();
        if (!text.isEmpty() && !m_responseTextOverflow) {
            m_responseText = m_responseText.concatenateWith(text);
            m_responseTextOverflow = m_responseText.isEmpty();
        }
    }

    if (m_responseLegacyStream)
        m_responseLegacyStream->finalize();

    clearVariablesForLoading();
    endLoading();
}

void XMLHttpRequest::didFinishLoadingFromBlob()
{
    WTF_LOG(Network, "XMLHttpRequest %p didFinishLoadingFromBlob", this);
    ScopedEventDispatchProtect protect(&m_eventDispatchRecursionLevel);

    didFinishLoadingInternal();
}

void XMLHttpRequest::didFailLoadingFromBlob()
{
    WTF_LOG(Network, "XMLHttpRequest %p didFailLoadingFromBlob()", this);
    ScopedEventDispatchProtect protect(&m_eventDispatchRecursionLevel);

    if (m_error)
        return;
    handleNetworkError();
}

PassRefPtr<BlobDataHandle> XMLHttpRequest::createBlobDataHandleFromResponse()
{
    ASSERT(m_downloadingToFile);
    OwnPtr<BlobData> blobData = BlobData::create();
    String filePath = m_response.downloadedFilePath();
    // If we errored out or got no data, we return an empty handle.
    if (!filePath.isEmpty() && m_lengthDownloadedToFile) {
        blobData->appendFile(filePath, 0, m_lengthDownloadedToFile, invalidFileTime());
        // FIXME: finalResponseMIMETypeWithFallback() defaults to
        // text/xml which may be incorrect. Replace it with
        // finalResponseMIMEType() after compatibility investigation.
        blobData->setContentType(finalResponseMIMETypeWithFallback().lower());
    }
    return BlobDataHandle::create(std::move(blobData), m_lengthDownloadedToFile);
}

void XMLHttpRequest::notifyParserStopped()
{
    ScopedEventDispatchProtect protect(&m_eventDispatchRecursionLevel);

    // This should only be called when response document is parsed asynchronously.
    ASSERT(m_responseDocumentParser);
    ASSERT(!m_responseDocumentParser->isParsing());
    ASSERT(!m_responseLegacyStream);

    // Do nothing if we are called from |internalAbort()|.
    if (m_error)
        return;

    clearVariablesForLoading();

    m_responseDocument->implicitClose();

    if (!m_responseDocument->wellFormed())
        m_responseDocument = nullptr;

    m_parsedResponse = true;

    endLoading();
}

void XMLHttpRequest::endLoading()
{
    InspectorInstrumentation::didFinishXHRLoading(getExecutionContext(), this, this, m_method, m_url);

    if (m_loader)
        m_loader = nullptr;

    changeState(DONE);

    if (!getExecutionContext()->isDocument() || !document() || !document()->frame() || !document()->frame()->page())
        return;

    if (status() >= 200 && status() < 300) {
        document()->frame()->page()->chromeClient().ajaxSucceeded(document()->frame());
    }
}

void XMLHttpRequest::didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
{
    WTF_LOG(Network, "XMLHttpRequest %p didSendData(%llu, %llu)", this, bytesSent, totalBytesToBeSent);
    ScopedEventDispatchProtect protect(&m_eventDispatchRecursionLevel);

    if (!m_upload)
        return;

    if (m_uploadEventsAllowed)
        m_upload->dispatchProgressEvent(bytesSent, totalBytesToBeSent);

    if (bytesSent == totalBytesToBeSent && !m_uploadComplete) {
        m_uploadComplete = true;
        if (m_uploadEventsAllowed)
            m_upload->dispatchEventAndLoadEnd(EventTypeNames::load, true, bytesSent, totalBytesToBeSent);
    }
}

void XMLHttpRequest::didReceiveResponse(unsigned long identifier, const ResourceResponse& response, PassOwnPtr<WebDataConsumerHandle> handle)
{
    ASSERT_UNUSED(handle, !handle);
    WTF_LOG(Network, "XMLHttpRequest %p didReceiveResponse(%lu)", this, identifier);
    ScopedEventDispatchProtect protect(&m_eventDispatchRecursionLevel);

    m_response = response;
    if (!m_mimeTypeOverride.isEmpty()) {
        m_response.setHTTPHeaderField(HTTPNames::Content_Type, m_mimeTypeOverride);
        m_finalResponseCharset = extractCharsetFromMediaType(m_mimeTypeOverride);
    }

    if (m_finalResponseCharset.isEmpty())
        m_finalResponseCharset = response.textEncodingName();
}

void XMLHttpRequest::parseDocumentChunk(const char* data, unsigned len)
{
    if (!m_responseDocumentParser) {
        ASSERT(!m_responseDocument);
        initResponseDocument();
        if (!m_responseDocument)
            return;

        m_responseDocumentParser = m_responseDocument->implicitOpen(AllowAsynchronousParsing);
        m_responseDocumentParser->addClient(this);
    }
    ASSERT(m_responseDocumentParser);

    if (m_responseDocumentParser->needsDecoder())
        m_responseDocumentParser->setDecoder(createDecoder());

    m_responseDocumentParser->appendBytes(data, len);
}

PassOwnPtr<TextResourceDecoder> XMLHttpRequest::createDecoder() const
{
    if (m_responseTypeCode == ResponseTypeJSON)
        return TextResourceDecoder::create("application/json", "UTF-8");

    if (!m_finalResponseCharset.isEmpty())
        return TextResourceDecoder::create("text/plain", m_finalResponseCharset);

    // allow TextResourceDecoder to look inside the m_response if it's XML or HTML
    if (responseIsXML()) {
        OwnPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("application/xml");
        // Don't stop on encoding errors, unlike it is done for other kinds
        // of XML resources. This matches the behavior of previous WebKit
        // versions, Firefox and Opera.
        decoder->useLenientXMLDecoding();

        return decoder;
    }

    if (responseIsHTML())
        return TextResourceDecoder::create("text/html", "UTF-8");

    return TextResourceDecoder::create("text/plain", "UTF-8");
}

void XMLHttpRequest::didReceiveData(const char* data, unsigned len)
{
    ScopedEventDispatchProtect protect(&m_eventDispatchRecursionLevel);
    if (m_error)
        return;

    if (m_state < HEADERS_RECEIVED)
        changeState(HEADERS_RECEIVED);

    // We need to check for |m_error| again, because |changeState| may trigger
    // readystatechange, and user javascript can cause |abort()|.
    if (m_error)
        return;

    if (!len)
        return;

    if (m_responseTypeCode == ResponseTypeDocument && responseIsHTML()) {
        parseDocumentChunk(data, len);
    } else if (m_responseTypeCode == ResponseTypeDefault || m_responseTypeCode == ResponseTypeText || m_responseTypeCode == ResponseTypeJSON || m_responseTypeCode == ResponseTypeDocument) {
        if (!m_decoder)
            m_decoder = createDecoder();

        auto text = m_decoder->decode(data, len);
        if (!text.isEmpty() && !m_responseTextOverflow) {
            m_responseText = m_responseText.concatenateWith(text);
            m_responseTextOverflow = m_responseText.isEmpty();
        }
    } else if (m_responseTypeCode == ResponseTypeArrayBuffer || m_responseTypeCode == ResponseTypeBlob) {
        // Buffer binary data.
        if (!m_binaryResponseBuilder)
            m_binaryResponseBuilder = SharedBuffer::create();
        m_binaryResponseBuilder->append(data, len);
    } else if (m_responseTypeCode == ResponseTypeLegacyStream) {
        if (!m_responseLegacyStream)
            m_responseLegacyStream = Stream::create(getExecutionContext(), responseType());
        m_responseLegacyStream->addData(data, len);
    }

    if (m_blobLoader) {
        // In this case, the data is provided by m_blobLoader. As progress
        // events are already fired, we should return here.
        return;
    }
    trackProgress(len);
}

void XMLHttpRequest::didDownloadData(int dataLength)
{
    ScopedEventDispatchProtect protect(&m_eventDispatchRecursionLevel);
    if (m_error)
        return;

    ASSERT(m_downloadingToFile);

    if (m_state < HEADERS_RECEIVED)
        changeState(HEADERS_RECEIVED);

    if (!dataLength)
        return;

    // readystatechange event handler may do something to put this XHR in error
    // state. We need to check m_error again here.
    if (m_error)
        return;

    m_lengthDownloadedToFile += dataLength;

    trackProgress(dataLength);
}

void XMLHttpRequest::handleDidTimeout()
{
    WTF_LOG(Network, "XMLHttpRequest %p handleDidTimeout()", this);

    // Response is cleared next, save needed progress event data.
    long long expectedLength = m_response.expectedContentLength();
    long long receivedLength = m_receivedLength;

    if (!internalAbort())
        return;

    handleRequestError(TimeoutError, EventTypeNames::timeout, receivedLength, expectedLength);
}

void XMLHttpRequest::suspend()
{
    m_progressEventThrottle->suspend();
}

void XMLHttpRequest::resume()
{
    m_progressEventThrottle->resume();
}

void XMLHttpRequest::stop()
{
    InspectorInstrumentation::didFailXHRLoading(getExecutionContext(), this, this, m_method, m_url);
    m_progressEventThrottle->stop();
    internalAbort();
}

bool XMLHttpRequest::hasPendingActivity() const
{
    // Neither this object nor the JavaScript wrapper should be deleted while
    // a request is in progress because we need to keep the listeners alive,
    // and they are referenced by the JavaScript wrapper.
    // |m_loader| is non-null while request is active and ThreadableLoaderClient
    // callbacks may be called, and |m_responseDocumentParser| is non-null while
    // DocumentParserClient callbacks may be called.
    if (m_loader || m_responseDocumentParser)
        return true;
    return m_eventDispatchRecursionLevel > 0;
}

void XMLHttpRequest::contextDestroyed()
{
    ASSERT(!m_loader);
    ActiveDOMObject::contextDestroyed();
}

const AtomicString& XMLHttpRequest::interfaceName() const
{
    return EventTargetNames::XMLHttpRequest;
}

ExecutionContext* XMLHttpRequest::getExecutionContext() const
{
    return ActiveDOMObject::getExecutionContext();
}

DEFINE_TRACE(XMLHttpRequest)
{
    visitor->trace(m_responseBlob);
    visitor->trace(m_responseLegacyStream);
    visitor->trace(m_responseDocument);
    visitor->trace(m_responseDocumentParser);
    visitor->trace(m_responseArrayBuffer);
    visitor->trace(m_progressEventThrottle);
    visitor->trace(m_upload);
    visitor->trace(m_blobLoader);
    XMLHttpRequestEventTarget::trace(visitor);
    DocumentParserClient::trace(visitor);
    ActiveDOMObject::trace(visitor);
}

} // namespace blink
