]> spindle.queued.net Git - midori/commitdiff
Initial support for WebKitDownload
authorChristian Dywan <christian@twotoasts.de>
Thu, 19 Mar 2009 17:28:50 +0000 (18:28 +0100)
committerChristian Dywan <christian@twotoasts.de>
Thu, 19 Mar 2009 17:28:50 +0000 (18:28 +0100)
At this point all downloads run automatically and appear in the
statusbar. The destination folder can be chosen in the preferences.
Download can be cancelled. The context menu works as well.

midori/marshal.list
midori/midori-browser.c
midori/midori-preferences.c
midori/midori-view.c
midori/midori-websettings.c

index c82c563942f83c5ce9df36465d2bc661e5cf1087..825f9730064a17e6d40eb85b65054da7adc04353 100644 (file)
@@ -1,3 +1,4 @@
+BOOLEAN:OBJECT
 BOOLEAN:VOID
 VOID:BOOLEAN,STRING
 VOID:OBJECT,ENUM
index 647542eaa81099eb462b4425b105631370791673..e667e7e384224aec0357e480f15438e3927f659e 100644 (file)
@@ -65,6 +65,7 @@ struct _MidoriBrowser
     gboolean find_typing;
 
     GtkWidget* statusbar;
+    GtkWidget* transferbar;
     GtkWidget* progressbar;
     gchar* statusbar_text;
 
@@ -893,6 +894,117 @@ midori_view_new_view_cb (GtkWidget*     view,
     }
 }
 
