privacy: React to changes in permissions store

Currently if control-center is already running with privacy panel in
foreground and user authorizes a new application to gain access to
location information from gnome-shell dialog, this change doesn't get
reflected in the privacy panel to user until they exit privacy panel.

This change fixes this by reacting to changes to permissions store.

https://bugzilla.gnome.org/show_bug.cgi?id=765006
This commit is contained in:
Zeeshan Ali (Khattak) 2016-04-13 17:13:33 +01:00
parent 9208f61eb6
commit 336851f997

View file

@ -71,6 +71,8 @@ struct _CcPrivacyPanelPrivate
GDBusProxy *gclue_manager; GDBusProxy *gclue_manager;
GDBusProxy *perm_store; GDBusProxy *perm_store;
GVariant *location_apps_perms; GVariant *location_apps_perms;
GVariant *location_apps_data;
GHashTable *location_app_switches;
GtkSizeGroup *location_icon_size_group; GtkSizeGroup *location_icon_size_group;
}; };
@ -515,7 +517,7 @@ on_location_app_state_set (GtkSwitch *widget,
{ {
LocationAppStateData *data = (LocationAppStateData *) user_data; LocationAppStateData *data = (LocationAppStateData *) user_data;
CcPrivacyPanel *self = data->self; CcPrivacyPanel *self = data->self;
GVariant *params, *in_dict, *out_data; GVariant *params;
GVariantIter iter; GVariantIter iter;
gchar *key; gchar *key;
gchar **value; gchar **value;
@ -527,8 +529,7 @@ on_location_app_state_set (GtkSwitch *widget,
data->changing_state = TRUE; data->changing_state = TRUE;
data->pending_state = state; data->pending_state = state;
in_dict = g_variant_get_child_value (self->priv->location_apps_perms, 0); g_variant_iter_init (&iter, self->priv->location_apps_perms);
g_variant_iter_init (&iter, in_dict);
g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY); g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
while (g_variant_iter_loop (&iter, "{s^as}", &key, &value)) while (g_variant_iter_loop (&iter, "{s^as}", &key, &value))
{ {
@ -549,16 +550,13 @@ on_location_app_state_set (GtkSwitch *widget,
if (tmp != NULL) if (tmp != NULL)
value[0] = tmp; value[0] = tmp;
} }
g_variant_unref (in_dict);
out_data = g_variant_get_child_value (self->priv->location_apps_perms, 1);
params = g_variant_new ("(sbsa{sas}v)", params = g_variant_new ("(sbsa{sas}v)",
APP_PERMISSIONS_TABLE, APP_PERMISSIONS_TABLE,
TRUE, TRUE,
APP_PERMISSIONS_ID, APP_PERMISSIONS_ID,
&builder, &builder,
out_data); self->priv->location_apps_data);
g_variant_unref (out_data);
g_dbus_proxy_call (self->priv->perm_store, g_dbus_proxy_call (self->priv->perm_store,
"Set", "Set",
@ -587,6 +585,14 @@ add_location_app (CcPrivacyPanel *self,
char *last_used_str; char *last_used_str;
LocationAppStateData *data; LocationAppStateData *data;
w = g_hash_table_lookup (priv->location_app_switches, app_id);
if (w != NULL)
{
gtk_switch_set_active (GTK_SWITCH (w), enabled);
return;
}
desktop_id = g_strdup_printf ("%s.desktop", app_id); desktop_id = g_strdup_printf ("%s.desktop", app_id);
app_info = g_desktop_app_info_new (desktop_id); app_info = g_desktop_app_info_new (desktop_id);
g_free (desktop_id); g_free (desktop_id);
@ -637,6 +643,9 @@ add_location_app (CcPrivacyPanel *self,
g_settings_bind (priv->location_settings, LOCATION_ENABLED, g_settings_bind (priv->location_settings, LOCATION_ENABLED,
w, "sensitive", w, "sensitive",
G_SETTINGS_BIND_DEFAULT); G_SETTINGS_BIND_DEFAULT);
g_hash_table_insert (priv->location_app_switches,
g_strdup (app_id),
g_object_ref (w));
data = g_slice_new (LocationAppStateData); data = g_slice_new (LocationAppStateData);
data->self = self; data->self = self;
@ -653,38 +662,26 @@ add_location_app (CcPrivacyPanel *self,
gtk_widget_show_all (row); gtk_widget_show_all (row);
} }
/* Steals permissions and permissions_data references */
static void static void
on_perm_store_lookup_done(GObject *source_object, update_perm_store (CcPrivacyPanel *self,
GAsyncResult *res, GVariant *permissions,
gpointer user_data) GVariant *permissions_data)
{ {
CcPrivacyPanel *self;
CcPrivacyPanelPrivate *priv; CcPrivacyPanelPrivate *priv;
GVariant *permissions, *dict;
GVariantIter iter; GVariantIter iter;
gchar *key; gchar *key;
gchar **value; gchar **value;
GList *children; GList *children;
GError *error = NULL;
permissions = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
res,
&error);
if (permissions == NULL)
{
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
g_warning ("Failed fetch permissions from xdg-app permission store: %s",
error->message);
g_error_free (error);
return;
}
self = user_data;
priv = self->priv; priv = self->priv;
g_clear_pointer (&priv->location_apps_perms, g_variant_unref);
priv->location_apps_perms = permissions; priv->location_apps_perms = permissions;
dict = g_variant_get_child_value (permissions, 0); g_clear_pointer (&priv->location_apps_data, g_variant_unref);
g_variant_iter_init (&iter, dict); priv->location_apps_data = permissions_data;
g_variant_iter_init (&iter, permissions);
while (g_variant_iter_loop (&iter, "{s^as}", &key, &value)) while (g_variant_iter_loop (&iter, "{s^as}", &key, &value))
{ {
gboolean enabled; gboolean enabled;
@ -701,7 +698,6 @@ on_perm_store_lookup_done(GObject *source_object,
add_location_app (self, key, enabled, last_used); add_location_app (self, key, enabled, last_used);
} }
g_variant_unref (dict);
children = gtk_container_get_children (GTK_CONTAINER (priv->location_apps_list_box)); children = gtk_container_get_children (GTK_CONTAINER (priv->location_apps_list_box));
if (g_list_length (children) > 0) if (g_list_length (children) > 0)
@ -712,6 +708,55 @@ on_perm_store_lookup_done(GObject *source_object,
g_list_free (children); g_list_free (children);
} }
static void
on_perm_store_signal (GDBusProxy *proxy,
gchar *sender_name,
gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{
GVariant *permissions, *permissions_data;
if (g_strcmp0 (signal_name, "Changed") != 0)
return;
permissions = g_variant_get_child_value (parameters, 4);
permissions_data = g_variant_get_child_value (parameters, 3);
update_perm_store (user_data, permissions, permissions_data);
}
static void
on_perm_store_lookup_done(GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
GVariant *ret, *permissions, *permissions_data;
GError *error = NULL;
ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
res,
&error);
if (ret == NULL)
{
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
g_warning ("Failed fetch permissions from xdg-app permission store: %s",
error->message);
g_error_free (error);
return;
}
permissions = g_variant_get_child_value (ret, 0);
permissions_data = g_variant_get_child_value (ret, 1);
update_perm_store (user_data, permissions, permissions_data);
g_signal_connect_object (source_object,
"g-signal",
G_CALLBACK (on_perm_store_signal),
user_data,
0);
}
static void static void
on_perm_store_ready (GObject *source_object, on_perm_store_ready (GObject *source_object,
GAsyncResult *res, GAsyncResult *res,
@ -772,6 +817,11 @@ add_location (CcPrivacyPanel *self)
w, "active", w, "active",
G_SETTINGS_BIND_DEFAULT); G_SETTINGS_BIND_DEFAULT);
priv->location_app_switches = g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,
g_object_unref);
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_NONE, G_DBUS_PROXY_FLAGS_NONE,
NULL, NULL,
@ -1197,6 +1247,8 @@ cc_privacy_panel_finalize (GObject *object)
g_clear_object (&priv->perm_store); g_clear_object (&priv->perm_store);
g_clear_object (&priv->location_icon_size_group); g_clear_object (&priv->location_icon_size_group);
g_clear_pointer (&priv->location_apps_perms, g_variant_unref); g_clear_pointer (&priv->location_apps_perms, g_variant_unref);
g_clear_pointer (&priv->location_apps_data, g_variant_unref);
g_clear_pointer (&priv->location_app_switches, g_hash_table_unref);
G_OBJECT_CLASS (cc_privacy_panel_parent_class)->finalize (object); G_OBJECT_CLASS (cc_privacy_panel_parent_class)->finalize (object);
} }