[epiphany] Switch web extensions to using private D-Bus connections



commit b8b391393aca52274063653b2d6e4b3c00e960fd
Author: Michael Catanzaro <mcatanzaro igalia com>
Date:   Sun Feb 7 21:35:02 2016 -0600

    Switch web extensions to using private D-Bus connections
    
    Instead of using the session bus. There's no point in advertising the
    web extension D-Bus interface as if it could be meaningfully used by
    anything other than the Epiphany UI process.
    
    EphyEmbedShell will run the D-Bus server, and the web extensions will
    connect to it.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=761009

 embed/ephy-embed-shell.c                      |  215 +++++++++++++------------
 embed/ephy-web-extension-proxy.c              |  168 +++++++++++---------
 embed/ephy-web-extension-proxy.h              |    4 +-
 embed/web-extension/ephy-web-extension-main.c |   46 +++---
 embed/web-extension/ephy-web-extension.c      |  105 ++++++++-----
 embed/web-extension/ephy-web-extension.h      |    3 +-
 lib/Makefile.am                               |    2 +
 lib/ephy-dbus-util.c                          |   37 +++++
 lib/ephy-dbus-util.h                          |   29 ++++
 9 files changed, 360 insertions(+), 249 deletions(-)
---
diff --git a/embed/ephy-embed-shell.c b/embed/ephy-embed-shell.c
index 6a3abcf..340709f 100644
--- a/embed/ephy-embed-shell.c
+++ b/embed/ephy-embed-shell.c
@@ -21,6 +21,7 @@
 #include "ephy-embed-shell.h"
 
 #include "ephy-about-handler.h"
+#include "ephy-dbus-util.h"
 #include "ephy-debug.h"
 #include "ephy-embed-prefs.h"
 #include "ephy-embed-private.h"
@@ -56,9 +57,8 @@ typedef struct {
   EphyAboutHandler *about_handler;
   guint update_overview_timeout_id;
   guint hiding_overview_item;
-  GDBusConnection *bus;
+  GDBusServer *dbus_server;
   GList *web_extensions;
-  guint web_extensions_page_created_signal_id;
 } EphyEmbedShellPrivate;
 
 enum
@@ -105,32 +105,11 @@ ephy_embed_shell_dispose (GObject *object)
   g_clear_object (&priv->user_content);
   g_clear_object (&priv->downloads_manager);
   g_clear_object (&priv->web_context);
+  g_clear_object (&priv->dbus_server);
 
   G_OBJECT_CLASS (ephy_embed_shell_parent_class)->dispose (object);
 }
 
