[gnome-control-center] notifications: Forward notification settings to portal
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-control-center] notifications: Forward notification settings to portal
- Date: Thu, 2 Mar 2017 21:40:56 +0000 (UTC)
commit 8b9be45cba0a9f973489f16d464d235451501080
Author: Matthias Clasen <mclasen redhat com>
Date: Wed Feb 22 06:57:14 2017 -0500
notifications: Forward notification settings to portal
The flatpak notification portal reads permissions out
of the permission store, so forward the notification
permissions there in order to prevent sandboxed
applications from sending notifications.
The difference is a bit cosmetic, since the shell would
not show the notification anyway in this case, but it
is nicer to just cut off the calls and not let them
through the portal in the first place.
https://bugzilla.gnome.org/show_bug.cgi?id=778851
panels/notifications/cc-edit-dialog.c | 136 ++++++++++++++++++++++++-
panels/notifications/cc-edit-dialog.h | 3 +-
panels/notifications/cc-notifications-panel.c | 38 +++++++-
3 files changed, 174 insertions(+), 3 deletions(-)
---
diff --git a/panels/notifications/cc-edit-dialog.c b/panels/notifications/cc-edit-dialog.c
index a06601d..778c18c 100644
--- a/panels/notifications/cc-edit-dialog.c
+++ b/panels/notifications/cc-edit-dialog.c
@@ -49,6 +49,33 @@ static void update_sound_switch (GtkWidget *dialog);
static void update_notification_switch (GtkWidget *dialog);
static void update_switches (GtkWidget *dialog);
+static void
+dialog_set_app_id (GtkWidget *dialog,
+ const char *app_id)
+{
+ g_object_set_data_full (G_OBJECT (dialog), "app-id", g_strdup (app_id), g_free);
+}
+
+static const char *
+dialog_get_app_id (GtkWidget *dialog)
+{
+ return (const char*)g_object_get_data (G_OBJECT (dialog), "app-id");
+}
+
+static void
+dialog_set_perm_store (GtkWidget *dialog,
+ GDBusProxy *proxy)
+{
+ if (proxy)
+ g_object_set_data_full (G_OBJECT (dialog), "perm-store", g_object_ref (proxy), g_object_unref);
+}
+
+static GDBusProxy *
+dialog_get_perm_store (GtkWidget *dialog)
+{
+ return (GDBusProxy *)g_object_get_data (G_OBJECT (dialog), "perm-store");
+}
+
static GtkWidget *
get_switch (GtkBuilder *builder,
const gchar *prefix)
@@ -76,11 +103,108 @@ set_key_from_switch (GtkWidget *dialog,
}
static void
+on_perm_store_set_done (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GVariant) results = NULL;
+ g_autoptr(GError) error = NULL;
+
+ results = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
+ res,
+ &error);
+ if (results == NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to store permissions: %s", error->message);
+ return;
+ }
+}
+
+static void
+set_portal_permissions_for_app (GtkWidget *dialog, GtkSwitch *the_switch)
+{
+ GDBusProxy *perm_store = dialog_get_perm_store (dialog);
+ const char *app_id = dialog_get_app_id (dialog);
+ gboolean allow = gtk_switch_get_active (the_switch);
+ g_autoptr(GVariant) perms = NULL;
+ g_autoptr(GVariant) new_perms = NULL;
+ g_autoptr(GVariant) data = NULL;
+ GVariantBuilder builder;
+ gboolean found;
+ int i;
+ const char *yes_strv[] = { "yes", NULL };
+ const char *no_strv[] = { "no", NULL };
+ g_autoptr(GVariant) reply = NULL;
+ g_autoptr(GError) error = NULL;
+
+ if (perm_store == NULL)
+ {
+ g_warning ("Could not find PermissionStore, not syncing notification permissions");
+ return;
+ }
+
+ new_perms = g_variant_new_strv (allow ? yes_strv : no_strv, 1);
+ g_variant_ref_sink (new_perms);
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE("a{sas}"));
+ found = FALSE;
+
+ reply = g_dbus_proxy_call_sync (perm_store,
+ "Lookup",
+ g_variant_new ("(ss)",
+ "notifications",
+ "notification"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ NULL);
+ if (reply)
+ {
+ g_variant_get (reply, "(@a{sas}v)", &perms, &data);
+
+ for (i = 0; i < g_variant_n_children (perms); i++)
+ {
+ const char *key;
+ g_autoptr(GVariant) value = NULL;
+
+ g_variant_get_child (perms, i, "{&s@as}", &key, &value);
+ if (g_strcmp0 (key, app_id) == 0)
+ {
+ found = TRUE;
+ g_variant_builder_add (&builder, "{s@as}", key, new_perms);
+ }
+ else
+ g_variant_builder_add (&builder, "{s@as}", key, value);
+ }
+ }
+
+ if (!found)
+ g_variant_builder_add (&builder, "{s@as}", app_id, new_perms);
+
+
+ g_dbus_proxy_call (perm_store,
+ "Set",
+ g_variant_new ("(sbsa{sas}v)",
+ "notifications",
+ TRUE,
+ "notification",
+ &builder,
+ data ? data : g_variant_new_byte (0)),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ on_perm_store_set_done,
+ data);
+}
+
+static void
notifications_switch_state_set_cb (GtkSwitch *widget,
GParamSpec *pspec,
GtkWidget *dialog)
{
set_key_from_switch (dialog, "enable", widget);
+ set_portal_permissions_for_app (dialog, widget);
update_sound_switch (dialog);
update_banner_switch (dialog);
update_banner_content_switch (dialog);
@@ -303,7 +427,8 @@ void
cc_build_edit_dialog (CcNotificationsPanel *panel,
GAppInfo *app,
GSettings *settings,
- GSettings *master_settings)
+ GSettings *master_settings,
+ GDBusProxy *perm_store)
{
GtkBuilder *builder;
GtkWindow *shell;
@@ -312,6 +437,7 @@ cc_build_edit_dialog (CcNotificationsPanel *panel,
GError *error = NULL;
gchar *objects[] = { "edit-dialog", NULL };
guint builder_result;
+ char *app_id;
builder = gtk_builder_new ();
builder_result = gtk_builder_add_objects_from_resource (builder,
@@ -331,6 +457,14 @@ cc_build_edit_dialog (CcNotificationsPanel *panel,
dialog = GTK_WIDGET (gtk_builder_get_object (builder, "edit-dialog"));
+ app_id = g_strdup (g_app_info_get_id (app));
+ if (g_str_has_suffix (app_id, ".desktop"))
+ app_id[strlen (app_id) - strlen (".desktop")] = '\0';
+ dialog_set_app_id (dialog, app_id);
+ g_free (app_id);
+
+ dialog_set_perm_store (dialog, perm_store);
+
g_object_set (dialog,
"title", g_app_info_get_name (app),
"transient-for", shell,
diff --git a/panels/notifications/cc-edit-dialog.h b/panels/notifications/cc-edit-dialog.h
index fdd73ac..c0dc274 100644
--- a/panels/notifications/cc-edit-dialog.h
+++ b/panels/notifications/cc-edit-dialog.h
@@ -27,7 +27,8 @@ G_BEGIN_DECLS
void cc_build_edit_dialog (CcNotificationsPanel *panel,
GAppInfo *app,
GSettings *settings,
- GSettings *master_settings);
+ GSettings *master_settings,
+ GDBusProxy *perm_store);
G_END_DECLS
diff --git a/panels/notifications/cc-notifications-panel.c b/panels/notifications/cc-notifications-panel.c
index a0c24b1..8cadb99 100644
--- a/panels/notifications/cc-notifications-panel.c
+++ b/panels/notifications/cc-notifications-panel.c
@@ -48,6 +48,8 @@ struct _CcNotificationsPanel {
GList *sections;
GList *sections_reverse;
+
+ GDBusProxy *perm_store;
};
struct _CcNotificationsPanelClass {
@@ -93,6 +95,7 @@ cc_notifications_panel_finalize (GObject *object)
CcNotificationsPanel *panel = CC_NOTIFICATIONS_PANEL (object);
g_clear_object (&panel->apps_load_cancellable);
+ g_clear_object (&panel->perm_store);
G_OBJECT_CLASS (cc_notifications_panel_parent_class)->finalize (object);
}
@@ -139,6 +142,29 @@ keynav_failed (GtkWidget *widget,
}
static void
+on_perm_store_ready (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ CcNotificationsPanel *self;
+ GDBusProxy *proxy;
+ GError *error = NULL;
+
+ proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
+ if (proxy == NULL)
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Failed to connect to xdg-app permission store: %s",
+ error->message);
+ g_error_free (error);
+
+ return;
+ }
+ self = user_data;
+ self->perm_store = proxy;
+}
+
+static void
cc_notifications_panel_init (CcNotificationsPanel *panel)
{
GtkWidget *w;
@@ -214,6 +240,16 @@ cc_notifications_panel_init (CcNotificationsPanel *panel)
gtk_container_add (GTK_CONTAINER (panel), w);
gtk_widget_show (w);
+
+ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "org.freedesktop.impl.portal.PermissionStore",
+ "/org/freedesktop/impl/portal/PermissionStore",
+ "org.freedesktop.impl.portal.PermissionStore",
+ panel->apps_load_cancellable,
+ on_perm_store_ready,
+ panel);
}
static const char *
@@ -535,7 +571,7 @@ select_app (GtkListBox *list_box,
Application *app;
app = g_object_get_qdata (G_OBJECT (row), application_quark ());
- cc_build_edit_dialog (panel, app->app_info, app->settings, panel->master_settings);
+ cc_build_edit_dialog (panel, app->app_info, app->settings, panel->master_settings, panel->perm_store);
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]