[epiphany] Save decision to allow or deny notifications
- From: Gustavo Noronha Silva <gns src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [epiphany] Save decision to allow or deny notifications
- Date: Wed, 28 Sep 2016 12:40:09 +0000 (UTC)
commit 6b1344e3404c0d0ac49aa10d32914360f5052ad2
Author: Gustavo Noronha Silva <gns gnome org>
Date: Wed Sep 28 12:25:41 2016 +0200
Save decision to allow or deny notifications
The decision is stored using gsettings database. No UI exists currently to
forget or manage the decisions.
https://bugzilla.gnome.org/show_bug.cgi?id=748339
data/Makefile.am | 2 +-
data/org.gnome.epiphany.host.gschema.xml | 13 +++
embed/Makefile.am | 2 +
embed/ephy-embed-shell.c | 12 +++
embed/ephy-embed-shell.h | 2 +
embed/ephy-hosts-manager.c | 152 ++++++++++++++++++++++++++++++
embed/ephy-hosts-manager.h | 45 +++++++++
embed/ephy-web-view.c | 61 ++++++++++--
8 files changed, 278 insertions(+), 11 deletions(-)
---
diff --git a/data/Makefile.am b/data/Makefile.am
index 7be5390..9744f0c 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -13,7 +13,7 @@ convert_DATA = epiphany.convert
gsettings_ENUM_NAMESPACE = org.gnome.Epiphany
gsettings_ENUM_FILES = $(top_srcdir)/lib/ephy-prefs.h
-gsettings_SCHEMAS = org.gnome.epiphany.gschema.xml
+gsettings_SCHEMAS = org.gnome.epiphany.gschema.xml org.gnome.epiphany.host.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.host.gschema.xml
new file mode 100644
index 0000000..f70c7b7
--- /dev/null
+++ b/data/org.gnome.epiphany.host.gschema.xml
@@ -0,0 +1,13 @@
+<schemalist>
+ <enum id="org.gnome.Epiphany.host.permissions">
+ <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="notifications-permission" enum="org.gnome.Epiphany.host.permissions">
+ <default>"undecided"</default>
+ </key>
+ </schema>
+</schemalist>
diff --git a/embed/Makefile.am b/embed/Makefile.am
index 7152d63..f950c30 100644
--- a/embed/Makefile.am
+++ b/embed/Makefile.am
@@ -40,6 +40,8 @@ libephyembed_la_SOURCES = \
ephy-file-monitor.h \
ephy-find-toolbar.c \
ephy-find-toolbar.h \
+ ephy-hosts-manager.c \
+ ephy-hosts-manager.h \
ephy-view-source-handler.c \
ephy-view-source-handler.h \
ephy-web-view.c \
diff --git a/embed/ephy-embed-shell.c b/embed/ephy-embed-shell.c
index 70556a1..446ad62 100644
--- a/embed/ephy-embed-shell.c
+++ b/embed/ephy-embed-shell.c
@@ -55,6 +55,7 @@ typedef struct {
EphyEmbedShellMode mode;
WebKitUserContentManager *user_content;
EphyDownloadsManager *downloads_manager;
+ EphyHostsManager *hosts_manager;
EphyAboutHandler *about_handler;
EphyViewSourceHandler *source_handler;
guint update_overview_timeout_id;
@@ -105,6 +106,7 @@ ephy_embed_shell_dispose (GObject *object)
g_clear_object (&priv->source_handler);
g_clear_object (&priv->user_content);
g_clear_object (&priv->downloads_manager);
+ g_clear_object (&priv->hosts_manager);
g_clear_object (&priv->web_context);
g_clear_object (&priv->dbus_server);
@@ -1252,3 +1254,13 @@ ephy_embed_shell_get_downloads_manager (EphyEmbedShell *shell)
priv->downloads_manager = EPHY_DOWNLOADS_MANAGER (g_object_new (EPHY_TYPE_DOWNLOADS_MANAGER, NULL));
return priv->downloads_manager;
}
+
+EphyHostsManager *
+ephy_embed_shell_get_hosts_manager (EphyEmbedShell *shell)
+{
+ EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
+
+ if (!priv->hosts_manager)
+ priv->hosts_manager = ephy_hosts_manager_new ();
+ return priv->hosts_manager;
+}
diff --git a/embed/ephy-embed-shell.h b/embed/ephy-embed-shell.h
index d826d80..233aa47 100644
--- a/embed/ephy-embed-shell.h
+++ b/embed/ephy-embed-shell.h
@@ -21,6 +21,7 @@
#include <webkit2/webkit2.h>
#include "ephy-downloads-manager.h"
+#include "ephy-hosts-manager.h"
G_BEGIN_DECLS
@@ -72,5 +73,6 @@ void ephy_embed_shell_set_thumbnail_path (EphyEmbedShell
const char *path);
WebKitUserContentManager *ephy_embed_shell_get_user_content_manager (EphyEmbedShell *shell);
EphyDownloadsManager *ephy_embed_shell_get_downloads_manager (EphyEmbedShell *shell);
+EphyHostsManager *ephy_embed_shell_get_hosts_manager (EphyEmbedShell *shell);
G_END_DECLS
diff --git a/embed/ephy-hosts-manager.c b/embed/ephy-hosts-manager.c
new file mode 100644
index 0000000..9a9d3df
--- /dev/null
+++ b/embed/ephy-hosts-manager.c
@@ -0,0 +1,152 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2015 Gustavo Noronha Silva <gns gnome org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#include "ephy-hosts-manager.h"
+
+#include "ephy-embed-shell.h"
+#include "ephy-file-helpers.h"
+#include "ephy-string.h"
+
+#define G_SETTINGS_ENABLE_BACKEND 1
+#include <gio/gsettingsbackend.h>
+
+struct _EphyHostsManager
+{
+ GObject parent_instance;
+
+ GHashTable *hosts_mapping;
+ GHashTable *settings_mapping;
+};
+
+G_DEFINE_TYPE (EphyHostsManager, ephy_hosts_manager, G_TYPE_OBJECT)
+
+static void
+ephy_hosts_manager_init (EphyHostsManager *manager)
+{
+ manager->hosts_mapping = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
+ manager->settings_mapping = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
+}
+
+static void
+ephy_hosts_manager_dispose (GObject *object)
+{
+ EphyHostsManager *manager = EPHY_HOSTS_MANAGER (object);
+
+ g_clear_pointer (&manager->hosts_mapping, g_hash_table_destroy);
+ g_clear_pointer (&manager->settings_mapping, g_hash_table_destroy);
+
+ G_OBJECT_CLASS (ephy_hosts_manager_parent_class)->dispose (object);
+}
+
+static void
+ephy_hosts_manager_class_init (EphyHostsManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = ephy_hosts_manager_dispose;
+
+ /**
+ * EphyHostsManager::setting-changed:
+ * @host_manager: the #EphyHostsManager that received the signal
+ * @host: the hostname for which the setting changed
+ * @key: the name of the key that changed
+ *
+ * The ::setting-changed signal is emitted when the a setting changes for
+ * one of the hosts managed by the manager. It can be used to represent the
+ * change on the UI for instance.
+ **/
+ g_signal_new ("setting-changed",
+ EPHY_TYPE_HOSTS_MANAGER,
+ G_SIGNAL_RUN_FIRST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE,
+ 2,
+ G_TYPE_STRING,
+ G_TYPE_STRING);
+}
+
+static void
+setting_changed_cb (GSettings *settings,
+ char *key,
+ EphyHostsManager *manager)
+{
+ const char *host = g_hash_table_lookup (manager->settings_mapping, settings);
+ g_signal_emit_by_name (manager, "setting-changed", host, key);
+}
+
+static GSettings *
+ephy_hosts_manager_get_settings_for_address (EphyHostsManager *manager,
+ const char *address)
+{
+ char *host = ephy_string_get_host_name (address);
+ char *key_file = NULL;
+ char *host_path = NULL;
+ GSettingsBackend* backend = NULL;
+ GSettings *settings;
+
+ g_assert (host != NULL);
+
+ settings = g_hash_table_lookup (manager->hosts_mapping, host);
+ if (settings) {
+ g_free (host);
+ 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");
+ 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);
+ g_object_unref (backend);
+
+ g_hash_table_insert (manager->hosts_mapping, host, settings);
+ g_hash_table_insert (manager->settings_mapping, settings, host);
+
+ g_signal_connect (settings, "changed",
+ G_CALLBACK (setting_changed_cb), manager);
+
+ return settings;
+}
+
+EphyHostsManager *
+ephy_hosts_manager_new (void)
+{
+ return EPHY_HOSTS_MANAGER (g_object_new (EPHY_TYPE_HOSTS_MANAGER, NULL));
+}
+
+EphyHostPermission
+ephy_hosts_manager_get_notifications_permission_for_address (EphyHostsManager *manager,
+ const char *address)
+{
+ GSettings *settings = ephy_hosts_manager_get_settings_for_address (manager, address);
+ return g_settings_get_enum (settings, "notifications-permission");
+}
+
+void
+ephy_hosts_manager_set_notifications_permission_for_address (EphyHostsManager *manager,
+ const char *address,
+ EphyHostPermission permission)
+{
+ GSettings *settings = ephy_hosts_manager_get_settings_for_address (manager, address);
+ g_settings_set_enum (settings, "notifications-permission", permission);
+}
diff --git a/embed/ephy-hosts-manager.h b/embed/ephy-hosts-manager.h
new file mode 100644
index 0000000..482337e
--- /dev/null
+++ b/embed/ephy-hosts-manager.h
@@ -0,0 +1,45 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2015 Gustavo Noronha Silva <gns gnome org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef EPHY_HOSTS_MANAGER_H
+#define EPHY_HOSTS_MANAGER_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_HOSTS_MANAGER (ephy_hosts_manager_get_type ())
+
+G_DECLARE_FINAL_TYPE (EphyHostsManager, ephy_hosts_manager, EPHY, HOSTS_MANAGER, GObject)
+
+typedef enum {
+ EPHY_HOST_PERMISSION_UNDECIDED = -1,
+ EPHY_HOST_PERMISSION_DENY = 0,
+ EPHY_HOST_PERMISSION_ALLOW = 1,
+} EphyHostPermission;
+
+EphyHostsManager* ephy_hosts_manager_new (void);
+EphyHostPermission ephy_hosts_manager_get_notifications_permission_for_address (EphyHostsManager
*manager,
+ const char
*address);
+void ephy_hosts_manager_set_notifications_permission_for_address (EphyHostsManager
*manager,
+ const char
*address,
+ EphyHostPermission
permission);
+
+G_END_DECLS
+
+#endif /* EPHY_HOSTS_MANAGER_H */
diff --git a/embed/ephy-web-view.c b/embed/ephy-web-view.c
index fd81021..708d229 100644
--- a/embed/ephy-web-view.c
+++ b/embed/ephy-web-view.c
@@ -1235,24 +1235,41 @@ decide_policy_cb (WebKitWebView *web_view,
return TRUE;
}
+typedef struct {
+ EphyWebView *web_view;
+ WebKitPermissionRequest *request;
+} PermissionRequestData;
+
static void
decide_on_permission_request (GtkWidget *info_bar,
int response,
- WebKitPermissionRequest *request)
+ PermissionRequestData *data)
{
gtk_widget_destroy (info_bar);
switch (response) {
case GTK_RESPONSE_YES:
- webkit_permission_request_allow (request);
+ webkit_permission_request_allow (data->request);
break;
default:
- webkit_permission_request_deny (request);
+ webkit_permission_request_deny (data->request);
break;
}
+ if (WEBKIT_IS_NOTIFICATION_PERMISSION_REQUEST (data->request) && response != GTK_RESPONSE_NONE) {
+ const char *address = ephy_web_view_get_address (data->web_view);
+ if (ephy_embed_utils_address_has_web_scheme (address)) {
+ EphyHostsManager *hosts_manager = ephy_embed_shell_get_hosts_manager (ephy_embed_shell_get_default ());
+ ephy_hosts_manager_set_notifications_permission_for_address (
+ hosts_manager,
+ address,
+ response == GTK_RESPONSE_YES ? EPHY_HOST_PERMISSION_ALLOW : EPHY_HOST_PERMISSION_DENY);
+ }
+ }
+
gtk_widget_destroy (info_bar);
- g_object_unref (request);
+ g_object_unref (data->request);
+ g_slice_free (PermissionRequestData, data);
}
static gboolean
@@ -1263,6 +1280,7 @@ permission_request_cb (WebKitWebView *web_view,
GtkWidget *action_area;
GtkWidget *content_area;
GtkWidget *label;
+ PermissionRequestData *data;
char *message;
char *host;
@@ -1270,11 +1288,30 @@ permission_request_cb (WebKitWebView *web_view,
!WEBKIT_IS_NOTIFICATION_PERMISSION_REQUEST (decision))
return FALSE;
- /* Application mode implies being OK with notifications. */
- if (WEBKIT_IS_NOTIFICATION_PERMISSION_REQUEST (decision) &&
- ephy_embed_shell_get_mode (ephy_embed_shell_get_default ()) == EPHY_EMBED_SHELL_MODE_APPLICATION) {
- webkit_permission_request_allow (decision);
- return TRUE;
+ if (WEBKIT_IS_NOTIFICATION_PERMISSION_REQUEST (decision)) {
+ /* Application mode implies being OK with notifications. */
+ if (ephy_embed_shell_get_mode (ephy_embed_shell_get_default ()) == EPHY_EMBED_SHELL_MODE_APPLICATION) {
+ webkit_permission_request_allow (decision);
+ return TRUE;
+ }
+
+ {
+ const char *address = ephy_web_view_get_address (EPHY_WEB_VIEW (web_view));
+ EphyHostsManager *hosts_manager = ephy_embed_shell_get_hosts_manager (ephy_embed_shell_get_default ());
+ EphyHostPermission permission = ephy_hosts_manager_get_notifications_permission_for_address
(hosts_manager, address);
+
+ switch (permission) {
+ case EPHY_HOST_PERMISSION_ALLOW:
+ webkit_permission_request_allow (decision);
+ return TRUE;
+ case EPHY_HOST_PERMISSION_DENY:
+ webkit_permission_request_deny (decision);
+ return TRUE;
+ case EPHY_HOST_PERMISSION_UNDECIDED:
+ default:
+ break;
+ }
+ }
}
info_bar = gtk_info_bar_new_with_buttons (_("Deny"), GTK_RESPONSE_NO,
@@ -1312,9 +1349,13 @@ permission_request_cb (WebKitWebView *web_view,
gtk_widget_show_all (info_bar);
/* Ref the decision, to keep it alive while we decide */
+ data = g_new (PermissionRequestData, 1);
+ data->web_view = EPHY_WEB_VIEW (web_view);
+ data->request = g_object_ref (decision);
+
g_signal_connect (info_bar, "response",
G_CALLBACK (decide_on_permission_request),
- g_object_ref (decision));
+ data);
if (WEBKIT_IS_GEOLOCATION_PERMISSION_REQUEST (decision))
ephy_web_view_track_info_bar (info_bar, &EPHY_WEB_VIEW (web_view)->geolocation_info_bar);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]