+#if WEBKIT_CHECK_VERSION (1, 1, 3)
+static void
+midori_browser_download_notify_progress_cb (WebKitDownload* download,
+                                            GParamSpec*     pspec,
+                                            GtkWidget*      progress)
+{
+    gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (progress),
+        webkit_download_get_progress (download));
+}
+
+static void
+midori_browser_download_notify_status_cb (WebKitDownload* download,
+                                          GParamSpec*     pspec,
+                                          GtkWidget*      button)
+{
+    switch (webkit_download_get_status (download))
+    {
+        case WEBKIT_DOWNLOAD_STATUS_FINISHED:
+        {
+            GtkWidget* icon;
+            icon = gtk_image_new_from_stock (GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU);
+            gtk_button_set_image (GTK_BUTTON (button), icon);
+            /* FIXME: Implement opening of files */
+            gtk_widget_set_sensitive (button, FALSE);
+            break;
+        }
+        case WEBKIT_DOWNLOAD_STATUS_CANCELLED:
+        case WEBKIT_DOWNLOAD_STATUS_ERROR:
+            gtk_widget_set_sensitive (button, FALSE);
+            break;
+        default:
+            break;
+    }
+}
+
+static void
+midori_browser_download_button_clicked_cb (GtkWidget*      button,
+                                           WebKitDownload* download)
+{
+    switch (webkit_download_get_status (download))
+    {
+        case WEBKIT_DOWNLOAD_STATUS_STARTED:
+            webkit_download_cancel (download);
+            break;
+        default:
+            break;
+    }
+}
+
+static void
+midori_browser_add_download_item (MidoriBrowser*  browser,
+                                  WebKitDownload* download)
+{
+    GtkWidget* box;
+    GtkWidget* icon;
+    GtkWidget* button;
+    GtkWidget* progress;
+
+    box = gtk_hbox_new (FALSE, 0);
+    /* icon = gtk_image_new_from_stock (STOCK_TRANSFER, GTK_ICON_SIZE_MENU);
+    gtk_box_pack_start (GTK_BOX (box), icon, FALSE, FALSE, 0); */
+    progress = gtk_progress_bar_new ();
+    gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR (progress),
+                                    PANGO_ELLIPSIZE_MIDDLE);
+    gtk_progress_bar_set_text (GTK_PROGRESS_BAR (progress),
+        webkit_download_get_suggested_filename (download));
+    /* Avoid a bug in WebKit */
+    if (webkit_download_get_status (download) != WEBKIT_DOWNLOAD_STATUS_CREATED)
+        gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (progress),
+            webkit_download_get_progress (download));
+    gtk_box_pack_start (GTK_BOX (box), progress, FALSE, FALSE, 0);
+    icon = gtk_image_new_from_stock (GTK_STOCK_CANCEL, GTK_ICON_SIZE_MENU);
+    button = gtk_button_new ();
+    gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
+    gtk_button_set_focus_on_click (GTK_BUTTON (button), FALSE);
+    gtk_container_add (GTK_CONTAINER (button), icon);
+    gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
+    gtk_widget_show_all (box);
+    gtk_box_pack_start (GTK_BOX (browser->transferbar), box,
+                        FALSE, FALSE, 3);
+
+    g_signal_connect (download, "notify::progress",
+        G_CALLBACK (midori_browser_download_notify_progress_cb), progress);
+    g_signal_connect (download, "notify::status",
+        G_CALLBACK (midori_browser_download_notify_status_cb), button);
+    g_signal_connect (button, "clicked",
+        G_CALLBACK (midori_browser_download_button_clicked_cb), download);
+}
+
+static gboolean
+midori_view_download_requested_cb (GtkWidget*      view,
+                                   WebKitDownload* download,
+                                   MidoriBrowser*  browser)
+{
+    if (!webkit_download_get_destination_uri (download))
+    {
+        gchar* folder = katze_object_get_string (browser->settings,
+                                                 "download-folder");
+        gchar* filename = g_build_filename (folder,
+            webkit_download_get_suggested_filename (download), NULL);
+        g_free (folder);
+        gchar* uri = g_filename_to_uri (filename, NULL, NULL);
+        g_free (filename);
+        webkit_download_set_destination_uri (download, uri);
+        g_free (uri);
+    }
+    midori_browser_add_download_item (browser, download);
+    return TRUE;
+}
+#endif
+
 static void
 midori_view_search_text_cb (GtkWidget*     view,
                             gboolean       found,
@@ -1017,6 +1129,10 @@ _midori_browser_add_tab (MidoriBrowser* browser,
                       midori_view_new_window_cb, browser,
                       "signal::new-view",
                       midori_view_new_view_cb, browser,
+                      #if WEBKIT_CHECK_VERSION (1, 1, 3)
+                      "signal::download-requested",
+                      midori_view_download_requested_cb, browser,
+                      #endif
                       "signal::search-text",
                       midori_view_search_text_cb, browser,
                       "signal::add-bookmark",
@@ -1782,9 +1898,9 @@ midori_browser_toolbar_popup_context_menu_cb (GtkWidget*     widget,
     menuitem = sokoke_action_create_popup_menu_item (
         _action_by_name (browser, "Bookmarkbar"));
     gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
-    menuitem = sokoke_action_create_popup_menu_item (
+    /*menuitem = sokoke_action_create_popup_menu_item (
         _action_by_name (browser, "Transferbar"));
-    gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
+    gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); */
     menuitem = sokoke_action_create_popup_menu_item (
         _action_by_name (browser, "Statusbar"));
     gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
@@ -3204,10 +3320,10 @@ static const GtkToggleActionEntry toggle_entries[] = {
    N_("_Bookmarkbar"), "",
    N_("Show bookmarkbar"), G_CALLBACK (_action_bookmarkbar_activate),
    FALSE },
- { "Transferbar", NULL,
/* { "Transferbar", NULL,
    N_("_Transferbar"), "",
-   N_("Show transferbar"), NULL/*G_CALLBACK (_action_transferbar_activate)*/,
-   FALSE },
+   N_("Show transferbar"), G_CALLBACK (_action_transferbar_activate),
+   FALSE }, */
  { "Statusbar", NULL,
    N_("_Statusbar"), "",
    N_("Show statusbar"), G_CALLBACK (_action_statusbar_activate),
@@ -3335,7 +3451,7 @@ static const gchar* ui_markup =
      "<menuitem action='Menubar'/>"
      "<menuitem action='Navigationbar'/>"
      "<menuitem action='Bookmarkbar'/>"
-     "<menuitem action='Transferbar'/>"
+     /* "<menuitem action='Transferbar'/>" */
      "<menuitem action='Statusbar'/>"
     "</menu>"
     "<menuitem action='Panel'/>"
@@ -3636,8 +3752,6 @@ midori_browser_init (MidoriBrowser* browser)
         g_error_free (error);
     }
 
-    /* _action_set_active(browser, "Transferbar", config->toolbarTransfers); */
-
     /* Hide the 'Dummy' which only holds otherwise unused actions */
     g_object_set (_action_by_name (browser, "Dummy"), "visible", FALSE, NULL);
 
@@ -3797,7 +3911,8 @@ midori_browser_init (MidoriBrowser* browser)
     g_object_set (_action_by_name (browser, "Menubar"), "visible", FALSE, NULL);
     g_object_set (_action_by_name (browser, "Statusbar"), "visible", FALSE, NULL);
     #endif
-    _action_set_sensitive (browser, "Transferbar", FALSE);
+    /* if (!g_signal_lookup ("download-requested", WEBKIT_TYPE_WEB_VIEW))
+        _action_set_sensitive (browser, "Transferbar", FALSE); */
     _action_set_sensitive (browser, "EncodingCustom", FALSE);
     _action_set_sensitive (browser, "SelectionSourceView", FALSE);
 
@@ -3982,12 +4097,18 @@ midori_browser_init (MidoriBrowser* browser)
     gtk_widget_modify_style (browser->statusbar, rcstyle);
     g_object_unref (rcstyle);
     gtk_box_pack_start (GTK_BOX (vbox), browser->statusbar, FALSE, FALSE, 0);
+
     browser->progressbar = gtk_progress_bar_new ();
     /* Set the progressbar's height to 1 to fit it in the statusbar */
     gtk_widget_set_size_request (browser->progressbar, -1, 1);
     gtk_box_pack_start (GTK_BOX (browser->statusbar), browser->progressbar,
                         FALSE, FALSE, 3);
 
+    browser->transferbar = gtk_hbox_new (FALSE, 0);
+    gtk_box_pack_start (GTK_BOX (browser->statusbar), browser->transferbar,
+                        FALSE, FALSE, 3);
+    gtk_widget_show (browser->transferbar);
+
     g_object_unref (ui_manager);
 }
 
index 25ae3a36a92a7bb382cfaee07c9292eb15354655..753e3136c6949b01bc308e54c20167551c54af01 100644 (file)
@@ -422,10 +422,12 @@ midori_preferences_set_settings (MidoriPreferences* preferences,
     SPANNED_ADD (button, 0, 2, 2, 3);
     FRAME_NEW (_("Transfers"));
     TABLE_NEW (3, 2);
+    #if WEBKIT_CHECK_VERSION (1, 1, 3)
     label = katze_property_label (settings, "download-folder");
     INDENTED_ADD (label, 0, 1, 0, 1);
     button = katze_property_proxy (settings, "download-folder", "folder");
     FILLED_ADD (button, 1, 2, 0, 1);
+    #else
     label = katze_property_label (settings, "download-manager");
     INDENTED_ADD (label, 0, 1, 1, 2);
     hbox = gtk_hbox_new (FALSE, 4);
@@ -440,6 +442,7 @@ midori_preferences_set_settings (MidoriPreferences* preferences,
     g_signal_connect (entry, "focus-out-event",
         G_CALLBACK (proxy_download_manager_icon_cb), button);
     FILLED_ADD (hbox, 1, 2, 1, 2);
+    #endif
     label = katze_property_label (settings, "text-editor");
     INDENTED_ADD (label, 0, 1, 2, 3);
     hbox = gtk_hbox_new (FALSE, 4);
index f30285d111d24a173879085cece8ad7a98f4cb85..a7c5ff9be8d86037a088160dcb0d4bce0ebfa8ef 100644 (file)
@@ -143,6 +143,7 @@ enum {
     NEW_TAB,
     NEW_WINDOW,
     NEW_VIEW,
+    DOWNLOAD_REQUESTED,
     SEARCH_TEXT,
     ADD_BOOKMARK,
     SAVE_AS,
@@ -271,6 +272,36 @@ midori_view_class_init (MidoriViewClass* class)
         MIDORI_TYPE_VIEW,
         MIDORI_TYPE_NEW_VIEW);
 
+    /**
+     * MidoriView::download-requested:
+     * @view: the object on which the signal is emitted
+     * @download: a new download
+     *
+     * Emitted when a new download is requested, if a
+     * file cannot be displayed or a download was started
+     * from the context menu.
+     *
+     * If the download should be accepted, a callback
+     * has to return %TRUE, and the download will also
+     * be started automatically.
+     *
+     * Note: This requires WebKitGTK 1.1.3.
+     *
+     * Return value: %TRUE if the download was handled
+     *
+     * Since: 0.1.5
+     */
+    signals[DOWNLOAD_REQUESTED] = g_signal_new (
+        "download-requested",
+        G_TYPE_FROM_CLASS (class),
+        (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
+        0,
+        g_signal_accumulator_true_handled,
+        NULL,
+        midori_cclosure_marshal_BOOLEAN__OBJECT,
+        G_TYPE_BOOLEAN, 1,
+        G_TYPE_OBJECT);
+
     /**
      * MidoriView::search-text:
      * @view: the object on which the signal is emitted
@@ -619,7 +650,12 @@ webkit_web_frame_load_done_cb (WebKitWebFrame* web_frame,
     gchar* title;
     gchar* data;
 
+    #if WEBKIT_CHECK_VERSION (1, 1, 3)
+    if (!success && webkit_web_view_can_show_mime_type (
+        WEBKIT_WEB_VIEW (view->web_view), view->mime_type))
+    #else
     if (!success)
+    #endif
     {
         /* i18n: The title of the 404 - Not found error page */
         title = g_strdup_printf (_("Not found - %s"), view->uri);
@@ -886,6 +922,7 @@ midori_web_view_menu_search_web_activate_cb (GtkWidget*  widget,
     g_free (uri);
 }
 
+#if !WEBKIT_CHECK_VERSION (1, 1, 3)
 static void
 midori_web_view_menu_save_as_activate_cb (GtkWidget*  widget,
                                           MidoriView* view)
@@ -899,6 +936,7 @@ midori_web_view_menu_download_activate_cb (GtkWidget*  widget,
 {
     sokoke_spawn_program (view->download_manager, view->link_uri);
 }
+#endif
 
 static void
 midori_web_view_menu_add_bookmark_activate_cb (GtkWidget*  widget,
@@ -977,6 +1015,11 @@ webkit_web_view_populate_popup_cb (WebKitWebView* web_view,
             G_CALLBACK (midori_web_view_menu_new_window_activate_cb), view);
         menuitem = (GtkWidget*)g_list_nth_data (items, 3);
         g_list_free (items);
+        #if WEBKIT_CHECK_VERSION (1, 1, 3)
+        /* hack to localize menu item */
+        label = gtk_bin_get_child (GTK_BIN (menuitem));
+        gtk_label_set_label (GTK_LABEL (label), _("_Download Link destination"));
+        #else
         /* hack to disable non-functional Download File
            FIXME: Make sure this really is the right menu item */
         gtk_widget_hide (menuitem);
@@ -998,6 +1041,7 @@ webkit_web_view_populate_popup_cb (WebKitWebView* web_view,
                 G_CALLBACK (midori_web_view_menu_download_activate_cb), view);
             gtk_widget_show (menuitem);
         }
+        #endif
         menuitem = gtk_image_menu_item_new_from_stock (STOCK_BOOKMARK_ADD, NULL);
         gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 5);
         g_signal_connect (menuitem, "activate",
@@ -1144,12 +1188,14 @@ webkit_web_view_mime_type_decision_cb (GtkWidget*               web_view,
     midori_view_update_icon (view, NULL);
     g_object_notify (G_OBJECT (view), "mime-type");
 
-    /* TODO: Display contents with a Viewable if WebKit can't do it */
-    /* TODO: Offer downloading file if it cannot be displayed at all */
-
     if (webkit_web_view_can_show_mime_type (WEBKIT_WEB_VIEW (web_view), mime_type))
         return FALSE;
 
+    #if WEBKIT_CHECK_VERSION (1, 1, 3)
+    webkit_web_policy_decision_download (decision);
+    return TRUE;
+    #endif
+
     uri = g_strdup_printf ("error:nodisplay %s",
         webkit_network_request_get_uri (request));
     midori_view_set_uri (view, uri);
@@ -1158,6 +1204,18 @@ webkit_web_view_mime_type_decision_cb (GtkWidget*               web_view,
     return TRUE;
 }
 
+#if WEBKIT_CHECK_VERSION (1, 1, 3)
+static gboolean
+webkit_web_view_download_requested_cb (GtkWidget*      web_view,
+                                       WebKitDownload* download,
+                                       MidoriView*     view)
+{
+    gboolean handled;
+    g_signal_emit (view, signals[DOWNLOAD_REQUESTED], 0, download, &handled);
+    return handled;
+}
+#endif
+
 static void
 webkit_web_view_console_message_cb (GtkWidget*   web_view,
                                     const gchar* message,
@@ -1576,7 +1634,12 @@ midori_view_construct_web_view (MidoriView* view)
                       webkit_web_view_create_web_view_cb, view,
                       "signal::mime-type-policy-decision-requested",
                       webkit_web_view_mime_type_decision_cb, view,
+                      #if WEBKIT_CHECK_VERSION (1, 1, 3)
+                      "signal::download-requested",
+                      webkit_web_view_download_requested_cb, view,
+                      #endif
                       NULL);
+
     g_object_connect (web_frame,
                       "signal::load-done",
                       webkit_web_frame_load_done_cb, view,
index ddc8cee21c0104e39a78367da18f3f8e0ad3ec4f..237edb9ddae5696cdbda9b4f0b32b48f5bd0d7e7 100644 (file)
@@ -291,6 +291,18 @@ midori_web_settings_get_property (GObject*    object,
                                   GValue*     value,
                                   GParamSpec* pspec);
 
+static const gchar*
+midori_get_download_dir (void)
+{
+    const gchar* dir = g_get_user_special_dir (G_USER_DIRECTORY_DOWNLOAD);
+    if (dir)
+    {
+        g_mkdir_with_parents (dir, 0700);
+        return dir;
+    }
+    return g_get_home_dir ();
+}
+
 static void
 midori_web_settings_class_init (MidoriWebSettingsClass* class)
 {
@@ -525,8 +537,12 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
                                      "download-folder",
                                      _("Download Folder"),
                                      _("The folder downloaded files are saved to"),
-                                     g_get_home_dir (),
-                                     G_PARAM_READABLE));
+                                     midori_get_download_dir (),
+    #if WEBKIT_CHECK_VERSION (1, 1, 3)
+                                     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+    #else
+                                     G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+    #endif
 
     g_object_class_install_property (gobject_class,
                                      PROP_DOWNLOAD_MANAGER,
@@ -584,7 +600,6 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
                                      TRUE,
                                      flags));
 
-    g_type_class_ref (WEBKIT_TYPE_WEB_VIEW);
     g_object_class_install_property (gobject_class,
                                      PROP_OPEN_NEW_PAGES_IN,
                                      g_param_spec_enum (
@@ -845,6 +860,7 @@ notify_default_encoding_cb (GObject*    object,
 static void
 midori_web_settings_init (MidoriWebSettings* web_settings)
 {
+    web_settings->download_folder = g_strdup (midori_get_download_dir ());
     web_settings->http_proxy = NULL;
     web_settings->open_popups_in_tabs = TRUE;
     web_settings->remember_last_form_inputs = TRUE;