libmalcontent: Factor getting/setting app filter into a manager
Create a new MctManager object which is used as the anchor for getting or setting MctAppFilters. This changes the API naming around quite a bit, but doesn’t really change its behaviour or functionality — see the tests for examples of how little things change. This is one step on the way to emitting a signal (from MctManager) when a user’s parental controls change. Signed-off-by: Philip Withnall <withnall@endlessm.com> https://gitlab.freedesktop.org/pwithnall/malcontent/issues/1
This commit is contained in:
parent
388dedbff2
commit
68ebe8b568
|
@ -0,0 +1,63 @@
|
||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||||
|
*
|
||||||
|
* Copyright © 2018, 2019 Endless Mobile, Inc.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* - Philip Withnall <withnall@endlessm.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <gio/gio.h>
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <libmalcontent/app-filter.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MctAppFilterListType:
|
||||||
|
* @MCT_APP_FILTER_LIST_BLACKLIST: Any program in the list is not allowed to
|
||||||
|
* be run.
|
||||||
|
* @MCT_APP_FILTER_LIST_WHITELIST: Any program not in the list is not allowed
|
||||||
|
* to be run.
|
||||||
|
*
|
||||||
|
* Different semantics for interpreting an application list.
|
||||||
|
*
|
||||||
|
* Since: 0.2.0
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
MCT_APP_FILTER_LIST_BLACKLIST,
|
||||||
|
MCT_APP_FILTER_LIST_WHITELIST,
|
||||||
|
} MctAppFilterListType;
|
||||||
|
|
||||||
|
struct _MctAppFilter
|
||||||
|
{
|
||||||
|
gint ref_count;
|
||||||
|
|
||||||
|
uid_t user_id;
|
||||||
|
|
||||||
|
gchar **app_list; /* (owned) (array zero-terminated=1) */
|
||||||
|
MctAppFilterListType app_list_type;
|
||||||
|
|
||||||
|
GVariant *oars_ratings; /* (type a{ss}) (owned non-floating) */
|
||||||
|
gboolean allow_user_installation;
|
||||||
|
gboolean allow_system_installation;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_END_DECLS
|
|
@ -29,39 +29,12 @@
|
||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
#include <libmalcontent/app-filter.h>
|
#include <libmalcontent/app-filter.h>
|
||||||
|
|
||||||
|
#include "libmalcontent/app-filter-private.h"
|
||||||
|
|
||||||
|
|
||||||
G_DEFINE_QUARK (MctAppFilterError, mct_app_filter_error)
|
G_DEFINE_QUARK (MctAppFilterError, mct_app_filter_error)
|
||||||
|
|
||||||
/**
|
/* struct _MctAppFilter is defined in app-filter-private.h */
|
||||||
* MctAppFilterListType:
|
|
||||||
* @MCT_APP_FILTER_LIST_BLACKLIST: Any program in the list is not allowed to
|
|
||||||
* be run.
|
|
||||||
* @MCT_APP_FILTER_LIST_WHITELIST: Any program not in the list is not allowed
|
|
||||||
* to be run.
|
|
||||||
*
|
|
||||||
* Different semantics for interpreting an application list.
|
|
||||||
*
|
|
||||||
* Since: 0.2.0
|
|
||||||
*/
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
MCT_APP_FILTER_LIST_BLACKLIST,
|
|
||||||
MCT_APP_FILTER_LIST_WHITELIST,
|
|
||||||
} MctAppFilterListType;
|
|
||||||
|
|
||||||
struct _MctAppFilter
|
|
||||||
{
|
|
||||||
gint ref_count;
|
|
||||||
|
|
||||||
uid_t user_id;
|
|
||||||
|
|
||||||
gchar **app_list; /* (owned) (array zero-terminated=1) */
|
|
||||||
MctAppFilterListType app_list_type;
|
|
||||||
|
|
||||||
GVariant *oars_ratings; /* (type a{ss}) (owned non-floating) */
|
|
||||||
gboolean allow_user_installation;
|
|
||||||
gboolean allow_system_installation;
|
|
||||||
};
|
|
||||||
|
|
||||||
G_DEFINE_BOXED_TYPE (MctAppFilter, mct_app_filter,
|
G_DEFINE_BOXED_TYPE (MctAppFilter, mct_app_filter,
|
||||||
mct_app_filter_ref, mct_app_filter_unref)
|
mct_app_filter_ref, mct_app_filter_unref)
|
||||||
|
@ -453,639 +426,6 @@ mct_app_filter_is_system_installation_allowed (MctAppFilter *filter)
|
||||||
return filter->allow_system_installation;
|
return filter->allow_system_installation;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* _mct_app_filter_build_app_filter_variant:
|
|
||||||
* @filter: an #MctAppFilter
|
|
||||||
*
|
|
||||||
* Build a #GVariant which contains the app filter from @filter, in the format
|
|
||||||
* used for storing it in AccountsService.
|
|
||||||
*
|
|
||||||
* Returns: (transfer floating): a new, floating #GVariant containing the app
|
|
||||||
* filter
|
|
||||||
* Since: 0.2.0
|
|
||||||
*/
|
|
||||||
static GVariant *
|
|
||||||
_mct_app_filter_build_app_filter_variant (MctAppFilter *filter)
|
|
||||||
{
|
|
||||||
g_auto(GVariantBuilder) builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("(bas)"));
|
|
||||||
|
|
||||||
g_return_val_if_fail (filter != NULL, NULL);
|
|
||||||
g_return_val_if_fail (filter->ref_count >= 1, NULL);
|
|
||||||
|
|
||||||
g_variant_builder_add (&builder, "b",
|
|
||||||
(filter->app_list_type == MCT_APP_FILTER_LIST_WHITELIST));
|
|
||||||
g_variant_builder_open (&builder, G_VARIANT_TYPE ("as"));
|
|
||||||
|
|
||||||
for (gsize i = 0; filter->app_list[i] != NULL; i++)
|
|
||||||
g_variant_builder_add (&builder, "s", filter->app_list[i]);
|
|
||||||
|
|
||||||
g_variant_builder_close (&builder);
|
|
||||||
|
|
||||||
return g_variant_builder_end (&builder);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if @error is a D-Bus remote error matching @expected_error_name. */
|
|
||||||
static gboolean
|
|
||||||
bus_remote_error_matches (const GError *error,
|
|
||||||
const gchar *expected_error_name)
|
|
||||||
{
|
|
||||||
g_autofree gchar *error_name = NULL;
|
|
||||||
|
|
||||||
if (!g_dbus_error_is_remote_error (error))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
error_name = g_dbus_error_get_remote_error (error);
|
|
||||||
|
|
||||||
return g_str_equal (error_name, expected_error_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Convert a #GDBusError into a #MctAppFilter error. */
|
|
||||||
static GError *
|
|
||||||
bus_error_to_app_filter_error (const GError *bus_error,
|
|
||||||
uid_t user_id)
|
|
||||||
{
|
|
||||||
if (g_error_matches (bus_error, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED) ||
|
|
||||||
bus_remote_error_matches (bus_error, "org.freedesktop.Accounts.Error.PermissionDenied"))
|
|
||||||
return g_error_new (MCT_APP_FILTER_ERROR, MCT_APP_FILTER_ERROR_PERMISSION_DENIED,
|
|
||||||
_("Not allowed to query app filter data for user %u"),
|
|
||||||
(guint) user_id);
|
|
||||||
else if (g_error_matches (bus_error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD) ||
|
|
||||||
bus_remote_error_matches (bus_error, "org.freedesktop.Accounts.Error.Failed"))
|
|
||||||
return g_error_new (MCT_APP_FILTER_ERROR, MCT_APP_FILTER_ERROR_INVALID_USER,
|
|
||||||
_("User %u does not exist"), (guint) user_id);
|
|
||||||
else
|
|
||||||
return g_error_copy (bus_error);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find the object path for the given @user_id on the accountsservice D-Bus
|
|
||||||
* interface, by calling its FindUserById() method. This is a synchronous,
|
|
||||||
* blocking function. */
|
|
||||||
static gchar *
|
|
||||||
accounts_find_user_by_id (GDBusConnection *connection,
|
|
||||||
uid_t user_id,
|
|
||||||
gboolean allow_interactive_authorization,
|
|
||||||
GCancellable *cancellable,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
g_autofree gchar *object_path = NULL;
|
|
||||||
g_autoptr(GVariant) result_variant = NULL;
|
|
||||||
g_autoptr(GError) local_error = NULL;
|
|
||||||
|
|
||||||
result_variant =
|
|
||||||
g_dbus_connection_call_sync (connection,
|
|
||||||
"org.freedesktop.Accounts",
|
|
||||||
"/org/freedesktop/Accounts",
|
|
||||||
"org.freedesktop.Accounts",
|
|
||||||
"FindUserById",
|
|
||||||
g_variant_new ("(x)", (gint64) user_id),
|
|
||||||
G_VARIANT_TYPE ("(o)"),
|
|
||||||
allow_interactive_authorization
|
|
||||||
? G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION
|
|
||||||
: G_DBUS_CALL_FLAGS_NONE,
|
|
||||||
-1, /* timeout, ms */
|
|
||||||
cancellable,
|
|
||||||
&local_error);
|
|
||||||
if (local_error != NULL)
|
|
||||||
{
|
|
||||||
g_autoptr(GError) app_filter_error = bus_error_to_app_filter_error (local_error,
|
|
||||||
user_id);
|
|
||||||
g_propagate_error (error, g_steal_pointer (&app_filter_error));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_variant_get (result_variant, "(o)", &object_path);
|
|
||||||
|
|
||||||
return g_steal_pointer (&object_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* mct_get_app_filter:
|
|
||||||
* @connection: (nullable): a #GDBusConnection to the system bus, or %NULL to
|
|
||||||
* use the default
|
|
||||||
* @user_id: ID of the user to query, typically coming from getuid()
|
|
||||||
* @flags: flags to affect the behaviour of the call
|
|
||||||
* @cancellable: (nullable): a #GCancellable, or %NULL
|
|
||||||
* @error: return location for a #GError, or %NULL
|
|
||||||
*
|
|
||||||
* Synchronous version of mct_get_app_filter_async().
|
|
||||||
*
|
|
||||||
* Returns: (transfer full): app filter for the queried user
|
|
||||||
* Since: 0.3.0
|
|
||||||
*/
|
|
||||||
MctAppFilter *
|
|
||||||
mct_get_app_filter (GDBusConnection *connection,
|
|
||||||
uid_t user_id,
|
|
||||||
MctGetAppFilterFlags flags,
|
|
||||||
GCancellable *cancellable,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
g_autofree gchar *object_path = NULL;
|
|
||||||
g_autoptr(GVariant) result_variant = NULL;
|
|
||||||
g_autoptr(GVariant) properties = NULL;
|
|
||||||
g_autoptr(GError) local_error = NULL;
|
|
||||||
g_autoptr(MctAppFilter) app_filter = NULL;
|
|
||||||
gboolean is_whitelist;
|
|
||||||
g_auto(GStrv) app_list = NULL;
|
|
||||||
const gchar *content_rating_kind;
|
|
||||||
g_autoptr(GVariant) oars_variant = NULL;
|
|
||||||
gboolean allow_user_installation;
|
|
||||||
gboolean allow_system_installation;
|
|
||||||
|
|
||||||
g_return_val_if_fail (connection == NULL || G_IS_DBUS_CONNECTION (connection), NULL);
|
|
||||||
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
|
|
||||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
|
||||||
|
|
||||||
if (connection == NULL)
|
|
||||||
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, cancellable, error);
|
|
||||||
if (connection == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
object_path = accounts_find_user_by_id (connection, user_id,
|
|
||||||
(flags & MCT_GET_APP_FILTER_FLAGS_INTERACTIVE),
|
|
||||||
cancellable, error);
|
|
||||||
if (object_path == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
result_variant =
|
|
||||||
g_dbus_connection_call_sync (connection,
|
|
||||||
"org.freedesktop.Accounts",
|
|
||||||
object_path,
|
|
||||||
"org.freedesktop.DBus.Properties",
|
|
||||||
"GetAll",
|
|
||||||
g_variant_new ("(s)", "com.endlessm.ParentalControls.AppFilter"),
|
|
||||||
G_VARIANT_TYPE ("(a{sv})"),
|
|
||||||
(flags & MCT_GET_APP_FILTER_FLAGS_INTERACTIVE)
|
|
||||||
? G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION
|
|
||||||
: G_DBUS_CALL_FLAGS_NONE,
|
|
||||||
-1, /* timeout, ms */
|
|
||||||
cancellable,
|
|
||||||
&local_error);
|
|
||||||
if (local_error != NULL)
|
|
||||||
{
|
|
||||||
g_autoptr(GError) app_filter_error = NULL;
|
|
||||||
|
|
||||||
if (g_error_matches (local_error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS))
|
|
||||||
{
|
|
||||||
/* o.fd.D.GetAll() will return InvalidArgs errors if
|
|
||||||
* accountsservice doesn’t have the com.endlessm.ParentalControls.AppFilter
|
|
||||||
* extension interface installed. */
|
|
||||||
app_filter_error = g_error_new_literal (MCT_APP_FILTER_ERROR,
|
|
||||||
MCT_APP_FILTER_ERROR_DISABLED,
|
|
||||||
_("App filtering is globally disabled"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
app_filter_error = bus_error_to_app_filter_error (local_error,
|
|
||||||
user_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_propagate_error (error, g_steal_pointer (&app_filter_error));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Extract the properties we care about. They may be silently omitted from the
|
|
||||||
* results if we don’t have permission to access them. */
|
|
||||||
properties = g_variant_get_child_value (result_variant, 0);
|
|
||||||
if (!g_variant_lookup (properties, "AppFilter", "(b^as)",
|
|
||||||
&is_whitelist, &app_list))
|
|
||||||
{
|
|
||||||
g_set_error (error, MCT_APP_FILTER_ERROR,
|
|
||||||
MCT_APP_FILTER_ERROR_PERMISSION_DENIED,
|
|
||||||
_("Not allowed to query app filter data for user %u"),
|
|
||||||
(guint) user_id);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!g_variant_lookup (properties, "OarsFilter", "(&s@a{ss})",
|
|
||||||
&content_rating_kind, &oars_variant))
|
|
||||||
{
|
|
||||||
/* Default value. */
|
|
||||||
content_rating_kind = "oars-1.1";
|
|
||||||
oars_variant = g_variant_new ("a{ss}", NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check that the OARS filter is in a format we support. Currently, that’s
|
|
||||||
* only oars-1.0 and oars-1.1. */
|
|
||||||
if (!g_str_equal (content_rating_kind, "oars-1.0") &&
|
|
||||||
!g_str_equal (content_rating_kind, "oars-1.1"))
|
|
||||||
{
|
|
||||||
g_set_error (error, MCT_APP_FILTER_ERROR,
|
|
||||||
MCT_APP_FILTER_ERROR_INVALID_DATA,
|
|
||||||
_("OARS filter for user %u has an unrecognized kind ‘%s’"),
|
|
||||||
(guint) user_id, content_rating_kind);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!g_variant_lookup (properties, "AllowUserInstallation", "b",
|
|
||||||
&allow_user_installation))
|
|
||||||
{
|
|
||||||
/* Default value. */
|
|
||||||
allow_user_installation = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!g_variant_lookup (properties, "AllowSystemInstallation", "b",
|
|
||||||
&allow_system_installation))
|
|
||||||
{
|
|
||||||
/* Default value. */
|
|
||||||
allow_system_installation = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Success. Create an #MctAppFilter object to contain the results. */
|
|
||||||
app_filter = g_new0 (MctAppFilter, 1);
|
|
||||||
app_filter->ref_count = 1;
|
|
||||||
app_filter->user_id = user_id;
|
|
||||||
app_filter->app_list = g_steal_pointer (&app_list);
|
|
||||||
app_filter->app_list_type =
|
|
||||||
is_whitelist ? MCT_APP_FILTER_LIST_WHITELIST : MCT_APP_FILTER_LIST_BLACKLIST;
|
|
||||||
app_filter->oars_ratings = g_steal_pointer (&oars_variant);
|
|
||||||
app_filter->allow_user_installation = allow_user_installation;
|
|
||||||
app_filter->allow_system_installation = allow_system_installation;
|
|
||||||
|
|
||||||
return g_steal_pointer (&app_filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void get_app_filter_thread_cb (GTask *task,
|
|
||||||
gpointer source_object,
|
|
||||||
gpointer task_data,
|
|
||||||
GCancellable *cancellable);
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
GDBusConnection *connection; /* (nullable) (owned) */
|
|
||||||
uid_t user_id;
|
|
||||||
MctGetAppFilterFlags flags;
|
|
||||||
} GetAppFilterData;
|
|
||||||
|
|
||||||
static void
|
|
||||||
get_app_filter_data_free (GetAppFilterData *data)
|
|
||||||
{
|
|
||||||
g_clear_object (&data->connection);
|
|
||||||
g_free (data);
|
|
||||||
}
|
|
||||||
|
|
||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GetAppFilterData, get_app_filter_data_free)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* mct_get_app_filter_async:
|
|
||||||
* @connection: (nullable): a #GDBusConnection to the system bus, or %NULL to
|
|
||||||
* use the default
|
|
||||||
* @user_id: ID of the user to query, typically coming from getuid()
|
|
||||||
* @flags: flags to affect the behaviour of the call
|
|
||||||
* @cancellable: (nullable): a #GCancellable, or %NULL
|
|
||||||
* @callback: a #GAsyncReadyCallback
|
|
||||||
* @user_data: user data to pass to @callback
|
|
||||||
*
|
|
||||||
* Asynchronously get a snapshot of the app filter settings for the given
|
|
||||||
* @user_id.
|
|
||||||
*
|
|
||||||
* @connection should be a connection to the system bus, where accounts-service
|
|
||||||
* runs. It’s provided mostly for testing purposes, or to allow an existing
|
|
||||||
* connection to be re-used. Pass %NULL to use the default connection.
|
|
||||||
*
|
|
||||||
* On failure, an #MctAppFilterError, a #GDBusError or a #GIOError will be
|
|
||||||
* returned.
|
|
||||||
*
|
|
||||||
* Since: 0.3.0
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
mct_get_app_filter_async (GDBusConnection *connection,
|
|
||||||
uid_t user_id,
|
|
||||||
MctGetAppFilterFlags flags,
|
|
||||||
GCancellable *cancellable,
|
|
||||||
GAsyncReadyCallback callback,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
g_autoptr(GTask) task = NULL;
|
|
||||||
g_autoptr(GetAppFilterData) data = NULL;
|
|
||||||
|
|
||||||
g_return_if_fail (connection == NULL || G_IS_DBUS_CONNECTION (connection));
|
|
||||||
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
|
||||||
|
|
||||||
task = g_task_new (NULL, cancellable, callback, user_data);
|
|
||||||
g_task_set_source_tag (task, mct_get_app_filter_async);
|
|
||||||
|
|
||||||
data = g_new0 (GetAppFilterData, 1);
|
|
||||||
data->connection = (connection != NULL) ? g_object_ref (connection) : NULL;
|
|
||||||
data->user_id = user_id;
|
|
||||||
data->flags = flags;
|
|
||||||
g_task_set_task_data (task, g_steal_pointer (&data),
|
|
||||||
(GDestroyNotify) get_app_filter_data_free);
|
|
||||||
|
|
||||||
g_task_run_in_thread (task, get_app_filter_thread_cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
get_app_filter_thread_cb (GTask *task,
|
|
||||||
gpointer source_object,
|
|
||||||
gpointer task_data,
|
|
||||||
GCancellable *cancellable)
|
|
||||||
{
|
|
||||||
g_autoptr(MctAppFilter) filter = NULL;
|
|
||||||
GetAppFilterData *data = task_data;
|
|
||||||
g_autoptr(GError) local_error = NULL;
|
|
||||||
|
|
||||||
filter = mct_get_app_filter (data->connection, data->user_id,
|
|
||||||
data->flags,
|
|
||||||
cancellable, &local_error);
|
|
||||||
|
|
||||||
if (local_error != NULL)
|
|
||||||
g_task_return_error (task, g_steal_pointer (&local_error));
|
|
||||||
else
|
|
||||||
g_task_return_pointer (task, g_steal_pointer (&filter),
|
|
||||||
(GDestroyNotify) mct_app_filter_unref);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* mct_get_app_filter_finish:
|
|
||||||
* @result: a #GAsyncResult
|
|
||||||
* @error: return location for a #GError, or %NULL
|
|
||||||
*
|
|
||||||
* Finish an asynchronous operation to get the app filter for a user, started
|
|
||||||
* with mct_get_app_filter_async().
|
|
||||||
*
|
|
||||||
* Returns: (transfer full): app filter for the queried user
|
|
||||||
* Since: 0.2.0
|
|
||||||
*/
|
|
||||||
MctAppFilter *
|
|
||||||
mct_get_app_filter_finish (GAsyncResult *result,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
g_return_val_if_fail (g_task_is_valid (result, NULL), NULL);
|
|
||||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
|
||||||
|
|
||||||
return g_task_propagate_pointer (G_TASK (result), error);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* mct_set_app_filter:
|
|
||||||
* @connection: (nullable): a #GDBusConnection to the system bus, or %NULL to
|
|
||||||
* use the default
|
|
||||||
* @user_id: ID of the user to set the filter for, typically coming from getuid()
|
|
||||||
* @app_filter: (transfer none): the app filter to set for the user
|
|
||||||
* @flags: flags to affect the behaviour of the call
|
|
||||||
* @cancellable: (nullable): a #GCancellable, or %NULL
|
|
||||||
* @error: return location for a #GError, or %NULL
|
|
||||||
*
|
|
||||||
* Synchronous version of mct_set_app_filter_async().
|
|
||||||
*
|
|
||||||
* Returns: %TRUE on success, %FALSE otherwise
|
|
||||||
* Since: 0.3.0
|
|
||||||
*/
|
|
||||||
gboolean
|
|
||||||
mct_set_app_filter (GDBusConnection *connection,
|
|
||||||
uid_t user_id,
|
|
||||||
MctAppFilter *app_filter,
|
|
||||||
MctSetAppFilterFlags flags,
|
|
||||||
GCancellable *cancellable,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
g_autofree gchar *object_path = NULL;
|
|
||||||
g_autoptr(GVariant) app_filter_variant = NULL;
|
|
||||||
g_autoptr(GVariant) oars_filter_variant = NULL;
|
|
||||||
g_autoptr(GVariant) allow_user_installation_variant = NULL;
|
|
||||||
g_autoptr(GVariant) allow_system_installation_variant = NULL;
|
|
||||||
g_autoptr(GVariant) app_filter_result_variant = NULL;
|
|
||||||
g_autoptr(GVariant) oars_filter_result_variant = NULL;
|
|
||||||
g_autoptr(GVariant) allow_user_installation_result_variant = NULL;
|
|
||||||
g_autoptr(GVariant) allow_system_installation_result_variant = NULL;
|
|
||||||
g_autoptr(GError) local_error = NULL;
|
|
||||||
|
|
||||||
g_return_val_if_fail (connection == NULL || G_IS_DBUS_CONNECTION (connection), FALSE);
|
|
||||||
g_return_val_if_fail (app_filter != NULL, FALSE);
|
|
||||||
g_return_val_if_fail (app_filter->ref_count >= 1, FALSE);
|
|
||||||
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
|
|
||||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
|
||||||
|
|
||||||
if (connection == NULL)
|
|
||||||
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, cancellable, error);
|
|
||||||
if (connection == NULL)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
object_path = accounts_find_user_by_id (connection, user_id,
|
|
||||||
(flags & MCT_SET_APP_FILTER_FLAGS_INTERACTIVE),
|
|
||||||
cancellable, error);
|
|
||||||
if (object_path == NULL)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
app_filter_variant = _mct_app_filter_build_app_filter_variant (app_filter);
|
|
||||||
oars_filter_variant = g_variant_new ("(s@a{ss})", "oars-1.1",
|
|
||||||
app_filter->oars_ratings);
|
|
||||||
allow_user_installation_variant = g_variant_new_boolean (app_filter->allow_user_installation);
|
|
||||||
allow_system_installation_variant = g_variant_new_boolean (app_filter->allow_system_installation);
|
|
||||||
|
|
||||||
app_filter_result_variant =
|
|
||||||
g_dbus_connection_call_sync (connection,
|
|
||||||
"org.freedesktop.Accounts",
|
|
||||||
object_path,
|
|
||||||
"org.freedesktop.DBus.Properties",
|
|
||||||
"Set",
|
|
||||||
g_variant_new ("(ssv)",
|
|
||||||
"com.endlessm.ParentalControls.AppFilter",
|
|
||||||
"AppFilter",
|
|
||||||
g_steal_pointer (&app_filter_variant)),
|
|
||||||
G_VARIANT_TYPE ("()"),
|
|
||||||
(flags & MCT_SET_APP_FILTER_FLAGS_INTERACTIVE)
|
|
||||||
? G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION
|
|
||||||
: G_DBUS_CALL_FLAGS_NONE,
|
|
||||||
-1, /* timeout, ms */
|
|
||||||
cancellable,
|
|
||||||
&local_error);
|
|
||||||
if (local_error != NULL)
|
|
||||||
{
|
|
||||||
g_propagate_error (error, bus_error_to_app_filter_error (local_error, user_id));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
oars_filter_result_variant =
|
|
||||||
g_dbus_connection_call_sync (connection,
|
|
||||||
"org.freedesktop.Accounts",
|
|
||||||
object_path,
|
|
||||||
"org.freedesktop.DBus.Properties",
|
|
||||||
"Set",
|
|
||||||
g_variant_new ("(ssv)",
|
|
||||||
"com.endlessm.ParentalControls.AppFilter",
|
|
||||||
"OarsFilter",
|
|
||||||
g_steal_pointer (&oars_filter_variant)),
|
|
||||||
G_VARIANT_TYPE ("()"),
|
|
||||||
(flags & MCT_SET_APP_FILTER_FLAGS_INTERACTIVE)
|
|
||||||
? G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION
|
|
||||||
: G_DBUS_CALL_FLAGS_NONE,
|
|
||||||
-1, /* timeout, ms */
|
|
||||||
cancellable,
|
|
||||||
&local_error);
|
|
||||||
if (local_error != NULL)
|
|
||||||
{
|
|
||||||
g_propagate_error (error, bus_error_to_app_filter_error (local_error, user_id));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
allow_user_installation_result_variant =
|
|
||||||
g_dbus_connection_call_sync (connection,
|
|
||||||
"org.freedesktop.Accounts",
|
|
||||||
object_path,
|
|
||||||
"org.freedesktop.DBus.Properties",
|
|
||||||
"Set",
|
|
||||||
g_variant_new ("(ssv)",
|
|
||||||
"com.endlessm.ParentalControls.AppFilter",
|
|
||||||
"AllowUserInstallation",
|
|
||||||
g_steal_pointer (&allow_user_installation_variant)),
|
|
||||||
G_VARIANT_TYPE ("()"),
|
|
||||||
(flags & MCT_SET_APP_FILTER_FLAGS_INTERACTIVE)
|
|
||||||
? G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION
|
|
||||||
: G_DBUS_CALL_FLAGS_NONE,
|
|
||||||
-1, /* timeout, ms */
|
|
||||||
cancellable,
|
|
||||||
&local_error);
|
|
||||||
if (local_error != NULL)
|
|
||||||
{
|
|
||||||
g_propagate_error (error, bus_error_to_app_filter_error (local_error, user_id));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
allow_system_installation_result_variant =
|
|
||||||
g_dbus_connection_call_sync (connection,
|
|
||||||
"org.freedesktop.Accounts",
|
|
||||||
object_path,
|
|
||||||
"org.freedesktop.DBus.Properties",
|
|
||||||
"Set",
|
|
||||||
g_variant_new ("(ssv)",
|
|
||||||
"com.endlessm.ParentalControls.AppFilter",
|
|
||||||
"AllowSystemInstallation",
|
|
||||||
g_steal_pointer (&allow_system_installation_variant)),
|
|
||||||
G_VARIANT_TYPE ("()"),
|
|
||||||
(flags & MCT_SET_APP_FILTER_FLAGS_INTERACTIVE)
|
|
||||||
? G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION
|
|
||||||
: G_DBUS_CALL_FLAGS_NONE,
|
|
||||||
-1, /* timeout, ms */
|
|
||||||
cancellable,
|
|
||||||
&local_error);
|
|
||||||
if (local_error != NULL)
|
|
||||||
{
|
|
||||||
g_propagate_error (error, bus_error_to_app_filter_error (local_error, user_id));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void set_app_filter_thread_cb (GTask *task,
|
|
||||||
gpointer source_object,
|
|
||||||
gpointer task_data,
|
|
||||||
GCancellable *cancellable);
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
GDBusConnection *connection; /* (nullable) (owned) */
|
|
||||||
uid_t user_id;
|
|
||||||
MctAppFilter *app_filter; /* (owned) */
|
|
||||||
MctSetAppFilterFlags flags;
|
|
||||||
} SetAppFilterData;
|
|
||||||
|
|
||||||
static void
|
|
||||||
set_app_filter_data_free (SetAppFilterData *data)
|
|
||||||
{
|
|
||||||
g_clear_object (&data->connection);
|
|
||||||
mct_app_filter_unref (data->app_filter);
|
|
||||||
g_free (data);
|
|
||||||
}
|
|
||||||
|
|
||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (SetAppFilterData, set_app_filter_data_free)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* mct_set_app_filter_async:
|
|
||||||
* @connection: (nullable): a #GDBusConnection to the system bus, or %NULL to
|
|
||||||
* use the default
|
|
||||||
* @user_id: ID of the user to set the filter for, typically coming from getuid()
|
|
||||||
* @app_filter: (transfer none): the app filter to set for the user
|
|
||||||
* @flags: flags to affect the behaviour of the call
|
|
||||||
* @cancellable: (nullable): a #GCancellable, or %NULL
|
|
||||||
* @callback: a #GAsyncReadyCallback
|
|
||||||
* @user_data: user data to pass to @callback
|
|
||||||
*
|
|
||||||
* Asynchronously set the app filter settings for the given @user_id to the
|
|
||||||
* given @app_filter instance. This will set all fields of the app filter.
|
|
||||||
*
|
|
||||||
* @connection should be a connection to the system bus, where accounts-service
|
|
||||||
* runs. It’s provided mostly for testing purposes, or to allow an existing
|
|
||||||
* connection to be re-used. Pass %NULL to use the default connection.
|
|
||||||
*
|
|
||||||
* On failure, an #MctAppFilterError, a #GDBusError or a #GIOError will be
|
|
||||||
* returned. The user’s app filter settings will be left in an undefined state.
|
|
||||||
*
|
|
||||||
* Since: 0.3.0
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
mct_set_app_filter_async (GDBusConnection *connection,
|
|
||||||
uid_t user_id,
|
|
||||||
MctAppFilter *app_filter,
|
|
||||||
MctSetAppFilterFlags flags,
|
|
||||||
GCancellable *cancellable,
|
|
||||||
GAsyncReadyCallback callback,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
g_autoptr(GTask) task = NULL;
|
|
||||||
g_autoptr(SetAppFilterData) data = NULL;
|
|
||||||
|
|
||||||
g_return_if_fail (connection == NULL || G_IS_DBUS_CONNECTION (connection));
|
|
||||||
g_return_if_fail (app_filter != NULL);
|
|
||||||
g_return_if_fail (app_filter->ref_count >= 1);
|
|
||||||
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
|
||||||
|
|
||||||
task = g_task_new (NULL, cancellable, callback, user_data);
|
|
||||||
g_task_set_source_tag (task, mct_set_app_filter_async);
|
|
||||||
|
|
||||||
data = g_new0 (SetAppFilterData, 1);
|
|
||||||
data->connection = (connection != NULL) ? g_object_ref (connection) : NULL;
|
|
||||||
data->user_id = user_id;
|
|
||||||
data->app_filter = mct_app_filter_ref (app_filter);
|
|
||||||
data->flags = flags;
|
|
||||||
g_task_set_task_data (task, g_steal_pointer (&data),
|
|
||||||
(GDestroyNotify) set_app_filter_data_free);
|
|
||||||
|
|
||||||
g_task_run_in_thread (task, set_app_filter_thread_cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
set_app_filter_thread_cb (GTask *task,
|
|
||||||
gpointer source_object,
|
|
||||||
gpointer task_data,
|
|
||||||
GCancellable *cancellable)
|
|
||||||
{
|
|
||||||
gboolean success;
|
|
||||||
SetAppFilterData *data = task_data;
|
|
||||||
g_autoptr(GError) local_error = NULL;
|
|
||||||
|
|
||||||
success = mct_set_app_filter (data->connection, data->user_id,
|
|
||||||
data->app_filter, data->flags,
|
|
||||||
cancellable, &local_error);
|
|
||||||
|
|
||||||
if (local_error != NULL)
|
|
||||||
g_task_return_error (task, g_steal_pointer (&local_error));
|
|
||||||
else
|
|
||||||
g_task_return_boolean (task, success);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* mct_set_app_filter_finish:
|
|
||||||
* @result: a #GAsyncResult
|
|
||||||
* @error: return location for a #GError, or %NULL
|
|
||||||
*
|
|
||||||
* Finish an asynchronous operation to set the app filter for a user, started
|
|
||||||
* with mct_set_app_filter_async().
|
|
||||||
*
|
|
||||||
* Returns: %TRUE on success, %FALSE otherwise
|
|
||||||
* Since: 0.2.0
|
|
||||||
*/
|
|
||||||
gboolean
|
|
||||||
mct_set_app_filter_finish (GAsyncResult *result,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
g_return_val_if_fail (g_task_is_valid (result, NULL), FALSE);
|
|
||||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
|
||||||
|
|
||||||
return g_task_propagate_boolean (G_TASK (result), error);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Actual implementation of #MctAppFilterBuilder.
|
* Actual implementation of #MctAppFilterBuilder.
|
||||||
*
|
*
|
||||||
|
|
|
@ -37,7 +37,8 @@ G_BEGIN_DECLS
|
||||||
* a user is inconsistent or invalid
|
* a user is inconsistent or invalid
|
||||||
* @MCT_APP_FILTER_ERROR_DISABLED: App filtering is disabled for all users (Since: 0.3.0)
|
* @MCT_APP_FILTER_ERROR_DISABLED: App filtering is disabled for all users (Since: 0.3.0)
|
||||||
*
|
*
|
||||||
* Errors which can be returned by mct_get_app_filter_async().
|
* Errors relating to #MctAppFilter instances, which can be returned by
|
||||||
|
* mct_manager_get_app_filter_async() (for example).
|
||||||
*
|
*
|
||||||
* Since: 0.2.0
|
* Since: 0.2.0
|
||||||
*/
|
*/
|
||||||
|
@ -78,40 +79,6 @@ typedef enum
|
||||||
MCT_APP_FILTER_OARS_VALUE_INTENSE,
|
MCT_APP_FILTER_OARS_VALUE_INTENSE,
|
||||||
} MctAppFilterOarsValue;
|
} MctAppFilterOarsValue;
|
||||||
|
|
||||||
/**
|
|
||||||
* MctGetAppFilterFlags:
|
|
||||||
* @MCT_GET_APP_FILTER_FLAGS_NONE: No flags set.
|
|
||||||
* @MCT_GET_APP_FILTER_FLAGS_INTERACTIVE: Allow interactive polkit dialogs when
|
|
||||||
* requesting authorization.
|
|
||||||
*
|
|
||||||
* Flags to control the behaviour of mct_get_app_filter() and
|
|
||||||
* mct_get_app_filter_async().
|
|
||||||
*
|
|
||||||
* Since: 0.3.0
|
|
||||||
*/
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
MCT_GET_APP_FILTER_FLAGS_NONE = 0,
|
|
||||||
MCT_GET_APP_FILTER_FLAGS_INTERACTIVE,
|
|
||||||
} MctGetAppFilterFlags;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* MctSetAppFilterFlags:
|
|
||||||
* @MCT_SET_APP_FILTER_FLAGS_NONE: No flags set.
|
|
||||||
* @MCT_SET_APP_FILTER_FLAGS_INTERACTIVE: Allow interactive polkit dialogs when
|
|
||||||
* requesting authorization.
|
|
||||||
*
|
|
||||||
* Flags to control the behaviour of mct_set_app_filter() and
|
|
||||||
* mct_set_app_filter_async().
|
|
||||||
*
|
|
||||||
* Since: 0.3.0
|
|
||||||
*/
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
MCT_SET_APP_FILTER_FLAGS_NONE = 0,
|
|
||||||
MCT_SET_APP_FILTER_FLAGS_INTERACTIVE,
|
|
||||||
} MctSetAppFilterFlags;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MctAppFilter:
|
* MctAppFilter:
|
||||||
*
|
*
|
||||||
|
@ -150,36 +117,6 @@ MctAppFilterOarsValue mct_app_filter_get_oars_value (MctAppFilter *filter,
|
||||||
gboolean mct_app_filter_is_user_installation_allowed (MctAppFilter *filter);
|
gboolean mct_app_filter_is_user_installation_allowed (MctAppFilter *filter);
|
||||||
gboolean mct_app_filter_is_system_installation_allowed (MctAppFilter *filter);
|
gboolean mct_app_filter_is_system_installation_allowed (MctAppFilter *filter);
|
||||||
|
|
||||||
MctAppFilter *mct_get_app_filter (GDBusConnection *connection,
|
|
||||||
uid_t user_id,
|
|
||||||
MctGetAppFilterFlags flags,
|
|
||||||
GCancellable *cancellable,
|
|
||||||
GError **error);
|
|
||||||
void mct_get_app_filter_async (GDBusConnection *connection,
|
|
||||||
uid_t user_id,
|
|
||||||
MctGetAppFilterFlags flags,
|
|
||||||
GCancellable *cancellable,
|
|
||||||
GAsyncReadyCallback callback,
|
|
||||||
gpointer user_data);
|
|
||||||
MctAppFilter *mct_get_app_filter_finish (GAsyncResult *result,
|
|
||||||
GError **error);
|
|
||||||
|
|
||||||
gboolean mct_set_app_filter (GDBusConnection *connection,
|
|
||||||
uid_t user_id,
|
|
||||||
MctAppFilter *app_filter,
|
|
||||||
MctSetAppFilterFlags flags,
|
|
||||||
GCancellable *cancellable,
|
|
||||||
GError **error);
|
|
||||||
void mct_set_app_filter_async (GDBusConnection *connection,
|
|
||||||
uid_t user_id,
|
|
||||||
MctAppFilter *app_filter,
|
|
||||||
MctSetAppFilterFlags flags,
|
|
||||||
GCancellable *cancellable,
|
|
||||||
GAsyncReadyCallback callback,
|
|
||||||
gpointer user_data);
|
|
||||||
gboolean mct_set_app_filter_finish (GAsyncResult *result,
|
|
||||||
GError **error);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MctAppFilterBuilder:
|
* MctAppFilterBuilder:
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,779 @@
|
||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||||
|
*
|
||||||
|
* Copyright © 2019 Endless Mobile, Inc.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* - Philip Withnall <withnall@endlessm.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <glib/gi18n-lib.h>
|
||||||
|
#include <gio/gio.h>
|
||||||
|
#include <libmalcontent/app-filter.h>
|
||||||
|
#include <libmalcontent/manager.h>
|
||||||
|
|
||||||
|
#include "libmalcontent/app-filter-private.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MctManager:
|
||||||
|
*
|
||||||
|
* #MctManager is a top-level management object which is used to query and
|
||||||
|
* monitor #MctAppFilters for different users.
|
||||||
|
*
|
||||||
|
* Since: 0.3.0
|
||||||
|
*/
|
||||||
|
struct _MctManager
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
|
||||||
|
GDBusConnection *connection; /* (owned) */
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (MctManager, mct_manager, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
PROP_CONNECTION = 1,
|
||||||
|
} MctManagerProperty;
|
||||||
|
|
||||||
|
static GParamSpec *props[PROP_CONNECTION + 1] = { NULL, };
|
||||||
|
|
||||||
|
static void
|
||||||
|
mct_manager_init (MctManager *self)
|
||||||
|
{
|
||||||
|
/* Nothing to do here. */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mct_manager_get_property (GObject *object,
|
||||||
|
guint property_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *spec)
|
||||||
|
{
|
||||||
|
MctManager *self = MCT_MANAGER (object);
|
||||||
|
|
||||||
|
switch ((MctManagerProperty) property_id)
|
||||||
|
{
|
||||||
|
case PROP_CONNECTION:
|
||||||
|
g_value_set_object (value, self->connection);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, spec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mct_manager_set_property (GObject *object,
|
||||||
|
guint property_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *spec)
|
||||||
|
{
|
||||||
|
MctManager *self = MCT_MANAGER (object);
|
||||||
|
|
||||||
|
switch ((MctManagerProperty) property_id)
|
||||||
|
{
|
||||||
|
case PROP_CONNECTION:
|
||||||
|
/* Construct-only. May be %NULL. */
|
||||||
|
g_assert (self->connection == NULL);
|
||||||
|
self->connection = g_value_dup_object (value);
|
||||||
|
g_assert (self->connection != NULL);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, spec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mct_manager_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
MctManager *self = MCT_MANAGER (object);
|
||||||
|
|
||||||
|
g_clear_object (&self->connection);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (mct_manager_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mct_manager_class_init (MctManagerClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->dispose = mct_manager_dispose;
|
||||||
|
object_class->get_property = mct_manager_get_property;
|
||||||
|
object_class->set_property = mct_manager_set_property;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MctManager:connection:
|
||||||
|
*
|
||||||
|
* A connection to the system bus, where accounts-service runs. It’s provided
|
||||||
|
* mostly for testing purposes, or to allow an existing connection to be
|
||||||
|
* re-used.
|
||||||
|
*
|
||||||
|
* Since: 0.3.0
|
||||||
|
*/
|
||||||
|
props[PROP_CONNECTION] = g_param_spec_object ("connection",
|
||||||
|
"D-Bus Connection",
|
||||||
|
"A connection to the system bus.",
|
||||||
|
G_TYPE_DBUS_CONNECTION,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
|
G_PARAM_STATIC_STRINGS);
|
||||||
|
|
||||||
|
g_object_class_install_properties (object_class,
|
||||||
|
G_N_ELEMENTS (props),
|
||||||
|
props);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mct_manager_new:
|
||||||
|
* @connection: (transfer none): a #GDBusConnection to use
|
||||||
|
*
|
||||||
|
* Create a new #MctManager.
|
||||||
|
*
|
||||||
|
* Returns: (transfer full): a new #MctManager
|
||||||
|
* Since: 0.3.0
|
||||||
|
*/
|
||||||
|
MctManager *
|
||||||
|
mct_manager_new (GDBusConnection *connection)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
|
||||||
|
|
||||||
|
return g_object_new (MCT_TYPE_MANAGER,
|
||||||
|
"connection", connection,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _mct_app_filter_build_app_filter_variant:
|
||||||
|
* @filter: an #MctAppFilter
|
||||||
|
*
|
||||||
|
* Build a #GVariant which contains the app filter from @filter, in the format
|
||||||
|
* used for storing it in AccountsService.
|
||||||
|
*
|
||||||
|
* Returns: (transfer floating): a new, floating #GVariant containing the app
|
||||||
|
* filter
|
||||||
|
* Since: 0.2.0
|
||||||
|
*/
|
||||||
|
static GVariant *
|
||||||
|
_mct_app_filter_build_app_filter_variant (MctAppFilter *filter)
|
||||||
|
{
|
||||||
|
g_auto(GVariantBuilder) builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE ("(bas)"));
|
||||||
|
|
||||||
|
g_return_val_if_fail (filter != NULL, NULL);
|
||||||
|
g_return_val_if_fail (filter->ref_count >= 1, NULL);
|
||||||
|
|
||||||
|
g_variant_builder_add (&builder, "b",
|
||||||
|
(filter->app_list_type == MCT_APP_FILTER_LIST_WHITELIST));
|
||||||
|
g_variant_builder_open (&builder, G_VARIANT_TYPE ("as"));
|
||||||
|
|
||||||
|
for (gsize i = 0; filter->app_list[i] != NULL; i++)
|
||||||
|
g_variant_builder_add (&builder, "s", filter->app_list[i]);
|
||||||
|
|
||||||
|
g_variant_builder_close (&builder);
|
||||||
|
|
||||||
|
return g_variant_builder_end (&builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if @error is a D-Bus remote error matching @expected_error_name. */
|
||||||
|
static gboolean
|
||||||
|
bus_remote_error_matches (const GError *error,
|
||||||
|
const gchar *expected_error_name)
|
||||||
|
{
|
||||||
|
g_autofree gchar *error_name = NULL;
|
||||||
|
|
||||||
|
if (!g_dbus_error_is_remote_error (error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
error_name = g_dbus_error_get_remote_error (error);
|
||||||
|
|
||||||
|
return g_str_equal (error_name, expected_error_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert a #GDBusError into a #MctAppFilter error. */
|
||||||
|
static GError *
|
||||||
|
bus_error_to_app_filter_error (const GError *bus_error,
|
||||||
|
uid_t user_id)
|
||||||
|
{
|
||||||
|
if (g_error_matches (bus_error, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED) ||
|
||||||
|
bus_remote_error_matches (bus_error, "org.freedesktop.Accounts.Error.PermissionDenied"))
|
||||||
|
return g_error_new (MCT_APP_FILTER_ERROR, MCT_APP_FILTER_ERROR_PERMISSION_DENIED,
|
||||||
|
_("Not allowed to query app filter data for user %u"),
|
||||||
|
(guint) user_id);
|
||||||
|
else if (g_error_matches (bus_error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD) ||
|
||||||
|
bus_remote_error_matches (bus_error, "org.freedesktop.Accounts.Error.Failed"))
|
||||||
|
return g_error_new (MCT_APP_FILTER_ERROR, MCT_APP_FILTER_ERROR_INVALID_USER,
|
||||||
|
_("User %u does not exist"), (guint) user_id);
|
||||||
|
else
|
||||||
|
return g_error_copy (bus_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find the object path for the given @user_id on the accountsservice D-Bus
|
||||||
|
* interface, by calling its FindUserById() method. This is a synchronous,
|
||||||
|
* blocking function. */
|
||||||
|
static gchar *
|
||||||
|
accounts_find_user_by_id (GDBusConnection *connection,
|
||||||
|
uid_t user_id,
|
||||||
|
gboolean allow_interactive_authorization,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_autofree gchar *object_path = NULL;
|
||||||
|
g_autoptr(GVariant) result_variant = NULL;
|
||||||
|
g_autoptr(GError) local_error = NULL;
|
||||||
|
|
||||||
|
result_variant =
|
||||||
|
g_dbus_connection_call_sync (connection,
|
||||||
|
"org.freedesktop.Accounts",
|
||||||
|
"/org/freedesktop/Accounts",
|
||||||
|
"org.freedesktop.Accounts",
|
||||||
|
"FindUserById",
|
||||||
|
g_variant_new ("(x)", (gint64) user_id),
|
||||||
|
G_VARIANT_TYPE ("(o)"),
|
||||||
|
allow_interactive_authorization
|
||||||
|
? G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION
|
||||||
|
: G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
-1, /* timeout, ms */
|
||||||
|
cancellable,
|
||||||
|
&local_error);
|
||||||
|
if (local_error != NULL)
|
||||||
|
{
|
||||||
|
g_autoptr(GError) app_filter_error = bus_error_to_app_filter_error (local_error,
|
||||||
|
user_id);
|
||||||
|
g_propagate_error (error, g_steal_pointer (&app_filter_error));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_variant_get (result_variant, "(o)", &object_path);
|
||||||
|
|
||||||
|
return g_steal_pointer (&object_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mct_manager_get_app_filter:
|
||||||
|
* @self: a #MctManager
|
||||||
|
* @user_id: ID of the user to query, typically coming from getuid()
|
||||||
|
* @flags: flags to affect the behaviour of the call
|
||||||
|
* @cancellable: (nullable): a #GCancellable, or %NULL
|
||||||
|
* @error: return location for a #GError, or %NULL
|
||||||
|
*
|
||||||
|
* Synchronous version of mct_manager_get_app_filter_async().
|
||||||
|
*
|
||||||
|
* Returns: (transfer full): app filter for the queried user
|
||||||
|
* Since: 0.3.0
|
||||||
|
*/
|
||||||
|
MctAppFilter *
|
||||||
|
mct_manager_get_app_filter (MctManager *self,
|
||||||
|
uid_t user_id,
|
||||||
|
MctGetAppFilterFlags flags,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_autofree gchar *object_path = NULL;
|
||||||
|
g_autoptr(GVariant) result_variant = NULL;
|
||||||
|
g_autoptr(GVariant) properties = NULL;
|
||||||
|
g_autoptr(GError) local_error = NULL;
|
||||||
|
g_autoptr(MctAppFilter) app_filter = NULL;
|
||||||
|
gboolean is_whitelist;
|
||||||
|
g_auto(GStrv) app_list = NULL;
|
||||||
|
const gchar *content_rating_kind;
|
||||||
|
g_autoptr(GVariant) oars_variant = NULL;
|
||||||
|
gboolean allow_user_installation;
|
||||||
|
gboolean allow_system_installation;
|
||||||
|
|
||||||
|
g_return_val_if_fail (MCT_IS_MANAGER (self), NULL);
|
||||||
|
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
|
||||||
|
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||||
|
|
||||||
|
object_path = accounts_find_user_by_id (self->connection, user_id,
|
||||||
|
(flags & MCT_GET_APP_FILTER_FLAGS_INTERACTIVE),
|
||||||
|
cancellable, error);
|
||||||
|
if (object_path == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
result_variant =
|
||||||
|
g_dbus_connection_call_sync (self->connection,
|
||||||
|
"org.freedesktop.Accounts",
|
||||||
|
object_path,
|
||||||
|
"org.freedesktop.DBus.Properties",
|
||||||
|
"GetAll",
|
||||||
|
g_variant_new ("(s)", "com.endlessm.ParentalControls.AppFilter"),
|
||||||
|
G_VARIANT_TYPE ("(a{sv})"),
|
||||||
|
(flags & MCT_GET_APP_FILTER_FLAGS_INTERACTIVE)
|
||||||
|
? G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION
|
||||||
|
: G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
-1, /* timeout, ms */
|
||||||
|
cancellable,
|
||||||
|
&local_error);
|
||||||
|
if (local_error != NULL)
|
||||||
|
{
|
||||||
|
g_autoptr(GError) app_filter_error = NULL;
|
||||||
|
|
||||||
|
if (g_error_matches (local_error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS))
|
||||||
|
{
|
||||||
|
/* o.fd.D.GetAll() will return InvalidArgs errors if
|
||||||
|
* accountsservice doesn’t have the com.endlessm.ParentalControls.AppFilter
|
||||||
|
* extension interface installed. */
|
||||||
|
app_filter_error = g_error_new_literal (MCT_APP_FILTER_ERROR,
|
||||||
|
MCT_APP_FILTER_ERROR_DISABLED,
|
||||||
|
_("App filtering is globally disabled"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
app_filter_error = bus_error_to_app_filter_error (local_error,
|
||||||
|
user_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_propagate_error (error, g_steal_pointer (&app_filter_error));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Extract the properties we care about. They may be silently omitted from the
|
||||||
|
* results if we don’t have permission to access them. */
|
||||||
|
properties = g_variant_get_child_value (result_variant, 0);
|
||||||
|
if (!g_variant_lookup (properties, "AppFilter", "(b^as)",
|
||||||
|
&is_whitelist, &app_list))
|
||||||
|
{
|
||||||
|
g_set_error (error, MCT_APP_FILTER_ERROR,
|
||||||
|
MCT_APP_FILTER_ERROR_PERMISSION_DENIED,
|
||||||
|
_("Not allowed to query app filter data for user %u"),
|
||||||
|
(guint) user_id);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_variant_lookup (properties, "OarsFilter", "(&s@a{ss})",
|
||||||
|
&content_rating_kind, &oars_variant))
|
||||||
|
{
|
||||||
|
/* Default value. */
|
||||||
|
content_rating_kind = "oars-1.1";
|
||||||
|
oars_variant = g_variant_new ("a{ss}", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that the OARS filter is in a format we support. Currently, that’s
|
||||||
|
* only oars-1.0 and oars-1.1. */
|
||||||
|
if (!g_str_equal (content_rating_kind, "oars-1.0") &&
|
||||||
|
!g_str_equal (content_rating_kind, "oars-1.1"))
|
||||||
|
{
|
||||||
|
g_set_error (error, MCT_APP_FILTER_ERROR,
|
||||||
|
MCT_APP_FILTER_ERROR_INVALID_DATA,
|
||||||
|
_("OARS filter for user %u has an unrecognized kind ‘%s’"),
|
||||||
|
(guint) user_id, content_rating_kind);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_variant_lookup (properties, "AllowUserInstallation", "b",
|
||||||
|
&allow_user_installation))
|
||||||
|
{
|
||||||
|
/* Default value. */
|
||||||
|
allow_user_installation = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_variant_lookup (properties, "AllowSystemInstallation", "b",
|
||||||
|
&allow_system_installation))
|
||||||
|
{
|
||||||
|
/* Default value. */
|
||||||
|
allow_system_installation = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Success. Create an #MctAppFilter object to contain the results. */
|
||||||
|
app_filter = g_new0 (MctAppFilter, 1);
|
||||||
|
app_filter->ref_count = 1;
|
||||||
|
app_filter->user_id = user_id;
|
||||||
|
app_filter->app_list = g_steal_pointer (&app_list);
|
||||||
|
app_filter->app_list_type =
|
||||||
|
is_whitelist ? MCT_APP_FILTER_LIST_WHITELIST : MCT_APP_FILTER_LIST_BLACKLIST;
|
||||||
|
app_filter->oars_ratings = g_steal_pointer (&oars_variant);
|
||||||
|
app_filter->allow_user_installation = allow_user_installation;
|
||||||
|
app_filter->allow_system_installation = allow_system_installation;
|
||||||
|
|
||||||
|
return g_steal_pointer (&app_filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void get_app_filter_thread_cb (GTask *task,
|
||||||
|
gpointer source_object,
|
||||||
|
gpointer task_data,
|
||||||
|
GCancellable *cancellable);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uid_t user_id;
|
||||||
|
MctGetAppFilterFlags flags;
|
||||||
|
} GetAppFilterData;
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_app_filter_data_free (GetAppFilterData *data)
|
||||||
|
{
|
||||||
|
g_free (data);
|
||||||
|
}
|
||||||
|
|
||||||
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GetAppFilterData, get_app_filter_data_free)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mct_manager_get_app_filter_async:
|
||||||
|
* @self: a #MctManager
|
||||||
|
* @user_id: ID of the user to query, typically coming from getuid()
|
||||||
|
* @flags: flags to affect the behaviour of the call
|
||||||
|
* @cancellable: (nullable): a #GCancellable, or %NULL
|
||||||
|
* @callback: a #GAsyncReadyCallback
|
||||||
|
* @user_data: user data to pass to @callback
|
||||||
|
*
|
||||||
|
* Asynchronously get a snapshot of the app filter settings for the given
|
||||||
|
* @user_id.
|
||||||
|
*
|
||||||
|
* On failure, an #MctAppFilterError, a #GDBusError or a #GIOError will be
|
||||||
|
* returned.
|
||||||
|
*
|
||||||
|
* Since: 0.3.0
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mct_manager_get_app_filter_async (MctManager *self,
|
||||||
|
uid_t user_id,
|
||||||
|
MctGetAppFilterFlags flags,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
g_autoptr(GTask) task = NULL;
|
||||||
|
g_autoptr(GetAppFilterData) data = NULL;
|
||||||
|
|
||||||
|
g_return_if_fail (MCT_IS_MANAGER (self));
|
||||||
|
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||||
|
|
||||||
|
task = g_task_new (self, cancellable, callback, user_data);
|
||||||
|
g_task_set_source_tag (task, mct_manager_get_app_filter_async);
|
||||||
|
|
||||||
|
data = g_new0 (GetAppFilterData, 1);
|
||||||
|
data->user_id = user_id;
|
||||||
|
data->flags = flags;
|
||||||
|
g_task_set_task_data (task, g_steal_pointer (&data),
|
||||||
|
(GDestroyNotify) get_app_filter_data_free);
|
||||||
|
|
||||||
|
g_task_run_in_thread (task, get_app_filter_thread_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_app_filter_thread_cb (GTask *task,
|
||||||
|
gpointer source_object,
|
||||||
|
gpointer task_data,
|
||||||
|
GCancellable *cancellable)
|
||||||
|
{
|
||||||
|
g_autoptr(MctAppFilter) filter = NULL;
|
||||||
|
MctManager *manager = MCT_MANAGER (source_object);
|
||||||
|
GetAppFilterData *data = task_data;
|
||||||
|
g_autoptr(GError) local_error = NULL;
|
||||||
|
|
||||||
|
filter = mct_manager_get_app_filter (manager, data->user_id,
|
||||||
|
data->flags,
|
||||||
|
cancellable, &local_error);
|
||||||
|
|
||||||
|
if (local_error != NULL)
|
||||||
|
g_task_return_error (task, g_steal_pointer (&local_error));
|
||||||
|
else
|
||||||
|
g_task_return_pointer (task, g_steal_pointer (&filter),
|
||||||
|
(GDestroyNotify) mct_app_filter_unref);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mct_manager_get_app_filter_finish:
|
||||||
|
* @self: a #MctManager
|
||||||
|
* @result: a #GAsyncResult
|
||||||
|
* @error: return location for a #GError, or %NULL
|
||||||
|
*
|
||||||
|
* Finish an asynchronous operation to get the app filter for a user, started
|
||||||
|
* with mct_manager_get_app_filter_async().
|
||||||
|
*
|
||||||
|
* Returns: (transfer full): app filter for the queried user
|
||||||
|
* Since: 0.3.0
|
||||||
|
*/
|
||||||
|
MctAppFilter *
|
||||||
|
mct_manager_get_app_filter_finish (MctManager *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (MCT_IS_MANAGER (self), NULL);
|
||||||
|
g_return_val_if_fail (g_task_is_valid (result, self), NULL);
|
||||||
|
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||||
|
|
||||||
|
return g_task_propagate_pointer (G_TASK (result), error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mct_manager_set_app_filter:
|
||||||
|
* @self: a #MctManager
|
||||||
|
* @user_id: ID of the user to set the filter for, typically coming from getuid()
|
||||||
|
* @app_filter: (transfer none): the app filter to set for the user
|
||||||
|
* @flags: flags to affect the behaviour of the call
|
||||||
|
* @cancellable: (nullable): a #GCancellable, or %NULL
|
||||||
|
* @error: return location for a #GError, or %NULL
|
||||||
|
*
|
||||||
|
* Synchronous version of mct_manager_set_app_filter_async().
|
||||||
|
*
|
||||||
|
* Returns: %TRUE on success, %FALSE otherwise
|
||||||
|
* Since: 0.3.0
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
mct_manager_set_app_filter (MctManager *self,
|
||||||
|
uid_t user_id,
|
||||||
|
MctAppFilter *app_filter,
|
||||||
|
MctSetAppFilterFlags flags,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_autofree gchar *object_path = NULL;
|
||||||
|
g_autoptr(GVariant) app_filter_variant = NULL;
|
||||||
|
g_autoptr(GVariant) oars_filter_variant = NULL;
|
||||||
|
g_autoptr(GVariant) allow_user_installation_variant = NULL;
|
||||||
|
g_autoptr(GVariant) allow_system_installation_variant = NULL;
|
||||||
|
g_autoptr(GVariant) app_filter_result_variant = NULL;
|
||||||
|
g_autoptr(GVariant) oars_filter_result_variant = NULL;
|
||||||
|
g_autoptr(GVariant) allow_user_installation_result_variant = NULL;
|
||||||
|
g_autoptr(GVariant) allow_system_installation_result_variant = NULL;
|
||||||
|
g_autoptr(GError) local_error = NULL;
|
||||||
|
g_autoptr(GDBusConnection) connection = NULL;
|
||||||
|
|
||||||
|
g_return_val_if_fail (MCT_IS_MANAGER (self), FALSE);
|
||||||
|
g_return_val_if_fail (app_filter != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (app_filter->ref_count >= 1, FALSE);
|
||||||
|
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
|
||||||
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||||
|
|
||||||
|
object_path = accounts_find_user_by_id (self->connection, user_id,
|
||||||
|
(flags & MCT_SET_APP_FILTER_FLAGS_INTERACTIVE),
|
||||||
|
cancellable, error);
|
||||||
|
if (object_path == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
app_filter_variant = _mct_app_filter_build_app_filter_variant (app_filter);
|
||||||
|
oars_filter_variant = g_variant_new ("(s@a{ss})", "oars-1.1",
|
||||||
|
app_filter->oars_ratings);
|
||||||
|
allow_user_installation_variant = g_variant_new_boolean (app_filter->allow_user_installation);
|
||||||
|
allow_system_installation_variant = g_variant_new_boolean (app_filter->allow_system_installation);
|
||||||
|
|
||||||
|
app_filter_result_variant =
|
||||||
|
g_dbus_connection_call_sync (self->connection,
|
||||||
|
"org.freedesktop.Accounts",
|
||||||
|
object_path,
|
||||||
|
"org.freedesktop.DBus.Properties",
|
||||||
|
"Set",
|
||||||
|
g_variant_new ("(ssv)",
|
||||||
|
"com.endlessm.ParentalControls.AppFilter",
|
||||||
|
"AppFilter",
|
||||||
|
g_steal_pointer (&app_filter_variant)),
|
||||||
|
G_VARIANT_TYPE ("()"),
|
||||||
|
(flags & MCT_SET_APP_FILTER_FLAGS_INTERACTIVE)
|
||||||
|
? G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION
|
||||||
|
: G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
-1, /* timeout, ms */
|
||||||
|
cancellable,
|
||||||
|
&local_error);
|
||||||
|
if (local_error != NULL)
|
||||||
|
{
|
||||||
|
g_propagate_error (error, bus_error_to_app_filter_error (local_error, user_id));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
oars_filter_result_variant =
|
||||||
|
g_dbus_connection_call_sync (self->connection,
|
||||||
|
"org.freedesktop.Accounts",
|
||||||
|
object_path,
|
||||||
|
"org.freedesktop.DBus.Properties",
|
||||||
|
"Set",
|
||||||
|
g_variant_new ("(ssv)",
|
||||||
|
"com.endlessm.ParentalControls.AppFilter",
|
||||||
|
"OarsFilter",
|
||||||
|
g_steal_pointer (&oars_filter_variant)),
|
||||||
|
G_VARIANT_TYPE ("()"),
|
||||||
|
(flags & MCT_SET_APP_FILTER_FLAGS_INTERACTIVE)
|
||||||
|
? G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION
|
||||||
|
: G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
-1, /* timeout, ms */
|
||||||
|
cancellable,
|
||||||
|
&local_error);
|
||||||
|
if (local_error != NULL)
|
||||||
|
{
|
||||||
|
g_propagate_error (error, bus_error_to_app_filter_error (local_error, user_id));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
allow_user_installation_result_variant =
|
||||||
|
g_dbus_connection_call_sync (self->connection,
|
||||||
|
"org.freedesktop.Accounts",
|
||||||
|
object_path,
|
||||||
|
"org.freedesktop.DBus.Properties",
|
||||||
|
"Set",
|
||||||
|
g_variant_new ("(ssv)",
|
||||||
|
"com.endlessm.ParentalControls.AppFilter",
|
||||||
|
"AllowUserInstallation",
|
||||||
|
g_steal_pointer (&allow_user_installation_variant)),
|
||||||
|
G_VARIANT_TYPE ("()"),
|
||||||
|
(flags & MCT_SET_APP_FILTER_FLAGS_INTERACTIVE)
|
||||||
|
? G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION
|
||||||
|
: G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
-1, /* timeout, ms */
|
||||||
|
cancellable,
|
||||||
|
&local_error);
|
||||||
|
if (local_error != NULL)
|
||||||
|
{
|
||||||
|
g_propagate_error (error, bus_error_to_app_filter_error (local_error, user_id));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
allow_system_installation_result_variant =
|
||||||
|
g_dbus_connection_call_sync (self->connection,
|
||||||
|
"org.freedesktop.Accounts",
|
||||||
|
object_path,
|
||||||
|
"org.freedesktop.DBus.Properties",
|
||||||
|
"Set",
|
||||||
|
g_variant_new ("(ssv)",
|
||||||
|
"com.endlessm.ParentalControls.AppFilter",
|
||||||
|
"AllowSystemInstallation",
|
||||||
|
g_steal_pointer (&allow_system_installation_variant)),
|
||||||
|
G_VARIANT_TYPE ("()"),
|
||||||
|
(flags & MCT_SET_APP_FILTER_FLAGS_INTERACTIVE)
|
||||||
|
? G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION
|
||||||
|
: G_DBUS_CALL_FLAGS_NONE,
|
||||||
|
-1, /* timeout, ms */
|
||||||
|
cancellable,
|
||||||
|
&local_error);
|
||||||
|
if (local_error != NULL)
|
||||||
|
{
|
||||||
|
g_propagate_error (error, bus_error_to_app_filter_error (local_error, user_id));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_app_filter_thread_cb (GTask *task,
|
||||||
|
gpointer source_object,
|
||||||
|
gpointer task_data,
|
||||||
|
GCancellable *cancellable);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uid_t user_id;
|
||||||
|
MctAppFilter *app_filter; /* (owned) */
|
||||||
|
MctSetAppFilterFlags flags;
|
||||||
|
} SetAppFilterData;
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_app_filter_data_free (SetAppFilterData *data)
|
||||||
|
{
|
||||||
|
mct_app_filter_unref (data->app_filter);
|
||||||
|
g_free (data);
|
||||||
|
}
|
||||||
|
|
||||||
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (SetAppFilterData, set_app_filter_data_free)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mct_manager_set_app_filter_async:
|
||||||
|
* @self: a #MctManager
|
||||||
|
* @user_id: ID of the user to set the filter for, typically coming from getuid()
|
||||||
|
* @app_filter: (transfer none): the app filter to set for the user
|
||||||
|
* @flags: flags to affect the behaviour of the call
|
||||||
|
* @cancellable: (nullable): a #GCancellable, or %NULL
|
||||||
|
* @callback: a #GAsyncReadyCallback
|
||||||
|
* @user_data: user data to pass to @callback
|
||||||
|
*
|
||||||
|
* Asynchronously set the app filter settings for the given @user_id to the
|
||||||
|
* given @app_filter instance. This will set all fields of the app filter.
|
||||||
|
*
|
||||||
|
* On failure, an #MctAppFilterError, a #GDBusError or a #GIOError will be
|
||||||
|
* returned. The user’s app filter settings will be left in an undefined state.
|
||||||
|
*
|
||||||
|
* Since: 0.3.0
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mct_manager_set_app_filter_async (MctManager *self,
|
||||||
|
uid_t user_id,
|
||||||
|
MctAppFilter *app_filter,
|
||||||
|
MctSetAppFilterFlags flags,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
g_autoptr(GTask) task = NULL;
|
||||||
|
g_autoptr(SetAppFilterData) data = NULL;
|
||||||
|
|
||||||
|
g_return_if_fail (MCT_IS_MANAGER (self));
|
||||||
|
g_return_if_fail (app_filter != NULL);
|
||||||
|
g_return_if_fail (app_filter->ref_count >= 1);
|
||||||
|
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||||
|
|
||||||
|
task = g_task_new (self, cancellable, callback, user_data);
|
||||||
|
g_task_set_source_tag (task, mct_manager_set_app_filter_async);
|
||||||
|
|
||||||
|
data = g_new0 (SetAppFilterData, 1);
|
||||||
|
data->user_id = user_id;
|
||||||
|
data->app_filter = mct_app_filter_ref (app_filter);
|
||||||
|
data->flags = flags;
|
||||||
|
g_task_set_task_data (task, g_steal_pointer (&data),
|
||||||
|
(GDestroyNotify) set_app_filter_data_free);
|
||||||
|
|
||||||
|
g_task_run_in_thread (task, set_app_filter_thread_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_app_filter_thread_cb (GTask *task,
|
||||||
|
gpointer source_object,
|
||||||
|
gpointer task_data,
|
||||||
|
GCancellable *cancellable)
|
||||||
|
{
|
||||||
|
gboolean success;
|
||||||
|
MctManager *manager = MCT_MANAGER (source_object);
|
||||||
|
SetAppFilterData *data = task_data;
|
||||||
|
g_autoptr(GError) local_error = NULL;
|
||||||
|
|
||||||
|
success = mct_manager_set_app_filter (manager, data->user_id,
|
||||||
|
data->app_filter, data->flags,
|
||||||
|
cancellable, &local_error);
|
||||||
|
|
||||||
|
if (local_error != NULL)
|
||||||
|
g_task_return_error (task, g_steal_pointer (&local_error));
|
||||||
|
else
|
||||||
|
g_task_return_boolean (task, success);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mct_manager_set_app_filter_finish:
|
||||||
|
* @self: a #MctManager
|
||||||
|
* @result: a #GAsyncResult
|
||||||
|
* @error: return location for a #GError, or %NULL
|
||||||
|
*
|
||||||
|
* Finish an asynchronous operation to set the app filter for a user, started
|
||||||
|
* with mct_manager_set_app_filter_async().
|
||||||
|
*
|
||||||
|
* Returns: %TRUE on success, %FALSE otherwise
|
||||||
|
* Since: 0.3.0
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
mct_manager_set_app_filter_finish (MctManager *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (MCT_IS_MANAGER (self), FALSE);
|
||||||
|
g_return_val_if_fail (g_task_is_valid (result, self), FALSE);
|
||||||
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||||
|
|
||||||
|
return g_task_propagate_boolean (G_TASK (result), error);
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||||
|
*
|
||||||
|
* Copyright © 2019 Endless Mobile, Inc.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* - Philip Withnall <withnall@endlessm.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <gio/gio.h>
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <libmalcontent/app-filter.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MctGetAppFilterFlags:
|
||||||
|
* @MCT_GET_APP_FILTER_FLAGS_NONE: No flags set.
|
||||||
|
* @MCT_GET_APP_FILTER_FLAGS_INTERACTIVE: Allow interactive polkit dialogs when
|
||||||
|
* requesting authorization.
|
||||||
|
*
|
||||||
|
* Flags to control the behaviour of mct_manager_get_app_filter() and
|
||||||
|
* mct_manager_get_app_filter_async().
|
||||||
|
*
|
||||||
|
* Since: 0.3.0
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
MCT_GET_APP_FILTER_FLAGS_NONE = 0,
|
||||||
|
MCT_GET_APP_FILTER_FLAGS_INTERACTIVE,
|
||||||
|
} MctGetAppFilterFlags;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MctSetAppFilterFlags:
|
||||||
|
* @MCT_SET_APP_FILTER_FLAGS_NONE: No flags set.
|
||||||
|
* @MCT_SET_APP_FILTER_FLAGS_INTERACTIVE: Allow interactive polkit dialogs when
|
||||||
|
* requesting authorization.
|
||||||
|
*
|
||||||
|
* Flags to control the behaviour of mct_manager_set_app_filter() and
|
||||||
|
* mct_manager_set_app_filter_async().
|
||||||
|
*
|
||||||
|
* Since: 0.3.0
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
MCT_SET_APP_FILTER_FLAGS_NONE = 0,
|
||||||
|
MCT_SET_APP_FILTER_FLAGS_INTERACTIVE,
|
||||||
|
} MctSetAppFilterFlags;
|
||||||
|
|
||||||
|
#define MCT_TYPE_MANAGER mct_manager_get_type ()
|
||||||
|
G_DECLARE_FINAL_TYPE (MctManager, mct_manager, MCT, MANAGER, GObject)
|
||||||
|
|
||||||
|
MctManager *mct_manager_new (GDBusConnection *connection);
|
||||||
|
|
||||||
|
MctAppFilter *mct_manager_get_app_filter (MctManager *self,
|
||||||
|
uid_t user_id,
|
||||||
|
MctGetAppFilterFlags flags,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error);
|
||||||
|
void mct_manager_get_app_filter_async (MctManager *self,
|
||||||
|
uid_t user_id,
|
||||||
|
MctGetAppFilterFlags flags,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
|
MctAppFilter *mct_manager_get_app_filter_finish (MctManager *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
gboolean mct_manager_set_app_filter (MctManager *self,
|
||||||
|
uid_t user_id,
|
||||||
|
MctAppFilter *app_filter,
|
||||||
|
MctSetAppFilterFlags flags,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GError **error);
|
||||||
|
void mct_manager_set_app_filter_async (MctManager *self,
|
||||||
|
uid_t user_id,
|
||||||
|
MctAppFilter *app_filter,
|
||||||
|
MctSetAppFilterFlags flags,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
|
gboolean mct_manager_set_app_filter_finish (MctManager *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
G_END_DECLS
|
|
@ -2,9 +2,14 @@ libmalcontent_api_version = '0'
|
||||||
libmalcontent_api_name = 'malcontent-' + libmalcontent_api_version
|
libmalcontent_api_name = 'malcontent-' + libmalcontent_api_version
|
||||||
libmalcontent_sources = [
|
libmalcontent_sources = [
|
||||||
'app-filter.c',
|
'app-filter.c',
|
||||||
|
'manager.c',
|
||||||
]
|
]
|
||||||
libmalcontent_headers = [
|
libmalcontent_headers = [
|
||||||
'app-filter.h',
|
'app-filter.h',
|
||||||
|
'manager.h',
|
||||||
|
]
|
||||||
|
libmalcontent_private_headers = [
|
||||||
|
'app-filter-private.h',
|
||||||
]
|
]
|
||||||
|
|
||||||
libmalcontent_public_deps = [
|
libmalcontent_public_deps = [
|
||||||
|
@ -20,7 +25,7 @@ libmalcontent_private_deps = [
|
||||||
libmalcontent_include_subdir = join_paths(libmalcontent_api_name, 'libmalcontent')
|
libmalcontent_include_subdir = join_paths(libmalcontent_api_name, 'libmalcontent')
|
||||||
|
|
||||||
libmalcontent = library(libmalcontent_api_name,
|
libmalcontent = library(libmalcontent_api_name,
|
||||||
libmalcontent_sources + libmalcontent_headers,
|
libmalcontent_sources + libmalcontent_headers + libmalcontent_private_headers,
|
||||||
dependencies: libmalcontent_public_deps + libmalcontent_private_deps,
|
dependencies: libmalcontent_public_deps + libmalcontent_private_deps,
|
||||||
include_directories: root_inc,
|
include_directories: root_inc,
|
||||||
install: true,
|
install: true,
|
||||||
|
@ -49,7 +54,7 @@ pkgconfig.generate(
|
||||||
)
|
)
|
||||||
|
|
||||||
gnome.generate_gir(libmalcontent,
|
gnome.generate_gir(libmalcontent,
|
||||||
sources: libmalcontent_sources + libmalcontent_headers,
|
sources: libmalcontent_sources + libmalcontent_headers + libmalcontent_private_headers,
|
||||||
nsversion: libmalcontent_api_version,
|
nsversion: libmalcontent_api_version,
|
||||||
namespace: 'Malcontent',
|
namespace: 'Malcontent',
|
||||||
symbol_prefix: 'mct_',
|
symbol_prefix: 'mct_',
|
||||||
|
@ -57,6 +62,7 @@ gnome.generate_gir(libmalcontent,
|
||||||
export_packages: 'libmalcontent',
|
export_packages: 'libmalcontent',
|
||||||
includes: ['GObject-2.0', 'Gio-2.0'],
|
includes: ['GObject-2.0', 'Gio-2.0'],
|
||||||
install: true,
|
install: true,
|
||||||
|
dependencies: libmalcontent_dep,
|
||||||
)
|
)
|
||||||
|
|
||||||
subdir('tests')
|
subdir('tests')
|
|
@ -26,6 +26,7 @@
|
||||||
#include <gio/gdesktopappinfo.h>
|
#include <gio/gdesktopappinfo.h>
|
||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
#include <libmalcontent/app-filter.h>
|
#include <libmalcontent/app-filter.h>
|
||||||
|
#include <libmalcontent/manager.h>
|
||||||
#include <libglib-testing/dbus-queue.h>
|
#include <libglib-testing/dbus-queue.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -422,6 +423,7 @@ typedef struct
|
||||||
GtDBusQueue *queue; /* (owned) */
|
GtDBusQueue *queue; /* (owned) */
|
||||||
uid_t valid_uid;
|
uid_t valid_uid;
|
||||||
uid_t missing_uid;
|
uid_t missing_uid;
|
||||||
|
MctManager *manager; /* (owned) */
|
||||||
} BusFixture;
|
} BusFixture;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -452,12 +454,15 @@ bus_set_up (BusFixture *fixture,
|
||||||
(GDBusInterfaceInfo *) &accounts_interface_info,
|
(GDBusInterfaceInfo *) &accounts_interface_info,
|
||||||
&local_error);
|
&local_error);
|
||||||
g_assert_no_error (local_error);
|
g_assert_no_error (local_error);
|
||||||
|
|
||||||
|
fixture->manager = mct_manager_new (gt_dbus_queue_get_client_connection (fixture->queue));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bus_tear_down (BusFixture *fixture,
|
bus_tear_down (BusFixture *fixture,
|
||||||
gconstpointer test_data)
|
gconstpointer test_data)
|
||||||
{
|
{
|
||||||
|
g_clear_object (&fixture->manager);
|
||||||
gt_dbus_queue_disconnect (fixture->queue, TRUE);
|
gt_dbus_queue_disconnect (fixture->queue, TRUE);
|
||||||
g_clear_pointer (&fixture->queue, gt_dbus_queue_free);
|
g_clear_pointer (&fixture->queue, gt_dbus_queue_free);
|
||||||
}
|
}
|
||||||
|
@ -477,7 +482,7 @@ async_result_cb (GObject *obj,
|
||||||
/* Generic mock accountsservice implementation which returns the properties
|
/* Generic mock accountsservice implementation which returns the properties
|
||||||
* given in #GetAppFilterData.properties if queried for a UID matching
|
* given in #GetAppFilterData.properties if queried for a UID matching
|
||||||
* #GetAppFilterData.expected_uid. Intended to be used for writing ‘successful’
|
* #GetAppFilterData.expected_uid. Intended to be used for writing ‘successful’
|
||||||
* mct_get_app_filter() tests returning a variety of values. */
|
* mct_manager_get_app_filter() tests returning a variety of values. */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uid_t expected_uid;
|
uid_t expected_uid;
|
||||||
|
@ -553,21 +558,21 @@ test_app_filter_bus_get (BusFixture *fixture,
|
||||||
{
|
{
|
||||||
g_autoptr(GAsyncResult) result = NULL;
|
g_autoptr(GAsyncResult) result = NULL;
|
||||||
|
|
||||||
mct_get_app_filter_async (gt_dbus_queue_get_client_connection (fixture->queue),
|
mct_manager_get_app_filter_async (fixture->manager,
|
||||||
fixture->valid_uid,
|
fixture->valid_uid,
|
||||||
MCT_GET_APP_FILTER_FLAGS_NONE, NULL,
|
MCT_GET_APP_FILTER_FLAGS_NONE, NULL,
|
||||||
async_result_cb, &result);
|
async_result_cb, &result);
|
||||||
|
|
||||||
while (result == NULL)
|
while (result == NULL)
|
||||||
g_main_context_iteration (NULL, TRUE);
|
g_main_context_iteration (NULL, TRUE);
|
||||||
app_filter = mct_get_app_filter_finish (result, &local_error);
|
app_filter = mct_manager_get_app_filter_finish (fixture->manager, result, &local_error);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
app_filter = mct_get_app_filter (gt_dbus_queue_get_client_connection (fixture->queue),
|
app_filter = mct_manager_get_app_filter (fixture->manager,
|
||||||
fixture->valid_uid,
|
fixture->valid_uid,
|
||||||
MCT_GET_APP_FILTER_FLAGS_NONE, NULL,
|
MCT_GET_APP_FILTER_FLAGS_NONE, NULL,
|
||||||
&local_error);
|
&local_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_assert_no_error (local_error);
|
g_assert_no_error (local_error);
|
||||||
|
@ -608,10 +613,10 @@ test_app_filter_bus_get_whitelist (BusFixture *fixture,
|
||||||
gt_dbus_queue_set_server_func (fixture->queue, get_app_filter_server_cb,
|
gt_dbus_queue_set_server_func (fixture->queue, get_app_filter_server_cb,
|
||||||
(gpointer) &get_app_filter_data);
|
(gpointer) &get_app_filter_data);
|
||||||
|
|
||||||
app_filter = mct_get_app_filter (gt_dbus_queue_get_client_connection (fixture->queue),
|
app_filter = mct_manager_get_app_filter (fixture->manager,
|
||||||
fixture->valid_uid,
|
fixture->valid_uid,
|
||||||
MCT_GET_APP_FILTER_FLAGS_NONE, NULL,
|
MCT_GET_APP_FILTER_FLAGS_NONE, NULL,
|
||||||
&local_error);
|
&local_error);
|
||||||
|
|
||||||
g_assert_no_error (local_error);
|
g_assert_no_error (local_error);
|
||||||
g_assert_nonnull (app_filter);
|
g_assert_nonnull (app_filter);
|
||||||
|
@ -659,10 +664,10 @@ test_app_filter_bus_get_all_oars_values (BusFixture *fixture,
|
||||||
gt_dbus_queue_set_server_func (fixture->queue, get_app_filter_server_cb,
|
gt_dbus_queue_set_server_func (fixture->queue, get_app_filter_server_cb,
|
||||||
(gpointer) &get_app_filter_data);
|
(gpointer) &get_app_filter_data);
|
||||||
|
|
||||||
app_filter = mct_get_app_filter (gt_dbus_queue_get_client_connection (fixture->queue),
|
app_filter = mct_manager_get_app_filter (fixture->manager,
|
||||||
fixture->valid_uid,
|
fixture->valid_uid,
|
||||||
MCT_GET_APP_FILTER_FLAGS_NONE, NULL,
|
MCT_GET_APP_FILTER_FLAGS_NONE, NULL,
|
||||||
&local_error);
|
&local_error);
|
||||||
|
|
||||||
g_assert_no_error (local_error);
|
g_assert_no_error (local_error);
|
||||||
g_assert_nonnull (app_filter);
|
g_assert_nonnull (app_filter);
|
||||||
|
@ -707,10 +712,10 @@ test_app_filter_bus_get_defaults (BusFixture *fixture,
|
||||||
gt_dbus_queue_set_server_func (fixture->queue, get_app_filter_server_cb,
|
gt_dbus_queue_set_server_func (fixture->queue, get_app_filter_server_cb,
|
||||||
(gpointer) &get_app_filter_data);
|
(gpointer) &get_app_filter_data);
|
||||||
|
|
||||||
app_filter = mct_get_app_filter (gt_dbus_queue_get_client_connection (fixture->queue),
|
app_filter = mct_manager_get_app_filter (fixture->manager,
|
||||||
fixture->valid_uid,
|
fixture->valid_uid,
|
||||||
MCT_GET_APP_FILTER_FLAGS_NONE, NULL,
|
MCT_GET_APP_FILTER_FLAGS_NONE, NULL,
|
||||||
&local_error);
|
&local_error);
|
||||||
|
|
||||||
g_assert_no_error (local_error);
|
g_assert_no_error (local_error);
|
||||||
g_assert_nonnull (app_filter);
|
g_assert_nonnull (app_filter);
|
||||||
|
@ -725,8 +730,8 @@ test_app_filter_bus_get_defaults (BusFixture *fixture,
|
||||||
g_assert_false (mct_app_filter_is_system_installation_allowed (app_filter));
|
g_assert_false (mct_app_filter_is_system_installation_allowed (app_filter));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test that mct_get_app_filter() returns an appropriate error if the mock D-Bus
|
/* Test that mct_manager_get_app_filter() returns an appropriate error if the
|
||||||
* service reports that the given user cannot be found.
|
* mock D-Bus service reports that the given user cannot be found.
|
||||||
*
|
*
|
||||||
* The mock D-Bus replies are generated inline. */
|
* The mock D-Bus replies are generated inline. */
|
||||||
static void
|
static void
|
||||||
|
@ -739,10 +744,10 @@ test_app_filter_bus_get_error_invalid_user (BusFixture *fixture,
|
||||||
g_autofree gchar *error_message = NULL;
|
g_autofree gchar *error_message = NULL;
|
||||||
g_autoptr(MctAppFilter) app_filter = NULL;
|
g_autoptr(MctAppFilter) app_filter = NULL;
|
||||||
|
|
||||||
mct_get_app_filter_async (gt_dbus_queue_get_client_connection (fixture->queue),
|
mct_manager_get_app_filter_async (fixture->manager,
|
||||||
fixture->missing_uid,
|
fixture->missing_uid,
|
||||||
MCT_GET_APP_FILTER_FLAGS_NONE, NULL,
|
MCT_GET_APP_FILTER_FLAGS_NONE, NULL,
|
||||||
async_result_cb, &result);
|
async_result_cb, &result);
|
||||||
|
|
||||||
/* Handle the FindUserById() call and claim the user doesn’t exist. */
|
/* Handle the FindUserById() call and claim the user doesn’t exist. */
|
||||||
gint64 user_id;
|
gint64 user_id;
|
||||||
|
@ -761,16 +766,17 @@ test_app_filter_bus_get_error_invalid_user (BusFixture *fixture,
|
||||||
/* Get the get_app_filter() result. */
|
/* Get the get_app_filter() result. */
|
||||||
while (result == NULL)
|
while (result == NULL)
|
||||||
g_main_context_iteration (NULL, TRUE);
|
g_main_context_iteration (NULL, TRUE);
|
||||||
app_filter = mct_get_app_filter_finish (result, &local_error);
|
app_filter = mct_manager_get_app_filter_finish (fixture->manager, result,
|
||||||
|
&local_error);
|
||||||
|
|
||||||
g_assert_error (local_error,
|
g_assert_error (local_error,
|
||||||
MCT_APP_FILTER_ERROR, MCT_APP_FILTER_ERROR_INVALID_USER);
|
MCT_APP_FILTER_ERROR, MCT_APP_FILTER_ERROR_INVALID_USER);
|
||||||
g_assert_null (app_filter);
|
g_assert_null (app_filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test that mct_get_app_filter() returns an appropriate error if the mock D-Bus
|
/* Test that mct_manager_get_app_filter() returns an appropriate error if the
|
||||||
* service reports that the properties of the given user can’t be accessed due
|
* mock D-Bus service reports that the properties of the given user can’t be
|
||||||
* to permissions.
|
* accessed due to permissions.
|
||||||
*
|
*
|
||||||
* The mock D-Bus replies are generated inline. */
|
* The mock D-Bus replies are generated inline. */
|
||||||
static void
|
static void
|
||||||
|
@ -784,10 +790,10 @@ test_app_filter_bus_get_error_permission_denied (BusFixture *fixture,
|
||||||
g_autofree gchar *object_path = NULL;
|
g_autofree gchar *object_path = NULL;
|
||||||
g_autoptr(MctAppFilter) app_filter = NULL;
|
g_autoptr(MctAppFilter) app_filter = NULL;
|
||||||
|
|
||||||
mct_get_app_filter_async (gt_dbus_queue_get_client_connection (fixture->queue),
|
mct_manager_get_app_filter_async (fixture->manager,
|
||||||
fixture->valid_uid,
|
fixture->valid_uid,
|
||||||
MCT_GET_APP_FILTER_FLAGS_NONE, NULL,
|
MCT_GET_APP_FILTER_FLAGS_NONE, NULL,
|
||||||
async_result_cb, &result);
|
async_result_cb, &result);
|
||||||
|
|
||||||
/* Handle the FindUserById() call. */
|
/* Handle the FindUserById() call. */
|
||||||
gint64 user_id;
|
gint64 user_id;
|
||||||
|
@ -817,16 +823,17 @@ test_app_filter_bus_get_error_permission_denied (BusFixture *fixture,
|
||||||
/* Get the get_app_filter() result. */
|
/* Get the get_app_filter() result. */
|
||||||
while (result == NULL)
|
while (result == NULL)
|
||||||
g_main_context_iteration (NULL, TRUE);
|
g_main_context_iteration (NULL, TRUE);
|
||||||
app_filter = mct_get_app_filter_finish (result, &local_error);
|
app_filter = mct_manager_get_app_filter_finish (fixture->manager, result,
|
||||||
|
&local_error);
|
||||||
|
|
||||||
g_assert_error (local_error,
|
g_assert_error (local_error,
|
||||||
MCT_APP_FILTER_ERROR, MCT_APP_FILTER_ERROR_PERMISSION_DENIED);
|
MCT_APP_FILTER_ERROR, MCT_APP_FILTER_ERROR_PERMISSION_DENIED);
|
||||||
g_assert_null (app_filter);
|
g_assert_null (app_filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test that mct_get_app_filter() returns an appropriate error if the mock D-Bus
|
/* Test that mct_manager_get_app_filter() returns an appropriate error if the
|
||||||
* service replies with no app filter properties (implying that it hasn’t sent
|
* mock D-Bus service replies with no app filter properties (implying that it
|
||||||
* the property values because of permissions).
|
* hasn’t sent the property values because of permissions).
|
||||||
*
|
*
|
||||||
* The mock D-Bus replies are generated inline. */
|
* The mock D-Bus replies are generated inline. */
|
||||||
static void
|
static void
|
||||||
|
@ -840,10 +847,10 @@ test_app_filter_bus_get_error_permission_denied_missing (BusFixture *fixture,
|
||||||
g_autofree gchar *object_path = NULL;
|
g_autofree gchar *object_path = NULL;
|
||||||
g_autoptr(MctAppFilter) app_filter = NULL;
|
g_autoptr(MctAppFilter) app_filter = NULL;
|
||||||
|
|
||||||
mct_get_app_filter_async (gt_dbus_queue_get_client_connection (fixture->queue),
|
mct_manager_get_app_filter_async (fixture->manager,
|
||||||
fixture->valid_uid,
|
fixture->valid_uid,
|
||||||
MCT_GET_APP_FILTER_FLAGS_NONE, NULL,
|
MCT_GET_APP_FILTER_FLAGS_NONE, NULL,
|
||||||
async_result_cb, &result);
|
async_result_cb, &result);
|
||||||
|
|
||||||
/* Handle the FindUserById() call. */
|
/* Handle the FindUserById() call. */
|
||||||
gint64 user_id;
|
gint64 user_id;
|
||||||
|
@ -874,15 +881,16 @@ test_app_filter_bus_get_error_permission_denied_missing (BusFixture *fixture,
|
||||||
/* Get the get_app_filter() result. */
|
/* Get the get_app_filter() result. */
|
||||||
while (result == NULL)
|
while (result == NULL)
|
||||||
g_main_context_iteration (NULL, TRUE);
|
g_main_context_iteration (NULL, TRUE);
|
||||||
app_filter = mct_get_app_filter_finish (result, &local_error);
|
app_filter = mct_manager_get_app_filter_finish (fixture->manager, result,
|
||||||
|
&local_error);
|
||||||
|
|
||||||
g_assert_error (local_error,
|
g_assert_error (local_error,
|
||||||
MCT_APP_FILTER_ERROR, MCT_APP_FILTER_ERROR_PERMISSION_DENIED);
|
MCT_APP_FILTER_ERROR, MCT_APP_FILTER_ERROR_PERMISSION_DENIED);
|
||||||
g_assert_null (app_filter);
|
g_assert_null (app_filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test that mct_get_app_filter() returns an error if the mock D-Bus service
|
/* Test that mct_manager_get_app_filter() returns an error if the mock D-Bus
|
||||||
* reports an unrecognised error.
|
* service reports an unrecognised error.
|
||||||
*
|
*
|
||||||
* The mock D-Bus replies are generated inline. */
|
* The mock D-Bus replies are generated inline. */
|
||||||
static void
|
static void
|
||||||
|
@ -894,10 +902,10 @@ test_app_filter_bus_get_error_unknown (BusFixture *fixture,
|
||||||
g_autoptr(GDBusMethodInvocation) invocation = NULL;
|
g_autoptr(GDBusMethodInvocation) invocation = NULL;
|
||||||
g_autoptr(MctAppFilter) app_filter = NULL;
|
g_autoptr(MctAppFilter) app_filter = NULL;
|
||||||
|
|
||||||
mct_get_app_filter_async (gt_dbus_queue_get_client_connection (fixture->queue),
|
mct_manager_get_app_filter_async (fixture->manager,
|
||||||
fixture->valid_uid,
|
fixture->valid_uid,
|
||||||
MCT_GET_APP_FILTER_FLAGS_NONE, NULL,
|
MCT_GET_APP_FILTER_FLAGS_NONE, NULL,
|
||||||
async_result_cb, &result);
|
async_result_cb, &result);
|
||||||
|
|
||||||
/* Handle the FindUserById() call and return a bogus error. */
|
/* Handle the FindUserById() call and return a bogus error. */
|
||||||
gint64 user_id;
|
gint64 user_id;
|
||||||
|
@ -918,16 +926,17 @@ test_app_filter_bus_get_error_unknown (BusFixture *fixture,
|
||||||
/* Get the get_app_filter() result. */
|
/* Get the get_app_filter() result. */
|
||||||
while (result == NULL)
|
while (result == NULL)
|
||||||
g_main_context_iteration (NULL, TRUE);
|
g_main_context_iteration (NULL, TRUE);
|
||||||
app_filter = mct_get_app_filter_finish (result, &local_error);
|
app_filter = mct_manager_get_app_filter_finish (fixture->manager, result,
|
||||||
|
&local_error);
|
||||||
|
|
||||||
/* We don’t actually care what error is actually used here. */
|
/* We don’t actually care what error is actually used here. */
|
||||||
g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR);
|
g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR);
|
||||||
g_assert_null (app_filter);
|
g_assert_null (app_filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test that mct_get_app_filter() returns an error if the mock D-Bus service
|
/* Test that mct_manager_get_app_filter() returns an error if the mock D-Bus
|
||||||
* reports an unknown interface, which means that parental controls are not
|
* service reports an unknown interface, which means that parental controls are
|
||||||
* installed properly.
|
* not installed properly.
|
||||||
*
|
*
|
||||||
* The mock D-Bus replies are generated inline. */
|
* The mock D-Bus replies are generated inline. */
|
||||||
static void
|
static void
|
||||||
|
@ -941,10 +950,10 @@ test_app_filter_bus_get_error_disabled (BusFixture *fixture,
|
||||||
g_autofree gchar *object_path = NULL;
|
g_autofree gchar *object_path = NULL;
|
||||||
g_autoptr(MctAppFilter) app_filter = NULL;
|
g_autoptr(MctAppFilter) app_filter = NULL;
|
||||||
|
|
||||||
mct_get_app_filter_async (gt_dbus_queue_get_client_connection (fixture->queue),
|
mct_manager_get_app_filter_async (fixture->manager,
|
||||||
fixture->valid_uid,
|
fixture->valid_uid,
|
||||||
MCT_GET_APP_FILTER_FLAGS_NONE, NULL,
|
MCT_GET_APP_FILTER_FLAGS_NONE, NULL,
|
||||||
async_result_cb, &result);
|
async_result_cb, &result);
|
||||||
|
|
||||||
/* Handle the FindUserById() call. */
|
/* Handle the FindUserById() call. */
|
||||||
gint64 user_id;
|
gint64 user_id;
|
||||||
|
@ -975,7 +984,8 @@ test_app_filter_bus_get_error_disabled (BusFixture *fixture,
|
||||||
/* Get the get_app_filter() result. */
|
/* Get the get_app_filter() result. */
|
||||||
while (result == NULL)
|
while (result == NULL)
|
||||||
g_main_context_iteration (NULL, TRUE);
|
g_main_context_iteration (NULL, TRUE);
|
||||||
app_filter = mct_get_app_filter_finish (result, &local_error);
|
app_filter = mct_manager_get_app_filter_finish (fixture->manager, result,
|
||||||
|
&local_error);
|
||||||
|
|
||||||
g_assert_error (local_error,
|
g_assert_error (local_error,
|
||||||
MCT_APP_FILTER_ERROR, MCT_APP_FILTER_ERROR_DISABLED);
|
MCT_APP_FILTER_ERROR, MCT_APP_FILTER_ERROR_DISABLED);
|
||||||
|
@ -1132,29 +1142,30 @@ test_app_filter_bus_set (BusFixture *fixture,
|
||||||
{
|
{
|
||||||
g_autoptr(GAsyncResult) result = NULL;
|
g_autoptr(GAsyncResult) result = NULL;
|
||||||
|
|
||||||
mct_set_app_filter_async (gt_dbus_queue_get_client_connection (fixture->queue),
|
mct_manager_set_app_filter_async (fixture->manager,
|
||||||
fixture->valid_uid, app_filter,
|
fixture->valid_uid, app_filter,
|
||||||
MCT_SET_APP_FILTER_FLAGS_NONE, NULL,
|
MCT_SET_APP_FILTER_FLAGS_NONE, NULL,
|
||||||
async_result_cb, &result);
|
async_result_cb, &result);
|
||||||
|
|
||||||
while (result == NULL)
|
while (result == NULL)
|
||||||
g_main_context_iteration (NULL, TRUE);
|
g_main_context_iteration (NULL, TRUE);
|
||||||
success = mct_set_app_filter_finish (result, &local_error);
|
success = mct_manager_set_app_filter_finish (fixture->manager, result,
|
||||||
|
&local_error);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
success = mct_set_app_filter (gt_dbus_queue_get_client_connection (fixture->queue),
|
success = mct_manager_set_app_filter (fixture->manager,
|
||||||
fixture->valid_uid, app_filter,
|
fixture->valid_uid, app_filter,
|
||||||
MCT_SET_APP_FILTER_FLAGS_NONE, NULL,
|
MCT_SET_APP_FILTER_FLAGS_NONE, NULL,
|
||||||
&local_error);
|
&local_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_assert_no_error (local_error);
|
g_assert_no_error (local_error);
|
||||||
g_assert_true (success);
|
g_assert_true (success);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test that mct_set_app_filter() returns an appropriate error if the mock D-Bus
|
/* Test that mct_manager__set_app_filter() returns an appropriate error if the
|
||||||
* service reports that the given user cannot be found.
|
* mock D-Bus service reports that the given user cannot be found.
|
||||||
*
|
*
|
||||||
* The mock D-Bus replies are generated inline. */
|
* The mock D-Bus replies are generated inline. */
|
||||||
static void
|
static void
|
||||||
|
@ -1172,10 +1183,10 @@ test_app_filter_bus_set_error_invalid_user (BusFixture *fixture,
|
||||||
/* Use the default app filter. */
|
/* Use the default app filter. */
|
||||||
app_filter = mct_app_filter_builder_end (&builder);
|
app_filter = mct_app_filter_builder_end (&builder);
|
||||||
|
|
||||||
mct_set_app_filter_async (gt_dbus_queue_get_client_connection (fixture->queue),
|
mct_manager_set_app_filter_async (fixture->manager,
|
||||||
fixture->missing_uid, app_filter,
|
fixture->missing_uid, app_filter,
|
||||||
MCT_SET_APP_FILTER_FLAGS_NONE, NULL,
|
MCT_SET_APP_FILTER_FLAGS_NONE, NULL,
|
||||||
async_result_cb, &result);
|
async_result_cb, &result);
|
||||||
|
|
||||||
/* Handle the FindUserById() call and claim the user doesn’t exist. */
|
/* Handle the FindUserById() call and claim the user doesn’t exist. */
|
||||||
gint64 user_id;
|
gint64 user_id;
|
||||||
|
@ -1194,15 +1205,17 @@ test_app_filter_bus_set_error_invalid_user (BusFixture *fixture,
|
||||||
/* Get the set_app_filter() result. */
|
/* Get the set_app_filter() result. */
|
||||||
while (result == NULL)
|
while (result == NULL)
|
||||||
g_main_context_iteration (NULL, TRUE);
|
g_main_context_iteration (NULL, TRUE);
|
||||||
success = mct_set_app_filter_finish (result, &local_error);
|
success = mct_manager_set_app_filter_finish (fixture->manager, result,
|
||||||
|
&local_error);
|
||||||
|
|
||||||
g_assert_error (local_error,
|
g_assert_error (local_error,
|
||||||
MCT_APP_FILTER_ERROR, MCT_APP_FILTER_ERROR_INVALID_USER);
|
MCT_APP_FILTER_ERROR, MCT_APP_FILTER_ERROR_INVALID_USER);
|
||||||
g_assert_false (success);
|
g_assert_false (success);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test that mct_set_app_filter() returns an appropriate error if the mock D-Bus
|
/* Test that mct_manager_set_app_filter() returns an appropriate error if the
|
||||||
* service replies with a permission denied error when setting properties.
|
* mock D-Bus service replies with a permission denied error when setting
|
||||||
|
* properties.
|
||||||
*
|
*
|
||||||
* The mock D-Bus replies are generated in set_app_filter_server_cb(). */
|
* The mock D-Bus replies are generated in set_app_filter_server_cb(). */
|
||||||
static void
|
static void
|
||||||
|
@ -1227,18 +1240,18 @@ test_app_filter_bus_set_error_permission_denied (BusFixture *fixture,
|
||||||
gt_dbus_queue_set_server_func (fixture->queue, set_app_filter_server_cb,
|
gt_dbus_queue_set_server_func (fixture->queue, set_app_filter_server_cb,
|
||||||
(gpointer) &set_app_filter_data);
|
(gpointer) &set_app_filter_data);
|
||||||
|
|
||||||
success = mct_set_app_filter (gt_dbus_queue_get_client_connection (fixture->queue),
|
success = mct_manager_set_app_filter (fixture->manager,
|
||||||
fixture->valid_uid, app_filter,
|
fixture->valid_uid, app_filter,
|
||||||
MCT_SET_APP_FILTER_FLAGS_NONE, NULL,
|
MCT_SET_APP_FILTER_FLAGS_NONE, NULL,
|
||||||
&local_error);
|
&local_error);
|
||||||
|
|
||||||
g_assert_error (local_error,
|
g_assert_error (local_error,
|
||||||
MCT_APP_FILTER_ERROR, MCT_APP_FILTER_ERROR_PERMISSION_DENIED);
|
MCT_APP_FILTER_ERROR, MCT_APP_FILTER_ERROR_PERMISSION_DENIED);
|
||||||
g_assert_false (success);
|
g_assert_false (success);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test that mct_set_app_filter() returns an error if the mock D-Bus service
|
/* Test that mct_manager_set_app_filter() returns an error if the mock D-Bus
|
||||||
* reports an unrecognised error.
|
* service reports an unrecognised error.
|
||||||
*
|
*
|
||||||
* The mock D-Bus replies are generated in set_app_filter_server_cb(). */
|
* The mock D-Bus replies are generated in set_app_filter_server_cb(). */
|
||||||
static void
|
static void
|
||||||
|
@ -1265,17 +1278,17 @@ test_app_filter_bus_set_error_unknown (BusFixture *fixture,
|
||||||
gt_dbus_queue_set_server_func (fixture->queue, set_app_filter_server_cb,
|
gt_dbus_queue_set_server_func (fixture->queue, set_app_filter_server_cb,
|
||||||
(gpointer) &set_app_filter_data);
|
(gpointer) &set_app_filter_data);
|
||||||
|
|
||||||
success = mct_set_app_filter (gt_dbus_queue_get_client_connection (fixture->queue),
|
success = mct_manager_set_app_filter (fixture->manager,
|
||||||
fixture->valid_uid, app_filter,
|
fixture->valid_uid, app_filter,
|
||||||
MCT_SET_APP_FILTER_FLAGS_NONE, NULL,
|
MCT_SET_APP_FILTER_FLAGS_NONE, NULL,
|
||||||
&local_error);
|
&local_error);
|
||||||
|
|
||||||
g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR);
|
g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR);
|
||||||
g_assert_false (success);
|
g_assert_false (success);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test that mct_set_app_filter() returns an error if the mock D-Bus service
|
/* Test that mct_manager_set_app_filter() returns an error if the mock D-Bus
|
||||||
* reports an InvalidArgs error with a given one of its Set() calls.
|
* service reports an InvalidArgs error with a given one of its Set() calls.
|
||||||
*
|
*
|
||||||
* @test_data contains a property index encoded with GINT_TO_POINTER(),
|
* @test_data contains a property index encoded with GINT_TO_POINTER(),
|
||||||
* indicating which Set() call to return the error on, since the calls are made
|
* indicating which Set() call to return the error on, since the calls are made
|
||||||
|
@ -1308,10 +1321,10 @@ test_app_filter_bus_set_error_invalid_property (BusFixture *fixture,
|
||||||
gt_dbus_queue_set_server_func (fixture->queue, set_app_filter_server_cb,
|
gt_dbus_queue_set_server_func (fixture->queue, set_app_filter_server_cb,
|
||||||
(gpointer) &set_app_filter_data);
|
(gpointer) &set_app_filter_data);
|
||||||
|
|
||||||
success = mct_set_app_filter (gt_dbus_queue_get_client_connection (fixture->queue),
|
success = mct_manager_set_app_filter (fixture->manager,
|
||||||
fixture->valid_uid, app_filter,
|
fixture->valid_uid, app_filter,
|
||||||
MCT_SET_APP_FILTER_FLAGS_NONE, NULL,
|
MCT_SET_APP_FILTER_FLAGS_NONE, NULL,
|
||||||
&local_error);
|
&local_error);
|
||||||
|
|
||||||
g_assert_error (local_error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS);
|
g_assert_error (local_error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS);
|
||||||
g_assert_false (success);
|
g_assert_false (success);
|
||||||
|
|
|
@ -22,7 +22,7 @@ import pwd
|
||||||
import sys
|
import sys
|
||||||
import gi
|
import gi
|
||||||
gi.require_version('Malcontent', '0') # noqa
|
gi.require_version('Malcontent', '0') # noqa
|
||||||
from gi.repository import Malcontent, GLib
|
from gi.repository import Malcontent, GLib, Gio
|
||||||
|
|
||||||
|
|
||||||
# Exit codes, which are a documented part of the API.
|
# Exit codes, which are a documented part of the API.
|
||||||
|
@ -42,8 +42,10 @@ def __get_app_filter(user_id, interactive):
|
||||||
else:
|
else:
|
||||||
flags = Malcontent.GetAppFilterFlags.NONE
|
flags = Malcontent.GetAppFilterFlags.NONE
|
||||||
|
|
||||||
return Malcontent.get_app_filter(
|
connection = Gio.bus_get_sync(Gio.BusType.SYSTEM)
|
||||||
connection=None, user_id=user_id,
|
manager = Malcontent.Manager.new(connection)
|
||||||
|
return manager.get_app_filter(
|
||||||
|
user_id=user_id,
|
||||||
flags=flags, cancellable=None)
|
flags=flags, cancellable=None)
|
||||||
|
|
||||||
|
|
||||||
|
@ -68,8 +70,10 @@ def __set_app_filter(user_id, app_filter, interactive):
|
||||||
else:
|
else:
|
||||||
flags = Malcontent.GetAppFilterFlags.NONE
|
flags = Malcontent.GetAppFilterFlags.NONE
|
||||||
|
|
||||||
Malcontent.set_app_filter(
|
connection = Gio.bus_get_sync(Gio.BusType.SYSTEM)
|
||||||
connection=None, user_id=user_id, app_filter=app_filter,
|
manager = Malcontent.Manager.new(connection)
|
||||||
|
manager.set_app_filter(
|
||||||
|
user_id=user_id, app_filter=app_filter,
|
||||||
flags=flags, cancellable=None)
|
flags=flags, cancellable=None)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue