⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xmlhttprequest.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    dispatchReadyStateChangeEvent();    if (m_state == DONE)        dispatchLoadEvent();}void XMLHttpRequest::open(const String& method, const KURL& url, bool async, ExceptionCode& ec){    internalAbort();    State previousState = m_state;    m_state = UNSENT;    m_error = false;    m_uploadComplete = false;    // clear stuff from possible previous load    clearResponse();    clearRequest();    ASSERT(m_state == UNSENT);    if (!isValidToken(method)) {        ec = SYNTAX_ERR;        return;    }        // Method names are case sensitive. But since Firefox uppercases method names it knows, we'll do the same.    String methodUpper(method.upper());        if (methodUpper == "TRACE" || methodUpper == "TRACK" || methodUpper == "CONNECT") {        ec = SECURITY_ERR;        return;    }    m_url = url;    if (methodUpper == "COPY" || methodUpper == "DELETE" || methodUpper == "GET" || methodUpper == "HEAD"        || methodUpper == "INDEX" || methodUpper == "LOCK" || methodUpper == "M-POST" || methodUpper == "MKCOL" || methodUpper == "MOVE"        || methodUpper == "OPTIONS" || methodUpper == "POST" || methodUpper == "PROPFIND" || methodUpper == "PROPPATCH" || methodUpper == "PUT"         || methodUpper == "UNLOCK")        m_method = methodUpper;    else        m_method = method;    m_async = async;    ASSERT(!m_loader);    // Check previous state to avoid dispatching readyState event    // when calling open several times in a row.    if (previousState != OPENED)        changeState(OPENED);    else        m_state = OPENED;}void XMLHttpRequest::open(const String& method, const KURL& url, bool async, const String& user, ExceptionCode& ec){    KURL urlWithCredentials(url);    urlWithCredentials.setUser(user);        open(method, urlWithCredentials, async, ec);}void XMLHttpRequest::open(const String& method, const KURL& url, bool async, const String& user, const String& password, ExceptionCode& ec){    KURL urlWithCredentials(url);    urlWithCredentials.setUser(user);    urlWithCredentials.setPass(password);        open(method, urlWithCredentials, async, ec);}bool XMLHttpRequest::initSend(ExceptionCode& ec){    if (!scriptExecutionContext())        return false;    if (m_state != OPENED || m_loader) {        ec = INVALID_STATE_ERR;        return false;    }    m_error = false;    return true;}void XMLHttpRequest::send(ExceptionCode& ec){    send(String(), ec);}void XMLHttpRequest::send(Document* document, ExceptionCode& ec){    ASSERT(document);    if (!initSend(ec))        return;    if (m_method != "GET" && m_method != "HEAD" && (m_url.protocolIs("http") || m_url.protocolIs("https"))) {        String contentType = getRequestHeader("Content-Type");        if (contentType.isEmpty()) {#if ENABLE(DASHBOARD_SUPPORT)            if (usesDashboardBackwardCompatibilityMode())                setRequestHeaderInternal("Content-Type", "application/x-www-form-urlencoded");            else#endif                // FIXME: this should include the charset used for encoding.                setRequestHeaderInternal("Content-Type", "application/xml");        }        // FIXME: According to XMLHttpRequest Level 2, this should use the Document.innerHTML algorithm        // from the HTML5 specification to serialize the document.        String body = createMarkup(document);        // FIXME: this should use value of document.inputEncoding to determine the encoding to use.        TextEncoding encoding = UTF8Encoding();        m_requestEntityBody = FormData::create(encoding.encode(body.characters(), body.length(), EntitiesForUnencodables));        if (m_upload)            m_requestEntityBody->setAlwaysStream(true);    }    createRequest(ec);}void XMLHttpRequest::send(const String& body, ExceptionCode& ec){    if (!initSend(ec))        return;    if (!body.isNull() && m_method != "GET" && m_method != "HEAD" && (m_url.protocolIs("http") || m_url.protocolIs("https"))) {        String contentType = getRequestHeader("Content-Type");        if (contentType.isEmpty()) {#if ENABLE(DASHBOARD_SUPPORT)            if (usesDashboardBackwardCompatibilityMode())                setRequestHeaderInternal("Content-Type", "application/x-www-form-urlencoded");            else#endif                setRequestHeaderInternal("Content-Type", "application/xml");        }        m_requestEntityBody = FormData::create(UTF8Encoding().encode(body.characters(), body.length(), EntitiesForUnencodables));        if (m_upload)            m_requestEntityBody->setAlwaysStream(true);    }    createRequest(ec);}void XMLHttpRequest::send(File* body, ExceptionCode& ec){    if (!initSend(ec))        return;    if (m_method != "GET" && m_method != "HEAD" && (m_url.protocolIs("http") || m_url.protocolIs("https"))) {        // FIXME: Should we set a Content-Type if one is not set.        // FIXME: add support for uploading bundles.        m_requestEntityBody = FormData::create();        m_requestEntityBody->appendFile(body->path(), false);    }    createRequest(ec);}void XMLHttpRequest::createRequest(ExceptionCode& ec){    if (m_async) {        dispatchLoadStartEvent();        if (m_requestEntityBody && m_upload)            m_upload->dispatchLoadStartEvent();    }    m_sameOriginRequest = scriptExecutionContext()->securityOrigin()->canRequest(m_url);    if (!m_sameOriginRequest) {        makeCrossSiteAccessRequest(ec);        return;    }    makeSameOriginRequest(ec);}void XMLHttpRequest::makeSameOriginRequest(ExceptionCode& ec){    ASSERT(m_sameOriginRequest);    ResourceRequest request(m_url);    request.setHTTPMethod(m_method);    if (m_requestEntityBody) {        ASSERT(m_method != "GET");        request.setHTTPBody(m_requestEntityBody.release());    }    if (m_requestHeaders.size() > 0)        request.addHTTPHeaderFields(m_requestHeaders);    if (m_async)        loadRequestAsynchronously(request);    else        loadRequestSynchronously(request, ec);}bool XMLHttpRequest::isSimpleCrossSiteAccessRequest() const{    if (m_method != "GET" && m_method != "POST")        return false;    HTTPHeaderMap::const_iterator end = m_requestHeaders.end();    for (HTTPHeaderMap::const_iterator it = m_requestHeaders.begin(); it != end; ++it) {        if (!isOnAccessControlSimpleRequestHeaderWhitelist(it->first))            return false;    }    return true;}void XMLHttpRequest::makeCrossSiteAccessRequest(ExceptionCode& ec){    ASSERT(!m_sameOriginRequest);    if (isSimpleCrossSiteAccessRequest())        makeSimpleCrossSiteAccessRequest(ec);    else        makeCrossSiteAccessRequestWithPreflight(ec);}void XMLHttpRequest::makeSimpleCrossSiteAccessRequest(ExceptionCode& ec){    ASSERT(isSimpleCrossSiteAccessRequest());    KURL url = m_url;    url.setUser(String());    url.setPass(String());     ResourceRequest request(url);    request.setHTTPMethod(m_method);    request.setAllowHTTPCookies(m_includeCredentials);    request.setHTTPOrigin(scriptExecutionContext()->securityOrigin()->toString());    if (m_requestHeaders.size() > 0)        request.addHTTPHeaderFields(m_requestHeaders);    if (m_async)        loadRequestAsynchronously(request);    else        loadRequestSynchronously(request, ec);}void XMLHttpRequest::makeCrossSiteAccessRequestWithPreflight(ExceptionCode& ec){    String origin = scriptExecutionContext()->securityOrigin()->toString();    KURL url = m_url;    url.setUser(String());    url.setPass(String());    if (!PreflightResultCache::shared().canSkipPreflight(origin, url, m_includeCredentials, m_method, m_requestHeaders)) {        m_inPreflight = true;        ResourceRequest preflightRequest(url);        preflightRequest.setHTTPMethod("OPTIONS");        preflightRequest.setHTTPHeaderField("Origin", origin);        preflightRequest.setHTTPHeaderField("Access-Control-Request-Method", m_method);        if (m_requestHeaders.size() > 0) {            Vector<UChar> headerBuffer;            HTTPHeaderMap::const_iterator it = m_requestHeaders.begin();            append(headerBuffer, it->first);            ++it;            HTTPHeaderMap::const_iterator end = m_requestHeaders.end();            for (; it != end; ++it) {                headerBuffer.append(',');                headerBuffer.append(' ');                append(headerBuffer, it->first);            }            preflightRequest.setHTTPHeaderField("Access-Control-Request-Headers", String::adopt(headerBuffer));            preflightRequest.addHTTPHeaderFields(m_requestHeaders);        }        if (m_async) {            loadRequestAsynchronously(preflightRequest);            return;        }        loadRequestSynchronously(preflightRequest, ec);        m_inPreflight = false;        if (ec)            return;    }    // Send the actual request.    ResourceRequest request(url);    request.setHTTPMethod(m_method);    request.setAllowHTTPCookies(m_includeCredentials);    request.setHTTPHeaderField("Origin", origin);    if (m_requestHeaders.size() > 0)        request.addHTTPHeaderFields(m_requestHeaders);    if (m_requestEntityBody) {        ASSERT(m_method != "GET");        request.setHTTPBody(m_requestEntityBody.release());    }    if (m_async) {        loadRequestAsynchronously(request);        return;    }    loadRequestSynchronously(request, ec);}void XMLHttpRequest::handleAsynchronousPreflightResult(){    ASSERT(m_inPreflight);    ASSERT(m_async);    m_inPreflight = false;    KURL url = m_url;    url.setUser(String());    url.setPass(String());    ResourceRequest request(url);    request.setHTTPMethod(m_method);    request.setAllowHTTPCookies(m_includeCredentials);    request.setHTTPOrigin(scriptExecutionContext()->securityOrigin()->toString());    if (m_requestHeaders.size() > 0)        request.addHTTPHeaderFields(m_requestHeaders);    if (m_requestEntityBody) {        ASSERT(m_method != "GET");        request.setHTTPBody(m_requestEntityBody.release());    }    loadRequestAsynchronously(request);}void XMLHttpRequest::loadRequestSynchronously(ResourceRequest& request, ExceptionCode& ec){    ASSERT(!m_async);    m_loader = 0;    m_exceptionCode = 0;    ThreadableLoader::loadResourceSynchronously(scriptExecutionContext(), request, *this);    if (!m_exceptionCode && m_error)        m_exceptionCode = XMLHttpRequestException::NETWORK_ERR;    ec = m_exceptionCode;}void XMLHttpRequest::loadRequestAsynchronously(ResourceRequest& request){    ASSERT(m_async);    m_exceptionCode = 0;    // SubresourceLoader::create can return null here, for example if we're no longer attached to a page.    // This is true while running onunload handlers.    // FIXME: 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?    // We need to keep content sniffing enabled for local files due to CFNetwork not providing a MIME type    // for local files otherwise, <rdar://problem/5671813>.    LoadCallbacks callbacks = m_inPreflight ? DoNotSendLoadCallbacks : SendLoadCallbacks;    ContentSniff contentSniff = request.url().isLocalFile() ? SniffContent : DoNotSniffContent;    if (m_upload)        request.setReportUploadProgress(true);    m_loader = ThreadableLoader::create(scriptExecutionContext(), this, request, callbacks, contentSniff);    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);    }}void XMLHttpRequest::abort(){    // internalAbort() calls dropProtection(), which may release the last reference.    RefPtr<XMLHttpRequest> protect(this);    bool sendFlag = m_loader;    internalAbort();    // Clear headers as required by the spec    m_requestHeaders.clear();        if ((m_state <= OPENED && !sendFlag) || m_state == DONE)        m_state = UNSENT;     else {        ASSERT(!m_loader);        changeState(DONE);        m_state = UNSENT;    }    dispatchAbortEvent();    if (!m_uploadComplete) {        m_uploadComplete = true;        if (m_upload)            m_upload->dispatchAbortEvent();    }}void XMLHttpRequest::internalAbort(){    bool hadLoader = m_loader;    m_error = true;    // FIXME: when we add the support for multi-part XHR, we will have to think be careful with this initialization.    m_receivedLength = 0;    if (hadLoader) {        m_loader->cancel();        m_loader = 0;    }    m_decoder = 0;    if (hadLoader)        dropProtection();}void XMLHttpRequest::clearResponse(){    m_response = ResourceResponse();    m_responseText = "";    m_createdDocument = false;    m_responseXML = 0;}void XMLHttpRequest::clearRequest(){    m_requestHeaders.clear();    m_requestEntityBody = 0;}void XMLHttpRequest::genericError(){    clearResponse();    clearRequest();    m_error = true;    // The spec says we should "Synchronously switch the state to DONE." and then "Synchronously dispatch a readystatechange event on the object"    // but this does not match Firefox.}void XMLHttpRequest::networkError(){    genericError();    dispatchErrorEvent();    if (!m_uploadComplete) {        m_uploadComplete = true;        if (m_upload)            m_upload->dispatchErrorEvent();    }}void XMLHttpRequest::abortError(){    genericError();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -