From 553cf8c4a065086212d22d52715333ee166b85b5 Mon Sep 17 00:00:00 2001 From: Christian Persch Date: Mon, 4 Jul 2005 12:22:41 +0000 Subject: Better fix for bug #151037 to make session shutdown work again. Also fix 2005-07-04 Christian Persch * embed/downloader-view.c: (remove_download), (prepare_close_cb), (downloader_view_init), (downloader_view_finalize), (downloader_view_remove_download), (download_dialog_delete_cb): * embed/ephy-embed-shell.c: (ephy_embed_shell_prepare_close), (ephy_embed_shell_class_init): * embed/ephy-embed-shell.h: * embed/ephy-favicon-cache.c: (prepare_close_cb), (ephy_favicon_cache_init), (kill_download): * embed/mozilla/mozilla-embed-find.cpp: * embed/mozilla/mozilla-embed-single.cpp: * embed/mozilla/mozilla-embed.cpp: * embed/mozilla/mozilla-notifiers.cpp: * embed/mozilla/mozilla-notifiers.h: * src/ephy-session.c: (ephy_session_init), (ephy_session_dispose), (ephy_session_autoresume), (close_dialog), (ephy_session_close): * src/ephy-shell.c: (ephy_shell_startup), (toolwindow_hide_cb): * src/ephy-window.c: (ephy_window_finalize): Better fix for bug #151037 to make session shutdown work again. Also fix session shutdown while resuming, and preserve the session in this case. --- ChangeLog | 24 +++++++++++++ doc/reference/tmpl/ephy-embed.sgml | 2 ++ embed/downloader-view.c | 62 +++++++++++++++++++++++++++++--- embed/ephy-embed-shell.c | 33 ++++++++++++++++++ embed/ephy-embed-shell.h | 4 +++ embed/ephy-favicon-cache.c | 18 +++++++++- embed/mozilla/mozilla-embed-find.cpp | 3 +- embed/mozilla/mozilla-embed-single.cpp | 19 ++++++++++ embed/mozilla/mozilla-embed.cpp | 13 ++++--- embed/mozilla/mozilla-notifiers.cpp | 6 ++-- embed/mozilla/mozilla-notifiers.h | 3 ++ src/ephy-session.c | 64 ++++++++++++++++++++++------------ src/ephy-shell.c | 19 +++++----- src/ephy-window.c | 3 +- 14 files changed, 223 insertions(+), 50 deletions(-) diff --git a/ChangeLog b/ChangeLog index 27e42f114..201c1c207 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +2005-07-04 Christian Persch + + * embed/downloader-view.c: (remove_download), (prepare_close_cb), + (downloader_view_init), (downloader_view_finalize), + (downloader_view_remove_download), (download_dialog_delete_cb): + * embed/ephy-embed-shell.c: (ephy_embed_shell_prepare_close), + (ephy_embed_shell_class_init): + * embed/ephy-embed-shell.h: + * embed/ephy-favicon-cache.c: (prepare_close_cb), + (ephy_favicon_cache_init), (kill_download): + * embed/mozilla/mozilla-embed-find.cpp: + * embed/mozilla/mozilla-embed-single.cpp: + * embed/mozilla/mozilla-embed.cpp: + * embed/mozilla/mozilla-notifiers.cpp: + * embed/mozilla/mozilla-notifiers.h: + * src/ephy-session.c: (ephy_session_init), (ephy_session_dispose), + (ephy_session_autoresume), (close_dialog), (ephy_session_close): + * src/ephy-shell.c: (ephy_shell_startup), (toolwindow_hide_cb): + * src/ephy-window.c: (ephy_window_finalize): + + Better fix for bug #151037 to make session shutdown work again. + Also fix session shutdown while resuming, and preserve the session + in this case. + 2005-07-03 Jean-François Rameau * embed/ephy-cookie-manager.h: diff --git a/doc/reference/tmpl/ephy-embed.sgml b/doc/reference/tmpl/ephy-embed.sgml index 6ff40c853..6ff26da6b 100644 --- a/doc/reference/tmpl/ephy-embed.sgml +++ b/doc/reference/tmpl/ephy-embed.sgml @@ -247,6 +247,8 @@ be done by casting). @: @: @: +@: +@: @: diff --git a/embed/downloader-view.c b/embed/downloader-view.c index 7499264ed..9ec3ac2da 100644 --- a/embed/downloader-view.c +++ b/embed/downloader-view.c @@ -82,6 +82,8 @@ struct DownloaderViewPrivate GtkWidget *abort_button; EggStatusIcon *status_icon; + + guint idle_unref : 1; }; enum @@ -207,33 +209,82 @@ show_status_icon (DownloaderView *dv) G_CALLBACK(status_icon_popup_menu_cb), dv); } +static gboolean +remove_download (EphyDownload *download, + gpointer rowref, + DownloaderView *view) +{ + g_signal_handlers_disconnect_matched + (download, G_SIGNAL_MATCH_DATA , + 0, 0, NULL, NULL, view); + ephy_download_cancel (download); + + g_object_unref (download); + 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); + + priv->idle_unref = FALSE; + + /* 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) { + g_object_ref (embed_shell); + 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); + dv->priv->idle_unref = TRUE; downloader_view_build_ui (dv); show_status_icon (dv); - g_object_ref (embed_shell); + 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); + gboolean idle_unref = dv->priv->idle_unref; g_object_unref (dv->priv->status_icon); g_hash_table_destroy (dv->priv->downloads_hash); G_OBJECT_CLASS (parent_class)->finalize (object); - ephy_object_idle_unref (embed_shell); + if (idle_unref) + { + ephy_object_idle_unref (embed_shell); + } + else + { + g_object_unref (embed_shell); + } } DownloaderView * @@ -709,7 +760,7 @@ downloader_view_remove_download (DownloaderView *dv, EphyDownload *download) 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); @@ -734,7 +785,9 @@ downloader_view_remove_download (DownloaderView *dv, EphyDownload *download) /* Close the dialog if there are no more downloads */ if (!g_hash_table_size (dv->priv->downloads_hash)) - g_object_unref (G_OBJECT (dv)); + { + g_object_unref (dv); + } } void @@ -765,6 +818,7 @@ gboolean download_dialog_delete_cb (GtkWidget *window, GdkEventAny *event, DownloaderView *dv) { + /* FIXME multi-head */ if (egg_tray_manager_check_running (gdk_screen_get_default ())) { gtk_widget_hide (dv->priv->window); diff --git a/embed/ephy-embed-shell.c b/embed/ephy-embed-shell.c index 8067bf0ea..600037c93 100644 --- a/embed/ephy-embed-shell.c +++ b/embed/ephy-embed-shell.c @@ -43,6 +43,14 @@ struct _EphyEmbedShellPrivate EphyEncodings *encodings; }; +enum +{ + PREPARE_CLOSE, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + static void ephy_embed_shell_class_init (EphyEmbedShellClass *klass); static void ephy_embed_shell_init (EphyEmbedShell *shell); @@ -204,6 +212,14 @@ ephy_embed_shell_get_encodings (EphyEmbedShell *shell) return G_OBJECT (shell->priv->encodings); } +void +ephy_embed_shell_prepare_close (EphyEmbedShell *shell) +{ + EphyEmbedShellPrivate *priv = shell->priv; + + g_signal_emit (shell, signals[PREPARE_CLOSE], 0); +} + static void ephy_embed_shell_init (EphyEmbedShell *shell) { @@ -225,5 +241,22 @@ ephy_embed_shell_class_init (EphyEmbedShellClass *klass) klass->get_embed_single = impl_get_embed_single; +/** + * EphyEmbed::prepare-close: + * @shell: + * + * The ::prepare-close signal is emitted when epiphany is preparing to + * quit on command from the session manager. You can use it when you need + * to do something special (shut down a service, for example). + **/ + signals[PREPARE_CLOSE] = + g_signal_new ("prepare-close", + EPHY_TYPE_EMBED_SHELL, + G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EphyEmbedShellClass, prepare_close), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + g_type_class_add_private (object_class, sizeof (EphyEmbedShellPrivate)); } diff --git a/embed/ephy-embed-shell.h b/embed/ephy-embed-shell.h index b5897781f..d5369749c 100644 --- a/embed/ephy-embed-shell.h +++ b/embed/ephy-embed-shell.h @@ -51,6 +51,8 @@ struct _EphyEmbedShellClass { GObjectClass parent_class; + void (* prepare_close) (EphyEmbedShell *shell); + /*< private >*/ GObject * (* get_embed_single) (EphyEmbedShell *shell); }; @@ -67,6 +69,8 @@ GObject *ephy_embed_shell_get_encodings (EphyEmbedShell *shell); GObject *ephy_embed_shell_get_embed_single (EphyEmbedShell *shell); +void ephy_embed_shell_prepare_close (EphyEmbedShell *shell); + G_END_DECLS #endif /* !EPHY_EMBED_SHELL_H */ diff --git a/embed/ephy-favicon-cache.c b/embed/ephy-favicon-cache.c index 83c14ffad..034ec305d 100644 --- a/embed/ephy-favicon-cache.c +++ b/embed/ephy-favicon-cache.c @@ -29,6 +29,7 @@ #include #include +#include "ephy-embed-shell.h" #include "ephy-embed-persist.h" #include "ephy-embed-factory.h" #include "ephy-file-helpers.h" @@ -44,6 +45,7 @@ static void ephy_favicon_cache_class_init (EphyFaviconCacheClass *klass); static void ephy_favicon_cache_init (EphyFaviconCache *cache); static void ephy_favicon_cache_finalize (GObject *object); +static gboolean kill_download (const char*, EphyEmbedPersist*, EphyFaviconCache*); #define EPHY_FAVICON_CACHE_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_FAVICON_CACHE, EphyFaviconCachePrivate)) @@ -204,6 +206,16 @@ remove_obsolete_icons (EphyFaviconCache *eb) } } +static void +prepare_close_cb (EphyEmbedShell *shell, + EphyFaviconCache *cache) +{ + EphyFaviconCachePrivate *priv = cache->priv; + + g_hash_table_foreach_remove (priv->downloads_hash, + (GHRFunc) kill_download, cache); +} + static void ephy_favicon_cache_init (EphyFaviconCache *cache) { @@ -251,10 +263,14 @@ ephy_favicon_cache_init (EphyFaviconCache *cache) ephy_node_db_load_from_file (cache->priv->db, cache->priv->xml_file, EPHY_FAVICON_CACHE_XML_ROOT, EPHY_FAVICON_CACHE_XML_VERSION); + + /* listen to prepare-close on the shell */ + g_signal_connect_object (embed_shell, "prepare-close", + G_CALLBACK (prepare_close_cb), cache, 0); } static gboolean -kill_download (char *key, +kill_download (const char *key, EphyEmbedPersist *persist, EphyFaviconCache *cache) { diff --git a/embed/mozilla/mozilla-embed-find.cpp b/embed/mozilla/mozilla-embed-find.cpp index 92e755e2b..d039b4d69 100644 --- a/embed/mozilla/mozilla-embed-find.cpp +++ b/embed/mozilla/mozilla-embed-find.cpp @@ -28,7 +28,6 @@ #include "mozilla-embed-find.h" #include "ephy-embed-find.h" #include "ephy-embed-shell.h" -#include "ephy-object-helpers.h" #include "ephy-debug.h" #define MOZILLA_EMBED_FIND_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), MOZILLA_TYPE_EMBED_FIND, MozillaEmbedFindPrivate)) @@ -122,7 +121,7 @@ mozilla_embed_find_finalize (GObject *object) parent_class->finalize (object); - ephy_object_idle_unref (embed_shell); + g_object_unref (embed_shell); } static void diff --git a/embed/mozilla/mozilla-embed-single.cpp b/embed/mozilla/mozilla-embed-single.cpp index 2053914e9..00d06875a 100644 --- a/embed/mozilla/mozilla-embed-single.cpp +++ b/embed/mozilla/mozilla-embed-single.cpp @@ -28,6 +28,7 @@ #include "ephy-cookie-manager.h" #include "ephy-password-manager.h" #include "ephy-permission-manager.h" +#include "ephy-embed-shell.h" #include "glib.h" #include "ephy-debug.h" @@ -544,6 +545,20 @@ init_services (MozillaEmbedSingle *single) return TRUE; } +static void +prepare_close_cb (EphyEmbedShell *shell) +{ + GValue value = { 0, }; + + /* To avoid evil web sites posing an alert and thus inhibiting + * shutdown, we just turn off javascript! :) + */ + g_value_init (&value, G_TYPE_BOOLEAN); + g_value_set_boolean (&value, FALSE); + mozilla_pref_set ("javascript.enabled", &value); + g_value_unset (&value); +} + static void mozilla_embed_single_init (MozillaEmbedSingle *mes) { @@ -571,6 +586,10 @@ mozilla_embed_single_init (MozillaEmbedSingle *mes) exit (0); } + + g_signal_connect_object (embed_shell, "prepare-close", + G_CALLBACK (prepare_close_cb), mes, + (GConnectFlags) 0); } static void diff --git a/embed/mozilla/mozilla-embed.cpp b/embed/mozilla/mozilla-embed.cpp index 1b7733e0d..1a8e31b55 100644 --- a/embed/mozilla/mozilla-embed.cpp +++ b/embed/mozilla/mozilla-embed.cpp @@ -29,7 +29,6 @@ #include "ephy-embed-shell.h" #include "ephy-command-manager.h" #include "ephy-string.h" -#include "ephy-object-helpers.h" #include "ephy-debug.h" #include "EphyBrowser.h" @@ -293,7 +292,7 @@ mozilla_embed_finalize (GObject *object) G_OBJECT_CLASS (parent_class)->finalize (object); - ephy_object_idle_unref (embed_shell); + g_object_unref (embed_shell); } static void @@ -1135,6 +1134,13 @@ _mozilla_embed_new_xul_dialog (void) g_object_ref (embed_shell); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + g_object_set_data_full (G_OBJECT (window), "EmbedShellRef", + embed_shell, + (GDestroyNotify) g_object_unref); + g_signal_connect_object (embed_shell, "prepare_close", + G_CALLBACK (gtk_widget_destroy), window, + (GConnectFlags) G_CONNECT_SWAPPED); + embed = gtk_moz_embed_new (); gtk_widget_show (embed); gtk_container_add (GTK_CONTAINER (window), embed); @@ -1155,8 +1161,5 @@ _mozilla_embed_new_xul_dialog (void) G_CALLBACK (xul_title_cb), window, (GConnectFlags) 0); - g_object_weak_ref (G_OBJECT (window), - (GWeakNotify) ephy_object_idle_unref, embed_shell); - return GTK_MOZ_EMBED (embed); } diff --git a/embed/mozilla/mozilla-notifiers.cpp b/embed/mozilla/mozilla-notifiers.cpp index 717a4fcbc..db227962b 100644 --- a/embed/mozilla/mozilla-notifiers.cpp +++ b/embed/mozilla/mozilla-notifiers.cpp @@ -412,8 +412,8 @@ static const PrefData notifier_entries[] = transform_cookies_accept_mode }, }; -static gboolean -mozilla_set_pref (const char *pref, +gboolean +mozilla_pref_set (const char *pref, const GValue *value) { g_return_val_if_fail (pref != NULL, FALSE); @@ -466,7 +466,7 @@ notify_cb (GConfClient *client, if (data->func (gcvalue, &value, data->user_data)) { - mozilla_set_pref (data->mozilla_pref, &value); + mozilla_pref_set (data->mozilla_pref, &value); g_value_unset (&value); } } diff --git a/embed/mozilla/mozilla-notifiers.h b/embed/mozilla/mozilla-notifiers.h index 72d5d1cf4..642361c29 100644 --- a/embed/mozilla/mozilla-notifiers.h +++ b/embed/mozilla/mozilla-notifiers.h @@ -45,6 +45,9 @@ guint mozilla_notifier_add (const char *gconf_key, void mozilla_notifier_remove (guint id); +gboolean mozilla_pref_set (const char *pref, + const GValue *value); + void mozilla_notifiers_init (void); void mozilla_notifiers_shutdown (void); diff --git a/src/ephy-session.c b/src/ephy-session.c index 96e016137..f39001116 100644 --- a/src/ephy-session.c +++ b/src/ephy-session.c @@ -57,7 +57,8 @@ struct _EphySessionPrivate GList *windows; GList *tool_windows; GtkWidget *resume_dialog; - gboolean dont_save; + guint dont_save : 1; + guint quit_while_resuming : 1; }; #define BOOKMARKS_EDITOR_ID "BookmarksEditor" @@ -261,41 +262,29 @@ impl_detach_window (EphyExtension *extension, */ } -static void -ensure_session_directory (void) -{ - char *dir; - - dir = g_build_filename (ephy_dot_dir (), "sessions", NULL); - if (g_file_test (dir, G_FILE_TEST_EXISTS) == FALSE) - { - if (mkdir (dir, 488) != 0) - { - g_error ("Unable to create session directory '%s'\n", dir); - } - } - - g_free (dir); -} - static void ephy_session_init (EphySession *session) { session->priv = EPHY_SESSION_GET_PRIVATE (session); LOG ("EphySession initialising"); - - ensure_session_directory (); } static void ephy_session_dispose (GObject *object) { EphySession *session = EPHY_SESSION(object); + EphySessionPrivate *priv = session->priv; LOG ("EphySession disposing"); - session_delete (session, SESSION_CRASHED); + /* Only remove the crashed session if we're not shutting down while + * the session resume dialogue was still shown! + */ + if (priv->quit_while_resuming == FALSE) + { + session_delete (session, SESSION_CRASHED); + } parent_class->dispose (object); } @@ -462,12 +451,25 @@ ephy_session_autoresume (EphySession *session, g_free (saved_session); - return retval; + /* ensure we don't open a blank window when quitting while resuming */ + return retval || priv->quit_while_resuming; +} + +static void +close_dialog (GtkWidget *widget) +{ + if (GTK_IS_DIALOG (widget)) + { + /* don't destroy them, someone might have a ref on them */ + gtk_dialog_response (GTK_DIALOG (widget), + GTK_RESPONSE_DELETE_EVENT); + } } void ephy_session_close (EphySession *session) { + EphySessionPrivate *priv = session->priv; GList *windows; LOG ("ephy_session_close"); @@ -476,7 +478,12 @@ ephy_session_close (EphySession *session) * destroying the windows and destroying the tool windows */ g_object_ref (ephy_shell); - session->priv->dont_save = TRUE; + + priv->dont_save = TRUE; + /* need to set this up here while the dialogue hasn't been killed yet */ + priv->quit_while_resuming = priv->resume_dialog != NULL; + + ephy_embed_shell_prepare_close (embed_shell); windows = ephy_session_get_windows (session); g_list_foreach (windows, (GFunc) gtk_widget_destroy, NULL); @@ -486,6 +493,17 @@ ephy_session_close (EphySession *session) g_list_foreach (windows, (GFunc) gtk_widget_destroy, NULL); g_list_free (windows); + ephy_embed_shell_prepare_close (embed_shell); + + /* there may still be windows open, like dialogues posed from + * web pages, etc. Try to kill them, but be sure NOT to destroy + * the gtkmozembed offscreen window! + * Here, we just check if it's a dialogue and close it if it is one. + */ + windows = gtk_window_list_toplevels (); + g_list_foreach (windows, (GFunc) close_dialog, NULL); + g_list_free (windows); + session->priv->dont_save = FALSE; g_object_unref (ephy_shell); } diff --git a/src/ephy-shell.c b/src/ephy-shell.c index 4b9bd1993..26eb28a61 100644 --- a/src/ephy-shell.c +++ b/src/ephy-shell.c @@ -47,7 +47,6 @@ #include "print-dialog.h" #include "ephy-prefs.h" #include "ephy-gui.h" -#include "ephy-object-helpers.h" #ifdef ENABLE_DBUS #include "ephy-dbus.h" @@ -481,8 +480,13 @@ ephy_shell_startup (EphyShell *shell, "from Bonobo when attempting to locate the automation " "object.")); automation = NULL; + goto done; } - else if (flags & EPHY_SHELL_STARTUP_BOOKMARKS_EDITOR) + + /* init the session manager up here so we can quit while the resume dialogue is on */ + gnome_session_init (shell); + + if (flags & EPHY_SHELL_STARTUP_BOOKMARKS_EDITOR) { GNOME_EphyAutomation_openBookmarksEditorWithStartupId (automation, user_time, &ev); @@ -510,14 +514,10 @@ ephy_shell_startup (EphyShell *shell, flags & EPHY_SHELL_STARTUP_FULLSCREEN); } - if (automation) - { - bonobo_object_release_unref (automation, &ev); - } - - gnome_session_init (shell); + bonobo_object_release_unref (automation, &ev); } +done: CORBA_exception_free (&ev); gdk_notify_startup_complete (); @@ -941,8 +941,7 @@ toolwindow_hide_cb (GtkWidget *widget, EphyShell *es) session = EPHY_SESSION (ephy_shell_get_session (es)); ephy_session_remove_window (ephy_shell->priv->session, GTK_WINDOW (widget)); - - ephy_object_idle_unref (ephy_shell); + g_object_unref (ephy_shell); } GtkWidget * diff --git a/src/ephy-window.c b/src/ephy-window.c index 186458fbd..3269b9c1b 100644 --- a/src/ephy-window.c +++ b/src/ephy-window.c @@ -56,7 +56,6 @@ #include "ephy-fullscreen-popup.h" #include "ephy-action-helper.h" #include "ephy-find-toolbar.h" -#include "ephy-object-helpers.h" #include #include @@ -2858,7 +2857,7 @@ ephy_window_finalize (GObject *object) LOG ("Ephy Window finalized %p", object); - ephy_object_idle_unref (ephy_shell); + g_object_unref (ephy_shell); } /** -- cgit v1.2.3