[epiphany] Implement GtkApplication based activation and uniqueness



commit 8415cf6da16201127aadb7853e3969ed824de919
Author: Claudio Saavedra <csaavedra igalia com>
Date:   Tue Jun 21 01:17:06 2011 +0300

    Implement GtkApplication based activation and uniqueness
    
    This replaces the existing dbus-glib activation and uniqueness code.
    The changes are kept to the minimum necessary to make all the features
    work, but there are still some optimizations possible (like doing most
    of the initialization in ephy_application_startup() when we know we
    are not remoting). These changes are left for later to avoid making
    this patch huge.
    
    Command-line parameter parsing is done in the main method and
    parameters are passed to the application through a
    EphyApplicationStartupContext structure, which is later passed as a
    GVariant to the primare instance. This way we avoid moving the
    GOption code out of the place where it's intended to run: in the
    main() method.
    
    Based in work by Alexandre Mazari.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=637334

 src/Makefile.am        |    4 +
 src/ephy-application.c |  369 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/ephy-application.h |   90 ++++++++++++
 src/ephy-main.c        |  287 +++++--------------------------------
 src/ephy-session.c     |    6 +
 src/ephy-shell.c       |   26 ++++
 src/ephy-shell.h       |    3 +
 src/ephy-window.c      |    2 +
 8 files changed, 537 insertions(+), 250 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 9c2e87e..4b095a8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -16,6 +16,7 @@ header_DATA = \
 NOINST_H_FILES = \
 	ephy-action-helper.h			\
 	ephy-activation.h			\
+	ephy-application.h			\
 	ephy-encoding-dialog.h			\
 	ephy-encoding-menu.h			\
 	ephy-find-toolbar.h			\
@@ -55,6 +56,7 @@ INST_H_FILES = \
 libephymain_la_SOURCES = \
 	ephy-activation.c			\
 	ephy-action-helper.c			\
+	ephy-application.c			\
 	ephy-completion-model.c			\
 	ephy-completion-model.h			\
 	ephy-dbus.c				\
@@ -291,6 +293,7 @@ EPHY_GIR_H_FILES = \
 	$(top_srcdir)/lib/widgets/ephy-download-widget.h \
 	$(top_srcdir)/lib/widgets/ephy-search-entry.h \
 	$(top_srcdir)/src/bookmarks/ephy-bookmarks.h \
+	$(top_srcdir)/src/ephy-application.h \
 	$(top_srcdir)/src/ephy-extension.h \
 	$(top_srcdir)/src/ephy-extensions-manager.h \
 	$(top_srcdir)/src/ephy-find-toolbar.h \
@@ -322,6 +325,7 @@ EPHY_GIR_C_FILES = \
 	$(top_srcdir)/lib/widgets/ephy-download-widget.c \
 	$(top_srcdir)/lib/widgets/ephy-search-entry.c \
 	$(top_srcdir)/src/bookmarks/ephy-bookmarks.c \
+	$(top_srcdir)/src/ephy-application.c \
 	$(top_srcdir)/src/ephy-extension.c \
 	$(top_srcdir)/src/ephy-extensions-manager.c \
 	$(top_srcdir)/src/ephy-find-toolbar.c \
