diff options
author | Diego Escalante Urrelo <descalante@igalia.com> | 2011-01-19 00:10:11 +0800 |
---|---|---|
committer | Diego Escalante Urrelo <descalante@igalia.com> | 2011-03-08 04:34:52 +0800 |
commit | b9f9bf1a0763492f8bf41b8856bbd1149c5871a9 (patch) | |
tree | 92ad55101bff9eabcbc17afdba4a398ce4c4b709 /embed/ephy-embed.c | |
parent | 7f7826a163f31bb662247ac4486dca0d01df35f6 (diff) | |
download | gsoc2013-epiphany-b9f9bf1a0763492f8bf41b8856bbd1149c5871a9.tar gsoc2013-epiphany-b9f9bf1a0763492f8bf41b8856bbd1149c5871a9.tar.gz gsoc2013-epiphany-b9f9bf1a0763492f8bf41b8856bbd1149c5871a9.tar.bz2 gsoc2013-epiphany-b9f9bf1a0763492f8bf41b8856bbd1149c5871a9.tar.lz gsoc2013-epiphany-b9f9bf1a0763492f8bf41b8856bbd1149c5871a9.tar.xz gsoc2013-epiphany-b9f9bf1a0763492f8bf41b8856bbd1149c5871a9.tar.zst gsoc2013-epiphany-b9f9bf1a0763492f8bf41b8856bbd1149c5871a9.zip |
ephy-download: add the new EphyDownload object
EphyDownload is a wrapper object around WebKitDownload that handles common
behavior in downloads: auto-destination, default action for the MIME type.
It can be used to wrap a WebKitDownload coming from a WebKitView or to download
a url: ephy_download_new_for_uri and ephy_download_new_for_download are
provided.
Its lifetime is not automagic like EphyEmbedPersist, so you have to unref it
when you no longer need it.
This new object replaces EphyEmbedPersist and enables us to use a single
codepath for downloads in all Epiphany.
Bug #618443
Diffstat (limited to 'embed/ephy-embed.c')
-rw-r--r-- | embed/ephy-embed.c | 476 |
1 files changed, 12 insertions, 464 deletions
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; } |