[epiphany/pgriffis/web-extension/commands: 2/5] WebExtensions: Provide Commands APIs




commit f543c8652a5b8a035a219c5009c058e28a6cf9b4
Author: Jamie Murphy <hello itsjamie dev>
Date:   Mon Jul 4 11:36:28 2022 -0700

    WebExtensions: Provide Commands APIs

 src/webextension/api/commands.c               | 212 +++++++++++++++++++++++++-
 src/webextension/ephy-web-extension-manager.c |   2 -
 src/webextension/ephy-web-extension.c         |  22 +++
 src/webextension/ephy-web-extension.h         |   6 +
 4 files changed, 238 insertions(+), 4 deletions(-)
---
diff --git a/src/webextension/api/commands.c b/src/webextension/api/commands.c
index b8e2c87cc..a9b329d04 100644
--- a/src/webextension/api/commands.c
+++ b/src/webextension/api/commands.c
@@ -19,9 +19,143 @@
 
 #include "config.h"
 
+#include "ephy-shell.h"
+
 #include "api-utils.h"
 #include "commands.h"
 
+/* Local command struct. */
+typedef struct {
+  EphyWebExtension *web_extension; /* Parent object */
+  char *name;
+  char *accelerator;
+  char *description;
+} Command;
+
+static void
+command_destroy (Command *cmd)
+{
+  //g_clear_pointer (&cmd->name);
+  g_free (cmd);
+}
+
+static void
+on_command_activated (GAction  *action,
+                      GVariant *parameter,
+                      gpointer  user_data)
+{
+  EphyWebExtensionManager *manager = ephy_web_extension_manager_get_default ();
+  Command *cmd = user_data;
+  JsonNode *node;
+  node = json_node_init_string (json_node_alloc (), cmd->name);
+
+  ephy_web_extension_manager_emit_in_extension_views (manager,
+                                                      cmd->web_extension,
+                                                      "commands.onCommand",
+                                                      json_to_string (node, FALSE));
+}
+
+static void
+setup_actions (Command *cmd)
+{
+  GSimpleAction *action = g_simple_action_new (cmd->name, NULL);
+  g_signal_connect (action, "activate", G_CALLBACK (on_command_activated), cmd);
+  g_action_map_add_action (G_ACTION_MAP (ephy_shell_get_default ()), (GAction *) action);
+  gtk_application_set_accels_for_action (GTK_APPLICATION (ephy_shell_get_default ()),
+                                         g_strdup_printf ("app.%s", cmd->name),
+                                         (const char *[]) {
+                                           cmd->accelerator,
+                                           NULL,
+                                         });
+}
+
+static Command *
+create_command (EphyWebExtension *self,
+                guint cmd)
+{
+  char * shortcut;
+  char * suggested_key;
+  char * description;
+  Command *command = g_new0 (Command, 1);
+
+  ephy_web_extension_get_command_data_from_index (self,
+                                                  cmd,
+                                                  &shortcut,
+                                                  &suggested_key,
+                                                  &description);
+
+  command->web_extension = self;
+  command->name = g_strdup(shortcut);
+  command->accelerator = g_strdup(suggested_key);
+  command->description = g_strdup(description);
+
+  setup_actions (command);
+
+  return command;
+}
+
+static GHashTable *
+get_commands (EphyWebExtension *self)
+{
+  GList *commands = ephy_web_extension_get_commands (self);
+  Command *cmd = NULL;
+
+  GHashTable *cmds = g_object_get_data (G_OBJECT (self), "commands");
+  if (cmds)
+      return cmds;
+
+  cmds = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify)command_destroy);
+  g_object_set_data_full (G_OBJECT (self), "commands", cmds, (GDestroyNotify)g_hash_table_destroy);
+
+  for (GList *list = commands; list && list->data; list = list->next) {
+    cmd = create_command (self, g_list_index (list, list->data));
+
+    g_hash_table_replace (cmds, cmd->name, cmd);
+  }
+  return cmds;
+}
+
+static JsonNode *
+command_to_node (Command *cmd)
+{
+  JsonNode *node;
+  JsonObject *obj;
+
+  if (!cmd)
+    return NULL;
+
+  node = json_node_init_object (json_node_alloc (), json_object_new ());
+  obj = json_node_get_object (node);
+  json_object_set_string_member (obj, "name", cmd->name);
+  json_object_set_string_member (obj, "shortcut", cmd->accelerator);
+  json_object_set_string_member (obj, "description", cmd->description);
+
+  return node;
+}
+
+char *
+create_accelerator (char *orig_string)
+{
+  char ** accelerator_keys = NULL;
+  char * accelerator = "";
+
+  if (strchr(orig_string, '<') != NULL || strchr (orig_string, '>') != NULL)
+    return orig_string;
+
+  accelerator_keys = g_strsplit((const gchar *) orig_string, "+", 0);
+
+  for (int i = 0; accelerator_keys[i]; i++) {
+    // We have to use 2 here, as F# keys are treated like normal keys.
+    if (strlen (accelerator_keys[i]) > 3) {
+      accelerator = g_strdup_printf ("%s<%s>", accelerator, accelerator_keys[i]);
+    } else {
+      accelerator = g_strdup_printf ("%s%s", accelerator, accelerator_keys[i]);
+    }
+  }
+
+  return accelerator;
+}
+
 static char *
 commands_handler_get_all (EphyWebExtension *self,
                           char             *name,
@@ -29,7 +163,17 @@ commands_handler_get_all (EphyWebExtension *self,
                           WebKitWebView    *web_view,
                           GError          **error)
 {
-  return NULL;
+  GHashTable *commands = get_commands (self);
+  g_autoptr (JsonNode) node = json_node_init_array (json_node_alloc (), json_array_new ());
+  JsonArray *rel = json_node_get_array (node);
+  GHashTableIter iter;
+  Command *cmd;
+
+  g_hash_table_iter_init (&iter, commands);
+  while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&cmd))
+    json_array_add_element (rel, command_to_node (cmd));
+
+  return json_to_string (node, FALSE);
 }
 
 static char *
