Home | History | Annotate | Download | only in xml
      1 /*
      2  *  Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved.
      3  *  Copyright (C) 2005-2007 Alexey Proskuryakov <ap (at) webkit.org>
      4  *  Copyright (C) 2007, 2008 Julien Chaffraix <jchaffraix (at) webkit.org>
      5  *  Copyright (C) 2008, 2011 Google Inc. All rights reserved.
      6  *  Copyright (C) 2012 Intel Corporation
      7  *
      8  *  This library is free software; you can redistribute it and/or
      9  *  modify it under the terms of the GNU Lesser General Public
     10  *  License as published by the Free Software Foundation; either
     11  *  version 2 of the License, or (at your option) any later version.
     12  *
     13  *  This library is distributed in the hope that it will be useful,
     14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     16  *  Lesser General Public License for more details.
     17  *
     18  *  You should have received a copy of the GNU Lesser General Public
     19  *  License along with this library; if not, write to the Free Software
     20  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
     21  */
     22 
     23 #include "config.h"
     24 #include "core/xml/XMLHttpRequest.h"
     25 
     26 #include "bindings/core/v8/ExceptionState.h"
     27 #include "core/FetchInitiatorTypeNames.h"
     28 #include "core/dom/ContextFeatures.h"
     29 #include "core/dom/DOMException.h"
     30 #include "core/dom/DOMImplementation.h"
     31 #include "core/dom/DocumentParser.h"
     32 #include "core/dom/ExceptionCode.h"
     33 #include "core/dom/XMLDocument.h"
     34 #include "core/editing/markup.h"
     35 #include "core/events/Event.h"
     36 #include "core/fetch/FetchUtils.h"
     37 #include "core/fileapi/Blob.h"
     38 #include "core/fileapi/File.h"
     39 #include "core/frame/Settings.h"
     40 #include "core/frame/UseCounter.h"
     41 #include "core/frame/csp/ContentSecurityPolicy.h"
     42 #include "core/html/DOMFormData.h"
     43 #include "core/html/HTMLDocument.h"
     44 #include "core/html/parser/TextResourceDecoder.h"
     45 #include "core/inspector/ConsoleMessage.h"
     46 #include "core/inspector/InspectorInstrumentation.h"
     47 #include "core/inspector/InspectorTraceEvents.h"
     48 #include "core/loader/ThreadableLoader.h"
     49 #include "core/streams/ReadableStream.h"
     50 #include "core/streams/ReadableStreamImpl.h"
     51 #include "core/streams/Stream.h"
     52 #include "core/streams/UnderlyingSource.h"
     53 #include "core/xml/XMLHttpRequestProgressEvent.h"
     54 #include "core/xml/XMLHttpRequestUpload.h"
     55 #include "platform/Logging.h"
     56 #include "platform/RuntimeEnabledFeatures.h"
     57 #include "platform/SharedBuffer.h"
     58 #include "platform/blob/BlobData.h"
     59 #include "platform/network/HTTPParsers.h"
     60 #include "platform/network/ParsedContentType.h"
     61 #include "platform/network/ResourceError.h"
     62 #include "platform/network/ResourceRequest.h"
     63 #include "public/platform/WebURLRequest.h"
     64 #include "wtf/ArrayBuffer.h"
     65 #include "wtf/ArrayBufferView.h"
     66 #include "wtf/Assertions.h"
     67 #include "wtf/RefCountedLeakCounter.h"
     68 #include "wtf/StdLibExtras.h"
     69 #include "wtf/text/CString.h"
     70 
     71 namespace blink {
     72 
     73 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, xmlHttpRequestCounter, ("XMLHttpRequest"));
     74 
     75 static bool isSetCookieHeader(const AtomicString& name)
     76 {
     77     return equalIgnoringCase(name, "set-cookie") || equalIgnoringCase(name, "set-cookie2");
     78 }
     79 
     80 static void replaceCharsetInMediaType(String& mediaType, const String& charsetValue)
     81 {
     82     unsigned pos = 0, len = 0;
     83 
     84     findCharsetInMediaType(mediaType, pos, len);
     85 
     86     if (!len) {
     87         // When no charset found, do nothing.
     88         return;
     89     }
     90 
     91     // Found at least one existing charset, replace all occurrences with new charset.
     92     while (len) {
     93         mediaType.replace(pos, len, charsetValue);
     94         unsigned start = pos + charsetValue.length();
     95         findCharsetInMediaType(mediaType, pos, len, start);
     96     }
     97 }
     98 
     99 static void logConsoleError(ExecutionContext* context, const String& message)
    100 {
    101     if (!context)
    102         return;
    103     // FIXME: It's not good to report the bad usage without indicating what source line it came from.
    104     // We should pass additional parameters so we can tell the console where the mistake occurred.
    105     context->addConsoleMessage(ConsoleMessage::create(JSMessageSource, ErrorMessageLevel, message));
    106 }
    107 
    108 namespace {
    109 
    110 class ReadableStreamSource : public GarbageCollectedFinalized<ReadableStreamSource>, public UnderlyingSource {
    111     USING_GARBAGE_COLLECTED_MIXIN(ReadableStreamSource);
    112 public:
    113     ReadableStreamSource(XMLHttpRequest* owner) : m_owner(owner) { }
    114     virtual ~ReadableStreamSource() { }
    115     virtual void pullSource() OVERRIDE { }
    116     virtual ScriptPromise cancelSource(ScriptState* scriptState, ScriptValue reason) OVERRIDE
    117     {
    118         m_owner->abort();
    119         return ScriptPromise::cast(scriptState, v8::Undefined(scriptState->isolate()));
    120     }
    121     virtual void trace(Visitor* visitor) OVERRIDE
    122     {
    123         visitor->trace(m_owner);
    124         UnderlyingSource::trace(visitor);
    125     }
    126 
    127 private:
    128     // This is RawPtr in non-oilpan build to avoid the reference cycle. To
    129     // avoid use-after free, the associated ReadableStream must be closed
    130     // or errored when m_owner is gone.
    131     RawPtrWillBeMember<XMLHttpRequest> m_owner;
    132 };
    133 
    134 } // namespace
    135 
    136 PassRefPtrWillBeRawPtr<XMLHttpRequest> XMLHttpRequest::create(ExecutionContext* context, PassRefPtr<SecurityOrigin> securityOrigin)
    137 {
    138     RefPtrWillBeRawPtr<XMLHttpRequest> xmlHttpRequest = adoptRefWillBeNoop(new XMLHttpRequest(context, securityOrigin));
    139     xmlHttpRequest->suspendIfNeeded();
    140 
    141     return xmlHttpRequest.release();
    142 }
    143 
    144 XMLHttpRequest::XMLHttpRequest(ExecutionContext* context, PassRefPtr<SecurityOrigin> securityOrigin)
    145     : ActiveDOMObject(context)
    146     , m_timeoutMilliseconds(0)
    147     , m_loaderIdentifier(0)
    148     , m_state(UNSENT)
    149     , m_lengthDownloadedToFile(0)
    150     , m_receivedLength(0)
    151     , m_lastSendLineNumber(0)
    152     , m_exceptionCode(0)
    153     , m_progressEventThrottle(this)
    154     , m_responseTypeCode(ResponseTypeDefault)
    155     , m_securityOrigin(securityOrigin)
    156     , m_async(true)
    157     , m_includeCredentials(false)
    158     , m_parsedResponse(false)
    159     , m_error(false)
    160     , m_uploadEventsAllowed(true)
    161     , m_uploadComplete(false)
    162     , m_sameOriginRequest(true)
    163     , m_downloadingToFile(false)
    164 {
    165 #ifndef NDEBUG
    166     xmlHttpRequestCounter.increment();
    167 #endif
    168 }
    169 
    170 XMLHttpRequest::~XMLHttpRequest()
    171 {
    172 #ifndef NDEBUG
    173     xmlHttpRequestCounter.decrement();
    174 #endif
    175 }
    176 
    177 Document* XMLHttpRequest::document() const
    178 {
    179     ASSERT(executionContext()->isDocument());
    180     return toDocument(executionContext());
    181 }
    182 
    183 SecurityOrigin* XMLHttpRequest::securityOrigin() const
    184 {
    185     return m_securityOrigin ? m_securityOrigin.get() : executionContext()->securityOrigin();
    186 }
    187 
    188 XMLHttpRequest::State XMLHttpRequest::readyState() const
    189 {
    190     return m_state;
    191 }
    192 
    193 ScriptString XMLHttpRequest::responseText(ExceptionState& exceptionState)
    194 {
    195     if (m_responseTypeCode != ResponseTypeDefault && m_responseTypeCode != ResponseTypeText) {
    196         exceptionState.throwDOMException(InvalidStateError, "The value is only accessible if the object's 'responseType' is '' or 'text' (was '" + responseType() + "').");
    197         return ScriptString();
    198     }
    199     if (m_error || (m_state != LOADING && m_state != DONE))
    200         return ScriptString();
    201     return m_responseText;
    202 }
    203 
    204 ScriptString XMLHttpRequest::responseJSONSource()
    205 {
    206     ASSERT(m_responseTypeCode == ResponseTypeJSON);
    207 
    208     if (m_error || m_state != DONE)
    209         return ScriptString();
    210     return m_responseText;
    211 }
    212 
    213 void XMLHttpRequest::initResponseDocument()
    214 {
    215     // The W3C spec requires the final MIME type to be some valid XML type, or text/html.
    216     // If it is text/html, then the responseType of "document" must have been supplied explicitly.
    217     bool isHTML = responseIsHTML();
    218     if ((m_response.isHTTP() && !responseIsXML() && !isHTML)
    219         || (isHTML && m_responseTypeCode == ResponseTypeDefault)
    220         || executionContext()->isWorkerGlobalScope()) {
    221         m_responseDocument = nullptr;
    222         return;
    223     }
    224 
    225     DocumentInit init = DocumentInit::fromContext(document()->contextDocument(), m_url);
    226     if (isHTML)
    227         m_responseDocument = HTMLDocument::create(init);
    228     else
    229         m_responseDocument = XMLDocument::create(init);
    230 
    231     // FIXME: Set Last-Modified.
    232     m_responseDocument->setSecurityOrigin(securityOrigin());
    233     m_responseDocument->setContextFeatures(document()->contextFeatures());
    234     m_responseDocument->setMimeType(finalResponseMIMETypeWithFallback());
    235 }
    236 
    237 Document* XMLHttpRequest::responseXML(ExceptionState& exceptionState)
    238 {
    239     if (m_responseTypeCode != ResponseTypeDefault && m_responseTypeCode != ResponseTypeDocument) {
    240         exceptionState.throwDOMException(InvalidStateError, "The value is only accessible if the object's 'responseType' is '' or 'document' (was '" + responseType() + "').");
    241         return 0;
    242     }
    243 
    244     if (m_error || m_state != DONE)
    245         return 0;
    246 
    247     if (!m_parsedResponse) {
    248         initResponseDocument();
    249         if (!m_responseDocument)
    250             return nullptr;
    251 
    252         m_responseDocument->setContent(m_responseText.flattenToString());
    253         if (!m_responseDocument->wellFormed())
    254             m_responseDocument = nullptr;
    255 
    256         m_parsedResponse = true;
    257     }
    258 
    259     return m_responseDocument.get();
    260 }
    261 
    262 Blob* XMLHttpRequest::responseBlob()
    263 {
    264     ASSERT(m_responseTypeCode == ResponseTypeBlob);
    265 
    266     // We always return null before DONE.
    267     if (m_error || m_state != DONE)
    268         return 0;
    269 
    270     if (!m_responseBlob) {
    271         OwnPtr<BlobData> blobData = BlobData::create();
    272         if (m_downloadingToFile) {
    273             ASSERT(!m_binaryResponseBuilder.get());
    274 
    275             // When responseType is set to "blob", we redirect the downloaded
    276             // data to a file-handle directly in the browser process. We get
    277             // the file-path from the ResourceResponse directly instead of
    278             // copying the bytes between the browser and the renderer.
    279             String filePath = m_response.downloadedFilePath();
    280             // If we errored out or got no data, we still return a blob, just
    281             // an empty one.
    282             if (!filePath.isEmpty() && m_lengthDownloadedToFile) {
    283                 blobData->appendFile(filePath);
    284                 // FIXME: finalResponseMIMETypeWithFallback() defaults to
    285                 // text/xml which may be incorrect. Replace it with
    286                 // finalResponseMIMEType() after compatibility investigation.
    287                 blobData->setContentType(finalResponseMIMETypeWithFallback());
    288             }
    289             m_responseBlob = Blob::create(BlobDataHandle::create(blobData.release(), m_lengthDownloadedToFile));
    290         } else {
    291             size_t size = 0;
    292             if (m_binaryResponseBuilder.get() && m_binaryResponseBuilder->size()) {
    293                 size = m_binaryResponseBuilder->size();
    294                 blobData->appendBytes(m_binaryResponseBuilder->data(), size);
    295                 blobData->setContentType(finalResponseMIMETypeWithFallback());
    296                 m_binaryResponseBuilder.clear();
    297             }
    298             m_responseBlob = Blob::create(BlobDataHandle::create(blobData.release(), size));
    299         }
    300     }
    301 
    302     return m_responseBlob.get();
    303 }
    304 
    305 ArrayBuffer* XMLHttpRequest::responseArrayBuffer()
    306 {
    307     ASSERT(m_responseTypeCode == ResponseTypeArrayBuffer);
    308 
    309     if (m_error || m_state != DONE)
    310         return 0;
    311 
    312     if (!m_responseArrayBuffer.get()) {
    313         if (m_binaryResponseBuilder.get() && m_binaryResponseBuilder->size() > 0) {
    314             m_responseArrayBuffer = m_binaryResponseBuilder->getAsArrayBuffer();
    315             if (!m_responseArrayBuffer) {
    316                 // m_binaryResponseBuilder failed to allocate an ArrayBuffer.
    317                 // We need to crash the renderer since there's no way defined in
    318                 // the spec to tell this to the user.
    319                 CRASH();
    320             }
    321             m_binaryResponseBuilder.clear();
    322         } else {
    323             m_responseArrayBuffer = ArrayBuffer::create(static_cast<void*>(0), 0);
    324         }
    325     }
    326 
    327     return m_responseArrayBuffer.get();
    328 }
    329 
    330 Stream* XMLHttpRequest::responseLegacyStream()
    331 {
    332     ASSERT(m_responseTypeCode == ResponseTypeLegacyStream);
    333 
    334     if (m_error || (m_state != LOADING && m_state != DONE))
    335         return 0;
    336 
    337     return m_responseLegacyStream.get();
    338 }
    339 
    340 ReadableStream* XMLHttpRequest::responseStream()
    341 {
    342     ASSERT(m_responseTypeCode == ResponseTypeStream);
    343     if (m_error || (m_state != LOADING && m_state != DONE))
    344         return 0;
    345 
    346     return m_responseStream;
    347 }
    348 
    349 void XMLHttpRequest::setTimeout(unsigned long timeout, ExceptionState& exceptionState)
    350 {
    351     // FIXME: Need to trigger or update the timeout Timer here, if needed. http://webkit.org/b/98156
    352     // 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."
    353     if (executionContext()->isDocument() && !m_async) {
    354         exceptionState.throwDOMException(InvalidAccessError, "Timeouts cannot be set for synchronous requests made from a document.");
    355         return;
    356     }
    357 
    358     m_timeoutMilliseconds = timeout;
    359 
    360     // From http://www.w3.org/TR/XMLHttpRequest/#the-timeout-attribute:
    361     // Note: This implies that the timeout attribute can be set while fetching is in progress. If
    362     // that occurs it will still be measured relative to the start of fetching.
    363     //
    364     // The timeout may be overridden after send.
    365     if (m_loader)
    366         m_loader->overrideTimeout(timeout);
    367 }
    368 
    369 void XMLHttpRequest::setResponseType(const String& responseType, ExceptionState& exceptionState)
    370 {
    371     if (m_state >= LOADING) {
    372         exceptionState.throwDOMException(InvalidStateError, "The response type cannot be set if the object's state is LOADING or DONE.");
    373         return;
    374     }
    375 
    376     // Newer functionality is not available to synchronous requests in window contexts, as a spec-mandated
    377     // attempt to discourage synchronous XHR use. responseType is one such piece of functionality.
    378     if (!m_async && executionContext()->isDocument()) {
    379         exceptionState.throwDOMException(InvalidAccessError, "The response type cannot be changed for synchronous requests made from a document.");
    380         return;
    381     }
    382 
    383     if (responseType == "") {
    384         m_responseTypeCode = ResponseTypeDefault;
    385     } else if (responseType == "text") {
    386         m_responseTypeCode = ResponseTypeText;
    387     } else if (responseType == "json") {
    388         m_responseTypeCode = ResponseTypeJSON;
    389     } else if (responseType == "document") {
    390         m_responseTypeCode = ResponseTypeDocument;
    391     } else if (responseType == "blob") {
    392         m_responseTypeCode = ResponseTypeBlob;
    393     } else if (responseType == "arraybuffer") {
    394         m_responseTypeCode = ResponseTypeArrayBuffer;
    395     } else if (responseType == "legacystream") {
    396         if (RuntimeEnabledFeatures::streamEnabled())
    397             m_responseTypeCode = ResponseTypeLegacyStream;
    398         else
    399             return;
    400     } else if (responseType == "stream") {
    401         if (RuntimeEnabledFeatures::streamEnabled())
    402             m_responseTypeCode = ResponseTypeStream;
    403         else
    404             return;
    405     } else {
    406         ASSERT_NOT_REACHED();
    407     }
    408 }
    409 
    410 String XMLHttpRequest::responseType()
    411 {
    412     switch (m_responseTypeCode) {
    413     case ResponseTypeDefault:
    414         return "";
    415     case ResponseTypeText:
    416         return "text";
    417     case ResponseTypeJSON:
    418         return "json";
    419     case ResponseTypeDocument:
    420         return "document";
    421     case ResponseTypeBlob:
    422         return "blob";
    423     case ResponseTypeArrayBuffer:
    424         return "arraybuffer";
    425     case ResponseTypeLegacyStream:
    426         return "legacystream";
    427     case ResponseTypeStream:
    428         return "stream";
    429     }
    430     return "";
    431 }
    432 
    433 String XMLHttpRequest::responseURL()
    434 {
    435     return m_response.url().string();
    436 }
    437 
    438 XMLHttpRequestUpload* XMLHttpRequest::upload()
    439 {
    440     if (!m_upload)
    441         m_upload = XMLHttpRequestUpload::create(this);
    442     return m_upload.get();
    443 }
    444 
    445 void XMLHttpRequest::trackProgress(int length)
    446 {
    447     m_receivedLength += length;
    448 
    449     if (m_state != LOADING) {
    450         changeState(LOADING);
    451     } else {
    452         // Dispatch a readystatechange event because many applications use
    453         // it to track progress although this is not specified.
    454         //
    455         // FIXME: Stop dispatching this event for progress tracking.
    456         dispatchReadyStateChangeEvent();
    457     }
    458     if (m_async)
    459         dispatchProgressEventFromSnapshot(EventTypeNames::progress);
    460 }
    461 
    462 void XMLHttpRequest::changeState(State newState)
    463 {
    464     if (m_state != newState) {
    465         m_state = newState;
    466         dispatchReadyStateChangeEvent();
    467     }
    468 }
    469 
    470 void XMLHttpRequest::dispatchReadyStateChangeEvent()
    471 {
    472     if (!executionContext())
    473         return;
    474 
    475     InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchXHRReadyStateChangeEvent(executionContext(), this);
    476 
    477     if (m_async || (m_state <= OPENED || m_state == DONE)) {
    478         TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "XHRReadyStateChange", "data", InspectorXhrReadyStateChangeEvent::data(executionContext(), this));
    479         TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack());
    480         XMLHttpRequestProgressEventThrottle::DeferredEventAction action = XMLHttpRequestProgressEventThrottle::Ignore;
    481         if (m_state == DONE) {
    482             if (m_error)
    483                 action = XMLHttpRequestProgressEventThrottle::Clear;
    484             else
    485                 action = XMLHttpRequestProgressEventThrottle::Flush;
    486         }
    487         m_progressEventThrottle.dispatchReadyStateChangeEvent(Event::create(EventTypeNames::readystatechange), action);
    488         TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", "data", InspectorUpdateCountersEvent::data());
    489     }
    490 
    491     InspectorInstrumentation::didDispatchXHRReadyStateChangeEvent(cookie);
    492     if (m_state == DONE && !m_error) {
    493         {
    494             TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "XHRLoad", "data", InspectorXhrLoadEvent::data(executionContext(), this));
    495             TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack());
    496             InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchXHRLoadEvent(executionContext(), this);
    497             dispatchProgressEventFromSnapshot(EventTypeNames::load);
    498             InspectorInstrumentation::didDispatchXHRLoadEvent(cookie);
    499         }
    500         dispatchProgressEventFromSnapshot(EventTypeNames::loadend);
    501         TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", "data", InspectorUpdateCountersEvent::data());
    502     }
    503 }
    504 
    505 void XMLHttpRequest::setWithCredentials(bool value, ExceptionState& exceptionState)
    506 {
    507     if (m_state > OPENED || m_loader) {
    508         exceptionState.throwDOMException(InvalidStateError,  "The value may only be set if the object's state is UNSENT or OPENED.");
    509         return;
    510     }
    511 
    512     // FIXME: According to XMLHttpRequest Level 2 we should throw InvalidAccessError exception here.
    513     // However for time being only print warning message to warn web developers.
    514     if (!m_async)
    515         UseCounter::countDeprecation(executionContext(), UseCounter::SyncXHRWithCredentials);
    516 
    517     m_includeCredentials = value;
    518 }
    519 
    520 AtomicString XMLHttpRequest::uppercaseKnownHTTPMethod(const AtomicString& method)
    521 {
    522     // Valid methods per step-5 of http://xhr.spec.whatwg.org/#the-open()-method.
    523     const char* const methods[] = {
    524         "DELETE",
    525         "GET",
    526         "HEAD",
    527         "OPTIONS",
    528         "POST",
    529         "PUT" };
    530 
    531     for (unsigned i = 0; i < WTF_ARRAY_LENGTH(methods); ++i) {
    532         if (equalIgnoringCase(method, methods[i])) {
    533             // Don't bother allocating a new string if it's already all uppercase.
    534             if (method == methods[i])
    535                 return method;
    536             return methods[i];
    537         }
    538     }
    539     return method;
    540 }
    541 
    542 void XMLHttpRequest::open(const AtomicString& method, const KURL& url, ExceptionState& exceptionState)
    543 {
    544     open(method, url, true, exceptionState);
    545 }
    546 
    547 void XMLHttpRequest::open(const AtomicString& method, const KURL& url, bool async, ExceptionState& exceptionState)
    548 {
    549     WTF_LOG(Network, "XMLHttpRequest %p open('%s', '%s', %d)", this, method.utf8().data(), url.elidedString().utf8().data(), async);
    550 
    551     if (!internalAbort())
    552         return;
    553 
    554     State previousState = m_state;
    555     m_state = UNSENT;
    556     m_error = false;
    557     m_uploadComplete = false;
    558 
    559     if (!isValidHTTPToken(method)) {
    560         exceptionState.throwDOMException(SyntaxError, "'" + method + "' is not a valid HTTP method.");
    561         return;
    562     }
    563 
    564     if (FetchUtils::isForbiddenMethod(method)) {
    565         exceptionState.throwSecurityError("'" + method + "' HTTP method is unsupported.");
    566         return;
    567     }
    568 
    569     if (!ContentSecurityPolicy::shouldBypassMainWorld(executionContext()) && !executionContext()->contentSecurityPolicy()->allowConnectToSource(url)) {
    570         // We can safely expose the URL to JavaScript, as these checks happen synchronously before redirection. JavaScript receives no new information.
    571         exceptionState.throwSecurityError("Refused to connect to '" + url.elidedString() + "' because it violates the document's Content Security Policy.");
    572         return;
    573     }
    574 
    575     if (!async && executionContext()->isDocument()) {
    576         if (document()->settings() && !document()->settings()->syncXHRInDocumentsEnabled()) {
    577             exceptionState.throwDOMException(InvalidAccessError, "Synchronous requests are disabled for this page.");
    578             return;
    579         }
    580 
    581         // Newer functionality is not available to synchronous requests in window contexts, as a spec-mandated
    582         // attempt to discourage synchronous XHR use. responseType is one such piece of functionality.
    583         if (m_responseTypeCode != ResponseTypeDefault) {
    584             exceptionState.throwDOMException(InvalidAccessError, "Synchronous requests from a document must not set a response type.");
    585             return;
    586         }
    587 
    588         // Similarly, timeouts are disabled for synchronous requests as well.
    589         if (m_timeoutMilliseconds > 0) {
    590             exceptionState.throwDOMException(InvalidAccessError, "Synchronous requests must not set a timeout.");
    591             return;
    592         }
    593     }
    594 
    595     m_method = uppercaseKnownHTTPMethod(method);
    596 
    597     m_url = url;
    598 
    599     m_async = async;
    600 
    601     ASSERT(!m_loader);
    602 
    603     // Check previous state to avoid dispatching readyState event
    604     // when calling open several times in a row.
    605     if (previousState != OPENED)
    606         changeState(OPENED);
    607     else
    608         m_state = OPENED;
    609 }
    610 
    611 void XMLHttpRequest::open(const AtomicString& method, const KURL& url, bool async, const String& user, ExceptionState& exceptionState)
    612 {
    613     KURL urlWithCredentials(url);
    614     urlWithCredentials.setUser(user);
    615 
    616     open(method, urlWithCredentials, async, exceptionState);
    617 }
    618 
    619 void XMLHttpRequest::open(const AtomicString& method, const KURL& url, bool async, const String& user, const String& password, ExceptionState& exceptionState)
    620 {
    621     KURL urlWithCredentials(url);
    622     urlWithCredentials.setUser(user);
    623     urlWithCredentials.setPass(password);
    624 
    625     open(method, urlWithCredentials, async, exceptionState);
    626 }
    627 
    628 bool XMLHttpRequest::initSend(ExceptionState& exceptionState)
    629 {
    630     if (!executionContext())
    631         return false;
    632 
    633     if (m_state != OPENED || m_loader) {
    634         exceptionState.throwDOMException(InvalidStateError, "The object's state must be OPENED.");
    635         return false;
    636     }
    637 
    638     m_error = false;
    639     return true;
    640 }
    641 
    642 void XMLHttpRequest::send(ExceptionState& exceptionState)
    643 {
    644     send(String(), exceptionState);
    645 }
    646 
    647 bool XMLHttpRequest::areMethodAndURLValidForSend()
    648 {
    649     return m_method != "GET" && m_method != "HEAD" && m_url.protocolIsInHTTPFamily();
    650 }
    651 
    652 void XMLHttpRequest::send(Document* document, ExceptionState& exceptionState)
    653 {
    654     WTF_LOG(Network, "XMLHttpRequest %p send() Document %p", this, document);
    655 
    656     ASSERT(document);
    657 
    658     if (!initSend(exceptionState))
    659         return;
    660 
    661     RefPtr<FormData> httpBody;
    662 
    663     if (areMethodAndURLValidForSend()) {
    664         if (getRequestHeader("Content-Type").isEmpty()) {
    665             // FIXME: this should include the charset used for encoding.
    666             setRequestHeaderInternal("Content-Type", "application/xml");
    667         }
    668 
    669         // FIXME: According to XMLHttpRequest Level 2, this should use the Document.innerHTML algorithm
    670         // from the HTML5 specification to serialize the document.
    671         String body = createMarkup(document);
    672 
    673         // FIXME: This should use value of document.inputEncoding to determine the encoding to use.
    674         httpBody = FormData::create(UTF8Encoding().encode(body, WTF::EntitiesForUnencodables));
    675         if (m_upload)
    676             httpBody->setAlwaysStream(true);
    677     }
    678 
    679     createRequest(httpBody.release(), exceptionState);
    680 }
    681 
    682 void XMLHttpRequest::send(const String& body, ExceptionState& exceptionState)
    683 {
    684     WTF_LOG(Network, "XMLHttpRequest %p send() String '%s'", this, body.utf8().data());
    685 
    686     if (!initSend(exceptionState))
    687         return;
    688 
    689     RefPtr<FormData> httpBody;
    690 
    691     if (!body.isNull() && areMethodAndURLValidForSend()) {
    692         String contentType = getRequestHeader("Content-Type");
    693         if (contentType.isEmpty()) {
    694             setRequestHeaderInternal("Content-Type", "text/plain;charset=UTF-8");
    695         } else {
    696             replaceCharsetInMediaType(contentType, "UTF-8");
    697             m_requestHeaders.set("Content-Type", AtomicString(contentType));
    698         }
    699 
    700         httpBody = FormData::create(UTF8Encoding().encode(body, WTF::EntitiesForUnencodables));
    701         if (m_upload)
    702             httpBody->setAlwaysStream(true);
    703     }
    704 
    705     createRequest(httpBody.release(), exceptionState);
    706 }
    707 
    708 void XMLHttpRequest::send(Blob* body, ExceptionState& exceptionState)
    709 {
    710     WTF_LOG(Network, "XMLHttpRequest %p send() Blob '%s'", this, body->uuid().utf8().data());
    711 
    712     if (!initSend(exceptionState))
    713         return;
    714 
    715     RefPtr<FormData> httpBody;
    716 
    717     if (areMethodAndURLValidForSend()) {
    718         if (getRequestHeader("Content-Type").isEmpty()) {
    719             const String& blobType = body->type();
    720             if (!blobType.isEmpty() && isValidContentType(blobType)) {
    721                 setRequestHeaderInternal("Content-Type", AtomicString(blobType));
    722             } else {
    723                 // From FileAPI spec, whenever media type cannot be determined,
    724                 // empty string must be returned.
    725                 setRequestHeaderInternal("Content-Type", "");
    726             }
    727         }
    728 
    729         // FIXME: add support for uploading bundles.
    730         httpBody = FormData::create();
    731         if (body->hasBackingFile()) {
    732             File* file = toFile(body);
    733             if (!file->path().isEmpty())
    734                 httpBody->appendFile(file->path());
    735             else if (!file->fileSystemURL().isEmpty())
    736                 httpBody->appendFileSystemURL(file->fileSystemURL());
    737             else
    738                 ASSERT_NOT_REACHED();
    739         } else {
    740             httpBody->appendBlob(body->uuid(), body->blobDataHandle());
    741         }
    742     }
    743 
    744     createRequest(httpBody.release(), exceptionState);
    745 }
    746 
    747 void XMLHttpRequest::send(DOMFormData* body, ExceptionState& exceptionState)
    748 {
    749     WTF_LOG(Network, "XMLHttpRequest %p send() DOMFormData %p", this, body);
    750 
    751     if (!initSend(exceptionState))
    752         return;
    753 
    754     RefPtr<FormData> httpBody;
    755 
    756     if (areMethodAndURLValidForSend()) {
    757         httpBody = body->createMultiPartFormData();
    758 
    759         if (getRequestHeader("Content-Type").isEmpty()) {
    760             AtomicString contentType = AtomicString("multipart/form-data; boundary=", AtomicString::ConstructFromLiteral) + httpBody->boundary().data();
    761             setRequestHeaderInternal("Content-Type", contentType);
    762         }
    763     }
    764 
    765     createRequest(httpBody.release(), exceptionState);
    766 }
    767 
    768 void XMLHttpRequest::send(ArrayBuffer* body, ExceptionState& exceptionState)
    769 {
    770     WTF_LOG(Network, "XMLHttpRequest %p send() ArrayBuffer %p", this, body);
    771 
    772     sendBytesData(body->data(), body->byteLength(), exceptionState);
    773 }
    774 
    775 void XMLHttpRequest::send(ArrayBufferView* body, ExceptionState& exceptionState)
    776 {
    777     WTF_LOG(Network, "XMLHttpRequest %p send() ArrayBufferView %p", this, body);
    778 
    779     sendBytesData(body->baseAddress(), body->byteLength(), exceptionState);
    780 }
    781 
    782 void XMLHttpRequest::sendBytesData(const void* data, size_t length, ExceptionState& exceptionState)
    783 {
    784     if (!initSend(exceptionState))
    785         return;
    786 
    787     RefPtr<FormData> httpBody;
    788 
    789     if (areMethodAndURLValidForSend()) {
    790         httpBody = FormData::create(data, length);
    791         if (m_upload)
    792             httpBody->setAlwaysStream(true);
    793     }
    794 
    795     createRequest(httpBody.release(), exceptionState);
    796 }
    797 
    798 void XMLHttpRequest::sendForInspectorXHRReplay(PassRefPtr<FormData> formData, ExceptionState& exceptionState)
    799 {
    800     createRequest(formData ? formData->deepCopy() : nullptr, exceptionState);
    801     m_exceptionCode = exceptionState.code();
    802 }
    803 
    804 void XMLHttpRequest::createRequest(PassRefPtr<FormData> httpBody, ExceptionState& exceptionState)
    805 {
    806     // Only GET request is supported for blob URL.
    807     if (m_url.protocolIs("blob") && m_method != "GET") {
    808         exceptionState.throwDOMException(NetworkError, "'GET' is the only method allowed for 'blob:' URLs.");
    809         return;
    810     }
    811 
    812     // The presence of upload event listeners forces us to use preflighting because POSTing to an URL that does not
    813     // permit cross origin requests should look exactly like POSTing to an URL that does not respond at all.
    814     // Also, only async requests support upload progress events.
    815     bool uploadEvents = false;
    816     if (m_async) {
    817         dispatchProgressEvent(EventTypeNames::loadstart, 0, 0);
    818         if (httpBody && m_upload) {
    819             uploadEvents = m_upload->hasEventListeners();
    820             m_upload->dispatchEvent(XMLHttpRequestProgressEvent::create(EventTypeNames::loadstart));
    821         }
    822     }
    823 
    824     m_sameOriginRequest = securityOrigin()->canRequest(m_url);
    825 
    826     // We also remember whether upload events should be allowed for this request in case the upload listeners are
    827     // added after the request is started.
    828     m_uploadEventsAllowed = m_sameOriginRequest || uploadEvents || !FetchUtils::isSimpleRequest(m_method, m_requestHeaders);
    829 
    830     ASSERT(executionContext());
    831     ExecutionContext& executionContext = *this->executionContext();
    832 
    833     ResourceRequest request(m_url);
    834     request.setHTTPMethod(m_method);
    835     request.setRequestContext(blink::WebURLRequest::RequestContextXMLHttpRequest);
    836 
    837     InspectorInstrumentation::willLoadXHR(&executionContext, this, this, m_method, m_url, m_async, httpBody ? httpBody->deepCopy() : nullptr, m_requestHeaders, m_includeCredentials);
    838 
    839     if (httpBody) {
    840         ASSERT(m_method != "GET");
    841         ASSERT(m_method != "HEAD");
    842         request.setHTTPBody(httpBody);
    843     }
    844 
    845     if (m_requestHeaders.size() > 0)
    846         request.addHTTPHeaderFields(m_requestHeaders);
    847 
    848     ThreadableLoaderOptions options;
    849     options.preflightPolicy = uploadEvents ? ForcePreflight : ConsiderPreflight;
    850     options.crossOriginRequestPolicy = UseAccessControl;
    851     options.initiator = FetchInitiatorTypeNames::xmlhttprequest;
    852     options.contentSecurityPolicyEnforcement = ContentSecurityPolicy::shouldBypassMainWorld(&executionContext) ? DoNotEnforceContentSecurityPolicy : EnforceConnectSrcDirective;
    853     options.timeoutMilliseconds = m_timeoutMilliseconds;
    854 
    855     ResourceLoaderOptions resourceLoaderOptions;
    856     resourceLoaderOptions.allowCredentials = (m_sameOriginRequest || m_includeCredentials) ? AllowStoredCredentials : DoNotAllowStoredCredentials;
    857     resourceLoaderOptions.credentialsRequested = m_includeCredentials ? ClientRequestedCredentials : ClientDidNotRequestCredentials;
    858     resourceLoaderOptions.securityOrigin = securityOrigin();
    859     resourceLoaderOptions.mixedContentBlockingTreatment = RuntimeEnabledFeatures::laxMixedContentCheckingEnabled() ? TreatAsPassiveContent : TreatAsActiveContent;
    860 
    861     // When responseType is set to "blob", we redirect the downloaded data to a
    862     // file-handle directly.
    863     m_downloadingToFile = responseTypeCode() == ResponseTypeBlob;
    864     if (m_downloadingToFile) {
    865         request.setDownloadToFile(true);
    866         resourceLoaderOptions.dataBufferingPolicy = DoNotBufferData;
    867     }
    868 
    869     m_exceptionCode = 0;
    870     m_error = false;
    871 
    872     if (m_async) {
    873         if (m_upload)
    874             request.setReportUploadProgress(true);
    875 
    876         // ThreadableLoader::create can return null here, for example if we're no longer attached to a page.
    877         // This is true while running onunload handlers.
    878         // FIXME: Maybe we need to be able to send XMLHttpRequests from onunload, <http://bugs.webkit.org/show_bug.cgi?id=10904>.
    879         // FIXME: Maybe create() can return null for other reasons too?
    880         ASSERT(!m_loader);
    881         m_loader = ThreadableLoader::create(executionContext, this, request, options, resourceLoaderOptions);
    882     } else {
    883         // Use count for XHR synchronous requests.
    884         UseCounter::count(&executionContext, UseCounter::XMLHttpRequestSynchronous);
    885         ThreadableLoader::loadResourceSynchronously(executionContext, request, *this, options, resourceLoaderOptions);
    886     }
    887 
    888     if (!m_exceptionCode && m_error)
    889         m_exceptionCode = NetworkError;
    890     if (m_exceptionCode)
    891         exceptionState.throwDOMException(m_exceptionCode, "Failed to load '" + m_url.elidedString() + "'.");
    892 }
    893 
    894 void XMLHttpRequest::abort()
    895 {
    896     WTF_LOG(Network, "XMLHttpRequest %p abort()", this);
    897 
    898     // internalAbort() clears |m_loader|. Compute |sendFlag| now.
    899     //
    900     // |sendFlag| corresponds to "the send() flag" defined in the XHR spec.
    901     //
    902     // |sendFlag| is only set when we have an active, asynchronous loader.
    903     // Don't use it as "the send() flag" when the XHR is in sync mode.
    904     bool sendFlag = m_loader;
    905 
    906     // internalAbort() clears the response. Save the data needed for
    907     // dispatching ProgressEvents.
    908     long long expectedLength = m_response.expectedContentLength();
    909     long long receivedLength = m_receivedLength;
    910 
    911     if (!internalAbort())
    912         return;
    913 
    914     // The script never gets any chance to call abort() on a sync XHR between
    915     // send() call and transition to the DONE state. It's because a sync XHR
    916     // doesn't dispatch any event between them. So, if |m_async| is false, we
    917     // can skip the "request error steps" (defined in the XHR spec) without any
    918     // state check.
    919     //
    920     // FIXME: It's possible open() is invoked in internalAbort() and |m_async|
    921     // becomes true by that. We should implement more reliable treatment for
    922     // nested method invocations at some point.
    923     if (m_async) {
    924         if ((m_state == OPENED && sendFlag) || m_state == HEADERS_RECEIVED || m_state == LOADING) {
    925             ASSERT(!m_loader);
    926             handleRequestError(0, EventTypeNames::abort, receivedLength, expectedLength);
    927         }
    928     }
    929     m_state = UNSENT;
    930 }
    931 
    932 void XMLHttpRequest::clearVariablesForLoading()
    933 {
    934     m_decoder.clear();
    935 
    936     if (m_responseDocumentParser) {
    937         m_responseDocumentParser->removeClient(this);
    938 #if !ENABLE(OILPAN)
    939         m_responseDocumentParser->detach();
    940 #endif
    941         m_responseDocumentParser = nullptr;
    942     }
    943 
    944     m_finalResponseCharset = String();
    945 }
    946 
    947 bool XMLHttpRequest::internalAbort()
    948 {
    949     m_error = true;
    950 
    951     if (m_responseDocumentParser && !m_responseDocumentParser->isStopped())
    952         m_responseDocumentParser->stopParsing();
    953 
    954     clearVariablesForLoading();
    955 
    956     InspectorInstrumentation::didFailXHRLoading(executionContext(), this, this);
    957 
    958     if (m_responseLegacyStream && m_state != DONE)
    959         m_responseLegacyStream->abort();
    960 
    961     if (m_responseStream) {
    962         // When the stream is already closed (including canceled from the
    963         // user), |error| does nothing.
    964         // FIXME: Create a more specific error.
    965         m_responseStream->error(DOMException::create(!m_async && m_exceptionCode ? m_exceptionCode : AbortError, "XMLHttpRequest::abort"));
    966     }
    967 
    968     clearResponse();
    969     clearRequest();
    970 
    971     if (!m_loader)
    972         return true;
    973 
    974     // Cancelling the ThreadableLoader m_loader may result in calling
    975     // window.onload synchronously. If such an onload handler contains open()
    976     // call on the same XMLHttpRequest object, reentry happens.
    977     //
    978     // If, window.onload contains open() and send(), m_loader will be set to
    979     // non 0 value. So, we cannot continue the outer open(). In such case,
    980     // just abort the outer open() by returning false.
    981     RefPtr<ThreadableLoader> loader = m_loader.release();
    982     loader->cancel();
    983 
    984     // If abort() called internalAbort() and a nested open() ended up
    985     // clearing the error flag, but didn't send(), make sure the error
    986     // flag is still set.
    987     bool newLoadStarted = hasPendingActivity();
    988     if (!newLoadStarted)
    989         m_error = true;
    990 
    991     return !newLoadStarted;
    992 }
    993 
    994 void XMLHttpRequest::clearResponse()
    995 {
    996     // FIXME: when we add the support for multi-part XHR, we will have to
    997     // be careful with this initialization.
    998     m_receivedLength = 0;
    999 
   1000     m_response = ResourceResponse();
   1001 
   1002     m_responseText.clear();
   1003 
   1004     m_parsedResponse = false;
   1005     m_responseDocument = nullptr;
   1006 
   1007     m_responseBlob = nullptr;
   1008 
   1009     m_downloadingToFile = false;
   1010     m_lengthDownloadedToFile = 0;
   1011 
   1012     m_responseLegacyStream = nullptr;
   1013     m_responseStream = nullptr;
   1014 
   1015     // These variables may referred by the response accessors. So, we can clear
   1016     // this only when we clear the response holder variables above.
   1017     m_binaryResponseBuilder.clear();
   1018     m_responseArrayBuffer.clear();
   1019 }
   1020 
   1021 void XMLHttpRequest::clearRequest()
   1022 {
   1023     m_requestHeaders.clear();
   1024 }
   1025 
   1026 void XMLHttpRequest::dispatchProgressEvent(const AtomicString& type, long long receivedLength, long long expectedLength)
   1027 {
   1028     bool lengthComputable = expectedLength > 0 && receivedLength <= expectedLength;
   1029     unsigned long long loaded = receivedLength >= 0 ? static_cast<unsigned long long>(receivedLength) : 0;
   1030     unsigned long long total = lengthComputable ? static_cast<unsigned long long>(expectedLength) : 0;
   1031 
   1032     m_progressEventThrottle.dispatchProgressEvent(type, lengthComputable, loaded, total);
   1033 
   1034     if (type == EventTypeNames::loadend)
   1035         InspectorInstrumentation::didDispatchXHRLoadendEvent(executionContext(), this);
   1036 }
   1037 
   1038 void XMLHttpRequest::dispatchProgressEventFromSnapshot(const AtomicString& type)
   1039 {
   1040     dispatchProgressEvent(type, m_receivedLength, m_response.expectedContentLength());
   1041 }
   1042 
   1043 void XMLHttpRequest::handleNetworkError()
   1044 {
   1045     WTF_LOG(Network, "XMLHttpRequest %p handleNetworkError()", this);
   1046 
   1047     // Response is cleared next, save needed progress event data.
   1048     long long expectedLength = m_response.expectedContentLength();
   1049     long long receivedLength = m_receivedLength;
   1050 
   1051     // Prevent the XMLHttpRequest instance from being destoryed during
   1052     // |internalAbort()|.
   1053     RefPtrWillBeRawPtr<XMLHttpRequest> protect(this);
   1054 
   1055     if (!internalAbort())
   1056         return;
   1057 
   1058     handleRequestError(NetworkError, EventTypeNames::error, receivedLength, expectedLength);
   1059 }
   1060 
   1061 void XMLHttpRequest::handleDidCancel()
   1062 {
   1063     WTF_LOG(Network, "XMLHttpRequest %p handleDidCancel()", this);
   1064 
   1065     // Response is cleared next, save needed progress event data.
   1066     long long expectedLength = m_response.expectedContentLength();
   1067     long long receivedLength = m_receivedLength;
   1068 
   1069     // Prevent the XMLHttpRequest instance from being destoryed during
   1070     // |internalAbort()|.
   1071     RefPtrWillBeRawPtr<XMLHttpRequest> protect(this);
   1072 
   1073     if (!internalAbort())
   1074         return;
   1075 
   1076     handleRequestError(AbortError, EventTypeNames::abort, receivedLength, expectedLength);
   1077 }
   1078 
   1079 void XMLHttpRequest::handleRequestError(ExceptionCode exceptionCode, const AtomicString& type, long long receivedLength, long long expectedLength)
   1080 {
   1081     WTF_LOG(Network, "XMLHttpRequest %p handleRequestError()", this);
   1082 
   1083     // The request error steps for event 'type' and exception 'exceptionCode'.
   1084 
   1085     if (!m_async && exceptionCode) {
   1086         m_state = DONE;
   1087         m_exceptionCode = exceptionCode;
   1088         return;
   1089     }
   1090     // With m_error set, the state change steps are minimal: any pending
   1091     // progress event is flushed + a readystatechange is dispatched.
   1092     // No new progress events dispatched; as required, that happens at
   1093     // the end here.
   1094     ASSERT(m_error);
   1095     changeState(DONE);
   1096 
   1097     if (!m_uploadComplete) {
   1098         m_uploadComplete = true;
   1099         if (m_upload && m_uploadEventsAllowed)
   1100             m_upload->handleRequestError(type);
   1101     }
   1102 
   1103     // Note: The below event dispatch may be called while |hasPendingActivity() == false|,
   1104     // when |handleRequestError| is called after |internalAbort()|.
   1105     // This is safe, however, as |this| will be kept alive from a strong ref |Event::m_target|.
   1106     dispatchProgressEvent(EventTypeNames::progress, receivedLength, expectedLength);
   1107     dispatchProgressEvent(type, receivedLength, expectedLength);
   1108     dispatchProgressEvent(EventTypeNames::loadend, receivedLength, expectedLength);
   1109 }
   1110 
   1111 void XMLHttpRequest::overrideMimeType(const AtomicString& mimeType, ExceptionState& exceptionState)
   1112 {
   1113     if (m_state == LOADING || m_state == DONE) {
   1114         exceptionState.throwDOMException(InvalidStateError, "MimeType cannot be overridden when the state is LOADING or DONE.");
   1115         return;
   1116     }
   1117 
   1118     m_mimeTypeOverride = mimeType;
   1119 }
   1120 
   1121 void XMLHttpRequest::setRequestHeader(const AtomicString& name, const AtomicString& value, ExceptionState& exceptionState)
   1122 {
   1123     if (m_state != OPENED || m_loader) {
   1124         exceptionState.throwDOMException(InvalidStateError, "The object's state must be OPENED.");
   1125         return;
   1126     }
   1127 
   1128     if (!isValidHTTPToken(name)) {
   1129         exceptionState.throwDOMException(SyntaxError, "'" + name + "' is not a valid HTTP header field name.");
   1130         return;
   1131     }
   1132 
   1133     if (!isValidHTTPHeaderValue(value)) {
   1134         exceptionState.throwDOMException(SyntaxError, "'" + value + "' is not a valid HTTP header field value.");
   1135         return;
   1136     }
   1137 
   1138     // No script (privileged or not) can set unsafe headers.
   1139     if (FetchUtils::isForbiddenHeaderName(name)) {
   1140         logConsoleError(executionContext(), "Refused to set unsafe header \"" + name + "\"");
   1141         return;
   1142     }
   1143 
   1144     setRequestHeaderInternal(name, value);
   1145 }
   1146 
   1147 void XMLHttpRequest::setRequestHeaderInternal(const AtomicString& name, const AtomicString& value)
   1148 {
   1149     HTTPHeaderMap::AddResult result = m_requestHeaders.add(name, value);
   1150     if (!result.isNewEntry)
   1151         result.storedValue->value = result.storedValue->value + ", " + value;
   1152 }
   1153 
   1154 const AtomicString& XMLHttpRequest::getRequestHeader(const AtomicString& name) const
   1155 {
   1156     return m_requestHeaders.get(name);
   1157 }
   1158 
   1159 String XMLHttpRequest::getAllResponseHeaders() const
   1160 {
   1161     if (m_state < HEADERS_RECEIVED || m_error)
   1162         return "";
   1163 
   1164     StringBuilder stringBuilder;
   1165 
   1166     HTTPHeaderSet accessControlExposeHeaderSet;
   1167     parseAccessControlExposeHeadersAllowList(m_response.httpHeaderField("Access-Control-Expose-Headers"), accessControlExposeHeaderSet);
   1168     HTTPHeaderMap::const_iterator end = m_response.httpHeaderFields().end();
   1169     for (HTTPHeaderMap::const_iterator it = m_response.httpHeaderFields().begin(); it!= end; ++it) {
   1170         // Hide Set-Cookie header fields from the XMLHttpRequest client for these reasons:
   1171         //     1) If the client did have access to the fields, then it could read HTTP-only
   1172         //        cookies; those cookies are supposed to be hidden from scripts.
   1173         //     2) There's no known harm in hiding Set-Cookie header fields entirely; we don't
   1174         //        know any widely used technique that requires access to them.
   1175         //     3) Firefox has implemented this policy.
   1176         if (isSetCookieHeader(it->key) && !securityOrigin()->canLoadLocalResources())
   1177             continue;
   1178 
   1179         if (!m_sameOriginRequest && !isOnAccessControlResponseHeaderWhitelist(it->key) && !accessControlExposeHeaderSet.contains(it->key))
   1180             continue;
   1181 
   1182         stringBuilder.append(it->key);
   1183         stringBuilder.append(':');
   1184         stringBuilder.append(' ');
   1185         stringBuilder.append(it->value);
   1186         stringBuilder.append('\r');
   1187         stringBuilder.append('\n');
   1188     }
   1189 
   1190     return stringBuilder.toString();
   1191 }
   1192 
   1193 const AtomicString& XMLHttpRequest::getResponseHeader(const AtomicString& name) const
   1194 {
   1195     if (m_state < HEADERS_RECEIVED || m_error)
   1196         return nullAtom;
   1197 
   1198     // See comment in getAllResponseHeaders above.
   1199     if (isSetCookieHeader(name) && !securityOrigin()->canLoadLocalResources()) {
   1200         logConsoleError(executionContext(), "Refused to get unsafe header \"" + name + "\"");
   1201         return nullAtom;
   1202     }
   1203 
   1204     HTTPHeaderSet accessControlExposeHeaderSet;
   1205     parseAccessControlExposeHeadersAllowList(m_response.httpHeaderField("Access-Control-Expose-Headers"), accessControlExposeHeaderSet);
   1206 
   1207     if (!m_sameOriginRequest && !isOnAccessControlResponseHeaderWhitelist(name) && !accessControlExposeHeaderSet.contains(name)) {
   1208         logConsoleError(executionContext(), "Refused to get unsafe header \"" + name + "\"");
   1209         return nullAtom;
   1210     }
   1211     return m_response.httpHeaderField(name);
   1212 }
   1213 
   1214 AtomicString XMLHttpRequest::finalResponseMIMEType() const
   1215 {
   1216     AtomicString overriddenType = extractMIMETypeFromMediaType(m_mimeTypeOverride);
   1217     if (!overriddenType.isEmpty())
   1218         return overriddenType;
   1219 
   1220     if (m_response.isHTTP())
   1221         return extractMIMETypeFromMediaType(m_response.httpHeaderField("Content-Type"));
   1222 
   1223     return m_response.mimeType();
   1224 }
   1225 
   1226 AtomicString XMLHttpRequest::finalResponseMIMETypeWithFallback() const
   1227 {
   1228     AtomicString finalType = finalResponseMIMEType();
   1229     if (!finalType.isEmpty())
   1230         return finalType;
   1231 
   1232     // FIXME: This fallback is not specified in the final MIME type algorithm
   1233     // of the XHR spec. Move this to more appropriate place.
   1234     return AtomicString("text/xml", AtomicString::ConstructFromLiteral);
   1235 }
   1236 
   1237 bool XMLHttpRequest::responseIsXML() const
   1238 {
   1239     return DOMImplementation::isXMLMIMEType(finalResponseMIMETypeWithFallback());
   1240 }
   1241 
   1242 bool XMLHttpRequest::responseIsHTML() const
   1243 {
   1244     return equalIgnoringCase(finalResponseMIMEType(), "text/html");
   1245 }
   1246 
   1247 int XMLHttpRequest::status() const
   1248 {
   1249     if (m_state == UNSENT || m_state == OPENED || m_error)
   1250         return 0;
   1251 
   1252     if (m_response.httpStatusCode())
   1253         return m_response.httpStatusCode();
   1254 
   1255     return 0;
   1256 }
   1257 
   1258 String XMLHttpRequest::statusText() const
   1259 {
   1260     if (m_state == UNSENT || m_state == OPENED || m_error)
   1261         return String();
   1262 
   1263     if (!m_response.httpStatusText().isNull())
   1264         return m_response.httpStatusText();
   1265 
   1266     return String();
   1267 }
   1268 
   1269 void XMLHttpRequest::didFail(const ResourceError& error)
   1270 {
   1271     WTF_LOG(Network, "XMLHttpRequest %p didFail()", this);
   1272 
   1273     // If we are already in an error state, for instance we called abort(), bail out early.
   1274     if (m_error)
   1275         return;
   1276 
   1277     if (error.isCancellation()) {
   1278         handleDidCancel();
   1279         // Now the XMLHttpRequest instance may be dead.
   1280         return;
   1281     }
   1282 
   1283     if (error.isTimeout()) {
   1284         handleDidTimeout();
   1285         // Now the XMLHttpRequest instance may be dead.
   1286         return;
   1287     }
   1288 
   1289     // Network failures are already reported to Web Inspector by ResourceLoader.
   1290     if (error.domain() == errorDomainBlinkInternal)
   1291         logConsoleError(executionContext(), "XMLHttpRequest cannot load " + error.failingURL() + ". " + error.localizedDescription());
   1292 
   1293     handleNetworkError();
   1294     // Now the XMLHttpRequest instance may be dead.
   1295 }
   1296 
   1297 void XMLHttpRequest::didFailRedirectCheck()
   1298 {
   1299     WTF_LOG(Network, "XMLHttpRequest %p didFailRedirectCheck()", this);
   1300 
   1301     handleNetworkError();
   1302     // Now the XMLHttpRequest instance may be dead.
   1303 }
   1304 
   1305 void XMLHttpRequest::didFinishLoading(unsigned long identifier, double)
   1306 {
   1307     WTF_LOG(Network, "XMLHttpRequest %p didFinishLoading(%lu)", this, identifier);
   1308 
   1309     if (m_error)
   1310         return;
   1311 
   1312     if (m_state < HEADERS_RECEIVED)
   1313         changeState(HEADERS_RECEIVED);
   1314 
   1315     m_loaderIdentifier = identifier;
   1316 
   1317     if (m_responseDocumentParser) {
   1318         // |DocumentParser::finish()| tells the parser that we have reached end of the data.
   1319         // When using |HTMLDocumentParser|, which works asynchronously, we do not have the
   1320         // complete document just after the |DocumentParser::finish()| call.
   1321         // Wait for the parser to call us back in |notifyParserStopped| to progress state.
   1322         m_responseDocumentParser->finish();
   1323         ASSERT(m_responseDocument);
   1324         return;
   1325     }
   1326 
   1327     if (m_decoder)
   1328         m_responseText = m_responseText.concatenateWith(m_decoder->flush());
   1329 
   1330     if (m_responseLegacyStream)
   1331         m_responseLegacyStream->finalize();
   1332 
   1333     if (m_responseStream)
   1334         m_responseStream->close();
   1335 
   1336     clearVariablesForLoading();
   1337     endLoading();
   1338 }
   1339 
   1340 void XMLHttpRequest::notifyParserStopped()
   1341 {
   1342     // This should only be called when response document is parsed asynchronously.
   1343     ASSERT(m_responseDocumentParser);
   1344     ASSERT(!m_responseDocumentParser->isParsing());
   1345     ASSERT(!m_responseLegacyStream);
   1346     ASSERT(!m_responseStream);
   1347 
   1348     // Do nothing if we are called from |internalAbort()|.
   1349     if (m_error)
   1350         return;
   1351 
   1352     clearVariablesForLoading();
   1353 
   1354     m_responseDocument->implicitClose();
   1355 
   1356     if (!m_responseDocument->wellFormed())
   1357         m_responseDocument = nullptr;
   1358 
   1359     m_parsedResponse = true;
   1360 
   1361     endLoading();
   1362 }
   1363 
   1364 void XMLHttpRequest::endLoading()
   1365 {
   1366     InspectorInstrumentation::didFinishXHRLoading(executionContext(), this, this, m_loaderIdentifier, m_responseText, m_method, m_url, m_lastSendURL, m_lastSendLineNumber);
   1367 
   1368     if (m_loader)
   1369         m_loader = nullptr;
   1370     m_loaderIdentifier = 0;
   1371 
   1372     changeState(DONE);
   1373 }
   1374 
   1375 void XMLHttpRequest::didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
   1376 {
   1377     WTF_LOG(Network, "XMLHttpRequest %p didSendData(%llu, %llu)", this, bytesSent, totalBytesToBeSent);
   1378 
   1379     if (!m_upload)
   1380         return;
   1381 
   1382     if (m_uploadEventsAllowed)
   1383         m_upload->dispatchProgressEvent(bytesSent, totalBytesToBeSent);
   1384 
   1385     if (bytesSent == totalBytesToBeSent && !m_uploadComplete) {
   1386         m_uploadComplete = true;
   1387         if (m_uploadEventsAllowed)
   1388             m_upload->dispatchEventAndLoadEnd(EventTypeNames::load, true, bytesSent, totalBytesToBeSent);
   1389     }
   1390 }
   1391 
   1392 void XMLHttpRequest::didReceiveResponse(unsigned long identifier, const ResourceResponse& response)
   1393 {
   1394     WTF_LOG(Network, "XMLHttpRequest %p didReceiveResponse(%lu)", this, identifier);
   1395 
   1396     m_response = response;
   1397     if (!m_mimeTypeOverride.isEmpty()) {
   1398         m_response.setHTTPHeaderField("Content-Type", m_mimeTypeOverride);
   1399         m_finalResponseCharset = extractCharsetFromMediaType(m_mimeTypeOverride);
   1400     }
   1401 
   1402     if (m_finalResponseCharset.isEmpty())
   1403         m_finalResponseCharset = response.textEncodingName();
   1404 }
   1405 
   1406 void XMLHttpRequest::parseDocumentChunk(const char* data, int len)
   1407 {
   1408     if (!m_responseDocumentParser) {
   1409         ASSERT(!m_responseDocument);
   1410         initResponseDocument();
   1411         if (!m_responseDocument)
   1412             return;
   1413 
   1414         m_responseDocumentParser = m_responseDocument->implicitOpen();
   1415         m_responseDocumentParser->addClient(this);
   1416     }
   1417     ASSERT(m_responseDocumentParser);
   1418 
   1419     if (m_responseDocumentParser->needsDecoder())
   1420         m_responseDocumentParser->setDecoder(createDecoder());
   1421 
   1422     m_responseDocumentParser->appendBytes(data, len);
   1423 }
   1424 
   1425 PassOwnPtr<TextResourceDecoder> XMLHttpRequest::createDecoder() const
   1426 {
   1427     if (m_responseTypeCode == ResponseTypeJSON)
   1428         return TextResourceDecoder::create("application/json", "UTF-8");
   1429 
   1430     if (!m_finalResponseCharset.isEmpty())
   1431         return TextResourceDecoder::create("text/plain", m_finalResponseCharset);
   1432 
   1433     // allow TextResourceDecoder to look inside the m_response if it's XML or HTML
   1434     if (responseIsXML()) {
   1435         OwnPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("application/xml");
   1436         // Don't stop on encoding errors, unlike it is done for other kinds
   1437         // of XML resources. This matches the behavior of previous WebKit
   1438         // versions, Firefox and Opera.
   1439         decoder->useLenientXMLDecoding();
   1440 
   1441         return decoder.release();
   1442     }
   1443 
   1444     if (responseIsHTML())
   1445         return TextResourceDecoder::create("text/html", "UTF-8");
   1446 
   1447     return TextResourceDecoder::create("text/plain", "UTF-8");
   1448 }
   1449 
   1450 void XMLHttpRequest::didReceiveData(const char* data, int len)
   1451 {
   1452     ASSERT(!m_downloadingToFile);
   1453 
   1454     if (m_error)
   1455         return;
   1456 
   1457     if (m_state < HEADERS_RECEIVED)
   1458         changeState(HEADERS_RECEIVED);
   1459 
   1460     // We need to check for |m_error| again, because |changeState| may trigger
   1461     // readystatechange, and user javascript can cause |abort()|.
   1462     if (m_error)
   1463         return;
   1464 
   1465     if (!len)
   1466         return;
   1467 
   1468     if (len == -1)
   1469         len = strlen(data);
   1470 
   1471     if (m_responseTypeCode == ResponseTypeDocument && responseIsHTML()) {
   1472         parseDocumentChunk(data, len);
   1473     } else if (m_responseTypeCode == ResponseTypeDefault || m_responseTypeCode == ResponseTypeText || m_responseTypeCode == ResponseTypeJSON || m_responseTypeCode == ResponseTypeDocument) {
   1474         if (!m_decoder)
   1475             m_decoder = createDecoder();
   1476 
   1477         m_responseText = m_responseText.concatenateWith(m_decoder->decode(data, len));
   1478     } else if (m_responseTypeCode == ResponseTypeArrayBuffer || m_responseTypeCode == ResponseTypeBlob) {
   1479         // Buffer binary data.
   1480         if (!m_binaryResponseBuilder)
   1481             m_binaryResponseBuilder = SharedBuffer::create();
   1482         m_binaryResponseBuilder->append(data, len);
   1483     } else if (m_responseTypeCode == ResponseTypeLegacyStream) {
   1484         if (!m_responseLegacyStream)
   1485             m_responseLegacyStream = Stream::create(executionContext(), responseType());
   1486         m_responseLegacyStream->addData(data, len);
   1487     } else if (m_responseTypeCode == ResponseTypeStream) {
   1488         if (!m_responseStream) {
   1489             m_responseStream = new ReadableStreamImpl<ReadableStreamChunkTypeTraits<ArrayBuffer> >(executionContext(), new ReadableStreamSource(this));
   1490             m_responseStream->didSourceStart();
   1491         }
   1492         m_responseStream->enqueue(ArrayBuffer::create(data, len));
   1493     }
   1494 
   1495     trackProgress(len);
   1496 }
   1497 
   1498 void XMLHttpRequest::didDownloadData(int dataLength)
   1499 {
   1500     if (m_error)
   1501         return;
   1502 
   1503     ASSERT(m_downloadingToFile);
   1504 
   1505     if (m_state < HEADERS_RECEIVED)
   1506         changeState(HEADERS_RECEIVED);
   1507 
   1508     if (!dataLength)
   1509         return;
   1510 
   1511     // readystatechange event handler may do something to put this XHR in error
   1512     // state. We need to check m_error again here.
   1513     if (m_error)
   1514         return;
   1515 
   1516     m_lengthDownloadedToFile += dataLength;
   1517 
   1518     trackProgress(dataLength);
   1519 }
   1520 
   1521 void XMLHttpRequest::handleDidTimeout()
   1522 {
   1523     WTF_LOG(Network, "XMLHttpRequest %p handleDidTimeout()", this);
   1524 
   1525     // Response is cleared next, save needed progress event data.
   1526     long long expectedLength = m_response.expectedContentLength();
   1527     long long receivedLength = m_receivedLength;
   1528 
   1529     // Prevent the XMLHttpRequest instance from being destoryed during
   1530     // |internalAbort()|.
   1531     RefPtrWillBeRawPtr<XMLHttpRequest> protect(this);
   1532 
   1533     if (!internalAbort())
   1534         return;
   1535 
   1536     handleRequestError(TimeoutError, EventTypeNames::timeout, receivedLength, expectedLength);
   1537 }
   1538 
   1539 void XMLHttpRequest::suspend()
   1540 {
   1541     m_progressEventThrottle.suspend();
   1542 }
   1543 
   1544 void XMLHttpRequest::resume()
   1545 {
   1546     m_progressEventThrottle.resume();
   1547 }
   1548 
   1549 void XMLHttpRequest::stop()
   1550 {
   1551     internalAbort();
   1552 }
   1553 
   1554 bool XMLHttpRequest::hasPendingActivity() const
   1555 {
   1556     // Neither this object nor the JavaScript wrapper should be deleted while
   1557     // a request is in progress because we need to keep the listeners alive,
   1558     // and they are referenced by the JavaScript wrapper.
   1559     // |m_loader| is non-null while request is active and ThreadableLoaderClient
   1560     // callbacks may be called, and |m_responseDocumentParser| is non-null while
   1561     // DocumentParserClient callbacks may be called.
   1562     return m_loader || m_responseDocumentParser;
   1563 }
   1564 
   1565 void XMLHttpRequest::contextDestroyed()
   1566 {
   1567     ASSERT(!m_loader);
   1568     ActiveDOMObject::contextDestroyed();
   1569 }
   1570 
   1571 const AtomicString& XMLHttpRequest::interfaceName() const
   1572 {
   1573     return EventTargetNames::XMLHttpRequest;
   1574 }
   1575 
   1576 ExecutionContext* XMLHttpRequest::executionContext() const
   1577 {
   1578     return ActiveDOMObject::executionContext();
   1579 }
   1580 
   1581 void XMLHttpRequest::trace(Visitor* visitor)
   1582 {
   1583     visitor->trace(m_responseBlob);
   1584     visitor->trace(m_responseLegacyStream);
   1585     visitor->trace(m_responseStream);
   1586     visitor->trace(m_streamSource);
   1587     visitor->trace(m_responseDocument);
   1588     visitor->trace(m_responseDocumentParser);
   1589     visitor->trace(m_progressEventThrottle);
   1590     visitor->trace(m_upload);
   1591     XMLHttpRequestEventTarget::trace(visitor);
   1592 }
   1593 
   1594 } // namespace blink
   1595