From 8281e714e9a93007bb5f1a1786b3f1d74500e3ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Wed, 5 Feb 2025 13:48:45 +0100 Subject: [PATCH] Support loading banner message from file Resolves: https://issues.redhat.com/browse/RHEL-4104 --- gdm-support-banner-message-file.patch | 232 ++++++++++++++++++++++++++ gnome-shell.spec | 1 + 2 files changed, 233 insertions(+) create mode 100644 gdm-support-banner-message-file.patch diff --git a/gdm-support-banner-message-file.patch b/gdm-support-banner-message-file.patch new file mode 100644 index 0000000..5157f26 --- /dev/null +++ b/gdm-support-banner-message-file.patch @@ -0,0 +1,232 @@ +From f328eee88c4e700a29625e87fd6fc997a138c66b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Fri, 22 Nov 2024 19:23:59 +0100 +Subject: [PATCH 1/3] loginDialog: Split out getBannerText() helper + +The new methods will make it easier to add alternative sources +for the banner text. + +Part-of: +--- + js/gdm/loginDialog.js | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js +index 27baae83ad..c3c397c0d1 100644 +--- a/js/gdm/loginDialog.js ++++ b/js/gdm/loginDialog.js +@@ -873,11 +873,18 @@ export const LoginDialog = GObject.registerClass({ + this._authPrompt.cancelButton.visible = cancelVisible; + } + ++ _getBannerText() { ++ const enabled = this._settings.get_boolean(GdmUtil.BANNER_MESSAGE_KEY); ++ if (!enabled) ++ return null; ++ ++ return this._settings.get_string(GdmUtil.BANNER_MESSAGE_TEXT_KEY); ++ } ++ + _updateBanner() { +- let enabled = this._settings.get_boolean(GdmUtil.BANNER_MESSAGE_KEY); +- let text = this._settings.get_string(GdmUtil.BANNER_MESSAGE_TEXT_KEY); ++ const text = this._getBannerText(); + +- if (enabled && text) { ++ if (text) { + this._bannerLabel.set_text(text); + this._bannerLabel.show(); + } else { +-- +2.48.1 + + +From 5f92c12c727bd447d7e539b1e6c8f3ac6ddf715a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Fri, 22 Nov 2024 19:36:42 +0100 +Subject: [PATCH 2/3] loginDialog: Update banner asynchronously + +We will soon allow reading the banner text from a file. Prepare +for that by making the method asynchronous. + +Part-of: +--- + js/gdm/loginDialog.js | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js +index c3c397c0d1..125cf299fa 100644 +--- a/js/gdm/loginDialog.js ++++ b/js/gdm/loginDialog.js +@@ -505,9 +505,9 @@ export const LoginDialog = GObject.registerClass({ + this._settings = new Gio.Settings({schema_id: GdmUtil.LOGIN_SCREEN_SCHEMA}); + + this._settings.connect(`changed::${GdmUtil.BANNER_MESSAGE_KEY}`, +- this._updateBanner.bind(this)); ++ () => this._updateBanner().catch(logError)); + this._settings.connect(`changed::${GdmUtil.BANNER_MESSAGE_TEXT_KEY}`, +- this._updateBanner.bind(this)); ++ () => this._updateBanner().catch(logError)); + this._settings.connect(`changed::${GdmUtil.DISABLE_USER_LIST_KEY}`, + this._updateDisableUserList.bind(this)); + this._settings.connect(`changed::${GdmUtil.LOGO_KEY}`, +@@ -576,7 +576,7 @@ export const LoginDialog = GObject.registerClass({ + this._bannerLabel.clutter_text.line_wrap = true; + this._bannerLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; + bannerBox.add_child(this._bannerLabel); +- this._updateBanner(); ++ this._updateBanner().catch(logError); + + this._sessionMenuButton = new SessionMenuButton(); + this._sessionMenuButton.connect('session-activated', +@@ -873,16 +873,19 @@ export const LoginDialog = GObject.registerClass({ + this._authPrompt.cancelButton.visible = cancelVisible; + } + +- _getBannerText() { ++ async _getBannerText() { + const enabled = this._settings.get_boolean(GdmUtil.BANNER_MESSAGE_KEY); + if (!enabled) + return null; + ++ // placeholder ++ await false; ++ + return this._settings.get_string(GdmUtil.BANNER_MESSAGE_TEXT_KEY); + } + +- _updateBanner() { +- const text = this._getBannerText(); ++ async _updateBanner() { ++ const text = await this._getBannerText(); + + if (text) { + this._bannerLabel.set_text(text); +-- +2.48.1 + + +From a73a4f8455b1374b38724a532137a9b614a7fb19 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Fri, 22 Nov 2024 19:17:44 +0100 +Subject: [PATCH 3/3] loginDialog: Support loading banner message from file + +Support the new `banner-message-path` and `banner-message-source` +settings, which allows loading the banner message from a path +instead of GSettings. This is mainly useful for `/etc/motd` and +similar mechanisms, to show the same message for both graphical +and non-graphical logins. + +Part-of: +--- + js/gdm/loginDialog.js | 53 +++++++++++++++++++++++++++++++++++++++++-- + js/gdm/util.js | 2 ++ + 2 files changed, 53 insertions(+), 2 deletions(-) + +diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js +index 125cf299fa..fa91615026 100644 +--- a/js/gdm/loginDialog.js ++++ b/js/gdm/loginDialog.js +@@ -46,6 +46,8 @@ const _SCROLL_ANIMATION_TIME = 500; + const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0; + const _CONFLICTING_SESSION_DIALOG_TIMEOUT = 60; + ++Gio._promisify(Gio.File.prototype, 'load_contents_async'); ++ + export const UserListItem = GObject.registerClass({ + Signals: {'activate': {}}, + }, class UserListItem extends St.Button { +@@ -508,6 +510,16 @@ export const LoginDialog = GObject.registerClass({ + () => this._updateBanner().catch(logError)); + this._settings.connect(`changed::${GdmUtil.BANNER_MESSAGE_TEXT_KEY}`, + () => this._updateBanner().catch(logError)); ++ this._settings.connect(`changed::${GdmUtil.BANNER_MESSAGE_SOURCE_KEY}`, ++ () => { ++ if (this._updateBannerMessageFile()) ++ this._updateBanner().catch(logError); ++ }); ++ this._settings.connect(`changed::${GdmUtil.BANNER_MESSAGE_PATH_KEY}`, ++ () => { ++ if (this._updateBannerMessageFile()) ++ this._updateBanner().catch(logError); ++ }); + this._settings.connect(`changed::${GdmUtil.DISABLE_USER_LIST_KEY}`, + this._updateDisableUserList.bind(this)); + this._settings.connect(`changed::${GdmUtil.LOGO_KEY}`, +@@ -576,6 +588,8 @@ export const LoginDialog = GObject.registerClass({ + this._bannerLabel.clutter_text.line_wrap = true; + this._bannerLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; + bannerBox.add_child(this._bannerLabel); ++ ++ this._updateBannerMessageFile(); + this._updateBanner().catch(logError); + + this._sessionMenuButton = new SessionMenuButton(); +@@ -873,13 +887,48 @@ export const LoginDialog = GObject.registerClass({ + this._authPrompt.cancelButton.visible = cancelVisible; + } + ++ _updateBannerMessageFile() { ++ const path = this._settings.get_string(GdmUtil.BANNER_MESSAGE_SOURCE_KEY) === 'file' ++ ? this._settings.get_string(GdmUtil.BANNER_MESSAGE_PATH_KEY) ++ : null; ++ const file = path ++ ? Gio.File.new_for_path(path) ++ : null; ++ ++ if (!file && !this._bannerMessageFile) ++ return false; ++ ++ if (file && this._bannerMessageFile && this._bannerMessageFile.equal(file)) ++ return false; ++ ++ this._bannerMessageMonitor?.disconnectObject(this); ++ this._bannerMessageMonitor = null; ++ ++ this._bannerMessageFile = file; ++ ++ if (file) { ++ this._bannerMessageMonitor = file.monitor_file(Gio.FileMonitorFlags.NONE, null); ++ this._bannerMessageMonitor.connectObject( ++ 'changed', () => this._updateBanner().catch(logError), this); ++ } ++ ++ return true; ++ } ++ + async _getBannerText() { + const enabled = this._settings.get_boolean(GdmUtil.BANNER_MESSAGE_KEY); + if (!enabled) + return null; + +- // placeholder +- await false; ++ if (this._bannerMessageFile) { ++ try { ++ const [contents] = await this._bannerMessageFile.load_contents_async(null); ++ return new TextDecoder().decode(contents); ++ } catch (e) { ++ console.error(`Failed to read banner from ${this._bannerMessageFile.get_path()}: ${e.message}`); ++ return null; ++ } ++ } + + return this._settings.get_string(GdmUtil.BANNER_MESSAGE_TEXT_KEY); + } +diff --git a/js/gdm/util.js b/js/gdm/util.js +index 1e0154f36f..f6b797c321 100644 +--- a/js/gdm/util.js ++++ b/js/gdm/util.js +@@ -33,7 +33,9 @@ export const PASSWORD_AUTHENTICATION_KEY = 'enable-password-authentication'; + export const FINGERPRINT_AUTHENTICATION_KEY = 'enable-fingerprint-authentication'; + export const SMARTCARD_AUTHENTICATION_KEY = 'enable-smartcard-authentication'; + export const BANNER_MESSAGE_KEY = 'banner-message-enable'; ++export const BANNER_MESSAGE_SOURCE_KEY = 'banner-message-source'; + export const BANNER_MESSAGE_TEXT_KEY = 'banner-message-text'; ++export const BANNER_MESSAGE_PATH_KEY = 'banner-message-path'; + export const ALLOWED_FAILURES_KEY = 'allowed-failures'; + + export const LOGO_KEY = 'logo'; +-- +2.48.1 + diff --git a/gnome-shell.spec b/gnome-shell.spec index dc782a4..4518b8b 100644 --- a/gnome-shell.spec +++ b/gnome-shell.spec @@ -30,6 +30,7 @@ Patch: 0001-gdm-Work-around-failing-fingerprint-auth.patch Patch: 0001-screenShield-unblank-when-inserting-smartcard.patch Patch: enforce-smartcard-at-unlock.patch Patch: disable-unlock-entry-until-question.patch +Patch: gdm-support-banner-message-file.patch # Extensions Patch: 0001-extensionDownloader-Refuse-to-override-system-extens.patch