diff options
-rw-r--r-- | ChangeLog | 32 | ||||
-rw-r--r-- | data/epiphany-service.xml | 15 | ||||
-rw-r--r-- | lib/ephy-file-helpers.c | 12 | ||||
-rw-r--r-- | lib/ephy-file-helpers.h | 4 | ||||
-rw-r--r-- | src/ephy-activation.c | 119 | ||||
-rw-r--r-- | src/ephy-activation.h | 2 | ||||
-rw-r--r-- | src/ephy-dbus.c | 5 | ||||
-rw-r--r-- | src/ephy-dbus.h | 5 | ||||
-rw-r--r-- | src/ephy-main.c | 264 | ||||
-rw-r--r-- | src/ephy-session.c | 622 | ||||
-rw-r--r-- | src/ephy-session.h | 25 | ||||
-rw-r--r-- | src/epiphany.defs | 9 |
12 files changed, 742 insertions, 372 deletions
@@ -1,3 +1,35 @@ +2006-02-02 Christian Persch <chpe@cvs.gnome.org> + + * src/ephy-session.c: (save_yourself_cb), (die_cb), + (session_command_free), (session_command_find), + (resume_dialog_response_cb), (resume_dialog_weak_ref_cb), + (session_command_autoresume), + (session_command_open_bookmarks_editor), + (session_command_open_uris), (session_command_dispatch), + (session_command_queue_next), (session_command_queue_clear), + (ephy_session_init), (ephy_session_dispose), + (ephy_session_finalize), (ephy_session_close), (ephy_session_load), + (ephy_session_get_active_window), (ephy_session_queue_command): + * src/ephy-session.h: + * src/ephy-main.c: (unref_proxy_reply_cb), (open_urls), + (call_dbus_proxy), (queue_commands), (main): + + Queue commands received from the main and remote instances, + and process them after autoresume has completed. Bug #328286. + + * data/epiphany-service.xml: + * lib/ephy-file-helpers.c: (ephy_file_helpers_init): + * lib/ephy-file-helpers.h: + * src/ephy-activation.c: (session_queue_command), + (ephy_activation_load_uri_list), (ephy_activation_load_session), + (ephy_activation_open_bookmarks_editor): + * src/ephy-activation.h: + * src/ephy-dbus.c: + * src/ephy-dbus.h: + * src/epiphany.defs: + + Adapt to those changed APIs. + 2006-01-31 Peter Harvey <peter.a.harvey@gmail.com> * lib/egg/egg-editable-toolbar.c diff --git a/data/epiphany-service.xml b/data/epiphany-service.xml index 049536f27..f2a759a73 100644 --- a/data/epiphany-service.xml +++ b/data/epiphany-service.xml @@ -2,16 +2,17 @@ <node name="/org/gnome/Epiphany"> <interface name="org.gnome.Epiphany"> <method name="loadSession"> - <arg type="s"/> - <arg type="u"/> + <arg type="s" name="SessionFilename" direction="in" /> + <arg type="u" name="Timestamp" direction="in" /> </method> - <method name="loadUris"> - <arg type="as"/> - <arg type="s"/> - <arg type="u"/> + <method name="loadURIList"> + <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="ephy_activation_load_uri_list" /> + <arg type="as" name="URIs" direction="in" /> + <arg type="s" name="Options" direction="in" /> + <arg type="u" name="Timestamp" direction="in" /> </method> <method name="openBookmarksEditor"> - <arg type="u"/> + <arg type="u" name="Timestamp" direction="in" /> </method> </interface> </node> diff --git a/lib/ephy-file-helpers.c b/lib/ephy-file-helpers.c index 1f93225b5..7a40fde5e 100644 --- a/lib/ephy-file-helpers.c +++ b/lib/ephy-file-helpers.c @@ -61,6 +61,7 @@ static GHashTable *files = NULL; static GHashTable *mime_table = NULL; static gboolean have_private_profile = FALSE; +static gboolean delete_profile_on_exit = FALSE; static char *dot_dir = NULL; static char *tmp_dir = NULL; static GList *del_on_exit = NULL; @@ -257,7 +258,9 @@ ephy_dot_dir (void) } gboolean -ephy_file_helpers_init (gboolean private_profile, +ephy_file_helpers_init (const char *profile_dir, + gboolean private_profile, + gboolean delete_profile, GError **error) { const char *uuid; @@ -281,8 +284,13 @@ ephy_file_helpers_init (gboolean private_profile, (GDestroyNotify) g_free); have_private_profile = private_profile; + delete_profile_on_exit = delete_profile; - if (private_profile) + if (private_profile && profile_dir != NULL) + { + dot_dir = g_strdup (profile_dir); + } + else if (private_profile) { if (ephy_file_tmp_dir () == NULL) { diff --git a/lib/ephy-file-helpers.h b/lib/ephy-file-helpers.h index 505e609c6..8f9440af9 100644 --- a/lib/ephy-file-helpers.h +++ b/lib/ephy-file-helpers.h @@ -43,7 +43,9 @@ typedef struct _EphyFileMonitor EphyFileMonitor; typedef void (* EphyFileMonitorFunc) (EphyFileMonitor*, const char*, GnomeVFSMonitorEventType, gpointer); typedef gboolean (* EphyFileMonitorDelayFunc) (EphyFileMonitor*, gpointer); -gboolean ephy_file_helpers_init (gboolean private_profile, +gboolean ephy_file_helpers_init (const char *profile_dir, + gboolean private_profile, + gboolean delete_profile_on_exit, GError **error); const char *ephy_file (const char *filename); diff --git a/src/ephy-activation.c b/src/ephy-activation.c index 8ad478748..c5b01d386 100644 --- a/src/ephy-activation.c +++ b/src/ephy-activation.c @@ -25,108 +25,57 @@ #include "ephy-shell.h" #include "ephy-session.h" #include "ephy-prefs.h" -#include "ephy-gui.h" #include "eel-gconf-extensions.h" #include "ephy-debug.h" -#include <string.h> - -gboolean -ephy_activation_load_uris (EphyDbus *ephy_dbus, - char **uris, - char *options, - guint startup_id, - GError **error) +static gboolean +session_queue_command (EphySessionCommand command, + char *arg, + char **args, + guint startup_id, + GError **error) { EphyShell *shell; EphySession *session; - EphyNewTabFlags flags = 0; - EphyWindow *window; - EphyTab *tab; - static char *empty_urls[] = { "", NULL }; - guint32 user_time = (guint32) startup_id; - guint i; - - g_return_val_if_fail (uris != NULL && options != NULL, TRUE); shell = ephy_shell_get_default (); - - g_object_ref (shell); - - session = EPHY_SESSION (ephy_shell_get_session (shell)); - g_assert (session != NULL); - - if (eel_gconf_get_boolean (CONF_LOCKDOWN_DISABLE_ARBITRARY_URL)) - { - uris = empty_urls; - } - - window = ephy_session_get_active_window (session); - -#if 0 - if (open_in_existing_tab && window != NULL) - { - ephy_gui_window_update_user_time (GTK_WIDGET (window), - user_time); - ephy_window_load_url (window, url); - return TRUE; - } -#endif - - if (strstr (options, "new-window") != NULL) - { - window = NULL; - flags |= EPHY_NEW_TAB_IN_NEW_WINDOW; - } - else if (strstr (options, "new-tab") != NULL) - { - flags |= EPHY_NEW_TAB_IN_EXISTING_WINDOW | - EPHY_NEW_TAB_JUMP; - } - - for (i = 0; uris[i] != NULL; ++i) + if (shell == NULL) { - const char *url = uris[i]; - EphyNewTabFlags page_flags; - - if (url[0] == '\0') - { - page_flags = EPHY_NEW_TAB_HOME_PAGE; - } - else - { - page_flags = EPHY_NEW_TAB_OPEN_PAGE; - } - - tab = ephy_shell_new_tab_full (shell,window, - NULL, url, - flags | page_flags, - EPHY_EMBED_CHROME_ALL, - FALSE, user_time); - - window = EPHY_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (tab))); + g_set_error (error, + g_quark_from_static_string ("ephy-activation-error"), + 0, + "Shutting down." /* FIXME i18n & better string */); + return FALSE; } - g_object_unref (shell); + session = EPHY_SESSION (ephy_shell_get_session (ephy_shell_get_default())); + g_assert (session != NULL); - /* FIXME: do we have to g_strfreev (uris) ? */ + ephy_session_queue_command (session, command, arg, args, + (guint32) startup_id, FALSE); return TRUE; } gboolean +ephy_activation_load_uri_list (EphyDbus *ephy_dbus, + char **uris, + char *options, + guint startup_id, + GError **error) +{ + return session_queue_command (EPHY_SESSION_CMD_OPEN_URIS, + options, uris, startup_id, error); +} + +gboolean ephy_activation_load_session (EphyDbus *ephy_dbus, char *session_name, guint startup_id, GError **error) { - EphySession *session; - guint32 user_time = (guint32) startup_id; - - session = EPHY_SESSION (ephy_shell_get_session (ephy_shell)); - ephy_session_load (session, session_name, user_time); - - return TRUE; + return session_queue_command (EPHY_SESSION_CMD_LOAD_SESSION, + session_name, NULL, startup_id, error); } gboolean @@ -134,9 +83,6 @@ ephy_activation_open_bookmarks_editor (EphyDbus *ephy_dbus, guint startup_id, GError **error) { - GtkWidget *editor; - guint32 user_time = (guint32) startup_id; - if (eel_gconf_get_boolean (CONF_LOCKDOWN_DISABLE_BOOKMARK_EDITING)) { g_set_error (error, @@ -147,9 +93,6 @@ ephy_activation_open_bookmarks_editor (EphyDbus *ephy_dbus, return FALSE; } - editor = ephy_shell_get_bookmarks_editor (ephy_shell); - ephy_gui_window_update_user_time (editor, user_time); - gtk_window_present (GTK_WINDOW (editor)); - - return TRUE; + return session_queue_command (EPHY_SESSION_CMD_OPEN_BOOKMARKS_EDITOR, + NULL, NULL, startup_id, error); } diff --git a/src/ephy-activation.h b/src/ephy-activation.h index 600759329..daf62d59f 100644 --- a/src/ephy-activation.h +++ b/src/ephy-activation.h @@ -26,7 +26,7 @@ G_BEGIN_DECLS /* activation handlers */ -gboolean ephy_activation_load_uris (EphyDbus *ephy_dbus, +gboolean ephy_activation_load_uri_list (EphyDbus *ephy_dbus, char **uris, char *options, guint startup_id, diff --git a/src/ephy-dbus.c b/src/ephy-dbus.c index 197fea900..e43523596 100644 --- a/src/ephy-dbus.c +++ b/src/ephy-dbus.c @@ -41,6 +41,11 @@ #define DBUS_NAME_FLAG_DO_NOT_QUEUE 0 #endif +/* Epiphany's DBUS ids */ +#define DBUS_EPHY_SERVICE "org.gnome.Epiphany" +#define DBUS_EPHY_PATH "/org/gnome/Epiphany" +#define DBUS_EPHY_INTERFACE "org.gnome.Epiphany" + #define RECONNECT_DELAY 3000 #define EPHY_DBUS_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_DBUS, EphyDbusPrivate)) diff --git a/src/ephy-dbus.h b/src/ephy-dbus.h index 611be0b77..943a44c76 100644 --- a/src/ephy-dbus.h +++ b/src/ephy-dbus.h @@ -30,11 +30,6 @@ G_BEGIN_DECLS -/* Epiphany's DBUS ids */ -#define DBUS_EPHY_SERVICE "org.gnome.Epiphany" -#define DBUS_EPHY_PATH "/org/gnome/Epiphany" -#define DBUS_EPHY_INTERFACE "org.gnome.Epiphany" - #define EPHY_TYPE_DBUS (ephy_dbus_get_type ()) #define EPHY_DBUS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EPHY_TYPE_DBUS, EphyDbus)) #define EPHY_DBUS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), EPHY_TYPE_DBUS, EphyDbusClass)) diff --git a/src/ephy-main.c b/src/ephy-main.c index be5954587..af53d230b 100644 --- a/src/ephy-main.c +++ b/src/ephy-main.c @@ -32,6 +32,7 @@ #include "ephy-activation.h" #include "ephy-session.h" #include "ephy-shell.h" +#include "ephy-prefs.h" #include "ephy-debug.h" #include <libxml/xmlversion.h> @@ -44,7 +45,6 @@ #include <gtk/gtkmessagedialog.h> #include <libgnome/gnome-program.h> -#include <libgnomeui/gnome-client.h> #include <libgnomeui/gnome-ui-init.h> #include <libgnomevfs/gnome-vfs-init.h> @@ -111,10 +111,17 @@ static const GOptionEntry libgnome_option_entries[] = #endif /* !GNOME_PARAM_GOPTION_CONTEXT */ #ifdef GNOME_ENABLE_DEBUG +static gboolean keep_profile_directory = FALSE; +static char *profile_directory = NULL; + static GOptionEntry debug_option_entries[] = { { "private-instance", 0, 0, G_OPTION_ARG_NONE, &private_instance, - N_("Start a private instance"), NULL }, + "Start a private instance", NULL }, + { "profile", 'p', 0, G_OPTION_ARG_STRING, &profile_directory, + "Profile directory to use in the private instance (default: a newly created directory in tmpdir)", "DIR" }, + { "keep-profile", 0, 0, G_OPTION_ARG_NONE, &keep_profile_directory, + "Don't delete the profile directory on exit (default: delete the temp profile on exit)", NULL }, { NULL } }; #endif /* GNOME_ENABLE_DEBUG */ @@ -235,100 +242,6 @@ shell_weak_notify (gpointer data, } } -static void -dbus_g_proxy_finalized_cb (EphyShell *shell, - GObject *zombie) -{ - LOG ("dbus_g_proxy_finalized_cb"); - - g_object_unref (shell); -} - -/* Gnome session client */ - -static gboolean -save_yourself_cb (GnomeClient *client, - gint phase, - GnomeSaveStyle save_style, - gboolean shutdown, - GnomeInteractStyle interact_style, - gboolean fast, - gpointer user_data) -{ - EphyShell *shell; - EphySession *session; - char *argv[] = { NULL, "--load-session", NULL }; - char *discard_argv[] = { "rm", "-f", NULL }; - char *tmp, *save_to; - - LOG ("save_yourself_cb"); - - /* FIXME FIXME */ - if (!ephy_shell_get_default ()) return FALSE; - - tmp = g_build_filename (ephy_dot_dir (), - "session_gnome-XXXXXX", - NULL); - save_to = ephy_file_tmp_filename (tmp, "xml"); - g_free (tmp); - - shell = ephy_shell_get_default (); - g_assert (shell != NULL); - - session = EPHY_SESSION (ephy_shell_get_session (shell)); - g_assert (session != NULL); - - argv[0] = g_get_prgname (); - argv[2] = save_to; - gnome_client_set_restart_command - (client, 3, argv); - - discard_argv[2] = save_to; - gnome_client_set_discard_command (client, 3, - discard_argv); - - ephy_session_save (session, save_to); - - g_free (save_to); - - return TRUE; -} - -static void -die_cb (GnomeClient* client, - gpointer user_data) - -{ - EphyShell *shell; - EphySession *session; - - LOG ("die_cb"); - - /* FIXME FIXME */ - if (!ephy_shell_get_default ()) return; - - shell = ephy_shell_get_default (); - g_assert (shell != NULL); - - session = EPHY_SESSION (ephy_shell_get_session (shell)); - g_assert (session != NULL); - - ephy_session_close (session); -} - -static void -gnome_session_init (void) -{ - GnomeClient *client; - - client = gnome_master_client (); - - g_signal_connect (client, "save_yourself", - G_CALLBACK (save_yourself_cb), NULL); - g_signal_connect (client, "die", - G_CALLBACK (die_cb), NULL); -} - #if 0 static char * path_from_command_line_arg (const char *arg) @@ -359,7 +272,7 @@ unref_proxy_reply_cb (DBusGProxy *proxy, g_object_unref (proxy); - if (!_ephy_dbus_is_name_owner () && gtk_main_level ()) + if (gtk_main_level ()) { gtk_main_quit (); } @@ -372,6 +285,7 @@ open_urls (DBusGProxy *proxy, { static const char *empty_arguments[] = { "", NULL }; GString *options; + char **uris; options = g_string_sized_new (64); @@ -384,13 +298,20 @@ open_urls (DBusGProxy *proxy, g_string_append (options, "new-tab,"); } - org_gnome_Epiphany_load_uris_async - (proxy, - extra_arguments ? (const char**) extra_arguments : (const char**)empty_arguments, - options->str, user_time, + if (extra_arguments == NULL) + { + uris = (char **) empty_arguments; + } + else + { + uris = (char **) extra_arguments; + } + + org_gnome_Epiphany_load_ur_ilist_async + (proxy, (const char **) uris, options->str, user_time, unref_proxy_reply_cb, NULL); - if (extra_arguments) + if (extra_arguments != NULL) { g_strfreev (extra_arguments); extra_arguments = NULL; @@ -422,22 +343,13 @@ call_dbus_proxy (DBusGProxy *proxy, org_gnome_Epiphany_load_session_async (proxy, session_filename, user_time, unref_proxy_reply_cb, shell); + + g_free (session_filename); + session_filename = NULL; } else { - /* no need to open the homepage if autoresume returns TRUE; - * we already opened session windows */ - if (!_ephy_dbus_is_name_owner () || - (ephy_session_autoresume - (EPHY_SESSION (ephy_shell_get_session (shell)), - user_time) == FALSE)) - { - retval = open_urls (proxy, user_time, error); - } - else - { - ephy_object_idle_unref (proxy); - } + retval = open_urls (proxy, user_time, error); } /* FIXME why? */ @@ -447,6 +359,70 @@ call_dbus_proxy (DBusGProxy *proxy, } static void +queue_commands (guint32 user_time) +{ + EphyShell *shell; + EphySession *session; + + shell = ephy_shell_get_default (); + g_assert (shell != NULL); + + session = EPHY_SESSION (ephy_shell_get_session (shell)); + g_assert (session != NULL); + + /* We only get here when starting a new instance, so we + * first need to autoresume! + */ + ephy_session_queue_command (session, + EPHY_SESSION_CMD_RESUME_SESSION, + NULL, NULL, user_time, TRUE); + + if (open_as_bookmarks_editor) + { + ephy_session_queue_command (session, + EPHY_SESSION_CMD_OPEN_BOOKMARKS_EDITOR, + NULL, NULL, user_time, FALSE); + } + else if (session_filename != NULL) + { + ephy_session_queue_command (session, + EPHY_SESSION_CMD_LOAD_SESSION, + session_filename, NULL, + user_time, FALSE); + + g_free (session_filename); + session_filename = NULL; + } + /* Don't queue any window openings if no extra arguments given, + * since session autoresume will open one for us. + */ + else if (extra_arguments != NULL) + { + GString *options; + + options = g_string_sized_new (64); + + if (open_in_new_window) + { + g_string_append (options, "new-window,"); + } + if (open_in_new_tab) + { + g_string_append (options, "new-tab,"); + } + + ephy_session_queue_command (session, + EPHY_SESSION_CMD_OPEN_URIS, + options->str, + extra_arguments, + user_time, FALSE); + + g_strfreev (extra_arguments); + extra_arguments = NULL; + } +} + +static void show_error_message (GError **error) { GtkWidget *dialog; @@ -582,6 +558,12 @@ main (int argc, #endif /* GNOME_PARAM_GOPTION_CONTEXT */ + if (extra_arguments != NULL && + eel_gconf_get_boolean (CONF_LOCKDOWN_DISABLE_ARBITRARY_URL)) + { + exit (1); + } + /* Get a timestamp manually if need be */ if (user_time == 0) { @@ -605,26 +587,26 @@ main (int argc, exit (1); } - /* Create DBUS proxy */ - proxy = ephy_dbus_get_proxy (ephy_dbus_get_default (), EPHY_DBUS_SESSION); - if (proxy == NULL) - { - error = g_error_new (STARTUP_ERROR_QUARK, - 0, - "Unable to get DBus proxy; aborting activation."); /* FIXME i18n */ - - _ephy_dbus_release (); - - show_error_message (&error); - - exit (1); - } - /* If we're remoting, no need to start up any further services, * just forward the call. */ if (!_ephy_dbus_is_name_owner ()) { + /* Create DBUS proxy */ + proxy = ephy_dbus_get_proxy (ephy_dbus_get_default (), EPHY_DBUS_SESSION); + if (proxy == NULL) + { + error = g_error_new (STARTUP_ERROR_QUARK, + 0, + "Unable to get DBus proxy; aborting activation."); /* FIXME i18n */ + + _ephy_dbus_release (); + + show_error_message (&error); + + exit (1); + } + if (!call_dbus_proxy (proxy, user_time, &error)) { _ephy_dbus_release (); @@ -645,7 +627,7 @@ main (int argc, /* We're not remoting; start our services */ - if (!ephy_file_helpers_init (FALSE, &error)) + if (!ephy_file_helpers_init (NULL, FALSE, FALSE, &error)) { _ephy_dbus_release (); @@ -654,9 +636,6 @@ main (int argc, exit (1); } - /* init the session manager up here so we can quit while the resume dialogue is shown */ - gnome_session_init (); - eel_gconf_monitor_add ("/apps/epiphany/general"); gnome_vfs_init (); ephy_stock_icons_init (); @@ -676,23 +655,8 @@ main (int argc, /* Now create the shell */ _ephy_shell_create_instance (); - g_object_weak_ref (G_OBJECT (proxy), - (GWeakNotify) dbus_g_proxy_finalized_cb, - g_object_ref (ephy_shell_get_default ())); - if (!call_dbus_proxy (proxy, user_time, &error)) - { - g_object_unref (ephy_shell_get_default ()); - g_object_unref (proxy); - g_assert (ephy_shell_get_default () == NULL); - - ephy_file_helpers_shutdown (); - _ephy_dbus_release (); - - show_error_message (&error); - - exit (1); - } + queue_commands (user_time); /* We'll release the initial reference on idle */ g_object_weak_ref (G_OBJECT (ephy_shell), shell_weak_notify, NULL); diff --git a/src/ephy-session.c b/src/ephy-session.c index ffa81bbe6..d9a9a59a0 100644 --- a/src/ephy-session.c +++ b/src/ephy-session.c @@ -36,9 +36,7 @@ #include "ephy-debug.h" #include <glib/gi18n.h> -#include <errno.h> -#include <string.h> -#include <stdlib.h> +#include <gtk/gtkmain.h> #include <gtk/gtkimage.h> #include <gtk/gtklabel.h> #include <gtk/gtkstock.h> @@ -46,11 +44,27 @@ #include <gtk/gtkvbox.h> #include <gtk/gtkdialog.h> #include <gtk/gtkmessagedialog.h> + +#include <libgnomeui/gnome-client.h> + #include <libgnomevfs/gnome-vfs-ops.h> #include <libgnomevfs/gnome-vfs-utils.h> + #include <libxml/tree.h> #include <libxml/xmlwriter.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> + +typedef struct +{ + EphySessionCommand command; + char *arg; + char **args; + guint32 user_time; +} SessionCommand; + #define EPHY_SESSION_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_SESSION, EphySessionPrivate)) struct _EphySessionPrivate @@ -58,6 +72,10 @@ struct _EphySessionPrivate GList *windows; GList *tool_windows; GtkWidget *resume_dialog; + + GQueue *queue; + guint queue_idle_id; + guint dont_save : 1; guint quit_while_resuming : 1; }; @@ -69,6 +87,7 @@ struct _EphySessionPrivate static void ephy_session_class_init (EphySessionClass *klass); static void ephy_session_iface_init (EphyExtensionIface *iface); static void ephy_session_init (EphySession *session); +static void session_command_queue_next (EphySession *session); enum { @@ -117,6 +136,57 @@ ephy_session_get_type (void) return type; } +/* Gnome session client */ + +static gboolean +save_yourself_cb (GnomeClient *client, + gint phase, + GnomeSaveStyle save_style, + gboolean shutdown, + GnomeInteractStyle interact_style, + gboolean fast, + EphySession *session) +{ + char *argv[] = { NULL, "--load-session", NULL }; + char *discard_argv[] = { "rm", "-f", NULL }; + char *tmp, *save_to; + + LOG ("save_yourself_cb"); + + tmp = g_build_filename (ephy_dot_dir (), + "session_gnome-XXXXXX", + NULL); + save_to = ephy_file_tmp_filename (tmp, "xml"); + g_free (tmp); + + argv[0] = g_get_prgname (); + argv[2] = save_to; + gnome_client_set_restart_command + (client, 3, argv); + + discard_argv[2] = save_to; + gnome_client_set_discard_command (client, 3, + discard_argv); + + ephy_session_save (session, save_to); + + g_free (save_to); + + return TRUE; +} + +static void +die_cb (GnomeClient* client, + EphySession *session) + +{ + LOG ("die_cb"); + + ephy_session_close (session); +} + +/* Helper functions */ + static char * get_session_filename (const char *filename) { @@ -207,6 +277,334 @@ window_focus_in_event_cb (EphyWindow *window, return FALSE; } +/* Queue worker */ + +static void +session_command_free (SessionCommand *cmd) +{ + g_assert (cmd != NULL); + + g_free (cmd->arg); + if (cmd->args) + { + g_strfreev (cmd->args); + } + + g_free (cmd); + + g_object_unref (ephy_shell_get_default ()); +} + +static int +session_command_find (const SessionCommand *cmd, + gpointer cmdptr) +{ + EphySessionCommand command = GPOINTER_TO_INT (cmdptr); + + return command != cmd->command; +} + +static void +resume_dialog_response_cb (GtkWidget *dialog, + int response, + EphySession *session) +{ + guint32 user_time; + + LOG ("resume_dialog_response_cb response:%d", response); + + gtk_widget_hide (dialog); + + user_time = gtk_get_current_event_time (); + + if (response == GTK_RESPONSE_ACCEPT) + { + ephy_session_queue_command (session, + EPHY_SESSION_CMD_LOAD_SESSION, + SESSION_CRASHED, NULL, + user_time, TRUE); + } + + ephy_session_queue_command (session, + EPHY_SESSION_CMD_MAYBE_OPEN_WINDOW, + NULL, NULL, user_time, FALSE); + + gtk_widget_destroy (dialog); +} + +static void +resume_dialog_weak_ref_cb (EphySession *session, + GObject *zombie) +{ + EphySessionPrivate *priv = session->priv; + + LOG ("resume_dialog_weak_ref_cb"); + + priv->resume_dialog = NULL; + + gtk_window_set_auto_startup_notification (TRUE); + + session_command_queue_next (session); + + g_object_unref (ephy_shell_get_default ()); +} + +static void +session_command_autoresume (EphySession *session, + guint32 user_time) +{ + EphySessionPrivate *priv = session->priv; + GtkWidget *dialog; + char *saved_session; + gboolean crashed_session; + + LOG ("ephy_session_autoresume"); + + saved_session = get_session_filename (SESSION_CRASHED); + crashed_session = g_file_test (saved_session, G_FILE_TEST_EXISTS); + g_free (saved_session); + + if (crashed_session == FALSE || + priv->windows != NULL || + priv->tool_windows != NULL) + { + /* FIXME can this happen? */ + if (priv->resume_dialog != NULL) + { + gtk_widget_hide (priv->resume_dialog); + gtk_widget_destroy (priv->resume_dialog); + } + + ephy_session_queue_command (session, + EPHY_SESSION_CMD_MAYBE_OPEN_WINDOW, + NULL, NULL, user_time, FALSE); + + return; + } + + if (priv->resume_dialog) + { + gtk_window_present_with_time (GTK_WINDOW (priv->resume_dialog), + user_time); + + return; + } + + /* Ref the shell while we show the dialogue. The unref + * happens in the weak ref notification when the dialogue + * is destroyed. + */ + g_object_ref (ephy_shell_get_default ()); + + dialog = gtk_message_dialog_new + (NULL, + GTK_DIALOG_MODAL, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_NONE, + _("Recover previous browser windows and tabs?")); + + gtk_message_dialog_format_secondary_text + (GTK_MESSAGE_DIALOG (dialog), + _("Epiphany appears to have exited unexpectedly the last time " + "it was run. You can recover the opened windows and tabs.")); + + gtk_dialog_add_button (GTK_DIALOG (dialog), + _("_Don't Recover"), GTK_RESPONSE_CANCEL); + gtk_dialog_add_button (GTK_DIALOG (dialog), + _("_Recover"), GTK_RESPONSE_ACCEPT); + + gtk_window_set_title (GTK_WINDOW (dialog), _("Crash Recovery")); + gtk_window_set_icon_name (GTK_WINDOW (dialog), "web-browser"); + gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER); + gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT); + + g_signal_connect (dialog, "response", + G_CALLBACK (resume_dialog_response_cb), session); + g_object_weak_ref (G_OBJECT (dialog), + (GWeakNotify) resume_dialog_weak_ref_cb, + session); + + /* FIXME ? */ + gtk_window_set_auto_startup_notification (FALSE); + + priv->resume_dialog = dialog; + + gtk_window_present_with_time (GTK_WINDOW (dialog), user_time); +} + +static void +session_command_open_bookmarks_editor (EphySession *session, + guint32 user_time) +{ + GtkWidget *editor; + + editor = ephy_shell_get_bookmarks_editor (ephy_shell_get_default ()); + + gtk_window_present_with_time (GTK_WINDOW (editor), user_time); +} + +static void +session_command_open_uris (EphySession *session, + char **uris, + const char *options, + guint32 user_time) +{ + EphyShell *shell; + EphyWindow *window; + EphyTab *tab; + EphyNewTabFlags flags = 0; + guint i; + + shell = ephy_shell_get_default (); + + g_object_ref (shell); + + window = ephy_session_get_active_window (session); + + if (options != NULL && strstr (options, "new-window") != NULL) + { + window = NULL; + flags |= EPHY_NEW_TAB_IN_NEW_WINDOW; + } + else if (options != NULL && strstr (options, "new-tab") != NULL) + { + flags |= EPHY_NEW_TAB_IN_EXISTING_WINDOW | + EPHY_NEW_TAB_JUMP; + } + + for (i = 0; uris[i] != NULL; ++i) + { + const char *url = uris[i]; + EphyNewTabFlags page_flags; + + if (url[0] == '\0') + { + page_flags = EPHY_NEW_TAB_HOME_PAGE; + } + else + { + page_flags = EPHY_NEW_TAB_OPEN_PAGE; + } + + tab = ephy_shell_new_tab_full (shell, window, + NULL /* parent tab */, + url, + flags | page_flags, + EPHY_EMBED_CHROME_ALL, + FALSE /* is popup? */, + user_time); + + window = EPHY_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (tab))); + } + + g_object_unref (shell); +} + +static gboolean +session_command_dispatch (EphySession *session) +{ + EphySessionPrivate *priv = session->priv; + SessionCommand *cmd; + gboolean run_again = TRUE; + + cmd = g_queue_pop_head (priv->queue); + g_assert (cmd != NULL); + + LOG ("dispatching queue cmd:%d", cmd->command); + + switch (cmd->command) + { + case EPHY_SESSION_CMD_RESUME_SESSION: + session_command_autoresume (session, cmd->user_time); + break; + case EPHY_SESSION_CMD_LOAD_SESSION: + ephy_session_load (session, cmd->arg, cmd->user_time); + break; + case EPHY_SESSION_CMD_OPEN_BOOKMARKS_EDITOR: + session_command_open_bookmarks_editor (session, cmd->user_time); + break; + case EPHY_SESSION_CMD_OPEN_URIS: + session_command_open_uris (session, cmd->args, cmd->arg, cmd->user_time); + break; + case EPHY_SESSION_CMD_MAYBE_OPEN_WINDOW: + /* FIXME: maybe just check for normal windows? */ + if (priv->windows == NULL && + priv->tool_windows == NULL) + { + ephy_shell_new_tab_full (ephy_shell_get_default (), + NULL /* window */, NULL /* tab */, + NULL /* URL */, + EPHY_NEW_TAB_IN_NEW_WINDOW | + EPHY_NEW_TAB_HOME_PAGE, + EPHY_EMBED_CHROME_ALL, + FALSE /* is popup? */, + cmd->user_time); + } + break; + default: + g_assert_not_reached (); + break; + } + + /* Look if there's anything else to dispatch */ + if (g_queue_is_empty (priv->queue) || + priv->resume_dialog != NULL) + { + priv->queue_idle_id = 0; + run_again = FALSE; + } + + /* This unrefs the shell! */ + session_command_free (cmd); + + return run_again; +} + +static void +session_command_queue_next (EphySession *session) +{ + EphySessionPrivate *priv = session->priv; + + LOG ("queue_next"); + + if (!g_queue_is_empty (priv->queue) && + priv->resume_dialog == NULL && + priv->queue_idle_id == 0) + { + priv->queue_idle_id = + g_idle_add ((GSourceFunc) session_command_dispatch, + session); + } +} + +static void +session_command_queue_clear (EphySession *session) +{ + EphySessionPrivate *priv = session->priv; + + if (priv->resume_dialog != NULL) + { + gtk_widget_destroy (priv->resume_dialog); + /* destroying the resume dialogue will set this to NULL */ + g_assert (priv->resume_dialog == NULL); + } + + if (priv->queue_idle_id != 0) + { + g_source_remove (priv->queue_idle_id); + priv->queue_idle_id = 0; + } + + if (priv->queue != NULL) + { + g_queue_foreach (priv->queue, (GFunc) session_command_free, NULL); + g_queue_free (priv->queue); + priv->queue = NULL; + } +} + +/* EphyExtensionIface implementation */ + static void impl_attach_window (EphyExtension *extension, EphyWindow *window) @@ -263,19 +661,33 @@ impl_detach_window (EphyExtension *extension, */ } +/* Class implementation */ + static void ephy_session_init (EphySession *session) { - session->priv = EPHY_SESSION_GET_PRIVATE (session); + EphySessionPrivate *priv; + GnomeClient *client; LOG ("EphySession initialising"); + + priv = session->priv = EPHY_SESSION_GET_PRIVATE (session); + + priv->queue = g_queue_new (); + + client = gnome_master_client (); + g_signal_connect (client, "save-yourself", + G_CALLBACK (save_yourself_cb), session); + g_signal_connect (client, "die", + G_CALLBACK (die_cb), session); } static void ephy_session_dispose (GObject *object) { - EphySession *session = EPHY_SESSION(object); + EphySession *session = EPHY_SESSION (object); EphySessionPrivate *priv = session->priv; + GnomeClient *client; LOG ("EphySession disposing"); @@ -287,6 +699,14 @@ ephy_session_dispose (GObject *object) session_delete (session, SESSION_CRASHED); } + session_command_queue_clear (session); + + client = gnome_master_client (); + g_signal_handlers_disconnect_by_func + (client, G_CALLBACK (save_yourself_cb), session); + g_signal_handlers_disconnect_by_func + (client, G_CALLBACK (die_cb), session); + parent_class->dispose (object); } @@ -301,7 +721,7 @@ ephy_session_finalize (GObject *object) g_list_free (session->priv->windows); g_list_free (session->priv->tool_windows); - G_OBJECT_CLASS (parent_class)->finalize (object); + parent_class->finalize (object); } static void @@ -363,100 +783,7 @@ ephy_session_class_init (EphySessionClass *class) g_type_class_add_private (object_class, sizeof (EphySessionPrivate)); } -static gboolean -offer_to_resume (EphySession *session, - guint32 user_time) -{ - GtkWidget *dialog; - int response; - - dialog = gtk_message_dialog_new - (NULL, - GTK_DIALOG_MODAL, - GTK_MESSAGE_WARNING, - GTK_BUTTONS_NONE, - _("Recover previous browser windows and tabs?")); - - gtk_message_dialog_format_secondary_text - (GTK_MESSAGE_DIALOG (dialog), - _("Epiphany appears to have exited unexpectedly the last time " - "it was run. You can recover the opened windows and tabs.")); - - gtk_dialog_add_button (GTK_DIALOG (dialog), - _("_Don't Recover"), GTK_RESPONSE_CANCEL); - gtk_dialog_add_button (GTK_DIALOG (dialog), - _("_Recover"), GTK_RESPONSE_ACCEPT); - - gtk_window_set_title (GTK_WINDOW (dialog), _("Crash Recovery")); - gtk_window_set_icon_name (GTK_WINDOW (dialog), "web-browser"); - gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER); - gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT); - - session->priv->resume_dialog = dialog; - - ephy_gui_window_update_user_time (session->priv->resume_dialog, - user_time); - - gtk_window_set_auto_startup_notification (FALSE); - response = gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_window_set_auto_startup_notification (TRUE); - - gtk_widget_destroy (dialog); - - session->priv->resume_dialog = NULL; - - return (response == GTK_RESPONSE_ACCEPT); -} - -/** - * ephy_session_autoresume: - * @session: a #EphySession - * @user_time: a timestamp, or 0 - * - * Resume a crashed session when necessary (interactive) - * - * Return value: TRUE if handled; windows have actually - * been opened or the dialog from a previous instance - * has been re-presented to the user. - **/ -gboolean -ephy_session_autoresume (EphySession *session, - guint32 user_time) -{ - EphySessionPrivate *priv = session->priv; - char *saved_session; - gboolean retval = FALSE; - - LOG ("ephy_session_autoresume"); - - if (priv->windows != NULL || priv->tool_windows != NULL) return FALSE; - - if (priv->resume_dialog) - { - ephy_gui_window_update_user_time (priv->resume_dialog, - user_time); - ephy_gui_window_present (GTK_WINDOW (priv->resume_dialog), - user_time); - return TRUE; - } - - saved_session = get_session_filename (SESSION_CRASHED); - - if (g_file_test (saved_session, G_FILE_TEST_EXISTS) - && offer_to_resume (session, user_time)) - { - priv->dont_save = TRUE; - retval = ephy_session_load (session, saved_session, - 0 /* since we've shown the dialogue */); - priv->dont_save = FALSE; - ephy_session_save (session, SESSION_CRASHED); - } - - g_free (saved_session); - - /* ensure we don't open a blank window when quitting while resuming */ - return retval || priv->quit_while_resuming; -} +/* Implementation */ static void close_dialog (GtkWidget *widget) @@ -480,12 +807,15 @@ ephy_session_close (EphySession *session) /* we have to ref the shell or else we may get finalised between * destroying the windows and destroying the tool windows */ - g_object_ref (ephy_shell); + g_object_ref (ephy_shell_get_default ()); 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; + /* Clear command queue */ + session_command_queue_clear (session); + ephy_embed_shell_prepare_close (embed_shell); /* there may still be windows open, like dialogues posed from @@ -513,7 +843,11 @@ ephy_session_close (EphySession *session) g_list_free (windows); session->priv->dont_save = FALSE; - g_object_unref (ephy_shell); + + /* Clear command queue */ + session_command_queue_clear (session); + + g_object_unref (ephy_shell_get_default ()); } static int @@ -861,7 +1195,7 @@ restore_geometry (GtkWindow *window, * ephy_session_load: * @session: a #EphySession * @filename: the path of the source file - * @user_time: a timestamp, or 0 + * @user_time: a user_time, or 0 * * Load a session from disk, restoring the windows and their state * @@ -872,6 +1206,7 @@ ephy_session_load (EphySession *session, const char *filename, guint32 user_time) { + EphySessionPrivate *priv = session->priv; xmlDocPtr doc; xmlNodePtr child; EphyWindow *window; @@ -890,6 +1225,10 @@ ephy_session_load (EphySession *session, return FALSE; } + g_object_ref (ephy_shell_get_default ()); + + priv->dont_save = TRUE; + child = xmlDocGetRootElement (doc); /* skip the session node */ @@ -946,7 +1285,13 @@ ephy_session_load (EphySession *session, xmlFreeDoc (doc); - return (session->priv->windows != NULL || session->priv->tool_windows != NULL); + priv->dont_save = FALSE; + + ephy_session_save (session, SESSION_CRASHED); + + g_object_unref (ephy_shell_get_default ()); + + return (priv->windows != NULL || priv->tool_windows != NULL); } /** @@ -1034,3 +1379,72 @@ ephy_session_get_active_window (EphySession *session) return window; } + +/** + * ephy_session_queue_command: + * @session: a #EphySession + **/ +void +ephy_session_queue_command (EphySession *session, + EphySessionCommand command, + const char *arg, + char **args, + guint32 user_time, + gboolean priority) +{ + EphySessionPrivate *priv; + GList *element; + SessionCommand *cmd; + + LOG ("queue_command command:%d", command); + + g_return_if_fail (EPHY_IS_SESSION (session)); + g_return_if_fail (command != EPHY_SESSION_CMD_OPEN_URIS || args != NULL); + + priv = session->priv; + + /* First look if the same command is already queued */ + if (command > EPHY_SESSION_CMD_RESUME_SESSION && + command < EPHY_SESSION_CMD_OPEN_URIS) + { + element = g_queue_find_custom (priv->queue, + GINT_TO_POINTER (command), + (GCompareFunc) session_command_find); + if (element != NULL) + { + cmd = (SessionCommand *) element->data; + + if ((command == EPHY_SESSION_CMD_LOAD_SESSION && + strcmp (cmd->arg, arg) == 0) || + command == EPHY_SESSION_CMD_OPEN_BOOKMARKS_EDITOR || + command == EPHY_SESSION_CMD_RESUME_SESSION) + { + cmd->user_time = user_time; + g_queue_remove (priv->queue, cmd); + g_queue_push_tail (priv->queue, cmd); + + return; + } + } + } + + /* FIXME: use g_slice_new */ + cmd = g_new0 (SessionCommand, 1); + cmd->command = command; + cmd->arg = arg ? g_strdup (arg) : NULL; + cmd->args = args ? g_strdupv (args) : NULL; + cmd->user_time = user_time; + /* This ref is released in session_command_free */ + g_object_ref (ephy_shell_get_default ()); + + if (priority) + { + g_queue_push_head (priv->queue, cmd); + } + else + { + g_queue_push_tail (priv->queue, cmd); + } + + session_command_queue_next (session); +} diff --git a/src/ephy-session.h b/src/ephy-session.h index 025f8425d..2bdc26fd6 100644 --- a/src/ephy-session.h +++ b/src/ephy-session.h @@ -39,8 +39,19 @@ G_BEGIN_DECLS #define EPHY_SESSION_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EPHY_TYPE_SESSION, EphySessionClass)) typedef struct _EphySession EphySession; -typedef struct _EphySessionClass EphySessionClass; typedef struct _EphySessionPrivate EphySessionPrivate; +typedef struct _EphySessionClass EphySessionClass; + +typedef enum +{ + EPHY_SESSION_CMD_RESUME_SESSION, + EPHY_SESSION_CMD_LOAD_SESSION, + EPHY_SESSION_CMD_OPEN_BOOKMARKS_EDITOR, + EPHY_SESSION_CMD_OPEN_URIS, + EPHY_SESSION_CMD_MAYBE_OPEN_WINDOW, + EPHY_SESSION_CMD_LAST + +} EphySessionCommand; struct _EphySession { @@ -66,9 +77,6 @@ gboolean ephy_session_load (EphySession *session, const char *filename, guint32 user_time); -gboolean ephy_session_autoresume (EphySession *session, - guint32 user_time); - void ephy_session_close (EphySession *session); GList *ephy_session_get_windows (EphySession *session); @@ -76,9 +84,16 @@ GList *ephy_session_get_windows (EphySession *session); void ephy_session_add_window (EphySession *session, GtkWindow *window); -void ephy_session_remove_window (EphySession *session, +void ephy_session_remove_window (EphySession *session, GtkWindow *window); +void ephy_session_queue_command (EphySession *session, + EphySessionCommand op, + const char *arg, + char **args, + guint32 user_time, + gboolean priority); + G_END_DECLS #endif diff --git a/src/epiphany.defs b/src/epiphany.defs index f70c2addb..9d0b81adb 100644 --- a/src/epiphany.defs +++ b/src/epiphany.defs @@ -2968,15 +2968,6 @@ ) ) -(define-method autoresume - (of-object "EphySession") - (c-name "ephy_session_autoresume") - (return-type "gboolean") - (parameters - '("guint32" "user_time") - ) -) - (define-method close (of-object "EphySession") (c-name "ephy_session_close") |