gnome-initial-setup/0006-gnome-initial-setup-Add-live-user-mode.patch
2023-09-10 20:20:10 -04:00

1784 lines
63 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From 026a99057ae42b6aee41e8be486c56c63bbaeb43 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Sun, 13 Aug 2023 09:39:07 -0400
Subject: [PATCH 6/9] gnome-initial-setup: Add live user mode
This commit adds a new "live user" mode meant to be run in live image
environments.
It asks questions the user should answer before the installer is
started, and provides a way for the user to initiate the installer
or just jump into the live session instead.
---
data/20-gnome-initial-setup.rules.in | 3 +-
gnome-initial-setup/gis-driver.c | 4 +-
gnome-initial-setup/gis-driver.h | 4 +-
gnome-initial-setup/gis-util.c | 70 ++++
gnome-initial-setup/gis-util.h | 2 +
gnome-initial-setup/gnome-initial-setup.c | 26 +-
.../pages/account/gis-account-pages.c | 21 +
.../pages/install/gis-install-page.c | 384 ++++++++++++++++++
.../pages/install/gis-install-page.h | 52 +++
.../pages/install/gis-install-page.ui | 49 +++
.../pages/install/install.gresource.xml | 7 +
gnome-initial-setup/pages/install/meson.build | 9 +
.../pages/keyboard/gis-keyboard-page.c | 10 +-
.../pages/language/gis-language-page.c | 5 +-
gnome-initial-setup/pages/meson.build | 1 +
.../pages/password/gis-password-page.c | 6 +
16 files changed, 635 insertions(+), 18 deletions(-)
create mode 100644 gnome-initial-setup/pages/install/gis-install-page.c
create mode 100644 gnome-initial-setup/pages/install/gis-install-page.h
create mode 100644 gnome-initial-setup/pages/install/gis-install-page.ui
create mode 100644 gnome-initial-setup/pages/install/install.gresource.xml
create mode 100644 gnome-initial-setup/pages/install/meson.build
diff --git a/data/20-gnome-initial-setup.rules.in b/data/20-gnome-initial-setup.rules.in
index 02fd21d0..881efde9 100644
--- a/data/20-gnome-initial-setup.rules.in
+++ b/data/20-gnome-initial-setup.rules.in
@@ -1,29 +1,30 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
//
// DO NOT EDIT THIS FILE, it will be overwritten on update.
//
// Allow the gnome-initial-setup user to do certain actions without
// being interrupted by password dialogs
polkit.addRule(function(action, subject) {
if (subject.user !== 'gnome-initial-setup')
return undefined;
var actionMatches = (action.id.indexOf('org.freedesktop.hostname1.') === 0 ||
action.id.indexOf('org.freedesktop.NetworkManager.') === 0 ||
action.id.indexOf('org.freedesktop.locale1.') === 0 ||
action.id.indexOf('org.freedesktop.accounts.') === 0 ||
action.id.indexOf('org.freedesktop.timedate1.') === 0 ||
action.id.indexOf('org.freedesktop.realmd.') === 0 ||
action.id.indexOf('com.endlessm.ParentalControls.') === 0 ||
- action.id.indexOf('org.fedoraproject.thirdparty.') === 0);
+ action.id.indexOf('org.fedoraproject.thirdparty.') === 0 ||
+ action.id.indexOf('org.freedesktop.login1.reboot') === 0);
if (actionMatches) {
if (subject.local)
return 'yes';
else
return 'auth_admin';
}
return undefined;
});
diff --git a/gnome-initial-setup/gis-driver.c b/gnome-initial-setup/gis-driver.c
index d3013063..b18a3808 100644
--- a/gnome-initial-setup/gis-driver.c
+++ b/gnome-initial-setup/gis-driver.c
@@ -19,60 +19,62 @@
* 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"
/* 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 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_LIVE_USER, "GIS_DRIVER_MODE_LIVE_USER", "live_user" },
+ { GIS_DRIVER_MODE_SYSTEM, "GIS_DRIVER_MODE_SYSTEM", "system" },
{ GIS_DRIVER_MODE_ALL, "GIS_DRIVER_MODE_ALL", "all" },
{ 0, NULL, NULL }
};
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;
@@ -764,61 +766,61 @@ static void
connect_to_gdm (GisDriver *driver)
{
g_autoptr(GError) error = NULL;
driver->client = gdm_client_new ();
driver->greeter = gdm_client_get_greeter_sync (driver->client, NULL, &error);
if (error == NULL)
driver->user_verifier = gdm_client_get_user_verifier_sync (driver->client, NULL, &error);
if (error != NULL) {
g_warning ("Failed to open connection to GDM: %s", error->message);
g_clear_object (&driver->user_verifier);
g_clear_object (&driver->greeter);
g_clear_object (&driver->client);
}
}
static void
gis_driver_startup (GApplication *app)
{
GisDriver *driver = GIS_DRIVER (app);
WebKitWebContext *context = webkit_web_context_get_default ();
G_APPLICATION_CLASS (gis_driver_parent_class)->startup (app);
#if !WEBKIT_CHECK_VERSION(2, 39, 5)
webkit_web_context_set_sandbox_enabled (context, TRUE);
#endif
- if (driver->mode == GIS_DRIVER_MODE_NEW_USER)
+ if (driver->mode & GIS_DRIVER_MODE_SYSTEM)
connect_to_gdm (driver);
driver->main_window = g_object_new (GTK_TYPE_APPLICATION_WINDOW,
"application", app,
"icon-name", "preferences-system",
"deletable", FALSE,
"title", _("Initial Setup"),
NULL);
g_signal_connect (driver->main_window,
"realize",
G_CALLBACK (window_realize_cb),
(gpointer)app);
driver->assistant = g_object_new (GIS_TYPE_ASSISTANT, NULL);
gtk_window_set_child (GTK_WINDOW (driver->main_window),
GTK_WIDGET (driver->assistant));
gis_driver_set_user_language (driver, setlocale (LC_MESSAGES, NULL), FALSE);
prepare_main_window (driver);
rebuild_pages (driver);
}
static void
gis_driver_init (GisDriver *driver)
{
load_vendor_conf_file (driver);
}
diff --git a/gnome-initial-setup/gis-driver.h b/gnome-initial-setup/gis-driver.h
index b57db2e2..aedb9a73 100644
--- a/gnome-initial-setup/gis-driver.h
+++ b/gnome-initial-setup/gis-driver.h
@@ -17,61 +17,63 @@
*
* 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 = 1 << 0,
GIS_DRIVER_MODE_EXISTING_USER = 1 << 1,
- GIS_DRIVER_MODE_ALL = (GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER),
+ GIS_DRIVER_MODE_LIVE_USER = 1 << 2,
+ GIS_DRIVER_MODE_SYSTEM = (GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_LIVE_USER),
+ GIS_DRIVER_MODE_ALL = (GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_EXISTING_USER | GIS_DRIVER_MODE_LIVE_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);
diff --git a/gnome-initial-setup/gis-util.c b/gnome-initial-setup/gis-util.c
index ac153fc1..315661b6 100644
--- a/gnome-initial-setup/gis-util.c
+++ b/gnome-initial-setup/gis-util.c
@@ -4,30 +4,100 @@
* 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/>.
*/
#include "config.h"
#include <gtk/gtk.h>
#include "gis-util.h"
void
gis_add_style_from_resource (const char *resource_path)
{
g_autoptr(GtkCssProvider) provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (provider, resource_path);
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
}
+
+gboolean
+gis_kernel_command_line_has_argument (const char *arguments[])
+{
+ GError *error = NULL;
+ g_autofree char *contents = NULL;
+ g_autoptr (GString) pattern = NULL;
+ gboolean has_argument = FALSE;
+ size_t i;
+
+ if (!g_file_get_contents ("/proc/cmdline", &contents, NULL, &error)) {
+ g_error_free (error);
+ return FALSE;
+ }
+
+ /* Build up the pattern by iterating through the alternatives,
+ * escaping all dots so they don't match any character but period,
+ * and adding word boundary specifiers around the arguments so
+ * substrings don't get matched.
+ *
+ * Also, add a | between each alternative.
+ */
+ pattern = g_string_new (NULL);
+ for (i = 0; arguments[i] != NULL; i++) {
+ g_autofree char *escaped_argument = g_regex_escape_string (arguments[i], -1);
+
+ if (i > 0) {
+ g_string_append (pattern, "|");
+ }
+
+ g_string_append (pattern, "\\b");
+
+ g_string_append (pattern, escaped_argument);
+
+ g_string_append (pattern, "\\b");
+ }
+
+ has_argument = g_regex_match_simple (pattern->str, contents, 0, 0);
+
+ return has_argument;
+}
+
+void
+gis_substitute_word_in_text (char **text,
+ const char *old_word,
+ const char *new_word)
+{
+ g_autoptr (GError) error = NULL;
+ g_autofree char *pattern = g_strdup_printf ("\\b%s\\b", old_word);
+ g_autoptr (GRegex) regex = g_regex_new (pattern, 0, 0, &error);
+ g_autofree char *replacement_text = NULL;
+
+ if (text == NULL || *text == NULL) {
+ return;
+ }
+
+ if (error != NULL) {
+ g_debug ("Error creating regex to match %s: %s\n", old_word, error->message);
+ }
+
+ replacement_text = g_regex_replace (regex, *text, -1, 0, new_word, 0, &error);
+
+ if (error != NULL) {
+ g_debug ("Error replacing %s with %s in %s: %s\n", old_word, new_word, *text, error->message);
+ return;
+ }
+
+ g_free (*text);
+ *text = g_steal_pointer (&replacement_text);
+}
diff --git a/gnome-initial-setup/gis-util.h b/gnome-initial-setup/gis-util.h
index 5041bddd..10dcd70c 100644
--- a/gnome-initial-setup/gis-util.h
+++ b/gnome-initial-setup/gis-util.h
@@ -1,19 +1,21 @@
/*
* Copyright 2023 Endless OS Foundation LLC
*
* 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/>.
*/
#pragma once
void gis_add_style_from_resource (const char *path);
+gboolean gis_kernel_command_line_has_argument (const char *arguments[]);
+void gis_substitute_word_in_text (char **text, const char *old_word, const char *new_word);
diff --git a/gnome-initial-setup/gnome-initial-setup.c b/gnome-initial-setup/gnome-initial-setup.c
index 59955779..bc7a4ee9 100644
--- a/gnome-initial-setup/gnome-initial-setup.c
+++ b/gnome-initial-setup/gnome-initial-setup.c
@@ -14,141 +14,146 @@
*
* 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 <adwaita.h>
#include <pwd.h>
#include <unistd.h>
#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"
+#include "pages/install/gis-install-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"
+#define VENDOR_LIVE_USER_ONLY_KEY "live_user_only"
static gboolean force_existing_user_mode;
+static gboolean force_live_user_mode;
static GPtrArray *skipped_pages;
typedef GisPage *(*PreparePage) (GisDriver *driver);
typedef struct {
const gchar *page_id;
PreparePage prepare_page_func;
GisDriverMode modes;
} PageData;
#define PAGE(name, modes) { #name, gis_prepare_ ## name ## _page, modes }
static PageData page_table[] = {
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 (network, GIS_DRIVER_MODE_ALL),
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 (timezone, GIS_DRIVER_MODE_ALL),
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),
+ /* In live user mode, the account page isn't displayed, it just quietly creates the live user */
+ PAGE (account, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_LIVE_USER),
+ PAGE (password, GIS_DRIVER_MODE_NEW_USER | GIS_DRIVER_MODE_LIVE_USER),
#ifdef HAVE_PARENTAL_CONTROLS
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, GIS_DRIVER_MODE_NEW_USER),
+ PAGE (install, GIS_DRIVER_MODE_LIVE_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 **
pages_to_skip_from_file (GisDriver *driver)
{
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
+ * - new_user_only (optional): list of pages to be skipped for modes other than new_user
+ * - existing_user_only (optional): list of pages to be skipped for modes other than existing_user
*
* 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);
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);
@@ -250,130 +255,137 @@ rebuild_pages_cb (GisDriver *driver)
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->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 if (force_live_user_mode)
+ return GIS_DRIVER_MODE_LIVE_USER;
else
return GIS_DRIVER_MODE_NEW_USER;
}
static gboolean
initial_setup_disabled_by_anaconda (void)
{
const gchar *file_name = SYSCONFDIR "/sysconfig/anaconda";
g_autoptr(GError) error = NULL;
g_autoptr(GKeyFile) key_file = g_key_file_new ();
if (!g_key_file_load_from_file (key_file, file_name, G_KEY_FILE_NONE, &error)) {
if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT) &&
!g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND)) {
g_warning ("Could not read %s: %s", file_name, error->message);
}
return FALSE;
}
return g_key_file_get_boolean (key_file, "General", "post_install_tools_disabled", NULL);
}
int
main (int argc, char *argv[])
{
GisDriver *driver;
int status;
GOptionContext *context;
GisDriverMode mode;
GOptionEntry entries[] = {
{ "existing-user", 0, 0, G_OPTION_ARG_NONE, &force_existing_user_mode,
_("Force existing user mode"), NULL },
+ { "live-user", 0, 0, G_OPTION_ARG_NONE, &force_live_user_mode,
+ _("Force live user mode"), NULL },
{ NULL }
};
g_unsetenv ("GIO_USE_VFS");
/* By default, libadwaita reads settings from the Settings portal, which causes
* the portal to be started, which causes gnome-keyring to be started. This
* interferes with our attempt below to manually start gnome-keyring and set
* the login keyring password to a well-known value, which we overwrite with
* the user's password once they choose one.
*/
g_setenv ("ADW_DISABLE_PORTAL", "1", TRUE);
context = g_option_context_new (_("— GNOME initial setup"));
g_option_context_add_main_entries (context, entries, NULL);
g_option_context_parse (context, &argc, &argv, NULL);
+ if (gis_kernel_command_line_has_argument ((const char *[]) { "rd.live.image", "endless.live_boot", NULL }))
+ force_live_user_mode = TRUE;
+
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
g_message ("Starting gnome-initial-setup");
if (gis_get_mock_mode ())
g_message ("Mock mode: changes will not be saved to disk");
else
g_message ("Production mode: changes will be saved to disk");
skipped_pages = g_ptr_array_new_with_free_func (destroy_page);
mode = get_mode ();
/* When we are running as the gnome-initial-setup user we
* dont have a normal user session and need to initialize
* the keyring manually so that we can pass the credentials
* along to the new user in the handoff.
*/
- if (mode == GIS_DRIVER_MODE_NEW_USER && !gis_get_mock_mode ())
+ if ((mode & GIS_DRIVER_MODE_SYSTEM) && !gis_get_mock_mode ())
gis_ensure_login_keyring ();
driver = gis_driver_new (mode);
adw_style_manager_set_color_scheme (adw_style_manager_get_default (),
ADW_COLOR_SCHEME_PREFER_LIGHT);
/* On first login, GNOME Shell offers to run a tour. If we also run Initial
* Setup, the two immovable, centred windows will sit atop one another.
* Until we have the ability to run Initial Setup in the "kiosk" mode, like
* it does in new-user mode, disable Initial Setup for existing users.
*
* https://gitlab.gnome.org/GNOME/gnome-initial-setup/-/issues/120#note_1019004
* https://gitlab.gnome.org/GNOME/gnome-initial-setup/-/issues/12
*/
if (mode == GIS_DRIVER_MODE_EXISTING_USER) {
g_message ("Skipping gnome-initial-setup for existing user");
gis_ensure_stamp_files (driver);
exit (EXIT_SUCCESS);
}
/* We only do this in existing-user mode, because if gdm launches us
* in new-user mode and we just exit, gdm's special g-i-s session
* never terminates. */
if (initial_setup_disabled_by_anaconda () &&
mode == GIS_DRIVER_MODE_EXISTING_USER) {
gis_ensure_stamp_files (driver);
exit (EXIT_SUCCESS);
}
g_signal_connect (driver, "rebuild-pages", G_CALLBACK (rebuild_pages_cb), NULL);
diff --git a/gnome-initial-setup/pages/account/gis-account-pages.c b/gnome-initial-setup/pages/account/gis-account-pages.c
index d9cc8d9f..8b0d8e99 100644
--- a/gnome-initial-setup/pages/account/gis-account-pages.c
+++ b/gnome-initial-setup/pages/account/gis-account-pages.c
@@ -1,32 +1,53 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2013 Red Hat
*
* 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>
*/
#include "config.h"
#include "gis-account-pages.h"
#include "gis-account-page.h"
GisPage *
gis_prepare_account_page (GisDriver *driver)
{
+ GisDriverMode driver_mode;
+
+ driver_mode = gis_driver_get_mode (driver);
+
+ if (driver_mode == GIS_DRIVER_MODE_LIVE_USER && !gis_kernel_command_line_has_argument ((const char *[]) { "rd.live.overlay", NULL })) {
+ ActUserManager *act_client = act_user_manager_get_default ();
+ const char *username = "liveuser";
+ g_autoptr(ActUser) user = NULL;
+ g_autoptr(GError) error = NULL;
+
+ user = act_user_manager_create_user (act_client, username, username, ACT_USER_ACCOUNT_TYPE_ADMINISTRATOR, &error);
+
+ if (user != NULL) {
+ act_user_set_password_mode (user, ACT_USER_PASSWORD_MODE_NONE);
+ gis_driver_set_username (driver, username);
+ gis_driver_set_account_mode (driver, UM_LOCAL);
+ gis_driver_set_user_permissions (driver, user, NULL);
+ }
+ return NULL;
+ }
+
return g_object_new (GIS_TYPE_ACCOUNT_PAGE,
"driver", driver,
NULL);
}
diff --git a/gnome-initial-setup/pages/install/gis-install-page.c b/gnome-initial-setup/pages/install/gis-install-page.c
new file mode 100644
index 00000000..70e3f9ec
--- /dev/null
+++ b/gnome-initial-setup/pages/install/gis-install-page.c
@@ -0,0 +1,384 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (C) 2023 Red Hat
+ *
+ * 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/>.
+ */
+
+/* Install page {{{1 */
+
+#define PAGE_ID "install"
+
+#include "config.h"
+#include "cc-common-language.h"
+#include "gis-install-page.h"
+#include "gis-pkexec.h"
+
+#include <glib/gstdio.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gio/gdesktopappinfo.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <act/act-user-manager.h>
+
+#define SERVICE_NAME "gdm-password"
+#define VENDOR_INSTALLER_GROUP "install"
+#define VENDOR_APPLICATION_KEY "application"
+
+struct _GisInstallPagePrivate {
+ GtkWidget *try_button;
+ GtkWidget *install_button;
+ AdwStatusPage *status_page;
+ GDesktopAppInfo *installer;
+
+ ActUser *user_account;
+ const gchar *user_password;
+};
+typedef struct _GisInstallPagePrivate GisInstallPagePrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (GisInstallPage, gis_install_page, GIS_TYPE_PAGE);
+
+static void
+request_info_query (GisInstallPage *page,
+ GdmUserVerifier *user_verifier,
+ const char *question,
+ gboolean is_secret)
+{
+ /* TODO: pop up modal dialog */
+ g_debug ("user verifier asks%s question: %s",
+ is_secret ? " secret" : "",
+ question);
+}
+
+static void
+on_info (GdmUserVerifier *user_verifier,
+ const char *service_name,
+ const char *info,
+ GisInstallPage *page)
+{
+ g_debug ("PAM module info: %s", info);
+}
+
+static void
+on_problem (GdmUserVerifier *user_verifier,
+ const char *service_name,
+ const char *problem,
+ GisInstallPage *page)
+{
+ g_warning ("PAM module error: %s", problem);
+}
+
+static void
+on_info_query (GdmUserVerifier *user_verifier,
+ const char *service_name,
+ const char *question,
+ GisInstallPage *page)
+{
+ request_info_query (page, user_verifier, question, FALSE);
+}
+
+static void
+on_secret_info_query (GdmUserVerifier *user_verifier,
+ const char *service_name,
+ const char *question,
+ GisInstallPage *page)
+{
+ GisInstallPagePrivate *priv = gis_install_page_get_instance_private (page);
+ gboolean should_send_password = priv->user_password != NULL;
+
+ g_debug ("PAM module secret info query: %s", question);
+ if (should_send_password) {
+ g_debug ("sending password\n");
+ gdm_user_verifier_call_answer_query (user_verifier,
+ service_name,
+ priv->user_password,
+ NULL, NULL, NULL);
+ priv->user_password = NULL;
+ } else {
+ request_info_query (page, user_verifier, question, TRUE);
+ }
+}
+
+static void
+on_session_opened (GdmGreeter *greeter,
+ const char *service_name,
+ GisInstallPage *page)
+{
+ gdm_greeter_call_start_session_when_ready_sync (greeter, service_name,
+ TRUE, NULL, NULL);
+}
+
+static void
+log_user_in (GisInstallPage *page)
+{
+ GisInstallPagePrivate *priv = gis_install_page_get_instance_private (page);
+ g_autoptr(GError) error = NULL;
+ GdmGreeter *greeter = NULL;
+ GdmUserVerifier *user_verifier = NULL;
+
+ if (!gis_driver_get_gdm_objects (GIS_PAGE (page)->driver,
+ &greeter, &user_verifier)) {
+ g_warning ("No GDM connection; not initiating login");
+ return;
+ }
+
+ g_signal_connect (user_verifier, "info",
+ G_CALLBACK (on_info), page);
+ g_signal_connect (user_verifier, "problem",
+ G_CALLBACK (on_problem), page);
+ g_signal_connect (user_verifier, "info-query",
+ G_CALLBACK (on_info_query), page);
+ g_signal_connect (user_verifier, "secret-info-query",
+ G_CALLBACK (on_secret_info_query), page);
+
+ g_signal_connect (greeter, "session-opened",
+ G_CALLBACK (on_session_opened), page);
+
+ gdm_user_verifier_call_begin_verification_for_user_sync (user_verifier,
+ SERVICE_NAME,
+ act_user_get_user_name (priv->user_account),
+ NULL, &error);
+
+ if (error != NULL)
+ g_warning ("Could not begin verification: %s", error->message);
+}
+
+static void
+on_try_button_clicked (GtkButton *button,
+ GisInstallPage *page)
+{
+ gis_ensure_stamp_files (GIS_PAGE (page)->driver);
+
+ gis_driver_hide_window (GIS_PAGE (page)->driver);
+ log_user_in (page);
+}
+
+static void
+on_installer_exited (GPid pid,
+ int exit_status,
+ gpointer user_data)
+{
+ g_autoptr (GError) error = NULL;
+ g_autoptr(GSubprocessLauncher) launcher = NULL;
+ g_autoptr(GSubprocess) subprocess = NULL;
+ gboolean started_to_reboot;
+
+ launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_SEARCH_PATH_FROM_ENVP);
+
+ g_subprocess_launcher_unsetenv (launcher, "SHELL");
+
+ subprocess = g_subprocess_launcher_spawn (launcher, &error, "systemctl", "reboot", NULL);
+
+ if (subprocess == NULL) {
+ g_warning ("Failed to initiate reboot: %s\n", error->message);
+ return;
+ }
+
+ started_to_reboot = g_subprocess_wait (subprocess, NULL, &error);
+
+ if (!started_to_reboot) {
+ g_warning ("Failed to reboot: %s\n", error->message);
+ return;
+ }
+}
+
+static void
+on_installer_started (GDesktopAppInfo *appinfo,
+ GPid pid,
+ gpointer user_data)
+{
+ g_child_watch_add (pid, on_installer_exited, user_data);
+}
+
+static void
+run_installer (GisInstallPage *page)
+{
+ g_autoptr (GError) error = NULL;
+ GisInstallPagePrivate *priv = gis_install_page_get_instance_private (page);
+ gboolean installer_launched;
+ g_autoptr (GAppLaunchContext) launch_context = NULL;
+ g_autofree char *language = NULL;
+
+ gis_ensure_stamp_files (GIS_PAGE (page)->driver);
+
+ launch_context = g_app_launch_context_new ();
+
+ g_app_launch_context_unsetenv (launch_context, "SHELL");
+
+ language = cc_common_language_get_current_language ();
+
+ if (language != NULL)
+ g_app_launch_context_setenv (launch_context, "LANG", language);
+
+ installer_launched = g_desktop_app_info_launch_uris_as_manager (priv->installer,
+ NULL,
+ launch_context,
+ G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_CHILD_INHERITS_STDERR | G_SPAWN_CHILD_INHERITS_STDOUT | G_SPAWN_SEARCH_PATH,
+ NULL,
+ NULL,
+ on_installer_started,
+ page,
+ &error);
+
+ if (!installer_launched)
+ g_warning ("Could not launch installer: %s", error->message);
+}
+
+static void
+on_install_button_clicked (GtkButton *button,
+ GisInstallPage *page)
+{
+ gis_driver_hide_window (GIS_PAGE (page)->driver);
+ run_installer (page);
+}
+
+static void
+gis_install_page_shown (GisPage *page)
+{
+ GisInstallPage *install = GIS_INSTALL_PAGE (page);
+ GisInstallPagePrivate *priv = gis_install_page_get_instance_private (install);
+ g_autoptr(GError) local_error = NULL;
+
+ if (!gis_driver_save_data (GIS_PAGE (page)->driver, &local_error))
+ g_warning ("Error saving data: %s", local_error->message);
+
+ gis_driver_get_user_permissions (GIS_PAGE (page)->driver,
+ &priv->user_account,
+ &priv->user_password);
+
+ gtk_widget_grab_focus (priv->install_button);
+}
+
+static void
+update_distro_name (GisInstallPage *page)
+{
+ GisInstallPagePrivate *priv = gis_install_page_get_instance_private (page);
+ g_autofree char *name = g_get_os_info (G_OS_INFO_KEY_NAME);
+ g_autofree char *text = NULL;
+
+ if (!name)
+ name = g_strdup ("GNOME");
+
+ text = g_strdup (adw_status_page_get_description (priv->status_page));
+ gis_substitute_word_in_text (&text, "GNOME", name);
+ adw_status_page_set_description (priv->status_page, text);
+ g_clear_pointer (&text, g_free);
+}
+
+static void
+update_distro_logo (GisInstallPage *page)
+{
+ GisInstallPagePrivate *priv = gis_install_page_get_instance_private (page);
+ g_autoptr (GtkIconTheme) icon_theme = NULL;
+ g_autofree char *logo_name = g_get_os_info ("LOGO");
+ g_autoptr(GtkIconPaintable) icon_paintable = NULL;
+ g_autoptr(GPtrArray) array = NULL;
+ g_autoptr(GIcon) icon = NULL;
+
+ if (logo_name == NULL)
+ logo_name = g_strdup ("gnome-logo");
+
+ array = g_ptr_array_new_with_free_func (g_free);
+ g_ptr_array_add (array, (gpointer) g_strdup_printf ("%s-text", logo_name));
+ g_ptr_array_add (array, (gpointer) g_strdup_printf ("%s", logo_name));
+
+ icon = g_themed_icon_new_from_names ((char **) array->pdata, array->len);
+ icon_theme = g_object_ref (gtk_icon_theme_get_for_display (gdk_display_get_default ()));
+ icon_paintable = gtk_icon_theme_lookup_by_gicon (icon_theme, icon,
+ 192,
+ gtk_widget_get_scale_factor (GTK_WIDGET (priv->status_page)),
+ gtk_widget_get_direction (GTK_WIDGET (priv->status_page)),
+ 0);
+
+ adw_status_page_set_paintable (priv->status_page, GDK_PAINTABLE (icon_paintable));
+}
+
+static gboolean
+find_installer (GisInstallPage *page)
+{
+ GisInstallPagePrivate *priv = gis_install_page_get_instance_private (page);
+ g_autofree char *desktop_file = NULL;
+
+ desktop_file = gis_driver_conf_get_string (GIS_PAGE (page)->driver,
+ VENDOR_INSTALLER_GROUP,
+ VENDOR_APPLICATION_KEY);
+
+ if (!desktop_file)
+ return FALSE;
+
+ priv->installer = g_desktop_app_info_new (desktop_file);
+
+ return priv->installer != NULL;
+}
+
+static void
+gis_install_page_constructed (GObject *object)
+{
+ GisInstallPage *page = GIS_INSTALL_PAGE (object);
+ GisInstallPagePrivate *priv = gis_install_page_get_instance_private (page);
+
+ G_OBJECT_CLASS (gis_install_page_parent_class)->constructed (object);
+
+ if (!find_installer (page))
+ gtk_widget_set_sensitive (priv->install_button, FALSE);
+
+ update_distro_name (page);
+ update_distro_logo (page);
+ g_signal_connect (priv->try_button, "clicked", G_CALLBACK (on_try_button_clicked), page);
+ g_signal_connect (priv->install_button, "clicked", G_CALLBACK (on_install_button_clicked), page);
+
+ gis_page_set_complete (GIS_PAGE (page), TRUE);
+
+ gtk_widget_set_visible (GTK_WIDGET (page), TRUE);
+}
+
+static void
+gis_install_page_locale_changed (GisPage *page)
+{
+ gis_page_set_title (page, _("Install or Try?"));
+}
+
+static void
+gis_install_page_class_init (GisInstallPageClass *klass)
+{
+ GisPageClass *page_class = GIS_PAGE_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass), "/org/gnome/initial-setup/gis-install-page.ui");
+
+ gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisInstallPage, try_button);
+ gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisInstallPage, install_button);
+ gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisInstallPage, status_page);
+
+ page_class->page_id = PAGE_ID;
+ page_class->locale_changed = gis_install_page_locale_changed;
+ page_class->shown = gis_install_page_shown;
+ object_class->constructed = gis_install_page_constructed;
+}
+
+static void
+gis_install_page_init (GisInstallPage *page)
+{
+ gtk_widget_init_template (GTK_WIDGET (page));
+}
+
+GisPage *
+gis_prepare_install_page (GisDriver *driver)
+{
+ return g_object_new (GIS_TYPE_INSTALL_PAGE,
+ "driver", driver,
+ NULL);
+}
diff --git a/gnome-initial-setup/pages/install/gis-install-page.h b/gnome-initial-setup/pages/install/gis-install-page.h
new file mode 100644
index 00000000..292427d8
--- /dev/null
+++ b/gnome-initial-setup/pages/install/gis-install-page.h
@@ -0,0 +1,52 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (C) 2023 Red Hat
+ *
+ * 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/>.
+ */
+
+#ifndef __GIS_INSTALL_PAGE_H__
+#define __GIS_INSTALL_PAGE_H__
+
+#include "gnome-initial-setup.h"
+
+G_BEGIN_DECLS
+
+#define GIS_TYPE_INSTALL_PAGE (gis_install_page_get_type ())
+#define GIS_INSTALL_PAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIS_TYPE_INSTALL_PAGE, GisInstallPage))
+#define GIS_INSTALL_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIS_TYPE_INSTALL_PAGE, GisInstallPageClass))
+#define GIS_IS_INSTALL_PAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIS_TYPE_INSTALL_PAGE))
+#define GIS_IS_INSTALL_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIS_TYPE_INSTALL_PAGE))
+#define GIS_INSTALL_PAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIS_TYPE_INSTALL_PAGE, GisInstallPageClass))
+
+typedef struct _GisInstallPage GisInstallPage;
+typedef struct _GisInstallPageClass GisInstallPageClass;
+
+struct _GisInstallPage
+{
+ GisPage parent;
+};
+
+struct _GisInstallPageClass
+{
+ GisPageClass parent_class;
+};
+
+GType gis_install_page_get_type (void);
+
+GisPage *gis_prepare_install_page (GisDriver *driver);
+
+G_END_DECLS
+
+#endif /* __GIS_INSTALL_PAGE_H__ */
diff --git a/gnome-initial-setup/pages/install/gis-install-page.ui b/gnome-initial-setup/pages/install/gis-install-page.ui
new file mode 100644
index 00000000..08cfbd6e
--- /dev/null
+++ b/gnome-initial-setup/pages/install/gis-install-page.ui
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GisInstallPage" parent="GisPage">
+ <child>
+ <object class="AdwStatusPage" id="status_page">
+ <property name="icon-name">gnome-logo</property>
+ <property name="title" translatable="yes">Install or Try?</property>
+ <property name="description" translatable="yes">This live media can be used to install GNOME, or it can be used to try GNOME as a temporary system. Installation can be started at any time using the install icon in Activities.</property>
+
+ <child>
+ <object class="GtkButton" id="start_button">
+ <property name="use_underline">True</property>
+ <property name="halign">center</property>
+ <style>
+ <class name="suggested-action"/>
+ <class name="pill"/>
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkBox" id="button_box">
+ <property name="orientation">horizontal</property>
+ <property name="homogeneous">True</property>
+ <property name="spacing">24</property>
+ <property name="halign">center</property>
+ <child>
+ <object class="GtkButton" id="install_button">
+ <property name="label" translatable="yes">Install…</property>
+ <style>
+ <class name="suggested-action"/>
+ <class name="pill"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="try_button">
+ <property name="label" translatable="yes">Try</property>
+ <style>
+ <class name="pill"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/gnome-initial-setup/pages/install/install.gresource.xml b/gnome-initial-setup/pages/install/install.gresource.xml
new file mode 100644
index 00000000..f1802db5
--- /dev/null
+++ b/gnome-initial-setup/pages/install/install.gresource.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/initial-setup">
+ <file preprocess="xml-stripblanks" alias="gis-install-page.ui">gis-install-page.ui</file>
+ </gresource>
+</gresources>
+
diff --git a/gnome-initial-setup/pages/install/meson.build b/gnome-initial-setup/pages/install/meson.build
new file mode 100644
index 00000000..e5084e5e
--- /dev/null
+++ b/gnome-initial-setup/pages/install/meson.build
@@ -0,0 +1,9 @@
+sources += gnome.compile_resources(
+ 'install-resources',
+ files('install.gresource.xml'),
+ c_name: 'install'
+)
+sources += files(
+ 'gis-install-page.c',
+ 'gis-install-page.h'
+)
diff --git a/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c b/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c
index f2bfe164..7801667c 100644
--- a/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c
+++ b/gnome-initial-setup/pages/keyboard/gis-keyboard-page.c
@@ -160,61 +160,61 @@ add_defaults_to_arrays (GisKeyboardPage *self,
static void
set_input_settings (GisKeyboardPage *self,
const char *type,
const char *id)
{
GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
g_autofree char *layout = NULL;
g_autofree char *variant = NULL;
g_autoptr(GVariant) default_input_sources = NULL;
g_autoptr(GVariant) input_sources = NULL;
g_autoptr(GPtrArray) layouts_array = NULL;
g_autoptr(GPtrArray) variants_array = NULL;
GVariantBuilder input_source_builder;
GVariantBuilder input_options_builder;
g_autoptr(GVariant) input_options = NULL;
gboolean is_system_mode;
size_t i;
g_autofree char *default_input_source_id = NULL;
default_input_sources = g_settings_get_default_value (priv->input_settings, KEY_INPUT_SOURCES);
input_sources = g_settings_get_value (priv->input_settings, KEY_INPUT_SOURCES);
if (!g_variant_equal (default_input_sources, input_sources))
return;
g_clear_pointer (&input_sources, g_variant_unref);
g_variant_builder_init (&input_options_builder, G_VARIANT_TYPE ("as"));
- is_system_mode = gis_driver_get_mode (GIS_PAGE (self)->driver) == GIS_DRIVER_MODE_NEW_USER;
+ is_system_mode = gis_driver_get_mode (GIS_PAGE (self)->driver) & GIS_DRIVER_MODE_SYSTEM;
layouts_array = g_ptr_array_new ();
variants_array = g_ptr_array_new ();
/* Notice the added latin layout (if relevant) gets put first for gsettings
* (input_source_builder and last for localed (layouts_array/variants_array)
* This ensures we get a cyrillic layout on ttys, but a latin layout by default
* in the UI.
*/
g_variant_builder_init (&input_source_builder, G_VARIANT_TYPE ("a(ss)"));
if (type != NULL && id != NULL) {
add_input_source_to_arrays (self, type, id, layouts_array, variants_array);
if (gnome_input_source_is_non_latin (type, id)) {
default_input_source_id = g_strdup ("us");
add_input_source_to_arrays (self, "xkb", default_input_source_id, layouts_array, variants_array);
g_variant_builder_add (&input_source_builder, "(ss)", "xkb", default_input_source_id);
} else {
default_input_source_id = g_strdup (id);
}
g_variant_builder_add (&input_source_builder, "(ss)", type, id);
}
if (default_input_source_id == NULL || !is_system_mode) {
add_defaults_to_variant_builder (self, type, id, &input_source_builder, &default_input_source_id);
}
input_sources = g_variant_builder_end (&input_source_builder);
for (i = 0; priv->default_options[i] != NULL; i++) {
@@ -274,61 +274,61 @@ change_locale_permission_acquired (GObject *source,
{
GisKeyboardPage *page = GIS_KEYBOARD_PAGE (data);
GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (page);
GError *error = NULL;
gboolean allowed;
allowed = g_permission_acquire_finish (priv->permission, res, &error);
if (error) {
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
g_warning ("Failed to acquire permission: %s", error->message);
g_error_free (error);
return;
}
if (allowed)
set_localed_input (GIS_KEYBOARD_PAGE (data));
}
static void
update_input (GisKeyboardPage *self)
{
GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
const gchar *type;
const gchar *id;
type = cc_input_chooser_get_input_type (CC_INPUT_CHOOSER (priv->input_chooser));
id = cc_input_chooser_get_input_id (CC_INPUT_CHOOSER (priv->input_chooser));
set_input_settings (self, type, id);
- if (gis_driver_get_mode (GIS_PAGE (self)->driver) == GIS_DRIVER_MODE_NEW_USER) {
+ if (gis_driver_get_mode (GIS_PAGE (self)->driver) & GIS_DRIVER_MODE_SYSTEM) {
if (g_permission_get_allowed (priv->permission)) {
set_localed_input (self);
} else if (g_permission_get_can_acquire (priv->permission)) {
g_permission_acquire_async (priv->permission,
NULL,
change_locale_permission_acquired,
self);
}
}
}
static gboolean
gis_keyboard_page_apply (GisPage *page,
GCancellable *cancellable)
{
update_input (GIS_KEYBOARD_PAGE (page));
return FALSE;
}
static void
add_default_input_sources (GisKeyboardPage *self)
{
set_input_settings (self, NULL, NULL);
}
static void
gis_keyboard_page_skip (GisPage *page)
{
GisKeyboardPage *self = GIS_KEYBOARD_PAGE (page);
GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
@@ -336,82 +336,82 @@ gis_keyboard_page_skip (GisPage *page)
priv->should_skip = TRUE;
if (priv->default_input_source_ids != NULL)
add_default_input_sources (self);
}
static void
preselect_input_source (GisKeyboardPage *self)
{
const char *language = NULL;
GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
language = cc_common_language_get_current_language ();
/* We deduce the initial input source from language if we're in a system mode
* (where preexisting system configuration may be stale) or if the language
* requires an input method (because there is no way for system configuration
* to denote the need for an input method)
*
* If it's a non-system mode we can trust the system configuration is probably
* a better bet than a heuristic based on locale.
*/
if (language != NULL) {
gboolean got_input_source;
const char *id, *type;
got_input_source = gnome_get_input_source_from_locale (language, &type, &id);
if (got_input_source) {
- gboolean is_system_mode = gis_driver_get_mode (GIS_PAGE (self)->driver) == GIS_DRIVER_MODE_NEW_USER;
+ gboolean is_system_mode = gis_driver_get_mode (GIS_PAGE (self)->driver) & GIS_DRIVER_MODE_SYSTEM;
if (is_system_mode || g_str_equal (type, "ibus")) {
cc_input_chooser_set_input (CC_INPUT_CHOOSER (priv->input_chooser),
id,
type);
return;
}
}
}
cc_input_chooser_set_input (CC_INPUT_CHOOSER (priv->input_chooser),
priv->default_input_source_ids[0],
priv->default_input_source_types[0]);
}
static void
update_page_complete (GisKeyboardPage *self)
{
GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
gboolean complete;
- if (gis_driver_get_mode (GIS_PAGE (self)->driver) == GIS_DRIVER_MODE_NEW_USER) {
+ if (gis_driver_get_mode (GIS_PAGE (self)->driver) & GIS_DRIVER_MODE_SYSTEM) {
complete = (priv->localed != NULL &&
cc_input_chooser_get_input_id (CC_INPUT_CHOOSER (priv->input_chooser)) != NULL);
} else {
complete = cc_input_chooser_get_input_id (CC_INPUT_CHOOSER (priv->input_chooser)) != NULL;
}
gis_page_set_complete (GIS_PAGE (self), complete);
}
static void
localed_proxy_ready (GObject *source,
GAsyncResult *res,
gpointer data)
{
GisKeyboardPage *self = data;
GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
GDBusProxy *proxy;
GError *error = NULL;
proxy = g_dbus_proxy_new_finish (res, &error);
if (!proxy) {
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
g_warning ("Failed to contact localed: %s", error->message);
g_error_free (error);
return;
}
priv->localed = proxy;
update_page_complete (self);
@@ -469,61 +469,61 @@ static void
gis_keyboard_page_constructed (GObject *object)
{
GisKeyboardPage *self = GIS_KEYBOARD_PAGE (object);
GisKeyboardPagePrivate *priv = gis_keyboard_page_get_instance_private (self);
G_OBJECT_CLASS (gis_keyboard_page_parent_class)->constructed (object);
g_signal_connect (priv->input_chooser, "confirm",
G_CALLBACK (input_confirmed), self);
g_signal_connect (priv->input_chooser, "changed",
G_CALLBACK (input_changed), self);
priv->input_settings = g_settings_new (GNOME_DESKTOP_INPUT_SOURCES_DIR);
g_settings_delay (priv->input_settings);
priv->cancellable = g_cancellable_new ();
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES,
NULL,
"org.freedesktop.locale1",
"/org/freedesktop/locale1",
"org.freedesktop.locale1",
priv->cancellable,
(GAsyncReadyCallback) localed_proxy_ready,
self);
gnome_get_default_input_sources (priv->cancellable, on_got_default_sources, self);
/* If we're in new user mode then we're manipulating system settings */
- if (gis_driver_get_mode (GIS_PAGE (self)->driver) == GIS_DRIVER_MODE_NEW_USER)
+ if (gis_driver_get_mode (GIS_PAGE (self)->driver) & GIS_DRIVER_MODE_SYSTEM)
priv->permission = polkit_permission_new_sync ("org.freedesktop.locale1.set-keyboard", NULL, NULL, NULL);
update_page_complete (self);
gtk_widget_set_visible (GTK_WIDGET (self), TRUE);
}
static void
gis_keyboard_page_locale_changed (GisPage *page)
{
gis_page_set_title (GIS_PAGE (page), _("Typing"));
}
static void
gis_keyboard_page_class_init (GisKeyboardPageClass * klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GisPageClass * page_class = GIS_PAGE_CLASS (klass);
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass), "/org/gnome/initial-setup/gis-keyboard-page.ui");
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass), GisKeyboardPage, input_chooser);
page_class->page_id = PAGE_ID;
page_class->apply = gis_keyboard_page_apply;
page_class->skip = gis_keyboard_page_skip;
page_class->locale_changed = gis_keyboard_page_locale_changed;
object_class->constructed = gis_keyboard_page_constructed;
object_class->finalize = gis_keyboard_page_finalize;
}
diff --git a/gnome-initial-setup/pages/language/gis-language-page.c b/gnome-initial-setup/pages/language/gis-language-page.c
index 26a01257..17117fa1 100644
--- a/gnome-initial-setup/pages/language/gis-language-page.c
+++ b/gnome-initial-setup/pages/language/gis-language-page.c
@@ -118,61 +118,61 @@ change_locale_permission_acquired (GObject *source,
}
static void
user_loaded (GObject *object,
GParamSpec *pspec,
gpointer user_data)
{
gchar *new_locale_id = user_data;
act_user_set_language (ACT_USER (object), new_locale_id);
g_free (new_locale_id);
}
static void
language_changed (CcLanguageChooser *chooser,
GParamSpec *pspec,
GisLanguagePage *page)
{
GisLanguagePagePrivate *priv = gis_language_page_get_instance_private (page);
GisDriver *driver;
GSettings *region_settings;
ActUser *user;
priv->new_locale_id = cc_language_chooser_get_language (chooser);
driver = GIS_PAGE (page)->driver;
gis_driver_set_user_language (driver, priv->new_locale_id, TRUE);
gtk_widget_set_default_direction (gtk_get_locale_direction ());
- if (gis_driver_get_mode (driver) == GIS_DRIVER_MODE_NEW_USER) {
+ if (gis_driver_get_mode (driver) & GIS_DRIVER_MODE_SYSTEM) {
gis_page_set_complete (GIS_PAGE (page), FALSE);
if (g_permission_get_allowed (priv->permission)) {
set_localed_locale (page);
}
else if (g_permission_get_can_acquire (priv->permission)) {
g_permission_acquire_async (priv->permission,
NULL,
change_locale_permission_acquired,
page);
}
}
/* Ensure we won't override the selected language for format strings */
region_settings = g_settings_new (GNOME_SYSTEM_LOCALE_DIR);
g_settings_reset (region_settings, REGION_KEY);
g_object_unref (region_settings);
user = act_user_manager_get_user (act_user_manager_get_default (),
g_get_user_name ());
if (act_user_is_loaded (user))
act_user_set_language (user, priv->new_locale_id);
else
g_signal_connect (user,
"notify::is-loaded",
G_CALLBACK (user_loaded),
g_strdup (priv->new_locale_id));
gis_welcome_widget_show_locale (GIS_WELCOME_WIDGET (priv->welcome_widget),
@@ -230,62 +230,61 @@ update_distro_logo (GisLanguagePage *page)
break;
}
}
}
static void
language_confirmed (CcLanguageChooser *chooser,
GisLanguagePage *page)
{
gis_assistant_next_page (gis_driver_get_assistant (GIS_PAGE (page)->driver));
}
static void
gis_language_page_constructed (GObject *object)
{
GisLanguagePage *page = GIS_LANGUAGE_PAGE (object);
GisLanguagePagePrivate *priv = gis_language_page_get_instance_private (page);
GDBusConnection *bus;
g_type_ensure (CC_TYPE_LANGUAGE_CHOOSER);
G_OBJECT_CLASS (gis_language_page_parent_class)->constructed (object);
update_distro_logo (page);
g_signal_connect (priv->language_chooser, "notify::language",
G_CALLBACK (language_changed), page);
g_signal_connect (priv->language_chooser, "confirm",
G_CALLBACK (language_confirmed), page);
- /* If we're in new user mode then we're manipulating system settings */
- if (gis_driver_get_mode (GIS_PAGE (page)->driver) == GIS_DRIVER_MODE_NEW_USER)
+ if (gis_driver_get_mode (GIS_PAGE (page)->driver) & GIS_DRIVER_MODE_SYSTEM)
{
priv->permission = polkit_permission_new_sync ("org.freedesktop.locale1.set-locale", NULL, NULL, NULL);
bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
g_dbus_proxy_new (bus,
G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES,
NULL,
"org.freedesktop.locale1",
"/org/freedesktop/locale1",
"org.freedesktop.locale1",
priv->cancellable,
(GAsyncReadyCallback) localed_proxy_ready,
object);
g_object_unref (bus);
}
else
{
gis_page_set_complete (GIS_PAGE (page), TRUE);
}
gtk_widget_set_visible (GTK_WIDGET (page), TRUE);
}
static void
gis_language_page_locale_changed (GisPage *page)
{
gis_page_set_title (GIS_PAGE (page), _("Welcome"));
}
static void
gis_language_page_dispose (GObject *object)
diff --git a/gnome-initial-setup/pages/meson.build b/gnome-initial-setup/pages/meson.build
index 32305018..5ac4a80d 100644
--- a/gnome-initial-setup/pages/meson.build
+++ b/gnome-initial-setup/pages/meson.build
@@ -1,21 +1,22 @@
pages = [
'account',
+ 'install',
'language',
'keyboard',
'network',
'timezone',
'privacy',
'goa',
'password',
'software',
'summary',
'welcome',
]
if libmalcontent_dep.found() and libmalcontent_ui_dep.found()
pages += 'parental-controls'
endif
foreach page: pages
subdir (page)
endforeach
diff --git a/gnome-initial-setup/pages/password/gis-password-page.c b/gnome-initial-setup/pages/password/gis-password-page.c
index 6c12ca38..3d648c48 100644
--- a/gnome-initial-setup/pages/password/gis-password-page.c
+++ b/gnome-initial-setup/pages/password/gis-password-page.c
@@ -464,47 +464,53 @@ gis_password_page_class_init (GisPasswordPageClass *klass)
*
* If %FALSE (the default), this page will collect a password for the main
* user account. If %TRUE, it will collect a password for controlling access
* to parental controls — this will affect where the password is stored, and
* the appearance of the page.
*
* Since: 3.36
*/
obj_props[PROP_PARENT_MODE] =
g_param_spec_boolean ("parent-mode", "Parent Mode",
"Whether to collect a password for the main user account or a parent account.",
FALSE,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_properties (object_class, G_N_ELEMENTS (obj_props), obj_props);
gis_add_style_from_resource ("/org/gnome/initial-setup/gis-password-page.css");
}
static void
gis_password_page_init (GisPasswordPage *page)
{
g_type_ensure (GIS_TYPE_PAGE_HEADER);
gtk_widget_init_template (GTK_WIDGET (page));
}
GisPage *
gis_prepare_password_page (GisDriver *driver)
{
+ GisDriverMode driver_mode;
+
+ driver_mode = gis_driver_get_mode (driver);
+ if (driver_mode == GIS_DRIVER_MODE_LIVE_USER && !gis_kernel_command_line_has_argument ((const char *[]) { "rd.live.overlay", NULL }))
+ return NULL;
+
return g_object_new (GIS_TYPE_PASSWORD_PAGE,
"driver", driver,
NULL);
}
GisPage *
gis_prepare_parent_password_page (GisDriver *driver)
{
/* Skip prompting for the parent password if parental controls arent enabled. */
if (!gis_driver_get_parental_controls_enabled (driver))
return NULL;
return g_object_new (GIS_TYPE_PASSWORD_PAGE,
"driver", driver,
"parent-mode", TRUE,
NULL);
}
--
2.41.0