[epiphany/pgriffis/web-extension/get-views: 13/14] WebExtensions: Implement extension.getViews() and extension.getBackgroundPage()




commit 197a67e5e57582025df5871726d5b27130aa5b1a
Author: Patrick Griffis <pgriffis igalia com>
Date:   Mon May 30 12:15:20 2022 -0500

    WebExtensions: Implement extension.getViews() and extension.getBackgroundPage()

 .../web-process-extension/ephy-webextension-api.c  | 52 ++++++++++++++++++++++
 .../resources/js/webextensions.js                  | 25 +++++++++--
 src/webextension/ephy-web-extension-manager.c      |  3 +-
 3 files changed, 76 insertions(+), 4 deletions(-)
---
diff --git a/embed/web-process-extension/ephy-webextension-api.c 
b/embed/web-process-extension/ephy-webextension-api.c
index 2448376f5..42f4330af 100644
--- a/embed/web-process-extension/ephy-webextension-api.c
+++ b/embed/web-process-extension/ephy-webextension-api.c
@@ -41,6 +41,9 @@ G_DEFINE_TYPE (EphyWebExtensionExtension, ephy_web_extension_extension, G_TYPE_O
 
 static EphyWebExtensionExtension *extension = NULL;
 
+static GHashTable *view_contexts;
+static JSCContext *background_context;
+
 static void
 ephy_web_extension_page_user_message_received_cb (WebKitWebPage     *page,
                                                   WebKitUserMessage *message)
@@ -220,6 +223,31 @@ ephy_send_message (const char *function_name,
                                                 ephy_message_data_new (resolve_callback, reject_callback));
 }
 
