summaryrefslogtreecommitdiffstats
path: root/gnome-initial-setup/pages/parental-controls/gis-parental-controls-page.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnome-initial-setup/pages/parental-controls/gis-parental-controls-page.c')
-rw-r--r--gnome-initial-setup/pages/parental-controls/gis-parental-controls-page.c246
1 files changed, 246 insertions, 0 deletions
diff --git a/gnome-initial-setup/pages/parental-controls/gis-parental-controls-page.c b/gnome-initial-setup/pages/parental-controls/gis-parental-controls-page.c
new file mode 100644
index 0000000..736194d
--- /dev/null
+++ b/gnome-initial-setup/pages/parental-controls/gis-parental-controls-page.c
@@ -0,0 +1,246 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright © 2020 Endless Mobile, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Written by:
+ * Philip Withnall <withnall@endlessm.com>
+ */
+
+/* Parental controls page {{{1 */
+
+#define PAGE_ID "parental-controls"
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib-object.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gtk/gtk.h>
+#include <libmalcontent-ui/malcontent-ui.h>
+
+#include "parental-controls-resources.h"
+#include "gis-page-header.h"
+#include "gis-parental-controls-page.h"
+
+struct _GisParentalControlsPage
+{
+ GisPage parent_instance;
+
+ GtkWidget *header;
+ GtkWidget *user_controls;
+};
+
+G_DEFINE_TYPE (GisParentalControlsPage, gis_parental_controls_page, GIS_TYPE_PAGE)
+
+static gboolean
+gis_parental_controls_page_save_data (GisPage *gis_page,
+ GError **error)
+{
+ GisParentalControlsPage *page = GIS_PARENTAL_CONTROLS_PAGE (gis_page);
+ g_autoptr(GDBusConnection) system_bus = NULL;
+ g_autoptr(MctManager) manager = NULL;
+ g_auto(MctAppFilterBuilder) builder = MCT_APP_FILTER_BUILDER_INIT ();
+ g_autoptr(MctAppFilter) app_filter = NULL;
+ ActUser *main_user;
+
+ /* The parent and child users are created by the #GisAccountPage earlier in
+ * the save_data() process. We now need to set the parental controls on the
+ * child user. The earlier step in the process must have succeeded. */
+ gis_driver_get_user_permissions (gis_page->driver, &main_user, NULL);
+ g_return_val_if_fail (main_user != NULL, FALSE);
+
+ mct_user_controls_build_app_filter (MCT_USER_CONTROLS (page->user_controls), &builder);
+ app_filter = mct_app_filter_builder_end (&builder);
+
+ /* FIXME: should become asynchronous */
+ system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
+ if (system_bus == NULL)
+ return FALSE;
+
+ manager = mct_manager_new (system_bus);
+ if (!mct_manager_set_app_filter (manager,
+ act_user_get_uid (main_user),
+ app_filter,
+ MCT_MANAGER_SET_VALUE_FLAGS_NONE,
+ NULL,
+ error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+gis_parental_controls_page_shown (GisPage *gis_page)
+{
+ GisParentalControlsPage *page = GIS_PARENTAL_CONTROLS_PAGE (gis_page);
+
+ gtk_widget_grab_focus (page->user_controls);
+}
+
+static void
+update_header (GisParentalControlsPage *page)
+{
+ g_autofree gchar *title = NULL;
+ const gchar *subtitle, *icon_name;
+ GdkPaintable *paintable;
+
+ /* Translators: The placeholder is the user’s full name. */
+ title = g_strdup_printf (_("Parental Controls for %s"),
+ gis_driver_get_full_name (GIS_PAGE (page)->driver));
+ subtitle = _("Set restrictions on what this user can run or install.");
+ paintable = gis_driver_get_avatar (GIS_PAGE (page)->driver);
+ icon_name = (paintable != NULL) ? NULL : "dialog-password-symbolic";
+
+ g_object_set (G_OBJECT (page->header),
+ "title", title,
+ "subtitle", subtitle,
+ NULL);
+ if (paintable != NULL)
+ g_object_set (G_OBJECT (page->header), "paintable", paintable, NULL);
+ else if (icon_name != NULL)
+ g_object_set (G_OBJECT (page->header), "icon-name", icon_name, NULL);
+}
+
+static void
+update_user_controls (GisParentalControlsPage *page)
+{
+ mct_user_controls_set_user_locale (MCT_USER_CONTROLS (page->user_controls),
+ gis_driver_get_user_language (GIS_PAGE (page)->driver));
+ mct_user_controls_set_user_display_name (MCT_USER_CONTROLS (page->user_controls),
+ gis_driver_get_full_name (GIS_PAGE (page)->driver));
+}
+
+static void
+user_details_changed_cb (GObject *obj,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ GisParentalControlsPage *page = GIS_PARENTAL_CONTROLS_PAGE (user_data);
+
+ update_user_controls (page);
+ update_header (page);
+}
+
+static void
+gis_parental_controls_page_constructed (GObject *object)
+{
+ GisParentalControlsPage *page = GIS_PARENTAL_CONTROLS_PAGE (object);
+ g_autoptr(GPermission) permission = NULL;
+ g_auto(MctAppFilterBuilder) builder = MCT_APP_FILTER_BUILDER_INIT ();
+ g_autoptr(MctAppFilter) app_filter = NULL;
+
+ G_OBJECT_CLASS (gis_parental_controls_page_parent_class)->constructed (object);
+
+ /* No validation needed. */
+ gis_page_set_complete (GIS_PAGE (page), TRUE);
+
+ /* Set up the user controls. We can’t set #MctUserControls:user because
+ * there’s no way to represent a not-yet-created user using an #ActUser. */
+ mct_user_controls_set_user_account_type (MCT_USER_CONTROLS (page->user_controls),
+ ACT_USER_ACCOUNT_TYPE_STANDARD);
+ update_user_controls (page);
+
+ app_filter = mct_app_filter_builder_end (&builder);
+ mct_user_controls_set_app_filter (MCT_USER_CONTROLS (page->user_controls), app_filter);
+
+ /* The gnome-initial-setup user should always be allowed to set parental
+ * controls. */
+ permission = g_simple_permission_new (TRUE);
+ mct_user_controls_set_permission (MCT_USER_CONTROLS (page->user_controls), permission);
+
+ /* Connect to signals. */
+ g_signal_connect (GIS_PAGE (page)->driver, "notify::full-name",
+ G_CALLBACK (user_details_changed_cb), page);
+ g_signal_connect (GIS_PAGE (page)->driver, "notify::avatar",
+ G_CALLBACK (user_details_changed_cb), page);
+ g_signal_connect (GIS_PAGE (page)->driver, "notify::user-locale",
+ G_CALLBACK (user_details_changed_cb), page);
+ g_signal_connect (GIS_PAGE (page)->driver, "notify::user-display-name",
+ G_CALLBACK (user_details_changed_cb), page);
+
+ update_header (page);
+
+ gtk_widget_show (GTK_WIDGET (page));
+}
+
+static void
+gis_parental_controls_page_dispose (GObject *object)
+{
+ GisParentalControlsPage *page = GIS_PARENTAL_CONTROLS_PAGE (object);
+
+ if (GIS_PAGE (object)->driver != NULL)
+ {
+ g_signal_handlers_disconnect_by_func (GIS_PAGE (page)->driver,
+ user_details_changed_cb, page);
+ }
+
+ G_OBJECT_CLASS (gis_parental_controls_page_parent_class)->dispose (object);
+}
+
+static void
+gis_parental_controls_page_locale_changed (GisPage *gis_page)
+{
+ GisParentalControlsPage *page = GIS_PARENTAL_CONTROLS_PAGE (gis_page);
+
+ gis_page_set_title (gis_page, _("Parental Controls"));
+ update_header (page);
+}
+
+static void
+gis_parental_controls_page_class_init (GisParentalControlsPageClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GisPageClass *page_class = GIS_PAGE_CLASS (klass);
+
+ object_class->constructed = gis_parental_controls_page_constructed;
+ object_class->dispose = gis_parental_controls_page_dispose;
+
+ page_class->page_id = PAGE_ID;
+ page_class->locale_changed = gis_parental_controls_page_locale_changed;
+ page_class->save_data = gis_parental_controls_page_save_data;
+ page_class->shown = gis_parental_controls_page_shown;
+
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/initial-setup/gis-parental-controls-page.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, GisParentalControlsPage, header);
+ gtk_widget_class_bind_template_child (widget_class, GisParentalControlsPage, user_controls);
+}
+
+static void
+gis_parental_controls_page_init (GisParentalControlsPage *page)
+{
+ g_resources_register (parental_controls_get_resource ());
+
+ /* Ensure types exist for widgets in the UI file. */
+ g_type_ensure (GIS_TYPE_PAGE_HEADER);
+ g_type_ensure (MCT_TYPE_USER_CONTROLS);
+
+ gtk_widget_init_template (GTK_WIDGET (page));
+}
+
+GisPage *
+gis_prepare_parental_controls_page (GisDriver *driver)
+{
+ /* Skip parental controls if they’re not enabled. */
+ if (!gis_driver_get_parental_controls_enabled (driver))
+ return NULL;
+
+ return g_object_new (GIS_TYPE_PARENTAL_CONTROLS_PAGE,
+ "driver", driver,
+ NULL);
+}