[epiphany/pgriffis/web-extension-fixes-2] WebExtensions: Refactor web process extension




commit 3abfcd39e3175372ea24824611a6c5ac3d77f09e
Author: Patrick Griffis <pgriffis igalia com>
Date:   Mon May 16 12:20:54 2022 -0500

    WebExtensions: Refactor web process extension
    
    - Ensure the Ephy extension isn't used in WebExtensions
    - Use the default script world for WebExtension views
    - Revert handling ephy-webextension URIs in the main WebContext
       The main web-context should only see a subset of "web_accessible_resources" (TODO)
    - Handle missing WebExtension resources gracefully
    - Fix base_uri for WebExtensions sometimes being incorrect

 embed/ephy-embed-shell.c                           |   5 +-
 .../ephy-web-process-extension-main.c              |   6 +-
 .../web-process-extension/ephy-webextension-api.c  |  24 +--
 src/webextension/api/runtime.c                     |   2 +-
 src/webextension/api/tabs.c                        |  11 +-
 src/webextension/ephy-web-extension-manager.c      | 187 +++++++++++----------
 6 files changed, 127 insertions(+), 108 deletions(-)
---
diff --git a/embed/ephy-embed-shell.c b/embed/ephy-embed-shell.c
index cc5f9832c..97caf1f14 100644
--- a/embed/ephy-embed-shell.c
+++ b/embed/ephy-embed-shell.c
@@ -783,11 +783,12 @@ initialize_web_process_extensions (WebKitWebContext *web_context,
 #endif
 
   private_profile = priv->mode == EPHY_EMBED_SHELL_MODE_PRIVATE || priv->mode == 
EPHY_EMBED_SHELL_MODE_INCOGNITO || priv->mode == EPHY_EMBED_SHELL_MODE_AUTOMATION;
-  user_data = g_variant_new ("(smsbb)",
+  user_data = g_variant_new ("(smsbbb)",
                              priv->guid,
                              ephy_profile_dir_is_default () ? NULL : ephy_profile_dir (),
                              g_settings_get_boolean (EPHY_SETTINGS_WEB, EPHY_PREFS_WEB_REMEMBER_PASSWORDS),
-                             private_profile);
+                             private_profile,
+                             FALSE);
   webkit_web_context_set_web_extensions_initialization_user_data (web_context, g_steal_pointer (&user_data));
 }
 
diff --git a/embed/web-process-extension/ephy-web-process-extension-main.c 
b/embed/web-process-extension/ephy-web-process-extension-main.c
index 749bcf128..63fee6605 100644
--- a/embed/web-process-extension/ephy-web-process-extension-main.c
+++ b/embed/web-process-extension/ephy-web-process-extension-main.c
@@ -39,9 +39,10 @@ webkit_web_extension_initialize_with_user_data (WebKitWebExtension *webkit_exten
   const char *profile_dir;
   gboolean private_profile;
   gboolean should_remember_passwords;
+  gboolean is_webextension;
   g_autoptr (GError) error = NULL;
 
-  g_variant_get (user_data, "(&sm&sbb)", &guid, &profile_dir, &should_remember_passwords, &private_profile);
+  g_variant_get (user_data, "(&sm&sbbb)", &guid, &profile_dir, &should_remember_passwords, &private_profile, 
&is_webextension);
 
   if (!ephy_file_helpers_init (profile_dir, 0, &error))
     g_warning ("Failed to initialize file helpers: %s", error->message);
@@ -53,6 +54,9 @@ webkit_web_extension_initialize_with_user_data (WebKitWebExtension *webkit_exten
 
   extension = ephy_web_process_extension_get ();
 
+  if (is_webextension)
+    return;
+
   ephy_web_process_extension_initialize (extension,
                                          webkit_extension,
                                          guid,
diff --git a/embed/web-process-extension/ephy-webextension-api.c 
b/embed/web-process-extension/ephy-webextension-api.c
index 1830da161..5cf5a6d8e 100644
--- a/embed/web-process-extension/ephy-webextension-api.c
+++ b/embed/web-process-extension/ephy-webextension-api.c
@@ -30,6 +30,7 @@ struct _EphyWebExtensionExtension {
   GObject parent_instance;
 
   WebKitWebExtension *extension;
+  char *guid;
   gboolean initialized;
 
   WebKitScriptWorld *script_world;
@@ -90,14 +91,9 @@ static char *
 js_geturl (const char *path,
            gpointer    user_data)
 {
-  JSCContext *context = jsc_context_get_current ();
-  JSCValue *value;
-  char *ret;
+  EphyWebExtensionExtension *extension = EPHY_WEB_EXTENSION_EXTENSION (user_data);
 
-  value = jsc_context_evaluate (context, "window.location.host", -1);
-  ret = g_strdup_printf ("ephy-webextension://%s/%s", jsc_value_to_string (value), path);
-
-  return ret;
+  return g_strdup_printf ("ephy-webextension://%s/%s", extension->guid, path);
 }
 
 static void
@@ -192,6 +188,7 @@ ephy_web_extension_dispose (GObject *object)
 
   g_clear_object (&extension->script_world);
   g_clear_object (&extension->extension);
+  g_clear_pointer (&extension->guid, g_free);
 
   g_clear_pointer (&extension->translation_table, g_hash_table_destroy);
 
@@ -298,11 +295,11 @@ ephy_web_extension_extension_initialize (EphyWebExtensionExtension *extension,
   if (extension->initialized)
     return;
 
-  extension->initialized = TRUE;
-
   g_assert (guid && *guid);
 
-  extension->script_world = webkit_script_world_new_with_name (guid);
+  extension->initialized = TRUE;
+  extension->guid = g_strdup (guid);
+  extension->script_world = webkit_script_world_get_default ();
 
   g_signal_connect (extension->script_world,
                     "window-object-cleared",
@@ -326,8 +323,13 @@ webkit_web_extension_initialize_with_user_data (WebKitWebExtension *webkit_exten
   const char *profile_dir;
   gboolean private_profile;
   gboolean should_remember_passwords;
+  gboolean is_webextension;
+
+  g_variant_get (user_data, "(&sm&sbbb)", &guid, &profile_dir, &should_remember_passwords, &private_profile, 
&is_webextension);
+
+  if (!is_webextension)
+    return;
 
-  g_variant_get (user_data, "(&sm&sbb)", &guid, &profile_dir, &should_remember_passwords, &private_profile);
   extension = ephy_web_extension_extension_get ();
 
   ephy_web_extension_extension_initialize (extension,
diff --git a/src/webextension/api/runtime.c b/src/webextension/api/runtime.c
index ec67b6600..156390461 100644
--- a/src/webextension/api/runtime.c
+++ b/src/webextension/api/runtime.c
@@ -56,7 +56,7 @@ runtime_handler_send_message (EphyWebExtension *self,
   g_autofree char *script = NULL;
 
   script = g_strdup_printf ("runtimeSendMessage(%s);", jsc_value_to_json (args, 2));
-  webkit_web_view_run_javascript_in_world (view, script, ephy_embed_shell_get_guid (EPHY_EMBED_SHELL 
(shell)), NULL, NULL, NULL);
+  webkit_web_view_run_javascript (view, script, NULL, NULL, NULL);
 
   return NULL;
 }
diff --git a/src/webextension/api/tabs.c b/src/webextension/api/tabs.c
index d54126704..ca156d137 100644
--- a/src/webextension/api/tabs.c
+++ b/src/webextension/api/tabs.c
@@ -163,12 +163,11 @@ tabs_handler_execute_script (EphyWebExtension *self,
   code_value = jsc_value_object_get_property (obj, "code");
   if (code_value) {
     g_autofree char *code = jsc_value_to_string (code_value);
-    webkit_web_view_run_javascript_in_world (WEBKIT_WEB_VIEW (ephy_shell_get_active_web_view (shell)),
-                                             code,
-                                             ephy_embed_shell_get_guid (ephy_embed_shell_get_default ()),
-                                             NULL,
-                                             NULL,
-                                             NULL);
+    webkit_web_view_run_javascript (WEBKIT_WEB_VIEW (ephy_shell_get_active_web_view (shell)),
+                                    code,
+                                    NULL,
+                                    NULL,
+                                    NULL);
   }
 
   return NULL;
diff --git a/src/webextension/ephy-web-extension-manager.c b/src/webextension/ephy-web-extension-manager.c
index f93700cb2..c37543101 100644
--- a/src/webextension/ephy-web-extension-manager.c
+++ b/src/webextension/ephy-web-extension-manager.c
@@ -189,51 +189,9 @@ ephy_web_extension_manager_class_init (EphyWebExtensionManagerClass *klass)
                   G_TYPE_NONE, 0);
 }
 
-static void
-web_extension_cb (WebKitURISchemeRequest *request,
-                  gpointer                user_data)
-{
-  EphyWebExtensionManager *self = EPHY_WEB_EXTENSION_MANAGER (user_data);
-  EphyWebExtension *web_extension = NULL;
-  const char *path;
-  const unsigned char *data;
-  gsize length;
-  g_autoptr (GInputStream) stream = NULL;
-  g_auto (GStrv) split = NULL;
-
-  path = webkit_uri_scheme_request_get_uri (request) + strlen ("ephy-webextension://");
-
-  split = g_strsplit (path, "/", -1);
-  /* FIND WEB EXTENSION */
-  for (GList *list = self->web_extensions; list && list->data; list = list->next) {
-    EphyWebExtension *ext = EPHY_WEB_EXTENSION (list->data);
-
-    if (strcmp (ephy_web_extension_get_guid (ext), split[0]) == 0) {
-      web_extension = EPHY_WEB_EXTENSION (list->data);
-      break;
-    }
-  }
-
-  if (!web_extension)
-    return;
-
-  data = ephy_web_extension_get_resource (web_extension, path + strlen (split[0]) + 1, &length);
-  if (!data)
-    return;
-
-  stream = g_memory_input_stream_new_from_data (data, length, NULL);
-  webkit_uri_scheme_request_finish (request, stream, length, NULL);
-}
-
 static void
 ephy_web_extension_manager_init (EphyWebExtensionManager *self)
 {
-  WebKitWebContext *web_context;
-
-  web_context = ephy_embed_shell_get_web_context (ephy_embed_shell_get_default ());
-  webkit_web_context_register_uri_scheme (web_context, "ephy-webextension", web_extension_cb, self, NULL);
-  webkit_security_manager_register_uri_scheme_as_secure (webkit_web_context_get_security_manager 
(web_context),
-                                                         "ephy-webextension");
 }
 
 EphyWebExtensionManager *
@@ -398,12 +356,11 @@ page_action_clicked (GtkWidget      *event_box,
   json = json_to_string (root, FALSE);
 
   script = g_strdup_printf ("pageActionOnClicked(%s);", json);
-  webkit_web_view_run_javascript_in_world (web_view,
-                                           script,
-                                           ephy_embed_shell_get_guid (EPHY_EMBED_SHELL (shell)),
-                                           NULL,
-                                           NULL,
-                                           NULL);
+  webkit_web_view_run_javascript (web_view,
+                                  script,
+                                  NULL,
+                                  NULL,
+                                  NULL);
 
   return GDK_EVENT_STOP;
 }
@@ -484,7 +441,7 @@ ephy_web_extension_handle_background_script_message (WebKitUserContentManager *u
 
       ret = handler.execute (web_extension, split[1], args);
       script = g_strdup_printf ("promises[%.f].resolve(%s);", jsc_value_to_double (promise), ret ? ret : "");
-      webkit_web_view_run_javascript_in_world (web_view, script, ephy_embed_shell_get_guid 
(ephy_embed_shell_get_default ()), NULL, NULL, NULL);
+      webkit_web_view_run_javascript (web_view, script, NULL, NULL, NULL);
 
       return;
     }
@@ -505,7 +462,7 @@ add_content_scripts (EphyWebExtension *web_extension,
 
   ucm = webkit_web_view_get_user_content_manager (WEBKIT_WEB_VIEW (web_view));
   g_signal_connect_object (ucm, "script-message-received", G_CALLBACK 
(ephy_web_extension_handle_background_script_message), web_extension, 0);
-  webkit_user_content_manager_register_script_message_handler_in_world (ucm, "epiphany", 
ephy_embed_shell_get_guid (ephy_embed_shell_get_default ()));
+  webkit_user_content_manager_register_script_message_handler (ucm, "epiphany");
 
   for (GList *list = content_scripts; list && list->data; list = list->next) {
     GList *js_list = ephy_web_extension_get_content_script_js (web_extension, list->data);
@@ -618,31 +575,96 @@ page_attached_cb (HdyTabView *tab_view,
   ephy_web_extension_manager_update_location_entry (self, window);
 }
 
+static void
+web_extension_cb (WebKitURISchemeRequest *request,
+                  gpointer                user_data)
+{
+  EphyWebExtension *web_extension = EPHY_WEB_EXTENSION (user_data);
+  const char *path;
+  const unsigned char *data;
+  gsize length;
+  g_autoptr (GInputStream) stream = NULL;
+  g_autoptr (GError) error = NULL;
+
+  path = webkit_uri_scheme_request_get_path (request);
+
+  data = ephy_web_extension_get_resource (web_extension, path + 1, &length);
+  if (!data) {
+      error = g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED, "Resource not found: %s", path);
+      webkit_uri_scheme_request_finish_error (request, error);
+      return;
+  }
+
+  stream = g_memory_input_stream_new_from_data (data, length, NULL);
+  webkit_uri_scheme_request_finish (request, stream, length, NULL);
+}
+
+static void
+init_web_extension_api (WebKitWebContext *web_context,
+                        EphyWebExtension *web_extension)
+{
+  g_autoptr (GVariant) user_data = NULL;
+
+#if DEVELOPER_MODE
+  webkit_web_context_set_web_extensions_directory (web_context, BUILD_ROOT "/embed/web-process-extension");
+#else
+  webkit_web_context_set_web_extensions_directory (web_context, EPHY_WEB_PROCESS_EXTENSIONS_DIR);
+#endif
+
+  user_data = g_variant_new ("(smsbbb)",
+                             ephy_web_extension_get_guid (web_extension),
+                             ephy_profile_dir_is_default () ? NULL : ephy_profile_dir (),
+                             FALSE,
+                             FALSE,
+                             TRUE);
+  webkit_web_context_set_web_extensions_initialization_user_data (web_context, g_steal_pointer (&user_data));
+}
+
 static GtkWidget *
 create_web_extensions_webview (EphyWebExtension *web_extension)
 {
   g_autoptr (WebKitUserContentManager) ucm = NULL;
-  WebKitSettings *settings;
+  WebKitWebContext *web_context;
   GtkWidget *web_view;
 
   /* Create an own ucm so new scripts/css are only applied to this web_view */
   ucm = webkit_user_content_manager_new ();
-  web_view = ephy_web_view_new_with_user_content_manager (ucm);
   g_signal_connect_object (ucm, "script-message-received::epiphany", G_CALLBACK 
(ephy_web_extension_handle_background_script_message), web_extension, 0);
+  webkit_user_content_manager_register_script_message_handler (ucm, "epiphany");
 
-  /* Get webcontext and register web_extension scheme */
-  webkit_user_content_manager_register_script_message_handler_in_world (ucm,
-                                                                        "epiphany",
-                                                                        ephy_embed_shell_get_guid 
(ephy_embed_shell_get_default ()));
+  web_context = webkit_web_context_new ();
+  webkit_web_context_register_uri_scheme (web_context, "ephy-webextension", web_extension_cb, web_extension, 
NULL);
+  webkit_security_manager_register_uri_scheme_as_secure (webkit_web_context_get_security_manager 
(web_context),
+                                                         "ephy-webextension");
+
+  g_signal_connect_object (web_context, "initialize-web-extensions", G_CALLBACK (init_web_extension_api), 
web_extension, 0);
 
-  settings = webkit_web_view_get_settings (WEBKIT_WEB_VIEW (web_view));
-  webkit_settings_set_enable_write_console_messages_to_stdout (settings, TRUE);
+  web_view = g_object_new (EPHY_TYPE_WEB_VIEW,
+                           "web-context", web_context,
+                           "user-content-manager", ucm,
+                           "settings", ephy_embed_prefs_get_settings (),
+                           NULL);
 
   update_translations (web_extension);
 
   return web_view;
 }
 
+static char *
+create_base_uri_for_resource_path (EphyWebExtension *web_extension, const char *resource_path)
+{
+  g_autofree char *dir_name = NULL;
+
+  if (resource_path) {
+    dir_name = g_path_get_dirname (resource_path);
+
+    if (g_strcmp0 (dir_name, ".") != 0)
+      return g_strdup_printf ("ephy-webextension://%s/%s/", ephy_web_extension_get_guid (web_extension), 
dir_name);
+  }
+
+  return g_strdup_printf ("ephy-webextension://%s/", ephy_web_extension_get_guid (web_extension));
+}
+
 static GtkWidget *
 create_browser_popup (EphyWebExtension *web_extension)
 {
@@ -650,7 +672,6 @@ create_browser_popup (EphyWebExtension *web_extension)
   GtkWidget *popover;
   g_autofree char *data = NULL;
   g_autofree char *base_uri = NULL;
-  g_autofree char *dir_name = NULL;
   const char *popup;
 
   popover = gtk_popover_new (NULL);
@@ -658,8 +679,7 @@ create_browser_popup (EphyWebExtension *web_extension)
   web_view = create_web_extensions_webview (web_extension);
 
   popup = ephy_web_extension_get_browser_popup (web_extension);
-  dir_name = g_path_get_dirname (popup);
-  base_uri = g_strdup_printf ("ephy-webextension://%s/%s/", ephy_web_extension_get_guid (web_extension), 
dir_name);
+  base_uri = create_base_uri_for_resource_path (web_extension, popup);
   data = ephy_web_extension_get_resource_as_string (web_extension, popup);
   webkit_web_view_load_html (WEBKIT_WEB_VIEW (web_view), (char *)data, base_uri);
   gtk_container_add (GTK_CONTAINER (popover), web_view);
@@ -672,26 +692,18 @@ static gboolean
 on_browser_action_clicked (GtkWidget *event_box,
                            gpointer   user_data)
 {
-  EphyShell *shell = ephy_shell_get_default ();
   EphyWebExtension *web_extension = EPHY_WEB_EXTENSION (user_data);
   EphyWebExtensionManager *self = ephy_shell_get_web_extension_manager (ephy_shell_get_default ());
   g_autofree char *script = NULL;
-  WebKitWebView *web_view = NULL;
-  gboolean own_web_view = !!ephy_web_extension_background_web_view_get_page (web_extension);
-
-  if (!own_web_view)
-    web_view = WEBKIT_WEB_VIEW (ephy_web_extension_manager_get_background_web_view (self, web_extension));
-  else
-    web_view = WEBKIT_WEB_VIEW (ephy_shell_get_active_web_view (shell));
+  WebKitWebView *web_view = WEBKIT_WEB_VIEW (ephy_web_extension_manager_get_background_web_view (self, 
web_extension));
 
   script = g_strdup_printf ("browserActionClicked();");
 
-  webkit_web_view_run_javascript_in_world (web_view,
-                                           script,
-                                           ephy_embed_shell_get_guid (ephy_embed_shell_get_default ()),
-                                           NULL,
-                                           NULL,
-                                           NULL);
+  webkit_web_view_run_javascript (web_view,
+                                  script,
+                                  NULL,
+                                  NULL,
+                                  NULL);
 
   return GDK_EVENT_STOP;
 }
@@ -853,17 +865,17 @@ run_background_script (EphyWebExtensionManager *self,
   background = create_web_extensions_webview (web_extension);
   ephy_web_extension_manager_set_background_web_view (self, web_extension, EPHY_WEB_VIEW (background));
 
+  base_uri = create_base_uri_for_resource_path (web_extension, page);
+
   if (page) {
     g_autofree char *data = ephy_web_extension_get_resource_as_string (web_extension, page);
-
-    base_uri = g_strdup_printf ("ephy-webextension://%s/%s/", ephy_web_extension_get_guid (web_extension), 
g_path_get_dirname (page));
-    webkit_web_view_load_html (WEBKIT_WEB_VIEW (background), (char *)data, base_uri);
+    if (data)
+      webkit_web_view_load_html (WEBKIT_WEB_VIEW (background), (char *)data, base_uri);
   } else {
     GPtrArray *scripts = ephy_web_extension_background_web_view_get_scripts (web_extension);
 
     ucm = webkit_web_view_get_user_content_manager (WEBKIT_WEB_VIEW (background));
 
-    base_uri = g_strdup_printf ("ephy-webextension://%s/", ephy_web_extension_get_guid (web_extension));
     for (unsigned int i = 0; i < scripts->len; i++) {
       const char *script_file = g_ptr_array_index (scripts, i);
       g_autofree char *data = NULL;
@@ -873,14 +885,15 @@ run_background_script (EphyWebExtensionManager *self,
         continue;
 
       data = ephy_web_extension_get_resource_as_string (web_extension, script_file);
-      user_script = webkit_user_script_new_for_world (data,
-                                                      WEBKIT_USER_CONTENT_INJECT_TOP_FRAME,
-                                                      WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_END,
-                                                      ephy_embed_shell_get_guid 
(ephy_embed_shell_get_default ()),
-                                                      NULL,
-                                                      NULL);
-
-      webkit_user_content_manager_add_script (ucm, user_script);
+      if (data) {
+        user_script = webkit_user_script_new (data,
+                                              WEBKIT_USER_CONTENT_INJECT_TOP_FRAME,
+                                              WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_END,
+                                              NULL,
+                                              NULL);
+
+        webkit_user_content_manager_add_script (ucm, user_script);
+      }
     }
     webkit_web_view_load_html (WEBKIT_WEB_VIEW (background), "<body></body>", base_uri);
   }


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