summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/WebKit/Source/core/xml/XMLHttpRequest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/WebKit/Source/core/xml/XMLHttpRequest.cpp')
-rw-r--r--chromium/third_party/WebKit/Source/core/xml/XMLHttpRequest.cpp286
1 files changed, 166 insertions, 120 deletions
diff --git a/chromium/third_party/WebKit/Source/core/xml/XMLHttpRequest.cpp b/chromium/third_party/WebKit/Source/core/xml/XMLHttpRequest.cpp
index e89de304925..77fba6242f3 100644
--- a/chromium/third_party/WebKit/Source/core/xml/XMLHttpRequest.cpp
+++ b/chromium/third_party/WebKit/Source/core/xml/XMLHttpRequest.cpp
@@ -23,28 +23,31 @@
#include "config.h"
#include "core/xml/XMLHttpRequest.h"
-#include "FetchInitiatorTypeNames.h"
-#include "RuntimeEnabledFeatures.h"
#include "bindings/v8/ExceptionState.h"
+#include "core/FetchInitiatorTypeNames.h"
#include "core/dom/ContextFeatures.h"
#include "core/dom/DOMImplementation.h"
#include "core/dom/ExceptionCode.h"
+#include "core/dom/XMLDocument.h"
#include "core/editing/markup.h"
#include "core/events/Event.h"
#include "core/fetch/CrossOriginAccessControl.h"
-#include "core/fetch/TextResourceDecoder.h"
#include "core/fileapi/Blob.h"
#include "core/fileapi/File.h"
#include "core/fileapi/Stream.h"
-#include "core/frame/ContentSecurityPolicy.h"
+#include "core/frame/Settings.h"
+#include "core/frame/UseCounter.h"
+#include "core/frame/csp/ContentSecurityPolicy.h"
#include "core/html/DOMFormData.h"
#include "core/html/HTMLDocument.h"
+#include "core/html/parser/TextResourceDecoder.h"
#include "core/inspector/InspectorInstrumentation.h"
+#include "core/inspector/InspectorTraceEvents.h"
#include "core/loader/ThreadableLoader.h"
-#include "core/frame/Settings.h"
#include "core/xml/XMLHttpRequestProgressEvent.h"
#include "core/xml/XMLHttpRequestUpload.h"
#include "platform/Logging.h"
+#include "platform/RuntimeEnabledFeatures.h"
#include "platform/SharedBuffer.h"
#include "platform/blob/BlobData.h"
#include "platform/network/HTTPParsers.h"
@@ -54,6 +57,7 @@
#include "public/platform/Platform.h"
#include "wtf/ArrayBuffer.h"
#include "wtf/ArrayBufferView.h"
+#include "wtf/Assertions.h"
#include "wtf/RefCountedLeakCounter.h"
#include "wtf/StdLibExtras.h"
#include "wtf/text/CString.h"
@@ -112,7 +116,7 @@ static bool isSetCookieHeader(const AtomicString& name)
static void replaceCharsetInMediaType(String& mediaType, const String& charsetValue)
{
- unsigned int pos = 0, len = 0;
+ unsigned pos = 0, len = 0;
findCharsetInMediaType(mediaType, pos, len);
@@ -124,7 +128,7 @@ static void replaceCharsetInMediaType(String& mediaType, const String& charsetVa
// Found at least one existing charset, replace all occurrences with new charset.
while (len) {
mediaType.replace(pos, len, charsetValue);
- unsigned int start = pos + charsetValue.length();
+ unsigned start = pos + charsetValue.length();
findCharsetInMediaType(mediaType, pos, len, start);
}
}
@@ -153,9 +157,9 @@ static void logConsoleError(ExecutionContext* context, const String& message)
context->addConsoleMessage(JSMessageSource, ErrorMessageLevel, message);
}
-PassRefPtr<XMLHttpRequest> XMLHttpRequest::create(ExecutionContext* context, PassRefPtr<SecurityOrigin> securityOrigin)
+PassRefPtrWillBeRawPtr<XMLHttpRequest> XMLHttpRequest::create(ExecutionContext* context, PassRefPtr<SecurityOrigin> securityOrigin)
{
- RefPtr<XMLHttpRequest> xmlHttpRequest(adoptRef(new XMLHttpRequest(context, securityOrigin)));
+ RefPtrWillBeRawPtr<XMLHttpRequest> xmlHttpRequest = adoptRefWillBeRefCountedGarbageCollected(new XMLHttpRequest(context, securityOrigin));
xmlHttpRequest->suspendIfNeeded();
return xmlHttpRequest.release();
@@ -242,26 +246,28 @@ Document* XMLHttpRequest::responseXML(ExceptionState& exceptionState)
return 0;
if (!m_createdDocument) {
- bool isHTML = equalIgnoringCase(responseMIMEType(), "text/html");
+ AtomicString mimeType = responseMIMEType();
+ bool isHTML = equalIgnoringCase(mimeType, "text/html");
// 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.
if ((m_response.isHTTP() && !responseIsXML() && !isHTML)
|| (isHTML && m_responseTypeCode == ResponseTypeDefault)
|| executionContext()->isWorkerGlobalScope()) {
- m_responseDocument = 0;
+ m_responseDocument = nullptr;
} else {
DocumentInit init = DocumentInit::fromContext(document()->contextDocument(), m_url);
if (isHTML)
m_responseDocument = HTMLDocument::create(init);
else
- m_responseDocument = Document::create(init);
+ m_responseDocument = XMLDocument::create(init);
// FIXME: Set Last-Modified.
m_responseDocument->setContent(m_responseText.flattenToString());
m_responseDocument->setSecurityOrigin(securityOrigin());
m_responseDocument->setContextFeatures(document()->contextFeatures());
+ m_responseDocument->setMimeType(mimeType);
if (!m_responseDocument->wellFormed())
- m_responseDocument = 0;
+ m_responseDocument = nullptr;
}
m_createdDocument = true;
}
@@ -279,14 +285,14 @@ Blob* XMLHttpRequest::responseBlob()
return 0;
if (!m_responseBlob) {
- // When "blob" is specified for the responseType attribute,
- // 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.
+ // 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.
OwnPtr<BlobData> blobData = BlobData::create();
String filePath = m_response.downloadedFilePath();
- // If we errored out or got no data, we still return a blob, just an empty one.
+ // If we errored out or got no data, we still return a blob, just an
+ // empty one.
if (!filePath.isEmpty() && m_downloadedBlobLength) {
blobData->appendFile(filePath);
blobData->setContentType(responseMIMEType()); // responseMIMEType defaults to text/xml which may be incorrect.
@@ -307,6 +313,12 @@ ArrayBuffer* XMLHttpRequest::responseArrayBuffer()
if (!m_responseArrayBuffer.get()) {
if (m_binaryResponseBuilder.get() && m_binaryResponseBuilder->size() > 0) {
m_responseArrayBuffer = m_binaryResponseBuilder->getAsArrayBuffer();
+ if (!m_responseArrayBuffer) {
+ // 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_binaryResponseBuilder.clear();
} else {
m_responseArrayBuffer = ArrayBuffer::create(static_cast<void*>(0), 0);
@@ -346,9 +358,7 @@ void XMLHttpRequest::setResponseType(const String& responseType, ExceptionState&
// 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.
- // We'll only disable this functionality for HTTP(S) requests since sync requests for local protocols
- // such as file: and data: still make sense to allow.
- if (!m_async && executionContext()->isDocument() && m_url.protocolIsInHTTPFamily()) {
+ if (!m_async && executionContext()->isDocument()) {
exceptionState.throwDOMException(InvalidAccessError, "The response type can only be changed for asynchronous HTTP requests made from a document.");
return;
}
@@ -396,6 +406,11 @@ String XMLHttpRequest::responseType()
return "";
}
+String XMLHttpRequest::responseURL()
+{
+ return m_response.url().string();
+}
+
XMLHttpRequestUpload* XMLHttpRequest::upload()
{
if (!m_upload)
@@ -408,7 +423,7 @@ void XMLHttpRequest::trackProgress(int length)
m_receivedLength += length;
if (m_async)
- dispatchThrottledProgressEventSnapshot(EventTypeNames::progress);
+ dispatchProgressEventFromSnapshot(EventTypeNames::progress);
if (m_state != LOADING) {
changeState(LOADING);
@@ -438,6 +453,8 @@ void XMLHttpRequest::dispatchReadyStateChangeEvent()
InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchXHRReadyStateChangeEvent(executionContext(), this);
if (m_async || (m_state <= OPENED || m_state == DONE)) {
+ TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "XHRReadyStateChange", "data", InspectorXhrReadyStateChangeEvent::data(executionContext(), this));
+ TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack());
ProgressEventAction flushAction = DoNotFlushProgressEvent;
if (m_state == DONE) {
if (m_error)
@@ -446,14 +463,20 @@ void XMLHttpRequest::dispatchReadyStateChangeEvent()
flushAction = FlushProgressEvent;
}
m_progressEventThrottle.dispatchReadyStateChangeEvent(XMLHttpRequestProgressEvent::create(EventTypeNames::readystatechange), flushAction);
+ TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", "data", InspectorUpdateCountersEvent::data());
}
InspectorInstrumentation::didDispatchXHRReadyStateChangeEvent(cookie);
if (m_state == DONE && !m_error) {
- InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchXHRLoadEvent(executionContext(), this);
- dispatchThrottledProgressEventSnapshot(EventTypeNames::load);
- InspectorInstrumentation::didDispatchXHRLoadEvent(cookie);
- dispatchThrottledProgressEventSnapshot(EventTypeNames::loadend);
+ {
+ TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "XHRLoad", "data", InspectorXhrLoadEvent::data(executionContext(), this));
+ TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack());
+ InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchXHRLoadEvent(executionContext(), this);
+ dispatchProgressEventFromSnapshot(EventTypeNames::load);
+ InspectorInstrumentation::didDispatchXHRLoadEvent(cookie);
+ }
+ dispatchProgressEventFromSnapshot(EventTypeNames::loadend);
+ TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", "data", InspectorUpdateCountersEvent::data());
}
}
@@ -464,6 +487,11 @@ void XMLHttpRequest::setWithCredentials(bool value, ExceptionState& exceptionSta
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)
+ UseCounter::countDeprecation(executionContext(), UseCounter::SyncXHRWithCredentials);
+
m_includeCredentials = value;
}
@@ -517,7 +545,7 @@ void XMLHttpRequest::open(const AtomicString& method, const KURL& url, Exception
void XMLHttpRequest::open(const AtomicString& method, const KURL& url, bool async, ExceptionState& exceptionState)
{
- WTF_LOG(Network, "XMLHttpRequest %p open('%s', '%s', %d)", this, method.string().utf8().data(), url.elidedString().utf8().data(), async);
+ WTF_LOG(Network, "XMLHttpRequest %p open('%s', '%s', %d)", this, method.utf8().data(), url.elidedString().utf8().data(), async);
if (!internalAbort())
return;
@@ -557,10 +585,8 @@ void XMLHttpRequest::open(const AtomicString& method, const KURL& url, bool asyn
// 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.
- // We'll only disable this functionality for HTTP(S) requests since sync requests for local protocols
- // such as file: and data: still make sense to allow.
- if (url.protocolIsInHTTPFamily() && m_responseTypeCode != ResponseTypeDefault) {
- exceptionState.throwDOMException(InvalidAccessError, "Synchronous HTTP requests from a document must not set a response type.");
+ if (m_responseTypeCode != ResponseTypeDefault) {
+ exceptionState.throwDOMException(InvalidAccessError, "Synchronous requests from a document must not set a response type.");
return;
}
@@ -637,6 +663,8 @@ void XMLHttpRequest::send(Document* document, ExceptionState& exceptionState)
if (!initSend(exceptionState))
return;
+ RefPtr<FormData> httpBody;
+
if (areMethodAndURLValidForSend()) {
if (getRequestHeader("Content-Type").isEmpty()) {
// FIXME: this should include the charset used for encoding.
@@ -648,12 +676,12 @@ void XMLHttpRequest::send(Document* document, ExceptionState& exceptionState)
String body = createMarkup(document);
// FIXME: This should use value of document.inputEncoding to determine the encoding to use.
- m_requestEntityBody = FormData::create(UTF8Encoding().encode(body, WTF::EntitiesForUnencodables));
+ httpBody = FormData::create(UTF8Encoding().encode(body, WTF::EntitiesForUnencodables));
if (m_upload)
- m_requestEntityBody->setAlwaysStream(true);
+ httpBody->setAlwaysStream(true);
}
- createRequest(exceptionState);
+ createRequest(httpBody.release(), exceptionState);
}
void XMLHttpRequest::send(const String& body, ExceptionState& exceptionState)
@@ -663,6 +691,8 @@ void XMLHttpRequest::send(const String& body, ExceptionState& exceptionState)
if (!initSend(exceptionState))
return;
+ RefPtr<FormData> httpBody;
+
if (!body.isNull() && areMethodAndURLValidForSend()) {
String contentType = getRequestHeader("Content-Type");
if (contentType.isEmpty()) {
@@ -672,12 +702,12 @@ void XMLHttpRequest::send(const String& body, ExceptionState& exceptionState)
m_requestHeaders.set("Content-Type", AtomicString(contentType));
}
- m_requestEntityBody = FormData::create(UTF8Encoding().encode(body, WTF::EntitiesForUnencodables));
+ httpBody = FormData::create(UTF8Encoding().encode(body, WTF::EntitiesForUnencodables));
if (m_upload)
- m_requestEntityBody->setAlwaysStream(true);
+ httpBody->setAlwaysStream(true);
}
- createRequest(exceptionState);
+ createRequest(httpBody.release(), exceptionState);
}
void XMLHttpRequest::send(Blob* body, ExceptionState& exceptionState)
@@ -687,26 +717,36 @@ void XMLHttpRequest::send(Blob* body, ExceptionState& exceptionState)
if (!initSend(exceptionState))
return;
+ RefPtr<FormData> httpBody;
+
if (areMethodAndURLValidForSend()) {
if (getRequestHeader("Content-Type").isEmpty()) {
const String& blobType = body->type();
- if (!blobType.isEmpty() && isValidContentType(blobType))
+ if (!blobType.isEmpty() && isValidContentType(blobType)) {
setRequestHeaderInternal("Content-Type", AtomicString(blobType));
- else {
- // From FileAPI spec, whenever media type cannot be determined, empty string must be returned.
+ } else {
+ // From FileAPI spec, whenever media type cannot be determined,
+ // empty string must be returned.
setRequestHeaderInternal("Content-Type", "");
}
}
// FIXME: add support for uploading bundles.
- m_requestEntityBody = FormData::create();
- if (body->hasBackingFile())
- m_requestEntityBody->appendFile(toFile(body)->path());
- else
- m_requestEntityBody->appendBlob(body->uuid(), body->blobDataHandle());
+ httpBody = FormData::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(exceptionState);
+ createRequest(httpBody.release(), exceptionState);
}
void XMLHttpRequest::send(DOMFormData* body, ExceptionState& exceptionState)
@@ -716,16 +756,18 @@ void XMLHttpRequest::send(DOMFormData* body, ExceptionState& exceptionState)
if (!initSend(exceptionState))
return;
+ RefPtr<FormData> httpBody;
+
if (areMethodAndURLValidForSend()) {
- m_requestEntityBody = body->createMultiPartFormData(body->encoding());
+ httpBody = body->createMultiPartFormData();
if (getRequestHeader("Content-Type").isEmpty()) {
- AtomicString contentType = AtomicString("multipart/form-data; boundary=", AtomicString::ConstructFromLiteral) + m_requestEntityBody->boundary().data();
+ AtomicString contentType = AtomicString("multipart/form-data; boundary=", AtomicString::ConstructFromLiteral) + httpBody->boundary().data();
setRequestHeaderInternal("Content-Type", contentType);
}
}
- createRequest(exceptionState);
+ createRequest(httpBody.release(), exceptionState);
}
void XMLHttpRequest::send(ArrayBuffer* body, ExceptionState& exceptionState)
@@ -754,23 +796,24 @@ void XMLHttpRequest::sendBytesData(const void* data, size_t length, ExceptionSta
if (!initSend(exceptionState))
return;
+ RefPtr<FormData> httpBody;
+
if (areMethodAndURLValidForSend()) {
- m_requestEntityBody = FormData::create(data, length);
+ httpBody = FormData::create(data, length);
if (m_upload)
- m_requestEntityBody->setAlwaysStream(true);
+ httpBody->setAlwaysStream(true);
}
- createRequest(exceptionState);
+ createRequest(httpBody.release(), exceptionState);
}
void XMLHttpRequest::sendForInspectorXHRReplay(PassRefPtr<FormData> formData, ExceptionState& exceptionState)
{
- m_requestEntityBody = formData ? formData->deepCopy() : 0;
- createRequest(exceptionState);
+ createRequest(formData ? formData->deepCopy() : nullptr, exceptionState);
m_exceptionCode = exceptionState.code();
}
-void XMLHttpRequest::createRequest(ExceptionState& exceptionState)
+void XMLHttpRequest::createRequest(PassRefPtr<FormData> httpBody, ExceptionState& exceptionState)
{
// Only GET request is supported for blob URL.
if (m_url.protocolIs("blob") && m_method != "GET") {
@@ -783,8 +826,8 @@ void XMLHttpRequest::createRequest(ExceptionState& exceptionState)
// Also, only async requests support upload progress events.
bool uploadEvents = false;
if (m_async) {
- m_progressEventThrottle.dispatchEvent(XMLHttpRequestProgressEvent::create(EventTypeNames::loadstart));
- if (m_requestEntityBody && m_upload) {
+ dispatchProgressEvent(EventTypeNames::loadstart, 0, 0);
+ if (httpBody && m_upload) {
uploadEvents = m_upload->hasEventListeners();
m_upload->dispatchEvent(XMLHttpRequestProgressEvent::create(EventTypeNames::loadstart));
}
@@ -796,46 +839,44 @@ void XMLHttpRequest::createRequest(ExceptionState& exceptionState)
// added after the request is started.
m_uploadEventsAllowed = m_sameOriginRequest || uploadEvents || !isSimpleCrossOriginAccessRequest(m_method, m_requestHeaders);
+ ASSERT(executionContext());
+ ExecutionContext& executionContext = *this->executionContext();
+
ResourceRequest request(m_url);
request.setHTTPMethod(m_method);
request.setTargetType(ResourceRequest::TargetIsXHR);
- // When "blob" is specified for the responseType attribute,
- // we redirect the downloaded data to a file-handle directly
- // and get the file-path as the result.
- if (responseTypeCode() == ResponseTypeBlob)
- request.setDownloadToFile(true);
-
- InspectorInstrumentation::willLoadXHR(executionContext(), this, this, m_method, m_url, m_async, m_requestEntityBody ? m_requestEntityBody->deepCopy() : 0, m_requestHeaders, m_includeCredentials);
+ InspectorInstrumentation::willLoadXHR(&executionContext, this, this, m_method, m_url, m_async, httpBody ? httpBody->deepCopy() : nullptr, m_requestHeaders, m_includeCredentials);
- if (m_requestEntityBody) {
+ if (httpBody) {
ASSERT(m_method != "GET");
ASSERT(m_method != "HEAD");
- request.setHTTPBody(m_requestEntityBody.release());
+ request.setHTTPBody(httpBody);
}
if (m_requestHeaders.size() > 0)
request.addHTTPHeaderFields(m_requestHeaders);
ThreadableLoaderOptions options;
- options.sendLoadCallbacks = SendCallbacks;
- options.sniffContent = DoNotSniffContent;
options.preflightPolicy = uploadEvents ? ForcePreflight : ConsiderPreflight;
- options.allowCredentials = (m_sameOriginRequest || m_includeCredentials) ? AllowStoredCredentials : DoNotAllowStoredCredentials;
- options.credentialsRequested = m_includeCredentials ? ClientRequestedCredentials : ClientDidNotRequestCredentials;
options.crossOriginRequestPolicy = UseAccessControl;
- options.securityOrigin = securityOrigin();
options.initiator = FetchInitiatorTypeNames::xmlhttprequest;
- options.contentSecurityPolicyEnforcement = ContentSecurityPolicy::shouldBypassMainWorld(executionContext()) ? DoNotEnforceContentSecurityPolicy : EnforceConnectSrcDirective;
- // TODO(tsepez): Specify TreatAsActiveContent per http://crbug.com/305303.
- options.mixedContentBlockingTreatment = TreatAsPassiveContent;
+ options.contentSecurityPolicyEnforcement = ContentSecurityPolicy::shouldBypassMainWorld(&executionContext) ? DoNotEnforceContentSecurityPolicy : EnforceConnectSrcDirective;
options.timeoutMilliseconds = m_timeoutMilliseconds;
- // Since we redirect the downloaded data to a file-handle directly
- // when "blob" is specified for the responseType attribute,
- // buffering is not needed.
- if (responseTypeCode() == ResponseTypeBlob)
- options.dataBufferingPolicy = DoNotBufferData;
+ ResourceLoaderOptions resourceLoaderOptions;
+ resourceLoaderOptions.allowCredentials = (m_sameOriginRequest || m_includeCredentials) ? AllowStoredCredentials : DoNotAllowStoredCredentials;
+ resourceLoaderOptions.credentialsRequested = m_includeCredentials ? ClientRequestedCredentials : ClientDidNotRequestCredentials;
+ resourceLoaderOptions.securityOrigin = securityOrigin();
+ // TODO(tsepez): Specify TreatAsActiveContent per http://crbug.com/305303.
+ resourceLoaderOptions.mixedContentBlockingTreatment = TreatAsPassiveContent;
+
+ // When responseType is set to "blob", we redirect the downloaded data to a
+ // file-handle directly.
+ if (responseTypeCode() == ResponseTypeBlob) {
+ request.setDownloadToFile(true);
+ resourceLoaderOptions.dataBufferingPolicy = DoNotBufferData;
+ }
m_exceptionCode = 0;
m_error = false;
@@ -849,7 +890,7 @@ void XMLHttpRequest::createRequest(ExceptionState& exceptionState)
// FIXME: Maybe we need to be able to send XMLHttpRequests from onunload, <http://bugs.webkit.org/show_bug.cgi?id=10904>.
// FIXME: Maybe create() can return null for other reasons too?
ASSERT(!m_loader);
- m_loader = ThreadableLoader::create(executionContext(), this, request, options);
+ m_loader = ThreadableLoader::create(executionContext, this, request, options, resourceLoaderOptions);
if (m_loader) {
// Neither this object nor the JavaScript wrapper should be deleted while
// a request is in progress because we need to keep the listeners alive,
@@ -857,13 +898,15 @@ void XMLHttpRequest::createRequest(ExceptionState& exceptionState)
setPendingActivity(this);
}
} else {
- ThreadableLoader::loadResourceSynchronously(executionContext(), request, *this, options);
+ // Use count for XHR synchronous requests.
+ UseCounter::count(&executionContext, UseCounter::XMLHttpRequestSynchronous);
+ ThreadableLoader::loadResourceSynchronously(executionContext, request, *this, options, resourceLoaderOptions);
}
if (!m_exceptionCode && m_error)
m_exceptionCode = NetworkError;
if (m_exceptionCode)
- exceptionState.throwUninformativeAndGenericDOMException(m_exceptionCode);
+ exceptionState.throwDOMException(m_exceptionCode, "Failed to load '" + m_url.elidedString() + "'.");
}
void XMLHttpRequest::abort()
@@ -871,7 +914,7 @@ void XMLHttpRequest::abort()
WTF_LOG(Network, "XMLHttpRequest %p abort()", this);
// internalAbort() calls dropProtection(), which may release the last reference.
- RefPtr<XMLHttpRequest> protect(this);
+ RefPtrWillBeRawPtr<XMLHttpRequest> protect(this);
bool sendFlag = m_loader;
@@ -957,11 +1000,12 @@ void XMLHttpRequest::clearResponse()
m_responseText.clear();
m_createdDocument = false;
- m_responseDocument = 0;
+ m_responseDocument = nullptr;
- m_responseBlob = 0;
+ m_responseBlob = nullptr;
+ m_downloadedBlobLength = 0;
- m_responseStream = 0;
+ m_responseStream = nullptr;
// These variables may referred by the response accessors. So, we can clear
// this only when we clear the response holder variables above.
@@ -972,7 +1016,6 @@ void XMLHttpRequest::clearResponse()
void XMLHttpRequest::clearRequest()
{
m_requestHeaders.clear();
- m_requestEntityBody = 0;
}
void XMLHttpRequest::handleDidFailGeneric()
@@ -983,30 +1026,18 @@ void XMLHttpRequest::handleDidFailGeneric()
m_error = true;
}
-void XMLHttpRequest::dispatchEventAndLoadEnd(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;
-
- m_progressEventThrottle.dispatchEventAndLoadEnd(type, lengthComputable, loaded, total);
-}
-
-void XMLHttpRequest::dispatchThrottledProgressEvent(const AtomicString& type, long long receivedLength, long long expectedLength)
+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;
- if (type == EventTypeNames::progress)
- m_progressEventThrottle.dispatchProgressEvent(lengthComputable, loaded, total);
- else
- m_progressEventThrottle.dispatchEvent(XMLHttpRequestProgressEvent::create(type, lengthComputable, loaded, total));
+ m_progressEventThrottle.dispatchProgressEvent(type, lengthComputable, loaded, total);
}
-void XMLHttpRequest::dispatchThrottledProgressEventSnapshot(const AtomicString& type)
+void XMLHttpRequest::dispatchProgressEventFromSnapshot(const AtomicString& type)
{
- return dispatchThrottledProgressEvent(type, m_receivedLength, m_response.expectedContentLength());
+ dispatchProgressEvent(type, m_receivedLength, m_response.expectedContentLength());
}
void XMLHttpRequest::handleNetworkError()
@@ -1058,8 +1089,9 @@ void XMLHttpRequest::handleRequestError(ExceptionCode exceptionCode, const Atomi
m_upload->handleRequestError(type);
}
- dispatchThrottledProgressEvent(EventTypeNames::progress, receivedLength, expectedLength);
- dispatchEventAndLoadEnd(type, receivedLength, expectedLength);
+ dispatchProgressEvent(EventTypeNames::progress, receivedLength, expectedLength);
+ dispatchProgressEvent(type, receivedLength, expectedLength);
+ dispatchProgressEvent(EventTypeNames::loadend, receivedLength, expectedLength);
}
void XMLHttpRequest::dropProtectionSoon()
@@ -1107,7 +1139,7 @@ void XMLHttpRequest::setRequestHeaderInternal(const AtomicString& name, const At
{
HTTPHeaderMap::AddResult result = m_requestHeaders.add(name, value);
if (!result.isNewEntry)
- result.iterator->value = result.iterator->value + ", " + value;
+ result.storedValue->value = result.storedValue->value + ", " + value;
}
const AtomicString& XMLHttpRequest::getRequestHeader(const AtomicString& name) const
@@ -1187,9 +1219,7 @@ AtomicString XMLHttpRequest::responseMIMEType() const
bool XMLHttpRequest::responseIsXML() const
{
- // FIXME: Remove the lower() call when DOMImplementation.isXMLMIMEType() is modified
- // to do case insensitive MIME type matching.
- return DOMImplementation::isXMLMIMEType(responseMIMEType().lower());
+ return DOMImplementation::isXMLMIMEType(responseMIMEType());
}
int XMLHttpRequest::status() const
@@ -1264,13 +1294,13 @@ void XMLHttpRequest::didFinishLoading(unsigned long identifier, double)
clearVariablesForLoading();
- InspectorInstrumentation::didFinishXHRLoading(executionContext(), this, this, identifier, m_responseText, m_url, m_lastSendURL, m_lastSendLineNumber);
+ InspectorInstrumentation::didFinishXHRLoading(executionContext(), this, this, identifier, m_responseText, m_method, m_url, m_lastSendURL, m_lastSendLineNumber);
// Prevent dropProtection releasing the last reference, and retain |this| until the end of this method.
- RefPtr<XMLHttpRequest> protect(this);
+ RefPtrWillBeRawPtr<XMLHttpRequest> protect(this);
if (m_loader) {
- m_loader = 0;
+ m_loader = nullptr;
dropProtection();
}
@@ -1321,19 +1351,22 @@ void XMLHttpRequest::didReceiveData(const char* data, int len)
bool useDecoder = m_responseTypeCode == ResponseTypeDefault || m_responseTypeCode == ResponseTypeText || m_responseTypeCode == ResponseTypeJSON || m_responseTypeCode == ResponseTypeDocument;
if (useDecoder && !m_decoder) {
- if (m_responseTypeCode == ResponseTypeJSON)
+ if (m_responseTypeCode == ResponseTypeJSON) {
m_decoder = TextResourceDecoder::create("application/json", "UTF-8");
- else if (!m_responseEncoding.isEmpty())
+ } else if (!m_responseEncoding.isEmpty()) {
m_decoder = TextResourceDecoder::create("text/plain", m_responseEncoding);
// allow TextResourceDecoder to look inside the m_response if it's XML or HTML
- else if (responseIsXML()) {
+ } else if (responseIsXML()) {
m_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.
+ // 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.
m_decoder->useLenientXMLDecoding();
- } else if (equalIgnoringCase(responseMIMEType(), "text/html"))
+ } else if (equalIgnoringCase(responseMIMEType(), "text/html")) {
m_decoder = TextResourceDecoder::create("text/html", "UTF-8");
- else
+ } else {
m_decoder = TextResourceDecoder::create("text/plain", "UTF-8");
+ }
}
if (!len)
@@ -1374,10 +1407,13 @@ void XMLHttpRequest::didDownloadData(int dataLength)
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_downloadedBlobLength += dataLength;
+
trackProgress(dataLength);
}
@@ -1386,7 +1422,7 @@ void XMLHttpRequest::handleDidTimeout()
WTF_LOG(Network, "XMLHttpRequest %p handleDidTimeout()", this);
// internalAbort() calls dropProtection(), which may release the last reference.
- RefPtr<XMLHttpRequest> protect(this);
+ RefPtrWillBeRawPtr<XMLHttpRequest> protect(this);
// Response is cleared next, save needed progress event data.
long long expectedLength = m_response.expectedContentLength();
@@ -1430,4 +1466,14 @@ ExecutionContext* XMLHttpRequest::executionContext() const
return ActiveDOMObject::executionContext();
}
+void XMLHttpRequest::trace(Visitor* visitor)
+{
+ visitor->trace(m_responseBlob);
+ visitor->trace(m_responseStream);
+ visitor->trace(m_responseDocument);
+ visitor->trace(m_progressEventThrottle);
+ visitor->trace(m_upload);
+ XMLHttpRequestEventTarget::trace(visitor);
+}
+
} // namespace WebCore