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(); }
Blob* XMLHttpRequest::responseBlob(ExceptionCode& ec) { if (m_responseTypeCode != ResponseTypeBlob) { ec = INVALID_STATE_ERR; return 0; } // We always return null before DONE. if (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. OwnPtr<BlobData> blobData = BlobData::create(); // 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); blobData->setContentType(responseMIMEType()); // responseMIMEType defaults to text/xml which may be incorrect. m_binaryResponseBuilder.clear(); } m_responseBlob = Blob::create(blobData.release(), size); } return m_responseBlob.get(); }
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(); }
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 "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. 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); blobData->setContentType(responseMIMEType()); // responseMIMEType defaults to text/xml which may be incorrect. } m_responseBlob = Blob::create(BlobDataHandle::create(blobData.release(), m_downloadedBlobLength)); } return m_responseBlob.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(); }
Document* XMLHttpRequest::responseXML(ExceptionState& exceptionState) { if (m_responseTypeCode != ResponseTypeDefault && m_responseTypeCode != ResponseTypeDocument) { exceptionState.throwDOMException(InvalidStateError, "The value is only accessible if the object's 'responseType' is '' or 'document' (was '" + responseType() + "')."); return 0; } if (m_error || m_state != DONE) return 0; 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) || executionContext()->isWorkerGlobalScope()) { m_responseDocument = 0; } else { DocumentInit init = DocumentInit::fromContext(document()->contextDocument(), m_url); if (isHTML) m_responseDocument = HTMLDocument::create(init); else m_responseDocument = Document::create(init); // FIXME: Set Last-Modified. m_responseDocument->setContent(m_responseText.flattenToString()); m_responseDocument->setSecurityOrigin(securityOrigin()); m_responseDocument->setContextFeatures(document()->contextFeatures()); if (!m_responseDocument->wellFormed()) m_responseDocument = 0; } m_createdDocument = true; } return m_responseDocument.get(); }
bool DocumentLoader::scheduleArchiveLoad(ResourceLoader* loader, const ResourceRequest& request, const KURL& originalURL) { ArchiveResource* resource = 0; if (request.url() == originalURL) resource = archiveResourceForURL(originalURL); if (!resource) { // WebArchiveDebugMode means we fail loads instead of trying to fetch them from the network if they're not in the archive. bool shouldFailLoad = m_frame->settings()->webArchiveDebugModeEnabled() && ArchiveFactory::isArchiveMimeType(responseMIMEType()); if (!shouldFailLoad) return false; } m_pendingSubstituteResources.set(loader, resource); deliverSubstituteResourcesAfterDelay(); return true; }
bool DocumentLoader::scheduleArchiveLoad(ResourceLoader* loader, const ResourceRequest& request) { if (ArchiveResource* resource = archiveResourceForURL(request.url())) { m_pendingSubstituteResources.set(loader, resource); deliverSubstituteResourcesAfterDelay(); return true; } if (!m_archive) return false; switch (m_archive->type()) { #if ENABLE(WEB_ARCHIVE) case Archive::WebArchive: // WebArchiveDebugMode means we fail loads instead of trying to fetch them from the network if they're not in the archive. return m_frame->settings() && m_frame->settings()->webArchiveDebugModeEnabled() && ArchiveFactory::isArchiveMimeType(responseMIMEType()); #endif #if ENABLE(MHTML) case Archive::MHTML: return true; // Always fail the load for resources not included in the MHTML. #endif default: return false; } }