Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1824)

Unified Diff: Source/core/xml/XMLHttpRequest.cpp

Issue 23444058: Use downloadToFile option when XHR downloads a Blob (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Add LayoutTests expected file for Linux Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« Source/core/xml/XMLHttpRequest.h ('K') | « Source/core/xml/XMLHttpRequest.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/xml/XMLHttpRequest.cpp
diff --git a/Source/core/xml/XMLHttpRequest.cpp b/Source/core/xml/XMLHttpRequest.cpp
index 4b041d4ec7e998a3f5e89b9c8366a8f3dc2c5a54..797318b8c5d62c57fb3b21b4f8de4dbdee325e64 100644
--- a/Source/core/xml/XMLHttpRequest.cpp
+++ b/Source/core/xml/XMLHttpRequest.cpp
@@ -276,31 +276,26 @@ Document* XMLHttpRequest::responseXML(ExceptionState& es)
Blob* XMLHttpRequest::responseBlob()
{
ASSERT(m_responseTypeCode == ResponseTypeBlob);
+ ASSERT(!m_binaryResponseBuilder.get());
// We always return null before DONE.
if (m_error || m_state != DONE)
return 0;
if (!m_responseBlob) {
- // FIXME: This causes two (or more) unnecessary copies of the data.
- // Chromium stores blob data in the browser process, so we're pulling the data
- // from the network only to copy it into the renderer to copy it back to the browser.
- // Ideally we'd get the blob/file-handle from the ResourceResponse directly
- // instead of copying the bytes. Embedders who store blob data in the
- // same process as WebCore would at least to teach BlobData to take
- // a SharedBuffer, even if they don't get the Blob from the network layer directly.
+ // When "blob" is specified for the responseType attribute,
+ // we redirect the downloaded data to the file-handle directly
tyoshino (SeeGerritForStatus) 2013/09/19 06:58:46 the file-handle -> a file-handle
yusukesuzuki 2013/09/19 07:19:06 Done.
+ // 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();
+ const String& filePath = m_response.downloadedFilePath();
// If we errored out or got no data, we still return a blob, just an empty one.
- size_t size = 0;
- if (m_binaryResponseBuilder) {
- RefPtr<RawData> rawData = RawData::create();
- size = m_binaryResponseBuilder->size();
- rawData->mutableData()->append(m_binaryResponseBuilder->data(), size);
- blobData->appendData(rawData, 0, BlobDataItem::toEndOfFile);
+ if (!filePath.isEmpty() && m_receivedLength) {
+ blobData->appendFile(filePath);
blobData->setContentType(responseMIMEType()); // responseMIMEType defaults to text/xml which may be incorrect.
- m_binaryResponseBuilder.clear();
}
- m_responseBlob = Blob::create(blobData.release(), size);
+ m_responseBlob = Blob::create(blobData.release(), m_receivedLength);
}
return m_responseBlob.get();
@@ -752,6 +747,12 @@ void XMLHttpRequest::createRequest(ExceptionState& es)
request.setHTTPMethod(m_method);
request.setTargetType(ResourceRequest::TargetIsXHR);
+ // When "blob" is specified for the responseType attribute,
+ // we redirect the downloaded data to the file-handle directly
+ // and get the file-path as the result.
+ if (responseTypeCode() == ResponseTypeBlob)
+ request.setDownloadToFile(true);
+
InspectorInstrumentation::willLoadXHR(scriptExecutionContext(), this, m_method, m_url, m_async, m_requestEntityBody ? m_requestEntityBody->deepCopy() : 0, m_requestHeaders, m_includeCredentials);
if (m_requestEntityBody) {
@@ -776,6 +777,12 @@ void XMLHttpRequest::createRequest(ExceptionState& es)
options.mixedContentBlockingTreatment = TreatAsActiveContent;
options.timeoutMilliseconds = m_timeoutMilliseconds;
+ // Since we redirect the downloaded data to the file-handle directly
+ // when "blob" is specified for the responseType attribute,
+ // buffering is not needed.
+ if (responseTypeCode() == ResponseTypeBlob)
+ options.dataBufferingPolicy = DoNotBufferData;
+
m_exceptionCode = 0;
m_error = false;
@@ -1176,6 +1183,8 @@ void XMLHttpRequest::didReceiveResponse(unsigned long identifier, const Resource
void XMLHttpRequest::didReceiveData(const char* data, int len)
{
+ ASSERT(m_responseTypeCode != ResponseTypeBlob);
+
if (m_error)
return;
@@ -1208,7 +1217,7 @@ void XMLHttpRequest::didReceiveData(const char* data, int len)
if (useDecoder) {
m_responseText = m_responseText.concatenateWith(m_decoder->decode(data, len));
- } else if (m_responseTypeCode == ResponseTypeArrayBuffer || m_responseTypeCode == ResponseTypeBlob) {
+ } else if (m_responseTypeCode == ResponseTypeArrayBuffer) {
// Buffer binary data.
if (!m_binaryResponseBuilder)
m_binaryResponseBuilder = SharedBuffer::create();
@@ -1237,6 +1246,38 @@ void XMLHttpRequest::didReceiveData(const char* data, int len)
}
}
+void XMLHttpRequest::didDownloadData(int len)
+{
+ ASSERT(m_responseTypeCode == ResponseTypeBlob);
+
+ if (m_error)
+ return;
+
+ if (m_state < HEADERS_RECEIVED)
+ changeState(HEADERS_RECEIVED);
+
+ if (!len)
+ return;
+
+ if (!m_error) {
tyoshino (SeeGerritForStatus) 2013/09/19 06:58:46 factor out L1232-1245 and reuse it
yusukesuzuki 2013/09/19 07:19:06 Done. Seeing the m_receivedLength comment, named `
+ long long expectedLength = m_response.expectedContentLength();
+ m_receivedLength += len;
+
+ if (m_async) {
+ bool lengthComputable = expectedLength > 0 && m_receivedLength <= expectedLength;
+ unsigned long long total = lengthComputable ? expectedLength : 0;
+ m_progressEventThrottle.dispatchProgressEvent(lengthComputable, m_receivedLength, total);
+ }
+
+ if (m_state != LOADING) {
+ changeState(LOADING);
+ } else {
+ // Firefox calls readyStateChanged every time it receives data, 4449442
+ callReadyStateChangeListener();
+ }
+ }
+}
+
void XMLHttpRequest::didTimeout()
{
// internalAbort() calls dropProtection(), which may release the last reference.
« Source/core/xml/XMLHttpRequest.h ('K') | « Source/core/xml/XMLHttpRequest.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698