@@ -39,6 +183,32 @@ commands_handler_reset (EphyWebExtension *self,
                         WebKitWebView    *web_view,
                         GError          **error)
 {
+  GHashTable *commands = get_commands (self);
+  g_autoptr (JSCValue) name_value = jsc_value_object_get_property_at_index (args, 0);
+  g_autofree char *name_str = NULL;
+  Command *cmd = NULL;
+  char * shortcut;
+  char * suggested_key;
+  char * description;
+
+  if (!jsc_value_is_string (name_value))
+    name_str = g_strdup ("");
+  else
+    name_str = jsc_value_to_string (name_value);
+
+  if (g_hash_table_lookup (commands, name_str)) {
+    cmd = g_hash_table_lookup (commands, name_str);
+    ephy_web_extension_get_command_data_from_name (self,
+                                                   name_str,
+                                                   &shortcut,
+                                                   &suggested_key,
+                                                   &description);
+
+    cmd->name = g_strdup(shortcut);
+    cmd->accelerator = g_strdup(suggested_key);
+    cmd->description = g_strdup(description);
+  }
+
   return NULL;
 }
 
@@ -49,6 +219,44 @@ commands_handler_update (EphyWebExtension *self,
                          WebKitWebView    *web_view,
                          GError          **error)
 {
+  GHashTable *commands = get_commands (self);
+  g_autoptr (JSCValue) obj = jsc_value_object_get_property_at_index (args, 0);
+  Command *cmd = NULL;
+  g_autofree char *name_str = NULL;
+  g_autofree char *desc_str = NULL;
+  g_autofree char *shortcut_str = NULL;
+
+  if (!jsc_value_is_object (obj))
+    return NULL;
+  else {
+    if (!jsc_value_object_has_property (obj, "name"))
+      return NULL;
+    else
+      name_str = jsc_value_to_string (jsc_value_object_get_property (obj, "name"));
+
+    if (jsc_value_object_has_property (obj, "description"))
+      desc_str = jsc_value_to_string (jsc_value_object_get_property (obj, "description"));
+
+    if (jsc_value_object_has_property (obj, "shortcut")) {
+      shortcut_str = jsc_value_to_string (jsc_value_object_get_property (obj, "shortcut"));
+      shortcut_str = create_accelerator (shortcut_str);
+    }
+  }
+
+  if (g_hash_table_lookup (commands, name_str)) {
+    cmd = g_hash_table_lookup (commands, name_str);
+    cmd->name = g_strdup(name_str);
+    cmd->accelerator = g_strdup(shortcut_str);
+    cmd->description = g_strdup(desc_str);
+  }
+
+  gtk_application_set_accels_for_action (GTK_APPLICATION (ephy_shell_get_default ()),
+                                         g_strdup_printf ("app.%s", cmd->name),
+                                         (const char *[]) {
+                                           cmd->accelerator,
+                                           NULL,
+                                         });
+
   return NULL;
 }
 
