[epiphany] Reimplement the original download logic and dialog.



commit 9365ffd004d6260e656453143eb32f333ae888a2
Author: Gustavo Noronha Silva <kov debian org>
Date:   Fri May 22 18:42:46 2009 -0300

    Reimplement the original download logic and dialog.
    
    We are still missing some of the MIME logic, pending on a WebKit
    feature landing.
---
 embed/downloader-view.c     |   51 +++++++++++++-
 embed/downloader-view.h     |   17 +++++
 embed/webkit/webkit-embed.c |  164 ++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 229 insertions(+), 3 deletions(-)

diff --git a/embed/downloader-view.c b/embed/downloader-view.c
index b154592..3bb56c1 100644
--- a/embed/downloader-view.c
+++ b/embed/downloader-view.c
@@ -416,6 +416,39 @@ ephy_download_get_remaining_time (WebKitDownload *download)
 }
 
 static void
+do_open_downloaded_file (DownloaderView *dv, WebKitDownload *download, gboolean open_location)
+{
+	DownloaderViewPrivate *priv = dv->priv;
+	GdkDisplay *gdk_display;
+	const char *destination_uri = webkit_download_get_destination_uri (download);
+	GFile *downloaded_file = g_file_new_for_uri (destination_uri);
+
+	gdk_display = gtk_widget_get_display (priv->window);
+	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;
@@ -427,7 +460,7 @@ update_download_row (DownloaderView *dv, WebKitDownload *download)
 	char *remaining, *file, *cur_progress, *name;
 	struct tm;
 	int percent = 0;
-
+	DownloadAction action;
 #ifdef HAVE_LIBNOTIFY
 	char *downloaded;
 #endif
@@ -451,6 +484,22 @@ update_download_row (DownloaderView *dv, WebKitDownload *download)
 		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;
+		default:
+			g_assert_not_reached ();
+			break;
+		}
+
 		downloader_view_remove_download (dv, download);
 #ifdef HAVE_LIBNOTIFY
 		downloaded = g_strdup_printf (_("The file â??%sâ?? has been downloaded."), 
diff --git a/embed/downloader-view.h b/embed/downloader-view.h
index 82cb101..e331cca 100644
--- a/embed/downloader-view.h
+++ b/embed/downloader-view.h
@@ -52,6 +52,23 @@ 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);
diff --git a/embed/webkit/webkit-embed.c b/embed/webkit/webkit-embed.c
index 87173fb..a04abc2 100644
--- a/embed/webkit/webkit-embed.c
+++ b/embed/webkit/webkit-embed.c
@@ -36,6 +36,7 @@
 #include "ephy-embed-shell.h"
 #include "ephy-embed-single.h"
 #include "ephy-embed-persist.h"
+#include "ephy-stock-icons.h"
 #include "ephy-string.h"
 #include "ephy-embed-event.h"
 #include "ephy-embed-utils.h"
@@ -436,6 +437,7 @@ download_requested_dialog_response_cb (GtkDialog *dialog,
   }
 
   gtk_widget_destroy (GTK_WIDGET (dialog));
+  g_object_unref (download);
 }
 
 static void
@@ -453,7 +455,7 @@ request_destination_uri (WebKitWebView *web_view,
    * 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));
+  window = gtk_widget_get_toplevel (GTK_WIDGET (web_view));
   if (!GTK_WIDGET_TOPLEVEL (window))
     window = NULL;
 
@@ -523,9 +525,161 @@ perform_auto_download (WebKitDownload *download)
   }
 
   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);
 }
 
+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 = EPHY_DOWNLOADER_VIEW (ephy_embed_shell_get_downloader_view (embed_shell));
+
+  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;
+      }
+      downloader_view_add_download (dview, download);
+    }
+    g_object_unref (download);
+    return;
+  }
+
+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, *button, *image;
+  const char *action_label;
+  char *mime_description;
+  EphyMimePermission mime_permission;
+  GAppInfo *helper_app;
+  const char *suggested_filename;
+
+  parent_window = gtk_widget_get_toplevel (GTK_WIDGET(web_view));
+  if (!GTK_WIDGET_TOPLEVEL (parent_window))
+    parent_window = NULL;
+
+  /* FIXME: we still have no way of getting the content type from
+   * webkit yet; we need to have a proper WebKitNetworkRequest
+   * implementation to do this here; see
+   * https://bugs.webkit.org/show_bug.cgi?id=18608
+   */
+  helper_app = NULL;
+  mime_description = NULL;
+  mime_permission = EPHY_MIME_PERMISSION_SAFE;
+  if (mime_description == NULL) {
+    /* Translators: The text before the "|" is context to help you decide on
+     * the correct translation. You MUST OMIT it in the translated string. */
+    mime_description = g_strdup (Q_("File Type:|Unknown"));
+    action = DOWNLOAD_ACTION_OPEN_LOCATION;
+  }
+
+  /* OPEN will never happen here, for now; see comment about
+   * WebKitNetworkRequest above!
+   */
+  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) {
+    dialog = gtk_message_dialog_new (GTK_WINDOW (parent_window),
+                                     GTK_DIALOG_DESTROY_WITH_PARENT,
+                                     GTK_MESSAGE_WARNING, GTK_BUTTONS_NONE,
+                                     _("Download this potentially unsafe file?"));
+
+    gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+                                              /* translators: First %s is the file type description,
+                                                 Second %s is the file name */
+                                              _("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);
+  } else if (action == DOWNLOAD_ACTION_OPEN && helper_app) {
+    dialog = gtk_message_dialog_new (GTK_WINDOW (parent_window),
+                                     GTK_DIALOG_DESTROY_WITH_PARENT,
+                                     GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
+                                     _("Open this file?"));
+
+    gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+                                              /* translators: First %s is the file type description,
+                                                 Second %s is the file name,
+                                                 Third %s is the application used to open the file */
+                                              _("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  {
+    dialog = gtk_message_dialog_new (GTK_WINDOW (parent_window),
+                                     GTK_DIALOG_DESTROY_WITH_PARENT,
+                                     GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
+                                     _("Download this file?"));
+
+    gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+                                              /* translators: First %s is the file type description,
+                                                 Second %s is the file name */
+                                              _("File Type: â??%sâ??.\n\nYou have no application able to open â??%sâ??. "
+                                                "You can download it instead."),
+                                              mime_description, suggested_filename);
+  }
+
+  g_free (mime_description);
+
+  button = gtk_button_new_with_label (_("_Save As..."));
+  image = gtk_image_new_from_stock (GTK_STOCK_SAVE_AS, GTK_ICON_SIZE_BUTTON);
+  gtk_button_set_image (GTK_BUTTON (button), image);
+  /* don't show the image! see bug #307818 */
+  gtk_widget_show (button);
+  gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, 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);
+
+  int 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 gboolean
 download_requested_cb (WebKitWebView *web_view,
                        WebKitDownload *download)
@@ -547,7 +701,13 @@ download_requested_cb (WebKitWebView *web_view,
   if (!define_destination_uri (download, TRUE))
     return FALSE;
 
-  request_destination_uri (web_view, download);
+  /* FIXME: when we are able to obtain the MIME information from
+   * WebKit, we will want to decide earlier whether we want to open or
+   * open the location to where the file was downloaded. See
+   * perform_auto_download, too.
+   */
+  g_object_ref (download); /* balanced in confirm_action_response_cb */
+  confirm_action_from_mime (web_view, download, DOWNLOAD_ACTION_DOWNLOAD);
 
   return TRUE;
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]