gnome-initial-setup/0005-driver-Specify-mode-via-flags-instead-of-boolean.patch
2023-08-28 17:49:18 -04:00

634 lines
20 KiB
Diff

From f5de1beabc325dc20090d02d85088dfb7f3a0584 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Sun, 13 Aug 2023 09:09:56 -0400
Subject: [PATCH 05/11] driver: Specify mode via flags instead of boolean
At the moment we just have system mode and new user mode,
but we're actually going to want other modes (such as
live user mode) as well.
Currently the code distinguishes between its two available
modes using a boolean `is_new_user`. That isn't extensible beyond
two modes, so this commit changes it use bit flags instead.
---
gnome-initial-setup/gis-driver.c | 17 ++-
gnome-initial-setup/gis-driver.h | 8 +-
gnome-initial-setup/gnome-initial-setup.c | 128 +++++++++++++---------
3 files changed, 93 insertions(+), 60 deletions(-)
diff --git a/gnome-initial-setup/gis-driver.c b/gnome-initial-setup/gis-driver.c
index 98b4fc3e..d3013063 100644
--- a/gnome-initial-setup/gis-driver.c
+++ b/gnome-initial-setup/gis-driver.c
@@ -9,75 +9,74 @@
*
* 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:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#include "config.h"
#include "gnome-initial-setup.h"
#include <errno.h>
#include <locale.h>
#include <stdlib.h>
#ifdef HAVE_WEBKITGTK_6_0
#include <webkit/webkit.h>
#else
#include <webkit2/webkit2.h>
#endif
#include "cc-common-language.h"
#include "gis-assistant.h"
-#define GIS_TYPE_DRIVER_MODE (gis_driver_mode_get_type ())
-
/* Statically include this for now. Maybe later
* we'll generate this from glib-mkenums. */
GType
gis_driver_mode_get_type (void) {
static GType enum_type_id = 0;
if (G_UNLIKELY (!enum_type_id))
{
- static const GEnumValue values[] = {
+ static const GFlagsValue values[] = {
{ GIS_DRIVER_MODE_NEW_USER, "GIS_DRIVER_MODE_NEW_USER", "new_user" },
{ GIS_DRIVER_MODE_EXISTING_USER, "GIS_DRIVER_MODE_EXISTING_USER", "existing_user" },
+ { GIS_DRIVER_MODE_ALL, "GIS_DRIVER_MODE_ALL", "all" },
{ 0, NULL, NULL }
};
- enum_type_id = g_enum_register_static("GisDriverMode", values);
+ enum_type_id = g_flags_register_static("GisDriverMode", values);
}
return enum_type_id;
}
enum {
REBUILD_PAGES,
LOCALE_CHANGED,
LAST_SIGNAL,
};
static guint signals[LAST_SIGNAL];
typedef enum {
PROP_MODE = 1,
PROP_USERNAME,
PROP_SMALL_SCREEN,
PROP_PARENTAL_CONTROLS_ENABLED,
PROP_FULL_NAME,
PROP_AVATAR,
} GisDriverProperty;
static GParamSpec *obj_props[PROP_AVATAR + 1];
struct _GisDriver {
AdwApplication parent_instance;
GtkWindow *main_window;
GisAssistant *assistant;
GdmClient *client;
@@ -624,61 +623,61 @@ gis_driver_get_property (GObject *object,
break;
case PROP_SMALL_SCREEN:
g_value_set_boolean (value, driver->small_screen);
break;
case PROP_PARENTAL_CONTROLS_ENABLED:
g_value_set_boolean (value, driver->parental_controls_enabled);
break;
case PROP_FULL_NAME:
g_value_set_string (value, driver->full_name);
break;
case PROP_AVATAR:
g_value_set_object (value, driver->avatar);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gis_driver_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GisDriver *driver = GIS_DRIVER (object);
switch ((GisDriverProperty) prop_id)
{
case PROP_MODE:
- driver->mode = g_value_get_enum (value);
+ driver->mode = g_value_get_flags (value);
break;
case PROP_USERNAME:
g_free (driver->username);
driver->username = g_value_dup_string (value);
break;
case PROP_PARENTAL_CONTROLS_ENABLED:
gis_driver_set_parental_controls_enabled (driver, g_value_get_boolean (value));
break;
case PROP_FULL_NAME:
gis_driver_set_full_name (driver, g_value_get_string (value));
break;
case PROP_AVATAR:
gis_driver_set_avatar (driver, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gis_driver_activate (GApplication *app)
{
GisDriver *driver = GIS_DRIVER (app);
G_APPLICATION_CLASS (gis_driver_parent_class)->activate (app);
gtk_window_present (GTK_WINDOW (driver->main_window));
}
@@ -826,64 +825,64 @@ gis_driver_init (GisDriver *driver)
static void
gis_driver_class_init (GisDriverClass *klass)
{
GApplicationClass *application_class = G_APPLICATION_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->get_property = gis_driver_get_property;
gobject_class->set_property = gis_driver_set_property;
gobject_class->dispose = gis_driver_dispose;
gobject_class->finalize = gis_driver_finalize;
application_class->startup = gis_driver_startup;
application_class->activate = gis_driver_activate;
signals[REBUILD_PAGES] =
g_signal_new ("rebuild-pages",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 0);
signals[LOCALE_CHANGED] =
g_signal_new ("locale-changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 0);
obj_props[PROP_MODE] =
- g_param_spec_enum ("mode", "", "",
- GIS_TYPE_DRIVER_MODE,
- GIS_DRIVER_MODE_EXISTING_USER,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+ g_param_spec_flags ("mode", "", "",
+ GIS_TYPE_DRIVER_MODE,
+ GIS_DRIVER_MODE_EXISTING_USER,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
obj_props[PROP_USERNAME] =
g_param_spec_string ("username", "", "",
NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
obj_props[PROP_SMALL_SCREEN] =
g_param_spec_boolean ("small-screen", "", "",
FALSE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
/**
* GisDriver:parental-controls-enabled:
*
* Whether parental controls are enabled for the main user. If this is %TRUE,
* two user accounts will be created when this page is saved: one for the main
* user (a child) which will be a standard account; and one for the parent
* which will be an administrative account.
*
* Since: 3.36
*/
obj_props[PROP_PARENTAL_CONTROLS_ENABLED] =
g_param_spec_boolean ("parental-controls-enabled",
"Parental Controls Enabled",
"Whether parental controls are enabled for the main user.",
FALSE,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
/**
* GisDriver:full-name: (nullable)
diff --git a/gnome-initial-setup/gis-driver.h b/gnome-initial-setup/gis-driver.h
index 9b935e24..b57db2e2 100644
--- a/gnome-initial-setup/gis-driver.h
+++ b/gnome-initial-setup/gis-driver.h
@@ -4,74 +4,78 @@
*
* 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:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef __GIS_DRIVER_H__
#define __GIS_DRIVER_H__
#include "gis-assistant.h"
#include "gis-page.h"
#include <act/act-user-manager.h>
#include <gdm/gdm-client.h>
#include <adwaita.h>
G_BEGIN_DECLS
#define GIS_TYPE_DRIVER (gis_driver_get_type ())
+#define GIS_TYPE_DRIVER_MODE (gis_driver_mode_get_type ())
G_DECLARE_FINAL_TYPE (GisDriver, gis_driver, GIS, DRIVER, AdwApplication)
typedef enum {
UM_LOCAL,
UM_ENTERPRISE,
NUM_MODES,
} UmAccountMode;
typedef enum {
- GIS_DRIVER_MODE_NEW_USER,
- GIS_DRIVER_MODE_EXISTING_USER,
+ GIS_DRIVER_MODE_NEW_USER = 1 << 0,
+ GIS_DRIVER_MODE_EXISTING_USER = 1 << 1,
+ GIS_DRIVER_MODE_ALL = (GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER),
} GisDriverMode;
+GType gis_driver_mode_get_type (void);
+
GisAssistant *gis_driver_get_assistant (GisDriver *driver);
void gis_driver_set_user_permissions (GisDriver *driver,
ActUser *user,
const gchar *password);
void gis_driver_get_user_permissions (GisDriver *driver,
ActUser **user,
const gchar **password);
void gis_driver_set_parent_permissions (GisDriver *driver,
ActUser *parent,
const gchar *password);
void gis_driver_get_parent_permissions (GisDriver *driver,
ActUser **parent,
const gchar **password);
void gis_driver_set_account_mode (GisDriver *driver,
UmAccountMode mode);
UmAccountMode gis_driver_get_account_mode (GisDriver *driver);
void gis_driver_set_parental_controls_enabled (GisDriver *driver,
gboolean parental_controls_enabled);
gboolean gis_driver_get_parental_controls_enabled (GisDriver *driver);
void gis_driver_set_user_language (GisDriver *driver,
const gchar *lang_id,
diff --git a/gnome-initial-setup/gnome-initial-setup.c b/gnome-initial-setup/gnome-initial-setup.c
index 113ded36..59955779 100644
--- a/gnome-initial-setup/gnome-initial-setup.c
+++ b/gnome-initial-setup/gnome-initial-setup.c
@@ -29,228 +29,258 @@
#include <stdlib.h>
#include <glib/gi18n.h>
#include "pages/welcome/gis-welcome-page.h"
#include "pages/language/gis-language-page.h"
#include "pages/keyboard/gis-keyboard-page.h"
#include "pages/network/gis-network-page.h"
#include "pages/timezone/gis-timezone-page.h"
#include "pages/privacy/gis-privacy-page.h"
#include "pages/software/gis-software-page.h"
#include "pages/goa/gis-goa-page.h"
#include "pages/account/gis-account-pages.h"
#include "pages/parental-controls/gis-parental-controls-page.h"
#include "pages/password/gis-password-page.h"
#include "pages/summary/gis-summary-page.h"
#define VENDOR_PAGES_GROUP "pages"
#define VENDOR_SKIP_KEY "skip"
#define VENDOR_NEW_USER_ONLY_KEY "new_user_only"
#define VENDOR_EXISTING_USER_ONLY_KEY "existing_user_only"
static gboolean force_existing_user_mode;
static GPtrArray *skipped_pages;
typedef GisPage *(*PreparePage) (GisDriver *driver);
typedef struct {
const gchar *page_id;
PreparePage prepare_page_func;
- gboolean new_user_only;
+ GisDriverMode modes;
} PageData;
-#define PAGE(name, new_user_only) { #name, gis_prepare_ ## name ## _page, new_user_only }
+#define PAGE(name, modes) { #name, gis_prepare_ ## name ## _page, modes }
static PageData page_table[] = {
- PAGE (welcome, FALSE),
- PAGE (language, FALSE),
- PAGE (keyboard, FALSE),
- PAGE (network, FALSE),
- PAGE (privacy, FALSE),
- PAGE (timezone, TRUE),
- PAGE (software, TRUE),
- PAGE (goa, FALSE),
- PAGE (account, TRUE),
- PAGE (password, TRUE),
+ PAGE (welcome, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER),
+ PAGE (language, GIS_DRIVER_MODE_ALL),
+ PAGE (keyboard, GIS_DRIVER_MODE_ALL),
+ PAGE (network, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER),
+ PAGE (privacy, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER),
+ PAGE (timezone, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER),
+ PAGE (software, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER),
+ PAGE (goa, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER),
+ PAGE (account, GIS_DRIVER_MODE_NEW_USER),
+ PAGE (password, GIS_DRIVER_MODE_NEW_USER),
#ifdef HAVE_PARENTAL_CONTROLS
- PAGE (parental_controls, TRUE),
- PAGE (parent_password, TRUE),
+ PAGE (parental_controls, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER),
+ PAGE (parent_password, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER),
#endif
- PAGE (summary, FALSE),
+ PAGE (summary, GIS_DRIVER_MODE_NEW_USER),
{ NULL },
};
#undef PAGE
static gboolean
should_skip_page (const gchar *page_id,
gchar **skip_pages)
{
guint i = 0;
/* special case welcome. We only want to show it if language
* is skipped
*/
if (strcmp (page_id, "welcome") == 0)
return !should_skip_page ("language", skip_pages);
/* check through our skip pages list for pages we don't want */
if (skip_pages) {
while (skip_pages[i]) {
if (g_strcmp0 (skip_pages[i], page_id) == 0)
return TRUE;
i++;
}
}
return FALSE;
}
static gchar **
-strv_append (gchar **a,
- gchar **b)
+pages_to_skip_from_file (GisDriver *driver)
{
- guint n = g_strv_length (a);
- guint m = g_strv_length (b);
-
- a = g_renew (gchar *, a, n + m + 1);
- for (guint i = 0; i < m; i++)
- a[n + i] = g_strdup (b[i]);
- a[n + m] = NULL;
-
- return a;
-}
-
-static gchar **
-pages_to_skip_from_file (GisDriver *driver,
- gboolean is_new_user)
-{
- GStrv skip_pages = NULL;
- GStrv additional_skip_pages = NULL;
+ GisDriverMode driver_mode;
+ GisDriverMode other_modes;
+ g_autoptr(GStrvBuilder) builder = g_strv_builder_new();
+ g_auto (GStrv) skip_pages = NULL;
+ g_autofree char *mode_group = NULL;
+ g_autoptr (GFlagsClass) driver_mode_flags_class = NULL;
+ const GFlagsValue *driver_mode_flags = NULL;
/* This code will read the keyfile containing vendor customization options and
* look for options under the "pages" group, and supports the following keys:
* - skip (optional): list of pages to be skipped always
* - new_user_only (optional): list of pages to be skipped in existing user mode
* - existing_user_only (optional): list of pages to be skipped in new user mode
*
+ * In addition it will look for options under the "{mode} pages" group where {mode} is the
+ * current driver mode for the following keys:
+ * - skip (optional): list of pages to be skipped for the current mode
+ *
* This is how this file might look on a vendor image:
*
* [pages]
* skip=timezone
+ *
+ * [new_user pages]
+ * skip=language;keyboard
+ *
+ * Older files might look like so:
+ *
+ * [pages]
+ * skip=timezone
* existing_user_only=language;keyboard
*/
skip_pages = gis_driver_conf_get_string_list (driver, VENDOR_PAGES_GROUP,
VENDOR_SKIP_KEY, NULL);
- additional_skip_pages =
- gis_driver_conf_get_string_list (driver, VENDOR_PAGES_GROUP,
- is_new_user ? VENDOR_EXISTING_USER_ONLY_KEY : VENDOR_NEW_USER_ONLY_KEY,
- NULL);
-
- if (!skip_pages && additional_skip_pages) {
- skip_pages = additional_skip_pages;
- } else if (skip_pages && additional_skip_pages) {
- skip_pages = strv_append (skip_pages, additional_skip_pages);
- g_strfreev (additional_skip_pages);
+ if (skip_pages != NULL)
+ {
+ g_strv_builder_addv (builder, (const char **) skip_pages);
+ g_clear_pointer (&skip_pages, g_strfreev);
+ }
+
+ driver_mode_flags_class = g_type_class_ref (GIS_TYPE_DRIVER_MODE);
+
+ driver_mode = gis_driver_get_mode (driver);
+ driver_mode_flags = g_flags_get_first_value (driver_mode_flags_class, driver_mode);
+
+ mode_group = g_strdup_printf ("%s pages", driver_mode_flags->value_nick);
+ skip_pages = gis_driver_conf_get_string_list (driver, mode_group,
+ VENDOR_SKIP_KEY, NULL);
+ if (skip_pages != NULL)
+ {
+ g_strv_builder_addv (builder, (const char **) skip_pages);
+ g_clear_pointer (&skip_pages, g_strfreev);
+ }
+
+ other_modes = GIS_DRIVER_MODE_ALL & ~driver_mode;
+ while (other_modes) {
+ const GFlagsValue *other_mode_flags = g_flags_get_first_value (driver_mode_flags_class, other_modes);
+
+ if (other_mode_flags != NULL) {
+ g_autofree char *vendor_key = g_strdup_printf ("%s_only", other_mode_flags->value_nick);
+
+ skip_pages = gis_driver_conf_get_string_list (driver, VENDOR_PAGES_GROUP,
+ vendor_key, NULL);
+
+ if (skip_pages != NULL)
+ {
+ g_strv_builder_addv (builder, (const char **) skip_pages);
+ g_clear_pointer (&skip_pages, g_strfreev);
+ }
+
+ other_modes &= ~other_mode_flags->value;
+ }
}
- return skip_pages;
+ return g_strv_builder_end (builder);
}
static void
destroy_pages_after (GisAssistant *assistant,
GisPage *page)
{
GList *pages, *l, *next;
pages = gis_assistant_get_all_pages (assistant);
for (l = pages; l != NULL; l = l->next)
if (l->data == page)
break;
l = l->next;
for (; l != NULL; l = next) {
next = l->next;
gis_assistant_remove_page (assistant, l->data);
}
}
static void
destroy_page (gpointer data)
{
GtkWidget *assistant;
GisPage *page;
page = data;
assistant = gtk_widget_get_ancestor (GTK_WIDGET (page), GIS_TYPE_ASSISTANT);
if (assistant)
gis_assistant_remove_page (GIS_ASSISTANT (assistant), page);
}
static void
rebuild_pages_cb (GisDriver *driver)
{
PageData *page_data;
GisPage *page;
GisAssistant *assistant;
GisPage *current_page;
gchar **skip_pages;
- gboolean is_new_user, skipped;
+ GisDriverMode driver_mode;
+ gboolean skipped;
assistant = gis_driver_get_assistant (driver);
current_page = gis_assistant_get_current_page (assistant);
page_data = page_table;
g_ptr_array_free (skipped_pages, TRUE);
skipped_pages = g_ptr_array_new_with_free_func (destroy_page);
if (current_page != NULL) {
destroy_pages_after (assistant, current_page);
for (page_data = page_table; page_data->page_id != NULL; ++page_data)
if (g_str_equal (page_data->page_id, GIS_PAGE_GET_CLASS (current_page)->page_id))
break;
++page_data;
}
- is_new_user = (gis_driver_get_mode (driver) == GIS_DRIVER_MODE_NEW_USER);
- skip_pages = pages_to_skip_from_file (driver, is_new_user);
+ driver_mode = gis_driver_get_mode (driver);
+ skip_pages = pages_to_skip_from_file (driver);
for (; page_data->page_id != NULL; ++page_data) {
skipped = FALSE;
- if ((page_data->new_user_only && !is_new_user) ||
+ if (((page_data->modes & driver_mode) == 0) ||
(should_skip_page (page_data->page_id, skip_pages)))
skipped = TRUE;
page = page_data->prepare_page_func (driver);
if (!page)
continue;
if (skipped) {
gis_page_skip (page);
g_ptr_array_add (skipped_pages, page);
} else {
gis_driver_add_page (driver, page);
}
}
g_strfreev (skip_pages);
}
static GisDriverMode
get_mode (void)
{
if (force_existing_user_mode)
return GIS_DRIVER_MODE_EXISTING_USER;
else
return GIS_DRIVER_MODE_NEW_USER;
}
static gboolean
initial_setup_disabled_by_anaconda (void)
{
--
2.41.0.rc2