[epiphany/wip/security-origins] Set initial notification permissions



commit 573c4bc8dff9a1614524f74c0bc60d87bef74560
Author: Michael Catanzaro <mcatanzaro gnome org>
Date:   Fri Dec 30 18:21:42 2016 -0600

    Set initial notification permissions
    
    https://bugs.webkit.org/show_bug.cgi?id=163366

 embed/ephy-embed-shell.c       |   25 +++++++-
 lib/ephy-permissions-manager.c |  142 ++++++++++++++++++++++++++++++++++++++-
 lib/ephy-permissions-manager.h |    6 ++
 3 files changed, 167 insertions(+), 6 deletions(-)
---
diff --git a/embed/ephy-embed-shell.c b/embed/ephy-embed-shell.c
index 0c4f03b..1156612 100644
--- a/embed/ephy-embed-shell.c
+++ b/embed/ephy-embed-shell.c
@@ -889,6 +889,24 @@ initialize_web_extensions (WebKitWebContext *web_context,
 }
 
 static void
+set_initial_notification_permissions (WebKitWebContext *web_context,
+                                      EphyEmbedShell   *shell)
+{
+  EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
+  GList *permitted_origins;
+  GList *denied_origins;
+
+  permitted_origins = ephy_permissions_manager_get_permitted_origins (priv->permissions_manager,
+                                                                      
EPHY_PERMISSION_TYPE_SHOW_NOTIFICATIONS);
+  denied_origins = ephy_permissions_manager_get_denied_origins (priv->permissions_manager,
+                                                                EPHY_PERMISSION_TYPE_SHOW_NOTIFICATIONS);
+  webkit_web_context_set_initial_notification_permissions (web_context, permitted_origins, denied_origins);
+
+  g_list_free_full (permitted_origins, (GDestroyNotify)webkit_security_origin_unref);
+  g_list_free_full (denied_origins, (GDestroyNotify)webkit_security_origin_unref);
+}
+
+static void
 web_extension_page_created (EphyWebExtensionProxy *extension,
                             guint64                page_id,
                             EphyEmbedShell        *shell)
@@ -1076,6 +1094,11 @@ ephy_embed_shell_startup (GApplication *application)
                     G_CALLBACK (initialize_web_extensions),
                     shell);
 
+  priv->permissions_manager = ephy_permissions_manager_new ();
+  g_signal_connect (priv->web_context, "set-initial-notification-permissions",
+                    G_CALLBACK (set_initial_notification_permissions),
+                    shell);
+
   /* Favicon Database */
   favicon_db_path = g_build_filename (EPHY_EMBED_SHELL_MODE_HAS_PRIVATE_PROFILE (priv->mode) ?
                                       ephy_dot_dir () : g_get_user_cache_dir (),
@@ -1587,7 +1610,5 @@ ephy_embed_shell_get_permissions_manager (EphyEmbedShell *shell)
 {
   EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
 
-  if (!priv->permissions_manager)
-    priv->permissions_manager = ephy_permissions_manager_new ();
   return priv->permissions_manager;
 }
diff --git a/lib/ephy-permissions-manager.c b/lib/ephy-permissions-manager.c
index 1f62fe0..ce691b3 100644
--- a/lib/ephy-permissions-manager.c
+++ b/lib/ephy-permissions-manager.c
@@ -27,6 +27,7 @@
 
 #define G_SETTINGS_ENABLE_BACKEND 1
 #include <gio/gsettingsbackend.h>
+#include <stdlib.h>
 #include <string.h>
 #include <webkit2/webkit2.h>
 
@@ -40,6 +41,8 @@ struct _EphyPermissionsManager
 
 G_DEFINE_TYPE (EphyPermissionsManager, ephy_permissions_manager, G_TYPE_OBJECT)
 
+#define PERMISSIONS_FILENAME "permissions.ini"
+
 static void
 ephy_permissions_manager_init (EphyPermissionsManager *manager)
 {
@@ -70,9 +73,9 @@ static GSettings *
 ephy_permissions_manager_get_settings_for_origin (EphyPermissionsManager *manager,
                                                   const char             *origin)
 {
-  char *key_file;
   char *origin_path;
   char *trimmed_protocol;
+  char *filename;
   GSettingsBackend* backend;
   GSettings *settings;
   WebKitSecurityOrigin *security_origin;
@@ -84,9 +87,9 @@ ephy_permissions_manager_get_settings_for_origin (EphyPermissionsManager *manage
   if (settings)
     return settings;
 
-  key_file = g_build_filename (ephy_dot_dir (), "permissions.ini", NULL);
-  backend = g_keyfile_settings_backend_new (key_file, "/", NULL);
-  g_free (key_file);
+  filename = g_build_filename (ephy_dot_dir (), PERMISSIONS_FILENAME, NULL);
+  backend = g_keyfile_settings_backend_new (filename, "/", NULL);
+  g_free (filename);
 
   /* Cannot contain consecutive slashes in GSettings path... */
   security_origin = webkit_security_origin_new_from_string (origin);
@@ -156,3 +159,134 @@ ephy_permissions_manager_set_permission (EphyPermissionsManager *manager,
   GSettings *settings = ephy_permissions_manager_get_settings_for_origin (manager, origin);
   g_settings_set_enum (settings, permission_type_to_string (type), permission);
 }
+
+static WebKitSecurityOrigin *
+group_name_to_security_origin (const char *group)
+{
+  char **tokens;
+  WebKitSecurityOrigin *origin = NULL;
+
+  /* Should be of form org/gnome/epiphany/permissions/http/example.com/0 */
+  tokens = g_strsplit (group, "/", -1);
+  if (g_strv_length (tokens) == 7 && tokens[4] != NULL && tokens[5] != NULL && tokens[6] != NULL)
+    origin = webkit_security_origin_new (tokens[4], tokens[5], atoi (tokens[6]));
+
+  g_strfreev (tokens);
+
+  return origin;
+}
+
+static WebKitSecurityOrigin *
+origin_for_keyfile_key (GKeyFile           *file,
+                        const char         *filename,
+                        const char         *group,
+                        const char         *key,
+                        EphyPermissionType  type,
+                        gboolean            permit)
+{
+  WebKitSecurityOrigin *origin = NULL;
+  char *value;
+  GError *error = NULL;
+
+  if (strcmp (permission_type_to_string (type), key) == 0) {
+    value = g_key_file_get_string (file, group, key, &error);
+    if (error != NULL) {
+      g_warning ("Error processing %s group %s key %s: %s",
+                 filename, group, key, error->message);
+      g_error_free (error);
+      return NULL;
+    }
+
+    if ((permit && strcmp (value, "'allow'") == 0) ||
+        (!permit && strcmp (value, "'deny'") == 0))
+      origin = group_name_to_security_origin (group);
+
+    g_free (value);
+  }
+
+  return origin;
+}
+
+static GList *
+origins_for_keyfile_group (GKeyFile           *file,
+                           const char         *filename,
+                           const char         *group,
+                           EphyPermissionType  type,
+                           gboolean            permit)
+{
+  char **keys;
+  gsize keys_length;
+  GList *origins = NULL;
+  WebKitSecurityOrigin *origin;
+  GError *error = NULL;
+
+  keys = g_key_file_get_keys (file, group, &keys_length, &error);
+  if (error != NULL) {
+    g_warning ("Error processing %s group %s: %s", filename, group, error->message);
+    g_error_free (error);
+    return NULL;
+  }
+
+  for (guint i = 0; i < keys_length; i++) {
+    origin = origin_for_keyfile_key (file, filename, group, keys[i], type, permit);
+    if (origin)
+      origins = g_list_prepend (origins, origin);
+  }
+
+  g_strfreev (keys);
+
+  return origins;
+}
+
+/* TODO: Consider caching this in memory. This gets called twice when
+ * starting each web process. It could be dozens or hundreds of file
+ * reads when starting the browser. It's silly to cache individual
+ * settings but not this. */
+static GList *
+ephy_permissions_manager_get_matching_origins (EphyPermissionsManager *manager,
+                                               EphyPermissionType      type,
+                                               gboolean                permit)
+{
+  GKeyFile *file;
+  char *filename;
+  char **groups;
+  gsize groups_length;
+  GList *origins = NULL;
+  GError *error = NULL;
+
+  file = g_key_file_new ();
+  filename = g_build_filename (ephy_dot_dir (), PERMISSIONS_FILENAME, NULL);
+
+  g_key_file_load_from_file (file, filename, G_KEY_FILE_NONE, &error);
+  if (error != NULL) {
+    if (!g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND))
+      g_warning ("Error processing %s: %s", filename, error->message);
+    g_error_free (error);
+    return NULL;
+  }
+
+  groups = g_key_file_get_groups (file, &groups_length);
+  for (guint i = 0; i < groups_length; i++)
+    origins = g_list_concat (origins,
+                             origins_for_keyfile_group (file, filename, groups[i], type, permit));
+
+  g_key_file_unref (file);
+  g_strfreev (groups);
+  g_free (filename);
+
+  return origins;
+}
+
+GList *
+ephy_permissions_manager_get_permitted_origins (EphyPermissionsManager *manager,
+                                                EphyPermissionType      type)
+{
+  return ephy_permissions_manager_get_matching_origins (manager, type, TRUE);
+}
+
+GList *
+ephy_permissions_manager_get_denied_origins (EphyPermissionsManager *manager,
+                                             EphyPermissionType      type)
+{
+  return ephy_permissions_manager_get_matching_origins (manager, type, FALSE);
+}
diff --git a/lib/ephy-permissions-manager.h b/lib/ephy-permissions-manager.h
index 1090a99..eeeb8b1 100644
--- a/lib/ephy-permissions-manager.h
+++ b/lib/ephy-permissions-manager.h
@@ -52,4 +52,10 @@ void                    ephy_permissions_manager_set_permission (EphyPermissions
                                                                  EphyPermissionType      type,
                                                                  const char             *origin,
                                                                  EphyPermission          permission);
+
+GList                  *ephy_permissions_manager_get_permitted_origins (EphyPermissionsManager *manager,
+                                                                        EphyPermissionType      type);
+GList                  *ephy_permissions_manager_get_denied_origins    (EphyPermissionsManager *manager,
+                                                                        EphyPermissionType      type);
+
 G_END_DECLS


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