| Index: Source/core/xml/XMLHttpRequest.cpp
|
| diff --git a/Source/core/xml/XMLHttpRequest.cpp b/Source/core/xml/XMLHttpRequest.cpp
|
| index 7315dd9326803e09632506d68e222b40475c8194..9939b1eb61770d39fc7c28c1155c513226bf7b71 100644
|
| --- a/Source/core/xml/XMLHttpRequest.cpp
|
| +++ b/Source/core/xml/XMLHttpRequest.cpp
|
| @@ -146,7 +146,7 @@ XMLHttpRequest::XMLHttpRequest(ExecutionContext* context, PassRefPtr<SecurityOri
|
| , m_timeoutMilliseconds(0)
|
| , m_loaderIdentifier(0)
|
| , m_state(UNSENT)
|
| - , m_downloadedBlobLength(0)
|
| + , m_lengthDownloadedToFile(0)
|
| , m_receivedLength(0)
|
| , m_lastSendLineNumber(0)
|
| , m_exceptionCode(0)
|
| @@ -160,6 +160,7 @@ XMLHttpRequest::XMLHttpRequest(ExecutionContext* context, PassRefPtr<SecurityOri
|
| , m_uploadEventsAllowed(true)
|
| , m_uploadComplete(false)
|
| , m_sameOriginRequest(true)
|
| + , m_downloadingToFile(false)
|
| {
|
| #ifndef NDEBUG
|
| xmlHttpRequestCounter.increment();
|
| @@ -261,29 +262,43 @@ Document* XMLHttpRequest::responseXML(ExceptionState& exceptionState)
|
| 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) {
|
| - // 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 (!filePath.isEmpty() && m_downloadedBlobLength) {
|
| - blobData->appendFile(filePath);
|
| - // FIXME: finalResponseMIMETypeWithFallback() defaults to text/xml
|
| - // which may be incorrect. Replace it with finalResponseMIMEType()
|
| - // after compatibility investigation.
|
| - blobData->setContentType(finalResponseMIMETypeWithFallback());
|
| + if (m_downloadingToFile) {
|
| + ASSERT(!m_binaryResponseBuilder.get());
|
| +
|
| + // 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.
|
| + String filePath = m_response.downloadedFilePath();
|
| + // If we errored out or got no data, we still return a blob, just
|
| + // an empty one.
|
| + if (!filePath.isEmpty() && m_lengthDownloadedToFile) {
|
| + blobData->appendFile(filePath);
|
| + // FIXME: finalResponseMIMETypeWithFallback() defaults to
|
| + // text/xml which may be incorrect. Replace it with
|
| + // finalResponseMIMEType() after compatibility investigation.
|
| + blobData->setContentType(finalResponseMIMETypeWithFallback());
|
| + }
|
| + m_responseBlob = Blob::create(BlobDataHandle::create(blobData.release(), m_lengthDownloadedToFile));
|
| + } else {
|
| + size_t size = 0;
|
| + if (m_binaryResponseBuilder.get() && m_binaryResponseBuilder->size()) {
|
| + RefPtr<RawData> rawData = RawData::create();
|
| + size = m_binaryResponseBuilder->size();
|
| + rawData->mutableData()->append(m_binaryResponseBuilder->data(), size);
|
| + blobData->appendData(rawData, 0, BlobDataItem::toEndOfFile);
|
| + blobData->setContentType(finalResponseMIMETypeWithFallback());
|
| + m_binaryResponseBuilder.clear();
|
| + }
|
| + m_responseBlob = Blob::create(BlobDataHandle::create(blobData.release(), size));
|
| }
|
| - m_responseBlob = Blob::create(BlobDataHandle::create(blobData.release(), m_downloadedBlobLength));
|
| }
|
|
|
| return m_responseBlob.get();
|
| @@ -853,7 +868,8 @@ void XMLHttpRequest::createRequest(PassRefPtr<FormData> httpBody, ExceptionState
|
|
|
| // When responseType is set to "blob", we redirect the downloaded data to a
|
| // file-handle directly.
|
| - if (responseTypeCode() == ResponseTypeBlob) {
|
| + m_downloadingToFile = responseTypeCode() == ResponseTypeBlob;
|
| + if (m_downloadingToFile) {
|
| request.setDownloadToFile(true);
|
| resourceLoaderOptions.dataBufferingPolicy = DoNotBufferData;
|
| }
|
| @@ -982,7 +998,9 @@ void XMLHttpRequest::clearResponse()
|
| m_responseDocument = nullptr;
|
|
|
| m_responseBlob = nullptr;
|
| - m_downloadedBlobLength = 0;
|
| +
|
| + m_downloadingToFile = false;
|
| + m_lengthDownloadedToFile = 0;
|
|
|
| m_responseLegacyStream = nullptr;
|
| m_responseStream = nullptr;
|
| @@ -1419,7 +1437,7 @@ PassOwnPtr<TextResourceDecoder> XMLHttpRequest::createDecoder() const
|
|
|
| void XMLHttpRequest::didReceiveData(const char* data, int len)
|
| {
|
| - ASSERT(m_responseTypeCode != ResponseTypeBlob);
|
| + ASSERT(!m_downloadingToFile);
|
|
|
| if (m_error)
|
| return;
|
| @@ -1440,7 +1458,7 @@ void XMLHttpRequest::didReceiveData(const char* data, int len)
|
| m_decoder = createDecoder();
|
|
|
| m_responseText = m_responseText.concatenateWith(m_decoder->decode(data, len));
|
| - } else if (m_responseTypeCode == ResponseTypeArrayBuffer) {
|
| + } else if (m_responseTypeCode == ResponseTypeArrayBuffer || m_responseTypeCode == ResponseTypeBlob) {
|
| // Buffer binary data.
|
| if (!m_binaryResponseBuilder)
|
| m_binaryResponseBuilder = SharedBuffer::create();
|
| @@ -1465,11 +1483,11 @@ void XMLHttpRequest::didReceiveData(const char* data, int len)
|
|
|
| void XMLHttpRequest::didDownloadData(int dataLength)
|
| {
|
| - ASSERT(m_responseTypeCode == ResponseTypeBlob);
|
| -
|
| if (m_error)
|
| return;
|
|
|
| + ASSERT(m_downloadingToFile);
|
| +
|
| if (m_state < HEADERS_RECEIVED)
|
| changeState(HEADERS_RECEIVED);
|
|
|
| @@ -1481,7 +1499,7 @@ void XMLHttpRequest::didDownloadData(int dataLength)
|
| if (m_error)
|
| return;
|
|
|
| - m_downloadedBlobLength += dataLength;
|
| + m_lengthDownloadedToFile += dataLength;
|
|
|
| trackProgress(dataLength);
|
| }
|
|
|