diff --git a/src/ephy-application.c b/src/ephy-application.c
new file mode 100644
index 0000000..8ba4d89
--- /dev/null
+++ b/src/ephy-application.c
@@ -0,0 +1,369 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ *  Copyright  2011 Igalia S.L.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#include "ephy-application.h"
+#include "ephy-file-helpers.h"
+#include "ephy-shell.h"
+#include "ephy-session.h"
+#include "ephy-debug.h"
+#include "ephy-profile-utils.h"
+
+#include <string.h>
+
+#define EPHY_APPLICATION_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_APPLICATION, EphyApplicationPrivate))
+
+struct _EphyApplicationPrivate {
+  EphyApplicationStartupContext *startup_context;
+};
+
+G_DEFINE_TYPE (EphyApplication, ephy_application, GTK_TYPE_APPLICATION);
+
+static void ephy_application_finalize (GObject *object);
+
+/**
+ * ephy_application_startup_context_new:
+ * @bookmarks_filename: A bookmarks file to import.
+ * @session_filename: A session to restore.
+ * @bookmark_url: A URL to be added to the bookmarks.
+ * @arguments: A %NULL-terminated array of URLs and file URIs to be opened.
+ * @user_time: The user time when the EphyApplication startup was invoked.
+ *
+ * Creates a new startup context. All string parameters, including
+ * @arguments, are copied.
+ *
+ * Returns: a newly allocated #EphyApplicationStartupContext
+ **/
+EphyApplicationStartupContext *
+ephy_application_startup_context_new (EphyStartupFlags startup_flags,
+                                      char *bookmarks_filename,
+                                      char *session_filename,
+                                      char *bookmark_url,
+                                      char **arguments,
+                                      guint32 user_time)
+{
+  EphyApplicationStartupContext *ctx = g_slice_new0 (EphyApplicationStartupContext);
+
+  ctx->startup_flags = startup_flags;
+
+  ctx->bookmarks_filename = g_strdup (bookmarks_filename);
+  ctx->session_filename = g_strdup (session_filename);
+  ctx->bookmark_url = g_strdup (bookmark_url);
+
+  ctx->arguments = g_strdupv (arguments);
+
+  ctx->user_time = user_time;
+
+  return ctx;
+}
+
+static void
+ephy_application_free_startup_context (EphyApplication *application)
+{
+  EphyApplicationStartupContext *ctx = application->priv->startup_context;
+
+  g_assert (ctx != NULL);
+
+  g_free (ctx->bookmarks_filename);
+  g_free (ctx->session_filename);
+  g_free (ctx->bookmark_url);
+
+  g_strfreev (ctx->arguments);
+
+  g_slice_free (EphyApplicationStartupContext, ctx);
+
+  application->priv->startup_context = NULL;
+}
+
+static void
+queue_commands (EphyApplication *application)
+{
+  EphyApplicationStartupContext *ctx;
+  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);
+
+  ctx = application->priv->startup_context;
+
+  /* We only get here when starting a new instance, so we first need
+     to autoresume! */
+  ephy_session_queue_command (EPHY_SESSION (ephy_shell_get_session (shell)),
+                              EPHY_SESSION_CMD_RESUME_SESSION,
+                              NULL, NULL, ctx->user_time, TRUE);
+
+  if (ctx->startup_flags & EPHY_STARTUP_BOOKMARKS_EDITOR)
+    ephy_session_queue_command (session,
+                                EPHY_SESSION_CMD_OPEN_BOOKMARKS_EDITOR,
+                                NULL, NULL, ctx->user_time, FALSE);
+
+  else if (ctx->session_filename != NULL) {
+    ephy_session_queue_command (session,
+                                EPHY_SESSION_CMD_LOAD_SESSION,
+                                ctx->session_filename, NULL,
+                                ctx->user_time, FALSE);
+  } else if (ctx->arguments != NULL) {
+    /* Don't queue any window openings if no extra arguments given, */
+    /* since session autoresume will open one for us. */
+    GString *options;
+
+    options = g_string_sized_new (64);
+
+    if (ctx->startup_flags & EPHY_STARTUP_NEW_WINDOW) {
+      g_string_append (options, "new-window,");
+    }
+    if (ctx->startup_flags & EPHY_STARTUP_NEW_TAB) {
+      g_string_append (options, "new-tab,external,");
+    }
+
+    ephy_session_queue_command (session,
+                                EPHY_SESSION_CMD_OPEN_URIS,
+                                options->str,
+                                ctx->arguments,
+                                ctx->user_time, FALSE);
+  }
+}
+
+static void
+ephy_application_startup (GApplication* application)
+{
+  /* We're not remoting; start our services */
+  /* Migrate profile if we are not running a private instance */
+  if (ephy_has_private_profile () == FALSE &&
+      ephy_profile_utils_get_migration_version () < EPHY_PROFILE_MIGRATION_VERSION) {
+    GError *error = NULL;
+    char *argv[1] = { "ephy-profile-migrator" };
+    char *envp[1] = { "EPHY_LOG_MODULES=ephy-profile" };
+
+    g_spawn_sync (NULL, argv, envp, G_SPAWN_SEARCH_PATH,
+                  NULL, NULL, NULL, NULL,
+                  NULL, &error);
+
+    if (error) {
+      LOG ("Failed to run migrator: %s", error->message);
+      g_error_free (error);
+    }
+  }
+}
+
+static void
+ephy_application_activate (GApplication *application)
+{
+  /*
+   * We get here on each new instance (remote or not). Queue the
+   * commands.
+   */
+  queue_commands (EPHY_APPLICATION (application));
+}
+
+/*
+ * We use this enumeration to conveniently fill and read from the
+ * dictionary variant that is sent from the remote to the primary
+ * instance.
+ */
+typedef enum {
+  CTX_STARTUP_FLAGS,
+  CTX_BOOKMARKS_FILENAME,
+  CTX_SESSION_FILENAME,
+  CTX_BOOKMARK_URL,
+  CTX_ARGUMENTS,
+  CTX_USER_TIME
+}CtxEnum;
+
+static void
+ephy_application_add_platform_data (GApplication *application,
+                                    GVariantBuilder *builder)
+{
+  EphyApplication *app;
+  EphyApplicationStartupContext *ctx;
+  GVariantBuilder *ctx_builder;
+
+  app = EPHY_APPLICATION (application);
+
+  G_APPLICATION_CLASS (ephy_application_parent_class)->add_platform_data (application,
+                                                                          builder);
+
+  if (app->priv->startup_context) {
+    /*
+     * We create an array variant that contains only the elements in
+     * ctx that are non-NULL.
+     */
+    ctx_builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
+    ctx = app->priv->startup_context;
+
+    if (ctx->startup_flags) {
+      g_variant_builder_add (ctx_builder, "{iv}",
+                             CTX_STARTUP_FLAGS,
+                             g_variant_new_byte (ctx->startup_flags));
+    }
+    if (ctx->bookmarks_filename) {
+      g_variant_builder_add (ctx_builder, "{iv}",
+                             CTX_BOOKMARKS_FILENAME,
+                             g_variant_new_string (ctx->bookmarks_filename));
+    }
+    if (ctx->session_filename) {
+      g_variant_builder_add (ctx_builder, "{iv}",
+                             CTX_SESSION_FILENAME,
+                             g_variant_new_string (ctx->session_filename));
+    }
+    if (ctx->bookmark_url) {
+      g_variant_builder_add (ctx_builder, "{iv}",
+                             CTX_BOOKMARK_URL,
+                             g_variant_new_string (ctx->bookmark_url));
+    }
+    if (ctx->arguments) {
+      g_variant_builder_add (ctx_builder, "{iv}",
+                             CTX_ARGUMENTS,
+                             g_variant_new_strv ((const gchar * const *)ctx->arguments, -1));
+    }
+
+    g_variant_builder_add (ctx_builder, "{iv}",
+                           CTX_USER_TIME,
+                           g_variant_new_uint32 (ctx->user_time));
+
+    g_variant_builder_add (builder, "{sv}",
+                           "ephy-application-startup-context",
+                           g_variant_builder_end (ctx_builder));
+
+    g_variant_builder_unref (ctx_builder);
+  }
+}
+
+static void
+ephy_application_before_emit (GApplication *application,
+                              GVariant *platform_data)
+{
+  GVariantIter iter, ctx_iter;
+  const char *key;
+  CtxEnum ctx_key;
+  GVariant *value, *ctx_value;
+  EphyApplicationStartupContext *ctx = NULL;
+
+  EphyApplication *app = EPHY_APPLICATION (application);
+
+  g_variant_iter_init (&iter, platform_data);
+  while (g_variant_iter_loop (&iter, "{&sv}", &key, &value)) {
+    if (strcmp (key, "ephy-application-startup-context") == 0) {
+      ctx = g_slice_new0 (EphyApplicationStartupContext);
+
+      /*
+       * Iterate over the startup context variant and fill the members
+       * that were wired. Everything else is just NULL.
+       */
+      g_variant_iter_init (&ctx_iter, value);
+      while (g_variant_iter_loop (&ctx_iter, "{iv}", &ctx_key, &ctx_value)) {
+        switch (ctx_key) {
+        case CTX_STARTUP_FLAGS:
+          ctx->startup_flags = g_variant_get_byte (ctx_value);
+          break;
+        case CTX_BOOKMARKS_FILENAME:
+          ctx->bookmarks_filename = g_variant_dup_string (ctx_value, NULL);
+          break;
+        case CTX_SESSION_FILENAME:
+          ctx->session_filename = g_variant_dup_string (ctx_value, NULL);
+          break;
+        case CTX_BOOKMARK_URL:
+          ctx->bookmark_url = g_variant_dup_string (ctx_value, NULL);
+          break;
+        case CTX_ARGUMENTS:
+          ctx->arguments = g_variant_dup_strv (ctx_value, NULL);
+          break;
+        case CTX_USER_TIME:
+          ctx->user_time = g_variant_get_uint32 (ctx_value);
+          break;
+        default:
+          g_assert_not_reached ();
+          break;
+        }
+      }
+    }
+  }
+
+  if (app->priv->startup_context)
+    ephy_application_free_startup_context (app);
+  app->priv->startup_context = ctx;
+
+  G_APPLICATION_CLASS (ephy_application_parent_class)->before_emit (application,
+                                                                    platform_data);
+}
+
+static void
+ephy_application_class_init (EphyApplicationClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS(class);
+  GApplicationClass *application_class = G_APPLICATION_CLASS (class);
+
+  object_class->finalize = ephy_application_finalize;
+
+  application_class->startup = ephy_application_startup;
+  application_class->activate = ephy_application_activate;
+  application_class->before_emit = ephy_application_before_emit;
+  application_class->add_platform_data = ephy_application_add_platform_data;
+
+  g_type_class_add_private (class, sizeof (EphyApplicationPrivate));
+}
+
+static void
+ephy_application_init (EphyApplication *application)
+{
+  application->priv = EPHY_APPLICATION_GET_PRIVATE(application);
+  application->priv->startup_context = NULL;
+}
+
+static void
+ephy_application_finalize (GObject *object)
+{
+  ephy_application_free_startup_context (EPHY_APPLICATION (object));
+
+  G_OBJECT_CLASS (ephy_application_parent_class)->finalize (object);
+}
+
+EphyApplication *
+ephy_application_new (void)
+{
+  return g_object_new (EPHY_TYPE_APPLICATION,
+                       "application-id", "org.gnome.Epiphany",
+                       "flags", G_APPLICATION_FLAGS_NONE,
+                       NULL);
+}
+
+/**
+ * ephy_application_set_startup_context:
+ * @application: A #EphyApplication
+ * @ctx: (transfer full): a #EphyApplicationStartupContext
+ *
+ * Sets the startup context to be used during activation of a new instance.
+ * See ephy_application_set_startup_new().
+ **/
+void
+ephy_application_set_startup_context (EphyApplication *application,
+                                      EphyApplicationStartupContext *ctx)
+{
+  g_return_if_fail (EPHY_IS_APPLICATION (application));
+
+  if (application->priv->startup_context)
+    ephy_application_free_startup_context (application);
+
+  application->priv->startup_context = ctx;
+}
diff --git a/src/ephy-application.h b/src/ephy-application.h
new file mode 100644
index 0000000..1b49098
--- /dev/null
+++ b/src/ephy-application.h
@@ -0,0 +1,90 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ *  Copyright  2011 Igalia S.L.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#if !defined (__EPHY_EPIPHANY_H_INSIDE__) && !defined (EPIPHANY_COMPILATION)
+#error "Only <epiphany/epiphany.h> can be included directly."
+#endif
+
+#ifndef __EPHY_APPLICATION_H__
+#define __EPHY_APPLICATION_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_APPLICATION             (ephy_application_get_type ())
+#define EPHY_APPLICATION(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj),EPHY_TYPE_APPLICATION, EphyApplication))
+#define EPHY_APPLICATION_CONST(obj)       (G_TYPE_CHECK_INSTANCE_CAST ((obj), EPHY_TYPE_APPLICATION, EphyApplication const))
+#define EPHY_APPLICATION_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), EPHY_TYPE_APPLICATION, EphyApplicationClass))
+#define EPHY_IS_APPLICATION(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EPHY_TYPE_APPLICATION))
+#define EPHY_IS_APPLICATION_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), EPHY_TYPE_APPLICATION))
+#define EPHY_APPLICATION_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), EPHY_TYPE_APPLICATION, EphyApplicationClass))
+
+typedef struct _EphyApplication       EphyApplication;
+typedef struct _EphyApplicationPrivate  EphyApplicationPrivate;
+typedef struct _EphyApplicationClass  EphyApplicationClass;
+
+extern EphyApplication *application;
+
+struct _EphyApplication {
+  GtkApplication parent;
+
+  EphyApplicationPrivate *priv;
+};
+
+struct _EphyApplicationClass {
+  GtkApplicationClass parent_class;
+};
+
+typedef enum {
+  EPHY_STARTUP_NEW_TAB          = 1 << 0,
+  EPHY_STARTUP_NEW_WINDOW       = 1 << 1,
+  EPHY_STARTUP_BOOKMARKS_EDITOR = 1 << 2
+} EphyStartupFlags;
+
+typedef struct {
+  EphyStartupFlags startup_flags;
+
+  char *bookmarks_filename;
+  char *session_filename;
+  char *bookmark_url;
+
+  char **arguments;
+
+  guint32 user_time;
+} EphyApplicationStartupContext;
+
+GType      ephy_application_get_type (void) G_GNUC_CONST;
+
+EphyApplication *ephy_application_new (void);
+
+void             ephy_application_set_startup_context (EphyApplication *application,
+                                                       EphyApplicationStartupContext *ctx);
+
+EphyApplicationStartupContext *
+ephy_application_startup_context_new (EphyStartupFlags startup_flags,
+                                      char *bookmarks_filename,
+                                      char *session_filename,
+                                      char *bookmark_url,
+                                      char **arguments,
+                                      guint32 user_time);
+G_END_DECLS
+
+#endif
diff --git a/src/ephy-main.c b/src/ephy-main.c
index 850b283..896cdcb 100644
--- a/src/ephy-main.c
+++ b/src/ephy-main.c
@@ -20,19 +20,15 @@
 
 #include "config.h"
 
