diff options
author | Gustavo Noronha Silva <gns@gnome.org> | 2009-08-21 01:59:07 +0800 |
---|---|---|
committer | Gustavo Noronha Silva <gns@gnome.org> | 2009-09-15 10:06:09 +0800 |
commit | def58964b0e7fa099b524a6e8bc34bed893118f7 (patch) | |
tree | 2180af55b166e386fe7b07df5e7610d9ab3baa3d | |
parent | bd03e748e07dd300015fdfee111420162f346e5f (diff) | |
download | gsoc2013-epiphany-def58964b0e7fa099b524a6e8bc34bed893118f7.tar gsoc2013-epiphany-def58964b0e7fa099b524a6e8bc34bed893118f7.tar.gz gsoc2013-epiphany-def58964b0e7fa099b524a6e8bc34bed893118f7.tar.bz2 gsoc2013-epiphany-def58964b0e7fa099b524a6e8bc34bed893118f7.tar.lz gsoc2013-epiphany-def58964b0e7fa099b524a6e8bc34bed893118f7.tar.xz gsoc2013-epiphany-def58964b0e7fa099b524a6e8bc34bed893118f7.tar.zst gsoc2013-epiphany-def58964b0e7fa099b524a6e8bc34bed893118f7.zip |
Implement saving the page using the DataSource API
Bug #562611
-rw-r--r-- | embed/ephy-web-view.c | 239 | ||||
-rw-r--r-- | embed/ephy-web-view.h | 2 | ||||
-rw-r--r-- | src/window-commands.c | 49 |
3 files changed, 275 insertions, 15 deletions
diff --git a/embed/ephy-web-view.c b/embed/ephy-web-view.c index f95c4b1e1..5f1f49af0 100644 --- a/embed/ephy-web-view.c +++ b/embed/ephy-web-view.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* - * Copyright © 2008 Gustavo Noronha Silva + * Copyright © 2008, 2009 Gustavo Noronha Silva * Copyright © 2009 Igalia S.L. * * This program is free software; you can redistribute it and/or modify @@ -2127,3 +2127,240 @@ ephy_web_view_get_title_composite (EphyWebView *view) return title != NULL ? title : ""; } +static void +ephy_web_view_save_sub_resource_start (GList *subresources, char *destination_uri); + +static void +ephy_web_view_close_cb (GOutputStream *ostream, GAsyncResult *result, GString *data) +{ + GList *subresources; + char *sub_destination_uri; + GError *error = NULL; + + subresources = (GList*)g_object_get_data (G_OBJECT (ostream), + "ephy-web-view-save-subresources"); + + sub_destination_uri = (char*)g_object_get_data (G_OBJECT (ostream), + "ephy-web-view-save-dest-uri"); + + g_output_stream_close_finish (ostream, result, &error); + g_object_unref (ostream); + + if (error) { + g_list_free (subresources); + g_free (sub_destination_uri); + g_warning ("Unable to write to file: %s", error->message); + g_error_free (error); + return; + } + + if (!subresources || !subresources->next) { + g_list_free (subresources); + g_free (sub_destination_uri); + return; + } + + subresources = subresources->next; + ephy_web_view_save_sub_resource_start (subresources, sub_destination_uri); +} + +static void +ephy_web_view_save_write_cb (GOutputStream *ostream, GAsyncResult *result, GString *data) +{ + GError *error = NULL; + gssize written; + + written = g_output_stream_write_finish (ostream, result, &error); + if (error) { + GList *subresources; + char *sub_destination_uri; + + subresources = (GList*)g_object_get_data (G_OBJECT (ostream), + "ephy-web-view-save-subresources"); + g_list_free (subresources); + + sub_destination_uri = (char*)g_object_get_data (G_OBJECT (ostream), + "ephy-web-view-save-dest-uri"); + g_free (sub_destination_uri); + + g_string_free (data, FALSE); + g_object_unref (ostream); + + g_warning ("Unable to write to file: %s", error->message); + + g_error_free (error); + return; + } + + if (written == data->len) { + g_string_free (data, FALSE); + g_output_stream_close_async (ostream, G_PRIORITY_DEFAULT, NULL, + (GAsyncReadyCallback)ephy_web_view_close_cb, + NULL); + return; + } + + data->len -= written; + data->str += written; + + g_output_stream_write_async (ostream, + data->str, data->len, + G_PRIORITY_DEFAULT, NULL, + (GAsyncReadyCallback)ephy_web_view_save_write_cb, + data); +} + +static void +ephy_web_view_save_replace_cb (GFile *file, GAsyncResult *result, GString *const_data) +{ + GFileOutputStream *ostream; + GList *subresources; + char *sub_destination_uri; + GString *data; + GError *error = NULL; + + subresources = (GList*)g_object_get_data (G_OBJECT (file), + "ephy-web-view-save-subresources"); + + sub_destination_uri = (char*)g_object_get_data (G_OBJECT (file), + "ephy-web-view-save-dest-uri"); + + ostream = g_file_replace_finish (file, result, &error); + if (error) { + g_warning ("Failed to save page: %s", error->message); + g_list_free (subresources); + g_free (sub_destination_uri); + g_error_free (error); + return; + } + + if (const_data) { + data = g_string_sized_new (const_data->len); + data->str = const_data->str; + data->len = const_data->len; + } else + data = g_string_new (""); + + /* If we have subresources to handle, pass the information along */ + if (subresources) { + g_object_set_data (G_OBJECT (ostream), + "ephy-web-view-save-subresources", + subresources); + + g_object_set_data (G_OBJECT (ostream), + "ephy-web-view-save-dest-uri", + sub_destination_uri); + } + + g_output_stream_write_async (G_OUTPUT_STREAM (ostream), + data->str, data->len, + G_PRIORITY_DEFAULT, NULL, + (GAsyncReadyCallback)ephy_web_view_save_write_cb, + data); +} + +static void +ephy_web_view_save_sub_resource_start (GList *subresources, char *destination_uri) +{ + WebKitWebResource *resource; + GFile *file; + char *resource_uri; + char *resource_name; + const GString *data; + + resource = WEBKIT_WEB_RESOURCE (subresources->data); + + resource_uri = (char*)webkit_web_resource_get_uri (resource); + resource_name = g_path_get_basename (resource_uri); + + resource_uri = g_strdup_printf ("%s/%s", + destination_uri, + resource_name); + + file = g_file_new_for_uri (resource_uri); + g_free (resource_uri); + + g_object_set_data (G_OBJECT (file), + "ephy-web-view-save-dest-uri", + destination_uri); + + g_object_set_data (G_OBJECT (file), + "ephy-web-view-save-subresources", + subresources); + + data = webkit_web_resource_get_data (resource); + + g_file_replace_async (file, NULL, FALSE, + G_FILE_CREATE_REPLACE_DESTINATION|G_FILE_CREATE_PRIVATE, + G_PRIORITY_DEFAULT, NULL, + (GAsyncReadyCallback)ephy_web_view_save_replace_cb, + (GString*)data); + + g_object_unref (file); +} + +static void +ephy_web_view_save_sub_resources (EphyWebView *view, const char *uri, GList *subresources) +{ + GFile *file; + char *filename; + char *dotpos; + char *directory_uri; + char *destination_uri; + GError *error = NULL; + + /* filename of the main resource without extension */ + filename = g_path_get_basename (uri); + dotpos = g_strrstr (filename, "."); + if (dotpos) + *dotpos = '\0'; + + directory_uri = g_path_get_dirname (uri); + destination_uri = g_strdup_printf (_("%s/%s Files"), directory_uri, filename); + + g_free (filename); + g_free (directory_uri); + + file = g_file_new_for_uri (destination_uri); + if (!g_file_make_directory (file, NULL, &error)) { + g_warning ("Could not create directory: %s", error->message); + g_error_free (error); + g_object_unref (file); + return; + } + g_object_unref (file); + + /* Now, let's start saving sub resources */ + ephy_web_view_save_sub_resource_start (subresources, destination_uri); +} + +void +ephy_web_view_save (EphyWebView *view, const char *uri) +{ + WebKitWebFrame *frame; + WebKitWebDataSource *data_source; + GList *subresources; + const GString *data; + GFile *file; + + /* Save main resource */ + frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW(view)); + data_source = webkit_web_frame_get_data_source (frame); + data = webkit_web_data_source_get_data (data_source); + + file = g_file_new_for_uri (uri); + g_file_replace_async (file, NULL, FALSE, + G_FILE_CREATE_REPLACE_DESTINATION|G_FILE_CREATE_PRIVATE, + G_PRIORITY_DEFAULT, NULL, + (GAsyncReadyCallback)ephy_web_view_save_replace_cb, + (GString*)data); + + g_object_unref (file); + + /* If subresources exist, save them */ + subresources = webkit_web_data_source_get_subresources (data_source); + if (!subresources) + return; + + ephy_web_view_save_sub_resources (view, uri, subresources); +} diff --git a/embed/ephy-web-view.h b/embed/ephy-web-view.h index d50bf4fa1..29f1bd34b 100644 --- a/embed/ephy-web-view.h +++ b/embed/ephy-web-view.h @@ -229,6 +229,8 @@ void ephy_web_view_set_loading_title (EphyWebView gboolean is_address); void ephy_web_view_popups_manager_reset (EphyWebView *view); +void ephy_web_view_save (EphyWebView *view, + const char *uri); G_END_DECLS diff --git a/src/window-commands.c b/src/window-commands.c index e6790c754..b3d437354 100644 --- a/src/window-commands.c +++ b/src/window-commands.c @@ -276,6 +276,32 @@ open_response_cb (GtkDialog *dialog, int response, EphyWindow *window) gtk_widget_destroy (GTK_WIDGET (dialog)); } +static void +save_response_cb (GtkDialog *dialog, int response, EphyEmbed *embed) +{ + if (response == GTK_RESPONSE_ACCEPT) + { + char *uri, *converted; + + uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog)); + if (uri != NULL) + { + converted = g_filename_to_utf8 (uri, -1, NULL, NULL, NULL); + + if (converted != NULL) + { + EphyWebView *web_view = ephy_embed_get_web_view (embed); + ephy_web_view_save (web_view, converted); + } + + g_free (converted); + g_free (uri); + } + } + + gtk_widget_destroy (GTK_WIDGET (dialog)); +} + void window_cmd_file_open (GtkAction *action, EphyWindow *window) @@ -299,26 +325,21 @@ window_cmd_file_save_as (GtkAction *action, EphyWindow *window) { EphyEmbed *embed; - EphyEmbedPersist *persist; + EphyFileChooser *dialog; embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window)); g_return_if_fail (embed != NULL); - persist = EPHY_EMBED_PERSIST - (g_object_new (EPHY_TYPE_EMBED_PERSIST, NULL)); - - ephy_embed_persist_set_embed (persist, embed); - ephy_embed_persist_set_fc_title (persist, _("Save As")); - ephy_embed_persist_set_fc_parent (persist,GTK_WINDOW (window)); - - ephy_embed_persist_set_flags - (persist, EPHY_EMBED_PERSIST_MAINDOC | EPHY_EMBED_PERSIST_ASK_DESTINATION); - ephy_embed_persist_set_persist_key - (persist, CONF_STATE_SAVE_DIR); + dialog = ephy_file_chooser_new (_("Save"), + GTK_WIDGET (window), + GTK_FILE_CHOOSER_ACTION_SAVE, + CONF_STATE_SAVE_DIR, + EPHY_FILE_FILTER_ALL_SUPPORTED); - ephy_embed_persist_save (persist); + g_signal_connect (dialog, "response", + G_CALLBACK (save_response_cb), embed); - g_object_unref (G_OBJECT(persist)); + gtk_widget_show (GTK_WIDGET (dialog)); } void |