Blob* XMLHttpRequest::responseBlob() { ASSERT(m_responseTypeCode == ResponseTypeBlob); ASSERT(doneWithoutErrors()); 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. auto blobData = std::make_unique<BlobData>(); // 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); String normalizedContentType = Blob::normalizedContentType(responseMIMEType()); blobData->setContentType(normalizedContentType); // responseMIMEType defaults to text/xml which may be incorrect. m_binaryResponseBuilder.clear(); } m_responseBlob = Blob::create(std::move(blobData), size); } return m_responseBlob.get(); }
void XMLHttpRequest::didCacheResponseJSON() { ASSERT(m_responseTypeCode == ResponseTypeJSON); ASSERT(doneWithoutErrors()); m_responseCacheIsValid = true; m_responseBuilder.clear(); }
Document* XMLHttpRequest::responseXML(ExceptionCode& ec) { if (m_responseTypeCode != ResponseTypeDefault && m_responseTypeCode != ResponseTypeDocument) { ec = INVALID_STATE_ERR; return nullptr; } if (!doneWithoutErrors()) return nullptr; if (!m_createdDocument) { bool isHTML = equalIgnoringCase(responseMIMEType(), "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) || scriptExecutionContext()->isWorkerGlobalScope()) { m_responseDocument = 0; } else { if (isHTML) m_responseDocument = HTMLDocument::create(0, m_url); else m_responseDocument = Document::create(0, m_url); // FIXME: Set Last-Modified. m_responseDocument->setContent(m_responseBuilder.toStringPreserveCapacity()); m_responseDocument->setSecurityOrigin(securityOrigin()); if (!m_responseDocument->wellFormed()) m_responseDocument = 0; } m_createdDocument = true; } return m_responseDocument.get(); }
RefPtr<ArrayBuffer> XMLHttpRequest::createResponseArrayBuffer() { ASSERT(m_responseType == ResponseType::Arraybuffer); ASSERT(doneWithoutErrors()); auto result = m_binaryResponseBuilder ? m_binaryResponseBuilder->createArrayBuffer() : ArrayBuffer::create(nullptr, 0); m_binaryResponseBuilder = nullptr; return result; }
ArrayBuffer* XMLHttpRequest::responseArrayBuffer() { ASSERT(m_responseTypeCode == ResponseTypeArrayBuffer); ASSERT(doneWithoutErrors()); if (!m_responseArrayBuffer) { if (m_binaryResponseBuilder) m_responseArrayBuffer = m_binaryResponseBuilder->createArrayBuffer(); else m_responseArrayBuffer = ArrayBuffer::create(nullptr, 0); m_binaryResponseBuilder.clear(); } return m_responseArrayBuffer.get(); }
Ref<Blob> XMLHttpRequest::createResponseBlob() { ASSERT(m_responseType == ResponseType::Blob); ASSERT(doneWithoutErrors()); if (!m_binaryResponseBuilder) return Blob::create(); // FIXME: We just received the data from NetworkProcess, and are sending it back. This is inefficient. Vector<uint8_t> data; data.append(m_binaryResponseBuilder->data(), m_binaryResponseBuilder->size()); m_binaryResponseBuilder = nullptr; String normalizedContentType = Blob::normalizedContentType(responseMIMEType()); // responseMIMEType defaults to text/xml which may be incorrect. return Blob::create(WTFMove(data), normalizedContentType); }
Blob* XMLHttpRequest::responseBlob() { ASSERT(m_responseTypeCode == ResponseTypeBlob); ASSERT(doneWithoutErrors()); if (!m_responseBlob) { if (m_binaryResponseBuilder) { // FIXME: We just received the data from NetworkProcess, and are sending it back. This is inefficient. Vector<char> data; data.append(m_binaryResponseBuilder->data(), m_binaryResponseBuilder->size()); String normalizedContentType = Blob::normalizedContentType(responseMIMEType()); // responseMIMEType defaults to text/xml which may be incorrect. m_responseBlob = Blob::create(std::move(data), normalizedContentType); m_binaryResponseBuilder.clear(); } else { // If we errored out or got no data, we still return a blob, just an empty one. m_responseBlob = Blob::create(); } } return m_responseBlob.get(); }
ExceptionOr<Document*> XMLHttpRequest::responseXML() { if (m_responseType != ResponseType::EmptyString && m_responseType != ResponseType::Document) return Exception { INVALID_STATE_ERR }; if (!doneWithoutErrors()) return nullptr; if (!m_createdDocument) { String mimeType = responseMIMEType(); bool isHTML = equalLettersIgnoringASCIICase(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_responseType == ResponseType::EmptyString) || scriptExecutionContext()->isWorkerGlobalScope()) { m_responseDocument = nullptr; } else { if (isHTML) m_responseDocument = HTMLDocument::create(0, m_url); else m_responseDocument = XMLDocument::create(0, m_url); // FIXME: Set Last-Modified. m_responseDocument->setContent(m_responseBuilder.toStringPreserveCapacity()); m_responseDocument->setContextDocument(downcast<Document>(*scriptExecutionContext())); m_responseDocument->setSecurityOriginPolicy(scriptExecutionContext()->securityOriginPolicy()); m_responseDocument->overrideMIMEType(mimeType); if (!m_responseDocument->wellFormed()) m_responseDocument = nullptr; } m_createdDocument = true; } return m_responseDocument.get(); }
void XMLHttpRequest::didCacheResponse() { ASSERT(doneWithoutErrors()); m_responseCacheIsValid = true; m_responseBuilder.clear(); }