+#include "ephy-application.h"
 #include "ephy-settings.h"
 #include "ephy-shell.h"
 #include "ephy-file-helpers.h"
-#include "ephy-object-helpers.h"
 #include "ephy-state.h"
 #include "ephy-debug.h"
 #include "ephy-stock-icons.h"
-#include "ephy-dbus-client-bindings.h"
-#include "ephy-activation.h"
 #include "ephy-session.h"
 #include "ephy-shell.h"
-#include "ephy-prefs.h"
-#include "ephy-profile-utils.h"
 #include "ephy-debug.h"
 #include "ephy-string.h"
 #include "eggsmclient.h"
@@ -200,169 +196,6 @@ slowly_and_stupidly_obtain_timestamp (Display *xdisplay)
 }
 
 static void
-unref_proxy_reply_cb (DBusGProxy *proxy,
-		      GError *error,
-		      gpointer user_data)
-{
-	if (error != NULL)
-	{
-		g_warning ("An error occurred while calling remote method: %s", error->message);
-		g_error_free (error);
-	}
-
-	g_object_unref (proxy);
-
-	if (gtk_main_level ())
-	{
-		gtk_main_quit ();
-	}
-}
-
-static gboolean
-open_urls (DBusGProxy *proxy,
-	   guint32 user_time,
-	   GError **error)
-{
-	static const char *empty_arguments[] = { "", NULL };
-	GString *options;
-	char **uris;
-
-	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,");
-	}
-
-	if (arguments == NULL)
-	{
-		uris = (char **) empty_arguments;
-	}
-	else
-	{
-		uris = (char **) arguments;
-	}
-
-	org_gnome_Epiphany_load_ur_ilist_async
-		(proxy, (const char **) uris, options->str, user_time,
-		 unref_proxy_reply_cb, NULL);
-	
-	if (arguments != NULL)
-	{
-		g_strfreev (arguments);
-		arguments = NULL;
-	}
-
-	g_string_free (options, TRUE);
-
-	return TRUE;
-}
-
-static gboolean
-call_dbus_proxy (DBusGProxy *proxy,
-		 guint32 user_time,
-		 GError **error)
-{
-	EphyShell *shell;
-	gboolean retval = TRUE;
-
-	shell = ephy_shell_get_default ();
-
-	if (open_as_bookmarks_editor)
-	{
-		org_gnome_Epiphany_open_bookmarks_editor_async
-			(proxy, user_time,
-			 unref_proxy_reply_cb, shell);
-	}
-	else if (session_filename != NULL)
-	{
-		org_gnome_Epiphany_load_session_async
-			(proxy, session_filename, user_time,
-			 unref_proxy_reply_cb, shell);
-
-		g_free (session_filename);
-		session_filename = NULL;
-	}
-	else
-	{
-		retval = open_urls (proxy, user_time, error);
-	}
-
-	/* FIXME why? */
-	dbus_g_connection_flush (ephy_dbus_get_bus (ephy_dbus_get_default (), EPHY_DBUS_SESSION));
-
-	return retval;
-}
-
-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 (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,external,");
-		}
-
-		ephy_session_queue_command (session,
-					    EPHY_SESSION_CMD_OPEN_URIS,
-					    options->str,
-					    arguments,
-					    user_time, FALSE);
-
-		g_strfreev (arguments);
-		arguments = NULL;
-	}
-}
-
-static void
 show_error_message (GError **error)
 {
 	GtkWidget *dialog;
@@ -383,10 +216,19 @@ show_error_message (GError **error)
 	gtk_dialog_run (GTK_DIALOG (dialog));
 }
 
