[epiphany/pgriffis/web-extension/load-thread] WebExtensions: Add support for web_accessible_resources
- From: Patrick Griffis <pgriffis src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [epiphany/pgriffis/web-extension/load-thread] WebExtensions: Add support for web_accessible_resources
- Date: Sat, 25 Jun 2022 23:48:15 +0000 (UTC)
commit f905b6ae7f77b1b0e3d2b7ed6cd70ee94388b96b
Author: Patrick Griffis <pgriffis igalia com>
Date: Sat Jun 25 18:43:04 2022 -0500
WebExtensions: Add support for web_accessible_resources
This filters requests not originating from the extension itself.
Closes #1790
src/webextension/ephy-web-extension-manager.c | 125 +++++++++++---------------
src/webextension/ephy-web-extension.c | 44 +++++++++
src/webextension/ephy-web-extension.h | 4 +
3 files changed, 101 insertions(+), 72 deletions(-)
---
diff --git a/src/webextension/ephy-web-extension-manager.c b/src/webextension/ephy-web-extension-manager.c
index d01ec151c..8d572a091 100644
--- a/src/webextension/ephy-web-extension-manager.c
+++ b/src/webextension/ephy-web-extension-manager.c
@@ -120,6 +120,19 @@ ephy_web_extension_manager_remove_from_list (EphyWebExtensionManager *self,
g_signal_emit (self, signals[CHANGED], 0);
}
+static EphyWebExtension *
+ephy_web_extension_manager_get_extension_by_guid (EphyWebExtensionManager *self,
+ const char *guid)
+{
+ for (guint i = 0; i < self->web_extensions->len; i++) {
+ EphyWebExtension *web_extension = g_ptr_array_index (self->web_extensions, i);
+ if (strcmp (guid, ephy_web_extension_get_guid (web_extension)) == 0)
+ return web_extension;
+ }
+
+ return NULL;
+}
+
static void
on_web_extension_loaded (GObject *source_object,
GAsyncResult *result,
@@ -189,49 +202,59 @@ ephy_web_extension_manager_scan_directory_async (EphyWebExtensionManager *self,
}
static void
-main_context_web_extension_scheme_cb (WebKitURISchemeRequest *request,
- gpointer user_data)
+destroy_widget_list (GSList *widget_list)
{
- EphyWebExtensionManager *self = EPHY_WEB_EXTENSION_MANAGER (user_data);
- EphyWebExtension *web_extension = NULL;
- const char *path;
+ g_slist_free_full (widget_list, (GDestroyNotify)gtk_widget_destroy);
+}
+
+static void
+ephy_webextension_scheme_cb (WebKitURISchemeRequest *request,
+ gpointer user_data)
+{
+ EphyWebExtensionManager *self = ephy_web_extension_manager_get_default ();
+ EphyWebExtension *web_extension = user_data;
+ EphyWebExtension *target_web_extension;
+ g_autoptr (GInputStream) stream = NULL;
+ g_autoptr (GUri) uri = NULL;
+ g_autoptr (GError) error = NULL;
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);
- for (guint i = 0; i < self->web_extensions->len; i++) {
- EphyWebExtension *ext = g_ptr_array_index (self->web_extensions, i);
-
- if (strcmp (ephy_web_extension_get_guid (ext), split[0]) == 0) {
- web_extension = ext;
- break;
- }
+ uri = g_uri_parse (webkit_uri_scheme_request_get_uri (request),
+ G_URI_FLAGS_ENCODED_PATH | G_URI_FLAGS_SCHEME_NORMALIZE,
+ &error);
+ if (!uri) {
+ webkit_uri_scheme_request_finish_error (request, g_steal_pointer (&error));
+ return;
}
- if (!web_extension)
+ target_web_extension = ephy_web_extension_manager_get_extension_by_guid (self, g_uri_get_host (uri));
+ if (!target_web_extension) {
+ error = g_error_new (WEB_EXTENSION_ERROR, WEB_EXTENSION_ERROR_INVALID_HOST, "Could not find extension
%s", g_uri_get_host (uri));
+ webkit_uri_scheme_request_finish_error (request, g_steal_pointer (&error));
return;
+ }
- /* FIXME: This needs to be filtered by the extension manifest's "web_accessible_resources"
- * property which involves some pattern matching. */
+ /* If this is not originating from the same WebExtension view we must find it and filter it by
web_accessible_resources. */
+ if (!web_extension || web_extension != target_web_extension) {
+ if (!ephy_web_extension_has_web_accessible_resource (target_web_extension, g_uri_get_path (uri) + 1)) {
+ error = g_error_new (G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED, "'%s' is not a
web_accessible_resource", g_uri_get_path (uri));
+ webkit_uri_scheme_request_finish_error (request, g_steal_pointer (&error));
+ return;
+ }
+ }
- data = ephy_web_extension_get_resource (web_extension, path + strlen (split[0]) + 1, &length);
- if (!data)
+ data = ephy_web_extension_get_resource (target_web_extension, g_uri_get_path (uri) + 1, &length);
+ if (!data) {
+ error = g_error_new (G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "'%s' was not found", g_uri_get_path (uri));
+ webkit_uri_scheme_request_finish_error (request, g_steal_pointer (&error));
return;
+ }
stream = g_memory_input_stream_new_from_data (data, length, NULL);
webkit_uri_scheme_request_finish (request, stream, length, NULL);
}
-static void
-destroy_widget_list (GSList *widget_list)
-{
- g_slist_free_full (widget_list, (GDestroyNotify)gtk_widget_destroy);
-}
-
static void
ephy_web_extension_manager_constructed (GObject *object)
{
@@ -286,7 +309,7 @@ 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",
main_context_web_extension_scheme_cb, self, NULL);
+ webkit_web_context_register_uri_scheme (web_context, "ephy-webextension", ephy_webextension_scheme_cb,
NULL, NULL);
webkit_security_manager_register_uri_scheme_as_secure (webkit_web_context_get_security_manager
(web_context),
"ephy-webextension");
@@ -798,35 +821,6 @@ 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;
-
- /* FIXME: For paths on different hosts we should support web_accessible_resources. */
- path = webkit_uri_scheme_request_get_path (request);
-
- /* FIXME: This may be the place to handle predefined messages and localized CSS:
- *
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Internationalization#predefined_messages
- */
-
- 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)
@@ -918,7 +912,7 @@ ephy_web_extensions_manager_create_web_extensions_webview (EphyWebExtension *web
web_context = webkit_web_context_new ();
- webkit_web_context_register_uri_scheme (web_context, "ephy-webextension", web_extension_cb, web_extension,
NULL);
+ webkit_web_context_register_uri_scheme (web_context, "ephy-webextension", ephy_webextension_scheme_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);
@@ -1332,19 +1326,6 @@ ephy_web_extension_manager_get_page_action (EphyWebExtensionManager *self,
return ret;
}
-static EphyWebExtension *
-ephy_web_extension_manager_get_extension_by_guid (EphyWebExtensionManager *self,
- const char *guid)
-{
- for (guint i = 0; i < self->web_extensions->len; i++) {
- EphyWebExtension *web_extension = g_ptr_array_index (self->web_extensions, i);
- if (strcmp (guid, ephy_web_extension_get_guid (web_extension)) == 0)
- return web_extension;
- }
-
- return NULL;
-}
-
void
ephy_web_extension_manager_handle_notifications_action (EphyWebExtensionManager *self,
GVariant *params)
diff --git a/src/webextension/ephy-web-extension.c b/src/webextension/ephy-web-extension.c
index 0b65f0cac..bdba26505 100644
--- a/src/webextension/ephy-web-extension.c
+++ b/src/webextension/ephy-web-extension.c
@@ -107,6 +107,7 @@ struct _EphyWebExtension {
GCancellable *cancellable;
char *local_storage_path;
JsonNode *local_storage;
+ GHashTable *web_accessible_resources;
};
G_DEFINE_QUARK (web - extension - error - quark, web_extension_error)
@@ -752,6 +753,24 @@ web_extension_add_permission (JsonArray *array,
g_hash_table_add (self->permissions, g_strdup (permission));
}
+static void
+web_extension_add_web_accessible_resource (JsonArray *array,
+ guint index_,
+ JsonNode *element_node,
+ gpointer user_data)
+{
+ EphyWebExtension *self = EPHY_WEB_EXTENSION (user_data);
+ const char *web_accessible_resource = json_node_get_string (element_node);
+
+ if (!web_accessible_resource)
+ return;
+
+ if (!self->web_accessible_resources)
+ self->web_accessible_resources = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+ g_hash_table_add (self->web_accessible_resources, g_strdup (web_accessible_resource));
+}
+
static void
ephy_web_extension_dispose (GObject *object)
{
@@ -775,6 +794,7 @@ ephy_web_extension_dispose (GObject *object)
g_clear_pointer (&self->permissions, g_hash_table_unref);
g_clear_pointer (&self->host_permissions, g_ptr_array_unref);
g_clear_pointer (&self->local_storage, json_node_unref);
+ g_clear_pointer (&self->web_accessible_resources, g_hash_table_unref);
g_clear_pointer (&self->page_action, web_extension_page_action_free);
g_clear_pointer (&self->browser_action, web_extension_browser_action_free);
@@ -911,6 +931,20 @@ ephy_web_extension_parse_manifest (EphyWebExtension *self,
json_array_foreach_element (array, web_extension_add_permission, self);
}
+ if (json_object_has_member (root_object, "web_accessible_resources")) {
+ JsonNode *node;
+ JsonArray *array;
+
+ node = json_object_get_member (root_object, "web_accessible_resources");
+ if (!JSON_NODE_HOLDS_ARRAY (node)) {
+ g_set_error (error, WEB_EXTENSION_ERROR, WEB_EXTENSION_ERROR_INVALID_MANIFEST,
"web_accessible_resources is not an array");
+ return FALSE;
+ }
+
+ array = json_node_get_array (node);
+ json_array_foreach_element (array, web_extension_add_web_accessible_resource, self);
+ }
+
return TRUE;
}
@@ -1576,3 +1610,13 @@ ephy_web_extension_create_sender_object (EphyWebExtension *self,
return json_to_string (node, FALSE);
}
+
+gboolean
+ephy_web_extension_has_web_accessible_resource (EphyWebExtension *self,
+ const char *path)
+{
+ if (!self->web_accessible_resources)
+ return FALSE;
+
+ return g_hash_table_contains (self->web_accessible_resources, path);
+}
\ No newline at end of file
diff --git a/src/webextension/ephy-web-extension.h b/src/webextension/ephy-web-extension.h
index 008217c90..a0601e804 100644
--- a/src/webextension/ephy-web-extension.h
+++ b/src/webextension/ephy-web-extension.h
@@ -57,6 +57,7 @@ typedef enum {
WEB_EXTENSION_ERROR_NOT_IMPLEMENTED = 1003,
WEB_EXTENSION_ERROR_INVALID_MANIFEST = 1004,
WEB_EXTENSION_ERROR_INVALID_XPI = 1005,
+ WEB_EXTENSION_ERROR_INVALID_HOST = 1006,
} WebExtensionErrorCode;
typedef struct {
@@ -168,5 +169,8 @@ void ephy_web_extension_clear_local_storage (EphyW
char *ephy_web_extension_create_sender_object (EphyWebExtension *self,
WebKitWebView *web_view);
+gboolean ephy_web_extension_has_web_accessible_resource (EphyWebExtension *self,
+ const char *path);
+
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]