@@ -86,4 +294,4 @@ ephy_web_extension_api_commands_handler (EphyWebExtension *self,
   g_warning ("%s(): '%s' not implemented by Epiphany!", __FUNCTION__, name);
   error = g_error_new_literal (WEB_EXTENSION_ERROR, WEB_EXTENSION_ERROR_NOT_IMPLEMENTED, "Not Implemented");
   g_task_return_error (task, g_steal_pointer (&error));
-}
\ No newline at end of file
+}
diff --git a/src/webextension/ephy-web-extension-manager.c b/src/webextension/ephy-web-extension-manager.c
index ef26374d1..40ded52c9 100644
--- a/src/webextension/ephy-web-extension-manager.c
+++ b/src/webextension/ephy-web-extension-manager.c
@@ -671,8 +671,6 @@ extension_view_handle_user_message (WebKitWebView     *web_view,
   for (guint idx = 0; idx < G_N_ELEMENTS (api_handlers); idx++) {
     EphyWebExtensionApiHandler handler = api_handlers[idx];
 
-    g_warning ("%s, %s", handler.name, split[0]);
-
     if (g_strcmp0 (handler.name, split[0]) == 0) {
       /* TODO: Cancellable */
       GTask *task = g_task_new (web_extension, NULL, 
(GAsyncReadyCallback)on_web_extension_api_handler_finish, NULL);
diff --git a/src/webextension/ephy-web-extension.c b/src/webextension/ephy-web-extension.c
index ca1ae90b6..66210a8b6 100644
--- a/src/webextension/ephy-web-extension.c
+++ b/src/webextension/ephy-web-extension.c
@@ -848,6 +848,28 @@ ephy_web_extension_get_command_data_from_index (EphyWebExtension    *self,
   return NULL;
 }
 
+void *
+ephy_web_extension_get_command_data_from_name (EphyWebExtension    *self,
+                                               const char          *name,
+                                               char**               shortcut,
+                                               char**               suggested_key,
+                                               char**               description)
+{
+  WebExtensionCommand *cmd = NULL;
+
+  for (GList *list = self->commands; list && list->data; list = list->next) {
+    cmd = list->data;
+
+    if (strcmp (cmd->shortcut, name) == 0) {
+      *shortcut =  strdup(cmd->shortcut);
+      *suggested_key = strdup(cmd->suggested_key);
+      *description = strdup(cmd->description);
+    }
+  }
+
+  return NULL;
+}
+
 GList *
 ephy_web_extension_get_commands (EphyWebExtension *self)
 {
diff --git a/src/webextension/ephy-web-extension.h b/src/webextension/ephy-web-extension.h
index 5d34a0226..7b280fa8b 100644
--- a/src/webextension/ephy-web-extension.h
+++ b/src/webextension/ephy-web-extension.h
@@ -156,6 +156,12 @@ void                  *ephy_web_extension_get_command_data_from_index     (EphyW
                                                                            char               
**suggested_key,
                                                                            char               **description);
 
+void                  *ephy_web_extension_get_command_data_from_name      (EphyWebExtension    *self,
+                                                                           const char          *name,
+                                                                           char               **shortcut,
+                                                                           char               
**suggested_key,
+                                                                           char               **description);
+
 gboolean               ephy_web_extension_has_tab_or_host_permission      (EphyWebExtension *self,
                                                                            EphyWebView      *web_view,
                                                                            gboolean          
is_user_interaction);


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