[epiphany/mcatanzaro/web-extension-proxy: 2/3] Have EphyEmbedShell own EphyWebExtensionProxy



commit a42d73abe5817d1d3320055cae8c68306f4f8524
Author: Michael Catanzaro <mcatanzaro igalia com>
Date:   Fri Mar 1 22:09:46 2019 -0600

    Have EphyEmbedShell own EphyWebExtensionProxy
    
    Currently we have a wild dual-ownership situation between EphyEmbedShell
    and EphyWebExtensionProxy (which is probably my fault from years ago).
    EphyWebExtensionProxy owns itself and unrefs itself when its D-Bus
    connection is closed, while EphyEmbedShell just watches for the
    EphyWebExtensionProxy to destroy itself with weak pointers. But this is
    racy: sometimes the EphyWebExtensionProxy is leaked because the UI
    process quits before the D-Bus connection is closed. Whoops.
    
    There's no need for objects to own themselves. It's much more natural
    for EphyEmbedShell to own the EphyWebExtensionProxy, since that's where
    it's created. EphyWebExtensionProxy can just signal when the connection
    is closed, so that EphyEmbedShell knows the right time to destroy it.

 embed/ephy-embed-shell.c         | 48 ++++++++++++++++------------------------
 embed/ephy-web-extension-proxy.c | 22 +++++++++---------
 2 files changed, 31 insertions(+), 39 deletions(-)
---
diff --git a/embed/ephy-embed-shell.c b/embed/ephy-embed-shell.c
index 37b79339b..0892d0a21 100644
--- a/embed/ephy-embed-shell.c
+++ b/embed/ephy-embed-shell.c
@@ -200,6 +200,11 @@ ephy_embed_shell_dispose (GObject *object)
     g_clear_object (&priv->cancellable);
   }
 
+  if (priv->web_extensions) {
+    g_list_free_full (priv->web_extensions, g_object_unref);
+    priv->web_extensions = NULL;
+  }
+
   g_clear_object (&priv->encodings);
   g_clear_object (&priv->page_setup);
   g_clear_object (&priv->print_settings);
@@ -920,32 +925,6 @@ ftp_request_cb (WebKitURISchemeRequest *request)
   g_object_unref (app_info);
 }
 
-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)
@@ -1000,18 +979,31 @@ web_extension_page_created (EphyWebExtensionProxy *extension,
   g_signal_emit (shell, signals[PAGE_CREATED], 0, page_id, extension);
 }
 
+static void
+web_extension_connection_closed (EphyWebExtensionProxy *extension,
+                                 EphyEmbedShell        *shell)
+{
+  EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
+
+  priv->web_extensions = g_list_remove (priv->web_extensions, extension);
+  g_object_unref (extension);
+}
+
 static gboolean
 new_connection_cb (GDBusServer     *server,
                    GDBusConnection *connection,
                    EphyEmbedShell  *shell)
 {
+  EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
   EphyWebExtensionProxy *extension;
 
   extension = ephy_web_extension_proxy_new (connection);
-  ephy_embed_shell_watch_web_extension (shell, extension);
+  priv->web_extensions = g_list_prepend (priv->web_extensions, extension);
 
   g_signal_connect_object (extension, "page-created",
                            G_CALLBACK (web_extension_page_created), shell, 0);
+  g_signal_connect_object (extension, "connection-closed",
+                           G_CALLBACK (web_extension_connection_closed), shell, 0);
 
   return TRUE;
 }
@@ -1318,8 +1310,6 @@ ephy_embed_shell_shutdown (GApplication *application)
                                                                           "passwordManagerQueryUsernames",
                                                                           priv->guid);
 
-  g_list_foreach (priv->web_extensions, (GFunc)ephy_embed_shell_unwatch_web_extension, application);
-
   g_object_unref (ephy_embed_prefs_get_settings ());
   ephy_embed_utils_shutdown ();
 }
diff --git a/embed/ephy-web-extension-proxy.c b/embed/ephy-web-extension-proxy.c
index dac338df4..27cfe3b32 100644
--- a/embed/ephy-web-extension-proxy.c
+++ b/embed/ephy-web-extension-proxy.c
@@ -36,6 +36,7 @@ struct _EphyWebExtensionProxy {
 
 enum {
   PAGE_CREATED,
+  CONNECTION_CLOSED,
 
   LAST_SIGNAL
 };
@@ -78,13 +79,6 @@ ephy_web_extension_proxy_class_init (EphyWebExtensionProxyClass *klass)
 
   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,
@@ -92,6 +86,13 @@ ephy_web_extension_proxy_class_init (EphyWebExtensionProxyClass *klass)
                   0, NULL, NULL, NULL,
                   G_TYPE_NONE, 1,
                   G_TYPE_UINT64);
+
+  signals[CONNECTION_CLOSED] =
+    g_signal_new ("connection-closed",
+                  EPHY_TYPE_WEB_EXTENSION_PROXY,
+                  G_SIGNAL_RUN_FIRST,
+                  0, NULL, NULL, NULL,
+                  G_TYPE_NONE, 0);
 }
 
 static void
@@ -120,8 +121,9 @@ web_extension_proxy_created_cb (GDBusProxy            *proxy,
     if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
       g_warning ("Error creating web extension proxy: %s", error->message);
 
-    /* Attempt to trigger connection_closed_cb, which will destroy us, and ensure that
-     * that EphyEmbedShell will remove us from its extensions list.
+    /* Attempt to trigger connection_closed_cb, which will emit the
+     * connection-closed signal, ensuring that EphyEmbedShell will
+     * remove us from its extensions list.
      */
     g_dbus_connection_close (web_extension->connection,
                              web_extension->cancellable,
@@ -154,7 +156,7 @@ connection_closed_cb (GDBusConnection       *connection,
   if (error && !remote_peer_vanished)
     g_warning ("Unexpectedly lost connection to web extension: %s", error->message);
 
-  g_object_unref (web_extension);
+  g_signal_emit (web_extension, signals[CONNECTION_CLOSED], 0);
 }
 
 EphyWebExtensionProxy *


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