📄 webkitdownload.cpp
字号:
/* * Copyright (C) 2008 Collabora Ltd. * Copyright (C) 2009 Gustavo Noronha Silva <gns@gnome.org> * * 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 "CString.h"#include "Noncopyable.h"#include "NotImplemented.h"#include "ResourceHandleClient.h"#include "ResourceRequest.h"#include "ResourceResponse.h"#include "webkitdownload.h"#include "webkitmarshal.h"#include "webkitprivate.h"#include <glib/gstdio.h>using namespace WebKit;using namespace WebCore;class DownloadClient : Noncopyable, public ResourceHandleClient { public: DownloadClient(WebKitDownload*); virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse&); virtual void didReceiveData(ResourceHandle*, const char*, int, int); virtual void didFinishLoading(ResourceHandle*); virtual void didFail(ResourceHandle*, const ResourceError&); virtual void wasBlocked(ResourceHandle*); virtual void cannotShowURL(ResourceHandle*); private: WebKitDownload* m_download;};extern "C" {#define WEBKIT_DOWNLOAD_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), WEBKIT_TYPE_DOWNLOAD, WebKitDownloadPrivate))struct _WebKitDownloadPrivate { gchar* destinationURI; gchar* suggestedFilename; guint currentSize; GTimer* timer; WebKitDownloadState state; GFileOutputStream* outputStream; DownloadClient* downloadClient; WebKitNetworkRequest* networkRequest; ResourceResponse* networkResponse; RefPtr<ResourceHandle> resourceHandle;};enum { // Normal signals. ERROR, LAST_SIGNAL};static guint webkit_download_signals[LAST_SIGNAL] = { 0 };enum { PROP_0, PROP_NETWORK_REQUEST, PROP_DESTINATION_URI, PROP_SUGGESTED_FILENAME, PROP_PROGRESS, PROP_CURRENT_SIZE, PROP_TOTAL_SIZE};G_DEFINE_TYPE(WebKitDownload, webkit_download, G_TYPE_OBJECT);static void webkit_download_dispose(GObject* object){ WebKitDownload* download = WEBKIT_DOWNLOAD(object); WebKitDownloadPrivate* priv = download->priv; if (priv->outputStream) { g_object_unref(priv->outputStream); priv->outputStream = NULL; } if (priv->networkRequest) { g_object_unref(priv->networkRequest); priv->networkRequest = NULL; } G_OBJECT_CLASS(webkit_download_parent_class)->dispose(object);}static void webkit_download_finalize(GObject* object){ WebKitDownload* download = WEBKIT_DOWNLOAD(object); WebKitDownloadPrivate* priv = download->priv; // We don't call webkit_download_cancel() because we don't want to emit // signals when finalizing an object. if (priv->resourceHandle) { if (priv->state == WEBKIT_DOWNLOAD_STATE_STARTED) { priv->resourceHandle->setClient(0); priv->resourceHandle->cancel(); } priv->resourceHandle.release(); } delete priv->downloadClient; delete priv->networkResponse; // The download object may never have _start called on it, so we // need to make sure timer is non-NULL. if (priv->timer) g_timer_destroy(priv->timer); g_free(priv->destinationURI); g_free(priv->suggestedFilename); G_OBJECT_CLASS(webkit_download_parent_class)->finalize(object);}static void webkit_download_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec){ WebKitDownload* download = WEBKIT_DOWNLOAD(object); switch(prop_id) { case PROP_NETWORK_REQUEST: g_value_set_object(value, webkit_download_get_network_request(download)); break; case PROP_DESTINATION_URI: g_value_set_string(value, webkit_download_get_destination_uri(download)); break; case PROP_SUGGESTED_FILENAME: g_value_set_string(value, webkit_download_get_suggested_filename(download)); break; case PROP_PROGRESS: g_value_set_double(value, webkit_download_get_progress(download)); break; case PROP_CURRENT_SIZE: g_value_set_uint64(value, webkit_download_get_current_size(download)); break; case PROP_TOTAL_SIZE: g_value_set_uint64(value, webkit_download_get_total_size(download)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); }}static void webkit_download_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec *pspec){ WebKitDownload* download = WEBKIT_DOWNLOAD(object); WebKitDownloadPrivate* priv = download->priv; switch(prop_id) { case PROP_NETWORK_REQUEST: priv->networkRequest = WEBKIT_NETWORK_REQUEST(g_value_dup_object(value)); // This is safe as network-request is a construct only property and // suggestedFilename is initially null. priv->suggestedFilename = g_path_get_basename(webkit_network_request_get_uri(priv->networkRequest)); break; case PROP_DESTINATION_URI: webkit_download_set_destination_uri(download, g_value_get_string(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); }}static void webkit_download_class_init(WebKitDownloadClass* downloadClass){ GObjectClass* objectClass = G_OBJECT_CLASS(downloadClass); objectClass->dispose = webkit_download_dispose; objectClass->finalize = webkit_download_finalize; objectClass->get_property = webkit_download_get_property; objectClass->set_property = webkit_download_set_property; /** * WebKitDownload::error: * @download: the object on which the signal is emitted * @current_bytes: the current count of bytes downloaded * @total_bytes: the total bytes count in the downloaded file, aka file size. * * Indicates an error in the download. * * Since: 1.1.2 */ webkit_download_signals[ERROR] = g_signal_new("error", G_TYPE_FROM_CLASS(downloadClass), (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), 0, g_signal_accumulator_true_handled, NULL, webkit_marshal_BOOLEAN__INT_INT_STRING, G_TYPE_BOOLEAN, 3, G_TYPE_INT, G_TYPE_INT, G_TYPE_STRING); // Properties. /** * WebKitDownload:network-request * * The #WebKitNetworkRequest instance associated with the download. * * Since: 1.1.2 */ g_object_class_install_property(objectClass, PROP_NETWORK_REQUEST, g_param_spec_object("network-request", "Network Request", "The network request for the URI that should be downloaded", WEBKIT_TYPE_NETWORK_REQUEST, (GParamFlags)(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY))); /** * WebKitDownload:destination-uri * * The URI of the save location for this download. * * Since: 1.1.2 */ g_object_class_install_property(objectClass, PROP_DESTINATION_URI, g_param_spec_string("destination-uri", "Destination URI", "The destination URI where to save the file", "", WEBKIT_PARAM_READWRITE)); /** * WebKitDownload:suggested-filename * * The file name suggested as default when saving * * Since: 1.1.2 */ g_object_class_install_property(objectClass, PROP_SUGGESTED_FILENAME, g_param_spec_string("suggested-filename", "Suggested Filename", "The filename suggested as default when saving", "", WEBKIT_PARAM_READABLE)); /** * WebKitDownload:progress: * * Determines the current progress of the download. * * Since: 1.1.2 */ g_object_class_install_property(objectClass, PROP_PROGRESS, g_param_spec_double("progress", "Progress", "Determines the current progress of the download", 0.0, 1.0, 1.0, WEBKIT_PARAM_READABLE)); /** * WebKitDownload:current-size * * The length of the data already downloaded * * Since: 1.1.2 */ g_object_class_install_property(objectClass, PROP_CURRENT_SIZE, g_param_spec_uint64("current-size", "Current Size", "The length of the data already downloaded", 0, G_MAXUINT64, 0, WEBKIT_PARAM_READABLE)); /** * WebKitDownload:total-size * * The total size of the file * * Since: 1.1.2 */ g_object_class_install_property(objectClass, PROP_CURRENT_SIZE, g_param_spec_uint64("total-size", "Total Size", "The total size of the file", 0, G_MAXUINT64, 0, WEBKIT_PARAM_READABLE)); g_type_class_add_private(downloadClass, sizeof(WebKitDownloadPrivate));}static void webkit_download_init(WebKitDownload* download){ WebKitDownloadPrivate* priv = WEBKIT_DOWNLOAD_GET_PRIVATE(download); download->priv = priv; priv->downloadClient = new DownloadClient(download); priv->currentSize = 0; priv->state = WEBKIT_DOWNLOAD_STATE_CREATED;}/** * webkit_download_new: * @request: a #WebKitNetworkRequest * * Creates a new #WebKitDownload object for the given * #WebKitNetworkRequest object. * * Returns: the new #WebKitDownload * * Since: 1.1.2 */WebKitDownload* webkit_download_new(WebKitNetworkRequest* request){ g_return_val_if_fail(request, NULL); return WEBKIT_DOWNLOAD(g_object_new(WEBKIT_TYPE_DOWNLOAD, "network-request", request, NULL));}static gboolean webkit_download_open_stream_for_uri(WebKitDownload* download, const gchar* uri, gboolean append=FALSE){ g_return_val_if_fail(uri, FALSE); WebKitDownloadPrivate* priv = download->priv; GFile* file = g_file_new_for_uri(uri); GError* error = NULL; if (append) priv->outputStream = g_file_append_to(file, G_FILE_CREATE_NONE, NULL, &error); else priv->outputStream = g_file_replace(file, NULL, TRUE, G_FILE_CREATE_NONE, NULL, &error); g_object_unref(file); if (error) { gboolean handled; g_signal_emit_by_name(download, "error", 0, WEBKIT_DOWNLOAD_ERROR_DESTINATION, error->message, &handled); g_error_free(error); return FALSE; } return TRUE;}static void webkit_download_close_stream(WebKitDownload* download){ WebKitDownloadPrivate* priv = download->priv; if (priv->outputStream) { g_object_unref(priv->outputStream); priv->outputStream = NULL; }}/** * webkit_download_start: * @download: the #WebKitDownload * * Initiates the download. Notice that you must have set the * destination-uri property before calling this method. * * Since: 1.1.2 */void webkit_download_start(WebKitDownload* download){ g_return_if_fail(WEBKIT_IS_DOWNLOAD(download)); WebKitDownloadPrivate* priv = download->priv; g_return_if_fail(priv->destinationURI); g_return_if_fail(priv->state == WEBKIT_DOWNLOAD_STATE_CREATED); g_return_if_fail(priv->timer == NULL); if (priv->resourceHandle) priv->resourceHandle->setClient(priv->downloadClient); else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -