[epiphany/wip/security-origins: 6/8] permissions-manager: operate on security origins, not hosts



commit 946a6005e084d674a2ef38c6dd1598eb6e591d41
Author: Michael Catanzaro <mcatanzaro gnome org>
Date:   Thu Dec 29 16:34:43 2016 -0600

    permissions-manager: operate on security origins, not hosts

 data/Makefile.am                                   |    2 +-
 ... => org.gnome.epiphany.permissions.gschema.xml} |   14 ++--
 embed/ephy-web-view.c                              |   30 +++++---
 embed/web-extension/ephy-web-extension.c           |   14 +++-
 lib/ephy-permissions-manager.c                     |   78 ++++++++++++--------
 lib/ephy-permissions-manager.h                     |   18 ++--
 src/profile-migrator/ephy-profile-migrator.c       |   15 ++++
 7 files changed, 106 insertions(+), 65 deletions(-)
---
diff --git a/data/Makefile.am b/data/Makefile.am
index d6aa63e..77c4753 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -10,7 +10,7 @@ $(desktop_DATA): $(desktop_in_files)
 gsettings_ENUM_NAMESPACE = org.gnome.Epiphany
 gsettings_ENUM_FILES = $(top_srcdir)/lib/ephy-prefs.h
 
-gsettings_SCHEMAS = org.gnome.epiphany.gschema.xml org.gnome.epiphany.host.gschema.xml
+gsettings_SCHEMAS = org.gnome.epiphany.gschema.xml org.gnome.epiphany.permissions.gschema.xml
 @GSETTINGS_RULES@
 
 appstream_in_files = org.gnome.Epiphany.appdata.xml.in
diff --git a/data/org.gnome.epiphany.host.gschema.xml b/data/org.gnome.epiphany.permissions.gschema.xml
similarity index 91%
rename from data/org.gnome.epiphany.host.gschema.xml
rename to data/org.gnome.epiphany.permissions.gschema.xml
index 2d5a153..22bbdd2 100644
--- a/data/org.gnome.epiphany.host.gschema.xml
+++ b/data/org.gnome.epiphany.permissions.gschema.xml
@@ -1,32 +1,32 @@
 <schemalist>
-  <enum id="org.gnome.Epiphany.host.permissions">
+  <enum id="org.gnome.Epiphany.Permissions.Permission">
     <value nick="undecided" value="-1"/>
     <value nick="deny" value="0"/>
     <value nick="allow" value="1"/>
   </enum>
 
-  <schema id="org.gnome.Epiphany.host" gettext-domain="">
-    <key name="audio-device-permission" enum="org.gnome.Epiphany.host.permissions">
+  <schema id="org.gnome.Epiphany.Permissions" gettext-domain="">
+    <key name="audio-device-permission" enum="org.gnome.Epiphany.Permissions.Permission">
       <default>"undecided"</default>
       <summary>Decision to apply when microphone permission is requested for this host</summary>
       <description>This option is used to save whether a given host has been given permission to access the 
user’s microphone. The “undecided” default means the browser needs to ask the user for permission, while 
“allow” and “deny” tell it to automatically make the decision upon request.</description>
     </key>
-    <key name="geolocation-permission" enum="org.gnome.Epiphany.host.permissions">
+    <key name="geolocation-permission" enum="org.gnome.Epiphany.Permissions.Permission">
       <default>"undecided"</default>
       <summary>Decision to apply when geolocation permission is requested for this host</summary>
       <description>This option is used to save whether a given host has been given permission to access the 
user’s location. The “undecided” default means the browser needs to ask the user for permission, while 
“allow” and “deny” tell it to automatically make the decision upon request.</description>
     </key>
-    <key name="notifications-permission" enum="org.gnome.Epiphany.host.permissions">
+    <key name="notifications-permission" enum="org.gnome.Epiphany.Permissions.Permission">
       <default>"undecided"</default>
       <summary>Decision to apply when notification permission is requested for this host</summary>
       <description>This option is used to save whether a given host has been given permission to show 
notifications. The “undecided” default means the browser needs to ask the user for permission, while “allow” 
and “deny” tell it to automatically make the decision upon request.</description>
     </key>
-    <key name="save-password-permission" enum="org.gnome.Epiphany.host.permissions">
+    <key name="save-password-permission" enum="org.gnome.Epiphany.Permissions.Permission">
       <default>"undecided"</default>
       <summary>Decision to apply when save password permission is requested for this host</summary>
       <description>This option is used to save whether a given host has been given permission to save 
passwords. The “undecided” default means the browser needs to ask the user for permission, while “allow” and 
“deny” tell it to automatically make the decision upon request.</description>
     </key>
-    <key name="video-device-permission" enum="org.gnome.Epiphany.host.permissions">
+    <key name="video-device-permission" enum="org.gnome.Epiphany.Permissions.Permission">
       <default>"undecided"</default>
       <summary>Decision to apply when webcam permission is requested for this host</summary>
       <description>This option is used to save whether a given host has been given permission to access the 
user’s webcam. The “undecided” default means the browser needs to ask the user for permission, while “allow” 
and “deny” tell it to automatically make the decision upon request.</description>
diff --git a/embed/ephy-web-view.c b/embed/ephy-web-view.c
index bbe6492..f379d31 100644
--- a/embed/ephy-web-view.c
+++ b/embed/ephy-web-view.c
@@ -703,10 +703,10 @@ form_auth_data_save_confirmation_response (GtkInfoBar          *info_bar,
     EphyEmbedShell *shell = ephy_embed_shell_get_default ();
     EphyPermissionsManager *manager = ephy_embed_shell_get_permissions_manager (shell);
 
-    ephy_permissions_manager_set_permission_for_address (manager,
-                                                         EPHY_PERMISSION_TYPE_SAVE_PASSWORD,
-                                                         data->origin,
-                                                         EPHY_PERMISSION_DENY);
+    ephy_permissions_manager_set_permission (manager,
+                                             EPHY_PERMISSION_TYPE_SAVE_PASSWORD,
+                                             data->origin,
+                                             EPHY_PERMISSION_DENY);
   }
 
   g_free (data->origin);
@@ -1317,11 +1317,11 @@ decide_on_permission_request (GtkWidget               *info_bar,
     shell = ephy_embed_shell_get_default ();
     permissions_manager = ephy_embed_shell_get_permissions_manager (shell);
 
-    ephy_permissions_manager_set_permission_for_address (permissions_manager,
-                                                         permission_type,
-                                                         data->origin,
-                                                         response == GTK_RESPONSE_YES ? EPHY_PERMISSION_ALLOW
-                                                                                      : 
EPHY_PERMISSION_DENY);
+    ephy_permissions_manager_set_permission (permissions_manager,
+                                             permission_type,
+                                             data->origin,
+                                             response == GTK_RESPONSE_YES ? EPHY_PERMISSION_ALLOW
+                                                                          : EPHY_PERMISSION_DENY);
   }
 
   gtk_widget_destroy (info_bar);