-static gint
-web_extension_compare (EphyWebExtensionProxy *proxy,
-                       const char *name_owner)
-{
-  return g_strcmp0 (ephy_web_extension_proxy_get_name_owner (proxy), name_owner);
-}
-
-static EphyWebExtensionProxy *
-ephy_embed_shell_find_web_extension (EphyEmbedShell *shell,
-                                     const char *name_owner)
-{
-  EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
-  GList *l;
-
-  l = g_list_find_custom (priv->web_extensions, name_owner, (GCompareFunc)web_extension_compare);
-
-  if (!l)
-    g_warning ("Could not find extension with name owner `%s´.", name_owner);
-
-  return l ? EPHY_WEB_EXTENSION_PROXY (l->data) : NULL;
-}
-
 static void
 web_extension_form_auth_data_message_received_cb (WebKitUserContentManager *manager,
                                                   WebKitJavascriptResult *message,
@@ -154,26 +133,6 @@ web_extension_form_auth_data_message_received_cb (WebKitUserContentManager *mana
 }
 
 static void
-web_extension_page_created (GDBusConnection *connection,
-                            const char *sender_name,
-                            const char *object_path,
-                            const char *interface_name,
-                            const char *signal_name,
-                            GVariant *parameters,
-                            EphyEmbedShell *shell)
-{
-  EphyWebExtensionProxy *web_extension;
-  guint64 page_id;
-
-  g_variant_get (parameters, "(t)", &page_id);
-
-  web_extension = ephy_embed_shell_find_web_extension (shell, sender_name);
-  if (!web_extension)
-    return;
-  g_signal_emit (shell, signals[PAGE_CREATED], 0, page_id, web_extension);
-}
-
-static void
 history_service_query_urls_cb (EphyHistoryService *service,
                                gboolean success,
                                GList *urls,
@@ -300,40 +259,6 @@ web_extension_about_apps_message_received_cb (WebKitUserContentManager *manager,
 }
 
 static void
-web_extension_destroyed (EphyEmbedShell *shell,
-                         GObject *web_extension)
-{
-  EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
-
-  priv->web_extensions = g_list_remove (priv->web_extensions, web_extension);
-}
-
-static void
-ephy_embed_shell_watch_web_extension (EphyEmbedShell *shell,
-                                      const char *web_extension_id)
-{
-  EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
-  EphyWebExtensionProxy *web_extension;
-  char *service_name;
-
-  if (!priv->bus)
-    return;
-
-  service_name = g_strdup_printf ("%s-%s", EPHY_WEB_EXTENSION_SERVICE_NAME, web_extension_id);
-  web_extension = ephy_web_extension_proxy_new (priv->bus, service_name);
-  priv->web_extensions = g_list_prepend (priv->web_extensions, web_extension);
-  g_object_weak_ref (G_OBJECT (web_extension), (GWeakNotify)web_extension_destroyed, shell);
-  g_free (service_name);
-}
-
-static void
-ephy_embed_shell_unwatch_web_extension (EphyWebExtensionProxy *web_extension,
-                                        EphyEmbedShell *shell)
-{
-  g_object_weak_unref (G_OBJECT (web_extension), (GWeakNotify)web_extension_destroyed, shell);
-}
-
-static void
 history_service_url_title_changed_cb (EphyHistoryService *service,
                                       const char *url,
                                       const char *title,
@@ -519,47 +444,129 @@ ephy_resource_request_cb (WebKitURISchemeRequest *request)
 }
 
 static void
+web_extension_destroyed (EphyEmbedShell *shell,
+                         GObject *web_extension)
+{
+  EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
+
+  priv->web_extensions = g_list_remove (priv->web_extensions, web_extension);
+}
+
+static void
+ephy_embed_shell_watch_web_extension (EphyEmbedShell *shell,
+                                      EphyWebExtensionProxy *web_extension)
+{
+  EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
+
+  priv->web_extensions = g_list_prepend (priv->web_extensions, web_extension);
+  g_object_weak_ref (G_OBJECT (web_extension), (GWeakNotify)web_extension_destroyed, shell);
+}
+
+static void
+ephy_embed_shell_unwatch_web_extension (EphyWebExtensionProxy *web_extension,
+                                        EphyEmbedShell *shell)
+{
+  g_object_weak_unref (G_OBJECT (web_extension), (GWeakNotify)web_extension_destroyed, shell);
+}
+
+static void
 initialize_web_extensions (WebKitWebContext* web_context,
                            EphyEmbedShell *shell)
 {
   EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
   GVariant *user_data;
   gboolean private_profile;
-  char *web_extension_id;
-  static guint web_extension_count = 0;
+  const char *address;
 
   webkit_web_context_set_web_extensions_directory (web_context, EPHY_WEB_EXTENSIONS_DIR);
 
-  web_extension_id = g_strdup_printf ("%u-%u", getpid (), ++web_extension_count);
-  ephy_embed_shell_watch_web_extension (shell, web_extension_id);
+  address = priv->dbus_server ? g_dbus_server_get_client_address (priv->dbus_server) : NULL;
 
   private_profile = EPHY_EMBED_SHELL_MODE_HAS_PRIVATE_PROFILE (priv->mode);
-  user_data = g_variant_new ("(ssb)", web_extension_id, ephy_dot_dir (), private_profile);
+  user_data = g_variant_new ("(mssb)",
+                             address,
+                             ephy_dot_dir (),
+                             private_profile);
   webkit_web_context_set_web_extensions_initialization_user_data (web_context, user_data);
 }
 
 static void
-ephy_embed_shell_setup_web_extensions_connection (EphyEmbedShell *shell)
+web_extension_page_created (EphyWebExtensionProxy *extension,
+                            guint64 page_id,
+                            EphyEmbedShell *shell)
+{
+  g_signal_emit (shell, signals[PAGE_CREATED], 0, page_id, extension);
+}
+
+static gboolean
+new_connection_cb (GDBusServer *server,
+                   GDBusConnection *connection,
+                   EphyEmbedShell *shell)
+{
+  EphyWebExtensionProxy *extension = ephy_web_extension_proxy_new (connection);
+  ephy_embed_shell_watch_web_extension (shell, extension);
+
+  g_signal_connect_object (extension, "page-created",
+                           G_CALLBACK (web_extension_page_created), shell, 0);
+
+  return TRUE;
+}
+
+static gboolean
+authorize_authenticated_peer_cb (GDBusAuthObserver *observer,
+                                 GIOStream *stream,
+                                 GCredentials *credentials,
+                                 EphyEmbedShell *shell)
+{
+  return ephy_dbus_peer_is_authorized (credentials);
+}
+
+static void
+ephy_embed_shell_setup_web_extensions_server (EphyEmbedShell *shell)
 {
   EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
+  GDBusAuthObserver *observer;
+  char *address;
+  char *guid;
+  GError *error = NULL;
 
-  priv->bus = g_application_get_dbus_connection (G_APPLICATION (shell));
-  if (!priv->bus) {
-    g_warning ("Application not connected to session bus");
-    return;
+  /* On Linux, this creates an abstract socket with a name that unnecessarily
+   * begins with the tmp dir. Where abstract sockets are unavailable, it
+   * actually creates the socket under the tmp dir. */
+  address = g_strdup_printf ("unix:tmpdir=%s", g_get_tmp_dir ());
+
+  guid = g_dbus_generate_guid ();
+  observer = g_dbus_auth_observer_new ();
+
+  g_signal_connect (observer, "authorize-authenticated-peer",
+                    G_CALLBACK (authorize_authenticated_peer_cb), shell);
+
+  /* Why sync?
+   *
+   * (a) The server must be started before web extensions try to connect.
+   * (b) Gio actually has no async version. Don't know why.
+   */
+  priv->dbus_server = g_dbus_server_new_sync (address,
+                                              G_DBUS_SERVER_FLAGS_NONE,
+                                              guid,
+                                              observer,
+                                              NULL,
+                                              &error);
+
+  if (error) {
+    g_warning ("Failed to start web extension server on %s: %s", address, error->message);
+    g_error_free (error);
+    goto out;
   }
 
-  priv->web_extensions_page_created_signal_id =
-    g_dbus_connection_signal_subscribe (priv->bus,
-                                        NULL,
-                                        EPHY_WEB_EXTENSION_INTERFACE,
-                                        "PageCreated",
-                                        EPHY_WEB_EXTENSION_OBJECT_PATH,
-                                        NULL,
-                                        G_DBUS_SIGNAL_FLAGS_NONE,
-                                        (GDBusSignalCallback)web_extension_page_created,
-                                        shell,
-                                        NULL);
+  g_signal_connect (priv->dbus_server, "new-connection",
+                    G_CALLBACK (new_connection_cb), shell);
+  g_dbus_server_start (priv->dbus_server);
+
+out:
+  g_free (address);
+  g_free (guid);
+  g_object_unref (observer);
 }
 
 static void
@@ -631,7 +638,7 @@ ephy_embed_shell_startup (GApplication* application)
   if (priv->mode != EPHY_EMBED_SHELL_MODE_TEST)
     ephy_embed_shell_create_web_context (embed_shell);
 
-  ephy_embed_shell_setup_web_extensions_connection (shell);
+  ephy_embed_shell_setup_web_extensions_server (shell);
 
   /* User content manager */
   if (priv->mode != EPHY_EMBED_SHELL_MODE_TEST)
@@ -713,16 +720,14 @@ ephy_embed_shell_shutdown (GApplication* application)
 
   G_APPLICATION_CLASS (ephy_embed_shell_parent_class)->shutdown (application);
 
+  if (priv->dbus_server)
+    g_dbus_server_stop (priv->dbus_server);
+
   webkit_user_content_manager_unregister_script_message_handler (priv->user_content, "overview");
   webkit_user_content_manager_unregister_script_message_handler (priv->user_content, "tlsErrorPage");
   webkit_user_content_manager_unregister_script_message_handler (priv->user_content, "formAuthData");
   webkit_user_content_manager_unregister_script_message_handler (priv->user_content, "aboutApps");
 
-  if (priv->web_extensions_page_created_signal_id > 0) {
-    g_dbus_connection_signal_unsubscribe (priv->bus, priv->web_extensions_page_created_signal_id);
-    priv->web_extensions_page_created_signal_id = 0;
-  }
-
   g_list_foreach (priv->web_extensions, (GFunc)ephy_embed_shell_unwatch_web_extension, application);
 
   g_object_unref (ephy_embed_prefs_get_settings ());
diff --git a/embed/ephy-web-extension-proxy.c b/embed/ephy-web-extension-proxy.c
index a62ff4d..6cf067a 100644
--- a/embed/ephy-web-extension-proxy.c
+++ b/embed/ephy-web-extension-proxy.c
@@ -26,37 +26,38 @@ struct _EphyWebExtensionProxy
 {
   GObject parent_instance;
 
-  GDBusProxy *proxy;
-  gchar *name_owner;
   GCancellable *cancellable;
-  guint watch_name_id;
-};
+  GDBusProxy *proxy;
+  GDBusConnection *connection;
 
-G_DEFINE_TYPE (EphyWebExtensionProxy, ephy_web_extension_proxy, G_TYPE_OBJECT)
+  guint page_created_signal_id;
+};
 
-static void
-ephy_web_extension_proxy_finalize (GObject *object)
+enum
 {
-  EphyWebExtensionProxy *web_extension = EPHY_WEB_EXTENSION_PROXY (object);
+  PAGE_CREATED,
 
-  g_clear_object (&web_extension->proxy);
+  LAST_SIGNAL
+};
 
-  G_OBJECT_CLASS (ephy_web_extension_proxy_parent_class)->finalize (object);
-}
+static guint signals[LAST_SIGNAL];
+
+G_DEFINE_TYPE (EphyWebExtensionProxy, ephy_web_extension_proxy, G_TYPE_OBJECT)
 
 static void
 ephy_web_extension_proxy_dispose (GObject *object)
 {
   EphyWebExtensionProxy *web_extension = EPHY_WEB_EXTENSION_PROXY (object);
 
-  g_clear_object (&web_extension->cancellable);
-
-  if (web_extension->watch_name_id > 0) {
-    g_bus_unwatch_name (web_extension->watch_name_id);
-    web_extension->watch_name_id = 0;
+  if (web_extension->page_created_signal_id > 0) {
+    g_dbus_connection_signal_unsubscribe (web_extension->connection,
+                                          web_extension->page_created_signal_id);
+    web_extension->page_created_signal_id = 0;
   }
 
-  g_clear_pointer (&web_extension->name_owner, g_free);
+  g_clear_object (&web_extension->cancellable);
+  g_clear_object (&web_extension->proxy);
+  g_clear_object (&web_extension->connection);
 
   G_OBJECT_CLASS (ephy_web_extension_proxy_parent_class)->dispose (object);
 }
@@ -71,8 +72,36 @@ ephy_web_extension_proxy_class_init (EphyWebExtensionProxyClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-  object_class->finalize = ephy_web_extension_proxy_finalize;
   object_class->dispose = ephy_web_extension_proxy_dispose;
+
+  /**
+   * EphyWebExtensionProxy::page-created:
+   * @web_extension: the #EphyWebExtensionProxy
+   * @page_id: the identifier of the web page created
+   *
+   * Emitted when a web page is created in the web process.
+   */
+  signals[PAGE_CREATED] =
+    g_signal_new ("page-created",
+                  EPHY_TYPE_WEB_EXTENSION_PROXY,
+                  G_SIGNAL_RUN_FIRST,
+                  0, NULL, NULL, NULL,
+                  G_TYPE_NONE, 1,
+                  G_TYPE_UINT64);
+}
+
+static void
+web_extension_page_created (GDBusConnection *connection,
+                            const char *sender_name,
+                            const char *object_path,
+                            const char *interface_name,
+                            const char *signal_name,
+                            GVariant *parameters,
+                            EphyWebExtensionProxy *web_extension)
+{
+  guint64 page_id;
+  g_variant_get (parameters, "(t)", &page_id);
+  g_signal_emit (web_extension, signals[PAGE_CREATED], 0, page_id);
 }
 
 static void
@@ -84,81 +113,72 @@ web_extension_proxy_created_cb (GDBusProxy *proxy,
 
   web_extension->proxy = g_dbus_proxy_new_finish (result, &error);
   if (!web_extension->proxy) {
-    g_warning ("Error creating web extension proxy: %s\n", error->message);
+    g_warning ("Error creating web extension proxy: %s", error->message);
     g_error_free (error);
+
+    /* Attempt to trigger connection_closed_cb, which will destroy us, and ensure that
+     * that EphyEmbedShell will remove us from its extensions list.
+     */
+    g_dbus_connection_close (web_extension->connection,
+                             web_extension->cancellable,
+                             NULL /* GAsyncReadyCallback */,
+                             NULL);
+    return;
   }
 
-  g_object_unref (web_extension);
+  web_extension->page_created_signal_id =
+    g_dbus_connection_signal_subscribe (web_extension->connection,
+                                        NULL,
+                                        EPHY_WEB_EXTENSION_INTERFACE,
+                                        "PageCreated",
+                                        EPHY_WEB_EXTENSION_OBJECT_PATH,
+                                        NULL,
+                                        G_DBUS_SIGNAL_FLAGS_NONE,
+                                        (GDBusSignalCallback)web_extension_page_created,
+                                        web_extension,
+                                        NULL);
 }
 
 static void
-web_extension_appeared_cb (GDBusConnection *connection,
-                           const gchar *name,
-                           const gchar *name_owner,
-                           EphyWebExtensionProxy *web_extension)
+connection_closed_cb (GDBusConnection *connection,
+                      gboolean remote_peer_vanished,
+                      GError *error,
+                      EphyWebExtensionProxy *web_extension)
 {
-  web_extension->name_owner = g_strdup (name_owner);
-  web_extension->cancellable = g_cancellable_new ();
-  g_dbus_proxy_new (connection,
-                    G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START |
-                    G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
-                    G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
-                    NULL,
-                    name,
-                    EPHY_WEB_EXTENSION_OBJECT_PATH,
-                    EPHY_WEB_EXTENSION_INTERFACE,
-                    web_extension->cancellable,
-                    (GAsyncReadyCallback)web_extension_proxy_created_cb,
-                    /* Ref here because the web process could crash, triggering
-                     * web_extension_vanished_cb() before this finishes. */
-                    g_object_ref (web_extension));
-}
-
-static void
-web_extension_vanished_cb (GDBusConnection *connection,
-                           const gchar *name,
-                           EphyWebExtensionProxy *web_extension)
-{
-  if (web_extension->name_owner)
-    g_object_unref (web_extension);
-}
+  if (error) {
+    if (!remote_peer_vanished)
+      g_warning ("Unexpectedly lost connection to web extension: %s", error->message);
+  }
 
-static void
-ephy_web_extension_proxy_watch_name (EphyWebExtensionProxy *web_extension,
-                                     GDBusConnection* bus,
-                                     const char *service_name)
-{
-  web_extension->watch_name_id =
-    g_bus_watch_name_on_connection (bus,
-                                    service_name,
-                                    G_BUS_NAME_WATCHER_FLAGS_NONE,
-                                    (GBusNameAppearedCallback)web_extension_appeared_cb,
-                                    (GBusNameVanishedCallback)web_extension_vanished_cb,
-                                    web_extension,
-                                    NULL);
+  g_object_unref (web_extension);
 }
 
 EphyWebExtensionProxy *
-ephy_web_extension_proxy_new (GDBusConnection *bus,
-                              const char *service_name)
+ephy_web_extension_proxy_new (GDBusConnection *connection)
 {
   EphyWebExtensionProxy *web_extension;
 
-  g_return_val_if_fail (G_IS_DBUS_CONNECTION (bus), NULL);
-  g_return_val_if_fail (service_name != NULL, NULL);
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
 
   web_extension = g_object_new (EPHY_TYPE_WEB_EXTENSION_PROXY, NULL);
-  ephy_web_extension_proxy_watch_name (web_extension, bus, service_name);
 
-  return web_extension;
-}
+  g_signal_connect (connection, "closed",
+                    G_CALLBACK (connection_closed_cb), web_extension);
 
-const char *
-ephy_web_extension_proxy_get_name_owner (EphyWebExtensionProxy *web_extension)
-{
-  g_return_val_if_fail (EPHY_IS_WEB_EXTENSION_PROXY (web_extension), NULL);
+  web_extension->cancellable = g_cancellable_new ();
+  web_extension->connection = g_object_ref (connection);
 
-  return web_extension->name_owner;
+  g_dbus_proxy_new (connection,
+                    G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+                    NULL,
+                    NULL,
+                    EPHY_WEB_EXTENSION_OBJECT_PATH,
+                    EPHY_WEB_EXTENSION_INTERFACE,
+                    web_extension->cancellable,
+                    (GAsyncReadyCallback)web_extension_proxy_created_cb,
+                    web_extension);
+
+  return web_extension;
 }
 
 void
diff --git a/embed/ephy-web-extension-proxy.h b/embed/ephy-web-extension-proxy.h
index a80e8bf..28cf0af 100644
--- a/embed/ephy-web-extension-proxy.h
+++ b/embed/ephy-web-extension-proxy.h
@@ -27,9 +27,7 @@ G_BEGIN_DECLS
 
 G_DECLARE_FINAL_TYPE (EphyWebExtensionProxy, ephy_web_extension_proxy, EPHY, WEB_EXTENSION_PROXY, GObject)
 
-EphyWebExtensionProxy *ephy_web_extension_proxy_new                                       (GDBusConnection   
    *bus,
-                                                                                           const char        
    *service_name);
-const char *           ephy_web_extension_proxy_get_name_owner                            
(EphyWebExtensionProxy *web_extension);
+EphyWebExtensionProxy *ephy_web_extension_proxy_new                                       (GDBusConnection   
    *connection);
 void                   ephy_web_extension_proxy_form_auth_data_save_confirmation_response 
(EphyWebExtensionProxy *web_extension,
                                                                                            guint             
     request_id,
                                                                                            gboolean          
     response);
diff --git a/embed/web-extension/ephy-web-extension-main.c b/embed/web-extension/ephy-web-extension-main.c
index 6db5673..9c416a0 100644
--- a/embed/web-extension/ephy-web-extension-main.c
+++ b/embed/web-extension/ephy-web-extension-main.c
@@ -20,59 +20,51 @@
 #include "config.h"
 
 #include "ephy-web-extension.h"
-#include "ephy-web-extension-names.h"
 #include "ephy-debug.h"
 #include "ephy-file-helpers.h"
 
-static void
-name_acquired_cb (GDBusConnection *connection,
-                  const char *name,
-                  EphyWebExtension *extension)
-{
-  ephy_web_extension_dbus_register (extension, connection);
-}
-
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
 
+static EphyWebExtension *extension = NULL;
+
 G_MODULE_EXPORT void
-webkit_web_extension_initialize_with_user_data (WebKitWebExtension *extension,
+webkit_web_extension_initialize_with_user_data (WebKitWebExtension *webkit_extension,
                                                 GVariant *user_data)
 {
-  EphyWebExtension *web_extension;
-  char *service_name;
-  const char *extension_id;
+  const char *server_address;
   const char *dot_dir;
   gboolean private_profile;
   GError *error = NULL;
 
-  g_variant_get (user_data, "(&s&sb)", &extension_id, &dot_dir, &private_profile);
+  g_variant_get (user_data, "(m&s&sb)", &server_address, &dot_dir, &private_profile);
+
+  if (!server_address) {
+    g_warning ("UI process did not start D-Bus server, giving up.");
+    return;
+  }
 
   if (!ephy_file_helpers_init (dot_dir, 0, &error)) {
-    g_printerr ("Failed to initialize file helpers: %s\n", error->message);
+    g_warning ("Failed to initialize file helpers: %s", error->message);
     g_error_free (error);
   }
 
   ephy_debug_init ();
 
-  web_extension = ephy_web_extension_get ();
-  ephy_web_extension_initialize (web_extension, extension, dot_dir, private_profile);
+  extension = ephy_web_extension_get ();
 
-  service_name = g_strdup_printf ("%s-%s", EPHY_WEB_EXTENSION_SERVICE_NAME, extension_id);
-  g_bus_own_name (G_BUS_TYPE_SESSION,
-                  service_name,
-                  G_BUS_NAME_OWNER_FLAGS_NONE,
-                  NULL,
-                  (GBusNameAcquiredCallback)name_acquired_cb,
-                  NULL,
-                  web_extension, NULL);
-  g_free (service_name);
+  ephy_web_extension_initialize (extension,
+                                 webkit_extension,
+                                 server_address,
+                                 dot_dir,
+                                 private_profile);
 }
 
 static void __attribute__((destructor))
 ephy_web_extension_shutdown (void)
 {
-  g_object_unref (ephy_web_extension_get ());
+  if (extension)
+    g_object_unref (extension);
 }
 
 #pragma GCC diagnostic pop
diff --git a/embed/web-extension/ephy-web-extension.c b/embed/web-extension/ephy-web-extension.c
index 672b803..d72245a 100644
--- a/embed/web-extension/ephy-web-extension.c
+++ b/embed/web-extension/ephy-web-extension.c
@@ -20,6 +20,7 @@
 #include "config.h"
 #include "ephy-web-extension.h"
 
+#include "ephy-dbus-util.h"
 #include "ephy-debug.h"
 #include "ephy-embed-form-auth.h"
 #include "ephy-file-helpers.h"
@@ -49,7 +50,7 @@ struct _EphyWebExtension
   gboolean initialized;
 
   GDBusConnection *dbus_connection;
-  guint registration_id;
+  GCancellable *cancellable;
   GArray *page_created_signals_pending;
 
   EphyUriTester *uri_tester;
@@ -1299,16 +1300,10 @@ ephy_web_extension_dispose (GObject *object)
   if (extension->page_created_signals_pending) {
       g_array_free (extension->page_created_signals_pending, TRUE);
       extension->page_created_signals_pending = NULL;
-    }
+   }
 
-  if (extension->dbus_connection) {
-    g_object_remove_weak_pointer (G_OBJECT (extension->dbus_connection),
-                                  (gpointer *)&extension->dbus_connection);
-    g_dbus_connection_unregister_object (extension->dbus_connection,
-                                         extension->registration_id);
-    extension->registration_id = 0;
-    extension->dbus_connection = NULL;
-  }
+  g_clear_object (&extension->cancellable);
+  g_clear_object (&extension->dbus_connection);
 
   g_clear_object (&extension->extension);
 
@@ -1342,12 +1337,63 @@ ephy_web_extension_get (void)
   return EPHY_WEB_EXTENSION (g_once (&once_init, ephy_web_extension_create_instance, NULL));
 }
 
+static void
+dbus_connection_created_cb (GObject *source_object,
+                            GAsyncResult *result,
+                            EphyWebExtension *extension)
+{
+  static GDBusNodeInfo *introspection_data = NULL;
+  GDBusConnection *connection;
+  guint registration_id;
+  GError *error = NULL;
+
+  if (!introspection_data)
+    introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
+
+  connection = g_dbus_connection_new_for_address_finish (result, &error);
+  if (error) {
+    g_warning ("Failed to connect to UI process: %s", error->message);
+    g_error_free (error);
+    return;
+  }
+
+  registration_id =
+    g_dbus_connection_register_object (connection,
+                                       EPHY_WEB_EXTENSION_OBJECT_PATH,
+                                       introspection_data->interfaces[0],
+                                       &interface_vtable,
+                                       extension,
+                                       NULL,
+                                       &error);
+  if (!registration_id) {
+    g_warning ("Failed to register web extension object: %s\n", error->message);
+    g_error_free (error);
+    g_object_unref (connection);
+    return;
+  }
+
+  extension->dbus_connection = connection;
+  ephy_web_extension_emit_page_created_signals_pending (extension);
+}
+
+static gboolean
+authorize_authenticated_peer_cb (GDBusAuthObserver *observer,
+                                 GIOStream *stream,
+                                 GCredentials *credentials,
+                                 EphyWebExtension *extension)
+{
+  return ephy_dbus_peer_is_authorized (credentials);
+}
+
 void
 ephy_web_extension_initialize (EphyWebExtension *extension,
                                WebKitWebExtension *wk_extension,
+                               const char *server_address,
                                const char *dot_dir,
                                gboolean is_private_profile)
 {
+  GDBusAuthObserver *observer;
+
   g_return_if_fail (EPHY_IS_WEB_EXTENSION (extension));
 
   if (extension->initialized)
@@ -1363,35 +1409,18 @@ ephy_web_extension_initialize (EphyWebExtension *extension,
   g_signal_connect_swapped (extension->extension, "page-created",
                             G_CALLBACK (ephy_web_extension_page_created_cb),
                             extension);
-}
-
-void
-ephy_web_extension_dbus_register (EphyWebExtension *extension,
-                                  GDBusConnection *connection)
-{
-  GError *error = NULL;
-  static GDBusNodeInfo *introspection_data = NULL;
 
-  g_return_if_fail (EPHY_IS_WEB_EXTENSION (extension));
-  g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
+  extension->cancellable = g_cancellable_new ();
 
-  if (!introspection_data)
-    introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
+  observer = g_dbus_auth_observer_new ();
+  g_signal_connect (observer, "authorize-authenticated-peer",
+                    G_CALLBACK (authorize_authenticated_peer_cb), extension);
 
-  extension->registration_id =
-    g_dbus_connection_register_object (connection,
-                                       EPHY_WEB_EXTENSION_OBJECT_PATH,
-                                       introspection_data->interfaces[0],
-                                       &interface_vtable,
-                                       extension,
-                                       NULL,
-                                       &error);
-  if (!extension->registration_id) {
-    g_warning ("Failed to register web extension object: %s\n", error->message);
-    g_error_free (error);
-  } else {
-    extension->dbus_connection = connection;
-    g_object_add_weak_pointer (G_OBJECT (connection), (gpointer *)&extension->dbus_connection);
-    ephy_web_extension_emit_page_created_signals_pending (extension);
-  }
+  g_dbus_connection_new_for_address (server_address,
+                                     G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
+                                     observer,
+                                     extension->cancellable,
+                                     (GAsyncReadyCallback)dbus_connection_created_cb,
+                                     extension);
+  g_object_unref (observer);
 }
diff --git a/embed/web-extension/ephy-web-extension.h b/embed/web-extension/ephy-web-extension.h
index ce62c06..f3535f4 100644
--- a/embed/web-extension/ephy-web-extension.h
+++ b/embed/web-extension/ephy-web-extension.h
@@ -30,10 +30,9 @@ G_DECLARE_FINAL_TYPE (EphyWebExtension, ephy_web_extension, EPHY, WEB_EXTENSION,
 EphyWebExtension *ephy_web_extension_get            (void);
 void              ephy_web_extension_initialize     (EphyWebExtension   *extension,
                                                      WebKitWebExtension *wk_extension,
+                                                     const char         *server_address,
                                                      const char         *dot_dir,
                                                      gboolean            is_private_profile);
-void              ephy_web_extension_dbus_register  (EphyWebExtension   *extension,
-                                                     GDBusConnection    *connection);
 
 
 G_END_DECLS
diff --git a/lib/Makefile.am b/lib/Makefile.am
index e8e96b5..4dc98e6 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -11,6 +11,8 @@ TYPES_H_FILES = \
        ephy-security-levels.h
 
 libephymisc_la_SOURCES = \
+       ephy-dbus-util.c                        \
+       ephy-dbus-util.h                        \
        ephy-debug.c                            \
        ephy-debug.h                            \
        ephy-dnd.c                              \
diff --git a/lib/ephy-dbus-util.c b/lib/ephy-dbus-util.c
new file mode 100644
index 0000000..961c805
--- /dev/null
+++ b/lib/ephy-dbus-util.c
@@ -0,0 +1,37 @@
+/*
+ *  Copyright © 2016 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ephy-dbus-util.h"
+
+gboolean
+ephy_dbus_peer_is_authorized (GCredentials *peer_credentials)
+{
+  static GCredentials *own_credentials = NULL;
+  GError *error = NULL;
+
+  if (!own_credentials)
+    own_credentials = g_credentials_new ();
+
+  if (peer_credentials && g_credentials_is_same_user (peer_credentials, own_credentials, &error))
+    return TRUE;
+
+  if (error) {
+    g_warning ("Failed to authorize web extension connection: %s", error->message);
+    g_error_free (error);
+  }
+  return FALSE;
+}
diff --git a/lib/ephy-dbus-util.h b/lib/ephy-dbus-util.h
new file mode 100644
index 0000000..0da7bb7
--- /dev/null
+++ b/lib/ephy-dbus-util.h
@@ -0,0 +1,29 @@
+/*
+ *  Copyright © 2016 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef EPHY_DBUS_UTIL_H
+#define EPHY_DBUS_UTIL_H
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+gboolean ephy_dbus_peer_is_authorized (GCredentials *peer_credentials);
+
+G_END_DECLS
+
+#endif


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