Document* XMLHttpRequest::responseXML(ExceptionCode& ec) { if (responseTypeCode() != ResponseTypeDefault && responseTypeCode() != ResponseTypeText && responseTypeCode() != ResponseTypeDocument) { ec = INVALID_STATE_ERR; return 0; } if (m_state != DONE) return 0; if (!m_createdDocument) { if ((m_response.isHTTP() && !responseIsXML()) || scriptExecutionContext()->isWorkerContext()) { // The W3C spec requires this. m_responseXML = 0; } else { m_responseXML = Document::create(0, m_url); // FIXME: Set Last-Modified. m_responseXML->setContent(m_responseBuilder.toStringPreserveCapacity()); m_responseXML->setSecurityOrigin(securityOrigin()); if (!m_responseXML->wellFormed()) m_responseXML = 0; } m_createdDocument = true; } return m_responseXML.get(); }
String XMLHttpRequest::responseText(ExceptionCode& ec) { if (responseTypeCode() != ResponseTypeDefault && responseTypeCode() != ResponseTypeText) { ec = INVALID_STATE_ERR; return ""; } return m_responseBuilder.toStringPreserveCapacity(); }
Blob* XMLHttpRequest::responseBlob(ExceptionCode& ec) const { if (responseTypeCode() != ResponseTypeBlob) { ec = INVALID_STATE_ERR; return 0; } return m_responseBlob.get(); }
void XMLHttpRequest::createRequest(ExceptionState& exceptionState) { // Only GET request is supported for blob URL. if (m_url.protocolIs("blob") && m_method != "GET") { exceptionState.throwDOMException(NetworkError, "'GET' is the only method allowed for 'blob:' URLs."); return; } // The presence of upload event listeners forces us to use preflighting because POSTing to an URL that does not // permit cross origin requests should look exactly like POSTing to an URL that does not respond at all. // 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) { uploadEvents = m_upload->hasEventListeners(); m_upload->dispatchEvent(XMLHttpRequestProgressEvent::create(EventTypeNames::loadstart)); } } m_sameOriginRequest = securityOrigin()->canRequest(m_url); // We also remember whether upload events should be allowed for this request in case the upload listeners are // added after the request is started. m_uploadEventsAllowed = m_sameOriginRequest || uploadEvents || !isSimpleCrossOriginAccessRequest(m_method, m_requestHeaders); 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); if (m_requestEntityBody) { ASSERT(m_method != "GET"); ASSERT(m_method != "HEAD"); request.setHTTPBody(m_requestEntityBody.release()); } 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.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; m_exceptionCode = 0; m_error = false; if (m_async) { if (m_upload) request.setReportUploadProgress(true); // ThreadableLoader::create can return null here, for example if we're no longer attached to a page. // This is true while running onunload handlers. // 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); 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, // and they are referenced by the JavaScript wrapper. setPendingActivity(this); } } else { ThreadableLoader::loadResourceSynchronously(executionContext(), request, *this, options); } if (!m_exceptionCode && m_error) m_exceptionCode = NetworkError; if (m_exceptionCode) exceptionState.throwUninformativeAndGenericDOMException(m_exceptionCode); }