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

📄 resourcehandlesoup.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 2008 Alp Toker <alp@atoker.com> * Copyright (C) 2008 Xan Lopez <xan@gnome.org> * Copyright (C) 2008 Collabora Ltd. * Copyright (C) 2009 Holger Hans Peter Freyther * Copyright (C) 2009 Gustavo Noronha Silva <gns@gnome.org> * Copyright (C) 2009 Christian Dywan <christian@imendio.com> * Copyright (C) 2009 Igalia S.L. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB.  If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */#include "config.h"#include "ResourceHandle.h"#include "Base64.h"#include "CookieJarSoup.h"#include "ChromeClient.h"#include "CString.h"#include "DocLoader.h"#include "Frame.h"#include "HTTPParsers.h"#include "Logging.h"#include "MIMETypeRegistry.h"#include "NotImplemented.h"#include "Page.h"#include "ResourceError.h"#include "ResourceHandleClient.h"#include "ResourceHandleInternal.h"#include "ResourceResponse.h"#include "TextEncoding.h"#include <errno.h>#include <fcntl.h>#include <gio/gio.h>#include <gtk/gtk.h>#include <libsoup/soup.h>#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#if PLATFORM(GTK)#define USE_GLIB_BASE64#endifnamespace WebCore {class WebCoreSynchronousLoader : public ResourceHandleClient, Noncopyable {public:    WebCoreSynchronousLoader(ResourceError&, ResourceResponse &, Vector<char>&);    ~WebCoreSynchronousLoader();    virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse&);    virtual void didReceiveData(ResourceHandle*, const char*, int, int lengthReceived);    virtual void didFinishLoading(ResourceHandle*);    virtual void didFail(ResourceHandle*, const ResourceError&);    void run();private:    ResourceError& m_error;    ResourceResponse& m_response;    Vector<char>& m_data;    bool m_finished;    GMainLoop* m_mainLoop;};WebCoreSynchronousLoader::WebCoreSynchronousLoader(ResourceError& error, ResourceResponse& response, Vector<char>& data)    : m_error(error)    , m_response(response)    , m_data(data)    , m_finished(false){    m_mainLoop = g_main_loop_new(0, false);}WebCoreSynchronousLoader::~WebCoreSynchronousLoader(){    g_main_loop_unref(m_mainLoop);}void WebCoreSynchronousLoader::didReceiveResponse(ResourceHandle*, const ResourceResponse& response){    m_response = response;}void WebCoreSynchronousLoader::didReceiveData(ResourceHandle*, const char* data, int length, int){    m_data.append(data, length);}void WebCoreSynchronousLoader::didFinishLoading(ResourceHandle*){    g_main_loop_quit(m_mainLoop);    m_finished = true;}void WebCoreSynchronousLoader::didFail(ResourceHandle* handle, const ResourceError& error){    m_error = error;    didFinishLoading(handle);}void WebCoreSynchronousLoader::run(){    if (!m_finished)        g_main_loop_run(m_mainLoop);}enum{    ERROR_TRANSPORT,    ERROR_UNKNOWN_PROTOCOL,    ERROR_BAD_NON_HTTP_METHOD,    ERROR_UNABLE_TO_OPEN_FILE,};struct FileMapping{    gpointer ptr;    gsize length;};static void freeFileMapping(gpointer data){    FileMapping* fileMapping = static_cast<FileMapping*>(data);    if (fileMapping->ptr != MAP_FAILED)        munmap(fileMapping->ptr, fileMapping->length);    g_slice_free(FileMapping, fileMapping);}static void cleanupGioOperation(ResourceHandleInternal* handle);ResourceHandleInternal::~ResourceHandleInternal(){    if (m_msg) {        g_object_unref(m_msg);        m_msg = 0;    }    cleanupGioOperation(this);    if (m_idleHandler) {        g_source_remove(m_idleHandler);        m_idleHandler = 0;    }}ResourceHandle::~ResourceHandle(){}static void fillResponseFromMessage(SoupMessage* msg, ResourceResponse* response){    SoupMessageHeadersIter iter;    const char* name = 0;    const char* value = 0;    soup_message_headers_iter_init(&iter, msg->response_headers);    while (soup_message_headers_iter_next(&iter, &name, &value))        response->setHTTPHeaderField(name, value);    String contentType = soup_message_headers_get(msg->response_headers, "Content-Type");    char* uri = soup_uri_to_string(soup_message_get_uri(msg), false);    response->setUrl(KURL(uri));    g_free(uri);    response->setMimeType(extractMIMETypeFromMediaType(contentType));    response->setTextEncodingName(extractCharsetFromMediaType(contentType));    response->setExpectedContentLength(soup_message_headers_get_content_length(msg->response_headers));    response->setHTTPStatusCode(msg->status_code);    response->setHTTPStatusText(msg->reason_phrase);    response->setSuggestedFilename(filenameFromHTTPContentDisposition(response->httpHeaderField("Content-Disposition")));}// Called each time the message is going to be sent again except the first time.// It's used mostly to let webkit know about redirects.static void restartedCallback(SoupMessage* msg, gpointer data){    ResourceHandle* handle = static_cast<ResourceHandle*>(data);    if (!handle)        return;    ResourceHandleInternal* d = handle->getInternal();    if (d->m_cancelled)        return;    char* uri = soup_uri_to_string(soup_message_get_uri(msg), false);    String location = String(uri);    g_free(uri);    KURL newURL = KURL(handle->request().url(), location);    ResourceRequest request = handle->request();    ResourceResponse response;    request.setURL(newURL);    fillResponseFromMessage(msg, &response);    if (d->client())        d->client()->willSendRequest(handle, request, response);    d->m_request.setURL(newURL);}static void gotHeadersCallback(SoupMessage* msg, gpointer data){    if (!SOUP_STATUS_IS_SUCCESSFUL(msg->status_code))        return;    // We still don't know anything about Content-Type, so we will try    // sniffing the contents of the file, and then report that we got    // headers    if (!soup_message_headers_get_content_type(msg->response_headers, NULL))        return;    ResourceHandle* handle = static_cast<ResourceHandle*>(data);    if (!handle)        return;    ResourceHandleInternal* d = handle->getInternal();    if (d->m_cancelled)        return;    ResourceHandleClient* client = handle->client();    if (!client)        return;    fillResponseFromMessage(msg, &d->m_response);    client->didReceiveResponse(handle, d->m_response);    d->m_reportedHeaders = true;}static void gotChunkCallback(SoupMessage* msg, SoupBuffer* chunk, gpointer data){    if (!SOUP_STATUS_IS_SUCCESSFUL(msg->status_code))        return;    ResourceHandle* handle = static_cast<ResourceHandle*>(data);    if (!handle)        return;    ResourceHandleInternal* d = handle->getInternal();    if (d->m_cancelled)        return;    ResourceHandleClient* client = handle->client();    if (!client)        return;    if (!d->m_reportedHeaders) {        gboolean uncertain;        char* contentType = g_content_type_guess(d->m_request.url().lastPathComponent().utf8().data(), reinterpret_cast<const guchar*>(chunk->data), chunk->length, &uncertain);        soup_message_headers_set_content_type(msg->response_headers, contentType, NULL);        g_free(contentType);        fillResponseFromMessage(msg, &d->m_response);        client->didReceiveResponse(handle, d->m_response);        d->m_reportedHeaders = true;    }    client->didReceiveData(handle, chunk->data, chunk->length, false);}// Called at the end of the message, with all the necessary about the last informations.// Doesn't get called for redirects.static void finishedCallback(SoupSession *session, SoupMessage* msg, gpointer data){    RefPtr<ResourceHandle>handle = adoptRef(static_cast<ResourceHandle*>(data));    // TODO: maybe we should run this code even if there's no client?    if (!handle)        return;    ResourceHandleInternal* d = handle->getInternal();    ResourceHandleClient* client = handle->client();    if (!client)        return;    if (d->m_cancelled)        return;    if (SOUP_STATUS_IS_TRANSPORT_ERROR(msg->status_code)) {        char* uri = soup_uri_to_string(soup_message_get_uri(msg), false);        ResourceError error("webkit-network-error", ERROR_TRANSPORT, uri, String::fromUTF8(msg->reason_phrase));        g_free(uri);        client->didFail(handle.get(), error);        return;    }    if (!SOUP_STATUS_IS_SUCCESSFUL(msg->status_code)) {        fillResponseFromMessage(msg, &d->m_response);        client->didReceiveResponse(handle.get(), d->m_response);        // WebCore might have cancelled the job in the while        if (d->m_cancelled)            return;        if (msg->response_body->data)            client->didReceiveData(handle.get(), msg->response_body->data, msg->response_body->length, true);    }    client->didFinishLoading(handle.get());}// parseDataUrl() is taken from the CURL http backend.static gboolean parseDataUrl(gpointer callback_data){    ResourceHandle* handle = static_cast<ResourceHandle*>(callback_data);    ResourceHandleClient* client = handle->client();    handle->getInternal()->m_idleHandler = 0;    ASSERT(client);    if (!client)        return false;    String url = handle->request().url().string();    ASSERT(url.startsWith("data:", false));    int index = url.find(',');    if (index == -1) {        client->cannotShowURL(handle);        return false;    }    String mediaType = url.substring(5, index - 5);    String data = url.substring(index + 1);    bool isBase64 = mediaType.endsWith(";base64", false);    if (isBase64)        mediaType = mediaType.left(mediaType.length() - 7);    if (mediaType.isEmpty())        mediaType = "text/plain;charset=US-ASCII";    String mimeType = extractMIMETypeFromMediaType(mediaType);    String charset = extractCharsetFromMediaType(mediaType);    ResourceResponse response;    response.setMimeType(mimeType);    if (isBase64) {        data = decodeURLEscapeSequences(data);        response.setTextEncodingName(charset);        client->didReceiveResponse(handle, response);        // Use the GLib Base64 if available, since WebCore's decoder isn't        // general-purpose and fails on Acid3 test 97 (whitespace).#ifdef USE_GLIB_BASE64        size_t outLength = 0;        char* outData = 0;        outData = reinterpret_cast<char*>(g_base64_decode(data.utf8().data(), &outLength));        if (outData && outLength > 0)            client->didReceiveData(handle, outData, outLength, 0);        g_free(outData);#else        Vector<char> out;        if (base64Decode(data.latin1().data(), data.latin1().length(), out) && out.size() > 0)            client->didReceiveData(handle, out.data(), out.size(), 0);#endif    } else {        // We have to convert to UTF-16 early due to limitations in KURL        data = decodeURLEscapeSequences(data, TextEncoding(charset));        response.setTextEncodingName("UTF-16");        client->didReceiveResponse(handle, response);        if (data.length() > 0)            client->didReceiveData(handle, reinterpret_cast<const char*>(data.characters()), data.length() * sizeof(UChar), 0);    }    client->didFinishLoading(handle);    return false;}bool ResourceHandle::startData(String urlString){    ResourceHandleInternal* d = this->getInternal();    // If parseDataUrl is called synchronously the job is not yet effectively started    // and webkit won't never know that the data has been parsed even didFinishLoading is called.    d->m_idleHandler = g_idle_add(parseDataUrl, this);    return true;}static SoupSession* createSoupSession(){    return soup_session_async_new();}static void ensureSessionIsInitialized(SoupSession* session){    if (g_object_get_data(G_OBJECT(session), "webkit-init"))        return;    SoupCookieJar* jar = reinterpret_cast<SoupCookieJar*>(soup_session_get_feature(session, SOUP_TYPE_COOKIE_JAR));    if (!jar)        soup_session_add_feature(session, SOUP_SESSION_FEATURE(defaultCookieJar()));    else        setDefaultCookieJar(jar);    if (!soup_session_get_feature(session, SOUP_TYPE_LOGGER) && LogNetwork.state == WTFLogChannelOn) {        SoupLogger* logger = soup_logger_new(static_cast<SoupLoggerLogLevel>(SOUP_LOGGER_LOG_BODY), -1);        soup_logger_attach(logger, session);        g_object_unref(logger);    }    g_object_set_data(G_OBJECT(session), "webkit-init", reinterpret_cast<void*>(0xdeadbeef));}bool ResourceHandle::startHttp(String urlString){    SoupSession* session = defaultSession();    ensureSessionIsInitialized(session);    SoupMessage* msg;    msg = soup_message_new(request().httpMethod().utf8().data(), urlString.utf8().data());    g_signal_connect(msg, "restarted", G_CALLBACK(restartedCallback), this);    g_signal_connect(msg, "got-headers", G_CALLBACK(gotHeadersCallback), this);    g_signal_connect(msg, "got-chunk", G_CALLBACK(gotChunkCallback), this);

⌨️ 快捷键说明

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