From 7af8baee8bdd5cbfcfb24ff5e2c304c25094d385 Mon Sep 17 00:00:00 2001 From: Christian Dywan Date: Thu, 19 Mar 2009 18:28:50 +0100 Subject: [PATCH] Initial support for WebKitDownload 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 | 1 + midori/midori-browser.c | 139 +++++++++++++++++++++++++++++++++--- midori/midori-preferences.c | 3 + midori/midori-view.c | 69 +++++++++++++++++- midori/midori-websettings.c | 22 +++++- 5 files changed, 219 insertions(+), 15 deletions(-) diff --git a/midori/marshal.list b/midori/marshal.list index c82c5639..825f9730 100644 --- a/midori/marshal.list +++ b/midori/marshal.list @@ -1,3 +1,4 @@ +BOOLEAN:OBJECT BOOLEAN:VOID VOID:BOOLEAN,STRING VOID:OBJECT,ENUM diff --git a/midori/midori-browser.c b/midori/midori-browser.c index 647542ea..e667e7e3 100644 --- a/midori/midori-browser.c +++ b/midori/midori-browser.c @@ -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 = "" "" "" - "" + /* "" */ "" "" "" @@ -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); } diff --git a/midori/midori-preferences.c b/midori/midori-preferences.c index 25ae3a36..753e3136 100644 --- a/midori/midori-preferences.c +++ b/midori/midori-preferences.c @@ -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); diff --git a/midori/midori-view.c b/midori/midori-view.c index f30285d1..a7c5ff9b 100644 --- a/midori/midori-view.c +++ b/midori/midori-view.c @@ -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, diff --git a/midori/midori-websettings.c b/midori/midori-websettings.c index ddc8cee2..237edb9d 100644 --- a/midori/midori-websettings.c +++ b/midori/midori-websettings.c @@ -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;