diff options
-rw-r--r-- | data/glade/epiphany.ui | 80 | ||||
-rw-r--r-- | embed/Makefile.am | 6 | ||||
-rw-r--r-- | embed/downloader-view.c | 1022 | ||||
-rw-r--r-- | embed/downloader-view.h | 84 | ||||
-rw-r--r-- | embed/ephy-download.c | 965 | ||||
-rw-r--r-- | embed/ephy-download.h | 115 | ||||
-rw-r--r-- | embed/ephy-embed-persist.c | 911 | ||||
-rw-r--r-- | embed/ephy-embed-persist.h | 132 | ||||
-rw-r--r-- | embed/ephy-embed-shell.c | 144 | ||||
-rw-r--r-- | embed/ephy-embed-shell.h | 16 | ||||
-rw-r--r-- | embed/ephy-embed.c | 476 | ||||
-rw-r--r-- | lib/ephy-marshal.list | 1 | ||||
-rw-r--r-- | po/POTFILES.in | 3 | ||||
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/ephy-session.c | 21 | ||||
-rw-r--r-- | src/ephy-shell.c | 1 | ||||
-rw-r--r-- | src/ephy-window.c | 1 | ||||
-rw-r--r-- | src/epiphany.h.in | 1 | ||||
-rw-r--r-- | src/popup-commands.c | 160 | ||||
-rw-r--r-- | src/window-commands.c | 1 | ||||
-rw-r--r-- | tests/Makefile.am | 6 | ||||
-rw-r--r-- | tests/ephy-download.c | 207 | ||||
-rw-r--r-- | tests/ephy-embed-persist.c | 315 |
23 files changed, 1494 insertions, 3178 deletions
diff --git a/data/glade/epiphany.ui b/data/glade/epiphany.ui index f8023a290..08c67b4a5 100644 --- a/data/glade/epiphany.ui +++ b/data/glade/epiphany.ui @@ -454,84 +454,4 @@ <action-widget response="-11">encoding_help_button</action-widget> </action-widgets> </object> - <object class="GtkDialog" id="download_manager_dialog"> - <property name="border_width">5</property> - <property name="title" translatable="yes">Downloads</property> - <property name="role">epiphany-download-manager</property> - <property name="default_width">440</property> - <property name="default_height">260</property> - <property name="type_hint">normal</property> - <child internal-child="vbox"> - <object class="GtkVBox" id="dialog-vbox31"> - <property name="visible">True</property> - <property name="orientation">vertical</property> - <property name="spacing">2</property> - <child> - <object class="GtkScrolledWindow" id="scrolledwindow1134"> - <property name="height_request">100</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="border_width">5</property> - <property name="hscrollbar_policy">automatic</property> - <property name="vscrollbar_policy">automatic</property> - <property name="shadow_type">in</property> - <child> - <object class="GtkTreeView" id="clist"> - <property name="visible">True</property> - <property name="can_focus">True</property> - </object> - </child> - </object> - <packing> - <property name="position">1</property> - </packing> - </child> - <child internal-child="action_area"> - <object class="GtkHButtonBox" id="dialog-action_area31"> - <property name="visible">True</property> - <property name="layout_style">end</property> - <child> - <object class="GtkButton" id="pause_button"> - <property name="label">DYNAMIC</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="can_default">True</property> - <property name="receives_default">False</property> - <property name="use_underline">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkButton" id="abort_button"> - <property name="label">gtk-stop</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="can_default">True</property> - <property name="receives_default">False</property> - <property name="use_stock">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="pack_type">end</property> - <property name="position">0</property> - </packing> - </child> - </object> - </child> - <action-widgets> - <action-widget response="1">pause_button</action-widget> - <action-widget response="2">abort_button</action-widget> - </action-widgets> - </object> </interface> diff --git a/embed/Makefile.am b/embed/Makefile.am index 51380435f..d517fb480 100644 --- a/embed/Makefile.am +++ b/embed/Makefile.am @@ -8,7 +8,6 @@ header_DATA = \ $(INST_H_FILES) NOINST_H_FILES = \ - downloader-view.h \ ephy-embed-dialog.h \ ephy-encodings.h \ ephy-favicon-cache.h @@ -16,10 +15,10 @@ NOINST_H_FILES = \ INST_H_FILES = \ ephy-adblock.h \ ephy-adblock-manager.h \ + ephy-download.h \ ephy-embed.h \ ephy-embed-container.h \ ephy-embed-event.h \ - ephy-embed-persist.h \ ephy-embed-prefs.h \ ephy-embed-single.h \ ephy-embed-shell.h \ @@ -36,12 +35,11 @@ BUILT_SOURCES = \ libephyembed_la_SOURCES = \ ephy-adblock.c \ ephy-adblock-manager.c \ - downloader-view.c \ + ephy-download.c \ ephy-embed.c \ ephy-embed-container.c \ ephy-embed-dialog.c \ ephy-embed-event.c \ - ephy-embed-persist.c \ ephy-embed-single.c \ ephy-embed-shell.c \ ephy-embed-utils.c \ diff --git a/embed/downloader-view.c b/embed/downloader-view.c deleted file mode 100644 index fd1cfcc3a..000000000 --- a/embed/downloader-view.c +++ /dev/null @@ -1,1022 +0,0 @@ -/* - * Copyright © 2000-2004 Marco Pesenti Gritti - * Copyright © 2003, 2004 Xan Lopez - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "config.h" - -#include "downloader-view.h" -#include "ephy-file-helpers.h" -#include "ephy-object-helpers.h" -#include "ephy-embed-shell.h" -#include "ephy-stock-icons.h" -#include "ephy-gui.h" -#include "ephy-debug.h" -#include "ephy-prefs.h" -#include "ephy-settings.h" - -#include <glib/gi18n.h> -#include <gtk/gtk.h> -#include <gdk/gdkx.h> - -enum -{ - COL_STATUS, - COL_PERCENT, - COL_IMAGE, - COL_FILE, - COL_REMAINING, - COL_DOWNLOAD_OBJECT -}; - -enum -{ - PROGRESS_COL_POS, - FILE_COL_POS, - REMAINING_COL_POS -}; - -#define EPHY_DOWNLOADER_VIEW_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_DOWNLOADER_VIEW, DownloaderViewPrivate)) - -struct _DownloaderViewPrivate -{ - GtkTreeModel *model; - GHashTable *downloads_hash; - - /* Widgets */ - GtkWidget *window; - GtkWidget *treeview; - GtkWidget *pause_button; - GtkWidget *abort_button; - - GtkStatusIcon *status_icon; - gboolean ownref; - - guint source_id; -}; - -enum -{ - RESPONSE_PAUSE = 1, - RESPONSE_STOP = 2 -}; - -static void -downloader_view_build_ui (DownloaderView *dv); -static void -downloader_view_class_init (DownloaderViewClass *klass); -static void -downloader_view_finalize (GObject *object); -static void -downloader_view_init (DownloaderView *dv); -static void -download_dialog_response_cb (GtkWidget *dialog, - int response, - DownloaderView *dv); -static gboolean -download_dialog_delete_event_cb (GtkWidget *window, - GdkEventAny *event, - DownloaderView *dv); - -static void -download_progress_cb (WebKitDownload *download, - GParamSpec *pspec, - DownloaderView *dv); -static void -download_status_changed_cb (WebKitDownload *download, - GParamSpec *pspec, - DownloaderView *dv); -static gboolean -download_error_cb (WebKitDownload *download, gint error_code, gint error_detail, - const gchar *reason, DownloaderView *dv); - -G_DEFINE_TYPE (DownloaderView, downloader_view, EPHY_TYPE_DIALOG) - -static void -downloader_view_class_init (DownloaderViewClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = downloader_view_finalize; - - g_type_class_add_private (object_class, sizeof(DownloaderViewPrivate)); -} - -static void -show_downloader_cb (DownloaderView *dv) -{ - if (!gtk_window_has_toplevel_focus (GTK_WINDOW (dv->priv->window))) - { - ephy_dialog_show (EPHY_DIALOG (dv)); - g_settings_set_boolean (EPHY_SETTINGS_UI, - EPHY_PREFS_UI_DOWNLOADS_HIDDEN, FALSE); - } - else - { - ephy_dialog_hide (EPHY_DIALOG (dv)); - g_settings_set_boolean (EPHY_SETTINGS_UI, - EPHY_PREFS_UI_DOWNLOADS_HIDDEN, TRUE); - } -} - -static void -status_icon_popup_menu_cb (GtkStatusIcon *icon, - guint button, - guint time, - DownloaderView *dv) -{ - GtkWidget *menu, *item; - - menu = gtk_menu_new (); - - /* this opens the downloader window, or brings it to the foreground if already open */ - item = gtk_menu_item_new_with_mnemonic (_("_Show Downloads")); - g_signal_connect_swapped (item, "activate", - G_CALLBACK (show_downloader_cb), dv); - gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); - gtk_widget_show_all (menu); - - gtk_menu_popup (GTK_MENU (menu), NULL, NULL, - gtk_status_icon_position_menu, icon, - button, time); -} - -static void -show_status_icon (DownloaderView *dv) -{ - DownloaderViewPrivate *priv = dv->priv; - - priv->status_icon = gtk_status_icon_new_from_stock (STOCK_DOWNLOAD); - - g_signal_connect_swapped (priv->status_icon, "activate", - G_CALLBACK (show_downloader_cb), dv); - g_signal_connect (priv->status_icon, "popup-menu", - G_CALLBACK (status_icon_popup_menu_cb), dv); - - gtk_status_icon_set_visible (priv->status_icon, TRUE); -} - -static gboolean -remove_download (WebKitDownload *download, - gpointer rowref, - DownloaderView *dv) -{ - WebKitDownloadStatus status; - - g_signal_handlers_disconnect_by_func - (download, G_CALLBACK (download_progress_cb), dv); - - g_signal_handlers_disconnect_by_func - (download, G_CALLBACK (download_status_changed_cb), dv); - - g_signal_handlers_disconnect_by_func - (download, G_CALLBACK (download_error_cb), dv); - - status = webkit_download_get_status (download); - if (status == WEBKIT_DOWNLOAD_STATUS_STARTED) - webkit_download_cancel (download); - - g_object_unref (download); - g_object_unref (dv); - return TRUE; -} - -static void -prepare_close_cb (EphyEmbedShell *shell, - DownloaderView *view) -{ - DownloaderViewPrivate *priv = view->priv; - - /* the downloader owns a ref to itself, no need for another ref */ - - /* hide window already */ - gtk_widget_hide (priv->window); - - /* cancel pending downloads */ - g_hash_table_foreach_remove (priv->downloads_hash, - (GHRFunc) remove_download, view); - - gtk_list_store_clear (GTK_LIST_STORE (priv->model)); - - /* drop the self reference */ - g_object_unref (view); -} - -static void -downloader_view_init (DownloaderView *dv) -{ - _ephy_embed_shell_track_object (embed_shell, G_OBJECT (dv)); - dv->priv = EPHY_DOWNLOADER_VIEW_GET_PRIVATE (dv); - - dv->priv->downloads_hash = g_hash_table_new_full - (g_direct_hash, g_direct_equal, NULL, - (GDestroyNotify)gtk_tree_row_reference_free); - - downloader_view_build_ui (dv); - - dv->priv->ownref = TRUE; - - show_status_icon (dv); - - g_signal_connect_object (embed_shell, "prepare_close", - G_CALLBACK (prepare_close_cb), dv, 0); -} - -static void -downloader_view_finalize (GObject *object) -{ - DownloaderView *dv = EPHY_DOWNLOADER_VIEW (object); - DownloaderViewPrivate *priv = dv->priv; - - if (priv->status_icon != NULL) - { - /* FIXME: this should not be necessary (setting visible to - * FALSE), but we have to work-around a GTK+/gnome-panel bug: - * http://bugzilla.gnome.org/show_bug.cgi?id=340110 - */ - gtk_status_icon_set_visible (priv->status_icon, FALSE); - g_object_unref (priv->status_icon); - priv->status_icon = NULL; - } - - if (priv->source_id != 0) - { - g_source_remove (priv->source_id); - priv->source_id = 0; - } - - g_hash_table_destroy (dv->priv->downloads_hash); - - G_OBJECT_CLASS (downloader_view_parent_class)->finalize (object); -} - -DownloaderView * -downloader_view_new (void) -{ - return EPHY_DOWNLOADER_VIEW (g_object_new (EPHY_TYPE_DOWNLOADER_VIEW, - "persist-position", TRUE, - "default-width", 420, - "default-height", 250, - NULL)); -} - -static char * -format_interval (gdouble interval) -{ - int hours, mins, secs; - - hours = (int) (interval / 3600); - interval -= hours * 3600; - mins = (int) (interval / 60); - interval -= mins * 60; - secs = (int) interval; - - if (hours > 0) - { - return g_strdup_printf (_("%u:%02u.%02u"), hours, mins, secs); - } - else - { - return g_strdup_printf (_("%02u.%02u"), mins, secs); - } -} - -static GtkTreeRowReference * -get_row_from_download (DownloaderView *dv, WebKitDownload *download) -{ - return g_hash_table_lookup (dv->priv->downloads_hash, download); -} - -static void -update_buttons (DownloaderView *dv) -{ - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter iter; - WebKitDownloadStatus status; - WebKitDownload *download; - gboolean pause_enabled = FALSE; - gboolean abort_enabled = FALSE; - gboolean label_pause = TRUE; - GList *selected = NULL; - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(dv->priv->treeview)); - selected = gtk_tree_selection_get_selected_rows (selection, &model); - - if (g_list_length (selected) == 1) - { - if (gtk_tree_model_get_iter (model, &iter, selected->data) != TRUE) - return; - - gtk_tree_model_get (model, &iter, COL_DOWNLOAD_OBJECT, &download, -1); - status = webkit_download_get_status (download); - - /* Pausing is not supported yet */ - pause_enabled = FALSE; - label_pause = TRUE; - abort_enabled = TRUE; - } - else - { - abort_enabled = TRUE; - } - - g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL); - g_list_free (selected); - - gtk_widget_set_sensitive (dv->priv->pause_button, pause_enabled); - gtk_widget_set_sensitive (dv->priv->abort_button, abort_enabled); - gtk_button_set_label (GTK_BUTTON (dv->priv->pause_button), - label_pause ? _("_Pause") : _("_Resume")); -} - -static char * -ephy_download_get_name (WebKitDownload *download) -{ - const char *target; - char *user_destination; - char *result; - - target = webkit_download_get_destination_uri (download); - user_destination = g_object_get_data (G_OBJECT (download), - "user-destination-uri"); - - if (user_destination || target) - { - result = g_path_get_basename (user_destination ? - user_destination : target); - } - else - { - result = g_strdup (_("Unknown")); - } - - return result; -} - -static gdouble -ephy_download_get_remaining_time (WebKitDownload *download) -{ - gint64 total, cur; - gdouble elapsed_time; - gdouble remaining_time; - gdouble per_byte_time; - - total = webkit_download_get_total_size (download); - cur = webkit_download_get_current_size (download); - elapsed_time = webkit_download_get_elapsed_time (download); - - if (cur <= 0) - { - return -1.0; - } - - per_byte_time = elapsed_time / cur; - remaining_time = per_byte_time * (total - cur); - - return remaining_time; -} - -static void -do_open_downloaded_file (DownloaderView *dv, WebKitDownload *download, gboolean open_location) -{ - DownloaderViewPrivate *priv = dv->priv; - GdkDisplay *gdk_display; - const char *destination_uri; - char *user_destination; - GFile *downloaded_file; - - gdk_display = gtk_widget_get_display (priv->window); - - destination_uri = webkit_download_get_destination_uri (download); - user_destination = g_object_get_data (G_OBJECT (download), - "user-destination-uri"); - - downloaded_file = g_file_new_for_uri (user_destination ? - user_destination : destination_uri); - if (open_location) - { - ephy_file_browse_to (downloaded_file, - gdk_x11_display_get_user_time (gdk_display)); - } - else - { - ephy_file_launch_handler (NULL, downloaded_file, - gdk_x11_display_get_user_time (gdk_display)); - } - g_object_unref (downloaded_file); -} - -static void -open_downloaded_file (DownloaderView *dv, WebKitDownload *download) -{ - do_open_downloaded_file (dv, download, FALSE); -} - -static void -open_downloaded_file_location (DownloaderView *dv, WebKitDownload *download) -{ - do_open_downloaded_file (dv, download, TRUE); -} - -static void -update_download_row (DownloaderView *dv, WebKitDownload *download) -{ - GtkTreeRowReference *row_ref; - GtkTreePath *path; - GtkTreeIter iter; - WebKitDownloadStatus status; - guint64 total, current; - gdouble remaining_seconds = 0.0; - char *remaining, *file, *cur_progress, *name; - struct tm; - int percent = 0; - DownloadAction action; - - row_ref = get_row_from_download (dv, download); - /* In downloader_view_add_download() we call this function manually to - * ensure the view has something visible in the tree view, however - * signal handlers might have already removed this download from the - * DV, this is that case. */ - if (row_ref == NULL) - return; - - /* Status special casing */ - status = webkit_download_get_status (download); - - total = webkit_download_get_total_size (download); - current = webkit_download_get_current_size (download); - - cur_progress = g_format_size_for_display (current); - - name = ephy_download_get_name (download); - - switch (status) - { - case WEBKIT_DOWNLOAD_STATUS_CANCELLED: - downloader_view_remove_download (dv, download); - return; - case WEBKIT_DOWNLOAD_STATUS_FINISHED: - action = GPOINTER_TO_INT(g_object_get_data (G_OBJECT(download), - "download-action")); - - switch (action) - { - case DOWNLOAD_ACTION_OPEN: - open_downloaded_file (dv, download); - break; - case DOWNLOAD_ACTION_OPEN_LOCATION: - open_downloaded_file_location (dv, download); - break; - case DOWNLOAD_ACTION_DOWNLOAD: - break; - default: - g_assert_not_reached (); - break; - } - - downloader_view_remove_download (dv, download); - - return; - case WEBKIT_DOWNLOAD_STATUS_STARTED: - percent = (int) (webkit_download_get_progress (download) * 100); - remaining_seconds = ephy_download_get_remaining_time (download); - break; - default: - break; - } - - if (total != -1 && current != -1) - { - char *total_progress; - - total_progress = g_format_size_for_display (total); - /* translators: first %s is filename, "%s of %s" is current/total file size */ - file = g_strdup_printf (_("%s\n%s of %s"), name, - cur_progress, total_progress); - g_free (total_progress); - } - else if (current != -1) - { - file = g_strdup_printf ("%s\n%s", name, cur_progress); - } - else - { - file = g_strdup_printf ("%s\n%s", name, _("Unknown")); - } - - if (remaining_seconds < 0) - { - remaining = g_strdup (_("Unknown")); - } - else - { - remaining = format_interval (remaining_seconds); - } - - path = gtk_tree_row_reference_get_path (row_ref); - gtk_tree_model_get_iter (dv->priv->model, &iter, path); - gtk_list_store_set (GTK_LIST_STORE (dv->priv->model), - &iter, - COL_STATUS, status, - COL_PERCENT, percent, - COL_FILE, file, - COL_REMAINING, remaining, - -1); - gtk_tree_path_free (path); - - g_free (name); - g_free (cur_progress); - g_free (file); - g_free (remaining); -} - -static void -update_status_icon (DownloaderView *dv) -{ - char *downloadstring; - int downloads; - - downloads = g_hash_table_size (dv->priv->downloads_hash); - - downloadstring = g_strdup_printf (ngettext ("%d download", - "%d downloads", downloads), - downloads); - - gtk_status_icon_set_tooltip_text (dv->priv->status_icon, - downloadstring); - g_free (downloadstring); -} - -static void -download_progress_cb (WebKitDownload *download, GParamSpec *pspec, DownloaderView *dv) -{ - update_download_row (dv, download); -} - -static void -download_status_changed_cb (WebKitDownload *download, GParamSpec *pspec, DownloaderView *dv) -{ - /* We already have handlers for progress and cancel/error, so - * we only handle finished here. - */ - if (webkit_download_get_status (download) == WEBKIT_DOWNLOAD_STATUS_FINISHED) - update_download_row (dv, download); -} - -static gboolean -download_error_cb (WebKitDownload *download, gint error_code, gint error_detail, const gchar *reason, DownloaderView *dv) -{ - update_download_row (dv, download); - - return FALSE; -} - -static gboolean -update_buttons_timeout_cb (DownloaderView *dv) -{ - update_buttons (dv); - - dv->priv->source_id = 0; - return FALSE; -} - -void -downloader_view_add_download (DownloaderView *dv, - WebKitDownload *download) -{ - GtkTreeRowReference *row_ref; - GtkTreeIter iter; - GtkTreeSelection *selection; - GtkTreePath *path; -#if 0 - GtkIconTheme *theme; - GtkIconInfo *icon_info; - GdkPixbuf *pixbuf; - char *mime, *icon_name; - int width = 16, height = 16; -#endif - gboolean visible = FALSE; - - /* dv may be unrefed inside update_download_row if the file - * downloaded completely while the user was choosing where to - * put it, so we need to protect it. - */ - g_object_ref (dv); - g_object_ref (download); - - gtk_list_store_append (GTK_LIST_STORE (dv->priv->model), - &iter); - gtk_list_store_set (GTK_LIST_STORE (dv->priv->model), - &iter, COL_DOWNLOAD_OBJECT, download, -1); - - path = gtk_tree_model_get_path (GTK_TREE_MODEL (dv->priv->model), &iter); - row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (dv->priv->model), path); - gtk_tree_path_free (path); - - g_hash_table_insert (dv->priv->downloads_hash, - download, - row_ref); - - update_status_icon (dv); - - selection = gtk_tree_view_get_selection - (GTK_TREE_VIEW (dv->priv->treeview)); - gtk_tree_selection_unselect_all (selection); - gtk_tree_selection_select_iter (selection, &iter); - - g_signal_connect_object (download, "notify::progress", - G_CALLBACK (download_progress_cb), dv, 0); - - g_signal_connect_object (download, "notify::status", - G_CALLBACK (download_status_changed_cb), dv, 0); - - g_signal_connect_object (download, "error", - G_CALLBACK (download_error_cb), dv, 0); - - update_download_row (dv, download); - - /* Show it already */ - g_object_get (G_OBJECT (dv->priv->window), "visible", &visible, NULL); - - /* In the previous update_download_row() (or handlers) the download - * might have finished, if that's the case, we have nothing else to do. - * A notification of the finished download will pop to inform the user - * there was success. */ - if (g_hash_table_size (dv->priv->downloads_hash) < 1) - { - ephy_dialog_hide (EPHY_DIALOG (dv)); - return; - } - - if (g_settings_get_boolean (EPHY_SETTINGS_UI, - EPHY_PREFS_UI_DOWNLOADS_HIDDEN) && !visible) - { - ephy_dialog_hide (EPHY_DIALOG (dv)); - } - else - { - ephy_dialog_show (EPHY_DIALOG (dv)); - } - -#if 0 - // FIXMEchpe port this to use GIcon when webkit gets download support - mime = ephy_download_get_mime (download); - - theme = gtk_icon_theme_get_default (); - icon_name = gnome_icon_lookup (theme, NULL, NULL, NULL, NULL, - mime, GNOME_ICON_LOOKUP_FLAGS_NONE, NULL); - g_free (mime); - - gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (GTK_WIDGET (dv->priv->window)), - GTK_ICON_SIZE_MENU, &width, &height); - width *= 2; - - icon_info = gtk_icon_theme_lookup_icon (theme, icon_name, width, 0); - g_free (icon_name); - if (icon_info == NULL) return; - - pixbuf = gdk_pixbuf_new_from_file_at_size - (gtk_icon_info_get_filename (icon_info), width, width, NULL); - gtk_icon_info_free (icon_info); - - gtk_list_store_set (GTK_LIST_STORE (dv->priv->model), - &iter, COL_IMAGE, pixbuf, -1); - if (pixbuf != NULL) - { - g_object_unref (pixbuf); - } -#endif - - if (dv->priv->source_id == 0) - dv->priv->source_id = g_timeout_add (100, (GSourceFunc) update_buttons_timeout_cb, dv); -} - -static void -selection_changed (GtkTreeSelection *selection, DownloaderView *dv) -{ - update_buttons (dv); -} - -static void -progress_cell_data_func (GtkTreeViewColumn *col, - GtkCellRenderer *renderer, - GtkTreeModel *model, - GtkTreeIter *iter, - gpointer user_data) -{ - WebKitDownloadStatus status; - const char *text = NULL; - int percent; - - gtk_tree_model_get (model, iter, - COL_STATUS, &status, - COL_PERCENT, &percent, - -1); - - switch (status) - { - case WEBKIT_DOWNLOAD_STATUS_CREATED: - text = C_("download status", "Unknown"); - break; - case WEBKIT_DOWNLOAD_STATUS_ERROR: - text = C_("download status", "Failed"); - break; - case WEBKIT_DOWNLOAD_STATUS_CANCELLED: - text = C_("download status", "Cancelled"); - case WEBKIT_DOWNLOAD_STATUS_STARTED: - if (percent == -1) - { - text = C_("download status", "Unknown"); - percent = 0; - } - break; - default: - g_return_if_reached (); - } - - g_object_set (renderer, "text", text, "value", percent, NULL); -} - -static void -downloader_view_build_ui (DownloaderView *dv) -{ - DownloaderViewPrivate *priv = dv->priv; - GtkListStore *liststore; - GtkTreeViewColumn *column; - GtkCellRenderer *renderer; - EphyDialog *d = EPHY_DIALOG (dv); - GtkTreeSelection *selection; - - ephy_dialog_construct (d, - ephy_file ("epiphany.ui"), - "download_manager_dialog", - NULL); - - /* lookup needed widgets */ - ephy_dialog_get_controls (d, - "download_manager_dialog", &priv->window, - "clist", &priv->treeview, - "pause_button", &priv->pause_button, - "abort_button", &priv->abort_button, - NULL); - - g_signal_connect (priv->window, "response", - G_CALLBACK (download_dialog_response_cb), dv); - g_signal_connect (priv->window, "delete-event", - G_CALLBACK (download_dialog_delete_event_cb), dv); - - gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview)), - GTK_SELECTION_BROWSE); - - liststore = gtk_list_store_new (6, - G_TYPE_INT, - G_TYPE_INT, - GDK_TYPE_PIXBUF, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_OBJECT); - - gtk_tree_view_set_model (GTK_TREE_VIEW(priv->treeview), - GTK_TREE_MODEL (liststore)); - g_object_unref (liststore); - gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(priv->treeview), - TRUE); - /* Icon and filename column*/ - column = gtk_tree_view_column_new (); - gtk_tree_view_column_set_title (column, _("File")); - renderer = gtk_cell_renderer_pixbuf_new (); - g_object_set (renderer, "xpad", 3, NULL); - gtk_tree_view_column_pack_start (column, renderer, FALSE); - gtk_tree_view_column_set_attributes (column, renderer, - "pixbuf", COL_IMAGE, - NULL); - renderer = gtk_cell_renderer_text_new (); - g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_MIDDLE, NULL); - gtk_tree_view_column_pack_start (column, renderer, TRUE); - gtk_tree_view_column_set_attributes (column, renderer, - "text", COL_FILE, - NULL); - gtk_tree_view_insert_column (GTK_TREE_VIEW (priv->treeview), column, FILE_COL_POS); - gtk_tree_view_column_set_expand (column, TRUE); - gtk_tree_view_column_set_resizable (column, TRUE); - gtk_tree_view_column_set_sort_column_id (column, COL_FILE); - gtk_tree_view_column_set_spacing (column, 3); - - /* Progress column */ - renderer = gtk_cell_renderer_progress_new (); - g_object_set (renderer, "xalign", 0.5, NULL); - gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW(priv->treeview), - PROGRESS_COL_POS, _("%"), - renderer, - NULL); - column = gtk_tree_view_get_column (GTK_TREE_VIEW(priv->treeview), PROGRESS_COL_POS); - gtk_tree_view_column_set_cell_data_func(column, renderer, progress_cell_data_func, NULL, NULL); - gtk_tree_view_column_set_sort_column_id (column, COL_PERCENT); - - /* Remainng time column */ - renderer = gtk_cell_renderer_text_new (); - g_object_set (renderer, "xalign", 0.5, NULL); - gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW(priv->treeview), - REMAINING_COL_POS, _("Remaining"), - renderer, - "text", COL_REMAINING, - NULL); - - column = gtk_tree_view_get_column (GTK_TREE_VIEW(priv->treeview), - REMAINING_COL_POS); - gtk_tree_view_column_set_sort_column_id (column, COL_REMAINING); - - gtk_tree_view_set_enable_search (GTK_TREE_VIEW (priv->treeview), FALSE); - - priv->model = GTK_TREE_MODEL (liststore); - - gtk_window_set_icon_name (GTK_WINDOW (priv->window), STOCK_DOWNLOAD); - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview)); - gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE); - g_signal_connect (selection, "changed", G_CALLBACK (selection_changed), dv); -} - -static void -download_dialog_pause (DownloaderView *dv) -{ - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter iter; - GValue val = {0, }; - WebKitDownload *download; - WebKitDownloadStatus status; - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(dv->priv->treeview)); - - if (!gtk_tree_selection_get_selected (selection, &model, &iter)) return; - - gtk_tree_model_get_value (model, &iter, COL_DOWNLOAD_OBJECT, &val); - download = g_value_get_object (&val); - - status = webkit_download_get_status (download); - - g_warning ("Pause/resume not implemented"); - - g_value_unset (&val); - - update_buttons (dv); -} - -void -downloader_view_remove_download (DownloaderView *dv, WebKitDownload *download) -{ - GtkTreeRowReference *row_ref; - GtkTreePath *path = NULL; - GtkTreeIter iter, iter2; - - row_ref = get_row_from_download (dv, download); - g_return_if_fail (row_ref); - - /* Get the row we'll select after removal ("smart" selection) */ - - path = gtk_tree_row_reference_get_path (row_ref); - gtk_tree_model_get_iter (GTK_TREE_MODEL (dv->priv->model), - &iter, path); - gtk_tree_path_free (path); - - row_ref = NULL; - iter2 = iter; - if (gtk_tree_model_iter_next (GTK_TREE_MODEL (dv->priv->model), &iter)) - { - path = gtk_tree_model_get_path (GTK_TREE_MODEL (dv->priv->model), &iter); - row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (dv->priv->model), path); - } - else - { - path = gtk_tree_model_get_path (GTK_TREE_MODEL (dv->priv->model), &iter2); - if (gtk_tree_path_prev (path)) - { - row_ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (dv->priv->model), - path); - } - } - gtk_tree_path_free (path); - - /* Removal */ - - gtk_list_store_remove (GTK_LIST_STORE (dv->priv->model), &iter2); - g_hash_table_remove (dv->priv->downloads_hash, download); - remove_download (download, NULL, dv); - - /* Actual selection */ - - if (row_ref != NULL) - { - path = gtk_tree_row_reference_get_path (row_ref); - if (path != NULL) - { - gtk_tree_view_set_cursor (GTK_TREE_VIEW (dv->priv->treeview), - path, NULL, FALSE); - gtk_tree_path_free (path); - } - gtk_tree_row_reference_free (row_ref); - } - - update_status_icon (dv); - - /* Close the dialog if there are no more downloads */ - if (!g_hash_table_size (dv->priv->downloads_hash)) - { - gtk_widget_set_sensitive (dv->priv->abort_button, FALSE); - gtk_widget_set_sensitive (dv->priv->pause_button, FALSE); - ephy_dialog_hide (EPHY_DIALOG (dv)); - - if (dv->priv->ownref) - { - dv->priv->ownref = FALSE; - g_object_unref (dv); - } - } -} - -static void -download_dialog_stop (DownloaderView *dv) -{ - GtkTreeSelection *selection; - GtkTreeIter iter; - GtkTreeModel *model; - GList *selected = NULL; - GList *downloads = NULL; - GList *l = NULL; - WebKitDownload *download; - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(dv->priv->treeview)); - model = gtk_tree_view_get_model (GTK_TREE_VIEW(dv->priv->treeview)); - - selected = gtk_tree_selection_get_selected_rows (selection, &model); - - for (l = selected; l; l = l->next) - { - if (!gtk_tree_model_get_iter (model, &iter, l->data)) continue; - - gtk_tree_model_get (model, &iter, COL_DOWNLOAD_OBJECT, &download, -1); - downloads = g_list_append (downloads, download); - } - - /* We have to kill the downloads separately (not in the previous for) - * because otherwise selection would change. - */ - for (l = downloads; l; l = l->next) - { - if (!l->data) continue; - webkit_download_cancel ((WebKitDownload*) l->data); - ephy_file_delete_uri (webkit_download_get_destination_uri ((WebKitDownload*) l->data)); - g_object_unref (l->data); - } - - g_list_foreach (selected, (GFunc) gtk_tree_path_free, NULL); - g_list_free (selected); - g_list_free (downloads); -} - -static void -download_dialog_response_cb (GtkWidget *dialog, - int response, - DownloaderView *dv) -{ - if (response == RESPONSE_PAUSE) - { - download_dialog_pause (dv); - } - else if (response == RESPONSE_STOP) - { - download_dialog_stop (dv); - } -} - -static gboolean -download_dialog_delete_event_cb (GtkWidget *window, - GdkEventAny *event, - DownloaderView *dv) -{ - DownloaderViewPrivate *priv = dv->priv; - - if (gtk_status_icon_is_embedded (priv->status_icon)) - { - gtk_widget_hide (window); - } - - return TRUE; -} diff --git a/embed/downloader-view.h b/embed/downloader-view.h deleted file mode 100644 index e331cca02..000000000 --- a/embed/downloader-view.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright © 2000, 2001, 2002 Marco Pesenti Gritti - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef DOWNLOADER_VIEW_H -#define DOWNLOADER_VIEW_H - -#include "ephy-dialog.h" - -#include <webkit/webkit.h> -#include <glib-object.h> -#include <glib.h> - -G_BEGIN_DECLS - -#define EPHY_TYPE_DOWNLOADER_VIEW (downloader_view_get_type ()) -#define EPHY_DOWNLOADER_VIEW(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EPHY_TYPE_DOWNLOADER_VIEW, DownloaderView)) -#define EPHY_DOWNLOADER_VIEW_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), EPHY_TYPE_DOWNLOADER_VIEW, DownloaderViewClass)) -#define EPHY_IS_DOWNLOADER_VIEW(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EPHY_TYPE_DOWNLOADER_VIEW)) -#define EPHY_IS_DOWNLOADER_VIEW_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EPHY_TYPE_DOWNLOADER_VIEW)) -#define EPHY_DOWNLOADER_VIEW_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EPHY_TYPE_DOWNLOADER_VIEW, DownloaderViewClass)) - -typedef struct _DownloaderView DownloaderView; -typedef struct _DownloaderViewPrivate DownloaderViewPrivate; -typedef struct _DownloaderViewClass DownloaderViewClass; - -struct _DownloaderView -{ - EphyDialog parent; - - /*< private >*/ - DownloaderViewPrivate *priv; -}; - -struct _DownloaderViewClass -{ - EphyDialogClass parent_class; -}; - -/* These represent actions to be performed after the download is - * successfully completed; NONE means no download will happen, - * DOWNLOAD is just a way to tell the mime content handler that a file - * chooser should be displayed so that the user can select where to - * download to, and is usually turned into OPEN_LOCATION after that - * happens (in other words, DOWNLOAD will never be an action when the - * download is finished). OPEN will try to run the default application - * that handles that file type. - */ -typedef enum -{ - DOWNLOAD_ACTION_NONE, - DOWNLOAD_ACTION_DOWNLOAD, - DOWNLOAD_ACTION_OPEN, - DOWNLOAD_ACTION_OPEN_LOCATION -} DownloadAction; - -GType downloader_view_get_type (void); - -DownloaderView *downloader_view_new (void); - -void downloader_view_add_download (DownloaderView *dv, - WebKitDownload *download); - -void downloader_view_remove_download (DownloaderView *dv, - WebKitDownload *download); - -G_END_DECLS - -#endif diff --git a/embed/ephy-download.c b/embed/ephy-download.c new file mode 100644 index 000000000..3a7d2d1ff --- /dev/null +++ b/embed/ephy-download.c @@ -0,0 +1,965 @@ +/* vim: set sw=2 ts=2 sts=2 et: */ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * ephy-download.c + * This file is part of Epiphany + * + * Copyright © 2011 - Igalia S.L. + * + * Epiphany is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Epiphany 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Epiphany; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "config.h" + +#include "ephy-debug.h" +#include "ephy-download.h" +#include "ephy-embed.h" +#include "ephy-embed-shell.h" +#include "ephy-embed-type-builtins.h" +#include "ephy-file-helpers.h" +#include "ephy-marshal.h" +#include "ephy-prefs.h" +#include "ephy-settings.h" + +#include <errno.h> +#include <glib/gi18n.h> +#include <string.h> +#include <webkit/webkit.h> + +G_DEFINE_TYPE (EphyDownload, ephy_download, G_TYPE_OBJECT) + +#define EPHY_DOWNLOAD_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), EPHY_TYPE_DOWNLOAD, EphyDownloadPrivate)) + +struct _EphyDownloadPrivate +{ + WebKitDownload *download; + + char *destination; + char *source; + + EphyDownloadActionType action; + guint32 start_time; + + GtkWidget *window; + GtkWidget *widget; +}; + +enum +{ + PROP_0, + PROP_DOWNLOAD, + PROP_DESTINATION, + PROP_SOURCE, + PROP_ACTION, + PROP_START_TIME, + PROP_WINDOW, + PROP_WIDGET +}; + +static void +ephy_download_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + EphyDownload *download; + EphyDownloadPrivate *priv; + + download = EPHY_DOWNLOAD (object); + priv = download->priv; + + switch (property_id) { + case PROP_WIDGET: + g_value_set_object (value, priv->widget); + break; + case PROP_WINDOW: + g_value_set_object (value, priv->window); + break; + case PROP_DOWNLOAD: + g_value_set_object (value, ephy_download_get_webkit_download (download)); + break; + case PROP_DESTINATION: + g_value_set_string (value, ephy_download_get_destination_uri (download)); + break; + case PROP_SOURCE: + g_value_set_string (value, ephy_download_get_source_uri (download)); + break; + case PROP_ACTION: + g_value_set_enum (value, ephy_download_get_action (download)); + break; + case PROP_START_TIME: + g_value_set_uint (value, ephy_download_get_start_time (download)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +ephy_download_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + EphyDownload *download; + download = EPHY_DOWNLOAD (object); + + switch (property_id) { + case PROP_DESTINATION: + ephy_download_set_destination_uri (download, g_value_get_string (value)); + break; + case PROP_ACTION: + ephy_download_set_action (download, g_value_get_enum (value)); + break; + case PROP_WINDOW: + ephy_download_set_window (download, g_value_get_object (value)); + break; + case PROP_WIDGET: + ephy_download_set_widget (download, g_value_get_object (value)); + break; + case PROP_DOWNLOAD: + case PROP_SOURCE: + case PROP_START_TIME: + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static EphyDownloadActionType +decide_action_from_mime (EphyDownload *ephy_download) +{ + WebKitNetworkResponse *response; + SoupMessage *message; + char *mime_description = NULL; + GAppInfo *helper_app = NULL; + EphyMimePermission mime_permission = EPHY_MIME_PERMISSION_SAFE; + EphyDownloadActionType action; + WebKitDownload *download; + + download = ephy_download_get_webkit_download (ephy_download); + + response = webkit_download_get_network_response (download); + message = webkit_network_response_get_message (response); + + if (message) { + const char *content_type = soup_message_headers_get_content_type (message->response_headers, NULL); + + if (content_type) { + mime_description = g_content_type_get_description (content_type); + helper_app = g_app_info_get_default_for_type (content_type, FALSE); + mime_permission = ephy_file_check_mime (content_type); + + if (helper_app) + action = EPHY_DOWNLOAD_ACTION_OPEN; + } + } + + if (mime_description == NULL) { + mime_description = g_strdup (C_("file type", "Unknown")); + action = EPHY_DOWNLOAD_ACTION_BROWSE_TO; + } + + /* Sometimes downloads can have a mime_description but a NULL helper_app + * in that case action is never changed so DOWNLOAD_ACTION_DOWNLOAD remains + * as action value. This is the same response value as Save as... + * button, which is wrong for the Download button. + */ + if (helper_app == NULL) + action = EPHY_DOWNLOAD_ACTION_BROWSE_TO; + + return action; +} + +/* From the old embed/mozilla/MozDownload.cpp */ +static const char* +file_is_compressed (const char *filename) +{ + int i; + static const char * const compression[] = {".gz", ".bz2", ".Z", ".lz", NULL}; + + for (i = 0; compression[i] != NULL; i++) { + if (g_str_has_suffix (filename, compression[i])) + return compression[i]; + } + + return NULL; +} + +static const char* +parse_extension (const char *filename) +{ + const char *compression; + const char *last_separator; + + compression = file_is_compressed (filename); + + /* if the file is compressed we might have a double extension */ + if (compression != NULL) { + int i; + static const char * const extensions[] = {"tar", "ps", "xcf", "dvi", "txt", "text", NULL}; + + for (i = 0; extensions[i] != NULL; i++) { + char *suffix; + suffix = g_strdup_printf (".%s%s", extensions[i], compression); + + if (g_str_has_suffix (filename, suffix)) { + char *p; + + p = g_strrstr (filename, suffix); + g_free (suffix); + + return p; + } + + g_free (suffix); + } + } + + /* no compression, just look for the last dot in the filename */ + last_separator = strrchr (filename, G_DIR_SEPARATOR); + return strrchr ((last_separator) ? last_separator : filename, '.'); +} + +static char * +define_destination_uri (EphyDownload *download) +{ + char *dest_dir; + char *dest_name; + char *destination_filename; + char *destination_uri; + const char *suggested_filename; + + suggested_filename = webkit_download_get_suggested_filename (download->priv->download); + dest_dir = ephy_file_get_downloads_dir (); + + /* Make sure the download directory exists */ + if (g_mkdir_with_parents (dest_dir, 0700) == -1) { + g_critical ("Could not create downloads directory \"%s\": %s", + dest_dir, strerror (errno)); + g_free (dest_dir); + return NULL; + } + + if (suggested_filename != NULL) { + dest_name = g_strdup (suggested_filename); + } else { + dest_name = ephy_file_tmp_filename ("ephy-download-XXXXXX", NULL); + } + + destination_filename = g_build_filename (dest_dir, dest_name, NULL); + g_free (dest_dir); + g_free (dest_name); + + /* Append (n) as needed. */ + if (g_file_test (destination_filename, G_FILE_TEST_EXISTS)) { + int i = 1; + const char *dot_pos; + gssize position; + char *serial = NULL; + GString *tmp_filename; + + dot_pos = parse_extension (destination_filename); + if (dot_pos) + position = dot_pos - destination_filename; + else + position = strlen (destination_filename); + + tmp_filename = g_string_new (NULL); + + do { + serial = g_strdup_printf ("(%d)", i++); + + g_string_assign (tmp_filename, destination_filename); + g_string_insert (tmp_filename, position, serial); + + g_free (serial); + } while (g_file_test (tmp_filename->str, G_FILE_TEST_EXISTS)); + + destination_filename = g_strdup (tmp_filename->str); + g_string_free (tmp_filename, TRUE); + } + + destination_uri = g_filename_to_uri (destination_filename, NULL, NULL); + g_free (destination_filename); + + g_assert (destination_uri); + + return destination_uri; +} + +/** + * ephy_download_set_destination_uri: + * @download: an #EphyDownload + * @destination: URI where to save @download + * + * Sets the destination URI of @download. It must be a proper URI, with a + * scheme like file:/// or similar. + **/ +void +ephy_download_set_destination_uri (EphyDownload *download, + const char *destination) +{ + EphyDownloadPrivate *priv; + char *scheme; + + g_return_if_fail (EPHY_IS_DOWNLOAD (download)); + g_return_if_fail (destination != NULL); + + priv = download->priv; + + scheme = g_uri_parse_scheme (destination); + g_return_if_fail (scheme != NULL); + g_free (scheme); + + priv->destination = g_strdup (destination); + + webkit_download_set_destination_uri (priv->download, priv->destination); + g_object_notify (G_OBJECT (download), "destination"); +} + +/** + * ephy_download_set_auto_destination: + * @download: an #EphyDownload + * + * Tells @download to automatically determine a destination for itself. + **/ +void +ephy_download_set_auto_destination (EphyDownload *download) +{ + char *dest; + + g_return_if_fail (EPHY_IS_DOWNLOAD (download)); + + dest = define_destination_uri (download); + ephy_download_set_destination_uri (download, dest); + + g_free (dest); +} + +/** + * ephy_download_set_action: + * @download: an #EphyDownload + * @action: #EphyDownloadActionType to execute + * + * Sets the @action to be executed when ephy_download_do_download_action () is + * called on @download or on finish when "Automatically download and open + * files" is set. + **/ +void +ephy_download_set_action (EphyDownload *download, + EphyDownloadActionType action) +{ + g_return_if_fail (EPHY_IS_DOWNLOAD (download)); + + download->priv->action = action; + g_object_notify (G_OBJECT (download), "action"); +} + +/** + * ephy_download_set_window: + * @download: an #EphyDownload + * @window: #GtkWidget that produced @download + * + * Sets @window to be @download's parent, this means that @download will be + * shown on @window's #EphyWindow (where it is contained). + **/ +void +ephy_download_set_window (EphyDownload *download, + GtkWidget *window) +{ + g_return_if_fail (EPHY_IS_DOWNLOAD (download)); + + if (download->priv->window != NULL) + g_object_unref (download->priv->window); + + download->priv->window = NULL; + + if (window != NULL) + download->priv->window = g_object_ref (window); + + g_object_notify (G_OBJECT (download), "window"); +} + +/** + * ephy_download_set_widget: + * @download: an #EphyDownload + * @widget: a #GtkWidget + * + * Sets @widget to be associated with @download as its UI. + **/ +void +ephy_download_set_widget (EphyDownload *download, + GtkWidget *widget) +{ + g_return_if_fail (EPHY_IS_DOWNLOAD (download)); + + if (download->priv->widget != NULL) + g_object_unref (download->priv->widget); + + download->priv->widget = NULL; + + if (widget != NULL) + download->priv->widget = g_object_ref (widget); + + g_object_notify (G_OBJECT (download), "widget"); +} + +/** + * ephy_download_get_widget: + * @download: an #EphyDownload + * + * Gets the #GtkWidget associated to this download. + * + * Returns: (transfer none): a #GtkWidget. + **/ +GtkWidget * +ephy_download_get_widget (EphyDownload *download) +{ + g_return_val_if_fail (EPHY_IS_DOWNLOAD (download), NULL); + + return download->priv->widget; +} + +/** + * ephy_download_get_webkit_download: + * @download: an #EphyDownload + * + * Gets the #WebKitDownload being wrapped by @download. + * + * Returns: (transfer none): a #WebKitDownload. + **/ +WebKitDownload * +ephy_download_get_webkit_download (EphyDownload *download) +{ + g_return_val_if_fail (EPHY_IS_DOWNLOAD (download), NULL); + + return download->priv->download; +} + +/** + * ephy_download_get_window: + * @download: an #EphyDownload + * + * Gets the window set as the parent of @download, this can be NULL if no + * specific window generated this download. + * + * Returns: (transfer none): a #GtkWidget + **/ +GtkWidget * +ephy_download_get_window (EphyDownload *download) +{ + g_return_val_if_fail (EPHY_IS_DOWNLOAD (download), NULL); + + return download->priv->window; +} + +/** + * ephy_download_get_destination_uri: + * @download: an #EphyDownload + * + * Gets the destination URI where the download is being saved. + * + * Returns: (transfer none): destination URI. + **/ +const char * +ephy_download_get_destination_uri (EphyDownload *download) +{ + g_return_val_if_fail (EPHY_IS_DOWNLOAD (download), NULL); + + return download->priv->destination; +} + +/** + * ephy_download_get_source_uri: + * @download: an #EphyDownload + * + * Gets the source URI that this download is/will download. + * + * Returns: source URI. + **/ +const char * +ephy_download_get_source_uri (EphyDownload *download) +{ + g_return_val_if_fail (EPHY_IS_DOWNLOAD (download), NULL); + + return download->priv->source; +} + +/** + * ephy_download_get_action: + * @download: an #EphyDownload + * + * Gets the #EphyDownloadActionType that this download will execute when + * ephy_download_do_download_action () is called on it. This action is + * performed automatically is "Automatically download and open files" is + * enabled. + * + * Returns: the #EphyDownloadActionType to be executed + **/ +EphyDownloadActionType +ephy_download_get_action (EphyDownload *download) +{ + g_return_val_if_fail (EPHY_IS_DOWNLOAD (download), EPHY_DOWNLOAD_ACTION_NONE); + + return download->priv->action; +} + +/** + * ephy_download_get_start_time: + * @download: an #EphyDownload + * + * Gets the time (returned by gtk_get_current_event_time ()) when @download was + * started with ephy_download_start (). Defaults to 0. + * + * Returns: the time when @download was started. + **/ +guint32 +ephy_download_get_start_time (EphyDownload *download) +{ + g_return_val_if_fail (EPHY_IS_DOWNLOAD (download), 0); + + return download->priv->start_time; +} + +/** + * ephy_download_start: + * @download: an #EphyDownload + * + * Starts the wrapped #WebKitDownload. + **/ +void +ephy_download_start (EphyDownload *download) +{ + EphyDownloadPrivate *priv; + + g_return_if_fail (EPHY_IS_DOWNLOAD (download)); + + priv = download->priv; + priv->start_time = gtk_get_current_event_time (); + + if (priv->destination == NULL) + ephy_download_set_auto_destination (download); + + webkit_download_start (priv->download); +} + +/** + * ephy_download_cancel: + * @download: an #EphyDownload + * + * Cancels the wrapped #WebKitDownload. + **/ +void +ephy_download_cancel (EphyDownload *download) +{ + g_return_if_fail (EPHY_IS_DOWNLOAD (download)); + + webkit_download_cancel (download->priv->download); +} + +/** + * ephy_download_do_download_action: + * @download: an #EphyDownload + * @action: one of #EphyDownloadActionType + * + * Executes the given @action for @download, this can be any of + * #EphyDownloadActionType, including #EPHY_DOWNLOAD_ACTION_AUTO which decides + * the default action from the mime type of @download. + * + * Returns: %TRUE if the action was executed succesfully. + * + **/ +gboolean +ephy_download_do_download_action (EphyDownload *download, + EphyDownloadActionType action) +{ + GFile *destination; + const char *destination_uri; + EphyDownloadPrivate *priv; + gboolean ret = FALSE; + + priv = download->priv; + + destination_uri = webkit_download_get_destination_uri (priv->download); + destination = g_file_new_for_uri (destination_uri); + + switch ((action ? action : priv->action)) { + case EPHY_DOWNLOAD_ACTION_AUTO: + LOG ("ephy_download_do_download_action: auto"); + ret = ephy_download_do_download_action (download, decide_action_from_mime (download)); + break; + case EPHY_DOWNLOAD_ACTION_BROWSE_TO: + LOG ("ephy_download_do_download_action: browse_to"); + ret = ephy_file_browse_to (destination, priv->start_time); + break; + case EPHY_DOWNLOAD_ACTION_OPEN: + LOG ("ephy_download_do_download_action: open"); + ret = ephy_file_launch_handler (NULL, destination, priv->start_time); + break; + case EPHY_DOWNLOAD_ACTION_NONE: + LOG ("ephy_download_do_download_action: none"); + ret = TRUE; + break; + default: + LOG ("ephy_download_do_download_action: unhandled action"); + ret = FALSE; + break; + } + g_object_unref (destination); + + return ret; +} + +static void +ephy_download_dispose (GObject *object) +{ + EphyDownload *download = EPHY_DOWNLOAD (object); + EphyDownloadPrivate *priv; + + LOG ("EphyDownload disposed %p", object); + + priv = download->priv; + + if (priv->download) { + g_object_unref (priv->download); + priv->download = NULL; + } + + if (priv->window) { + g_object_unref (priv->window); + priv->window = NULL; + } + + if (priv->widget) { + g_object_unref (priv->widget); + priv->widget = NULL; + } + + ephy_embed_shell_remove_download (embed_shell, download); + + G_OBJECT_CLASS (ephy_download_parent_class)->dispose (object); +} + +static void +ephy_download_finalize (GObject *object) +{ + EphyDownload *download = EPHY_DOWNLOAD (object); + EphyDownloadPrivate *priv; + + priv = download->priv; + + g_free (priv->destination); + g_free (priv->source); + + LOG ("EphyDownload finalised %p", object); + + G_OBJECT_CLASS (ephy_download_parent_class)->finalize (object); +} + +static void +ephy_download_class_init (EphyDownloadClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (EphyDownloadPrivate)); + + object_class->get_property = ephy_download_get_property; + object_class->set_property = ephy_download_set_property; + object_class->dispose = ephy_download_dispose; + object_class->finalize = ephy_download_finalize; + + /** + * EphyDownload::download: + * + * Internal WebKitDownload. + */ + g_object_class_install_property (object_class, PROP_DOWNLOAD, + g_param_spec_object ("download", + "Internal WebKitDownload", + "The WebKitDownload used internally by EphyDownload", + WEBKIT_TYPE_DOWNLOAD, + G_PARAM_READABLE | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB)); + + /** + * EphyDownload::destination: + * + * The destination URI where to store the download. + */ + g_object_class_install_property (object_class, PROP_DESTINATION, + g_param_spec_string ("destination", + "Destination", + "Destination file URI", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB)); + /** + * EphyDownload::source: + * + * Download's origin URI + */ + g_object_class_install_property (object_class, PROP_SOURCE, + g_param_spec_string ("source", + "Source", + "Source URI", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB)); + + /** + * EphyDownload::action: + * + * Action to take when the download finishes and "Automatically download and + * open files" is enabled, or when ephy_download_do_download_action () is + * called. + */ + g_object_class_install_property (object_class, PROP_ACTION, + g_param_spec_enum ("action", + "Download action", + "Action to take when download finishes", + EPHY_TYPE_DOWNLOAD_ACTION_TYPE, + EPHY_DOWNLOAD_ACTION_NONE, + G_PARAM_READABLE | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB)); + + /** + * EphyDownload::start-time: + * + * User time when the download started, useful for launching applications + * aware of focus stealing. + */ + g_object_class_install_property (object_class, PROP_START_TIME, + g_param_spec_uint ("start-time", + "Event start time", + "Time for focus-stealing prevention.", + 0, G_MAXUINT32, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB)); + + /** + * EphyDownload::window: + * + * Window that produced the download, the download will be shown in its + * parent window. + */ + g_object_class_install_property (object_class, PROP_WINDOW, + g_param_spec_object ("window", + "A GtkWindow", + "Window that produced this download.", + GTK_TYPE_WIDGET, + G_PARAM_READWRITE | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB)); + + /** + * EphyDownload::widget: + * + * An EphyDownloadWidget -or any other GtkWidget- that is representing this + * EphyDownload to the user. + */ + g_object_class_install_property (object_class, PROP_WIDGET, + g_param_spec_object ("widget", + "A GtkWidget", + "GtkWidget showing this download.", + GTK_TYPE_WIDGET, + G_PARAM_READWRITE | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB)); + + /** + * EphyDownload::completed: + * + * The ::completed signal is emitted when @download has finished downloading. + **/ + g_signal_new ("completed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EphyDownloadClass, completed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + /** + * EphyDownload::error: + * + * The ::error signal wraps the @download ::error signal. + **/ + g_signal_new ("error", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EphyDownloadClass, error), + NULL, NULL, + ephy_marshal_BOOLEAN__INT_INT_STRING, + G_TYPE_NONE, + 0); +} + +static void +ephy_download_init (EphyDownload *download) +{ + download->priv = EPHY_DOWNLOAD_GET_PRIVATE (download); + + LOG ("EphyDownload initialising %p", download); + + download->priv->download = NULL; + download->priv->destination = NULL; + + download->priv->action = EPHY_DOWNLOAD_ACTION_NONE; + + download->priv->start_time = 0; + + download->priv->window = NULL; + download->priv->widget = NULL; +} + +static void +download_status_changed_cb (GObject *object, + GParamSpec *pspec, + EphyDownload *download) +{ + WebKitDownloadStatus status; + EphyDownloadPrivate *priv; + + priv = download->priv; + + status = webkit_download_get_status (priv->download); + + if (status == WEBKIT_DOWNLOAD_STATUS_FINISHED) { + g_signal_emit_by_name (download, "completed"); + + if (g_settings_get_boolean (EPHY_SETTINGS_MAIN, EPHY_PREFS_AUTO_DOWNLOADS)) { + ephy_download_do_download_action (download, EPHY_DOWNLOAD_ACTION_AUTO); + } else { + ephy_download_do_download_action (download, EPHY_DOWNLOAD_ACTION_NONE); + } + + ephy_embed_shell_remove_download (embed_shell, download); + } else if (status == WEBKIT_DOWNLOAD_STATUS_CANCELLED || + status == WEBKIT_DOWNLOAD_STATUS_ERROR) { + } else if (status == WEBKIT_DOWNLOAD_STATUS_STARTED) { + ephy_embed_shell_add_download (embed_shell, download); + } +} + +static gboolean +download_error_cb (WebKitDownload *download, + gint error_code, + gint error_detail, + char *reason, + gpointer user_data) +{ + EphyDownload *ephy_download; + gboolean ret = FALSE; + + ephy_download = EPHY_DOWNLOAD (user_data); + + LOG ("error (%d - %d)! %s", error_code, error_detail, reason); + g_signal_emit_by_name (ephy_download, "error", + error_code, error_detail, reason, &ret); + + return ret; +} + +/** + * ephy_download_new: + * + * Creates a new #EphyDownload. You can use ephy_download_new_for_download and + * ephy_download_new_for_uri as convenience functions to create #EphyDownload + * objects. + * + * Returns: an #EphyDownload. + **/ +EphyDownload * +ephy_download_new (void) +{ + return g_object_new (EPHY_TYPE_DOWNLOAD, NULL); +} + +static EphyDownload * +_ephy_download_new (WebKitDownload *webkit_download, const char *uri) +{ + EphyDownload *ephy_download; + ephy_download = ephy_download_new (); + + if (webkit_download == NULL) { + WebKitNetworkRequest *request; + + request = webkit_network_request_new (uri); + webkit_download = webkit_download_new (request); + + g_return_val_if_fail (webkit_download != NULL, NULL); + g_object_unref (request); + } + + g_signal_connect (webkit_download, "notify::status", + G_CALLBACK (download_status_changed_cb), + ephy_download); + g_signal_connect (webkit_download, "error", + G_CALLBACK (download_error_cb), + ephy_download); + + ephy_download->priv->download = g_object_ref (webkit_download); + ephy_download->priv->source = g_strdup (webkit_download_get_uri (webkit_download)); + + return ephy_download; +} + +/** + * ephy_download_new_for_download: + * @download: a #WebKitDownload to wrap + * + * Wraps @download in an #EphyDownload. + * + * Returns: an #EphyDownload. + **/ +EphyDownload * +ephy_download_new_for_download (WebKitDownload *download) +{ + g_return_val_if_fail (WEBKIT_IS_DOWNLOAD (download), NULL); + + return _ephy_download_new (download, NULL); +} + +/** + * ephy_download_new_for_uri: + * @uri: a source URI from where to download + * + * Creates an #EphyDownload to download @uri. + * + * Returns: an #EphyDownload. + **/ +EphyDownload * +ephy_download_new_for_uri (const char *uri) +{ + g_return_val_if_fail (uri != NULL, NULL); + + return _ephy_download_new (NULL, uri); +} diff --git a/embed/ephy-download.h b/embed/ephy-download.h new file mode 100644 index 000000000..8c84bbe05 --- /dev/null +++ b/embed/ephy-download.h @@ -0,0 +1,115 @@ +/* vim: set sw=2 ts=2 sts=2 et: */ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * ephy-download.h + * This file is part of Epiphany + * + * Copyright © 2011 - Igalia S.L. + * + * Epiphany is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Epiphany 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Epiphany; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#if !defined (__EPHY_EPIPHANY_H_INSIDE__) && !defined (EPIPHANY_COMPILATION) +#error "Only <epiphany/epiphany.h> can be included directly." +#endif + +#ifndef _EPHY_DOWNLOAD_H +#define _EPHY_DOWNLOAD_H + +#include <glib-object.h> +#include <webkit/webkit.h> + +#include "ephy-embed.h" + +G_BEGIN_DECLS + +#define EPHY_TYPE_DOWNLOAD ephy_download_get_type() +#define EPHY_DOWNLOAD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EPHY_TYPE_DOWNLOAD, EphyDownload)) +#define EPHY_DOWNLOAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EPHY_TYPE_DOWNLOAD, EphyDownloadClass)) +#define EPHY_IS_DOWNLOAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EPHY_TYPE_DOWNLOAD)) +#define EPHY_IS_DOWNLOAD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EPHY_TYPE_DOWNLOAD)) +#define EPHY_DOWNLOAD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EPHY_TYPE_DOWNLOAD, EphyDownloadClass)) + +typedef struct _EphyDownload EphyDownload; +typedef struct _EphyDownloadClass EphyDownloadClass; +typedef struct _EphyDownloadPrivate EphyDownloadPrivate; + +struct _EphyDownload +{ + GObject parent; + + EphyDownloadPrivate *priv; +}; + +struct _EphyDownloadClass +{ + GObjectClass parent_class; + + void (* completed) (EphyDownload *download); + void (* error) (EphyDownload *download, + gint error_code, + gint error_detail, + char *reason); +}; + +typedef enum +{ + EPHY_DOWNLOAD_ACTION_NONE, + EPHY_DOWNLOAD_ACTION_AUTO, + EPHY_DOWNLOAD_ACTION_BROWSE_TO, + EPHY_DOWNLOAD_ACTION_OPEN +} EphyDownloadActionType; + +GType ephy_download_get_type (void) G_GNUC_CONST; + +EphyDownload *ephy_download_new (void); +EphyDownload *ephy_download_new_for_uri (const char *uri); +EphyDownload *ephy_download_new_for_download (WebKitDownload *download); + + +void ephy_download_start (EphyDownload *download); +void ephy_download_pause (EphyDownload *download); +void ephy_download_cancel (EphyDownload *download); + +void ephy_download_set_auto_destination (EphyDownload *download); +void ephy_download_set_destination_uri (EphyDownload *download, + const char *destination); + +WebKitDownload *ephy_download_get_webkit_download (EphyDownload *download); + +const char *ephy_download_get_destination_uri (EphyDownload *download); +const char *ephy_download_get_source_uri (EphyDownload *download); + + +guint32 ephy_download_get_start_time (EphyDownload *download); + +GtkWidget *ephy_download_get_window (EphyDownload *download); +void ephy_download_set_window (EphyDownload *download, + GtkWidget *window); + +EphyDownloadActionType ephy_download_get_action (EphyDownload *download); +void ephy_download_set_action (EphyDownload *download, + EphyDownloadActionType action); +gboolean ephy_download_do_download_action (EphyDownload *download, + EphyDownloadActionType action); + +GtkWidget *ephy_download_get_widget (EphyDownload *download); +void ephy_download_set_widget (EphyDownload *download, + GtkWidget *widget); + +G_END_DECLS + +#endif /* _EPHY_DOWNLOAD_H */ diff --git a/embed/ephy-embed-persist.c b/embed/ephy-embed-persist.c deleted file mode 100644 index 5d7a442c0..000000000 --- a/embed/ephy-embed-persist.c +++ /dev/null @@ -1,911 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright © 2000-2003 Marco Pesenti Gritti - * Copyright © 2003 Christian Persch - * Copyright © 2010 Igalia S.L. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "config.h" - -#include "downloader-view.h" -#include "ephy-embed-persist.h" -#include "ephy-embed-shell.h" -#include "ephy-embed-type-builtins.h" -#include "ephy-file-chooser.h" -#include "ephy-file-helpers.h" -#include "ephy-debug.h" - -#include <gtk/gtk.h> -#include <glib/gi18n.h> - -enum -{ - PROP_0, - PROP_DEST, - PROP_EMBED, - PROP_FILECHOOSER_TITLE, - PROP_FILECHOOSER_PARENT, - PROP_FLAGS, - PROP_HANDLER, - PROP_MAX_SIZE, - PROP_PERSISTKEY, - PROP_SOURCE, - PROP_USER_TIME -}; - -#define EPHY_EMBED_PERSIST_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_EMBED_PERSIST, EphyEmbedPersistPrivate)) - -struct _EphyEmbedPersistPrivate -{ - char *dest; - char *source; - char *fc_title; - char *persist_key; - EphyEmbed *embed; - gint64 max_size; - EphyEmbedPersistFlags flags; - GtkWindow *fc_parent; - guint32 user_time; - WebKitDownload *download; - DownloaderView *dview; -}; - -static void ephy_embed_persist_class_init (EphyEmbedPersistClass *klass); -static void ephy_embed_persist_init (EphyEmbedPersist *ges); - -G_DEFINE_TYPE (EphyEmbedPersist, ephy_embed_persist, G_TYPE_OBJECT) - -/** - * ephy_embed_persist_set_dest: - * @persist: an #EphyEmbedPersist - * @value: the path to which @persist should save data - * - * Sets the path to which @persist should save data. - **/ -void -ephy_embed_persist_set_dest (EphyEmbedPersist *persist, - const char *value) -{ - g_return_if_fail (EPHY_IS_EMBED_PERSIST (persist)); - - persist->priv->dest = g_strdup (value); -} - -/** - * ephy_embed_persist_set_embed: - * @persist: an #EphyEmbedPersist - * @value: a parent #EphyEmbed - * - * Sets the #EphyEmbed from which @persist will download data. - * - * An #EphyEmbed is absolutely required to download if @persist's - * #EphyEmbedPersistFlags include %EPHY_EMBED_PERSIST_COPY_PAGE. Regardless, an - * #EphyEmbed should be set for <emphasis>every</emphasis> #EphyEmbedPersist, - * since it determines request information such as the referring page. - **/ -void -ephy_embed_persist_set_embed (EphyEmbedPersist *persist, - EphyEmbed *value) -{ - g_return_if_fail (EPHY_IS_EMBED_PERSIST (persist)); - - persist->priv->embed = value; -} - -/** - * ephy_embed_persist_set_fc_title: - * @persist: an #EphyEmbedPersist - * @value: the title to be displayed by the filechooser - * - * Sets the title of the filechooser window. The filechooser will only be - * displayed if %EPHY_EMBED_PERSIST_ASK_DESTINATION has been set with - * ephy_embed_persist_set_flags(). - **/ -void -ephy_embed_persist_set_fc_title (EphyEmbedPersist *persist, - const char *value) -{ - g_return_if_fail (EPHY_IS_EMBED_PERSIST (persist)); - - persist->priv->fc_title = g_strdup (value); -} - -/** - * ephy_embed_persist_set_fc_parent: - * @persist: an #EphyEmbedPersist - * @value: the #EphyWindow which should be the filechooser's parent - * - * Sets the #EphyWindow which should be @persist's filechooser's parent. The - * filechooser will only be displayed if %EPHY_EMBED_PERSIST_ASK_DESTINATION - * has been set with ephy_embed_persist_set_flags(). - **/ -void -ephy_embed_persist_set_fc_parent (EphyEmbedPersist *persist, - GtkWindow *value) -{ - EphyEmbedPersistPrivate *priv; - GtkWindow **wptr; - - g_return_if_fail (EPHY_IS_EMBED_PERSIST (persist)); - g_return_if_fail (gtk_widget_is_toplevel (GTK_WIDGET (value))); - - priv = persist->priv; - - priv->fc_parent = value; - wptr = &priv->fc_parent; - g_object_add_weak_pointer (G_OBJECT (priv->fc_parent), - (gpointer *) wptr); -} - -/** - * ephy_embed_persist_set_flags: - * @persist: an #EphyEmbedPersist - * @value: the desired #EphyEmbedPersistFlags - * - * Sets the flags to be used for @persist's download. - **/ -void -ephy_embed_persist_set_flags (EphyEmbedPersist *persist, - EphyEmbedPersistFlags value) -{ - g_return_if_fail (EPHY_IS_EMBED_PERSIST (persist)); - - persist->priv->flags = value; -} - -/** - * ephy_embed_persist_set_max_size: - * @persist: an #EphyEmbedPersist - * @value: maximum size of requested download, in bytes - * - * Sets the maximum size of @persist's download. - * - * If the requested file is discovered to be larger than @value, the download - * will be aborted. Note that @persist will have to actually begin downloading - * before it can abort, since it doesn't know the filesize before the download - * starts. - **/ -void -ephy_embed_persist_set_max_size (EphyEmbedPersist *persist, - gint64 value) -{ - g_return_if_fail (EPHY_IS_EMBED_PERSIST (persist)); - - persist->priv->max_size = value; -} - -/** - * ephy_embed_persist_set_persist_key: - * @persist: an #EphyEmbedPersist - * @value: a GConf key - * - * Sets the GConf key from which @persist will determine the default download - * directory. - **/ -void -ephy_embed_persist_set_persist_key (EphyEmbedPersist *persist, - const char *value) -{ - g_return_if_fail (EPHY_IS_EMBED_PERSIST (persist)); - - persist->priv->persist_key = g_strdup (value); -} - -/** - * ephy_embed_persist_set_source: - * @persist: an #EphyEmbedPersist - * @value: the URL from which @persist should download - * - * Sets the URL from which @persist should download. This should be used in - * conjunction with ephy_embed_persist_set_embed(). - **/ -void -ephy_embed_persist_set_source (EphyEmbedPersist *persist, - const char *value) -{ - g_return_if_fail (EPHY_IS_EMBED_PERSIST (persist)); - - persist->priv->source = g_strdup (value); -} - -/** - * ephy_embed_persist_set_user_time: - * @persist: an #EphyEmbedPersist - * @user_time: a timestamp, or 0 - * - * Sets the time stamp of the user action which created @persist. - * Defaults to gtk_get_current_event_time() when @persist is created. - **/ -void -ephy_embed_persist_set_user_time (EphyEmbedPersist *persist, - guint32 user_time) -{ - g_return_if_fail (EPHY_IS_EMBED_PERSIST (persist)); - - LOG ("ephy_embed_persist_set_user_time persist %p user-time %d", - persist, user_time); - - persist->priv->user_time = user_time; -} - -/** - * ephy_embed_persist_get_dest: - * @persist: an #EphyEmbedPersist - * - * Returns the destination filename to which @persist will save its download. - * - * Return value: @persist's destination filename - **/ -const char * -ephy_embed_persist_get_dest (EphyEmbedPersist *persist) -{ - g_return_val_if_fail (EPHY_IS_EMBED_PERSIST (persist), NULL); - - return persist->priv->dest; -} - -/** - * ephy_embed_persist_get_embed: - * @persist: an #EphyEmbedPersist - * - * Returns the #EphyEmbed from which @persist will download. - * - * Return value: (transfer none): the #EphyEmbed from which @persist - * will download - **/ -EphyEmbed * -ephy_embed_persist_get_embed (EphyEmbedPersist *persist) -{ - g_return_val_if_fail (EPHY_IS_EMBED_PERSIST (persist), NULL); - - return persist->priv->embed; -} - -/** - * ephy_embed_persist_get_fc_title: - * @persist: an #EphyEmbedPersist - * - * Returns the title to be displayed in @persist's filechooser. - * - * Return value: the title to be displayed in @persist's filechooser - **/ -const char * -ephy_embed_persist_get_fc_title (EphyEmbedPersist *persist) -{ - g_return_val_if_fail (EPHY_IS_EMBED_PERSIST (persist), NULL); - - return persist->priv->fc_title; -} - -/** - * ephy_embed_persist_get_fc_parent: - * @persist: an #EphyEmbedPersist - * - * Returns the #EphyWindow which should serve as a parent for @persist's - * filechooser. - * - * Return value: (transfer none): the #EphyWindow parent for @persist's - * filechooser - **/ -GtkWindow * -ephy_embed_persist_get_fc_parent (EphyEmbedPersist *persist) -{ - g_return_val_if_fail (EPHY_IS_EMBED_PERSIST (persist), NULL); - - return persist->priv->fc_parent; -} - -/** - * ephy_embed_persist_get_flags: - * @persist: an #EphyEmbedPersist - * - * Returns @persist's #EphyEmbedPersistFlags. - * - * Return value: @persist's #EphyEmbedPersistFlags - **/ -EphyEmbedPersistFlags -ephy_embed_persist_get_flags (EphyEmbedPersist *persist) -{ - g_return_val_if_fail (EPHY_IS_EMBED_PERSIST (persist), 0); - - return persist->priv->flags; -} - -/** - * ephy_embed_persist_get_max_size: - * @persist: an #EphyEmbedPersist - * - * Returns the maximum size of @persist's requested download, in bytes. - * - * Return value: the maximum size of @persist's requested download, in bytes - **/ -gint64 -ephy_embed_persist_get_max_size (EphyEmbedPersist *persist) -{ - g_return_val_if_fail (EPHY_IS_EMBED_PERSIST (persist), 0); - - return persist->priv->max_size; -} - -/** - * ephy_embed_persist_get_persist_key: - * @persist: an #EphyEmbedPersist - * - * Returns the GConf key which determines Epiphany's default download directory. - * - * Return value: the GConf key to the default download directory - **/ -const char * -ephy_embed_persist_get_persist_key (EphyEmbedPersist *persist) -{ - g_return_val_if_fail (EPHY_IS_EMBED_PERSIST (persist), NULL); - - return persist->priv->persist_key; -} - -/** - * ephy_embed_persist_get_source: - * @persist: an #EphyEmbedPersist - * - * Returns the source URL of the file to download. - * - * Return value: a source URL - **/ -const char * -ephy_embed_persist_get_source (EphyEmbedPersist *persist) -{ - g_return_val_if_fail (EPHY_IS_EMBED_PERSIST (persist), NULL); - - return persist->priv->source; -} - -/** - * ephy_embed_persist_get_user_time: - * @persist: an #EphyEmbedPersist - * - * Returns the timestamp of the user action which created @persist. - * If not set explicitly, defaults to gtk_get_current_event_time () - * at the time of creation of @persist. - * - * Return value: a timestamp, or 0 - **/ -guint32 -ephy_embed_persist_get_user_time (EphyEmbedPersist *persist) -{ - g_return_val_if_fail (EPHY_IS_EMBED_PERSIST (persist), 0); - - return persist->priv->user_time; -} - -static void -ephy_embed_persist_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - EphyEmbedPersist *persist = EPHY_EMBED_PERSIST (object); - - switch (prop_id) - { - case PROP_DEST: - ephy_embed_persist_set_dest (persist, g_value_get_string (value)); - break; - case PROP_EMBED: - ephy_embed_persist_set_embed (persist, g_value_get_object (value)); - break; - case PROP_FILECHOOSER_TITLE: - ephy_embed_persist_set_fc_title (persist, g_value_get_string (value)); - break; - case PROP_FILECHOOSER_PARENT: - ephy_embed_persist_set_fc_parent (persist, g_value_get_object (value)); - break; - case PROP_FLAGS: - ephy_embed_persist_set_flags (persist, g_value_get_flags (value)); - break; - case PROP_MAX_SIZE: - ephy_embed_persist_set_max_size (persist, g_value_get_int64 (value)); - break; - case PROP_PERSISTKEY: - ephy_embed_persist_set_persist_key (persist, g_value_get_string (value)); - break; - case PROP_SOURCE: - ephy_embed_persist_set_source (persist, g_value_get_string (value)); - break; - case PROP_USER_TIME: - ephy_embed_persist_set_user_time (persist, g_value_get_uint (value)); - break; - } -} - -static void -ephy_embed_persist_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - EphyEmbedPersist *persist = EPHY_EMBED_PERSIST (object); - - switch (prop_id) - { - case PROP_DEST: - g_value_set_string (value, ephy_embed_persist_get_dest (persist)); - break; - case PROP_EMBED: - g_value_set_object (value, ephy_embed_persist_get_embed (persist)); - break; - case PROP_FILECHOOSER_TITLE: - g_value_set_string (value, ephy_embed_persist_get_fc_title (persist)); - break; - case PROP_FILECHOOSER_PARENT: - g_value_set_object (value, ephy_embed_persist_get_fc_parent (persist)); - break; - case PROP_FLAGS: - g_value_set_flags (value, ephy_embed_persist_get_flags (persist)); - break; - case PROP_MAX_SIZE: - g_value_set_int64 (value, ephy_embed_persist_get_max_size (persist)); - break; - case PROP_PERSISTKEY: - g_value_set_string (value, ephy_embed_persist_get_persist_key (persist)); - break; - case PROP_SOURCE: - g_value_set_string (value, ephy_embed_persist_get_source (persist)); - break; - case PROP_USER_TIME: - g_value_set_uint (value, ephy_embed_persist_get_user_time (persist)); - break; - } -} - -static void -ephy_embed_persist_init (EphyEmbedPersist *persist) -{ - persist->priv = EPHY_EMBED_PERSIST_GET_PRIVATE (persist); - - LOG ("EphyEmbedPersist initialising %p", persist); - - persist->priv->max_size = -1; - persist->priv->dview = NULL; - - ephy_embed_persist_set_user_time (persist, gtk_get_current_event_time ()); -} - -static void -ephy_embed_persist_dispose (GObject *object) -{ - EphyEmbedPersist *persist = EPHY_EMBED_PERSIST (object); - EphyEmbedPersistPrivate *priv = persist->priv; - - if (priv->download) - { - g_object_unref (priv->download); - priv->download = NULL; - } - - LOG ("EphyEmbedPersist disposed %p", object); - - G_OBJECT_CLASS (ephy_embed_persist_parent_class)->dispose (object); -} - -static void -ephy_embed_persist_finalize (GObject *object) -{ - EphyEmbedPersist *persist = EPHY_EMBED_PERSIST (object); - EphyEmbedPersistPrivate *priv = persist->priv; - GtkWindow **wptr; - - g_free (priv->dest); - g_free (priv->source); - g_free (priv->fc_title); - g_free (priv->persist_key); - - if (priv->fc_parent != NULL) - { - wptr = &priv->fc_parent; - g_object_remove_weak_pointer (G_OBJECT (priv->fc_parent), - (gpointer *) wptr); - } - - LOG ("EphyEmbedPersist finalised %p", object); - - G_OBJECT_CLASS (ephy_embed_persist_parent_class)->finalize (object); -} - -static void -ephy_embed_persist_class_init (EphyEmbedPersistClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = ephy_embed_persist_finalize; - object_class->dispose = ephy_embed_persist_dispose; - object_class->set_property = ephy_embed_persist_set_property; - object_class->get_property = ephy_embed_persist_get_property; - - /* init signals */ -/** - * EphyEmbedPersist::completed: - * - * The ::completed signal is emitted when @persist has finished downloading. The - * download must have started with ephy_embed_persist_save(). - **/ - g_signal_new ("completed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EphyEmbedPersistClass, completed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, - 0); -/** - * EphyEmbedPersist::cancelled: - * - * The ::cancelled signal is emitted when @persist's download has been - * cancelled with ephy_embed_persist_cancel(). - **/ - g_signal_new ("cancelled", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EphyEmbedPersistClass, cancelled), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, - 0); - - g_object_class_install_property (object_class, - PROP_DEST, - g_param_spec_string ("dest", - "Destination", - "Destination file path", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - g_object_class_install_property (object_class, - PROP_EMBED, - g_param_spec_object ("embed", - "Embed", - "The embed containing the document", - G_TYPE_OBJECT, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | - G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property (object_class, - PROP_FILECHOOSER_TITLE, - g_param_spec_string ("filechooser-title", - "Filechooser title", - "Title to use if showing filechooser", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - g_object_class_install_property (object_class, - PROP_FILECHOOSER_PARENT, - g_param_spec_object ("filechooser-parent", - "Filechooser parent", - "The parent window for the filechooser", - GTK_TYPE_WINDOW, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - g_object_class_install_property (object_class, - PROP_FLAGS, - g_param_spec_flags ("flags", - "Flags", - "Flags", - EPHY_TYPE_EMBED_PERSIST_FLAGS, - 0, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - g_object_class_install_property (object_class, - PROP_MAX_SIZE, - g_param_spec_int64 ("max-size", - "Maxsize", - "Maximum size of the file", - -1, - G_MAXINT64, - -1, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - g_object_class_install_property (object_class, - PROP_PERSISTKEY, - g_param_spec_string ("persist-key", - "persist key", - "Path persistence gconf key", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - g_object_class_install_property (object_class, - PROP_SOURCE, - g_param_spec_string ("source", - "Source", - "Url of the document to save", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - g_object_class_install_property (object_class, - PROP_USER_TIME, - g_param_spec_uint ("user-time", - "User Time", - "User Time", - 0, - G_MAXUINT, - 0, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - g_type_class_add_private (object_class, sizeof(EphyEmbedPersistPrivate)); -} - -/** - * ephy_embed_persist_cancel: - * @persist: an #EphyEmbedPersist - * - * Cancels @persist's download. This will not delete the partially downloaded - * file. - **/ -void -ephy_embed_persist_cancel (EphyEmbedPersist *persist) -{ - g_return_if_fail (EPHY_IS_EMBED_PERSIST (persist)); - - /* webkit_download_cancel() triggers download_status_changed_cb() with - * status = WEBKIT_DOWNLOAD_STATUS_CANCELLED so we don't need to emit - * the signal. - */ - if (persist->priv->download) - { - webkit_download_cancel (persist->priv->download); - } - else - { - g_object_unref (persist); - } -} - -static void -response_cb (GtkDialog *dialog, - int response_id, - EphyEmbedPersist *persist) -{ - WebKitDownload *download; - - download = persist->priv->download; - - if (response_id == GTK_RESPONSE_ACCEPT) - { - char *uri; - - uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER(dialog)); - - if (persist->priv->dview) - downloader_view_add_download (persist->priv->dview, download); - - webkit_download_set_destination_uri (download, uri); - webkit_download_start (download); - - g_free (uri); - } - else - { - g_object_unref (persist); - } - - gtk_widget_destroy (GTK_WIDGET (dialog)); -} - -static void -download_status_changed_cb (GObject *object, - GParamSpec *pspec, - EphyEmbedPersist *persist) -{ - EphyEmbedPersistPrivate *priv; - WebKitDownload *download; - WebKitDownloadStatus status; - - priv = persist->priv; - download = WEBKIT_DOWNLOAD (object); - status = webkit_download_get_status (download); - - if (status == WEBKIT_DOWNLOAD_STATUS_FINISHED) - { - g_signal_emit_by_name (persist, "completed"); - g_object_unref (persist); - } - else if (status == WEBKIT_DOWNLOAD_STATUS_CANCELLED || - status == WEBKIT_DOWNLOAD_STATUS_ERROR) - { - g_signal_emit_by_name (persist, "cancelled"); - g_object_unref (persist); - } -} - -/** - * ephy_embed_persist_save: - * @persist: an #EphyEmbedPersist - * - * Begins saving the file specified in @persist. - * - * If @persist's #EphyEmbedPersistFlags include %EPHY_EMBED_PERSIST_ASK_DESTINATION, a - * filechooser dialog will be shown first. If this flag is not set and no - * destination has been set, the target will be saved to the default download - * directory using the suggested name, if no suggested name can be get the - * download will fail. - * - * The file will continue to download in the background until either the - * ::completed or the ::cancelled signals are emitted by @persist. - * - * Return value: %TRUE if the download began successfully - **/ -gboolean -ephy_embed_persist_save (EphyEmbedPersist *persist) -{ - EphyEmbedPersistPrivate *priv; - WebKitNetworkRequest *request; - - g_return_val_if_fail (EPHY_IS_EMBED_PERSIST (persist), FALSE); - - priv = persist->priv; - g_return_val_if_fail (priv->source != NULL, FALSE); - - /* Balanced when priv->download is not needed anymore: here, in - * ephy_embed_persist_cancel() and in download_status_changed_cb(). - */ - g_object_ref (persist); - - if (priv->embed) - { - EphyWebView *web_view; - SoupMessage *msg; - gchar *referer; - - /* Get the webview associated to the embed */ - web_view = ephy_embed_get_web_view (priv->embed); - - /* Create the request with a SoupMessage to allow - setting the 'Referer' as got from the embed */ - msg = soup_message_new (SOUP_METHOD_GET, priv->source); - request = WEBKIT_NETWORK_REQUEST ( - g_object_new (WEBKIT_TYPE_NETWORK_REQUEST, - "message", msg, - NULL)); - - /* Add the referer to the request headers */ - referer = ephy_web_view_get_location (web_view, FALSE); - soup_message_headers_append (msg->request_headers, - "Referer", referer); - g_free (referer); - g_object_unref (msg); - } - else - { - /* Create a normal network request otherwise */ - request = webkit_network_request_new (priv->source); - } - - priv->download = webkit_download_new (request); - g_object_unref (request); - - g_signal_connect (priv->download, "notify::status", - G_CALLBACK (download_status_changed_cb), - persist); - - /* Should we include downloads in DownloaderView? */ - if (!(priv->flags & EPHY_EMBED_PERSIST_NO_VIEW)) - { - priv->dview = EPHY_DOWNLOADER_VIEW - (ephy_embed_shell_get_downloader_view (embed_shell)); - - g_object_set_data (G_OBJECT (priv->download), "download-action", - GINT_TO_POINTER (DOWNLOAD_ACTION_DOWNLOAD)); - } - - if (priv->flags & EPHY_EMBED_PERSIST_ASK_DESTINATION) - { - EphyFileChooser *dialog; - GtkWidget *window; - const char *suggested_filename; - - suggested_filename = webkit_download_get_suggested_filename (priv->download); - window = GTK_WIDGET (priv->fc_parent); - - dialog = ephy_file_chooser_new (priv->fc_title ? - priv->fc_title : _("Save"), - window, - GTK_FILE_CHOOSER_ACTION_SAVE, - priv->persist_key, - EPHY_FILE_FILTER_ALL); - - gtk_file_chooser_set_do_overwrite_confirmation - (GTK_FILE_CHOOSER (dialog), TRUE); - gtk_file_chooser_set_current_name - (GTK_FILE_CHOOSER (dialog), suggested_filename); - - g_signal_connect (dialog, "response", - G_CALLBACK (response_cb), persist); - - gtk_widget_show (GTK_WIDGET (dialog)); - - return TRUE; - } - else - { - char *dest_uri; - - if (priv->dest) - { - dest_uri = g_filename_to_uri (priv->dest, NULL, NULL); - } - else - { - const char *suggested_filename = NULL; - char *downloads_dir; - char *dest_filename; - - suggested_filename = webkit_download_get_suggested_filename (priv->download); - - if (suggested_filename == NULL) - { - g_object_unref (persist); - return FALSE; - } - - downloads_dir = ephy_file_get_downloads_dir (); - dest_filename = g_build_filename (downloads_dir, - suggested_filename, - NULL); - g_free (downloads_dir); - - priv->dest = dest_filename; - dest_uri = g_filename_to_uri (dest_filename, NULL, NULL); - } - - if (priv->dview) - downloader_view_add_download (priv->dview, priv->download); - - webkit_download_set_destination_uri (priv->download, dest_uri); - webkit_download_start (priv->download); - - g_free (dest_uri); - - return TRUE; - } - - g_object_unref (persist); - return FALSE; -} - -/** - * ephy_embed_persist_to_string: - * @persist: an #EphyEmbedPersist - * - * Returns the download specified by @persist as a string instead of downloading - * it to a file. - * - * The download is synchronous. An #EphyEmbed must be specified with - * ephy_embed_persist_set_embed(). The function implicitly assumes that - * @persist's #EphyEmbedPersistFlags include %EPHY_EMBED_PERSIST_COPY_PAGE. If @persist's - * #EphyEmbed has not finished downloading, this function will only return the - * portion of data which has already been downloaded. - * - * The document will be modified: it will only include absolute links and it - * will be encoded as UTF-8. - * - * Return value: The contents of @persist's #EphyEmbed's web page - **/ -char * -ephy_embed_persist_to_string (EphyEmbedPersist *persist) -{ - g_return_val_if_fail (EPHY_IS_EMBED_PERSIST (persist), NULL); - return NULL; -} diff --git a/embed/ephy-embed-persist.h b/embed/ephy-embed-persist.h deleted file mode 100644 index 8dcc848e0..000000000 --- a/embed/ephy-embed-persist.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright © 2000-2003 Marco Pesenti Gritti - * Copyright © 2003 Christian Persch - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#if !defined (__EPHY_EPIPHANY_H_INSIDE__) && !defined (EPIPHANY_COMPILATION) -#error "Only <epiphany/epiphany.h> can be included directly." -#endif - -#ifndef EPHY_EMBED_PERSIST_H -#define EPHY_EMBED_PERSIST_H - -#include "ephy-embed.h" - -#include <glib-object.h> -#include <glib.h> - -#include <gtk/gtk.h> - -G_BEGIN_DECLS - -#define EPHY_TYPE_EMBED_PERSIST (ephy_embed_persist_get_type ()) -#define EPHY_EMBED_PERSIST(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EPHY_TYPE_EMBED_PERSIST, EphyEmbedPersist)) -#define EPHY_EMBED_PERSIST_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), EPHY_TYPE_EMBED_PERSIST, EphyEmbedPersistClass)) -#define EPHY_IS_EMBED_PERSIST(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EPHY_TYPE_EMBED_PERSIST)) -#define EPHY_IS_EMBED_PERSIST_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EPHY_TYPE_EMBED_PERSIST)) -#define EPHY_EMBED_PERSIST_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EPHY_TYPE_EMBED_PERSIST, EphyEmbedPersistClass)) - -typedef struct _EphyEmbedPersistClass EphyEmbedPersistClass; -typedef struct _EphyEmbedPersist EphyEmbedPersist; -typedef struct _EphyEmbedPersistPrivate EphyEmbedPersistPrivate; - -typedef enum -{ - EPHY_EMBED_PERSIST_COPY_PAGE = 1 << 0, - EPHY_EMBED_PERSIST_MAINDOC = 1 << 1, - EPHY_EMBED_PERSIST_NO_VIEW = 1 << 2, - EPHY_EMBED_PERSIST_ASK_DESTINATION = 1 << 3, - EPHY_EMBED_PERSIST_DO_CONVERSION = 1 << 4, - EPHY_EMBED_PERSIST_FROM_CACHE = 1 << 5, - EPHY_EMBED_PERSIST_NO_CERTDIALOGS = 1 << 6, - EPHY_EMBED_PERSIST_NO_COOKIES = 1 << 7 -} EphyEmbedPersistFlags; - -struct _EphyEmbedPersist -{ - GObject parent; - - /*< private >*/ - EphyEmbedPersistPrivate *priv; -}; - -struct _EphyEmbedPersistClass -{ - GObjectClass parent_class; - - void (* completed) (EphyEmbedPersist *persist); - void (* cancelled) (EphyEmbedPersist *persist); -}; - -GType ephy_embed_persist_flags_get_type (void); - -GType ephy_embed_persist_get_type (void); - -gboolean ephy_embed_persist_save (EphyEmbedPersist *persist); - -void ephy_embed_persist_cancel (EphyEmbedPersist *persist); - -void ephy_embed_persist_set_dest (EphyEmbedPersist *persist, - const char *value); - -void ephy_embed_persist_set_embed (EphyEmbedPersist *persist, - EphyEmbed *value); - -void ephy_embed_persist_set_fc_title (EphyEmbedPersist *persist, - const char *value); - -void ephy_embed_persist_set_fc_parent (EphyEmbedPersist *persist, - GtkWindow *value); - -void ephy_embed_persist_set_flags (EphyEmbedPersist *persist, - EphyEmbedPersistFlags value); - -void ephy_embed_persist_set_max_size (EphyEmbedPersist *persist, - gint64 value); - -void ephy_embed_persist_set_persist_key (EphyEmbedPersist *persist, - const char *value); - -void ephy_embed_persist_set_source (EphyEmbedPersist *persist, - const char *value); -void ephy_embed_persist_set_user_time (EphyEmbedPersist *persist, - guint32 user_time); - -const char *ephy_embed_persist_get_dest (EphyEmbedPersist *persist); - -EphyEmbed *ephy_embed_persist_get_embed (EphyEmbedPersist *persist); - -const char *ephy_embed_persist_get_fc_title (EphyEmbedPersist *persist); - -GtkWindow *ephy_embed_persist_get_fc_parent (EphyEmbedPersist *persist); - -EphyEmbedPersistFlags ephy_embed_persist_get_flags (EphyEmbedPersist *persist); - -gint64 ephy_embed_persist_get_max_size (EphyEmbedPersist *persist); - -const char *ephy_embed_persist_get_persist_key (EphyEmbedPersist *persist); - -const char *ephy_embed_persist_get_source (EphyEmbedPersist *persist); - -guint32 ephy_embed_persist_get_user_time (EphyEmbedPersist *persist); - -char *ephy_embed_persist_to_string (EphyEmbedPersist *persist); - -G_END_DECLS - -#endif diff --git a/embed/ephy-embed-shell.c b/embed/ephy-embed-shell.c index 3fcf7ee82..a0d77cdc6 100644 --- a/embed/ephy-embed-shell.c +++ b/embed/ephy-embed-shell.c @@ -25,9 +25,9 @@ #include <glib/gstdio.h> #include <gtk/gtk.h> -#include "downloader-view.h" #include "ephy-adblock-manager.h" #include "ephy-debug.h" +#include "ephy-download.h" #include "ephy-embed-shell.h" #include "ephy-embed-single.h" #include "ephy-encodings.h" @@ -50,7 +50,7 @@ struct _EphyEmbedShellPrivate { EphyHistory *global_history; - DownloaderView *downloader_view; + GList *downloads; EphyFaviconCache *favicon_cache; EphyEmbedSingle *embed_single; EphyEncodings *encodings; @@ -63,6 +63,8 @@ struct _EphyEmbedShellPrivate enum { + DOWNLOAD_ADDED, + DOWNLOAD_REMOVED, PREPARE_CLOSE, QUIT, LAST_SIGNAL @@ -83,17 +85,6 @@ ephy_embed_shell_dispose (GObject *object) EphyEmbedShell *shell = EPHY_EMBED_SHELL (object); EphyEmbedShellPrivate *priv = shell->priv; - if (priv->downloader_view != NULL) - { - DownloaderView **downloader_view = &priv->downloader_view; - LOG ("Unref downloader"); - g_object_remove_weak_pointer - (G_OBJECT (priv->downloader_view), - (gpointer *) downloader_view); - g_object_unref (priv->downloader_view); - priv->downloader_view = NULL; - } - if (priv->favicon_cache != NULL) { LOG ("Unref favicon cache"); @@ -128,6 +119,14 @@ ephy_embed_shell_finalize (GObject *object) { EphyEmbedShell *shell = EPHY_EMBED_SHELL (object); + if (shell->priv->downloads != NULL) + { + LOG ("Destroying downloads list"); + g_list_foreach (shell->priv->downloads, (GFunc) g_object_unref, NULL); + g_list_free (shell->priv->downloads); + shell->priv->downloads = NULL; + } + if (shell->priv->global_history) { LOG ("Unref history"); @@ -190,44 +189,6 @@ ephy_embed_shell_get_global_history (EphyEmbedShell *shell) return G_OBJECT (shell->priv->global_history); } -/** - * ephy_embed_shell_get_downloader_view: - * @shell: the #EphyEmbedShell - * - * Return value: (transfer none): - **/ -GObject * -ephy_embed_shell_get_downloader_view (EphyEmbedShell *shell) -{ - g_return_val_if_fail (EPHY_IS_EMBED_SHELL (shell), NULL); - - if (shell->priv->downloader_view == NULL) - { - DownloaderView **downloader_view; - shell->priv->downloader_view = downloader_view_new (); - downloader_view = &shell->priv->downloader_view; - g_object_add_weak_pointer - (G_OBJECT(shell->priv->downloader_view), - (gpointer *) downloader_view); - } - - return G_OBJECT (shell->priv->downloader_view); -} - -/** - * ephy_embed_shell_get_downloader_view_nocreate: - * @shell: the #EphyEmbedShell - * - * Return value: (transfer none): - **/ -GObject * -ephy_embed_shell_get_downloader_view_nocreate (EphyEmbedShell *shell) -{ - g_return_val_if_fail (EPHY_IS_EMBED_SHELL (shell), NULL); - - return (GObject *) shell->priv->downloader_view; -} - static GObject * impl_get_embed_single (EphyEmbedShell *shell) { @@ -319,6 +280,8 @@ ephy_embed_shell_init (EphyEmbedShell *shell) /* globally accessible singleton */ g_assert (embed_shell == NULL); embed_shell = shell; + + shell->priv->downloads = NULL; } static void @@ -332,6 +295,40 @@ ephy_embed_shell_class_init (EphyEmbedShellClass *klass) klass->get_embed_single = impl_get_embed_single; /** + * EphyEmbed::download-added: + * @shell: the #EphyEmbedShell + * @download: the #EphyDownload added + * + * Emitted when a #EphyDownload has been added to the global watch list of + * @shell, via ephy_embed_shell_add_download. + **/ + signals[DOWNLOAD_ADDED] = + g_signal_new ("download-added", + EPHY_TYPE_EMBED_SHELL, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EphyEmbedShellClass, download_added), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, EPHY_TYPE_DOWNLOAD); + +/** + * EphyEmbed::download-removed: + * @shell: the #EphyEmbedShell + * @download: the #EphyDownload being removed + * + * Emitted when a #EphyDownload has been removed from the global watch list of + * @shell, via ephy_embed_shell_remove_download. + **/ + signals[DOWNLOAD_REMOVED] = + g_signal_new ("download-removed", + EPHY_TYPE_EMBED_SHELL, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EphyEmbedShellClass, download_removed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, EPHY_TYPE_DOWNLOAD); + +/** * EphyEmbed::prepare-close: * @shell: the #EphyEmbedShell * @@ -563,6 +560,51 @@ ephy_embed_shell_get_print_settings (EphyEmbedShell *shell) return priv->print_settings; } +/** + * ephy_embed_shell_get_downloads: + * @shell: the #EphyEmbedShell + * + * Gets the global #GList object listing active downloads. + * + * Returns: (transfer none): a #GList object + **/ +GList * +ephy_embed_shell_get_downloads (EphyEmbedShell *shell) +{ + EphyEmbedShellPrivate *priv; + + g_return_val_if_fail (EPHY_IS_EMBED_SHELL (shell), NULL); + priv = shell->priv; + + return priv->downloads; +} + +void +ephy_embed_shell_add_download (EphyEmbedShell *shell, EphyDownload *download) +{ + EphyEmbedShellPrivate *priv; + + g_return_if_fail (EPHY_IS_EMBED_SHELL (shell)); + + priv = shell->priv; + priv->downloads = g_list_prepend (priv->downloads, download); + + g_signal_emit_by_name (shell, "download-added", download, NULL); +} + +void +ephy_embed_shell_remove_download (EphyEmbedShell *shell, EphyDownload *download) +{ + EphyEmbedShellPrivate *priv; + + g_return_if_fail (EPHY_IS_EMBED_SHELL (shell)); + + priv = shell->priv; + priv->downloads = g_list_remove (priv->downloads, download); + + g_signal_emit_by_name (shell, "download-removed", download, NULL); +} + static void object_notify_cb (EphyEmbedShell *shell, GObject *object) diff --git a/embed/ephy-embed-shell.h b/embed/ephy-embed-shell.h index c58df978c..00087fa9b 100644 --- a/embed/ephy-embed-shell.h +++ b/embed/ephy-embed-shell.h @@ -28,6 +28,8 @@ #include <glib-object.h> #include <gtk/gtk.h> +#include "ephy-download.h" + G_BEGIN_DECLS #define EPHY_TYPE_EMBED_SHELL (ephy_embed_shell_get_type ()) @@ -55,6 +57,9 @@ struct _EphyEmbedShellClass { GObjectClass parent_class; + void (* download_added) (EphyEmbedShell *shell, EphyDownload *download); + void (* download_removed) (EphyEmbedShell *shell, EphyDownload *download); + void (* prepare_close) (EphyEmbedShell *shell); /*< private >*/ @@ -69,10 +74,6 @@ GObject *ephy_embed_shell_get_favicon_cache (EphyEmbedShell *shell); GObject *ephy_embed_shell_get_global_history (EphyEmbedShell *shell); -GObject *ephy_embed_shell_get_downloader_view (EphyEmbedShell *shell); - -GObject *ephy_embed_shell_get_downloader_view_nocreate (EphyEmbedShell *shell); - GObject *ephy_embed_shell_get_encodings (EphyEmbedShell *shell); GObject *ephy_embed_shell_get_embed_single (EphyEmbedShell *shell); @@ -91,6 +92,13 @@ void ephy_embed_shell_set_print_settings (EphyEmbedShell *shell, GtkPrintSettings *ephy_embed_shell_get_print_settings (EphyEmbedShell *shell); +GList *ephy_embed_shell_get_downloads (EphyEmbedShell *shell); + +void ephy_embed_shell_add_download (EphyEmbedShell *shell, + EphyDownload *download); +void ephy_embed_shell_remove_download (EphyEmbedShell *shell, + EphyDownload *download); + /* Private API */ void _ephy_embed_shell_track_object (EphyEmbedShell *shell, GObject *object); diff --git a/embed/ephy-embed.c b/embed/ephy-embed.c index ebd34d163..6f008f565 100644 --- a/embed/ephy-embed.c +++ b/embed/ephy-embed.c @@ -25,14 +25,13 @@ #include "config.h" -#include "downloader-view.h" #include "ephy-adblock-manager.h" #include "ephy-debug.h" +#include "ephy-download.h" #include "ephy-embed.h" #include "ephy-embed-event.h" #include "ephy-embed-shell.h" #include "ephy-embed-single.h" -#include "ephy-embed-persist.h" #include "ephy-embed-prefs.h" #include "ephy-embed-utils.h" #include "ephy-file-chooser.h" @@ -359,458 +358,14 @@ ephy_embed_inspect_close_cb (WebKitWebInspector *inspector, return TRUE; } -static void -download_requested_dialog_response_cb (GtkDialog *dialog, - int response_id, - WebKitDownload *download) -{ - if (response_id == GTK_RESPONSE_ACCEPT) { - DownloaderView *dview; - char *uri; - - uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog)); - g_object_set_data (G_OBJECT (download), "user-destination-uri", uri); - - dview = EPHY_DOWNLOADER_VIEW (ephy_embed_shell_get_downloader_view (embed_shell)); - downloader_view_add_download (dview, download); - } else { - webkit_download_cancel (download); - ephy_file_delete_uri (webkit_download_get_destination_uri (download)); - } - - gtk_widget_destroy (GTK_WIDGET (dialog)); - /* User provided us with a destination or cancelled, unfreeze. */ - g_object_thaw_notify (G_OBJECT (download)); - g_object_unref (download); -} - -static void -request_destination_uri (WebKitWebView *web_view, - WebKitDownload *download) -{ - EphyFileChooser *dialog; - GtkWidget *window; - const char *suggested_filename; - - suggested_filename = webkit_download_get_suggested_filename (download); - - /* - * Try to get the toplevel window related to the WebView that caused - * the download, and use NULL otherwise; we don't want to pass the - * WebView or other widget as a parent window. - */ - window = gtk_widget_get_toplevel (GTK_WIDGET (web_view)); - if (!gtk_widget_is_toplevel (window)) - window = NULL; - - dialog = ephy_file_chooser_new (_("Save"), - window, - GTK_FILE_CHOOSER_ACTION_SAVE, - EPHY_PREFS_STATE_SAVE_DIR, - EPHY_FILE_FILTER_ALL_SUPPORTED); - gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE); - gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), suggested_filename); - - g_signal_connect (dialog, "response", - G_CALLBACK (download_requested_dialog_response_cb), download); - - gtk_widget_show_all (GTK_WIDGET (dialog)); -} - -/* From the old embed/mozilla/MozDownload.cpp */ -static const char* -file_is_compressed (const char *filename) -{ - int i; - static const char * const compression[] = {".gz", ".bz2", ".Z", ".lz", NULL}; - - for (i = 0; compression[i] != NULL; i++) { - if (g_str_has_suffix (filename, compression[i])) - return compression[i]; - } - - return NULL; -} - -static const char* -parse_extension (const char *filename) -{ - const char *compression; - const char *last_separator; - - compression = file_is_compressed (filename); - - /* if the file is compressed we might have a double extension */ - if (compression != NULL) { - int i; - static const char * const extensions[] = {"tar", "ps", "xcf", "dvi", "txt", "text", NULL}; - - for (i = 0; extensions[i] != NULL; i++) { - char *suffix; - suffix = g_strdup_printf (".%s%s", extensions[i], compression); - - if (g_str_has_suffix (filename, suffix)) { - char *p; - - p = g_strrstr (filename, suffix); - g_free (suffix); - - return p; - } - - g_free (suffix); - } - } - - /* no compression, just look for the last dot in the filename */ - last_separator = strrchr (filename, G_DIR_SEPARATOR); - return strrchr ((last_separator) ? last_separator : filename, '.'); -} - -static gboolean -define_destination_uri (WebKitDownload *download, - gboolean temporary) -{ - char *tmp_dir; - char *destination_filename; - char *destination_uri; - const char *suggested_filename; - - suggested_filename = webkit_download_get_suggested_filename (download); - - /* If we are not doing an automatic download, use a temporary file - * to start the download while we ask the user for the location to - * where the file must go. - */ - if (temporary) - tmp_dir = g_build_filename (ephy_dot_dir (), "downloads", NULL); - else - tmp_dir = ephy_file_get_downloads_dir (); - - /* Make sure the download directory exists */ - if (g_mkdir_with_parents (tmp_dir, 0700) == -1) { - g_critical ("Could not create downloads directory \"%s\": %s", - tmp_dir, strerror (errno)); - g_free (tmp_dir); - return FALSE; - } - - destination_filename = g_build_filename (tmp_dir, suggested_filename, NULL); - - if (g_file_test (destination_filename, G_FILE_TEST_EXISTS)) { - int i = 1; - const char *dot_pos; - gssize position; - char *serial = NULL; - GString *tmp_filename; - - dot_pos = parse_extension (destination_filename); - if (dot_pos) - position = dot_pos - destination_filename; - else - position = strlen (destination_filename); - - tmp_filename = g_string_new (NULL); - - do { - serial = g_strdup_printf ("(%d)", i++); - - g_string_assign (tmp_filename, destination_filename); - g_string_insert (tmp_filename, position, serial); - - g_free (serial); - } while (g_file_test (tmp_filename->str, G_FILE_TEST_EXISTS)); - - destination_filename = g_strdup (tmp_filename->str); - g_string_free (tmp_filename, TRUE); - } - - destination_uri = g_strconcat ("file://", destination_filename, NULL); - - LOG ("define_destination_uri: Downloading to %s", destination_filename); - - webkit_download_set_destination_uri (download, destination_uri); - - g_free (tmp_dir); - g_free (destination_filename); - g_free (destination_uri); - - return TRUE; -} - -static gboolean -perform_auto_download (WebKitDownload *download) -{ - DownloaderView *dview; - - if (!define_destination_uri (download, FALSE)) { - webkit_download_cancel (download); - ephy_file_delete_uri (webkit_download_get_destination_uri (download)); - return FALSE; - } - - dview = EPHY_DOWNLOADER_VIEW (ephy_embed_shell_get_downloader_view (embed_shell)); - - g_object_set_data (G_OBJECT(download), "download-action", GINT_TO_POINTER(DOWNLOAD_ACTION_OPEN)); - downloader_view_add_download (dview, download); - - return TRUE; -} - void ephy_embed_auto_download_url (EphyEmbed *embed, const char *url) { - WebKitNetworkRequest *request; - WebKitDownload *download; - - request = webkit_network_request_new (url); - download = webkit_download_new (request); - g_object_unref (request); - - if (perform_auto_download (download)) - webkit_download_start (download); -} - -static void -confirm_action_response_cb (GtkWidget *dialog, - int response, - WebKitDownload *download) -{ - WebKitWebView *web_view = g_object_get_data (G_OBJECT(dialog), "webkit-view"); - DownloaderView *dview; - - gtk_widget_destroy (dialog); - - if (response > 0) { - switch (response) { - case DOWNLOAD_ACTION_OPEN: - g_object_set_data (G_OBJECT (download), "download-action", - GINT_TO_POINTER (DOWNLOAD_ACTION_OPEN)); - break; - case DOWNLOAD_ACTION_DOWNLOAD: - case DOWNLOAD_ACTION_OPEN_LOCATION: - g_object_set_data (G_OBJECT (download), "download-action", - GINT_TO_POINTER (DOWNLOAD_ACTION_OPEN_LOCATION)); - break; - } - - if (response == DOWNLOAD_ACTION_DOWNLOAD) { - /* balanced in download_requested_dialog_response_cb */ - g_object_ref (download); - request_destination_uri (web_view, download); - } else { - if (!define_destination_uri (download, FALSE)) { - goto cleanup; - } - dview = EPHY_DOWNLOADER_VIEW (ephy_embed_shell_get_downloader_view (embed_shell)); - downloader_view_add_download (dview, download); - /* User selected "Open", he won't be providing a destination, unfreeze. */ - g_object_thaw_notify (G_OBJECT (download)); - } - g_object_unref (download); - return; - } + EphyDownload *download; -cleanup: - webkit_download_cancel (download); - ephy_file_delete_uri (webkit_download_get_destination_uri (download)); - g_object_unref (download); -} - -static void -confirm_action_from_mime (WebKitWebView *web_view, - WebKitDownload *download, - DownloadAction action) -{ - GtkWidget *parent_window; - GtkWidget *dialog; - const char *action_label; - char *mime_description; - EphyMimePermission mime_permission; - GAppInfo *helper_app; - const char *suggested_filename; - int default_response; - WebKitNetworkResponse *response; - SoupMessage *message; - GtkMessageType mtype; - char *title; - char *secondary; - - parent_window = gtk_widget_get_toplevel (GTK_WIDGET(web_view)); - if (!gtk_widget_is_toplevel (parent_window)) - parent_window = NULL; - - helper_app = NULL; - mime_description = NULL; - mime_permission = EPHY_MIME_PERMISSION_SAFE; - - response = webkit_download_get_network_response (download); - message = webkit_network_response_get_message (response); - - if (message) { - const char *content_type = soup_message_headers_get_content_type (message->response_headers, NULL); - - if (content_type) { - mime_description = g_content_type_get_description (content_type); - helper_app = g_app_info_get_default_for_type (content_type, FALSE); - mime_permission = ephy_file_check_mime (content_type); - - if (helper_app) - action = DOWNLOAD_ACTION_OPEN; - } - } - - if (mime_description == NULL) { - mime_description = g_strdup (C_("file type", "Unknown")); - action = DOWNLOAD_ACTION_OPEN_LOCATION; - } - - /* Sometimes downloads can have a mime_description but a NULL helper_app - * in that case action is never changed so DOWNLOAD_ACTION_DOWNLOAD remains - * as action value. This is the same response value as Save as... - * button, which is wrong for the Download button. - */ - if (helper_app == NULL) - action = DOWNLOAD_ACTION_OPEN_LOCATION; - - action_label = (action == DOWNLOAD_ACTION_OPEN) ? GTK_STOCK_OPEN : STOCK_DOWNLOAD; - suggested_filename = webkit_download_get_suggested_filename (download); - - if (mime_permission != EPHY_MIME_PERMISSION_SAFE && helper_app) { - title = _("Download this potentially unsafe file?"); - mtype = GTK_MESSAGE_WARNING; - /* translators: First %s is the file type description, second %s is the - * file name */ - secondary = g_strdup_printf (_("File Type: “%s”.\n\nIt is unsafe to open " - "“%s” as it could potentially damage your " - "documents or invade your privacy. " - "You can download it instead."), - mime_description, suggested_filename); - - action_label = STOCK_DOWNLOAD; - } else if (action == DOWNLOAD_ACTION_OPEN && helper_app) { - title = _("Open this file?"); - mtype = GTK_MESSAGE_QUESTION; - /* translators: First %s is the file type description, second %s is the - * file name, third %s is the application used to open the file */ - secondary = g_strdup_printf (_("File Type: “%s”.\n\nYou can open “%s” " - "using “%s” or save it."), - mime_description, suggested_filename, - g_app_info_get_name (helper_app)); - } else { - title = _("Download this file?"); - mtype = GTK_MESSAGE_QUESTION; - /* translators: First %s is the file type description, second %s is the - * file name */ - secondary = g_strdup_printf (_("File Type: “%s”.\n\nYou have no " - "application able to open “%s”. " - "You can download it instead."), - mime_description, suggested_filename); - } - - dialog = gtk_message_dialog_new (GTK_WINDOW (parent_window), - GTK_DIALOG_DESTROY_WITH_PARENT, - mtype, GTK_BUTTONS_NONE, - title); - gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), - secondary, NULL); - - g_free (mime_description); - - gtk_dialog_add_button (GTK_DIALOG (dialog), - GTK_STOCK_SAVE_AS, DOWNLOAD_ACTION_DOWNLOAD); - gtk_dialog_add_button (GTK_DIALOG (dialog), - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); - gtk_dialog_add_button (GTK_DIALOG (dialog), - action_label, action); - - gtk_window_set_icon_name (GTK_WINDOW (dialog), EPHY_STOCK_EPHY); - - default_response = (action == DOWNLOAD_ACTION_NONE) ? - (int) GTK_RESPONSE_CANCEL : (int) action; - - gtk_dialog_set_default_response (GTK_DIALOG (dialog), default_response); - - g_object_set_data (G_OBJECT (dialog), "webkit-view", web_view); - g_signal_connect (dialog, "response", - G_CALLBACK (confirm_action_response_cb), - download); - - gtk_window_present (GTK_WINDOW (dialog)); -} - -static void -download_status_changed_cb (GObject *object, - GParamSpec *pspec, - EphyEmbed *embed) -{ - WebKitDownload *download = WEBKIT_DOWNLOAD (object); - - if (webkit_download_get_status (download) == WEBKIT_DOWNLOAD_STATUS_FINISHED) - { - GFile *destination; - GFile *temp; - char *destination_uri; - const char *temp_uri; - - temp_uri = webkit_download_get_destination_uri (download); - destination_uri = g_object_get_data (G_OBJECT (download), - "user-destination-uri"); - - LOG ("download_status_changed_cb: finished, moving temp file %s to %s", - temp_uri, destination_uri); - - /* No user-destination-uri is set, hence this is an auto download and we - * have nothing else to do. */ - if (destination_uri == NULL) return; - - temp = g_file_new_for_uri (temp_uri); - destination = g_file_new_for_uri (destination_uri); - - ephy_file_switch_temp_file (destination, temp); - - g_object_unref (destination); - g_object_unref (temp); - } - else if (webkit_download_get_status (download) == WEBKIT_DOWNLOAD_STATUS_STARTED) - { - /* Prevent this callback from being called before the user has selected a - * destination. It is freed either here or in - * download_requested_dialog_response_cb(). Both situations are mutually - * exclusive. - * - * This freeze is removed either here below, in - * download_requested_dialog_response_cb() or confirm_action_response_cb(). - */ - g_object_freeze_notify (G_OBJECT (download)); - - if (g_settings_get_boolean (EPHY_SETTINGS_MAIN, - EPHY_PREFS_AUTO_DOWNLOADS)) { - perform_auto_download (download); - /* User won't select a destination, unfreeze. */ - g_object_thaw_notify (G_OBJECT (download)); - return; - } - - /* Balanced in confirm_action_response_cb. */ - g_object_ref (download); - - confirm_action_from_mime (EPHY_GET_WEBKIT_WEB_VIEW_FROM_EMBED (embed), - download, DOWNLOAD_ACTION_DOWNLOAD); - } -} - -static gboolean -download_error_cb (WebKitDownload *download, - gint error_code, - gint error_detail, - const gchar *reason, - EphyEmbed *embed) -{ - /* FIXME: handle download errors and notify the user. */ - LOG ("download_error_cb: Error (%d:%d): %s", error_code, error_detail, reason); - - return FALSE; + download = ephy_download_new_for_uri (url); + ephy_download_set_auto_destination (download); + ephy_download_set_action (download, EPHY_DOWNLOAD_ACTION_OPEN); } static gboolean @@ -818,26 +373,19 @@ download_requested_cb (WebKitWebView *web_view, WebKitDownload *download, EphyEmbed *embed) { + EphyDownload *ed; + GtkWidget *window; + /* Is download locked down? */ if (g_settings_get_boolean (EPHY_SETTINGS_LOCKDOWN, EPHY_PREFS_LOCKDOWN_SAVE_TO_DISK)) return FALSE; - /* Wait for the request to be sent in all cases, so that we have a - * response which may contain a suggested filename */ - g_signal_connect (download, "notify::status", - G_CALLBACK (download_status_changed_cb), - embed); - g_signal_connect (download, "error", - G_CALLBACK (download_error_cb), - embed); + window = gtk_widget_get_toplevel (GTK_WIDGET (embed)); - /* If we are not performing an auto-download, we will ask the user - * where they want the file to go to; we will start downloading to a - * temporary location while the user decides. - */ - if (!define_destination_uri (download, TRUE)) - return FALSE; + ed = ephy_download_new_for_download (download); + ephy_download_set_window (ed, window); + ephy_download_set_auto_destination (ed); return TRUE; } diff --git a/lib/ephy-marshal.list b/lib/ephy-marshal.list index c3f186572..babe824e6 100644 --- a/lib/ephy-marshal.list +++ b/lib/ephy-marshal.list @@ -1,5 +1,6 @@ BOOLEAN:BOXED BOOLEAN:ENUM,STRING,STRING,STRING +BOOLEAN:INT,INT,STRING BOOLEAN:OBJECT BOOLEAN:STRING BOOLEAN:STRING,BOOLEAN,BOOLEAN diff --git a/po/POTFILES.in b/po/POTFILES.in index 4e297e65c..300c80978 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -10,9 +10,8 @@ data/org.gnome.epiphany.gschema.xml.in [type: gettext/glade] data/glade/form-signing-dialog.ui [type: gettext/glade] data/glade/prefs-dialog.ui [type: gettext/glade] data/glade/print.ui -embed/downloader-view.c +embed/ephy-download.c embed/ephy-embed.c -embed/ephy-embed-persist.c embed/ephy-embed-shell.c embed/ephy-embed-single.c embed/ephy-embed-utils.c diff --git a/src/Makefile.am b/src/Makefile.am index ad6bf9ebc..dd9a0e13f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -264,10 +264,10 @@ MAINTAINERCLEANFILES = $(stamp_files) $(BUILT_SOURCES) if HAVE_INTROSPECTION EPHY_GIR_H_FILES = \ + $(top_srcdir)/embed/ephy-download.h \ $(top_srcdir)/embed/ephy-embed.h \ $(top_srcdir)/embed/ephy-embed-container.h \ $(top_srcdir)/embed/ephy-embed-event.h \ - $(top_srcdir)/embed/ephy-embed-persist.h \ $(top_srcdir)/embed/ephy-embed-shell.h \ $(top_srcdir)/embed/ephy-embed-single.h \ $(top_srcdir)/embed/ephy-favicon-cache.h \ @@ -294,10 +294,10 @@ EPHY_GIR_H_FILES = \ $(NULL) EPHY_GIR_C_FILES = \ + $(top_srcdir)/embed/ephy-download.c \ $(top_srcdir)/embed/ephy-embed.c \ $(top_srcdir)/embed/ephy-embed-container.c \ $(top_srcdir)/embed/ephy-embed-event.c \ - $(top_srcdir)/embed/ephy-embed-persist.c \ $(top_srcdir)/embed/ephy-embed-shell.c \ $(top_srcdir)/embed/ephy-embed-single.c \ $(top_srcdir)/embed/ephy-favicon-cache.c \ diff --git a/src/ephy-session.c b/src/ephy-session.c index cee9e490e..65ca3d228 100644 --- a/src/ephy-session.c +++ b/src/ephy-session.c @@ -167,7 +167,6 @@ confirm_shutdown_dialog_weak_ref_cb (InteractData *data, EphySessionPrivate *priv = data->session->priv; EggSMClient *sm_client = data->sm_client; EphyShell *shell; - GObject *dv; gboolean will_quit; LOG ("confirm_shutdown_dialog_weak_ref_cb response %d", data->response); @@ -180,14 +179,6 @@ confirm_shutdown_dialog_weak_ref_cb (InteractData *data, g_object_weak_unref (G_OBJECT (shell), (GWeakNotify) confirm_shutdown_dialog_accept_cb, data); - - dv = ephy_embed_shell_get_downloader_view_nocreate (ephy_embed_shell_get_default ()); - if (dv != NULL) - { - g_object_weak_unref (dv, - (GWeakNotify) confirm_shutdown_dialog_accept_cb, - data); - } } if (data->timeout_id != 0) @@ -208,15 +199,16 @@ client_quit_requested_cb (EggSMClient *sm_client, EphySession *session) { EphySessionPrivate *priv = session->priv; - GObject *dv; GtkWidget *dialog, *box; InteractData *data; + GList *downloads; /* If we're shutting down, check if there are downloads * remaining, since they can't be restarted. */ - if (ephy_shell_get_default () == NULL || - (dv = ephy_embed_shell_get_downloader_view_nocreate (ephy_embed_shell_get_default ())) == NULL) + + downloads = ephy_embed_shell_get_downloads (embed_shell); + if (ephy_shell_get_default () == NULL || g_list_length (downloads) == 0) { egg_sm_client_will_quit (sm_client, TRUE); return; @@ -271,11 +263,6 @@ client_quit_requested_cb (EggSMClient *sm_client, (GWeakNotify) confirm_shutdown_dialog_accept_cb, data); - /* When the download finishes, un-veto the shutdown */ - g_object_weak_ref (dv, - (GWeakNotify) confirm_shutdown_dialog_accept_cb, - data); - g_signal_connect (dialog, "response", G_CALLBACK (confirm_shutdown_dialog_response_cb), data); g_object_weak_ref (G_OBJECT (dialog), diff --git a/src/ephy-shell.c b/src/ephy-shell.c index f15ceda6a..6fddf9d2d 100644 --- a/src/ephy-shell.c +++ b/src/ephy-shell.c @@ -48,7 +48,6 @@ #include "ephy-extensions-manager.h" #include "ephy-session.h" #include "ephy-lockdown.h" -#include "downloader-view.h" #include "egg-toolbars-model.h" #include "ephy-toolbars-model.h" #include "ephy-toolbar.h" diff --git a/src/ephy-window.c b/src/ephy-window.c index 98eb1c44d..b251fb00f 100644 --- a/src/ephy-window.c +++ b/src/ephy-window.c @@ -52,7 +52,6 @@ #include "ephy-fullscreen-popup.h" #include "ephy-action-helper.h" #include "ephy-find-toolbar.h" -#include "ephy-embed-persist.h" #include "ephy-location-entry.h" #include "ephy-web-view.h" diff --git a/src/epiphany.h.in b/src/epiphany.h.in index a722c556c..8664c15bd 100644 --- a/src/epiphany.h.in +++ b/src/epiphany.h.in @@ -38,6 +38,7 @@ #include <epiphany/ephy-bookmarks.h> #include <epiphany/ephy-bookmarks-type-builtins.h> #include <epiphany/ephy-dialog.h> +#include <epiphany/ephy-download.h> #include <epiphany/ephy-embed-container.h> #include <epiphany/ephy-embed-event.h> #include <epiphany/ephy-embed.h> diff --git a/src/popup-commands.c b/src/popup-commands.c index 1bbce9dce..0bec4fbb2 100644 --- a/src/popup-commands.c +++ b/src/popup-commands.c @@ -21,12 +21,13 @@ #include "config.h" #include "popup-commands.h" +#include "ephy-download.h" #include "ephy-shell.h" #include "ephy-embed-container.h" -#include "ephy-embed-persist.h" #include "ephy-embed-utils.h" #include "ephy-prefs.h" #include "ephy-file-helpers.h" +#include "ephy-file-chooser.h" #include "ephy-bookmarks-ui.h" #include "ephy-web-view.h" @@ -179,28 +180,25 @@ popup_cmd_copy_link_address (GtkAction *action, } static void -save_property_url_completed_cb (EphyEmbedPersist *persist) +response_cb (GtkDialog *dialog, + int response_id, + EphyDownload *download) { - if (!(ephy_embed_persist_get_flags (persist) & - EPHY_EMBED_PERSIST_ASK_DESTINATION)) + if (response_id == GTK_RESPONSE_ACCEPT) { - const char *dest; - GFile *dest_file; - guint32 user_time; + char *uri; - user_time = ephy_embed_persist_get_user_time (persist); - dest = ephy_embed_persist_get_dest (persist); - - g_return_if_fail (dest != NULL); - - dest_file = g_file_new_for_path (dest); - - g_return_if_fail (dest_file != NULL); - /* If save location is the desktop, nautilus will not open */ - ephy_file_browse_to (dest_file, user_time); - - g_object_unref (dest_file); + uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog)); + ephy_download_set_destination_uri (download, uri); + ephy_download_start (download); + g_free (uri); + } + else + { + ephy_download_cancel (download); } + + gtk_widget_destroy (GTK_WIDGET (dialog)); } static void @@ -213,38 +211,44 @@ save_property_url (GtkAction *action, EphyEmbedEvent *event; const char *location; GValue value = { 0, }; - EphyEmbedPersist *persist; - EphyEmbed *embed; + EphyDownload *download; event = ephy_window_get_context_event (window); g_return_if_fail (event != NULL); - embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window)); - g_return_if_fail (embed != NULL); - ephy_embed_event_get_property (event, property, &value); location = g_value_get_string (&value); - persist = EPHY_EMBED_PERSIST - (g_object_new (EPHY_TYPE_EMBED_PERSIST, NULL)); - - ephy_embed_persist_set_fc_title (persist, title); - ephy_embed_persist_set_fc_parent (persist, GTK_WINDOW (window)); - ephy_embed_persist_set_flags - (persist, EPHY_EMBED_PERSIST_FROM_CACHE | - (ask_dest ? EPHY_EMBED_PERSIST_ASK_DESTINATION : 0)); - ephy_embed_persist_set_persist_key - (persist, EPHY_PREFS_STATE_SAVE_DIR); - ephy_embed_persist_set_source (persist, location); - ephy_embed_persist_set_embed (persist, embed); - - g_signal_connect (persist, "completed", - G_CALLBACK (save_property_url_completed_cb), NULL); - - ephy_embed_persist_save (persist); - - g_object_unref (G_OBJECT (persist)); + download = ephy_download_new_for_uri (location); + ephy_download_set_window (download, GTK_WIDGET (window)); g_value_unset (&value); + + if (ask_dest) + { + EphyFileChooser *dialog; + char *base; + + base = g_path_get_basename (location); + dialog = ephy_file_chooser_new (title, GTK_WIDGET (window), + GTK_FILE_CHOOSER_ACTION_SAVE, + EPHY_PREFS_STATE_SAVE_DIR, + EPHY_FILE_FILTER_ALL); + + gtk_file_chooser_set_do_overwrite_confirmation + (GTK_FILE_CHOOSER (dialog), TRUE); + gtk_file_chooser_set_current_name + (GTK_FILE_CHOOSER (dialog), base); + g_signal_connect (dialog, "response", + G_CALLBACK (response_cb), download); + gtk_widget_show (GTK_WIDGET (dialog)); + + g_free (base); + } + else + { + ephy_download_set_auto_destination (download); + ephy_download_start (download); + } } void @@ -293,15 +297,15 @@ popup_cmd_save_image_as (GtkAction *action, #define GNOME_APPEARANCE_PROPERTIES "gnome-appearance-properties.desktop" static void -background_download_completed (EphyEmbedPersist *persist, +background_download_completed (EphyDownload *download, GtkWidget *window) { - const char *bg; + char *bg; guint32 user_time; - user_time = ephy_embed_persist_get_user_time (persist); + user_time = ephy_download_get_start_time (download); - bg = ephy_embed_persist_get_dest (persist); + bg = g_filename_from_uri (ephy_download_get_destination_uri (download), NULL, NULL); /* open the Appearance Properties capplet on the Background tab */ if (!ephy_file_launch_desktop_file (GNOME_APPEARANCE_PROPERTIES, bg, user_time, window)) @@ -315,8 +319,7 @@ background_download_completed (EphyEmbedPersist *persist, ephy_file_launch_desktop_file ("gnome-background.desktop", bg, user_time, window); } } - - g_object_unref (persist); + g_free (bg); } void @@ -325,43 +328,36 @@ popup_cmd_set_image_as_background (GtkAction *action, { EphyEmbedEvent *event; const char *location; - char *dest, *base, *base_converted; + char *dest_uri, *dest, *base, *base_converted; GValue value = { 0, }; - EphyEmbedPersist *persist; - EphyEmbed *embed; + EphyDownload *download; event = ephy_window_get_context_event (window); g_return_if_fail (event != NULL); - embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window)); - g_return_if_fail (embed != NULL); - ephy_embed_event_get_property (event, "image-uri", &value); location = g_value_get_string (&value); - persist = EPHY_EMBED_PERSIST - (g_object_new (EPHY_TYPE_EMBED_PERSIST, NULL)); + download = ephy_download_new_for_uri (location); + ephy_download_set_window (download, GTK_WIDGET (window)); base = g_path_get_basename (location); base_converted = g_filename_from_utf8 (base, -1, NULL, NULL, NULL); dest = g_build_filename (ephy_dot_dir (), base_converted, NULL); + dest_uri = g_filename_to_uri (dest, NULL, NULL); - ephy_embed_persist_set_dest (persist, dest); - ephy_embed_persist_set_flags (persist, EPHY_EMBED_PERSIST_NO_VIEW | - EPHY_EMBED_PERSIST_FROM_CACHE); - ephy_embed_persist_set_source (persist, location); + ephy_download_set_destination_uri (download, dest_uri); - g_signal_connect (persist, "completed", - G_CALLBACK (background_download_completed), - window); + g_signal_connect (download, "completed", + G_CALLBACK (background_download_completed), window); - ephy_embed_persist_save (persist); - g_object_unref (persist); + ephy_download_start (download); g_value_unset (&value); - g_free (dest); g_free (base); g_free (base_converted); + g_free (dest); + g_free (dest_uri); } void @@ -425,19 +421,19 @@ image_open_uri (GFile *file, } static void -save_source_completed_cb (EphyEmbedPersist *persist) +save_source_completed_cb (EphyDownload *download) { const char *dest; const char *source; guint32 user_time; GFile *file; - user_time = ephy_embed_persist_get_user_time (persist); - dest = ephy_embed_persist_get_dest (persist); - source = ephy_embed_persist_get_source (persist); + user_time = ephy_download_get_start_time (download); + dest = ephy_download_get_destination_uri (download); + source = ephy_download_get_source_uri (download); g_return_if_fail (dest != NULL); - file = g_file_new_for_path (dest); + file = g_file_new_for_uri (dest); image_open_uri (file, source, user_time); g_object_unref (file); @@ -446,9 +442,9 @@ save_source_completed_cb (EphyEmbedPersist *persist) static void save_temp_source (const char *address) { - EphyEmbedPersist *persist; + EphyDownload *download; const char *static_temp_dir; - char *base, *tmp_name, *tmp_path, *dest; + char *base, *tmp_name, *tmp_path, *dest, *dest_uri; if (address == NULL) return; @@ -467,21 +463,17 @@ save_temp_source (const char *address) if (dest == NULL) return; - persist = EPHY_EMBED_PERSIST - (g_object_new (EPHY_TYPE_EMBED_PERSIST, NULL)); - - ephy_embed_persist_set_source (persist, address); - ephy_embed_persist_set_dest (persist, dest); - ephy_embed_persist_set_flags (persist, EPHY_EMBED_PERSIST_FROM_CACHE | - EPHY_EMBED_PERSIST_NO_VIEW); + dest_uri = g_filename_to_uri (dest, NULL, NULL); + download = ephy_download_new_for_uri (address); + ephy_download_set_destination_uri (download, dest_uri); - g_signal_connect (persist, "completed", + g_signal_connect (download, "completed", G_CALLBACK (save_source_completed_cb), NULL); - ephy_embed_persist_save (persist); - g_object_unref (persist); + ephy_download_start (download); g_free (dest); + g_free (dest_uri); } void diff --git a/src/window-commands.c b/src/window-commands.c index ff3647c59..6b70b09e9 100644 --- a/src/window-commands.c +++ b/src/window-commands.c @@ -27,7 +27,6 @@ #include "ephy-embed-single.h" #include "ephy-embed-utils.h" #include "ephy-shell.h" -#include "ephy-embed-persist.h" #include "ephy-debug.h" #include "window-commands.h" #include "ephy-prefs.h" diff --git a/tests/Makefile.am b/tests/Makefile.am index 8cba75725..bb538d845 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,5 +1,5 @@ noinst_PROGRAMS = \ - test-ephy-embed-persist \ + test-ephy-download \ test-ephy-embed-single \ test-ephy-location-entry \ test-ephy-search-entry \ @@ -33,8 +33,8 @@ LDADD += \ $(SEED_LIBS) endif -test_ephy_embed_persist_SOURCES = \ - ephy-embed-persist.c +test_ephy_download_SOURCES = \ + ephy-download.c test_ephy_embed_single_SOURCES = \ ephy-embed-single.c diff --git a/tests/ephy-download.c b/tests/ephy-download.c new file mode 100644 index 000000000..14fe81a2d --- /dev/null +++ b/tests/ephy-download.c @@ -0,0 +1,207 @@ +/* vim: set sw=2 ts=2 sts=2 et: */ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * ephy-download.c + * This file is part of Epiphany + * + * Copyright © 2011 - Igalia S.L. + * + * Epiphany is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Epiphany 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Epiphany; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "ephy-debug.h" +#include "ephy-download.h" +#include "ephy-embed-prefs.h" +#include "ephy-file-helpers.h" +#include "ephy-shell.h" + +#include <glib.h> +#include <glib/gstdio.h> +#include <gtk/gtk.h> +#include <string.h> + +#define HTML_STRING "testing-embed-persist" +SoupURI *base_uri; + +static char * +get_uri_for_path (const char *path) +{ + SoupURI *uri; + char *uri_string; + + uri = soup_uri_new_with_base (base_uri, path); + uri_string = soup_uri_to_string (uri, FALSE); + soup_uri_free (uri); + + return uri_string; +} + +static void +server_callback (SoupServer *server, + SoupMessage *msg, + const char *path, + GHashTable *query, + SoupClientContext *context, + gpointer data) +{ + soup_message_set_status (msg, SOUP_STATUS_OK); + + if (g_str_equal (path, "/cancelled")) + soup_message_set_status (msg, SOUP_STATUS_CANT_CONNECT); + + soup_message_body_append (msg->response_body, SOUP_MEMORY_STATIC, + HTML_STRING, strlen (HTML_STRING)); + + soup_message_body_complete (msg->response_body); +} + +typedef struct { + GMainLoop *loop; + EphyDownload *download; + char *destination; + char *source; +} Fixture; + +static void +fixture_setup (Fixture *fixture, gconstpointer data) +{ + char *tmp_filename; + char *dest_file; + + tmp_filename = ephy_file_tmp_filename ("ephy-download-XXXXXX", NULL); + dest_file = g_build_filename (ephy_file_tmp_dir (), tmp_filename, NULL); + + fixture->source = get_uri_for_path ("/default"); + fixture->download = ephy_download_new_for_uri (fixture->source); + fixture->destination = g_filename_to_uri (dest_file, NULL, NULL); + fixture->loop = g_main_loop_new (NULL, TRUE); + + ephy_download_set_destination_uri (fixture->download, fixture->destination); + + g_free (tmp_filename); + g_free (dest_file); +} + +static void +fixture_teardown (Fixture *fixture, gconstpointer data) +{ + g_free (fixture->destination); + g_free (fixture->source); + + g_object_unref (fixture->download); + + g_main_loop_unref (fixture->loop); +} + +static gboolean +test_file_was_downloaded (EphyDownload *download) +{ + char *filename; + gboolean ret; + + filename = g_filename_from_uri (ephy_download_get_destination_uri (download), + NULL, NULL); + + ret = g_file_test (filename, G_FILE_TEST_EXISTS); + g_free (filename); + + return ret; +} + +static void +completed_cb (EphyDownload *download, + Fixture *fixture) +{ + g_assert (test_file_was_downloaded (download)); + g_main_loop_quit (fixture->loop); +} + +static void +test_ephy_download_new (Fixture *fixture, gconstpointer data) +{ + g_assert (EPHY_IS_DOWNLOAD (fixture->download)); +} + +static void +test_ephy_download_new_for_uri (Fixture *fixture, gconstpointer data) +{ + EphyDownload *download; + + download = ephy_download_new_for_uri (fixture->source); + + g_assert (EPHY_IS_DOWNLOAD (download)); + + g_assert_cmpstr (fixture->source, ==, ephy_download_get_source_uri (download)); + + g_signal_connect (G_OBJECT (download), "completed", + G_CALLBACK (completed_cb), fixture); + + g_main_loop_run (fixture->loop); +} + +static void +test_ephy_download_start (Fixture *fixture, gconstpointer data) +{ + g_signal_connect (G_OBJECT (fixture->download), "completed", + G_CALLBACK (completed_cb), fixture); + + g_main_loop_run (fixture->loop); +} + +int +main (int argc, char *argv[]) +{ + int ret; + SoupServer *server; + + gtk_test_init (&argc, &argv); + g_thread_init (NULL); + + ephy_debug_init (); + ephy_embed_prefs_init (); + _ephy_shell_create_instance (); + + if (!ephy_file_helpers_init (NULL, TRUE, FALSE, NULL)) { + g_debug ("Something wrong happened with ephy_file_helpers_init()"); + return -1; + } + + server = soup_server_new (SOUP_SERVER_PORT, 0, NULL); + soup_server_run_async (server); + + base_uri = soup_uri_new ("http://127.0.0.1/"); + soup_uri_set_port (base_uri, soup_server_get_port (server)); + + soup_server_add_handler (server, NULL, server_callback, NULL, NULL); + + g_test_add ("/embed/ephy-download/new", + Fixture, NULL, fixture_setup, + test_ephy_download_new, fixture_teardown); + g_test_add ("/embed/ephy-download/new_for_uri", + Fixture, NULL, fixture_setup, + test_ephy_download_new_for_uri, fixture_teardown); + g_test_add ("/embed/ephy-download/start", + Fixture, NULL, fixture_setup, + test_ephy_download_start, fixture_teardown); + + ret = g_test_run (); + + g_object_unref (ephy_shell); + ephy_file_helpers_shutdown (); + + return ret; +} diff --git a/tests/ephy-embed-persist.c b/tests/ephy-embed-persist.c deleted file mode 100644 index 971c3577d..000000000 --- a/tests/ephy-embed-persist.c +++ /dev/null @@ -1,315 +0,0 @@ -/* vim: set sw=2 ts=2 sts=2 et: */ -/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* - * ephy-embed-persist.c - * This file is part of Epiphany - * - * Copyright © 2009, 2010 - Gustavo Noronha Silva - * Copyright © 2010 - Igalia S.L. - * - * Epiphany is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * Epiphany 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Epiphany; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301 USA - */ - -#include "config.h" -#include "ephy-debug.h" -#include "ephy-embed-persist.h" -#include "ephy-embed-prefs.h" -#include "ephy-file-helpers.h" -#include "ephy-shell.h" -#include "ephy-stock-icons.h" -#include <glib.h> -#include <glib/gstdio.h> -#include <gtk/gtk.h> -#include <libsoup/soup.h> -#include <string.h> - -#define HTML_STRING "testing-embed-persist" -SoupURI *base_uri; - -static char * -get_uri_for_path (const char *path) -{ - SoupURI *uri; - char *uri_string; - - uri = soup_uri_new_with_base (base_uri, path); - uri_string = soup_uri_to_string (uri, FALSE); - soup_uri_free (uri); - - return uri_string; -} - -static void -server_callback (SoupServer *server, - SoupMessage *msg, - const char *path, - GHashTable *query, - SoupClientContext *context, - gpointer data) -{ - soup_message_set_status (msg, SOUP_STATUS_OK); - - if (g_str_equal (path, "/cancelled")) - soup_message_set_status (msg, SOUP_STATUS_CANT_CONNECT); - - soup_message_body_append (msg->response_body, SOUP_MEMORY_STATIC, - HTML_STRING, strlen (HTML_STRING)); - - soup_message_body_complete (msg->response_body); -} - -typedef struct { - GMainLoop *loop; - EphyEmbedPersist *embed; - char *destination; -} PersistFixture; - -static void -persist_fixture_setup (PersistFixture *fixture, - gconstpointer data) -{ - char *tmp_filename; - char *uri_string; - - tmp_filename = ephy_file_tmp_filename ("embed-persist-save-XXXXXX", NULL); - fixture->destination = g_build_filename (ephy_file_tmp_dir (), tmp_filename, NULL); - - fixture->loop = g_main_loop_new (NULL, TRUE); - fixture->embed = EPHY_EMBED_PERSIST (g_object_new (EPHY_TYPE_EMBED_PERSIST, NULL)); - - uri_string = get_uri_for_path ("/default"); - - ephy_embed_persist_set_source (fixture->embed, uri_string); - ephy_embed_persist_set_dest (fixture->embed, fixture->destination); - ephy_embed_persist_set_flags (fixture->embed, EPHY_EMBED_PERSIST_NO_VIEW); - - g_free (tmp_filename); - g_free (uri_string); -} - -static void -persist_fixture_teardown (PersistFixture *fixture, - gconstpointer data) -{ - g_unlink (fixture->destination); - g_free (fixture->destination); - - if (fixture->embed != NULL) - g_object_unref (fixture->embed); - - g_main_loop_unref (fixture->loop); -} - -static void -test_embed_persist_new (PersistFixture *fixture, - gconstpointer data) -{ - g_assert (EPHY_IS_EMBED_PERSIST (fixture->embed)); -} - -static void -test_embed_persist_set_dest (PersistFixture *fixture, - gconstpointer data) -{ - const char *dest_value = NULL; - char *read_value; - - ephy_embed_persist_set_dest (fixture->embed, dest_value); - g_object_get (G_OBJECT (fixture->embed), "dest", &read_value, NULL); - - g_assert_cmpstr (dest_value, ==, read_value); - - g_free (read_value); -} - -static void -test_embed_persist_set_embed (PersistFixture *fixture, - gconstpointer data) -{ - EphyEmbed *orig_value; - EphyEmbed *fail_value; - EphyEmbed *read_value; - - orig_value = EPHY_EMBED (g_object_new (EPHY_TYPE_EMBED, NULL)); - fail_value = EPHY_EMBED (g_object_new (EPHY_TYPE_EMBED, NULL)); - - ephy_embed_persist_set_embed (fixture->embed, orig_value); - g_object_get (G_OBJECT (fixture->embed), "embed", &read_value, NULL); - - g_assert (read_value == orig_value); - g_assert (read_value != fail_value); - - g_object_unref (read_value); - g_object_ref_sink (fail_value); - g_object_unref (fail_value); -} - -static void -test_embed_persist_save_empty_dest (PersistFixture *fixture, - gconstpointer data) -{ - ephy_embed_persist_set_source (fixture->embed, "ficticious-source"); - - /* No dest is set and no EPHY_EMBED_PERSIST_ASK_DESTINATION flag, - so the destination will be downloads folder with the suggested filename. */ - g_assert (ephy_embed_persist_save (fixture->embed) == TRUE); - - /* Otherwise the reference from ephy_embed_persist_save () is never unref'd */ - ephy_embed_persist_cancel (fixture->embed); -} - -static void -test_embed_persist_save (PersistFixture *fixture, - gconstpointer data) -{ - /* Source and dest set, should return TRUE */ - g_assert (ephy_embed_persist_save (fixture->embed) == TRUE); - - /* Otherwise the reference from ephy_embed_persist_save () is never unref'd */ - ephy_embed_persist_cancel (fixture->embed); -} - -static void -test_embed_persist_cancel (PersistFixture *fixture, - gconstpointer data) -{ - ephy_embed_persist_cancel (fixture->embed); - /* This is the only case where the embed unrefs itself */ - fixture->embed = NULL; -} - -static void -completed_cb (EphyEmbedPersist *persist, - PersistFixture *fixture) -{ - g_main_loop_quit (fixture->loop); -} - -static void -test_embed_persist_save_completed (PersistFixture *fixture, - gconstpointer userdata) -{ - g_signal_connect (G_OBJECT (fixture->embed), "completed", - G_CALLBACK (completed_cb), fixture); - - ephy_embed_persist_save (fixture->embed); - - g_main_loop_run (fixture->loop); - - g_assert (g_file_test (fixture->destination, G_FILE_TEST_EXISTS)); -} - -static void -cancelled_cb (EphyEmbedPersist *persist, - PersistFixture *fixture) -{ - g_main_loop_quit (fixture->loop); -} - -static void -test_embed_persist_cancelled (PersistFixture *fixture, - gconstpointer userdata) -{ - char *uri_string; - - g_signal_connect (G_OBJECT (fixture->embed), "cancelled", - G_CALLBACK (cancelled_cb), fixture); - - uri_string = get_uri_for_path ("/cancelled"); - ephy_embed_persist_set_source (fixture->embed, uri_string); - g_free (uri_string); - - g_assert (ephy_embed_persist_save (fixture->embed)); - - g_main_loop_run (fixture->loop); -} - -int -main (int argc, char *argv[]) -{ - int ret; - SoupServer *server; - - gtk_test_init (&argc, &argv); - g_thread_init (NULL); - - ephy_debug_init (); - ephy_embed_prefs_init (); - _ephy_shell_create_instance (); - - if (!ephy_file_helpers_init (NULL, TRUE, FALSE, NULL)) { - g_debug ("Something wrong happened with ephy_file_helpers_init()"); - return -1; - } - - server = soup_server_new (SOUP_SERVER_PORT, 0, NULL); - soup_server_run_async (server); - - base_uri = soup_uri_new ("http://127.0.0.1/"); - soup_uri_set_port (base_uri, soup_server_get_port (server)); - - soup_server_add_handler (server, NULL, server_callback, NULL, NULL); - - g_test_add ("/embed/ephy-embed-persist/new", - PersistFixture, NULL, - persist_fixture_setup, - test_embed_persist_new, - persist_fixture_teardown); - g_test_add ("/embed/ephy-embed-persist/set_dest", - PersistFixture, NULL, - persist_fixture_setup, - test_embed_persist_set_dest, - persist_fixture_teardown); - g_test_add ("/embed/ephy-embed-persist/set_embed", - PersistFixture, NULL, - persist_fixture_setup, - test_embed_persist_set_embed, - persist_fixture_teardown); - g_test_add ("/embed/ephy-embed-persist/save_empty_dest", - PersistFixture, NULL, - persist_fixture_setup, - test_embed_persist_save_empty_dest, - persist_fixture_teardown); - - g_test_add ("/embed/ephy-embed-persist/save", - PersistFixture, NULL, - persist_fixture_setup, - test_embed_persist_save, - persist_fixture_teardown); - g_test_add ("/embed/ephy-embed-persist/cancel", - PersistFixture, NULL, - persist_fixture_setup, - test_embed_persist_cancel, - persist_fixture_teardown); - - g_test_add ("/embed/ephy-embed-persist/save_completed", - PersistFixture, NULL, - persist_fixture_setup, - test_embed_persist_save_completed, - persist_fixture_teardown); - g_test_add ("/embed/ephy-embed-persist/cancelled", - PersistFixture, NULL, - persist_fixture_setup, - test_embed_persist_cancelled, - persist_fixture_teardown); - - ret = g_test_run (); - - g_object_unref (ephy_shell); - ephy_file_helpers_shutdown (); - - return ret; -} |