+static JSCValue *
+ephy_get_view_objects (gpointer user_data)
+{
+  g_autoptr (GPtrArray) window_objects = g_ptr_array_new ();
+  GHashTableIter iter;
+  JSCContext *context;
+
+  g_hash_table_iter_init (&iter, view_contexts);
+  while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&context)) {
+    if (context == background_context)
+      g_ptr_array_insert (window_objects, 0, jsc_context_get_global_object (context));
+    else
+      g_ptr_array_add (window_objects, jsc_context_get_global_object (context));
+  }
+
+  return jsc_value_new_array_from_garray (jsc_context_get_current (), window_objects);
+}
+
+static void
+on_frame_destroyed (gpointer  user_data,
+                    GObject  *object_location)
+{
+  g_hash_table_remove (view_contexts, user_data);
+}
+
 static void
 window_object_cleared_cb (WebKitScriptWorld         *world,
                           WebKitWebPage             *page,
@@ -238,6 +266,16 @@ window_object_cleared_cb (WebKitScriptWorld         *world,
 
   js_context = webkit_frame_get_js_context_for_script_world (frame, world);
 
+  /* FIXME: This is a herustic that the first view is the background view.
+   * instead we should indicate this at extension creation time. */
+  if (!background_context)
+    background_context = js_context;
+
+  if (!g_hash_table_contains (view_contexts, GUINT_TO_POINTER (webkit_frame_get_id (frame)))) {
+    g_hash_table_insert (view_contexts, GUINT_TO_POINTER (webkit_frame_get_id (frame)), g_object_ref 
(js_context));
+    g_object_weak_ref (G_OBJECT (frame), on_frame_destroyed, GUINT_TO_POINTER (webkit_frame_get_id (frame)));
+  }
+
   js_browser = jsc_context_get_value (js_context, "browser");
   g_assert (!jsc_value_is_object (js_browser));
 
@@ -262,6 +300,18 @@ window_object_cleared_cb (WebKitScriptWorld         *world,
 
   ephy_webextension_install_common_apis (js_context, extension->guid, extension->translations);
 
+  js_browser = jsc_context_get_value (js_context, "browser");
+  js_extension = jsc_value_object_get_property (js_browser, "extension");
+
+  js_function = jsc_value_new_function (js_context,
+                                        "ephy_get_view_objects",
+                                        G_CALLBACK (ephy_get_view_objects),
+                                        NULL,
+                                        NULL,
+                                        JSC_TYPE_VALUE, 0);
+  jsc_value_object_set_property (js_extension, "_ephy_get_view_objects", js_function);
+  g_clear_object (&js_function);
+
   bytes = g_resources_lookup_data ("/org/gnome/epiphany-web-extension/js/webextensions.js", 
G_RESOURCE_LOOKUP_FLAGS_NONE, NULL);
   data = g_bytes_get_data (bytes, &data_size);
   result = jsc_context_evaluate_with_source_uri (js_context, data, data_size, 
"resource:///org/gnome/epiphany-web-extension/js/webextensions.js", 1);
@@ -312,6 +362,8 @@ ephy_web_extension_extension_initialize (EphyWebExtensionExtension *extension,
   extension->guid = g_strdup (guid);
   extension->extension = g_object_ref (wk_extension);
 
+  view_contexts = g_hash_table_new_full (NULL, NULL, NULL, g_object_unref);
+
   g_signal_connect (webkit_script_world_get_default (),
                     "window-object-cleared",
                     G_CALLBACK (window_object_cleared_cb),
diff --git a/embed/web-process-extension/resources/js/webextensions.js 
b/embed/web-process-extension/resources/js/webextensions.js
index dea92ae4b..0577555ad 100644
--- a/embed/web-process-extension/resources/js/webextensions.js
+++ b/embed/web-process-extension/resources/js/webextensions.js
@@ -34,9 +34,27 @@ window.browser.notifications = {
 };
 
 // browser.extension is defined in ephy-webextension-common.c
-window.browser.extension.getViews = function (...args) { return []; };
-// Firefox returns null in private mode. So extensions sometimes handle this.
-window.browser.extension.getBackgroundPage = function () { return null; };
+window.browser.extension.getViews = function (fetchProperties) {
+    const window_objects = window.browser.extension._ephy_get_view_objects();
+    if (!window_objects || !fetchProperties)
+        return window_objects;
+
+    // TODO: Implement actual filtering.
+    if (fetchProperties.type === 'background')
+        return [window_objects[0]];
+    else if (fetchProperties.type === 'popup')
+        return window_objects.slice(1);
+    else if (fetchProperties.type !== undefined)
+        return [];
+
+    return window_objects;
+};
+window.browser.extension.getBackgroundPage = function () {
+    const views = window.browser.extension.getViews({type: 'background'});
+    if (!views)
+        return null;
+    return views[0];
+};
 
 // browser.runtime is defined in webextensions-common.js
 window.browser.runtime.getBrowserInfo = function (...args) { return ephy_message ('runtime.getBrowserInfo', 
args); };
@@ -46,6 +64,7 @@ window.browser.runtime.setUninstallURL = function (...args) { return ephy_messag
 window.browser.runtime.onInstalled = new EphyEventListener ();
 window.browser.runtime.onMessageExternal = new EphyEventListener ();
 window.browser.runtime.sendNativeMessage = function (...args) { return ephy_message 
('runtime.sendNativeMessage', args); };
+window.browser.runtime.getBackgroundPage = window.browser.extension.getBackgroundPage;
 
 
 window.browser.pageAction = {
diff --git a/src/webextension/ephy-web-extension-manager.c b/src/webextension/ephy-web-extension-manager.c
index 0dea1d86c..585e7acd6 100644
--- a/src/webextension/ephy-web-extension-manager.c
+++ b/src/webextension/ephy-web-extension-manager.c
@@ -725,6 +725,7 @@ init_web_extension_api (WebKitWebContext *web_context,
 static GtkWidget *
 create_web_extensions_webview (EphyWebExtension *web_extension)
 {
+  EphyWebExtensionManager *manager = ephy_web_extension_manager_get_default ();
   g_autoptr (WebKitUserContentManager) ucm = NULL;
   WebKitSettings *settings;
   WebKitWebContext *web_context;
@@ -745,7 +746,7 @@ create_web_extensions_webview (EphyWebExtension *web_extension)
                            "web-context", web_context,
                            "user-content-manager", ucm,
                            "settings", ephy_embed_prefs_get_settings (),
-                           "expand", TRUE,
+                           "related-view", ephy_web_extension_manager_get_background_web_view (manager, 
web_extension),
                            NULL);
 
   settings = webkit_web_view_get_settings (WEBKIT_WEB_VIEW (web_view));


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