예제 #1
0
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();
}
예제 #2
0
String XMLHttpRequest::responseText(ExceptionCode& ec)
{
    if (responseTypeCode() != ResponseTypeDefault && responseTypeCode() != ResponseTypeText) {
        ec = INVALID_STATE_ERR;
        return "";
    }
    return m_responseBuilder.toStringPreserveCapacity();
}
예제 #3
0
Blob* XMLHttpRequest::responseBlob(ExceptionCode& ec) const
{
    if (responseTypeCode() != ResponseTypeBlob) {
        ec = INVALID_STATE_ERR;
        return 0;
    }
    return m_responseBlob.get();
}
예제 #4
0
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);
}