@@ -1430,6 +1430,7 @@ permission_request_cb (WebKitWebView           *web_view,
                        WebKitPermissionRequest *decision)
 {
   const char *address;
+  char *origin;
   EphyEmbedShell *shell;
   EphyPermissionsManager *permissions_manager;
   EphyPermission permission;
@@ -1456,10 +1457,15 @@ permission_request_cb (WebKitWebView           *web_view,
   }
 
   address = ephy_web_view_get_address (EPHY_WEB_VIEW (web_view));
+  origin = ephy_uri_to_security_origin (address);
+  if (origin == NULL)
+    return FALSE;
+
   permissions_manager = ephy_embed_shell_get_permissions_manager (ephy_embed_shell_get_default ());
-  permission = ephy_permissions_manager_get_permission_for_address (permissions_manager,
-                                                                    permission_type,
-                                                                    address);
+  permission = ephy_permissions_manager_get_permission (permissions_manager,
+                                                        permission_type,
+                                                        origin);
+  g_free (origin);
 
   switch (permission) {
   case EPHY_PERMISSION_ALLOW:
diff --git a/embed/web-extension/ephy-web-extension.c b/embed/web-extension/ephy-web-extension.c
index b3bb597..ea6d3c2 100644
--- a/embed/web-extension/ephy-web-extension.c
+++ b/embed/web-extension/ephy-web-extension.c
@@ -377,16 +377,20 @@ should_store_cb (const char *username,
   EphyPermission permission;
   SoupURI *uri;
   char *uri_string;
+  char *origin = NULL;
 
   uri = ephy_embed_form_auth_get_uri (form_auth);
   uri_string = soup_uri_to_string (uri, FALSE);
-  if (!uri_string)
+  if (uri_string == NULL)
     return;
+  origin = ephy_uri_to_security_origin (uri_string);
+  if (origin == NULL)
+    goto out;
 
   web_extension = ephy_web_extension_get ();
-  permission = ephy_permissions_manager_get_permission_for_address (web_extension->permissions_manager,
-                                                                    EPHY_PERMISSION_TYPE_SAVE_PASSWORD,
-                                                                    uri_string);
+  permission = ephy_permissions_manager_get_permission (web_extension->permissions_manager,
+                                                        EPHY_PERMISSION_TYPE_SAVE_PASSWORD,
+                                                        origin);
 
   if (permission == EPHY_PERMISSION_DENY) {
     LOG ("User/password storage permission previously denied. Not asking about storing.");
@@ -428,6 +432,8 @@ should_store_cb (const char *username,
   }
 
 out:
+  if (origin != NULL)
+    g_free (origin);
   g_free (uri_string);
 }
 
diff --git a/lib/ephy-permissions-manager.c b/lib/ephy-permissions-manager.c
index 274d7aa..1f62fe0 100644
--- a/lib/ephy-permissions-manager.c
+++ b/lib/ephy-permissions-manager.c
@@ -27,12 +27,14 @@
 
 #define G_SETTINGS_ENABLE_BACKEND 1
 #include <gio/gsettingsbackend.h>
+#include <string.h>
+#include <webkit2/webkit2.h>
 
 struct _EphyPermissionsManager
 {
   GObject parent_instance;
 
-  GHashTable *hosts_mapping;
+  GHashTable *origins_mapping;
   GHashTable *settings_mapping;
 };
 
@@ -41,7 +43,7 @@ G_DEFINE_TYPE (EphyPermissionsManager, ephy_permissions_manager, G_TYPE_OBJECT)
 static void
 ephy_permissions_manager_init (EphyPermissionsManager *manager)
 {
-  manager->hosts_mapping = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
+  manager->origins_mapping = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
   manager->settings_mapping = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
 }
 
@@ -50,7 +52,7 @@ ephy_permissions_manager_dispose (GObject *object)
 {
   EphyPermissionsManager *manager = EPHY_PERMISSIONS_MANAGER (object);
 
-  g_clear_pointer (&manager->hosts_mapping, g_hash_table_destroy);
+  g_clear_pointer (&manager->origins_mapping, g_hash_table_destroy);
   g_clear_pointer (&manager->settings_mapping, g_hash_table_destroy);
 
   G_OBJECT_CLASS (ephy_permissions_manager_parent_class)->dispose (object);
@@ -65,36 +67,48 @@ ephy_permissions_manager_class_init (EphyPermissionsManagerClass *klass)
 }
 
 static GSettings *
-ephy_permissions_manager_get_settings_for_address (EphyPermissionsManager *manager,
-                                                   const char             *address)
+ephy_permissions_manager_get_settings_for_origin (EphyPermissionsManager *manager,
+                                                  const char             *origin)
 {
-  char *host = ephy_string_get_host_name (address);
-  char *key_file = NULL;
-  char *host_path = NULL;
-  GSettingsBackend* backend = NULL;
+  char *key_file;
+  char *origin_path;
+  char *trimmed_protocol;
+  GSettingsBackend* backend;
   GSettings *settings;
+  WebKitSecurityOrigin *security_origin;
+  char *pos;
 
-  g_assert (host != NULL);
+  g_assert (origin != NULL);
 
-  settings = g_hash_table_lookup (manager->hosts_mapping, host);
-  if (settings) {
-    g_free (host);
+  settings = g_hash_table_lookup (manager->origins_mapping, origin);
+  if (settings)
     return settings;
-  }
 
-  key_file = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "hosts.ini", ephy_dot_dir ());
-  backend = g_keyfile_settings_backend_new (key_file, "/", "Hosts");
+  key_file = g_build_filename (ephy_dot_dir (), "permissions.ini", NULL);
+  backend = g_keyfile_settings_backend_new (key_file, "/", NULL);
   g_free (key_file);
 
-  host_path = g_strdup_printf ("/org/gnome/epiphany/hosts/%s/", host);
-
-  settings = g_settings_new_with_backend_and_path ("org.gnome.Epiphany.host", backend, host_path);
-
-  g_free (host_path);
+  /* Cannot contain consecutive slashes in GSettings path... */
+  security_origin = webkit_security_origin_new_from_string (origin);
+  trimmed_protocol = g_strdup (webkit_security_origin_get_protocol (security_origin));
+  pos = strchr (trimmed_protocol, '/');
+  if (pos != NULL)
+    *pos = '\0';
+
+  origin_path = g_strdup_printf ("/org/gnome/epiphany/permissions/%s/%s/%u/",
+                                 trimmed_protocol,
+                                 webkit_security_origin_get_host (security_origin),
+                                 webkit_security_origin_get_port (security_origin));
+
+  settings = g_settings_new_with_backend_and_path ("org.gnome.Epiphany.Permissions", backend, origin_path);
+  g_free (trimmed_protocol);
+  g_free (origin_path);
   g_object_unref (backend);
+  webkit_security_origin_unref (security_origin);
 
-  g_hash_table_insert (manager->hosts_mapping, host, settings);
-  g_hash_table_insert (manager->settings_mapping, settings, host);
+  /* Note that settings is owned only by the first hash table! */
+  g_hash_table_insert (manager->origins_mapping, g_strdup (origin), settings);
+  g_hash_table_insert (manager->settings_mapping, settings, g_strdup (origin));
 
   return settings;
 }
@@ -125,20 +139,20 @@ permission_type_to_string (EphyPermissionType type)
 }
 
 EphyPermission
-ephy_permissions_manager_get_permission_for_address (EphyPermissionsManager *manager,
-                                                     EphyPermissionType      type,
-                                                     const char             *address)
+ephy_permissions_manager_get_permission (EphyPermissionsManager *manager,
+                                         EphyPermissionType      type,
+                                         const char             *origin)
 {
-  GSettings *settings = ephy_permissions_manager_get_settings_for_address (manager, address);
+  GSettings *settings = ephy_permissions_manager_get_settings_for_origin (manager, origin);
   return g_settings_get_enum (settings, permission_type_to_string (type));
 }
 
 void
-ephy_permissions_manager_set_permission_for_address (EphyPermissionsManager *manager,
-                                                     EphyPermissionType      type,
-                                                     const char             *address,
-                                                     EphyPermission          permission)
+ephy_permissions_manager_set_permission (EphyPermissionsManager *manager,
+                                         EphyPermissionType      type,
+                                         const char             *origin,
+                                         EphyPermission          permission)
 {
-  GSettings *settings = ephy_permissions_manager_get_settings_for_address (manager, address);
+  GSettings *settings = ephy_permissions_manager_get_settings_for_origin (manager, origin);
   g_settings_set_enum (settings, permission_type_to_string (type), permission);
 }
diff --git a/lib/ephy-permissions-manager.h b/lib/ephy-permissions-manager.h
index 75fe2bf..fbad3a0 100644
--- a/lib/ephy-permissions-manager.h
+++ b/lib/ephy-permissions-manager.h
@@ -43,13 +43,13 @@ typedef enum {
   EPHY_PERMISSION_TYPE_ACCESS_WEBCAM
 } EphyPermissionType;
 
-EphyPermissionsManager *ephy_permissions_manager_new                        (void);
-
-EphyPermission          ephy_permissions_manager_get_permission_for_address (EphyPermissionsManager *manager,
-                                                                             EphyPermissionType      type,
-                                                                             const char             
*address);
-void                    ephy_permissions_manager_set_permission_for_address (EphyPermissionsManager *manager,
-                                                                             EphyPermissionType      type,
-                                                                             const char             *address,
-                                                                             EphyPermission          
permission);
+EphyPermissionsManager *ephy_permissions_manager_new            (void);
+
+EphyPermission          ephy_permissions_manager_get_permission (EphyPermissionsManager *manager,
+                                                                 EphyPermissionType      type,
+                                                                 const char             *origin);
+void                    ephy_permissions_manager_set_permission (EphyPermissionsManager *manager,
+                                                                 EphyPermissionType      type,
+                                                                 const char             *origin,
+                                                                 EphyPermission          permission);
 G_END_DECLS
diff --git a/src/profile-migrator/ephy-profile-migrator.c b/src/profile-migrator/ephy-profile-migrator.c
index f4bd2a8..7e207fe 100644
--- a/src/profile-migrator/ephy-profile-migrator.c
+++ b/src/profile-migrator/ephy-profile-migrator.c
@@ -605,6 +605,20 @@ migrate_bookmarks (void)
 }
 
 static void
+migrate_permissions (void)
+{
+  char *filename;
+  GFile *file;
+
+  filename = g_build_filename (ephy_dot_dir (), "hosts.ini", NULL);
+  file = g_file_new_for_path (filename);
+  g_free (filename);
+
+  g_file_delete (file, NULL, NULL);
+  g_object_unref (file);
+}
+
+static void
 migrate_nothing (void)
 {
   /* Used to replace migrators that have been removed. Only remove migrators
@@ -627,6 +641,7 @@ const EphyProfileMigrator migrators[] = {
   migrate_form_passwords_to_libsecret,
   migrate_app_desktop_file_categories,
   migrate_bookmarks,
+  migrate_permissions
 };
 
 static gboolean


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