-static void
-shell_quit_cb (EphyShell *shell, gpointer data)
+static EphyStartupFlags
+get_startup_flags (void)
 {
-	gtk_main_quit ();
+	EphyStartupFlags flags = 0;
+
+	if (open_in_new_tab)
+		flags |= EPHY_STARTUP_NEW_TAB;
+	if (open_in_new_window)
+		flags |= EPHY_STARTUP_NEW_WINDOW;
+	if (open_as_bookmarks_editor)
+		flags |= EPHY_STARTUP_BOOKMARKS_EDITOR;
+
+	return flags;
 }
 
 int
@@ -395,10 +237,13 @@ main (int argc,
 {
 	GOptionContext *option_context;
 	GOptionGroup *option_group;
-	DBusGProxy *proxy;
 	GError *error = NULL;
 	guint32 user_time;
 	gboolean arbitrary_url;
+	EphyApplication *application;
+	EphyApplicationStartupContext *ctx;
+	EphyStartupFlags startup_flags;
+	int status;
 
 #ifdef ENABLE_NLS
 	/* Initialize the i18n stuff */
@@ -409,7 +254,6 @@ main (int argc,
 
 	/* Threads have to be initialised before calling ANY glib function */
 	g_thread_init (NULL);
-	dbus_g_thread_init ();
 
 	/* check libxml2 API version epiphany was compiled with against the
 	 * version we're running with.
@@ -570,87 +414,17 @@ main (int argc,
 
 	startup_error_quark = g_quark_from_static_string ("epiphany-startup-error");
 
-	if (!_ephy_dbus_startup (!private_instance, &error))
-	{
-		_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 (!private_instance &&
-	    !_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 ();
-
-			show_error_message (&error);
-
-			exit (1);
-		}
-
-		/* Wait for the response */
-		gtk_main ();
-
-		_ephy_dbus_release ();
-
-		gdk_notify_startup_complete ();
-
-		exit (0);
-	}
-
-	/* We're not remoting; start our services */
+	/* Start our services */
 	if (!ephy_file_helpers_init (profile_directory,
 				     private_instance,
 				     keep_temp_directory || profile_directory,
 				     &error))
 	{
-		_ephy_dbus_release ();
-
 		show_error_message (&error);
 
 		exit (1);
 	}
 
-	/* Migrate profile if we are not running a private instance */
-	if (ephy_has_private_profile () == FALSE &&
-	    ephy_profile_utils_get_migration_version () < EPHY_PROFILE_MIGRATION_VERSION)
-	{
-		GError *error = NULL;
-		char *argv[1] = { "ephy-profile-migrator" };
-		char *envp[1] = { "EPHY_LOG_MODULES=ephy-profile" };
-
-		g_spawn_sync (NULL, argv, envp, G_SPAWN_SEARCH_PATH,
-			      NULL, NULL, NULL, NULL,
-			      NULL, &error);
-
-		if (error)
-		{
-			LOG ("Failed to run migrator: %s", error->message);
-			g_error_free (error);
-		}
-	}
-
 	ephy_stock_icons_init ();
 	ephy_file_load_accels ();
 
@@ -659,11 +433,26 @@ main (int argc,
 
 	/* Now create the shell */
 	_ephy_shell_create_instance ();
-	g_signal_connect (ephy_shell, "quit", G_CALLBACK (shell_quit_cb), NULL);
 
-	queue_commands (user_time);
+	application = ephy_shell_get_application (ephy_shell_get_default());
+	if (private_instance) {
+		GApplicationFlags flags;
 
-	gtk_main ();
+		flags = g_application_get_flags (G_APPLICATION (application));
+		flags |= G_APPLICATION_NON_UNIQUE;
+
+		g_application_set_flags (G_APPLICATION (application), flags);
+	}
+	startup_flags = get_startup_flags ();
+	ctx = ephy_application_startup_context_new (startup_flags,
+						    bookmarks_file,
+						    session_filename,
+						    bookmark_url,
+						    arguments,
+						    user_time);
+	g_strfreev (arguments);
+	ephy_application_set_startup_context (application, ctx);
+	status = g_application_run (G_APPLICATION (application), argc, argv);
 
 	/* Shutdown */
 	g_object_unref (ephy_shell);
@@ -674,7 +463,5 @@ main (int argc,
 	ephy_file_helpers_shutdown ();
 	xmlCleanupParser ();
 
-	_ephy_dbus_release ();
-
-	return 0;
+	return status;
 }
diff --git a/src/ephy-session.c b/src/ephy-session.c
index 0c52fe2..9e489d0 100644
--- a/src/ephy-session.c
+++ b/src/ephy-session.c
@@ -816,6 +816,8 @@ session_command_dispatch (EphySession *session)
 		run_again = FALSE;
 	}
 
+	g_application_release (G_APPLICATION (ephy_shell_get_application (ephy_shell_get_default ())));
+
 	/* This unrefs the shell! */
 	session_command_free (cmd);
 
@@ -1674,6 +1676,7 @@ ephy_session_add_window (EphySession *session,
 
 	session->priv->tool_windows =
 		g_list_append (session->priv->tool_windows, window);
+	gtk_application_add_window (GTK_APPLICATION (ephy_shell_get_application (ephy_shell_get_default ())), window);
 
 	ephy_session_save (session, SESSION_CRASHED);
 }
@@ -1694,6 +1697,7 @@ ephy_session_remove_window (EphySession *session,
 
 	session->priv->tool_windows =
 		g_list_remove (session->priv->tool_windows, window);
+	gtk_application_remove_window (GTK_APPLICATION (ephy_shell_get_application (ephy_shell_get_default ())), window);
 
 	ephy_session_save (session, SESSION_CRASHED);
 }
@@ -1800,6 +1804,8 @@ ephy_session_queue_command (EphySession *session,
 
 	session_command_queue_next (session);
 
+	g_application_hold (G_APPLICATION (ephy_shell_get_application (ephy_shell_get_default ())));
+
 	if (priv->resume_window != NULL)
 	{
 		gtk_window_present_with_time (GTK_WINDOW (priv->resume_window),
diff --git a/src/ephy-shell.c b/src/ephy-shell.c
index 6a246ee..7c6f6d6 100644
--- a/src/ephy-shell.c
+++ b/src/ephy-shell.c
@@ -72,6 +72,7 @@ struct _EphyShellPrivate
 	EggToolbarsModel *toolbars_model;
 	EggToolbarsModel *fs_toolbars_model;
 	EphyExtensionsManager *extensions_manager;
+	EphyApplication *application;
 #ifdef ENABLE_NETWORK_MANAGER
 	EphyNetworkManager *nm_proxy;
 #endif
@@ -212,6 +213,8 @@ ephy_shell_init (EphyShell *shell)
 	ephy_shell = shell;
 	g_object_add_weak_pointer (G_OBJECT(ephy_shell),
 				   (gpointer *)ptr);
+
+	shell->priv->application = ephy_application_new ();
 }
 
 static void
@@ -304,6 +307,13 @@ ephy_shell_dispose (GObject *object)
 	}
 #endif /* ENABLE_NETWORK_MANAGER */
 
+	if (priv->application != NULL)
+	{
+		LOG ("Unref application");
+		g_object_unref (priv->application);
+		priv->application = NULL;
+	}
+
 	G_OBJECT_CLASS (ephy_shell_parent_class)->dispose (object);
 }
 
@@ -805,6 +815,22 @@ ephy_shell_get_prefs_dialog (EphyShell *shell)
 	return shell->priv->prefs_dialog;
 }
 
+/**
+ * ephy_shell_get_application:
+ * @shell: A #EphyApplication
+ *
+ * Gets the #EphyApplication for @shell
+ *
+ * Returns: (transfer none): a #EphyApplication
+ **/
+EphyApplication *
+ephy_shell_get_application (EphyShell *shell)
+{
+	g_return_val_if_fail (EPHY_IS_SHELL (shell), NULL);
+
+	return shell->priv->application;
+}
+
 void
 _ephy_shell_create_instance (void)
 {
diff --git a/src/ephy-shell.h b/src/ephy-shell.h
index 895c91d..18d6aab 100644
--- a/src/ephy-shell.h
+++ b/src/ephy-shell.h
@@ -29,6 +29,7 @@
 #include "ephy-bookmarks.h"
 #include "ephy-window.h"
 #include "ephy-embed.h"
+#include "ephy-application.h"
 
 #include <webkit/webkit.h>
 #include <glib-object.h>
@@ -126,6 +127,8 @@ GObject        *ephy_shell_get_pdm_dialog		(EphyShell *shell);
 
 GObject        *ephy_shell_get_prefs_dialog		(EphyShell *shell);
 
+EphyApplication *ephy_shell_get_application             (EphyShell *shell);
+
 /* private API */
 void	       _ephy_shell_create_instance		(void);
 
diff --git a/src/ephy-window.c b/src/ephy-window.c
index 0069151..28031e5 100644
--- a/src/ephy-window.c
+++ b/src/ephy-window.c
@@ -3825,6 +3825,8 @@ ephy_window_constructor (GType type,
 	proxies = gtk_action_get_proxies (action);
 	proxy = GTK_WIDGET (proxies->data);
 	priv->entry = ephy_location_entry_get_entry (EPHY_LOCATION_ENTRY (proxy));
+	gtk_window_set_application (GTK_WINDOW (window),
+				    GTK_APPLICATION (ephy_shell_get_application (ephy_shell_get_default ())));
 	
 	return object;
 }



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