commit fc3c01ff1ebda00832d941d45878be58667ee731 Author: MSVSphere Packaging Team Date: Fri Apr 14 13:11:43 2023 +0300 import gnome-settings-daemon-40.0.1-10.el9 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f38ec39 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/gnome-settings-daemon-40.0.1.tar.xz diff --git a/.gnome-settings-daemon.metadata b/.gnome-settings-daemon.metadata new file mode 100644 index 0000000..e403ab1 --- /dev/null +++ b/.gnome-settings-daemon.metadata @@ -0,0 +1 @@ +5c9249cc5e89627bd548d7cfc9f839c7524ad85f SOURCES/gnome-settings-daemon-40.0.1.tar.xz diff --git a/SOURCES/0001-Make-power-button-action-always-power-off-when-chass.patch b/SOURCES/0001-Make-power-button-action-always-power-off-when-chass.patch new file mode 100644 index 0000000..baac87c --- /dev/null +++ b/SOURCES/0001-Make-power-button-action-always-power-off-when-chass.patch @@ -0,0 +1,45 @@ +From a94fd3a1a055c55f96adb1482cb96c7a541af7dd Mon Sep 17 00:00:00 2001 +From: Felipe Borges +Date: Wed, 15 Feb 2023 15:27:59 +0100 +Subject: [PATCH] Make power-button-action always power off when chassis=server + +Servers often don't support hibernation/suspend. +--- + .../org.gnome.settings-daemon.plugins.power.gschema.xml.in | 2 +- + plugins/media-keys/gsd-media-keys-manager.c | 7 ++++--- + 2 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/data/org.gnome.settings-daemon.plugins.power.gschema.xml.in b/data/org.gnome.settings-daemon.plugins.power.gschema.xml.in +index e1a8787b..ef0ea530 100644 +--- a/data/org.gnome.settings-daemon.plugins.power.gschema.xml.in ++++ b/data/org.gnome.settings-daemon.plugins.power.gschema.xml.in +@@ -39,7 +39,7 @@ + + 'suspend' + Power button action +- The action to take when the system power button is pressed. Virtual machines only honor the 'nothing' action, and will shutdown otherwise. Tablets always suspend, ignoring all the other action options. ++ The action to take when the system power button is pressed. Virtual machines and servers only honor the 'nothing' action, and will shutdown otherwise. Tablets always suspend, ignoring all the other action options. + + + true +diff --git a/plugins/media-keys/gsd-media-keys-manager.c b/plugins/media-keys/gsd-media-keys-manager.c +index 60ff2ced..26d0e438 100644 +--- a/plugins/media-keys/gsd-media-keys-manager.c ++++ b/plugins/media-keys/gsd-media-keys-manager.c +@@ -2042,9 +2042,10 @@ do_config_power_button_action (GsdMediaKeysManager *manager, + return; + + action_type = g_settings_get_enum (priv->power_settings, "power-button-action"); +- /* Always power off VMs, except when power-button-action is "nothing" */ +- if (g_strcmp0 (priv->chassis_type, "vm") == 0) { +- g_warning_once ("Virtual machines only honor the 'nothing' power-button-action, and will shutdown otherwise"); ++ /* Always power off VMs and servers, except when power-button-action is "nothing" */ ++ if (g_strcmp0 (priv->chassis_type, "vm") == 0 || ++ g_strcmp0 (priv->chassis_type, "server")) { ++ g_warning ("Virtual machines only honor the 'nothing' power-button-action, and will shutdown otherwise"); + + if (action_type != GSD_POWER_BUTTON_ACTION_NOTHING) + power_action (manager, "PowerOff", FALSE); +-- +2.37.1 + diff --git a/SOURCES/0001-power-Enable-power-saver-profile-when-low-on-battery.patch b/SOURCES/0001-power-Enable-power-saver-profile-when-low-on-battery.patch new file mode 100644 index 0000000..2092fec --- /dev/null +++ b/SOURCES/0001-power-Enable-power-saver-profile-when-low-on-battery.patch @@ -0,0 +1,458 @@ +From 8dd4c164f6ce166a5767588bd6fb8e4c3e8e1a09 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Fri, 16 Jul 2021 13:40:10 +0200 +Subject: [PATCH 1/4] power: Enable power-saver profile when low on battery + +When low on battery, and if the feature is enabled, hold the power +profile to "power-saver" until the battery is sufficiently recharged. +--- + ...ttings-daemon.plugins.power.gschema.xml.in | 5 + + plugins/power/gsd-power-manager.c | 128 ++++++++++++++++++ + plugins/power/test.py | 32 +++++ + 3 files changed, 165 insertions(+) + +diff --git a/data/org.gnome.settings-daemon.plugins.power.gschema.xml.in b/data/org.gnome.settings-daemon.plugins.power.gschema.xml.in +index 93c704e9..04b287bd 100644 +--- a/data/org.gnome.settings-daemon.plugins.power.gschema.xml.in ++++ b/data/org.gnome.settings-daemon.plugins.power.gschema.xml.in +@@ -41,5 +41,10 @@ + Power button action + The action to take when the system power button is pressed. This action is hard-coded (and the setting ignored) on virtual machines (power off) and tablets (suspend). + ++ ++ true ++ Enable power-saver profile when battery is low ++ Automatically enable the "power-saver" profile using power-profiles-daemon if the battery is low. ++ + + +diff --git a/plugins/power/gsd-power-manager.c b/plugins/power/gsd-power-manager.c +index 95cec9c3..1f125a6f 100644 +--- a/plugins/power/gsd-power-manager.c ++++ b/plugins/power/gsd-power-manager.c +@@ -59,6 +59,10 @@ + #define UPOWER_DBUS_INTERFACE "org.freedesktop.UPower" + #define UPOWER_DBUS_INTERFACE_KBDBACKLIGHT "org.freedesktop.UPower.KbdBacklight" + ++#define PPD_DBUS_NAME "net.hadess.PowerProfiles" ++#define PPD_DBUS_PATH "/net/hadess/PowerProfiles" ++#define PPD_DBUS_INTERFACE "net.hadess.PowerProfiles" ++ + #define GSD_POWER_SETTINGS_SCHEMA "org.gnome.settings-daemon.plugins.power" + + #define GSD_POWER_DBUS_NAME GSD_DBUS_NAME ".Power" +@@ -185,6 +189,10 @@ struct _GsdPowerManager + gdouble ambient_last_absolute; + gint64 ambient_last_time; + ++ /* Power Profiles */ ++ GDBusProxy *power_profiles_proxy; ++ guint32 power_saver_cookie; ++ + /* Sound */ + guint32 critical_alert_timeout_id; + +@@ -1927,6 +1935,67 @@ idle_configure (GsdPowerManager *manager) + } + } + ++static void ++hold_profile_cb (GObject *source_object, ++ GAsyncResult *res, ++ gpointer user_data) ++{ ++ GsdPowerManager *manager = user_data; ++ g_autoptr(GError) error = NULL; ++ g_autoptr(GVariant) result = NULL; ++ ++ result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), ++ res, ++ &error); ++ if (result == NULL) { ++ g_warning ("Couldn't hold power-saver profile: %s", error->message); ++ return; ++ } ++ ++ if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(u)"))) { ++ g_variant_get (result, "(u)", &manager->power_saver_cookie); ++ g_debug ("Holding power-saver profile with cookie %u", manager->power_saver_cookie); ++ } else { ++ g_warning ("Calling HoldProfile() did not return a uint32"); ++ } ++} ++ ++static void ++enable_power_saver (GsdPowerManager *manager) ++{ ++ if (!manager->power_profiles_proxy) ++ return; ++ if (!g_settings_get_boolean (manager->settings, "power-saver-profile-on-low-battery")) ++ return; ++ ++ g_debug ("Starting hold of power-saver profile"); ++ ++ g_dbus_proxy_call (manager->power_profiles_proxy, ++ "HoldProfile", ++ g_variant_new("(sss)", ++ "power-saver", ++ "Power saver profile when low on battery", ++ GSD_POWER_DBUS_NAME), ++ G_DBUS_CALL_FLAGS_NONE, ++ -1, manager->cancellable, hold_profile_cb, manager); ++} ++ ++static void ++disable_power_saver (GsdPowerManager *manager) ++{ ++ if (!manager->power_profiles_proxy || manager->power_saver_cookie == 0) ++ return; ++ ++ g_debug ("Releasing power-saver profile"); ++ ++ g_dbus_proxy_call (manager->power_profiles_proxy, ++ "ReleaseProfile", ++ g_variant_new ("(u)", manager->power_saver_cookie), ++ G_DBUS_CALL_FLAGS_NONE, ++ -1, NULL, dbus_call_log_error, "ReleaseProfile failed"); ++ manager->power_saver_cookie = 0; ++} ++ + static void + main_battery_or_ups_low_changed (GsdPowerManager *manager, + gboolean is_low) +@@ -1935,6 +2004,10 @@ main_battery_or_ups_low_changed (GsdPowerManager *manager, + return; + manager->battery_is_low = is_low; + idle_configure (manager); ++ if (is_low) ++ enable_power_saver (manager); ++ else ++ disable_power_saver (manager); + } + + static gboolean +@@ -2078,6 +2151,39 @@ screensaver_signal_cb (GDBusProxy *proxy, + handle_wake_up_screen (GSD_POWER_MANAGER (user_data)); + } + ++static void ++power_profiles_proxy_signal_cb (GDBusProxy *proxy, ++ const gchar *sender_name, ++ const gchar *signal_name, ++ GVariant *parameters, ++ gpointer user_data) ++{ ++ GsdPowerManager *manager = GSD_POWER_MANAGER (user_data); ++ ++ if (g_strcmp0 (signal_name, "ProfileReleased") != 0) ++ return; ++ manager->power_saver_cookie = 0; ++} ++ ++static void ++power_profiles_proxy_ready_cb (GObject *source_object, ++ GAsyncResult *res, ++ gpointer user_data) ++{ ++ g_autoptr(GError) error = NULL; ++ GsdPowerManager *manager = GSD_POWER_MANAGER (user_data); ++ ++ manager->power_profiles_proxy = g_dbus_proxy_new_for_bus_finish (res, &error); ++ if (manager->power_profiles_proxy == NULL) { ++ g_debug ("Could not connect to power-profiles-daemon: %s", error->message); ++ return; ++ } ++ ++ g_signal_connect (manager->power_profiles_proxy, "g-signal", ++ G_CALLBACK (power_profiles_proxy_signal_cb), ++ manager); ++} ++ + static void + power_keyboard_proxy_ready_cb (GObject *source_object, + GAsyncResult *res, +@@ -2289,6 +2395,14 @@ engine_settings_key_changed_cb (GSettings *settings, + idle_configure (manager); + return; + } ++ if (g_str_equal (key, "power-saver-profile-on-low-battery")) { ++ if (manager->battery_is_low && ++ g_settings_get_boolean (settings, key)) ++ enable_power_saver (manager); ++ else ++ disable_power_saver (manager); ++ return; ++ } + } + + static void +@@ -2599,6 +2713,17 @@ on_rr_screen_acquired (GObject *object, + g_signal_connect (manager->up_client, "notify::on-battery", + G_CALLBACK (up_client_on_battery_cb), manager); + ++ /* connect to power-profiles-daemon */ ++ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, ++ G_DBUS_PROXY_FLAGS_NONE, ++ NULL, ++ PPD_DBUS_NAME, ++ PPD_DBUS_PATH, ++ PPD_DBUS_INTERFACE, ++ manager->cancellable, ++ power_profiles_proxy_ready_cb, ++ manager); ++ + /* connect to UPower for keyboard backlight control */ + manager->kbd_brightness_now = -1; + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, +@@ -2862,6 +2987,9 @@ gsd_power_manager_stop (GsdPowerManager *manager) + + g_clear_object (&manager->screensaver_proxy); + ++ disable_power_saver (manager); ++ g_clear_object (&manager->power_profiles_proxy); ++ + play_loop_stop (&manager->critical_alert_timeout_id); + + g_clear_object (&manager->idle_monitor); +diff --git a/plugins/power/test.py b/plugins/power/test.py +index bb5861a4..f554400e 100755 +--- a/plugins/power/test.py ++++ b/plugins/power/test.py +@@ -76,6 +76,13 @@ class PowerPluginBase(gsdtestcase.GSDTestCase): + 'gnome_screensaver', stdout=subprocess.PIPE) + gsdtestcase.set_nonblock(self.screensaver.stdout) + ++ # start mock power-profiles-daemon ++ try: ++ (self.ppd, self.obj_ppd) = self.spawn_server_template('power_profiles_daemon') ++ self.addCleanup(self.stop_process, self.ppd) ++ except ModuleNotFoundError: ++ self.ppd = None ++ + self.session_log = OutputChecker() + self.session = subprocess.Popen(['gnome-session', '-f', + '-a', os.path.join(self.workdir, 'autostart'), +@@ -1302,5 +1309,30 @@ class PowerPluginTest8(PowerPluginBase): + + self.assertEqual(exc.exception.get_dbus_message(), 'No usable backlight could be found!') + ++ def test_power_saver_on_low_battery(self): ++ '''Check that the power-saver profile gets held when low on battery''' ++ ++ if not self.ppd: ++ self.skipTest("power-profiles-daemon dbusmock support is not available") ++ ++ obj_props = dbus.Interface(self.obj_ppd, dbus.PROPERTIES_IFACE) ++ ++ self.set_composite_battery_discharging() ++ time.sleep(0.5) ++ holds = obj_props.Get('net.hadess.PowerProfiles', 'ActiveProfileHolds') ++ self.assertEqual(len(holds), 0) ++ ++ self.set_composite_battery_critical() ++ time.sleep(0.5) ++ holds = obj_props.Get('net.hadess.PowerProfiles', 'ActiveProfileHolds') ++ self.assertEqual(len(holds), 1) ++ self.assertEqual(holds[0]['Profile'], 'power-saver') ++ self.assertEqual(holds[0]['ApplicationId'], 'org.gnome.SettingsDaemon.Power') ++ ++ self.set_composite_battery_discharging() ++ time.sleep(0.5) ++ holds = obj_props.Get('net.hadess.PowerProfiles', 'ActiveProfileHolds') ++ self.assertEqual(len(holds), 0) ++ + # avoid writing to stderr + unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=2)) +-- +2.31.1 + + +From 74ed476d1a37a43eeba8c8bee8f5be5d499b0805 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Wed, 28 Jul 2021 16:40:24 +0200 +Subject: [PATCH 2/4] power: Dim screen faster if power saver mode is on + +As done on other platforms, aggressively dim the screen after a +short period when the user has selected to enter power saver mode. + +The same aggressive screen dim will be used if the battery is low and +power-profiles-daemon is not available. If it is available, then it +fixes a screen dim happening when the battery was low which might +have been unwanted. + +See https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/232 + +Prior art: +https://support.apple.com/en-us/HT205234 +--- + plugins/power/gsd-power-manager.c | 46 +++++++++++++++++++++++++++++-- + 1 file changed, 44 insertions(+), 2 deletions(-) + +diff --git a/plugins/power/gsd-power-manager.c b/plugins/power/gsd-power-manager.c +index 1f125a6f..cfef9718 100644 +--- a/plugins/power/gsd-power-manager.c ++++ b/plugins/power/gsd-power-manager.c +@@ -192,6 +192,7 @@ struct _GsdPowerManager + /* Power Profiles */ + GDBusProxy *power_profiles_proxy; + guint32 power_saver_cookie; ++ gboolean power_saver_enabled; + + /* Sound */ + guint32 critical_alert_timeout_id; +@@ -1780,6 +1781,20 @@ clear_idle_watch (GnomeIdleMonitor *monitor, + *id = 0; + } + ++static gboolean ++is_power_save_active (GsdPowerManager *manager) ++{ ++ /* ++ * If we have power-profiles-daemon, then we follow its setting, ++ * otherwise we go into power-save mode when the battery is low. ++ */ ++ if (manager->power_profiles_proxy && ++ g_dbus_proxy_get_name_owner (manager->power_profiles_proxy)) ++ return manager->power_saver_enabled; ++ else ++ return manager->battery_is_low; ++} ++ + static void + idle_configure (GsdPowerManager *manager) + { +@@ -1903,8 +1918,8 @@ idle_configure (GsdPowerManager *manager) + /* Don't dim when the screen lock is active */ + } else if (!on_battery) { + /* Don't dim when charging */ +- } else if (manager->battery_is_low) { +- /* Aggressively blank when battery is low */ ++ } else if (is_power_save_active (manager)) { ++ /* Try to save power by dimming agressively */ + timeout_dim = SCREENSAVER_TIMEOUT_BLANK; + } else { + if (g_settings_get_boolean (manager->settings, "idle-dim")) { +@@ -2165,6 +2180,27 @@ power_profiles_proxy_signal_cb (GDBusProxy *proxy, + manager->power_saver_cookie = 0; + } + ++static void ++update_active_power_profile (GsdPowerManager *manager) ++{ ++ g_autoptr(GVariant) v = NULL; ++ const char *active_profile; ++ gboolean power_saver_enabled; ++ ++ v = g_dbus_proxy_get_cached_property (manager->power_profiles_proxy, "ActiveProfile"); ++ if (v) { ++ active_profile = g_variant_get_string (v, NULL); ++ power_saver_enabled = g_strcmp0 (active_profile, "power-saver") == 0; ++ if (power_saver_enabled != manager->power_saver_enabled) { ++ manager->power_saver_enabled = power_saver_enabled; ++ idle_configure (manager); ++ } ++ } else { ++ /* p-p-d might have disappeared from the bus */ ++ idle_configure (manager); ++ } ++} ++ + static void + power_profiles_proxy_ready_cb (GObject *source_object, + GAsyncResult *res, +@@ -2179,9 +2215,15 @@ power_profiles_proxy_ready_cb (GObject *source_object, + return; + } + ++ g_signal_connect_swapped (manager->power_profiles_proxy, ++ "g-properties-changed", ++ G_CALLBACK (update_active_power_profile), ++ manager); + g_signal_connect (manager->power_profiles_proxy, "g-signal", + G_CALLBACK (power_profiles_proxy_signal_cb), + manager); ++ ++ update_active_power_profile (manager); + } + + static void +-- +2.31.1 + + +From 89e25ed7871258aa6df7f824e226a7b8a28f23f3 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Thu, 29 Jul 2021 12:05:40 +0200 +Subject: [PATCH 3/4] power: Respect dim screen settings when not on battery + +The dim screen settings in the UI was not well respected as it only +worked on discharging laptops. + +Closes: https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/837 +--- + plugins/power/gsd-power-manager.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/plugins/power/gsd-power-manager.c b/plugins/power/gsd-power-manager.c +index cfef9718..e7b9752f 100644 +--- a/plugins/power/gsd-power-manager.c ++++ b/plugins/power/gsd-power-manager.c +@@ -1916,8 +1916,6 @@ idle_configure (GsdPowerManager *manager) + timeout_dim = 0; + if (manager->screensaver_active) { + /* Don't dim when the screen lock is active */ +- } else if (!on_battery) { +- /* Don't dim when charging */ + } else if (is_power_save_active (manager)) { + /* Try to save power by dimming agressively */ + timeout_dim = SCREENSAVER_TIMEOUT_BLANK; +-- +2.31.1 + + +From f91abc0033b9cf17fd0e171cb7d652f88edac294 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Mon, 9 Aug 2021 17:57:11 +0200 +Subject: [PATCH 4/4] power: When dimming the screen, dim it quicker by default + +Now that we respect the "dim when idle" setting[1], dim quicker to try +and save more power. 4/5 of the timeout to the screensaver was always a +bit too undecided as a fraction, even when using the dimming as a +warning that the screen was going to go to the screensaver (see commit +7bc750a5). + +[1]: Except in power-saver mode where we always dim aggressively +--- + plugins/power/gsd-power-constants.h | 2 +- + plugins/power/gsdpowerconstants.py | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/plugins/power/gsd-power-constants.h b/plugins/power/gsd-power-constants.h +index 91e2296a..8bf9c641 100644 +--- a/plugins/power/gsd-power-constants.h ++++ b/plugins/power/gsd-power-constants.h +@@ -25,7 +25,7 @@ + #define IDLE_DIM_BLANK_DISABLED_MIN 60 /* seconds */ + + /* Which fraction of the idle-delay is the idle-dim delay */ +-#define IDLE_DELAY_TO_IDLE_DIM_MULTIPLIER 4.0/5.0 ++#define IDLE_DELAY_TO_IDLE_DIM_MULTIPLIER 1.0/2.0 + + /* The dim delay under which we do not bother dimming */ + #define MINIMUM_IDLE_DIM_DELAY 10 /* seconds */ +diff --git a/plugins/power/gsdpowerconstants.py b/plugins/power/gsdpowerconstants.py +index a07798ee..26fa5bfc 100644 +--- a/plugins/power/gsdpowerconstants.py ++++ b/plugins/power/gsdpowerconstants.py +@@ -8,7 +8,7 @@ + + SCREENSAVER_TIMEOUT_BLANK = 15; + IDLE_DIM_BLANK_DISABLED_MIN = 60; +-IDLE_DELAY_TO_IDLE_DIM_MULTIPLIER = 4.0/5.0; ++IDLE_DELAY_TO_IDLE_DIM_MULTIPLIER = 1.0/2.0; + MINIMUM_IDLE_DIM_DELAY = 10; + POWER_UP_TIME_ON_AC = 15; + GSD_MOCK_DEFAULT_BRIGHTNESS = 50; +-- +2.31.1 + diff --git a/SOURCES/0001-power-Respect-the-nothing-power-button-action-for-VM.patch b/SOURCES/0001-power-Respect-the-nothing-power-button-action-for-VM.patch new file mode 100644 index 0000000..fbd79b1 --- /dev/null +++ b/SOURCES/0001-power-Respect-the-nothing-power-button-action-for-VM.patch @@ -0,0 +1,57 @@ +From f71fb47c3f783f3405bd910e1e170dc5e1f10e7c Mon Sep 17 00:00:00 2001 +From: Felipe Borges +Date: Wed, 4 Jan 2023 13:41:31 +0100 +Subject: [PATCH] power: Respect the "nothing" power-button-action for VMs + +There are use-cases when one wants to forcefully make the guest ignore +poweroff requests from the hypervisor. + +See https://bugzilla.redhat.com/2062051 + +See also https://gitlab.gnome.org/GNOME/gnome-settings-daemon/-/issues/46 +--- + ....gnome.settings-daemon.plugins.power.gschema.xml.in | 2 +- + plugins/media-keys/gsd-media-keys-manager.c | 10 +++++++--- + 2 files changed, 8 insertions(+), 4 deletions(-) + +diff --git a/data/org.gnome.settings-daemon.plugins.power.gschema.xml.in b/data/org.gnome.settings-daemon.plugins.power.gschema.xml.in +index 04b287bd..e1a8787b 100644 +--- a/data/org.gnome.settings-daemon.plugins.power.gschema.xml.in ++++ b/data/org.gnome.settings-daemon.plugins.power.gschema.xml.in +@@ -39,7 +39,7 @@ + + 'suspend' + Power button action +- The action to take when the system power button is pressed. This action is hard-coded (and the setting ignored) on virtual machines (power off) and tablets (suspend). ++ The action to take when the system power button is pressed. Virtual machines only honor the 'nothing' action, and will shutdown otherwise. Tablets always suspend, ignoring all the other action options. + + + true +diff --git a/plugins/media-keys/gsd-media-keys-manager.c b/plugins/media-keys/gsd-media-keys-manager.c +index 15e96e0e..60ff2ced 100644 +--- a/plugins/media-keys/gsd-media-keys-manager.c ++++ b/plugins/media-keys/gsd-media-keys-manager.c +@@ -2041,13 +2041,17 @@ do_config_power_button_action (GsdMediaKeysManager *manager, + if (priv->power_button_disabled) + return; + +- /* Always power off VMs when power off is pressed in the menus */ ++ action_type = g_settings_get_enum (priv->power_settings, "power-button-action"); ++ /* Always power off VMs, except when power-button-action is "nothing" */ + if (g_strcmp0 (priv->chassis_type, "vm") == 0) { +- power_action (manager, "PowerOff", !in_lock_screen); ++ g_warning_once ("Virtual machines only honor the 'nothing' power-button-action, and will shutdown otherwise"); ++ ++ if (action_type != GSD_POWER_BUTTON_ACTION_NOTHING) ++ power_action (manager, "PowerOff", FALSE); ++ + return; + } + +- action_type = g_settings_get_enum (priv->power_settings, "power-button-action"); + switch (action_type) { + case GSD_POWER_BUTTON_ACTION_SUSPEND: + action = GSD_POWER_ACTION_SUSPEND; +-- +2.37.1 + diff --git a/SOURCES/im-module-setting-fix.patch b/SOURCES/im-module-setting-fix.patch new file mode 100644 index 0000000..6673c25 --- /dev/null +++ b/SOURCES/im-module-setting-fix.patch @@ -0,0 +1,561 @@ +From 6ab152961de63dec953981aea24a7f0b4e7949ec Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Fri, 3 Dec 2021 23:38:50 +0100 +Subject: [PATCH 1/3] xsettings: Adopt code to look up GTK IM module + +Right now, gsd-keyboard and gsd-xsettings have a strange relation +where the first sets the gtk-im-module dconf setting for the latter +to read the setting and forward it through XSettings. + +Since this detection is highly X11 specific, make it happen in the +Xsettings daemon itself, from the relevant setting and device presence. + +This makes users still able to shoot themselves in the foot by changing +the setting, X11 clients able to be told to switch to ibus if it turns +out necessary, and Wayland clients unaffected otherwise. + +Related: https://gitlab.gnome.org/GNOME/gtk/-/issues/4443 +--- + plugins/keyboard/gsd-keyboard-manager.c | 147 --------------------- + plugins/xsettings/gsd-xsettings-manager.c | 153 ++++++++++++++++++++++ + 2 files changed, 153 insertions(+), 147 deletions(-) + +diff --git a/plugins/keyboard/gsd-keyboard-manager.c b/plugins/keyboard/gsd-keyboard-manager.c +index cb4ea98b..d41393bc 100644 +--- a/plugins/keyboard/gsd-keyboard-manager.c ++++ b/plugins/keyboard/gsd-keyboard-manager.c +@@ -57,10 +57,6 @@ + + #define GNOME_DESKTOP_INTERFACE_DIR "org.gnome.desktop.interface" + +-#define KEY_GTK_IM_MODULE "gtk-im-module" +-#define GTK_IM_MODULE_SIMPLE "gtk-im-context-simple" +-#define GTK_IM_MODULE_IBUS "ibus" +- + #define GNOME_DESKTOP_INPUT_SOURCES_DIR "org.gnome.desktop.input-sources" + + #define KEY_INPUT_SOURCES "sources" +@@ -71,9 +67,6 @@ + + #define DEFAULT_LAYOUT "us" + +-#define GNOME_A11Y_APPLICATIONS_INTERFACE_DIR "org.gnome.desktop.a11y.applications" +-#define KEY_OSK_ENABLED "screen-keyboard-enabled" +- + struct _GsdKeyboardManager + { + GObject parent; +@@ -81,21 +74,14 @@ struct _GsdKeyboardManager + guint start_idle_id; + GSettings *settings; + GSettings *input_sources_settings; +- GSettings *a11y_settings; + GDBusProxy *localed; + GCancellable *cancellable; +- +- GdkDeviceManager *device_manager; +- guint device_added_id; +- guint device_removed_id; + }; + + static void gsd_keyboard_manager_class_init (GsdKeyboardManagerClass *klass); + static void gsd_keyboard_manager_init (GsdKeyboardManager *keyboard_manager); + static void gsd_keyboard_manager_finalize (GObject *object); + +-static void update_gtk_im_module (GsdKeyboardManager *manager); +- + G_DEFINE_TYPE (GsdKeyboardManager, gsd_keyboard_manager, G_TYPE_OBJECT) + + static gpointer manager_object = NULL; +@@ -218,121 +204,6 @@ settings_changed (GSettings *settings, + + } + +-static void +-device_added_cb (GdkDeviceManager *device_manager, +- GdkDevice *device, +- GsdKeyboardManager *manager) +-{ +- GdkInputSource source; +- +- source = gdk_device_get_source (device); +- if (source == GDK_SOURCE_TOUCHSCREEN) { +- update_gtk_im_module (manager); +- } +-} +- +-static void +-device_removed_cb (GdkDeviceManager *device_manager, +- GdkDevice *device, +- GsdKeyboardManager *manager) +-{ +- GdkInputSource source; +- +- source = gdk_device_get_source (device); +- if (source == GDK_SOURCE_TOUCHSCREEN) +- update_gtk_im_module (manager); +-} +- +-static void +-set_devicepresence_handler (GsdKeyboardManager *manager) +-{ +- GdkDeviceManager *device_manager; +- +- if (gnome_settings_is_wayland ()) +- return; +- +- device_manager = gdk_display_get_device_manager (gdk_display_get_default ()); +- +- manager->device_added_id = g_signal_connect (G_OBJECT (device_manager), "device-added", +- G_CALLBACK (device_added_cb), manager); +- manager->device_removed_id = g_signal_connect (G_OBJECT (device_manager), "device-removed", +- G_CALLBACK (device_removed_cb), manager); +- manager->device_manager = device_manager; +-} +- +-static gboolean +-need_ibus (GVariant *sources) +-{ +- GVariantIter iter; +- const gchar *type; +- +- g_variant_iter_init (&iter, sources); +- while (g_variant_iter_next (&iter, "(&s&s)", &type, NULL)) +- if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS)) +- return TRUE; +- +- return FALSE; +-} +- +-static gboolean +-need_osk (GsdKeyboardManager *manager) +-{ +- gboolean has_touchscreen = FALSE; +- GList *devices; +- GdkSeat *seat; +- +- if (g_settings_get_boolean (manager->a11y_settings, +- KEY_OSK_ENABLED)) +- return TRUE; +- +- seat = gdk_display_get_default_seat (gdk_display_get_default ()); +- devices = gdk_seat_get_slaves (seat, GDK_SEAT_CAPABILITY_TOUCH); +- +- has_touchscreen = devices != NULL; +- +- g_list_free (devices); +- +- return has_touchscreen; +-} +- +-static void +-set_gtk_im_module (GsdKeyboardManager *manager, +- GSettings *settings, +- GVariant *sources) +-{ +- const gchar *new_module; +- gchar *current_module; +- +- if (need_ibus (sources) || need_osk (manager)) +- new_module = GTK_IM_MODULE_IBUS; +- else +- new_module = GTK_IM_MODULE_SIMPLE; +- +- current_module = g_settings_get_string (settings, KEY_GTK_IM_MODULE); +- if (!g_str_equal (current_module, new_module)) +- g_settings_set_string (settings, KEY_GTK_IM_MODULE, new_module); +- g_free (current_module); +-} +- +-static void +-update_gtk_im_module (GsdKeyboardManager *manager) +-{ +- GSettings *interface_settings; +- GVariant *sources; +- +- /* Gtk+ uses the IM module advertised in XSETTINGS so, if we +- * have IBus input sources, we want it to load that +- * module. Otherwise we can use the default "simple" module +- * which is builtin gtk+ +- */ +- interface_settings = g_settings_new (GNOME_DESKTOP_INTERFACE_DIR); +- sources = g_settings_get_value (manager->input_sources_settings, +- KEY_INPUT_SOURCES); +- set_gtk_im_module (manager, interface_settings, sources); +- g_object_unref (interface_settings); +- g_variant_unref (sources); +-} +- + static void + get_sources_from_xkb_config (GsdKeyboardManager *manager) + { +@@ -580,18 +451,7 @@ start_keyboard_idle_cb (GsdKeyboardManager *manager) + + manager->settings = g_settings_new (GSD_KEYBOARD_DIR); + +- set_devicepresence_handler (manager); +- + manager->input_sources_settings = g_settings_new (GNOME_DESKTOP_INPUT_SOURCES_DIR); +- g_signal_connect_swapped (manager->input_sources_settings, +- "changed::" KEY_INPUT_SOURCES, +- G_CALLBACK (update_gtk_im_module), manager); +- +- manager->a11y_settings = g_settings_new (GNOME_A11Y_APPLICATIONS_INTERFACE_DIR); +- g_signal_connect_swapped (manager->a11y_settings, +- "changed::" KEY_OSK_ENABLED, +- G_CALLBACK (update_gtk_im_module), manager); +- update_gtk_im_module (manager); + + manager->cancellable = g_cancellable_new (); + +@@ -645,14 +505,7 @@ gsd_keyboard_manager_stop (GsdKeyboardManager *manager) + + g_clear_object (&manager->settings); + g_clear_object (&manager->input_sources_settings); +- g_clear_object (&manager->a11y_settings); + g_clear_object (&manager->localed); +- +- if (manager->device_manager != NULL) { +- g_signal_handler_disconnect (manager->device_manager, manager->device_added_id); +- g_signal_handler_disconnect (manager->device_manager, manager->device_removed_id); +- manager->device_manager = NULL; +- } + } + + static void +diff --git a/plugins/xsettings/gsd-xsettings-manager.c b/plugins/xsettings/gsd-xsettings-manager.c +index 5f1b4583..1aa020db 100644 +--- a/plugins/xsettings/gsd-xsettings-manager.c ++++ b/plugins/xsettings/gsd-xsettings-manager.c +@@ -56,6 +56,9 @@ + #define PRIVACY_SETTINGS_SCHEMA "org.gnome.desktop.privacy" + #define WM_SETTINGS_SCHEMA "org.gnome.desktop.wm.preferences" + #define A11Y_SCHEMA "org.gnome.desktop.a11y" ++#define A11Y_INTERFACE_SCHEMA "org.gnome.desktop.a11y.interface" ++#define A11Y_APPLICATIONS_SCHEMA "org.gnome.desktop.a11y.applications" ++#define INPUT_SOURCES_SCHEMA "org.gnome.desktop.input-sources" + #define CLASSIC_WM_SETTINGS_SCHEMA "org.gnome.shell.extensions.classic-overrides" + + #define XSETTINGS_PLUGIN_SCHEMA "org.gnome.settings-daemon.plugins.xsettings" +@@ -72,9 +75,18 @@ + #define FONT_HINTING_KEY "font-hinting" + #define FONT_RGBA_ORDER_KEY "font-rgba-order" + ++#define INPUT_SOURCES_KEY "sources" ++#define OSK_ENABLED_KEY "screen-keyboard-enabled" ++#define GTK_IM_MODULE_KEY "gtk-im-module" ++ + #define GTK_SETTINGS_DBUS_PATH "/org/gtk/Settings" + #define GTK_SETTINGS_DBUS_NAME "org.gtk.Settings" + ++#define INPUT_SOURCE_TYPE_IBUS "ibus" ++ ++#define GTK_IM_MODULE_SIMPLE "gtk-im-context-simple" ++#define GTK_IM_MODULE_IBUS "ibus" ++ + static const gchar introspection_xml[] = + "" + " " +@@ -277,6 +289,11 @@ struct _GsdXSettingsManager + FcMonitor *fontconfig_monitor; + gint64 fontconfig_timestamp; + ++ GSettings *interface_settings; ++ GSettings *input_sources_settings; ++ GSettings *a11y_settings; ++ GdkSeat *user_seat; ++ + GsdXSettingsGtk *gtk; + + guint introspect_properties_changed_id; +@@ -286,6 +303,9 @@ struct _GsdXSettingsManager + guint display_config_watch_id; + guint monitors_changed_id; + ++ guint device_added_id; ++ guint device_removed_id; ++ + guint shell_name_watch_id; + gboolean have_shell; + +@@ -1291,6 +1311,112 @@ migrate_settings (void) + mouse_entries, G_N_ELEMENTS (mouse_entries)); + } + ++static gboolean ++need_ibus (GsdXSettingsManager *manager) ++{ ++ GVariant *sources; ++ GVariantIter iter; ++ const gchar *type; ++ gboolean needs_ibus = FALSE; ++ ++ sources = g_settings_get_value (manager->input_sources_settings, ++ INPUT_SOURCES_KEY); ++ ++ g_variant_iter_init (&iter, sources); ++ while (g_variant_iter_next (&iter, "(&s&s)", &type, NULL)) { ++ if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS)) { ++ needs_ibus = TRUE; ++ break; ++ } ++ } ++ ++ g_variant_unref (sources); ++ ++ return needs_ibus; ++} ++ ++static gboolean ++need_osk (GsdXSettingsManager *manager) ++{ ++ gboolean has_touchscreen = FALSE; ++ GList *devices; ++ GdkSeat *seat; ++ ++ if (g_settings_get_boolean (manager->a11y_settings, ++ OSK_ENABLED_KEY)) ++ return TRUE; ++ ++ seat = gdk_display_get_default_seat (gdk_display_get_default ()); ++ devices = gdk_seat_get_slaves (seat, GDK_SEAT_CAPABILITY_TOUCH); ++ ++ has_touchscreen = devices != NULL; ++ ++ g_list_free (devices); ++ ++ return has_touchscreen; ++} ++ ++static void ++update_gtk_im_module (GsdXSettingsManager *manager) ++{ ++ const gchar *module; ++ gchar *setting; ++ ++ setting = g_settings_get_string (manager->interface_settings, ++ GTK_IM_MODULE_KEY); ++ if (setting && *setting) ++ module = setting; ++ else if (need_ibus (manager) || need_osk (manager)) ++ module = GTK_IM_MODULE_IBUS; ++ else ++ module = GTK_IM_MODULE_SIMPLE; ++ ++ xsettings_manager_set_string (manager->manager, "Gtk/IMModule", module); ++ g_free (setting); ++} ++ ++static void ++device_added_cb (GdkSeat *user_seat, ++ GdkDevice *device, ++ GsdXSettingsManager *manager) ++{ ++ GdkInputSource source; ++ ++ source = gdk_device_get_source (device); ++ if (source == GDK_SOURCE_TOUCHSCREEN) { ++ update_gtk_im_module (manager); ++ } ++} ++ ++static void ++device_removed_cb (GdkSeat *user_seat, ++ GdkDevice *device, ++ GsdXSettingsManager *manager) ++{ ++ GdkInputSource source; ++ ++ source = gdk_device_get_source (device); ++ if (source == GDK_SOURCE_TOUCHSCREEN) ++ update_gtk_im_module (manager); ++} ++ ++static void ++set_devicepresence_handler (GsdXSettingsManager *manager) ++{ ++ GdkSeat *user_seat; ++ ++ if (gnome_settings_is_wayland ()) ++ return; ++ ++ user_seat = gdk_display_get_default_seat (gdk_display_get_default ()); ++ ++ manager->device_added_id = g_signal_connect (G_OBJECT (user_seat), "device-added", ++ G_CALLBACK (device_added_cb), manager); ++ manager->device_removed_id = g_signal_connect (G_OBJECT (user_seat), "device-removed", ++ G_CALLBACK (device_removed_cb), manager); ++ manager->user_seat = user_seat; ++} ++ + gboolean + gsd_xsettings_manager_start (GsdXSettingsManager *manager, + GError **error) +@@ -1312,6 +1438,23 @@ gsd_xsettings_manager_start (GsdXSettingsManager *manager, + return FALSE; + } + ++ set_devicepresence_handler (manager); ++ manager->interface_settings = g_settings_new (INTERFACE_SETTINGS_SCHEMA); ++ g_signal_connect_swapped (manager->interface_settings, ++ "changed::" GTK_IM_MODULE_KEY, ++ G_CALLBACK (update_gtk_im_module), manager); ++ ++ manager->input_sources_settings = g_settings_new (INPUT_SOURCES_SCHEMA); ++ g_signal_connect_swapped (manager->input_sources_settings, ++ "changed::" INPUT_SOURCES_KEY, ++ G_CALLBACK (update_gtk_im_module), manager); ++ ++ manager->a11y_settings = g_settings_new (A11Y_APPLICATIONS_SCHEMA); ++ g_signal_connect_swapped (manager->a11y_settings, ++ "changed::" OSK_ENABLED_KEY, ++ G_CALLBACK (update_gtk_im_module), manager); ++ update_gtk_im_module (manager); ++ + manager->monitors_changed_id = + g_dbus_connection_signal_subscribe (manager->dbus_connection, + "org.gnome.Mutter.DisplayConfig", +@@ -1507,6 +1650,16 @@ gsd_xsettings_manager_stop (GsdXSettingsManager *manager) + g_object_unref (manager->gtk); + manager->gtk = NULL; + } ++ ++ if (manager->user_seat != NULL) { ++ g_signal_handler_disconnect (manager->user_seat, manager->device_added_id); ++ g_signal_handler_disconnect (manager->user_seat, manager->device_removed_id); ++ manager->user_seat = NULL; ++ } ++ ++ g_clear_object (&manager->a11y_settings); ++ g_clear_object (&manager->input_sources_settings); ++ g_clear_object (&manager->interface_settings); + } + + static void +-- +2.37.1 + + +From c1de15e0c7f145491482045c688e9f2d444cb041 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Tue, 15 Mar 2022 13:31:23 +0100 +Subject: [PATCH 2/3] keyboard: "Migrate" gtk-im-context setting before giving + control to user + +This setting used to be modified by gsd-keyboard at runtime, but it no +longer does. We want to leave this setting in a pristine state before +we lend control to the user in order to avoid setting leftovers make +GTK and others use the unintended IM module. + +Since the setting is actually staying on the same schema/path, there is +no nice mechanism that would help us in doing a one-time port, so rely +on a file at ~/.cache to make this happen once. In the common case, it +just adds one stat() more at startup. + +After this migration is done, the gtk-im-module setting can be considered +in full control of the user. +--- + plugins/keyboard/gsd-keyboard-manager.c | 35 +++++++++++++++++++++++++ + 1 file changed, 35 insertions(+) + +diff --git a/plugins/keyboard/gsd-keyboard-manager.c b/plugins/keyboard/gsd-keyboard-manager.c +index d41393bc..15247c78 100644 +--- a/plugins/keyboard/gsd-keyboard-manager.c ++++ b/plugins/keyboard/gsd-keyboard-manager.c +@@ -67,6 +67,8 @@ + + #define DEFAULT_LAYOUT "us" + ++#define SETTINGS_PORTED_FILE ".gsd-keyboard.settings-ported" ++ + struct _GsdKeyboardManager + { + GObject parent; +@@ -541,6 +543,14 @@ gsd_keyboard_manager_finalize (GObject *object) + G_OBJECT_CLASS (gsd_keyboard_manager_parent_class)->finalize (object); + } + ++static GVariant * ++reset_gtk_im_module (GVariant *variant, ++ GVariant *old_default, ++ GVariant *new_default) ++{ ++ return NULL; ++} ++ + static void + migrate_keyboard_settings (void) + { +@@ -550,12 +560,37 @@ migrate_keyboard_settings (void) + { "delay", "delay", NULL }, + { "remember-numlock-state", "remember-numlock-state", NULL }, + }; ++ g_autofree char *filename = NULL; + + gsd_settings_migrate_check ("org.gnome.settings-daemon.peripherals.keyboard.deprecated", + "/org/gnome/settings-daemon/peripherals/keyboard/", + "org.gnome.desktop.peripherals.keyboard", + "/org/gnome/desktop/peripherals/keyboard/", + entries, G_N_ELEMENTS (entries)); ++ ++ /* In prior versions to GNOME 42, the gtk-im-module setting was ++ * owned by gsd-keyboard. Reset it once before giving it back ++ * to the user. ++ */ ++ filename = g_build_filename (g_get_user_config_dir (), ++ SETTINGS_PORTED_FILE, ++ NULL); ++ ++ if (!g_file_test (filename, G_FILE_TEST_EXISTS)) { ++ GsdSettingsMigrateEntry im_entry[] = { ++ { "gtk-im-module", "gtk-im-module", reset_gtk_im_module }, ++ }; ++ g_autoptr(GError) error = NULL; ++ ++ gsd_settings_migrate_check ("org.gnome.desktop.interface", ++ "/org/gnome/desktop/interface/", ++ "org.gnome.desktop.interface", ++ "/org/gnome/desktop/interface/", ++ im_entry, G_N_ELEMENTS (im_entry)); ++ ++ if (!g_file_set_contents (filename, "", -1, &error)) ++ g_warning ("Error migrating gtk-im-module: %s", error->message); ++ } + } + + GsdKeyboardManager * +-- +2.37.1 + + +From 46452c04aee1bfd51e23a53dba89ac95e0c06823 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Fri, 29 Apr 2022 14:37:27 +0200 +Subject: [PATCH 3/3] xsettings: Remove direct mapping from gtk-im-module to + Gtk/IMModule + +This is now handled dynamically since commit e2d268eb00, so we should +not tie dconf setting and Xsetting automatically here. Doing so, we +are clobbering the dynamic value on startup, making it only effective +on later changes. + +Fixes: https://gitlab.gnome.org/GNOME/gnome-settings-daemon/-/issues/682 +--- + plugins/xsettings/gsd-xsettings-manager.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/plugins/xsettings/gsd-xsettings-manager.c b/plugins/xsettings/gsd-xsettings-manager.c +index 1aa020db..d692cefb 100644 +--- a/plugins/xsettings/gsd-xsettings-manager.c ++++ b/plugins/xsettings/gsd-xsettings-manager.c +@@ -498,7 +498,6 @@ static TranslationEntry translations [] = { + { "org.gnome.desktop.interface", "cursor-blink-time", "Net/CursorBlinkTime", translate_int_int }, + { "org.gnome.desktop.interface", "cursor-blink-timeout", "Gtk/CursorBlinkTimeout", translate_int_int }, + { "org.gnome.desktop.interface", "gtk-theme", "Net/ThemeName", translate_string_string }, +- { "org.gnome.desktop.interface", "gtk-im-module", "Gtk/IMModule", translate_string_string }, + { "org.gnome.desktop.interface", "icon-theme", "Net/IconThemeName", translate_string_string }, + { "org.gnome.desktop.interface", "cursor-theme", "Gtk/CursorThemeName", translate_string_string }, + { "org.gnome.desktop.interface", "gtk-enable-primary-paste", "Gtk/EnablePrimaryPaste", translate_bool_int }, +-- +2.37.1 + diff --git a/SOURCES/org.gnome.settings-daemon.plugins.power.gschema.override b/SOURCES/org.gnome.settings-daemon.plugins.power.gschema.override new file mode 100644 index 0000000..c6b28c1 --- /dev/null +++ b/SOURCES/org.gnome.settings-daemon.plugins.power.gschema.override @@ -0,0 +1,2 @@ +[org.gnome.settings-daemon.plugins.power] +sleep-inactive-ac-timeout=0 diff --git a/SOURCES/print-notifications-clear-in-stop.patch b/SOURCES/print-notifications-clear-in-stop.patch new file mode 100644 index 0000000..649defd --- /dev/null +++ b/SOURCES/print-notifications-clear-in-stop.patch @@ -0,0 +1,45 @@ +--- gnome-settings-daemon-40.0.1/plugins/print-notifications/gsd-print-notifications-manager.c ++++ gnome-settings-daemon-40.0.1/plugins/print-notifications/gsd-print-notifications-manager.c +@@ -1268,6 +1268,7 @@ scp_handler (GsdPrintNotificationsManage + kill (manager->scp_handler_pid, SIGHUP); + g_spawn_close_pid (manager->scp_handler_pid); + manager->scp_handler_spawned = FALSE; ++ manager->scp_handler_pid = -1; + } + } + +@@ -1636,8 +1636,10 @@ gsd_print_notifications_manager_stop (Gs + manager->check_source_id = 0; + } + +- if (manager->subscription_id >= 0) ++ if (manager->subscription_id >= 0) { + cancel_subscription (manager->subscription_id); ++ manager->subscription_id = -1; ++ } + + g_clear_pointer (&manager->printing_printers, g_hash_table_destroy); + +@@ -1649,6 +1651,7 @@ gsd_print_notifications_manager_stop (Gs + g_source_remove (data->timeout_id); + } + g_list_free_full (manager->timeouts, free_timeout_data); ++ manager->timeouts = NULL; + + for (tmp = manager->active_notifications; tmp; tmp = g_list_next (tmp)) { + reason_data = (ReasonData *) tmp->data; +@@ -1665,12 +1668,14 @@ gsd_print_notifications_manager_stop (Gs + } + } + g_list_free_full (manager->active_notifications, free_reason_data); ++ manager->active_notifications = NULL; + + for (tmp = manager->held_jobs; tmp; tmp = g_list_next (tmp)) { + job = (HeldJob *) tmp->data; + g_source_remove (job->timeout_id); + } + g_list_free_full (manager->held_jobs, free_held_job); ++ manager->held_jobs = NULL; + + scp_handler (manager, FALSE); + } diff --git a/SOURCES/subscription-manager-support.patch b/SOURCES/subscription-manager-support.patch new file mode 100644 index 0000000..a098a55 --- /dev/null +++ b/SOURCES/subscription-manager-support.patch @@ -0,0 +1,3612 @@ +From f73e1e8187570ddbc2fe40a78176689f12859123 Mon Sep 17 00:00:00 2001 +From: Richard Hughes +Date: Thu, 20 Aug 2020 11:16:09 -0400 +Subject: [PATCH 01/20] subman: Add a new plugin to provide system subscription + registration + +--- + meson.build | 1 + + plugins/meson.build | 1 + + plugins/subman/README.md | 56 + + plugins/subman/gsd-subman-common.c | 36 + + plugins/subman/gsd-subman-common.h | 40 + + plugins/subman/gsd-subman-helper.c | 372 +++++++ + plugins/subman/gsd-subscription-manager.c | 982 ++++++++++++++++++ + plugins/subman/gsd-subscription-manager.h | 63 ++ + plugins/subman/main.c | 8 + + plugins/subman/meson.build | 56 + + ...ome.SettingsDaemon.Subscription.desktop.in | 9 + + ...ettings-daemon.plugins.subman.policy.in.in | 27 + + ...gnome.settings-daemon.plugins.subman.rules | 7 + + 13 files changed, 1658 insertions(+) + create mode 100644 plugins/subman/README.md + create mode 100644 plugins/subman/gsd-subman-common.c + create mode 100644 plugins/subman/gsd-subman-common.h + create mode 100644 plugins/subman/gsd-subman-helper.c + create mode 100644 plugins/subman/gsd-subscription-manager.c + create mode 100644 plugins/subman/gsd-subscription-manager.h + create mode 100644 plugins/subman/main.c + create mode 100644 plugins/subman/meson.build + create mode 100644 plugins/subman/org.gnome.SettingsDaemon.Subscription.desktop.in + create mode 100644 plugins/subman/org.gnome.settings-daemon.plugins.subman.policy.in.in + create mode 100644 plugins/subman/org.gnome.settings-daemon.plugins.subman.rules + +diff --git a/meson.build b/meson.build +index ba2a90ca..3cef1ae1 100644 +--- a/meson.build ++++ b/meson.build +@@ -102,6 +102,7 @@ libcanberra_gtk_dep = dependency('libcanberra-gtk3') + libgeoclue_dep = dependency('libgeoclue-2.0', version: '>= 2.3.1') + libnotify_dep = dependency('libnotify', version: '>= 0.7.3') + libpulse_mainloop_glib_dep = dependency('libpulse-mainloop-glib', version: '>= 2.0') ++jsonglib_dep = dependency('json-glib-1.0', version: '>= 1.1.1') + pango_dep = dependency('pango', version: '>= 1.20.0') + polkit_gobject_dep = dependency('polkit-gobject-1', version: '>= 0.114') + upower_glib_dep = dependency('upower-glib', version: '>= 0.99.8') +diff --git a/plugins/meson.build b/plugins/meson.build +index 16397dc6..920b5cc9 100644 +--- a/plugins/meson.build ++++ b/plugins/meson.build +@@ -1,6 +1,7 @@ + all_plugins = [ + ['a11y-settings', 'A11ySettings', 'GNOME accessibility'], + ['color', 'Color', 'GNOME color management'], ++ ['subman', 'Subscription', 'GNOME subscription management'], + ['datetime', 'Datetime', 'GNOME date & time'], + ['power', 'Power', 'GNOME power management'], + ['housekeeping', 'Housekeeping', 'GNOME maintenance of expirable data'], +diff --git a/plugins/subman/README.md b/plugins/subman/README.md +new file mode 100644 +index 00000000..3e1cc3cd +--- /dev/null ++++ b/plugins/subman/README.md +@@ -0,0 +1,56 @@ ++GNOME Settings Daemon: Subscription Manager Plugin ++================================================== ++ ++Testing: ++ ++To add a test acccount on subscription.rhsm.stage.redhat.com, use Ethel: ++http://account-manager-stage.app.eng.rdu2.redhat.com/#view ++ ++Register with a username and password ++------------------------------------- ++ ++ gdbus call \ ++ --session \ ++ --dest org.gnome.SettingsDaemon.Subscription \ ++ --object-path /org/gnome/SettingsDaemon/Subscription \ ++ --method org.gnome.SettingsDaemon.Subscription.Register "{'kind':<'username'>,'hostname':<'subscription.rhsm.stage.redhat.com'>,'username':<'rhughes_test'>,'password':<'barbaz'>}" ++ ++To register with a certificate ++------------------------------ ++ ++ gdbus call \ ++ --session \ ++ --dest org.gnome.SettingsDaemon.Subscription \ ++ --object-path /org/gnome/SettingsDaemon/Subscription \ ++ --method org.gnome.SettingsDaemon.Subscription.Register "{'kind':<'key'>,'hostname':<'subscription.rhsm.stage.redhat.com'>,'organisation':<'foo'>,'activation-key':<'barbaz'>}" ++ ++To unregister ++------------- ++ ++ gdbus call \ ++ --session \ ++ --dest org.gnome.SettingsDaemon.Subscription \ ++ --object-path /org/gnome/SettingsDaemon/Subscription \ ++ --method org.gnome.SettingsDaemon.Subscription.Unregister ++ ++Debugging ++--------- ++ ++Get the UNIX socket using `Subscription.Register` then call something like: ++ ++ sudo G_MESSAGES_DEBUG=all ./plugins/subman/gsd-subman-helper \ ++ --address="unix:abstract=/var/run/dbus-ulGB1wfnbn,guid=71e6bf329d861ce366df7a1d5d036a5b" \ ++ --kind="register-with-username" \ ++ --username="rhughes_test" \ ++ --password="barbaz" \ ++ --hostname="subscription.rhsm.stage.redhat.com" \ ++ --organisation="" ++ ++You can all see some basic debugging running `rhsmd` in the foreground: ++ ++ sudo /usr/libexec/rhsmd -d -k ++ ++Known Limitations ++================= ++ ++Proxy servers are not supported, nor are custom host ports or prefixes. +diff --git a/plugins/subman/gsd-subman-common.c b/plugins/subman/gsd-subman-common.c +new file mode 100644 +index 00000000..e515131e +--- /dev/null ++++ b/plugins/subman/gsd-subman-common.c +@@ -0,0 +1,36 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2019 Richard Hughes ++ * ++ * 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 . ++ * ++ */ ++ ++#include "config.h" ++ ++#include "gsd-subman-common.h" ++ ++const gchar * ++gsd_subman_subscription_status_to_string (GsdSubmanSubscriptionStatus status) ++{ ++ if (status == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID) ++ return "valid"; ++ if (status == GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID) ++ return "invalid"; ++ if (status == GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED) ++ return "disabled"; ++ if (status == GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID) ++ return "partially-valid"; ++ return "unknown"; ++} +diff --git a/plugins/subman/gsd-subman-common.h b/plugins/subman/gsd-subman-common.h +new file mode 100644 +index 00000000..fccf9f6a +--- /dev/null ++++ b/plugins/subman/gsd-subman-common.h +@@ -0,0 +1,40 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2019 Richard Hughes ++ * ++ * 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 . ++ * ++ */ ++ ++#ifndef __GSD_SUBMAN_COMMON_H ++#define __GSD_SUBMAN_COMMON_H ++ ++#include ++ ++G_BEGIN_DECLS ++ ++typedef enum { ++ GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN, ++ GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID, ++ GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID, ++ GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED, ++ GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID, ++ GSD_SUBMAN_SUBSCRIPTION_STATUS_LAST ++} GsdSubmanSubscriptionStatus; ++ ++const gchar *gsd_subman_subscription_status_to_string (GsdSubmanSubscriptionStatus status); ++ ++G_END_DECLS ++ ++#endif /* __GSD_SUBMAN_COMMON_H */ +diff --git a/plugins/subman/gsd-subman-helper.c b/plugins/subman/gsd-subman-helper.c +new file mode 100644 +index 00000000..69ebec7e +--- /dev/null ++++ b/plugins/subman/gsd-subman-helper.c +@@ -0,0 +1,372 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2019 Richard Hughes ++ * ++ * Licensed under the GNU General Public License Version 2 ++ * ++ * 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, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include "config.h" ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++static void ++_helper_convert_error (const gchar *json_txt, GError **error) ++{ ++ JsonNode *json_root; ++ JsonObject *json_obj; ++ const gchar *message; ++ g_autoptr(JsonParser) json_parser = json_parser_new (); ++ ++ /* this may be plain text or JSON :| */ ++ if (!json_parser_load_from_data (json_parser, json_txt, -1, NULL)) { ++ g_set_error_literal (error, ++ G_IO_ERROR, ++ G_IO_ERROR_NOT_SUPPORTED, ++ json_txt); ++ return; ++ } ++ json_root = json_parser_get_root (json_parser); ++ json_obj = json_node_get_object (json_root); ++ if (!json_object_has_member (json_obj, "message")) { ++ g_set_error (error, ++ G_IO_ERROR, ++ G_IO_ERROR_INVALID_DATA, ++ "no message' in %s", json_txt); ++ return; ++ } ++ message = json_object_get_string_member (json_obj, "message"); ++ if (g_strstr_len (message, -1, "Invalid user credentials") != NULL) { ++ g_set_error_literal (error, ++ G_IO_ERROR, ++ G_IO_ERROR_PERMISSION_DENIED, ++ message); ++ return; ++ } ++ g_set_error_literal (error, ++ G_IO_ERROR, ++ G_IO_ERROR_NOT_SUPPORTED, ++ message); ++} ++ ++static gboolean ++_helper_unregister (GError **error) ++{ ++ g_autoptr(GDBusProxy) proxy = NULL; ++ g_autoptr(GVariantBuilder) proxy_options = NULL; ++ g_autoptr(GVariant) res = NULL; ++ ++ g_debug ("unregistering"); ++ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, ++ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | ++ G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, ++ NULL, ++ "com.redhat.RHSM1", ++ "/com/redhat/RHSM1/Unregister", ++ "com.redhat.RHSM1.Unregister", ++ NULL, error); ++ if (proxy == NULL) { ++ g_prefix_error (error, "Failed to get proxy: "); ++ return FALSE; ++ } ++ proxy_options = g_variant_builder_new (G_VARIANT_TYPE_VARDICT); ++ res = g_dbus_proxy_call_sync (proxy, ++ "Unregister", ++ g_variant_new ("(a{sv}s)", ++ proxy_options, ++ ""), /* lang */ ++ G_DBUS_CALL_FLAGS_NONE, ++ -1, NULL, error); ++ return res != NULL; ++} ++ ++static gboolean ++_helper_auto_attach (GError **error) ++{ ++ const gchar *str = NULL; ++ g_autoptr(GDBusProxy) proxy = NULL; ++ g_autoptr(GVariantBuilder) proxy_options = NULL; ++ g_autoptr(GVariant) res = NULL; ++ ++ g_debug ("auto-attaching subscriptions"); ++ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, ++ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | ++ G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, ++ NULL, ++ "com.redhat.RHSM1", ++ "/com/redhat/RHSM1/Attach", ++ "com.redhat.RHSM1.Attach", ++ NULL, error); ++ if (proxy == NULL) { ++ g_prefix_error (error, "Failed to get proxy: "); ++ return FALSE; ++ } ++ proxy_options = g_variant_builder_new (G_VARIANT_TYPE_VARDICT); ++ res = g_dbus_proxy_call_sync (proxy, ++ "AutoAttach", ++ g_variant_new ("(sa{sv}s)", ++ "", /* now? */ ++ proxy_options, ++ ""), /* lang */ ++ G_DBUS_CALL_FLAGS_NONE, ++ -1, NULL, error); ++ if (res == NULL) ++ return FALSE; ++ g_variant_get (res, "(&s)", &str); ++ g_debug ("Attach.AutoAttach: %s", str); ++ return TRUE; ++} ++ ++static gboolean ++_helper_save_config (const gchar *key, const gchar *value, GError **error) ++{ ++ g_autoptr(GDBusProxy) proxy = NULL; ++ g_autoptr(GVariant) res = NULL; ++ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, ++ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | ++ G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, ++ NULL, ++ "com.redhat.RHSM1", ++ "/com/redhat/RHSM1/Config", ++ "com.redhat.RHSM1.Config", ++ NULL, error); ++ if (proxy == NULL) { ++ g_prefix_error (error, "Failed to get proxy: "); ++ return FALSE; ++ } ++ res = g_dbus_proxy_call_sync (proxy, "Set", ++ g_variant_new ("(svs)", ++ key, ++ g_variant_new_string (value), ++ ""), /* lang */ ++ G_DBUS_CALL_FLAGS_NONE, ++ -1, NULL, error); ++ return res != NULL; ++} ++ ++int ++main (int argc, char *argv[]) ++{ ++ const gchar *userlang = ""; /* as root, so no translations */ ++ g_autofree gchar *activation_key = NULL; ++ g_autofree gchar *address = NULL; ++ g_autofree gchar *hostname = NULL; ++ g_autofree gchar *kind = NULL; ++ g_autofree gchar *organisation = NULL; ++ g_autofree gchar *password = NULL; ++ g_autofree gchar *port = NULL; ++ g_autofree gchar *prefix = NULL; ++ g_autofree gchar *proxy_server = NULL; ++ g_autofree gchar *username = NULL; ++ g_autoptr(GDBusConnection) conn_private = NULL; ++ g_autoptr(GDBusProxy) proxy = NULL; ++ g_autoptr(GError) error = NULL; ++ g_autoptr(GOptionContext) context = g_option_context_new (NULL); ++ g_autoptr(GVariantBuilder) proxy_options = NULL; ++ g_autoptr(GVariantBuilder) subman_conopts = NULL; ++ g_autoptr(GVariantBuilder) subman_options = NULL; ++ ++ const GOptionEntry options[] = { ++ { "kind", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, ++ &kind, "Kind, e.g. 'username' or 'key'", NULL }, ++ { "address", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, ++ &address, "UNIX address", NULL }, ++ { "username", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, ++ &username, "Username", NULL }, ++ { "password", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, ++ &password, "Password", NULL }, ++ { "organisation", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, ++ &organisation, "Organisation", NULL }, ++ { "activation-key", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, ++ &activation_key, "Activation keys", NULL }, ++ { "hostname", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, ++ &hostname, "Registration server hostname", NULL }, ++ { "prefix", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, ++ &prefix, "Registration server prefix", NULL }, ++ { "port", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, ++ &port, "Registration server port", NULL }, ++ { "proxy", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, ++ &proxy_server, "Proxy settings", NULL }, ++ { NULL} ++ }; ++ ++ /* check calling UID */ ++ if (getuid () != 0 || geteuid () != 0) { ++ g_printerr ("This program can only be used by the root user\n"); ++ return G_IO_ERROR_NOT_SUPPORTED; ++ } ++ g_option_context_add_main_entries (context, options, NULL); ++ if (!g_option_context_parse (context, &argc, &argv, &error)) { ++ g_printerr ("Failed to parse arguments: %s\n", error->message); ++ return G_IO_ERROR_NOT_SUPPORTED; ++ } ++ ++ /* uncommon actions */ ++ if (kind == NULL) { ++ g_printerr ("No --kind specified\n"); ++ return G_IO_ERROR_INVALID_DATA; ++ } ++ if (g_strcmp0 (kind, "unregister") == 0) { ++ if (!_helper_unregister (&error)) { ++ g_printerr ("Failed to Unregister: %s\n", error->message); ++ return G_IO_ERROR_NOT_INITIALIZED; ++ } ++ return EXIT_SUCCESS; ++ } ++ if (g_strcmp0 (kind, "auto-attach") == 0) { ++ if (!_helper_auto_attach (&error)) { ++ g_printerr ("Failed to AutoAttach: %s\n", error->message); ++ return G_IO_ERROR_NOT_INITIALIZED; ++ } ++ return EXIT_SUCCESS; ++ } ++ ++ /* connect to abstract socket for reasons */ ++ if (address == NULL) { ++ g_printerr ("No --address specified\n"); ++ return G_IO_ERROR_INVALID_DATA; ++ } ++ conn_private = g_dbus_connection_new_for_address_sync (address, ++ G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, ++ NULL, NULL, ++ &error); ++ if (conn_private == NULL) { ++ g_printerr ("Invalid --address specified: %s\n", error->message); ++ return G_IO_ERROR_INVALID_DATA; ++ } ++ proxy = g_dbus_proxy_new_sync (conn_private, ++ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, ++ NULL, /* GDBusInterfaceInfo */ ++ NULL, /* name */ ++ "/com/redhat/RHSM1/Register", ++ "com.redhat.RHSM1.Register", ++ NULL, &error); ++ if (proxy == NULL) { ++ g_printerr ("Count not contact RHSM: %s\n", error->message); ++ return G_IO_ERROR_NOT_FOUND; ++ } ++ ++ /* enable_content=1 auto attaches the subscription */ ++ subman_options = g_variant_builder_new (G_VARIANT_TYPE("a{ss}")); ++ ++ g_variant_builder_add (subman_options, "{ss}", "enable_content", "1"); ++ ++ /* set registration server */ ++ if (hostname == NULL || hostname[0] == '\0') ++ hostname = g_strdup ("subscription.rhsm.redhat.com"); ++ if (prefix == NULL || prefix[0] == '\0') ++ prefix = g_strdup ("/subscription"); ++ if (port == NULL || port[0] == '\0') ++ port = g_strdup ("443"); ++ subman_conopts = g_variant_builder_new (G_VARIANT_TYPE("a{ss}")); ++ g_variant_builder_add (subman_conopts, "{ss}", "host", hostname); ++ g_variant_builder_add (subman_conopts, "{ss}", "handler", prefix); ++ g_variant_builder_add (subman_conopts, "{ss}", "port", port); ++ ++ /* call into RHSM */ ++ if (g_strcmp0 (kind, "register-with-key") == 0) { ++ g_auto(GStrv) activation_keys = NULL; ++ g_autoptr(GError) error_local = NULL; ++ g_autoptr(GVariant) res = NULL; ++ ++ if (activation_key == NULL) { ++ g_printerr ("Required --activation-key\n"); ++ return G_IO_ERROR_INVALID_DATA; ++ } ++ if (organisation == NULL) { ++ g_printerr ("Required --organisation\n"); ++ return G_IO_ERROR_INVALID_DATA; ++ } ++ ++ g_debug ("registering using activation key"); ++ activation_keys = g_strsplit (activation_key, ",", -1); ++ res = g_dbus_proxy_call_sync (proxy, ++ "RegisterWithActivationKeys", ++ g_variant_new ("(s^asa{ss}a{ss}s)", ++ organisation, ++ activation_keys, ++ subman_options, ++ subman_conopts, ++ userlang), ++ G_DBUS_CALL_FLAGS_NO_AUTO_START, ++ -1, NULL, &error_local); ++ if (res == NULL) { ++ g_dbus_error_strip_remote_error (error_local); ++ _helper_convert_error (error_local->message, &error); ++ g_printerr ("Failed to RegisterWithActivationKeys: %s\n", error->message); ++ return error->code; ++ } ++ } else if (g_strcmp0 (kind, "register-with-username") == 0) { ++ g_autoptr(GError) error_local = NULL; ++ g_autoptr(GVariant) res = NULL; ++ ++ g_debug ("registering using username and password"); ++ if (username == NULL) { ++ g_printerr ("Required --username\n"); ++ return G_IO_ERROR_INVALID_DATA; ++ } ++ if (password == NULL) { ++ g_printerr ("Required --password\n"); ++ return G_IO_ERROR_INVALID_DATA; ++ } ++ if (organisation == NULL) { ++ g_printerr ("Required --organisation\n"); ++ return G_IO_ERROR_INVALID_DATA; ++ } ++ res = g_dbus_proxy_call_sync (proxy, ++ "Register", ++ g_variant_new ("(sssa{ss}a{ss}s)", ++ organisation, ++ username, ++ password, ++ subman_options, ++ subman_conopts, ++ userlang), ++ G_DBUS_CALL_FLAGS_NO_AUTO_START, ++ -1, NULL, &error_local); ++ if (res == NULL) { ++ g_dbus_error_strip_remote_error (error_local); ++ _helper_convert_error (error_local->message, &error); ++ g_printerr ("Failed to Register: %s\n", error->message); ++ return error->code; ++ } ++ } else { ++ g_printerr ("Invalid --kind specified: %s\n", kind); ++ return G_IO_ERROR_INVALID_DATA; ++ } ++ ++ /* set the new hostname */ ++ if (!_helper_save_config ("server.hostname", hostname, &error)) { ++ g_printerr ("Failed to save hostname: %s\n", error->message); ++ return G_IO_ERROR_NOT_INITIALIZED; ++ } ++ if (!_helper_save_config ("server.prefix", prefix, &error)) { ++ g_printerr ("Failed to save prefix: %s\n", error->message); ++ return G_IO_ERROR_NOT_INITIALIZED; ++ } ++ if (!_helper_save_config ("server.port", port, &error)) { ++ g_printerr ("Failed to save port: %s\n", error->message); ++ return G_IO_ERROR_NOT_INITIALIZED; ++ } ++ ++ return EXIT_SUCCESS; ++} ++ +diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c +new file mode 100644 +index 00000000..08b13fa6 +--- /dev/null ++++ b/plugins/subman/gsd-subscription-manager.c +@@ -0,0 +1,982 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2019 Richard Hughes ++ * ++ * 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 . ++ * ++ */ ++ ++#include "config.h" ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "gnome-settings-profile.h" ++#include "gsd-subman-common.h" ++#include "gsd-subscription-manager.h" ++ ++#define GSD_DBUS_NAME "org.gnome.SettingsDaemon" ++#define GSD_DBUS_PATH "/org/gnome/SettingsDaemon" ++#define GSD_DBUS_BASE_INTERFACE "org.gnome.SettingsDaemon" ++ ++#define GSD_SUBSCRIPTION_DBUS_NAME GSD_DBUS_NAME ".Subscription" ++#define GSD_SUBSCRIPTION_DBUS_PATH GSD_DBUS_PATH "/Subscription" ++#define GSD_SUBSCRIPTION_DBUS_INTERFACE GSD_DBUS_BASE_INTERFACE ".Subscription" ++ ++static const gchar introspection_xml[] = ++"" ++" " ++" " ++" " ++" " ++" " ++" " ++" " ++""; ++ ++#define GSD_SUBSCRIPTION_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_SUBSCRIPTION_MANAGER, GsdSubscriptionManagerPrivate)) ++ ++typedef enum { ++ _RHSM_INTERFACE_CONFIG, ++ _RHSM_INTERFACE_REGISTER_SERVER, ++ _RHSM_INTERFACE_ATTACH, ++ _RHSM_INTERFACE_ENTITLEMENT, ++ _RHSM_INTERFACE_PRODUCTS, ++ _RHSM_INTERFACE_CONSUMER, ++ _RHSM_INTERFACE_SYSPURPOSE, ++ _RHSM_INTERFACE_LAST ++} _RhsmInterface; ++ ++struct GsdSubscriptionManagerPrivate ++{ ++ /* D-Bus */ ++ guint name_id; ++ GDBusNodeInfo *introspection_data; ++ GDBusConnection *connection; ++ GCancellable *bus_cancellable; ++ ++ GDBusProxy *proxies[_RHSM_INTERFACE_LAST]; ++ const gchar *userlang; /* owned by GLib internally */ ++ GHashTable *config; /* str:str */ ++ gchar *address; ++ ++ GTimer *timer_last_notified; ++ NotifyNotification *notification_expired; ++ NotifyNotification *notification_registered; ++ NotifyNotification *notification_registration_required; ++ GsdSubmanSubscriptionStatus subscription_status; ++ GsdSubmanSubscriptionStatus subscription_status_last; ++}; ++ ++enum { ++ PROP_0, ++}; ++ ++static void gsd_subscription_manager_class_init (GsdSubscriptionManagerClass *klass); ++static void gsd_subscription_manager_init (GsdSubscriptionManager *subscription_manager); ++static void gsd_subscription_manager_finalize (GObject *object); ++ ++G_DEFINE_TYPE (GsdSubscriptionManager, gsd_subscription_manager, G_TYPE_OBJECT) ++ ++static gpointer manager_object = NULL; ++ ++GQuark ++gsd_subscription_manager_error_quark (void) ++{ ++ static GQuark quark = 0; ++ if (!quark) ++ quark = g_quark_from_static_string ("gsd_subscription_manager_error"); ++ return quark; ++} ++ ++static GsdSubmanSubscriptionStatus ++_client_subscription_status_from_text (const gchar *status_txt) ++{ ++ if (g_strcmp0 (status_txt, "Unknown") == 0) ++ return GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; ++ if (g_strcmp0 (status_txt, "Current") == 0) ++ return GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID; ++ if (g_strcmp0 (status_txt, "Invalid") == 0) ++ return GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID; ++ if (g_strcmp0 (status_txt, "Disabled") == 0) ++ return GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED; ++ if (g_strcmp0 (status_txt, "Insufficient") == 0) ++ return GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID; ++ g_warning ("Unknown subscription status: %s", status_txt); // 'Current'? ++ return GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; ++} ++ ++static void ++_emit_property_changed (GsdSubscriptionManager *manager, ++ const gchar *property_name, ++ GVariant *property_value) ++{ ++ GsdSubscriptionManagerPrivate *priv = manager->priv; ++ GVariantBuilder builder; ++ GVariantBuilder invalidated_builder; ++ ++ /* not yet connected */ ++ if (priv->connection == NULL) ++ return; ++ ++ /* build the dict */ ++ g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as")); ++ g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY); ++ g_variant_builder_add (&builder, ++ "{sv}", ++ property_name, ++ property_value); ++ g_dbus_connection_emit_signal (priv->connection, ++ NULL, ++ GSD_SUBSCRIPTION_DBUS_PATH, ++ "org.freedesktop.DBus.Properties", ++ "PropertiesChanged", ++ g_variant_new ("(sa{sv}as)", ++ GSD_SUBSCRIPTION_DBUS_INTERFACE, ++ &builder, ++ &invalidated_builder), ++ NULL); ++ g_variant_builder_clear (&builder); ++ g_variant_builder_clear (&invalidated_builder); ++} ++ ++static gboolean ++_client_subscription_status_update (GsdSubscriptionManager *manager, GError **error) ++{ ++ GsdSubscriptionManagerPrivate *priv = manager->priv; ++ JsonNode *json_root; ++ JsonObject *json_obj; ++ const gchar *json_txt = NULL; ++ const gchar *status_txt = NULL; ++ g_autoptr(GVariant) val = NULL; ++ g_autoptr(JsonParser) json_parser = json_parser_new (); ++ ++ /* save old value */ ++ priv->subscription_status_last = priv->subscription_status; ++ ++ val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_ENTITLEMENT], ++ "GetStatus", ++ g_variant_new ("(ss)", ++ "", /* assumed as 'now' */ ++ priv->userlang), ++ G_DBUS_CALL_FLAGS_NONE, ++ -1, NULL, error); ++ if (val == NULL) ++ return FALSE; ++ g_variant_get (val, "(&s)", &json_txt); ++ g_debug ("Entitlement.GetStatus JSON: %s", json_txt); ++ if (!json_parser_load_from_data (json_parser, json_txt, -1, error)) ++ return FALSE; ++ json_root = json_parser_get_root (json_parser); ++ json_obj = json_node_get_object (json_root); ++ if (!json_object_has_member (json_obj, "status")) { ++ g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, ++ "no Entitlement.GetStatus status in %s", json_txt); ++ return FALSE; ++ } ++ ++ status_txt = json_object_get_string_member (json_obj, "status"); ++ g_debug ("Entitlement.GetStatus: %s", status_txt); ++ priv->subscription_status = _client_subscription_status_from_text (status_txt); ++ ++ /* emit notification for g-c-c */ ++ if (priv->subscription_status != priv->subscription_status_last) { ++ _emit_property_changed (manager, "SubscriptionStatus", ++ g_variant_new_uint32 (priv->subscription_status)); ++ } ++ ++ return TRUE; ++} ++ ++static gboolean ++_client_syspurpose_update (GsdSubscriptionManager *manager, GError **error) ++{ ++ GsdSubscriptionManagerPrivate *priv = manager->priv; ++ JsonNode *json_root; ++ JsonObject *json_obj; ++ const gchar *json_txt = NULL; ++ g_autoptr(GVariant) val = NULL; ++ g_autoptr(JsonParser) json_parser = json_parser_new (); ++ ++ val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_SYSPURPOSE], ++ "GetSyspurpose", ++ g_variant_new ("(s)", priv->userlang), ++ G_DBUS_CALL_FLAGS_NONE, ++ -1, NULL, error); ++ if (val == NULL) ++ return FALSE; ++ g_variant_get (val, "(&s)", &json_txt); ++ g_debug ("Syspurpose.GetSyspurpose JSON: %s", json_txt); ++ if (!json_parser_load_from_data (json_parser, json_txt, -1, error)) ++ return FALSE; ++ json_root = json_parser_get_root (json_parser); ++ json_obj = json_node_get_object (json_root); ++ if (!json_object_has_member (json_obj, "status")) { ++ g_debug ("Syspurpose.GetSyspurpose: Unknown"); ++ return TRUE; ++ } ++ g_debug ("Syspurpose.GetSyspurpose: '%s", json_object_get_string_member (json_obj, "status")); ++ return TRUE; ++} ++ ++static gboolean ++_client_register_start (GsdSubscriptionManager *manager, GError **error) ++{ ++ GsdSubscriptionManagerPrivate *priv = manager->priv; ++ const gchar *address = NULL; ++ g_autoptr(GDBusProxy) proxy = NULL; ++ g_autoptr(GVariant) val = NULL; ++ ++ /* already started */ ++ if (priv->address != NULL) ++ return TRUE; ++ ++ /* apparently: "we can't send registration credentials over the regular ++ * system or session bus since those aren't really locked down..." */ ++ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, ++ G_DBUS_PROXY_FLAGS_NONE, ++ NULL, ++ "com.redhat.RHSM1", ++ "/com/redhat/RHSM1/RegisterServer", ++ "com.redhat.RHSM1.RegisterServer", ++ NULL, error); ++ if (proxy == NULL) ++ return FALSE; ++ val = g_dbus_proxy_call_sync (proxy, "Start", ++ g_variant_new ("(s)", priv->userlang), ++ G_DBUS_CALL_FLAGS_NONE, ++ -1, NULL, error); ++ if (val == NULL) ++ return FALSE; ++ g_variant_get (val, "(&s)", &address); ++ g_debug ("RegisterServer.Start: %s", address); ++ priv->address = g_strdup (address); ++ return TRUE; ++} ++ ++static gboolean ++_client_register_stop (GsdSubscriptionManager *manager, GError **error) ++{ ++ GsdSubscriptionManagerPrivate *priv = manager->priv; ++ g_autoptr(GDBusProxy) proxy = NULL; ++ g_autoptr(GVariant) val = NULL; ++ ++ /* already started */ ++ if (priv->address == NULL) ++ return TRUE; ++ ++ /* stop registration server */ ++ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, ++ G_DBUS_PROXY_FLAGS_NONE, ++ NULL, ++ "com.redhat.RHSM1", ++ "/com/redhat/RHSM1/RegisterServer", ++ "com.redhat.RHSM1.RegisterServer", ++ NULL, error); ++ if (proxy == NULL) ++ return FALSE; ++ val = g_dbus_proxy_call_sync (proxy, "Stop", ++ g_variant_new ("(s)", priv->userlang), ++ G_DBUS_CALL_FLAGS_NONE, ++ -1, NULL, error); ++ if (val == NULL) ++ return FALSE; ++ g_clear_pointer (&priv->address, g_free); ++ return TRUE; ++} ++ ++static gboolean ++_client_subprocess_wait_check (GSubprocess *subprocess, GError **error) ++{ ++ gint rc; ++ if (!g_subprocess_wait (subprocess, NULL, error)) { ++ g_prefix_error (error, "failed to run pkexec: "); ++ return FALSE; ++ } ++ rc = g_subprocess_get_exit_status (subprocess); ++ if (rc != 0) { ++ GInputStream *istream = g_subprocess_get_stderr_pipe (subprocess); ++ gchar buf[1024] = { 0x0 }; ++ gsize sz = 0; ++ g_input_stream_read_all (istream, buf, sizeof(buf) - 1, &sz, NULL, NULL); ++ if (sz == 0) { ++ g_set_error_literal (error, G_IO_ERROR, rc, ++ "Failed to run helper without stderr"); ++ return FALSE; ++ } ++ g_set_error_literal (error, G_IO_ERROR, rc, buf); ++ return FALSE; ++ } ++ return TRUE; ++} ++ ++typedef enum { ++ _NOTIFY_EXPIRED, ++ _NOTIFY_REGISTRATION_REQUIRED, ++ _NOTIFY_REGISTERED ++} _NotifyKind; ++ ++static void ++_show_notification (GsdSubscriptionManager *manager, _NotifyKind notify_kind) ++{ ++ GsdSubscriptionManagerPrivate *priv = manager->priv; ++ switch (notify_kind) { ++ case _NOTIFY_EXPIRED: ++ notify_notification_close (priv->notification_registered, NULL); ++ notify_notification_close (priv->notification_registration_required, NULL); ++ notify_notification_show (priv->notification_expired, NULL); ++ break; ++ case _NOTIFY_REGISTRATION_REQUIRED: ++ notify_notification_close (priv->notification_registered, NULL); ++ notify_notification_close (priv->notification_expired, NULL); ++ notify_notification_show (priv->notification_registration_required, NULL); ++ break; ++ case _NOTIFY_REGISTERED: ++ notify_notification_close (priv->notification_expired, NULL); ++ notify_notification_close (priv->notification_registration_required, NULL); ++ notify_notification_show (priv->notification_registered, NULL); ++ break; ++ default: ++ break; ++ } ++ g_timer_reset (priv->timer_last_notified); ++} ++ ++static void ++_client_maybe__show_notification (GsdSubscriptionManager *manager) ++{ ++ GsdSubscriptionManagerPrivate *priv = manager->priv; ++ ++ /* startup */ ++ if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN && ++ priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN) { ++ _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); ++ return; ++ } ++ ++ /* something changed */ ++ if (priv->subscription_status_last != priv->subscription_status) { ++ g_debug ("transisition from subscription status '%s' to '%s'", ++ gsd_subman_subscription_status_to_string (priv->subscription_status_last), ++ gsd_subman_subscription_status_to_string (priv->subscription_status)); ++ ++ /* needs registration */ ++ if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID && ++ priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID) { ++ _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); ++ return; ++ } ++ ++ /* was unregistered */ ++ if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID && ++ priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN) { ++ _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); ++ return; ++ } ++ ++ /* registered */ ++ if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN && ++ priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID && ++ g_timer_elapsed (priv->timer_last_notified, NULL) > 60) { ++ _show_notification (manager, _NOTIFY_REGISTERED); ++ return; ++ } ++ } ++ ++ /* nag again */ ++ if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN && ++ g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { ++ _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); ++ return; ++ } ++ if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID && ++ g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { ++ _show_notification (manager, _NOTIFY_EXPIRED); ++ return; ++ } ++ if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID && ++ g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { ++ _show_notification (manager, _NOTIFY_EXPIRED); ++ return; ++ } ++} ++ ++static gboolean ++_client_register_with_keys (GsdSubscriptionManager *manager, ++ const gchar *hostname, ++ const gchar *organisation, ++ const gchar *activation_key, ++ GError **error) ++{ ++ GsdSubscriptionManagerPrivate *priv = manager->priv; ++ g_autoptr(GSubprocess) subprocess = NULL; ++ ++ /* apparently: "we can't send registration credentials over the regular ++ * system or session bus since those aren't really locked down..." */ ++ if (!_client_register_start (manager, error)) ++ return FALSE; ++ g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); ++ subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error, ++ "pkexec", LIBEXECDIR "/gsd-subman-helper", ++ "--kind", "register-with-key", ++ "--address", priv->address, ++ "--hostname", hostname, ++ "--organisation", organisation, ++ "--activation-key", activation_key, ++ NULL); ++ if (subprocess == NULL) { ++ g_prefix_error (error, "failed to find pkexec: "); ++ return FALSE; ++ } ++ if (!_client_subprocess_wait_check (subprocess, error)) ++ return FALSE; ++ ++ /* FIXME: also do on error? */ ++ if (!_client_register_stop (manager, error)) ++ return FALSE; ++ if (!_client_subscription_status_update (manager, error)) ++ return FALSE; ++ _client_maybe__show_notification (manager); ++ ++ /* success */ ++ return TRUE; ++} ++ ++static gboolean ++_client_register (GsdSubscriptionManager *manager, ++ const gchar *hostname, ++ const gchar *organisation, ++ const gchar *username, ++ const gchar *password, ++ GError **error) ++{ ++ GsdSubscriptionManagerPrivate *priv = manager->priv; ++ g_autoptr(GSubprocess) subprocess = NULL; ++ ++ /* fallback */ ++ if (organisation == NULL) ++ organisation = ""; ++ ++ /* apparently: "we can't send registration credentials over the regular ++ * system or session bus since those aren't really locked down..." */ ++ if (!_client_register_start (manager, error)) ++ return FALSE; ++ g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); ++ subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error, ++ "pkexec", LIBEXECDIR "/gsd-subman-helper", ++ "--kind", "register-with-username", ++ "--address", priv->address, ++ "--hostname", hostname, ++ "--organisation", organisation, ++ "--username", username, ++ "--password", password, ++ NULL); ++ if (subprocess == NULL) { ++ g_prefix_error (error, "failed to find pkexec: "); ++ return FALSE; ++ } ++ if (!_client_subprocess_wait_check (subprocess, error)) ++ return FALSE; ++ ++ /* FIXME: also do on error? */ ++ if (!_client_register_stop (manager, error)) ++ return FALSE; ++ if (!_client_subscription_status_update (manager, error)) ++ return FALSE; ++ _client_maybe__show_notification (manager); ++ return TRUE; ++} ++ ++static gboolean ++_client_unregister (GsdSubscriptionManager *manager, GError **error) ++{ ++ g_autoptr(GSubprocess) subprocess = NULL; ++ ++ /* apparently: "we can't send registration credentials over the regular ++ * system or session bus since those aren't really locked down..." */ ++ if (!_client_register_start (manager, error)) ++ return FALSE; ++ g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); ++ subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error, ++ "pkexec", LIBEXECDIR "/gsd-subman-helper", ++ "--kind", "unregister", ++ NULL); ++ if (subprocess == NULL) { ++ g_prefix_error (error, "failed to find pkexec: "); ++ return FALSE; ++ } ++ if (!_client_subprocess_wait_check (subprocess, error)) ++ return FALSE; ++ if (!_client_subscription_status_update (manager, error)) ++ return FALSE; ++ _client_maybe__show_notification (manager); ++ return TRUE; ++} ++ ++static gboolean ++_client_update_config (GsdSubscriptionManager *manager, GError **error) ++{ ++ GsdSubscriptionManagerPrivate *priv = manager->priv; ++ g_autoptr(GVariant) val = NULL; ++ g_autoptr(GVariant) val_server = NULL; ++ g_autoptr(GVariantDict) dict = NULL; ++ GVariantIter iter; ++ gchar *key; ++ gchar *value; ++ ++ val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_CONFIG], ++ "GetAll", ++ g_variant_new ("(s)", priv->userlang), ++ G_DBUS_CALL_FLAGS_NONE, ++ -1, NULL, error); ++ if (val == NULL) ++ return FALSE; ++ dict = g_variant_dict_new (g_variant_get_child_value (val, 0)); ++ val_server = g_variant_dict_lookup_value (dict, "server", G_VARIANT_TYPE("a{ss}")); ++ if (val_server != NULL) { ++ g_variant_iter_init (&iter, val_server); ++ while (g_variant_iter_next (&iter, "{ss}", &key, &value)) { ++ g_debug ("%s=%s", key, value); ++ g_hash_table_insert (priv->config, ++ g_steal_pointer (&key), ++ g_steal_pointer (&value)); ++ } ++ } ++ return TRUE; ++} ++ ++static void ++_subman_proxy_signal_cb (GDBusProxy *proxy, ++ const gchar *sender_name, ++ const gchar *signal_name, ++ GVariant *parameters, ++ GsdSubscriptionManager *manager) ++{ ++ g_autoptr(GError) error = NULL; ++ if (!_client_syspurpose_update (manager, &error)) { ++ g_warning ("failed to update syspurpose: %s", error->message); ++ g_clear_error (&error); ++ } ++ if (!_client_subscription_status_update (manager, &error)) { ++ g_warning ("failed to update subscription status: %s", error->message); ++ g_clear_error (&error); ++ } ++ _client_maybe__show_notification (manager); ++} ++ ++static void ++_client_unload (GsdSubscriptionManager *manager) ++{ ++ GsdSubscriptionManagerPrivate *priv = manager->priv; ++ for (guint i = 0; i < _RHSM_INTERFACE_LAST; i++) ++ g_clear_object (&priv->proxies[i]); ++ g_hash_table_unref (priv->config); ++} ++ ++static const gchar * ++_rhsm_interface_to_string (_RhsmInterface kind) ++{ ++ if (kind == _RHSM_INTERFACE_CONFIG) ++ return "Config"; ++ if (kind == _RHSM_INTERFACE_REGISTER_SERVER) ++ return "RegisterServer"; ++ if (kind == _RHSM_INTERFACE_ATTACH) ++ return "Attach"; ++ if (kind == _RHSM_INTERFACE_ENTITLEMENT) ++ return "Entitlement"; ++ if (kind == _RHSM_INTERFACE_PRODUCTS) ++ return "Products"; ++ if (kind == _RHSM_INTERFACE_CONSUMER) ++ return "Consumer"; ++ if (kind == _RHSM_INTERFACE_SYSPURPOSE) ++ return "Syspurpose"; ++ return NULL; ++} ++ ++static gboolean ++_client_load (GsdSubscriptionManager *manager, GError **error) ++{ ++ GsdSubscriptionManagerPrivate *priv = manager->priv; ++ ++ priv->config = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); ++ ++ /* connect to all the interfaces on the *different* objects :| */ ++ for (guint i = 0; i < _RHSM_INTERFACE_LAST; i++) { ++ const gchar *kind = _rhsm_interface_to_string (i); ++ g_autofree gchar *opath = g_strdup_printf ("/com/redhat/RHSM1/%s", kind); ++ g_autofree gchar *iface = g_strdup_printf ("com.redhat.RHSM1.%s", kind); ++ priv->proxies[i] = ++ g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, ++ G_DBUS_PROXY_FLAGS_NONE, ++ NULL, ++ "com.redhat.RHSM1", ++ opath, iface, ++ NULL, ++ error); ++ if (priv->proxies[i] == NULL) ++ return FALSE; ++ /* we want to get notified if the status of the system changes */ ++ g_signal_connect (priv->proxies[i], "g-signal", ++ G_CALLBACK (_subman_proxy_signal_cb), manager); ++ } ++ ++ /* get initial status */ ++ priv->userlang = ""; ++ if (!_client_update_config (manager, error)) ++ return FALSE; ++ if (!_client_subscription_status_update (manager, error)) ++ return FALSE; ++ if (!_client_syspurpose_update (manager, error)) ++ return FALSE; ++ ++ /* success */ ++ return TRUE; ++} ++ ++gboolean ++gsd_subscription_manager_start (GsdSubscriptionManager *manager, GError **error) ++{ ++ gboolean ret; ++ g_debug ("Starting subscription manager"); ++ gnome_settings_profile_start (NULL); ++ ret = _client_load (manager, error); ++ _client_maybe__show_notification (manager); ++ gnome_settings_profile_end (NULL); ++ return ret; ++} ++ ++void ++gsd_subscription_manager_stop (GsdSubscriptionManager *manager) ++{ ++ g_debug ("Stopping subscription manager"); ++ _client_unload (manager); ++} ++ ++static void ++gsd_subscription_manager_class_init (GsdSubscriptionManagerClass *klass) ++{ ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ object_class->finalize = gsd_subscription_manager_finalize; ++ notify_init ("gnome-settings-daemon"); ++ g_type_class_add_private (klass, sizeof (GsdSubscriptionManagerPrivate)); ++} ++ ++static void ++_launch_info_overview (void) ++{ ++ const gchar *argv[] = { "gnome-control-center", "info-overview", NULL }; ++ g_debug ("Running gnome-control-center info-overview"); ++ g_spawn_async (NULL, (gchar **) argv, NULL, G_SPAWN_SEARCH_PATH, ++ NULL, NULL, NULL, NULL); ++} ++ ++static void ++_notify_closed_cb (NotifyNotification *notification, gpointer user_data) ++{ ++ /* FIXME: only launch when clicking on the main body, not the window close */ ++ if (notify_notification_get_closed_reason (notification) == 0x400) ++ _launch_info_overview (); ++} ++ ++static void ++_notify_clicked_cb (NotifyNotification *notification, char *action, gpointer user_data) ++{ ++ _launch_info_overview (); ++} ++ ++static void ++gsd_subscription_manager_init (GsdSubscriptionManager *manager) ++{ ++ GsdSubscriptionManagerPrivate *priv = manager->priv = GSD_SUBSCRIPTION_MANAGER_GET_PRIVATE (manager); ++ ++ priv->timer_last_notified = g_timer_new (); ++ ++ /* expired */ ++ priv->notification_expired = ++ notify_notification_new (_("Subscription Has Expired"), ++ _("Add or renew a subscription to continue receiving software updates."), ++ NULL); ++ notify_notification_set_app_name (priv->notification_expired, _("Subscription")); ++ notify_notification_set_hint_string (priv->notification_expired, "desktop-entry", "subman-panel"); ++ notify_notification_set_hint_string (priv->notification_expired, "x-gnome-privacy-scope", "system"); ++ notify_notification_set_urgency (priv->notification_expired, NOTIFY_URGENCY_CRITICAL); ++ notify_notification_add_action (priv->notification_expired, ++ "info-overview", _("Subscribe System…"), ++ _notify_clicked_cb, ++ manager, NULL); ++ g_signal_connect (priv->notification_expired, "closed", ++ G_CALLBACK (_notify_closed_cb), manager); ++ ++ /* registered */ ++ priv->notification_registered = ++ notify_notification_new (_("Registration Successful"), ++ _("The system has been registered and software updates have been enabled."), ++ NULL); ++ notify_notification_set_app_name (priv->notification_registered, _("Subscription")); ++ notify_notification_set_hint_string (priv->notification_registered, "desktop-entry", "subman-panel"); ++ notify_notification_set_hint_string (priv->notification_registered, "x-gnome-privacy-scope", "system"); ++ notify_notification_set_urgency (priv->notification_registered, NOTIFY_URGENCY_CRITICAL); ++ g_signal_connect (priv->notification_registered, "closed", ++ G_CALLBACK (_notify_closed_cb), manager); ++ ++ /* registration required */ ++ priv->notification_registration_required = ++ notify_notification_new (_("System Not Registered"), ++ _("Please register your system to receive software updates."), ++ NULL); ++ notify_notification_set_app_name (priv->notification_registration_required, _("Subscription")); ++ notify_notification_set_hint_string (priv->notification_registration_required, "desktop-entry", "subman-panel"); ++ notify_notification_set_hint_string (priv->notification_registration_required, "x-gnome-privacy-scope", "system"); ++ notify_notification_set_urgency (priv->notification_registration_required, NOTIFY_URGENCY_CRITICAL); ++ notify_notification_add_action (priv->notification_registration_required, ++ "info-overview", _("Register System…"), ++ _notify_clicked_cb, ++ manager, NULL); ++ g_signal_connect (priv->notification_registration_required, "closed", ++ G_CALLBACK (_notify_closed_cb), manager); ++} ++ ++static void ++gsd_subscription_manager_finalize (GObject *object) ++{ ++ GsdSubscriptionManager *manager; ++ ++ g_return_if_fail (object != NULL); ++ g_return_if_fail (GSD_IS_SUBSCRIPTION_MANAGER (object)); ++ ++ manager = GSD_SUBSCRIPTION_MANAGER (object); ++ ++ gsd_subscription_manager_stop (manager); ++ ++ if (manager->priv->bus_cancellable != NULL) { ++ g_cancellable_cancel (manager->priv->bus_cancellable); ++ g_clear_object (&manager->priv->bus_cancellable); ++ } ++ ++ g_clear_pointer (&manager->priv->introspection_data, g_dbus_node_info_unref); ++ g_clear_object (&manager->priv->connection); ++ g_clear_object (&manager->priv->notification_expired); ++ g_clear_object (&manager->priv->notification_registered); ++ g_timer_destroy (manager->priv->timer_last_notified); ++ ++ if (manager->priv->name_id != 0) { ++ g_bus_unown_name (manager->priv->name_id); ++ manager->priv->name_id = 0; ++ } ++ ++ G_OBJECT_CLASS (gsd_subscription_manager_parent_class)->finalize (object); ++} ++ ++static void ++handle_method_call (GDBusConnection *connection, ++ const gchar *sender, ++ const gchar *object_path, ++ const gchar *interface_name, ++ const gchar *method_name, ++ GVariant *parameters, ++ GDBusMethodInvocation *invocation, ++ gpointer user_data) ++{ ++ GsdSubscriptionManager *manager = GSD_SUBSCRIPTION_MANAGER (user_data); ++ g_autoptr(GError) error = NULL; ++ ++ if (g_strcmp0 (method_name, "Register") == 0) { ++ const gchar *organisation = NULL; ++ const gchar *hostname = NULL; ++ ++ if (FALSE) { ++ g_dbus_method_invocation_return_error_literal (invocation, ++ G_IO_ERROR, G_IO_ERROR_NOT_INITIALIZED, ++ "Cannot register at this time"); ++ ++ return; ++ } ++ ++ g_autoptr(GVariantDict) dict = g_variant_dict_new (g_variant_get_child_value (parameters, 0)); ++ ++ const gchar *kind = NULL; ++ if (!g_variant_dict_lookup (dict, "kind", "&s", &kind)) { ++ g_dbus_method_invocation_return_error_literal (invocation, ++ G_IO_ERROR, G_IO_ERROR_FAILED, ++ "No kind specified"); ++ ++ return; ++ } ++ if (g_strcmp0 (kind, "username") == 0) { ++ const gchar *username = NULL; ++ const gchar *password = NULL; ++ g_variant_dict_lookup (dict, "hostname", "&s", &hostname); ++ g_variant_dict_lookup (dict, "organisation", "&s", &organisation); ++ g_variant_dict_lookup (dict, "username", "&s", &username); ++ g_variant_dict_lookup (dict, "password", "&s", &password); ++ if (!_client_register (manager, ++ hostname, ++ organisation, ++ username, ++ password, ++ &error)) { ++ g_dbus_method_invocation_return_gerror (invocation, error); ++ return; ++ } ++ } else if (g_strcmp0 (kind, "key") == 0) { ++ const gchar *activation_key = NULL; ++ g_variant_dict_lookup (dict, "hostname", "&s", &hostname); ++ g_variant_dict_lookup (dict, "organisation", "&s", &organisation); ++ g_variant_dict_lookup (dict, "activation-key", "&s", &activation_key); ++ if (!_client_register_with_keys (manager, ++ hostname, ++ organisation, ++ activation_key, ++ &error)) { ++ g_dbus_method_invocation_return_gerror (invocation, error); ++ return; ++ } ++ } else { ++ g_dbus_method_invocation_return_error_literal (invocation, ++ G_IO_ERROR, G_IO_ERROR_FAILED, ++ "Invalid kind specified"); ++ ++ return; ++ } ++ g_dbus_method_invocation_return_value (invocation, NULL); ++ } else if (g_strcmp0 (method_name, "Unregister") == 0) { ++ if (!_client_unregister (manager, &error)) { ++ g_dbus_method_invocation_return_gerror (invocation, error); ++ return; ++ } ++ g_dbus_method_invocation_return_value (invocation, NULL); ++ } else { ++ g_assert_not_reached (); ++ } ++} ++ ++static GVariant * ++handle_get_property (GDBusConnection *connection, ++ const gchar *sender, ++ const gchar *object_path, ++ const gchar *interface_name, ++ const gchar *property_name, ++ GError **error, gpointer user_data) ++{ ++ GsdSubscriptionManager *manager = GSD_SUBSCRIPTION_MANAGER (user_data); ++ GsdSubscriptionManagerPrivate *priv = manager->priv; ++ ++ if (g_strcmp0 (interface_name, GSD_SUBSCRIPTION_DBUS_INTERFACE) != 0) { ++ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, ++ "No such interface: %s", interface_name); ++ return NULL; ++ } ++ ++ if (g_strcmp0 (property_name, "SubscriptionStatus") == 0) ++ return g_variant_new_uint32 (priv->subscription_status); ++ ++ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, ++ "Failed to get property: %s", property_name); ++ return NULL; ++} ++ ++static gboolean ++handle_set_property (GDBusConnection *connection, ++ const gchar *sender, ++ const gchar *object_path, ++ const gchar *interface_name, ++ const gchar *property_name, ++ GVariant *value, ++ GError **error, gpointer user_data) ++{ ++ if (g_strcmp0 (interface_name, GSD_SUBSCRIPTION_DBUS_INTERFACE) != 0) { ++ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, ++ "No such interface: %s", interface_name); ++ return FALSE; ++ } ++ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, ++ "No such property: %s", property_name); ++ return FALSE; ++} ++ ++static const GDBusInterfaceVTable interface_vtable = ++{ ++ handle_method_call, ++ handle_get_property, ++ handle_set_property ++}; ++ ++static void ++name_lost_handler_cb (GDBusConnection *connection, const gchar *name, gpointer user_data) ++{ ++ g_debug ("lost name, so exiting"); ++ gtk_main_quit (); ++} ++ ++static void ++on_bus_gotten (GObject *source_object, GAsyncResult *res, GsdSubscriptionManager *manager) ++{ ++ GsdSubscriptionManagerPrivate *priv = manager->priv; ++ GDBusConnection *connection; ++ g_autoptr(GError) error = NULL; ++ ++ connection = g_bus_get_finish (res, &error); ++ if (connection == NULL) { ++ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) ++ g_warning ("Could not get session bus: %s", error->message); ++ return; ++ } ++ ++ priv->connection = connection; ++ g_dbus_connection_register_object (connection, ++ GSD_SUBSCRIPTION_DBUS_PATH, ++ priv->introspection_data->interfaces[0], ++ &interface_vtable, ++ manager, ++ NULL, ++ NULL); ++ priv->name_id = g_bus_own_name_on_connection (connection, ++ GSD_SUBSCRIPTION_DBUS_NAME, ++ G_BUS_NAME_OWNER_FLAGS_NONE, ++ NULL, ++ name_lost_handler_cb, ++ manager, ++ NULL); ++} ++ ++static void ++register_manager_dbus (GsdSubscriptionManager *manager) ++{ ++ GsdSubscriptionManagerPrivate *priv = manager->priv; ++ ++ priv->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL); ++ g_assert (priv->introspection_data != NULL); ++ priv->bus_cancellable = g_cancellable_new (); ++ ++ g_bus_get (G_BUS_TYPE_SESSION, priv->bus_cancellable, ++ (GAsyncReadyCallback) on_bus_gotten, manager); ++} ++ ++GsdSubscriptionManager * ++gsd_subscription_manager_new (void) ++{ ++ if (manager_object != NULL) { ++ g_object_ref (manager_object); ++ } else { ++ manager_object = g_object_new (GSD_TYPE_SUBSCRIPTION_MANAGER, NULL); ++ g_object_add_weak_pointer (manager_object, ++ (gpointer *) &manager_object); ++ register_manager_dbus (manager_object); ++ } ++ ++ return GSD_SUBSCRIPTION_MANAGER (manager_object); ++} +diff --git a/plugins/subman/gsd-subscription-manager.h b/plugins/subman/gsd-subscription-manager.h +new file mode 100644 +index 00000000..6a524b1b +--- /dev/null ++++ b/plugins/subman/gsd-subscription-manager.h +@@ -0,0 +1,63 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2019 Richard Hughes ++ * ++ * 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 . ++ * ++ */ ++ ++#ifndef __GSD_SUBSCRIPTION_MANAGER_H ++#define __GSD_SUBSCRIPTION_MANAGER_H ++ ++#include ++ ++G_BEGIN_DECLS ++ ++#define GSD_TYPE_SUBSCRIPTION_MANAGER (gsd_subscription_manager_get_type ()) ++#define GSD_SUBSCRIPTION_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSD_TYPE_SUBSCRIPTION_MANAGER, GsdSubscriptionManager)) ++#define GSD_SUBSCRIPTION_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSD_TYPE_SUBSCRIPTION_MANAGER, GsdSubscriptionManagerClass)) ++#define GSD_IS_SUBSCRIPTION_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSD_TYPE_SUBSCRIPTION_MANAGER)) ++#define GSD_IS_SUBSCRIPTION_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSD_TYPE_SUBSCRIPTION_MANAGER)) ++#define GSD_SUBSCRIPTION_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSD_TYPE_SUBSCRIPTION_MANAGER, GsdSubscriptionManagerClass)) ++#define GSD_SUBSCRIPTION_MANAGER_ERROR (gsd_subscription_manager_error_quark ()) ++ ++typedef struct GsdSubscriptionManagerPrivate GsdSubscriptionManagerPrivate; ++ ++typedef struct ++{ ++ GObject parent; ++ GsdSubscriptionManagerPrivate *priv; ++} GsdSubscriptionManager; ++ ++typedef struct ++{ ++ GObjectClass parent_class; ++} GsdSubscriptionManagerClass; ++ ++enum ++{ ++ GSD_SUBSCRIPTION_MANAGER_ERROR_FAILED ++}; ++ ++GType gsd_subscription_manager_get_type (void); ++GQuark gsd_subscription_manager_error_quark (void); ++ ++GsdSubscriptionManager *gsd_subscription_manager_new (void); ++gboolean gsd_subscription_manager_start (GsdSubscriptionManager *manager, ++ GError **error); ++void gsd_subscription_manager_stop (GsdSubscriptionManager *manager); ++ ++G_END_DECLS ++ ++#endif /* __GSD_SUBSCRIPTION_MANAGER_H */ +diff --git a/plugins/subman/main.c b/plugins/subman/main.c +new file mode 100644 +index 00000000..28ac995b +--- /dev/null ++++ b/plugins/subman/main.c +@@ -0,0 +1,8 @@ ++#define NEW gsd_subscription_manager_new ++#define START gsd_subscription_manager_start ++#define STOP gsd_subscription_manager_stop ++#define MANAGER GsdSubscriptionManager ++#define GDK_BACKEND "x11" ++#include "gsd-subscription-manager.h" ++ ++#include "daemon-skeleton-gtk.h" +diff --git a/plugins/subman/meson.build b/plugins/subman/meson.build +new file mode 100644 +index 00000000..bfd073b6 +--- /dev/null ++++ b/plugins/subman/meson.build +@@ -0,0 +1,56 @@ ++sources = files( ++ 'gsd-subscription-manager.c', ++ 'gsd-subman-common.c', ++ 'main.c' ++) ++ ++deps = plugins_deps + [ ++ libnotify_dep, ++ gtk_dep, ++ jsonglib_dep, ++ m_dep, ++] ++ ++cflags += ['-DBINDIR="@0@"'.format(gsd_bindir)] ++cflags += ['-DLIBEXECDIR="@0@"'.format(gsd_libexecdir)] ++ ++executable( ++ 'gsd-' + plugin_name, ++ sources, ++ include_directories: [top_inc, common_inc], ++ dependencies: deps, ++ c_args: cflags, ++ install: true, ++ install_rpath: gsd_pkglibdir, ++ install_dir: gsd_libexecdir ++) ++ ++# .Register needs to be called from root as subman can't do PolicyKit... ++policy = 'org.gnome.settings-daemon.plugins.subman.policy' ++policy_in = configure_file( ++ input: policy + '.in.in', ++ output: policy + '.in', ++ configuration: plugins_conf ++) ++ ++i18n.merge_file( ++ policy, ++ input: policy_in, ++ output: policy, ++ po_dir: po_dir, ++ install: true, ++ install_dir: join_paths(gsd_datadir, 'polkit-1', 'actions') ++) ++ ++install_data('org.gnome.settings-daemon.plugins.subman.rules', ++ install_dir : join_paths(gsd_datadir, 'polkit-1', 'rules.d')) ++ ++executable( ++ 'gsd-subman-helper', ++ 'gsd-subman-helper.c', ++ include_directories: top_inc, ++ dependencies: [gio_dep, jsonglib_dep], ++ install: true, ++ install_rpath: gsd_pkglibdir, ++ install_dir: gsd_libexecdir ++) +diff --git a/plugins/subman/org.gnome.SettingsDaemon.Subscription.desktop.in b/plugins/subman/org.gnome.SettingsDaemon.Subscription.desktop.in +new file mode 100644 +index 00000000..14fe5915 +--- /dev/null ++++ b/plugins/subman/org.gnome.SettingsDaemon.Subscription.desktop.in +@@ -0,0 +1,9 @@ ++[Desktop Entry] ++Type=Application ++Name=GNOME Settings Daemon's subscription manager plugin ++Exec=@libexecdir@/gsd-subman ++OnlyShowIn=GNOME; ++NoDisplay=true ++X-GNOME-Autostart-Phase=Initialization ++X-GNOME-Autostart-Notify=true ++X-GNOME-AutoRestart=true +diff --git a/plugins/subman/org.gnome.settings-daemon.plugins.subman.policy.in.in b/plugins/subman/org.gnome.settings-daemon.plugins.subman.policy.in.in +new file mode 100644 +index 00000000..59e9fdd4 +--- /dev/null ++++ b/plugins/subman/org.gnome.settings-daemon.plugins.subman.policy.in.in +@@ -0,0 +1,27 @@ ++ ++ ++ ++ ++ ++ ++ GNOME Settings Daemon ++ http://git.gnome.org/browse/gnome-settings-daemon ++ emblem-synchronizing ++ ++ ++ Register the system ++ Authentication is required to register the system ++ ++ no ++ no ++ auth_admin_keep ++ ++ @libexecdir@/gsd-subman-helper ++ ++ ++ +diff --git a/plugins/subman/org.gnome.settings-daemon.plugins.subman.rules b/plugins/subman/org.gnome.settings-daemon.plugins.subman.rules +new file mode 100644 +index 00000000..1ed3a0ea +--- /dev/null ++++ b/plugins/subman/org.gnome.settings-daemon.plugins.subman.rules +@@ -0,0 +1,7 @@ ++polkit.addRule(function(action, subject) { ++ if (action.id == "org.gnome.settings-daemon.plugins.subman.register" && ++ subject.active == true && subject.local == true && ++ subject.isInGroup("wheel")) { ++ return polkit.Result.YES; ++ } ++}); +-- +2.37.0 + + +From d85f9992ac4b413d07092363568213991f38d898 Mon Sep 17 00:00:00 2001 +From: Kalev Lember +Date: Thu, 27 Jun 2019 16:12:00 +0200 +Subject: [PATCH 02/20] subman: Add InstalledProducts dbus property for g-c-c + +--- + plugins/subman/gsd-subscription-manager.c | 135 ++++++++++++++++++++++ + 1 file changed, 135 insertions(+) + +diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c +index 08b13fa6..a8c18a26 100644 +--- a/plugins/subman/gsd-subscription-manager.c ++++ b/plugins/subman/gsd-subscription-manager.c +@@ -1,6 +1,7 @@ + /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2019 Richard Hughes ++ * Copyright (C) 2019 Kalev Lember + * + * 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 +@@ -44,6 +45,7 @@ static const gchar introspection_xml[] = + " " + " " + " " ++" " + " " + " " + ""; +@@ -72,6 +74,7 @@ struct GsdSubscriptionManagerPrivate + GDBusProxy *proxies[_RHSM_INTERFACE_LAST]; + const gchar *userlang; /* owned by GLib internally */ + GHashTable *config; /* str:str */ ++ GPtrArray *installed_products; + gchar *address; + + GTimer *timer_last_notified; +@@ -92,6 +95,32 @@ static void gsd_subscription_manager_finalize (GObject *objec + + G_DEFINE_TYPE (GsdSubscriptionManager, gsd_subscription_manager, G_TYPE_OBJECT) + ++typedef struct ++{ ++ gchar *product_name; ++ gchar *product_id; ++ gchar *version; ++ gchar *arch; ++ gchar *status; ++ gchar *starts; ++ gchar *ends; ++} ProductData; ++ ++static void ++product_data_free (ProductData *product) ++{ ++ g_free (product->product_name); ++ g_free (product->product_id); ++ g_free (product->version); ++ g_free (product->arch); ++ g_free (product->status); ++ g_free (product->starts); ++ g_free (product->ends); ++ g_free (product); ++} ++ ++G_DEFINE_AUTOPTR_CLEANUP_FUNC (ProductData, product_data_free); ++ + static gpointer manager_object = NULL; + + GQuark +@@ -120,6 +149,32 @@ _client_subscription_status_from_text (const gchar *status_txt) + return GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; + } + ++static GVariant * ++_make_installed_products_variant (GPtrArray *installed_products) ++{ ++ GVariantBuilder builder; ++ g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}")); ++ ++ for (guint i = 0; i < installed_products->len; i++) { ++ ProductData *product = g_ptr_array_index (installed_products, i); ++ g_auto(GVariantDict) dict; ++ ++ g_variant_dict_init (&dict, NULL); ++ ++ g_variant_dict_insert (&dict, "product-name", "s", product->product_name); ++ g_variant_dict_insert (&dict, "product-id", "s", product->product_id); ++ g_variant_dict_insert (&dict, "version", "s", product->version); ++ g_variant_dict_insert (&dict, "arch", "s", product->arch); ++ g_variant_dict_insert (&dict, "status", "s", product->status); ++ g_variant_dict_insert (&dict, "starts", "s", product->starts); ++ g_variant_dict_insert (&dict, "ends", "s", product->ends); ++ ++ g_variant_builder_add_value (&builder, g_variant_dict_end (&dict)); ++ } ++ ++ return g_variant_builder_end (&builder); ++} ++ + static void + _emit_property_changed (GsdSubscriptionManager *manager, + const gchar *property_name, +@@ -154,6 +209,69 @@ _emit_property_changed (GsdSubscriptionManager *manager, + g_variant_builder_clear (&invalidated_builder); + } + ++static gboolean ++_client_installed_products_update (GsdSubscriptionManager *manager, GError **error) ++{ ++ GsdSubscriptionManagerPrivate *priv = manager->priv; ++ JsonNode *json_root; ++ JsonArray *json_products_array; ++ const gchar *json_txt = NULL; ++ g_autoptr(GVariant) val = NULL; ++ g_autoptr(JsonParser) json_parser = json_parser_new (); ++ ++ val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_PRODUCTS], ++ "ListInstalledProducts", ++ g_variant_new ("(sa{sv}s)", ++ "" /* filter_string */, ++ NULL /* proxy_options */, ++ priv->userlang), ++ G_DBUS_CALL_FLAGS_NONE, ++ -1, NULL, error); ++ if (val == NULL) ++ return FALSE; ++ g_variant_get (val, "(&s)", &json_txt); ++ g_debug ("Products.ListInstalledProducts JSON: %s", json_txt); ++ if (!json_parser_load_from_data (json_parser, json_txt, -1, error)) ++ return FALSE; ++ json_root = json_parser_get_root (json_parser); ++ json_products_array = json_node_get_array (json_root); ++ if (json_products_array == NULL) { ++ g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, ++ "no InstalledProducts array in %s", json_txt); ++ return FALSE; ++ } ++ ++ g_ptr_array_set_size (priv->installed_products, 0); ++ ++ for (guint i = 0; i < json_array_get_length (json_products_array); i++) { ++ JsonArray *json_product = json_array_get_array_element (json_products_array, i); ++ g_autoptr(ProductData) product = g_new0 (ProductData, 1); ++ ++ if (json_product == NULL) ++ continue; ++ if (json_array_get_length (json_product) < 8) { ++ g_debug ("Unexpected number of array elements in InstalledProducts JSON"); ++ continue; ++ } ++ ++ product->product_name = g_strdup (json_array_get_string_element (json_product, 0)); ++ product->product_id = g_strdup (json_array_get_string_element (json_product, 1)); ++ product->version = g_strdup (json_array_get_string_element (json_product, 2)); ++ product->arch = g_strdup (json_array_get_string_element (json_product, 3)); ++ product->status = g_strdup (json_array_get_string_element (json_product, 4)); ++ product->starts = g_strdup (json_array_get_string_element (json_product, 6)); ++ product->ends = g_strdup (json_array_get_string_element (json_product, 7)); ++ ++ g_ptr_array_add (priv->installed_products, g_steal_pointer (&product)); ++ } ++ ++ /* emit notification for g-c-c */ ++ _emit_property_changed (manager, "InstalledProducts", ++ _make_installed_products_variant (priv->installed_products)); ++ ++ return TRUE; ++} ++ + static gboolean + _client_subscription_status_update (GsdSubscriptionManager *manager, GError **error) + { +@@ -450,6 +568,8 @@ _client_register_with_keys (GsdSubscriptionManager *manager, + return FALSE; + if (!_client_subscription_status_update (manager, error)) + return FALSE; ++ if (!_client_installed_products_update (manager, error)) ++ return FALSE; + _client_maybe__show_notification (manager); + + /* success */ +@@ -497,6 +617,8 @@ _client_register (GsdSubscriptionManager *manager, + return FALSE; + if (!_client_subscription_status_update (manager, error)) + return FALSE; ++ if (!_client_installed_products_update (manager, error)) ++ return FALSE; + _client_maybe__show_notification (manager); + return TRUE; + } +@@ -523,6 +645,8 @@ _client_unregister (GsdSubscriptionManager *manager, GError **error) + return FALSE; + if (!_client_subscription_status_update (manager, error)) + return FALSE; ++ if (!_client_installed_products_update (manager, error)) ++ return FALSE; + _client_maybe__show_notification (manager); + return TRUE; + } +@@ -575,6 +699,10 @@ _subman_proxy_signal_cb (GDBusProxy *proxy, + g_warning ("failed to update subscription status: %s", error->message); + g_clear_error (&error); + } ++ if (!_client_installed_products_update (manager, &error)) { ++ g_warning ("failed to update installed products: %s", error->message); ++ g_clear_error (&error); ++ } + _client_maybe__show_notification (manager); + } + +@@ -640,6 +768,8 @@ _client_load (GsdSubscriptionManager *manager, GError **error) + return FALSE; + if (!_client_subscription_status_update (manager, error)) + return FALSE; ++ if (!_client_installed_products_update (manager, error)) ++ return FALSE; + if (!_client_syspurpose_update (manager, error)) + return FALSE; + +@@ -703,6 +833,7 @@ gsd_subscription_manager_init (GsdSubscriptionManager *manager) + { + GsdSubscriptionManagerPrivate *priv = manager->priv = GSD_SUBSCRIPTION_MANAGER_GET_PRIVATE (manager); + ++ priv->installed_products = g_ptr_array_new_with_free_func ((GDestroyNotify) product_data_free); + priv->timer_last_notified = g_timer_new (); + + /* expired */ +@@ -767,6 +898,7 @@ gsd_subscription_manager_finalize (GObject *object) + g_clear_object (&manager->priv->bus_cancellable); + } + ++ g_clear_pointer (&manager->priv->installed_products, g_ptr_array_unref); + g_clear_pointer (&manager->priv->introspection_data, g_dbus_node_info_unref); + g_clear_object (&manager->priv->connection); + g_clear_object (&manager->priv->notification_expired); +@@ -884,6 +1016,9 @@ handle_get_property (GDBusConnection *connection, + if (g_strcmp0 (property_name, "SubscriptionStatus") == 0) + return g_variant_new_uint32 (priv->subscription_status); + ++ if (g_strcmp0 (property_name, "InstalledProducts") == 0) ++ return _make_installed_products_variant (priv->installed_products); ++ + g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, + "Failed to get property: %s", property_name); + return NULL; +-- +2.37.0 + + +From 65750e137dc591d34c1166de28ce2f73eb17d51e Mon Sep 17 00:00:00 2001 +From: Kalev Lember +Date: Fri, 28 Jun 2019 18:10:36 +0200 +Subject: [PATCH 03/20] subman: Increase RHSM dbus call timeouts + +Increase the dbus timeouts to 5 minutes as the register/unregister calls +seem to routinely take more than a minute. +--- + plugins/subman/gsd-subman-helper.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/plugins/subman/gsd-subman-helper.c b/plugins/subman/gsd-subman-helper.c +index 69ebec7e..a649ae03 100644 +--- a/plugins/subman/gsd-subman-helper.c ++++ b/plugins/subman/gsd-subman-helper.c +@@ -28,6 +28,8 @@ + #include + #include + ++#define DBUS_TIMEOUT 300000 /* 5 minutes */ ++ + static void + _helper_convert_error (const gchar *json_txt, GError **error) + { +@@ -94,7 +96,8 @@ _helper_unregister (GError **error) + proxy_options, + ""), /* lang */ + G_DBUS_CALL_FLAGS_NONE, +- -1, NULL, error); ++ DBUS_TIMEOUT, ++ NULL, error); + return res != NULL; + } + +@@ -127,7 +130,8 @@ _helper_auto_attach (GError **error) + proxy_options, + ""), /* lang */ + G_DBUS_CALL_FLAGS_NONE, +- -1, NULL, error); ++ DBUS_TIMEOUT, ++ NULL, error); + if (res == NULL) + return FALSE; + g_variant_get (res, "(&s)", &str); +@@ -158,7 +162,8 @@ _helper_save_config (const gchar *key, const gchar *value, GError **error) + g_variant_new_string (value), + ""), /* lang */ + G_DBUS_CALL_FLAGS_NONE, +- -1, NULL, error); ++ DBUS_TIMEOUT, ++ NULL, error); + return res != NULL; + } + +@@ -307,7 +312,8 @@ main (int argc, char *argv[]) + subman_conopts, + userlang), + G_DBUS_CALL_FLAGS_NO_AUTO_START, +- -1, NULL, &error_local); ++ DBUS_TIMEOUT, ++ NULL, &error_local); + if (res == NULL) { + g_dbus_error_strip_remote_error (error_local); + _helper_convert_error (error_local->message, &error); +@@ -341,7 +347,8 @@ main (int argc, char *argv[]) + subman_conopts, + userlang), + G_DBUS_CALL_FLAGS_NO_AUTO_START, +- -1, NULL, &error_local); ++ DBUS_TIMEOUT, ++ NULL, &error_local); + if (res == NULL) { + g_dbus_error_strip_remote_error (error_local); + _helper_convert_error (error_local->message, &error); +-- +2.37.0 + + +From cbbaf0ac6b826e38c38eba401e4afc5f71708389 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 20 Aug 2020 11:20:47 -0400 +Subject: [PATCH 04/20] subman: Drop userlang field + +It's currently always erroneously set to empty string. + +This commit drops it, and just uses "C.UTF-8" everywhere, +which is what we actually want. +--- + plugins/subman/gsd-subscription-manager.c | 14 ++++++-------- + 1 file changed, 6 insertions(+), 8 deletions(-) + +diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c +index a8c18a26..46f051a5 100644 +--- a/plugins/subman/gsd-subscription-manager.c ++++ b/plugins/subman/gsd-subscription-manager.c +@@ -72,7 +72,6 @@ struct GsdSubscriptionManagerPrivate + GCancellable *bus_cancellable; + + GDBusProxy *proxies[_RHSM_INTERFACE_LAST]; +- const gchar *userlang; /* owned by GLib internally */ + GHashTable *config; /* str:str */ + GPtrArray *installed_products; + gchar *address; +@@ -224,7 +223,7 @@ _client_installed_products_update (GsdSubscriptionManager *manager, GError **err + g_variant_new ("(sa{sv}s)", + "" /* filter_string */, + NULL /* proxy_options */, +- priv->userlang), ++ "C.UTF-8"), + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, error); + if (val == NULL) +@@ -290,7 +289,7 @@ _client_subscription_status_update (GsdSubscriptionManager *manager, GError **er + "GetStatus", + g_variant_new ("(ss)", + "", /* assumed as 'now' */ +- priv->userlang), ++ "C.UTF-8"), + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, error); + if (val == NULL) +@@ -332,7 +331,7 @@ _client_syspurpose_update (GsdSubscriptionManager *manager, GError **error) + + val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_SYSPURPOSE], + "GetSyspurpose", +- g_variant_new ("(s)", priv->userlang), ++ g_variant_new ("(s)", "C.UTF-8"), + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, error); + if (val == NULL) +@@ -375,7 +374,7 @@ _client_register_start (GsdSubscriptionManager *manager, GError **error) + if (proxy == NULL) + return FALSE; + val = g_dbus_proxy_call_sync (proxy, "Start", +- g_variant_new ("(s)", priv->userlang), ++ g_variant_new ("(s)", "C.UTF-8"), + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, error); + if (val == NULL) +@@ -408,7 +407,7 @@ _client_register_stop (GsdSubscriptionManager *manager, GError **error) + if (proxy == NULL) + return FALSE; + val = g_dbus_proxy_call_sync (proxy, "Stop", +- g_variant_new ("(s)", priv->userlang), ++ g_variant_new ("(s)", "C.UTF-8"), + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, error); + if (val == NULL) +@@ -664,7 +663,7 @@ _client_update_config (GsdSubscriptionManager *manager, GError **error) + + val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_CONFIG], + "GetAll", +- g_variant_new ("(s)", priv->userlang), ++ g_variant_new ("(s)", "C.UTF-8"), + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, error); + if (val == NULL) +@@ -763,7 +762,6 @@ _client_load (GsdSubscriptionManager *manager, GError **error) + } + + /* get initial status */ +- priv->userlang = ""; + if (!_client_update_config (manager, error)) + return FALSE; + if (!_client_subscription_status_update (manager, error)) +-- +2.37.0 + + +From be0e7fdd2e19a1322e0c69081b8a2bf8d62d743a Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Sun, 24 Jan 2021 15:04:17 -0500 +Subject: [PATCH 05/20] subman: Use user locale for registration/subscription + operations + +This makes sure that error messages are in the correct locale. +--- + plugins/subman/gsd-subman-helper.c | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +diff --git a/plugins/subman/gsd-subman-helper.c b/plugins/subman/gsd-subman-helper.c +index a649ae03..3c892c33 100644 +--- a/plugins/subman/gsd-subman-helper.c ++++ b/plugins/subman/gsd-subman-helper.c +@@ -24,11 +24,13 @@ + #include + #include + #include ++#include + + #include + #include + + #define DBUS_TIMEOUT 300000 /* 5 minutes */ ++static const char *locale; + + static void + _helper_convert_error (const gchar *json_txt, GError **error) +@@ -94,7 +96,7 @@ _helper_unregister (GError **error) + "Unregister", + g_variant_new ("(a{sv}s)", + proxy_options, +- ""), /* lang */ ++ locale), + G_DBUS_CALL_FLAGS_NONE, + DBUS_TIMEOUT, + NULL, error); +@@ -128,7 +130,7 @@ _helper_auto_attach (GError **error) + g_variant_new ("(sa{sv}s)", + "", /* now? */ + proxy_options, +- ""), /* lang */ ++ locale), + G_DBUS_CALL_FLAGS_NONE, + DBUS_TIMEOUT, + NULL, error); +@@ -160,7 +162,7 @@ _helper_save_config (const gchar *key, const gchar *value, GError **error) + g_variant_new ("(svs)", + key, + g_variant_new_string (value), +- ""), /* lang */ ++ locale), + G_DBUS_CALL_FLAGS_NONE, + DBUS_TIMEOUT, + NULL, error); +@@ -170,7 +172,6 @@ _helper_save_config (const gchar *key, const gchar *value, GError **error) + int + main (int argc, char *argv[]) + { +- const gchar *userlang = ""; /* as root, so no translations */ + g_autofree gchar *activation_key = NULL; + g_autofree gchar *address = NULL; + g_autofree gchar *hostname = NULL; +@@ -218,6 +219,10 @@ main (int argc, char *argv[]) + g_printerr ("This program can only be used by the root user\n"); + return G_IO_ERROR_NOT_SUPPORTED; + } ++ ++ setlocale (LC_ALL, ""); ++ locale = setlocale (LC_MESSAGES, NULL); ++ + g_option_context_add_main_entries (context, options, NULL); + if (!g_option_context_parse (context, &argc, &argv, &error)) { + g_printerr ("Failed to parse arguments: %s\n", error->message); +@@ -310,7 +315,7 @@ main (int argc, char *argv[]) + activation_keys, + subman_options, + subman_conopts, +- userlang), ++ locale), + G_DBUS_CALL_FLAGS_NO_AUTO_START, + DBUS_TIMEOUT, + NULL, &error_local); +@@ -345,7 +350,7 @@ main (int argc, char *argv[]) + password, + subman_options, + subman_conopts, +- userlang), ++ locale), + G_DBUS_CALL_FLAGS_NO_AUTO_START, + DBUS_TIMEOUT, + NULL, &error_local); +-- +2.37.0 + + +From a45af9d440fc55c1df3e4f12d15129d50d89f792 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 20 Aug 2020 13:34:19 -0400 +Subject: [PATCH 06/20] subman: Handle subscription-manager giving invalid + status better + +subscription-manager potentially returns status messages that the +subman plugin treats as enum values translated in some unknown +other language. It could be tied to system locale, or due to a +caching bug a previous locale used. + +This commit tries to work around that bug, by instead relying on +the GetUUID() method and valid attribute. If there's no UUID we +know the system is unregistered. If there's a UUID but the valid +attribute is FALSE we know the system is registered, but hasn't +got proper entitlements. +--- + plugins/subman/gsd-subscription-manager.c | 69 ++++++++++++----------- + 1 file changed, 36 insertions(+), 33 deletions(-) + +diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c +index 46f051a5..e2c16056 100644 +--- a/plugins/subman/gsd-subscription-manager.c ++++ b/plugins/subman/gsd-subscription-manager.c +@@ -131,23 +131,6 @@ gsd_subscription_manager_error_quark (void) + return quark; + } + +-static GsdSubmanSubscriptionStatus +-_client_subscription_status_from_text (const gchar *status_txt) +-{ +- if (g_strcmp0 (status_txt, "Unknown") == 0) +- return GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; +- if (g_strcmp0 (status_txt, "Current") == 0) +- return GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID; +- if (g_strcmp0 (status_txt, "Invalid") == 0) +- return GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID; +- if (g_strcmp0 (status_txt, "Disabled") == 0) +- return GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED; +- if (g_strcmp0 (status_txt, "Insufficient") == 0) +- return GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID; +- g_warning ("Unknown subscription status: %s", status_txt); // 'Current'? +- return GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; +-} +- + static GVariant * + _make_installed_products_variant (GPtrArray *installed_products) + { +@@ -275,40 +258,60 @@ static gboolean + _client_subscription_status_update (GsdSubscriptionManager *manager, GError **error) + { + GsdSubscriptionManagerPrivate *priv = manager->priv; ++ g_autoptr(GVariant) uuid = NULL; ++ const gchar *uuid_txt = NULL; + JsonNode *json_root; + JsonObject *json_obj; + const gchar *json_txt = NULL; +- const gchar *status_txt = NULL; +- g_autoptr(GVariant) val = NULL; ++ g_autoptr(GVariant) status = NULL; + g_autoptr(JsonParser) json_parser = json_parser_new (); + + /* save old value */ + priv->subscription_status_last = priv->subscription_status; + +- val = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_ENTITLEMENT], +- "GetStatus", +- g_variant_new ("(ss)", +- "", /* assumed as 'now' */ +- "C.UTF-8"), +- G_DBUS_CALL_FLAGS_NONE, +- -1, NULL, error); +- if (val == NULL) ++ uuid = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_CONSUMER], ++ "GetUuid", ++ g_variant_new ("(s)", ++ "C.UTF-8"), ++ G_DBUS_CALL_FLAGS_NONE, ++ -1, NULL, error); ++ if (uuid == NULL) + return FALSE; +- g_variant_get (val, "(&s)", &json_txt); ++ ++ g_variant_get (uuid, "(&s)", &uuid_txt); ++ ++ status = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_ENTITLEMENT], ++ "GetStatus", ++ g_variant_new ("(ss)", ++ "", /* assumed as 'now' */ ++ "C.UTF-8"), ++ G_DBUS_CALL_FLAGS_NONE, ++ -1, NULL, error); ++ if (status == NULL) ++ return FALSE; ++ g_variant_get (status, "(&s)", &json_txt); + g_debug ("Entitlement.GetStatus JSON: %s", json_txt); + if (!json_parser_load_from_data (json_parser, json_txt, -1, error)) + return FALSE; + json_root = json_parser_get_root (json_parser); + json_obj = json_node_get_object (json_root); +- if (!json_object_has_member (json_obj, "status")) { ++ if (!json_object_has_member (json_obj, "valid")) { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, +- "no Entitlement.GetStatus status in %s", json_txt); ++ "no Entitlement.GetStatus valid in %s", json_txt); + return FALSE; + } + +- status_txt = json_object_get_string_member (json_obj, "status"); +- g_debug ("Entitlement.GetStatus: %s", status_txt); +- priv->subscription_status = _client_subscription_status_from_text (status_txt); ++ gboolean is_valid = json_object_get_boolean_member (json_obj, "valid"); ++ ++ if (uuid_txt[0] != '\0') { ++ if (is_valid) { ++ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID; ++ } else { ++ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID; ++ } ++ } else { ++ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; ++ } + + /* emit notification for g-c-c */ + if (priv->subscription_status != priv->subscription_status_last) { +-- +2.37.0 + + +From 609e78ba17ee5610b35dd40f9763ca91306c3535 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 25 Aug 2020 10:34:03 -0400 +Subject: [PATCH 07/20] subman: Force re-subscribe if the admin already + subscribed + +It's possible for an admin to to half-enroll the system with RHN, +using the CLI tools. + +Meaning, it's possible for them to register the system with the +service, but not attach to a purchased license for the machine, +the, so called, entitlements. + +The subman module always does both halves of the registration process +in lock step. This means, if an admin tries to register using GNOME +while in a half-registered state, subman will fail because the first +step, the registration step, is already finished. + +This commit addresses that problem by trying to unregister up front +before registering. +--- + plugins/subman/gsd-subman-helper.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/plugins/subman/gsd-subman-helper.c b/plugins/subman/gsd-subman-helper.c +index 3c892c33..c248dbc3 100644 +--- a/plugins/subman/gsd-subman-helper.c ++++ b/plugins/subman/gsd-subman-helper.c +@@ -78,7 +78,6 @@ _helper_unregister (GError **error) + g_autoptr(GVariantBuilder) proxy_options = NULL; + g_autoptr(GVariant) res = NULL; + +- g_debug ("unregistering"); + proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | + G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, +@@ -235,6 +234,7 @@ main (int argc, char *argv[]) + return G_IO_ERROR_INVALID_DATA; + } + if (g_strcmp0 (kind, "unregister") == 0) { ++ g_debug ("unregistering"); + if (!_helper_unregister (&error)) { + g_printerr ("Failed to Unregister: %s\n", error->message); + return G_IO_ERROR_NOT_INITIALIZED; +@@ -306,6 +306,9 @@ main (int argc, char *argv[]) + return G_IO_ERROR_INVALID_DATA; + } + ++ g_debug ("trying to unregister in case machine is already registered"); ++ _helper_unregister (NULL); ++ + g_debug ("registering using activation key"); + activation_keys = g_strsplit (activation_key, ",", -1); + res = g_dbus_proxy_call_sync (proxy, +@@ -329,7 +332,6 @@ main (int argc, char *argv[]) + g_autoptr(GError) error_local = NULL; + g_autoptr(GVariant) res = NULL; + +- g_debug ("registering using username and password"); + if (username == NULL) { + g_printerr ("Required --username\n"); + return G_IO_ERROR_INVALID_DATA; +@@ -342,6 +344,11 @@ main (int argc, char *argv[]) + g_printerr ("Required --organisation\n"); + return G_IO_ERROR_INVALID_DATA; + } ++ ++ g_debug ("trying to unregister in case machine is already registered"); ++ _helper_unregister (NULL); ++ ++ g_debug ("registering using username and password"); + res = g_dbus_proxy_call_sync (proxy, + "Register", + g_variant_new ("(sssa{ss}a{ss}s)", +-- +2.37.0 + + +From c189fe1089c1f1975352b1a7fbe41f31ad3adc3b Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 25 Aug 2020 16:20:42 -0400 +Subject: [PATCH 08/20] subman: Don't send secrets through command line + +The command line is introspectable with "ps", and it even gets logged +to syslog, so it's not suitable for passing secrets. + +Unfortunately, the user's password is currently passed. + +This commit addresses that problem by passing the password through +stdin, instead. +--- + plugins/subman/gsd-subman-helper.c | 32 ++++++++------ + plugins/subman/gsd-subscription-manager.c | 52 ++++++++++++++++++++--- + plugins/subman/meson.build | 2 +- + 3 files changed, 66 insertions(+), 20 deletions(-) + +diff --git a/plugins/subman/gsd-subman-helper.c b/plugins/subman/gsd-subman-helper.c +index c248dbc3..03d2cd64 100644 +--- a/plugins/subman/gsd-subman-helper.c ++++ b/plugins/subman/gsd-subman-helper.c +@@ -21,12 +21,14 @@ + + #include "config.h" + ++ + #include + #include + #include + #include + + #include ++#include + #include + + #define DBUS_TIMEOUT 300000 /* 5 minutes */ +@@ -176,7 +178,6 @@ main (int argc, char *argv[]) + g_autofree gchar *hostname = NULL; + g_autofree gchar *kind = NULL; + g_autofree gchar *organisation = NULL; +- g_autofree gchar *password = NULL; + g_autofree gchar *port = NULL; + g_autofree gchar *prefix = NULL; + g_autofree gchar *proxy_server = NULL; +@@ -188,6 +189,7 @@ main (int argc, char *argv[]) + g_autoptr(GVariantBuilder) proxy_options = NULL; + g_autoptr(GVariantBuilder) subman_conopts = NULL; + g_autoptr(GVariantBuilder) subman_options = NULL; ++ g_autoptr(GInputStream) standard_input_stream = g_unix_input_stream_new (STDIN_FILENO, FALSE); + + const GOptionEntry options[] = { + { "kind", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, +@@ -196,12 +198,8 @@ main (int argc, char *argv[]) + &address, "UNIX address", NULL }, + { "username", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, + &username, "Username", NULL }, +- { "password", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, +- &password, "Password", NULL }, + { "organisation", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, + &organisation, "Organisation", NULL }, +- { "activation-key", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, +- &activation_key, "Activation keys", NULL }, + { "hostname", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, + &hostname, "Registration server hostname", NULL }, + { "prefix", '\0', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, +@@ -296,16 +294,20 @@ main (int argc, char *argv[]) + g_auto(GStrv) activation_keys = NULL; + g_autoptr(GError) error_local = NULL; + g_autoptr(GVariant) res = NULL; ++ gchar activation_key[PIPE_BUF + 1] = ""; + +- if (activation_key == NULL) { +- g_printerr ("Required --activation-key\n"); +- return G_IO_ERROR_INVALID_DATA; +- } + if (organisation == NULL) { + g_printerr ("Required --organisation\n"); + return G_IO_ERROR_INVALID_DATA; + } + ++ g_input_stream_read (standard_input_stream, activation_key, sizeof (activation_key) - 1, NULL, &error_local); ++ ++ if (error_local != NULL) { ++ g_printerr ("Could not read activation key: %s\n", error_local->message); ++ return G_IO_ERROR_INVALID_DATA; ++ } ++ + g_debug ("trying to unregister in case machine is already registered"); + _helper_unregister (NULL); + +@@ -331,20 +333,24 @@ main (int argc, char *argv[]) + } else if (g_strcmp0 (kind, "register-with-username") == 0) { + g_autoptr(GError) error_local = NULL; + g_autoptr(GVariant) res = NULL; ++ gchar password[PIPE_BUF + 1] = ""; + + if (username == NULL) { + g_printerr ("Required --username\n"); + return G_IO_ERROR_INVALID_DATA; + } +- if (password == NULL) { +- g_printerr ("Required --password\n"); +- return G_IO_ERROR_INVALID_DATA; +- } + if (organisation == NULL) { + g_printerr ("Required --organisation\n"); + return G_IO_ERROR_INVALID_DATA; + } + ++ g_input_stream_read (standard_input_stream, password, sizeof (password) - 1, NULL, &error_local); ++ ++ if (error_local != NULL) { ++ g_printerr ("Could not read password: %s\n", error_local->message); ++ return G_IO_ERROR_INVALID_DATA; ++ } ++ + g_debug ("trying to unregister in case machine is already registered"); + _helper_unregister (NULL); + +diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c +index e2c16056..0838d490 100644 +--- a/plugins/subman/gsd-subscription-manager.c ++++ b/plugins/subman/gsd-subscription-manager.c +@@ -21,6 +21,7 @@ + #include "config.h" + + #include ++#include + #include + #include + #include +@@ -544,26 +545,45 @@ _client_register_with_keys (GsdSubscriptionManager *manager, + { + GsdSubscriptionManagerPrivate *priv = manager->priv; + g_autoptr(GSubprocess) subprocess = NULL; ++ g_autoptr(GBytes) stdin_buf = g_bytes_new (activation_key, strlen (activation_key) + 1); ++ g_autoptr(GBytes) stderr_buf = NULL; ++ gint rc; + + /* apparently: "we can't send registration credentials over the regular + * system or session bus since those aren't really locked down..." */ + if (!_client_register_start (manager, error)) + return FALSE; + g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); +- subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error, ++ subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDERR_PIPE, error, + "pkexec", LIBEXECDIR "/gsd-subman-helper", + "--kind", "register-with-key", + "--address", priv->address, + "--hostname", hostname, + "--organisation", organisation, +- "--activation-key", activation_key, + NULL); + if (subprocess == NULL) { + g_prefix_error (error, "failed to find pkexec: "); + return FALSE; + } +- if (!_client_subprocess_wait_check (subprocess, error)) ++ ++ if (!g_subprocess_communicate (subprocess, stdin_buf, NULL, NULL, &stderr_buf, error)) { ++ g_prefix_error (error, "failed to run pkexec: "); + return FALSE; ++ } ++ ++ rc = g_subprocess_get_exit_status (subprocess); ++ if (rc != 0) { ++ if (g_bytes_get_size (stderr_buf) == 0) { ++ g_set_error_literal (error, G_IO_ERROR, rc, ++ "Failed to run helper without stderr"); ++ return FALSE; ++ } ++ ++ g_set_error (error, G_IO_ERROR, rc, ++ "%.*s", ++ g_bytes_get_size (stderr_buf), ++ g_bytes_get_data (stderr_buf, NULL)); ++ } + + /* FIXME: also do on error? */ + if (!_client_register_stop (manager, error)) +@@ -588,6 +608,9 @@ _client_register (GsdSubscriptionManager *manager, + { + GsdSubscriptionManagerPrivate *priv = manager->priv; + g_autoptr(GSubprocess) subprocess = NULL; ++ g_autoptr(GBytes) stdin_buf = g_bytes_new (password, strlen (password) + 1); ++ g_autoptr(GBytes) stderr_buf = NULL; ++ gint rc; + + /* fallback */ + if (organisation == NULL) +@@ -598,21 +621,38 @@ _client_register (GsdSubscriptionManager *manager, + if (!_client_register_start (manager, error)) + return FALSE; + g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); +- subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, error, ++ subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDERR_PIPE, ++ error, + "pkexec", LIBEXECDIR "/gsd-subman-helper", + "--kind", "register-with-username", + "--address", priv->address, + "--hostname", hostname, + "--organisation", organisation, + "--username", username, +- "--password", password, + NULL); + if (subprocess == NULL) { + g_prefix_error (error, "failed to find pkexec: "); + return FALSE; + } +- if (!_client_subprocess_wait_check (subprocess, error)) ++ ++ if (!g_subprocess_communicate (subprocess, stdin_buf, NULL, NULL, &stderr_buf, error)) { ++ g_prefix_error (error, "failed to run pkexec: "); + return FALSE; ++ } ++ ++ rc = g_subprocess_get_exit_status (subprocess); ++ if (rc != 0) { ++ if (g_bytes_get_size (stderr_buf) == 0) { ++ g_set_error_literal (error, G_IO_ERROR, rc, ++ "Failed to run helper without stderr"); ++ return FALSE; ++ } ++ ++ g_set_error (error, G_IO_ERROR, rc, ++ "%.*s", ++ g_bytes_get_size (stderr_buf), ++ g_bytes_get_data (stderr_buf, NULL)); ++ } + + /* FIXME: also do on error? */ + if (!_client_register_stop (manager, error)) +diff --git a/plugins/subman/meson.build b/plugins/subman/meson.build +index bfd073b6..e4b4589d 100644 +--- a/plugins/subman/meson.build ++++ b/plugins/subman/meson.build +@@ -49,7 +49,7 @@ executable( + 'gsd-subman-helper', + 'gsd-subman-helper.c', + include_directories: top_inc, +- dependencies: [gio_dep, jsonglib_dep], ++ dependencies: [gio_dep, gio_unix_dep, jsonglib_dep], + install: true, + install_rpath: gsd_pkglibdir, + install_dir: gsd_libexecdir +-- +2.37.0 + + +From 3398c5037f9bdf2f6d3d2161146a6edea6c144f2 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 21 Jan 2021 09:52:19 -0500 +Subject: [PATCH 09/20] subman: Don't treat failure to attach as fatal + +Many organizations don't require specific subscriptions to get +updates (called "simple content access"). At the moment, +those systems get an error when registering. + +This commit quiets the error. +--- + plugins/subman/gsd-subman-helper.c | 46 ++++++++++++++++++++++++------ + 1 file changed, 37 insertions(+), 9 deletions(-) + +diff --git a/plugins/subman/gsd-subman-helper.c b/plugins/subman/gsd-subman-helper.c +index 03d2cd64..ddfe389f 100644 +--- a/plugins/subman/gsd-subman-helper.c ++++ b/plugins/subman/gsd-subman-helper.c +@@ -52,6 +52,17 @@ _helper_convert_error (const gchar *json_txt, GError **error) + } + json_root = json_parser_get_root (json_parser); + json_obj = json_node_get_object (json_root); ++ if (json_object_has_member (json_obj, "severity")) { ++ const gchar *severity; ++ ++ /* warnings are non-fatal so we ignore them ++ */ ++ severity = json_object_get_string_member (json_obj, "severity"); ++ if (g_strstr_len (severity, -1, "warning") != NULL) { ++ return; ++ } ++ } ++ + if (!json_object_has_member (json_obj, "message")) { + g_set_error (error, + G_IO_ERROR, +@@ -108,6 +119,7 @@ static gboolean + _helper_auto_attach (GError **error) + { + const gchar *str = NULL; ++ g_autoptr(GError) error_local = NULL; + g_autoptr(GDBusProxy) proxy = NULL; + g_autoptr(GVariantBuilder) proxy_options = NULL; + g_autoptr(GVariant) res = NULL; +@@ -120,9 +132,12 @@ _helper_auto_attach (GError **error) + "com.redhat.RHSM1", + "/com/redhat/RHSM1/Attach", + "com.redhat.RHSM1.Attach", +- NULL, error); ++ NULL, &error_local); + if (proxy == NULL) { +- g_prefix_error (error, "Failed to get proxy: "); ++ g_dbus_error_strip_remote_error (error_local); ++ g_propagate_prefixed_error (error, ++ g_steal_pointer (&error_local), ++ "Failed to get proxy: "); + return FALSE; + } + proxy_options = g_variant_builder_new (G_VARIANT_TYPE_VARDICT); +@@ -134,9 +149,18 @@ _helper_auto_attach (GError **error) + locale), + G_DBUS_CALL_FLAGS_NONE, + DBUS_TIMEOUT, +- NULL, error); +- if (res == NULL) +- return FALSE; ++ NULL, &error_local); ++ if (res == NULL) { ++ g_dbus_error_strip_remote_error (error_local); ++ _helper_convert_error (error_local->message, error); ++ ++ if (*error != NULL) { ++ g_prefix_error (error, "Failed to get proxy: "); ++ return FALSE; ++ } ++ ++ return TRUE; ++ } + g_variant_get (res, "(&s)", &str); + g_debug ("Attach.AutoAttach: %s", str); + return TRUE; +@@ -327,8 +351,10 @@ main (int argc, char *argv[]) + if (res == NULL) { + g_dbus_error_strip_remote_error (error_local); + _helper_convert_error (error_local->message, &error); +- g_printerr ("Failed to RegisterWithActivationKeys: %s\n", error->message); +- return error->code; ++ if (error != NULL) { ++ g_printerr ("Failed to RegisterWithActivationKeys: %s\n", error->message); ++ return error->code; ++ } + } + } else if (g_strcmp0 (kind, "register-with-username") == 0) { + g_autoptr(GError) error_local = NULL; +@@ -370,8 +396,10 @@ main (int argc, char *argv[]) + if (res == NULL) { + g_dbus_error_strip_remote_error (error_local); + _helper_convert_error (error_local->message, &error); +- g_printerr ("Failed to Register: %s\n", error->message); +- return error->code; ++ if (error != NULL) { ++ g_printerr ("Failed to Register: %s\n", error->message); ++ return error->code; ++ } + } + } else { + g_printerr ("Invalid --kind specified: %s\n", kind); +-- +2.37.0 + + +From ae88d09fd12a971d5f60c5eee5d3b7710e4884be Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Sun, 24 Jan 2021 11:24:36 -0500 +Subject: [PATCH 10/20] subman: Add new no-installed-products state + +It's possible, though unlikley, the system has +no packages installed from Red Hat supported package sets. + +This commit adds a new state to track that situation. +--- + plugins/subman/gsd-subman-common.c | 2 ++ + plugins/subman/gsd-subman-common.h | 1 + + plugins/subman/gsd-subscription-manager.c | 17 +++++++---------- + 3 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/plugins/subman/gsd-subman-common.c b/plugins/subman/gsd-subman-common.c +index e515131e..eef5175d 100644 +--- a/plugins/subman/gsd-subman-common.c ++++ b/plugins/subman/gsd-subman-common.c +@@ -32,5 +32,7 @@ gsd_subman_subscription_status_to_string (GsdSubmanSubscriptionStatus status) + return "disabled"; + if (status == GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID) + return "partially-valid"; ++ if (status == GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS) ++ return "no-installed-products"; + return "unknown"; + } +diff --git a/plugins/subman/gsd-subman-common.h b/plugins/subman/gsd-subman-common.h +index fccf9f6a..f8a3d9f4 100644 +--- a/plugins/subman/gsd-subman-common.h ++++ b/plugins/subman/gsd-subman-common.h +@@ -30,6 +30,7 @@ typedef enum { + GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID, + GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED, + GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID, ++ GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS, + GSD_SUBMAN_SUBSCRIPTION_STATUS_LAST + } GsdSubmanSubscriptionStatus; + +diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c +index 0838d490..46f8d35c 100644 +--- a/plugins/subman/gsd-subscription-manager.c ++++ b/plugins/subman/gsd-subscription-manager.c +@@ -269,6 +269,13 @@ _client_subscription_status_update (GsdSubscriptionManager *manager, GError **er + + /* save old value */ + priv->subscription_status_last = priv->subscription_status; ++ if (!_client_installed_products_update (manager, error)) ++ goto out; ++ ++ if (priv->installed_products->len == 0) { ++ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS; ++ goto out; ++ } + + uuid = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_CONSUMER], + "GetUuid", +@@ -590,8 +597,6 @@ _client_register_with_keys (GsdSubscriptionManager *manager, + return FALSE; + if (!_client_subscription_status_update (manager, error)) + return FALSE; +- if (!_client_installed_products_update (manager, error)) +- return FALSE; + _client_maybe__show_notification (manager); + + /* success */ +@@ -659,8 +664,6 @@ _client_register (GsdSubscriptionManager *manager, + return FALSE; + if (!_client_subscription_status_update (manager, error)) + return FALSE; +- if (!_client_installed_products_update (manager, error)) +- return FALSE; + _client_maybe__show_notification (manager); + return TRUE; + } +@@ -741,10 +744,6 @@ _subman_proxy_signal_cb (GDBusProxy *proxy, + g_warning ("failed to update subscription status: %s", error->message); + g_clear_error (&error); + } +- if (!_client_installed_products_update (manager, &error)) { +- g_warning ("failed to update installed products: %s", error->message); +- g_clear_error (&error); +- } + _client_maybe__show_notification (manager); + } + +@@ -809,8 +808,6 @@ _client_load (GsdSubscriptionManager *manager, GError **error) + return FALSE; + if (!_client_subscription_status_update (manager, error)) + return FALSE; +- if (!_client_installed_products_update (manager, error)) +- return FALSE; + if (!_client_syspurpose_update (manager, error)) + return FALSE; + +-- +2.37.0 + + +From 18e5e5862aba2031d1a93671ad8156dcc7709eaf Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Sun, 24 Jan 2021 11:26:40 -0500 +Subject: [PATCH 11/20] subman: Fix some build warnings + +--- + plugins/subman/gsd-subscription-manager.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c +index 46f8d35c..1f9ca447 100644 +--- a/plugins/subman/gsd-subscription-manager.c ++++ b/plugins/subman/gsd-subscription-manager.c +@@ -588,8 +588,8 @@ _client_register_with_keys (GsdSubscriptionManager *manager, + + g_set_error (error, G_IO_ERROR, rc, + "%.*s", +- g_bytes_get_size (stderr_buf), +- g_bytes_get_data (stderr_buf, NULL)); ++ (int) g_bytes_get_size (stderr_buf), ++ (char *) g_bytes_get_data (stderr_buf, NULL)); + } + + /* FIXME: also do on error? */ +@@ -655,8 +655,8 @@ _client_register (GsdSubscriptionManager *manager, + + g_set_error (error, G_IO_ERROR, rc, + "%.*s", +- g_bytes_get_size (stderr_buf), +- g_bytes_get_data (stderr_buf, NULL)); ++ (int) g_bytes_get_size (stderr_buf), ++ (char *) g_bytes_get_data (stderr_buf, NULL)); + } + + /* FIXME: also do on error? */ +-- +2.37.0 + + +From f3f5369b1d68f002b020f803fb59cdcb3205e6dc Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Sun, 24 Jan 2021 11:27:42 -0500 +Subject: [PATCH 12/20] subman: Add DBus API to subscribe for updates on + already registered system + +It's possible an admin may have registered their system without +attaching any subscriptions to it. + +At the moment, gnome-settings-daemon only provides a way to register +and subscribe in one step. + +This commit adds an API to support doing the last half of the process +on its own. +--- + plugins/subman/gsd-subscription-manager.c | 51 +++++++++++++++++++++++ + 1 file changed, 51 insertions(+) + +diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c +index 1f9ca447..705f8b11 100644 +--- a/plugins/subman/gsd-subscription-manager.c ++++ b/plugins/subman/gsd-subscription-manager.c +@@ -46,6 +46,7 @@ static const gchar introspection_xml[] = + " " + " " + " " ++" " + " " + " " + " " +@@ -696,6 +697,50 @@ _client_unregister (GsdSubscriptionManager *manager, GError **error) + return TRUE; + } + ++static gboolean ++_client_attach (GsdSubscriptionManager *manager, ++ GError **error) ++{ ++ g_autoptr(GSubprocess) subprocess = NULL; ++ g_autoptr(GBytes) stderr_buf = NULL; ++ gint rc; ++ ++ g_debug ("spawning %s", LIBEXECDIR "/gsd-subman-helper"); ++ subprocess = g_subprocess_new (G_SUBPROCESS_FLAGS_STDERR_PIPE, ++ error, ++ "pkexec", LIBEXECDIR "/gsd-subman-helper", ++ "--kind", "auto-attach", ++ NULL); ++ if (subprocess == NULL) { ++ g_prefix_error (error, "failed to find pkexec: "); ++ return FALSE; ++ } ++ ++ if (!g_subprocess_communicate (subprocess, NULL, NULL, NULL, &stderr_buf, error)) { ++ g_prefix_error (error, "failed to run pkexec: "); ++ return FALSE; ++ } ++ ++ rc = g_subprocess_get_exit_status (subprocess); ++ if (rc != 0) { ++ if (g_bytes_get_size (stderr_buf) == 0) { ++ g_set_error_literal (error, G_IO_ERROR, rc, ++ "Failed to run helper without stderr"); ++ return FALSE; ++ } ++ ++ g_set_error (error, G_IO_ERROR, rc, ++ "%.*s", ++ (int) g_bytes_get_size (stderr_buf), ++ (char *) g_bytes_get_data (stderr_buf, NULL)); ++ } ++ ++ if (!_client_subscription_status_update (manager, error)) ++ return FALSE; ++ _client_maybe__show_notification (manager); ++ return TRUE; ++} ++ + static gboolean + _client_update_config (GsdSubscriptionManager *manager, GError **error) + { +@@ -1029,6 +1074,12 @@ handle_method_call (GDBusConnection *connection, + return; + } + g_dbus_method_invocation_return_value (invocation, NULL); ++ } else if (g_strcmp0 (method_name, "Attach") == 0) { ++ if (!_client_attach (manager, &error)) { ++ g_dbus_method_invocation_return_gerror (invocation, error); ++ return; ++ } ++ g_dbus_method_invocation_return_value (invocation, NULL); + } else { + g_assert_not_reached (); + } +-- +2.37.0 + + +From d00d1c34921d6301579ee29a51be89ce8250e83d Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Sun, 24 Jan 2021 11:34:03 -0500 +Subject: [PATCH 13/20] subman: Improve subscription status handling + +This commit improves how subscription-manager status is +parsed to give more detailed information about subscription +state. +--- + plugins/subman/gsd-subscription-manager.c | 33 +++++++++++++++++++---- + 1 file changed, 28 insertions(+), 5 deletions(-) + +diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c +index 705f8b11..6d80bfa9 100644 +--- a/plugins/subman/gsd-subscription-manager.c ++++ b/plugins/subman/gsd-subscription-manager.c +@@ -289,6 +289,11 @@ _client_subscription_status_update (GsdSubscriptionManager *manager, GError **er + + g_variant_get (uuid, "(&s)", &uuid_txt); + ++ if (uuid_txt[0] == '\0') { ++ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; ++ goto out; ++ } ++ + status = g_dbus_proxy_call_sync (priv->proxies[_RHSM_INTERFACE_ENTITLEMENT], + "GetStatus", + g_variant_new ("(ss)", +@@ -304,6 +309,13 @@ _client_subscription_status_update (GsdSubscriptionManager *manager, GError **er + return FALSE; + json_root = json_parser_get_root (json_parser); + json_obj = json_node_get_object (json_root); ++ ++ const gchar *status_id = NULL; ++ ++ if (json_object_has_member (json_obj, "status_id")) { ++ status_id = json_object_get_string_member (json_obj, "status_id"); ++ } ++ + if (!json_object_has_member (json_obj, "valid")) { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, + "no Entitlement.GetStatus valid in %s", json_txt); +@@ -312,16 +324,27 @@ _client_subscription_status_update (GsdSubscriptionManager *manager, GError **er + + gboolean is_valid = json_object_get_boolean_member (json_obj, "valid"); + +- if (uuid_txt[0] != '\0') { +- if (is_valid) { ++ if (is_valid) { ++ if (g_strcmp0 (status_id, "disabled") != 0) { + priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID; + } else { +- priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID; ++ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED; ++ } ++ goto out; ++ } ++ ++ for (guint i = 0; i < priv->installed_products->len; i++) { ++ ProductData *product = g_ptr_array_index (priv->installed_products, i); ++ ++ if (g_strcmp0 (product->status, "subscribed") == 0) { ++ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID; ++ goto out; + } +- } else { +- priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN; + } + ++ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID; ++ ++out: + /* emit notification for g-c-c */ + if (priv->subscription_status != priv->subscription_status_last) { + _emit_property_changed (manager, "SubscriptionStatus", +-- +2.37.0 + + +From a3d4e534a1dfa6a6ff68d0bede69e063ffeeb4d7 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Sun, 24 Jan 2021 11:55:19 -0500 +Subject: [PATCH 14/20] subman: Drop "LAST" from status enum + +It's unused, so get rid of it. +--- + plugins/subman/gsd-subman-common.h | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/plugins/subman/gsd-subman-common.h b/plugins/subman/gsd-subman-common.h +index f8a3d9f4..88226564 100644 +--- a/plugins/subman/gsd-subman-common.h ++++ b/plugins/subman/gsd-subman-common.h +@@ -31,7 +31,6 @@ typedef enum { + GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED, + GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID, + GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS, +- GSD_SUBMAN_SUBSCRIPTION_STATUS_LAST + } GsdSubmanSubscriptionStatus; + + const gchar *gsd_subman_subscription_status_to_string (GsdSubmanSubscriptionStatus status); +-- +2.37.0 + + +From 78859ea58014ee740de0c484308b6dedf4c59ab3 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Sun, 24 Jan 2021 12:41:20 -0500 +Subject: [PATCH 15/20] subman: Clean up notification behavior + +Notifications were only displayed for some status transitions. + +This commit introduces some booleans based on the old and new +statuses to make the code clearer and to make it easier to hit +all the cases. +--- + plugins/subman/gsd-subman-common.h | 1 + + plugins/subman/gsd-subscription-manager.c | 141 ++++++++++++++++++---- + 2 files changed, 120 insertions(+), 22 deletions(-) + +diff --git a/plugins/subman/gsd-subman-common.h b/plugins/subman/gsd-subman-common.h +index 88226564..9397dbe4 100644 +--- a/plugins/subman/gsd-subman-common.h ++++ b/plugins/subman/gsd-subman-common.h +@@ -25,6 +25,7 @@ + G_BEGIN_DECLS + + typedef enum { ++ GSD_SUBMAN_SUBSCRIPTION_STATUS_NOT_READ = -1, + GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN, + GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID, + GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID, +diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c +index 6d80bfa9..aaccbbc6 100644 +--- a/plugins/subman/gsd-subscription-manager.c ++++ b/plugins/subman/gsd-subscription-manager.c +@@ -270,6 +270,7 @@ _client_subscription_status_update (GsdSubscriptionManager *manager, GError **er + + /* save old value */ + priv->subscription_status_last = priv->subscription_status; ++ + if (!_client_installed_products_update (manager, error)) + goto out; + +@@ -512,55 +513,149 @@ static void + _client_maybe__show_notification (GsdSubscriptionManager *manager) + { + GsdSubscriptionManagerPrivate *priv = manager->priv; ++ gboolean was_read, was_registered, had_subscriptions, needed_subscriptions; ++ gboolean is_read, is_registered, has_subscriptions, needs_subscriptions; ++ ++ switch (priv->subscription_status_last) { ++ case GSD_SUBMAN_SUBSCRIPTION_STATUS_NOT_READ: ++ was_read = FALSE; ++ was_registered = FALSE; ++ needed_subscriptions = TRUE; ++ had_subscriptions = FALSE; ++ break; ++ case GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN: ++ was_read = TRUE; ++ was_registered = FALSE; ++ needed_subscriptions = TRUE; ++ had_subscriptions = FALSE; ++ break; ++ case GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID: ++ was_read = TRUE; ++ was_registered = TRUE; ++ needed_subscriptions = TRUE; ++ had_subscriptions = TRUE; ++ break; ++ case GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID: ++ was_read = TRUE; ++ was_registered = TRUE; ++ needed_subscriptions = TRUE; ++ had_subscriptions = FALSE; ++ break; ++ case GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED: ++ was_read = TRUE; ++ was_registered = TRUE; ++ needed_subscriptions = FALSE; ++ had_subscriptions = FALSE; ++ break; ++ case GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID: ++ was_read = TRUE; ++ was_registered = TRUE; ++ needed_subscriptions = TRUE; ++ had_subscriptions = FALSE; ++ case GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS: ++ was_read = TRUE; ++ was_registered = FALSE; ++ needed_subscriptions = FALSE; ++ had_subscriptions = FALSE; ++ break; ++ } ++ ++ switch (priv->subscription_status) { ++ case GSD_SUBMAN_SUBSCRIPTION_STATUS_NOT_READ: ++ is_read = FALSE; ++ is_registered = FALSE; ++ needs_subscriptions = TRUE; ++ has_subscriptions = FALSE; ++ break; ++ case GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN: ++ is_read = TRUE; ++ is_registered = FALSE; ++ needs_subscriptions = TRUE; ++ has_subscriptions = FALSE; ++ break; ++ case GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID: ++ is_read = TRUE; ++ is_registered = TRUE; ++ needs_subscriptions = TRUE; ++ has_subscriptions = TRUE; ++ break; ++ case GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID: ++ case GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID: ++ is_read = TRUE; ++ is_registered = TRUE; ++ needs_subscriptions = TRUE; ++ has_subscriptions = FALSE; ++ break; ++ case GSD_SUBMAN_SUBSCRIPTION_STATUS_DISABLED: ++ is_read = TRUE; ++ is_registered = TRUE; ++ needs_subscriptions = FALSE; ++ has_subscriptions = FALSE; ++ break; ++ case GSD_SUBMAN_SUBSCRIPTION_STATUS_NO_INSTALLED_PRODUCTS: ++ is_read = TRUE; ++ is_registered = FALSE; ++ needs_subscriptions = FALSE; ++ has_subscriptions = FALSE; ++ break; ++ } + + /* startup */ +- if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN && +- priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN) { ++ if (!was_read && is_read && priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN) { + _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); + return; + } + + /* something changed */ +- if (priv->subscription_status_last != priv->subscription_status) { ++ if (was_read && is_read && priv->subscription_status_last != priv->subscription_status) { + g_debug ("transisition from subscription status '%s' to '%s'", + gsd_subman_subscription_status_to_string (priv->subscription_status_last), + gsd_subman_subscription_status_to_string (priv->subscription_status)); + +- /* needs registration */ +- if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID && +- priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID) { +- _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); ++ /* needs subscription */ ++ if (is_registered && needs_subscriptions && !has_subscriptions) { ++ _show_notification (manager, _NOTIFY_EXPIRED); + return; + } + + /* was unregistered */ +- if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID && +- priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN) { ++ if (was_registered && !is_registered) { + _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); + return; + } + +- /* registered */ +- if (priv->subscription_status_last == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN && +- priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_VALID && +- g_timer_elapsed (priv->timer_last_notified, NULL) > 60) { +- _show_notification (manager, _NOTIFY_REGISTERED); +- return; ++ /* just registered */ ++ if (!was_registered && is_registered) { ++ if (!needs_subscriptions || has_subscriptions) { ++ _show_notification (manager, _NOTIFY_REGISTERED); ++ return; ++ } ++ } ++ ++ /* subscriptions changed */ ++ if (was_registered && is_registered) { ++ /* subscribed */ ++ if (!had_subscriptions && ++ needs_subscriptions && has_subscriptions) { ++ _show_notification (manager, _NOTIFY_REGISTERED); ++ return; ++ } ++ ++ /* simple content access enabled */ ++ if (needed_subscriptions && !had_subscriptions && !needs_subscriptions) { ++ _show_notification (manager, _NOTIFY_REGISTERED); ++ return; ++ } + } + } + + /* nag again */ +- if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_UNKNOWN && ++ if (!is_registered && + g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { + _show_notification (manager, _NOTIFY_REGISTRATION_REQUIRED); + return; + } +- if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_INVALID && +- g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { +- _show_notification (manager, _NOTIFY_EXPIRED); +- return; +- } +- if (priv->subscription_status == GSD_SUBMAN_SUBSCRIPTION_STATUS_PARTIALLY_VALID && ++ if (is_registered && !has_subscriptions && needs_subscriptions && + g_timer_elapsed (priv->timer_last_notified, NULL) > 60 * 60 * 24) { + _show_notification (manager, _NOTIFY_EXPIRED); + return; +@@ -941,6 +1036,8 @@ gsd_subscription_manager_init (GsdSubscriptionManager *manager) + + priv->installed_products = g_ptr_array_new_with_free_func ((GDestroyNotify) product_data_free); + priv->timer_last_notified = g_timer_new (); ++ priv->subscription_status = GSD_SUBMAN_SUBSCRIPTION_STATUS_NOT_READ; ++ priv->subscription_status_last = GSD_SUBMAN_SUBSCRIPTION_STATUS_NOT_READ; + + /* expired */ + priv->notification_expired = +-- +2.37.0 + + +From f9a405172b08607777b47c03dbd1034227690fce Mon Sep 17 00:00:00 2001 +From: Kalev Lember +Date: Fri, 12 Feb 2021 14:51:29 +0100 +Subject: [PATCH 16/20] subman: Update POTFILES.in + +--- + po/POTFILES.in | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/po/POTFILES.in b/po/POTFILES.in +index e721f526..7d5b7e9d 100644 +--- a/po/POTFILES.in ++++ b/po/POTFILES.in +@@ -24,6 +24,8 @@ plugins/print-notifications/gsd-printer.c + plugins/print-notifications/gsd-print-notifications-manager.c + plugins/smartcard/gsd-smartcard-manager.c + plugins/smartcard/gsd-smartcard-service.c ++plugins/subman/gsd-subscription-manager.c ++plugins/subman/org.gnome.settings-daemon.plugins.subman.policy.in.in + plugins/usb-protection/gsd-usb-protection-manager.c + plugins/wacom/gsd-wacom-manager.c + plugins/wacom/org.gnome.settings-daemon.plugins.wacom.policy.in.in +-- +2.37.0 + + +From 957d7916a843140898f7a3ca2adeb826cd5e6a99 Mon Sep 17 00:00:00 2001 +From: Kalev Lember +Date: Mon, 6 Sep 2021 21:31:14 +0200 +Subject: [PATCH 17/20] subman: Don't force X11 backend + +All of this should work just fine with Wayland. +--- + plugins/subman/main.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/plugins/subman/main.c b/plugins/subman/main.c +index 28ac995b..839c1b79 100644 +--- a/plugins/subman/main.c ++++ b/plugins/subman/main.c +@@ -2,7 +2,6 @@ + #define START gsd_subscription_manager_start + #define STOP gsd_subscription_manager_stop + #define MANAGER GsdSubscriptionManager +-#define GDK_BACKEND "x11" + #include "gsd-subscription-manager.h" + + #include "daemon-skeleton-gtk.h" +-- +2.37.0 + + +From ea88e09c4e9cb2a6dc67740d556f52761297f5b6 Mon Sep 17 00:00:00 2001 +From: Kalev Lember +Date: Tue, 7 Sep 2021 13:08:12 +0200 +Subject: [PATCH 18/20] subman: Fix desktop file hint for notifications + +We don't have a separate subman-panel. It's all part of +info-overview-panel, as of now at least. +--- + plugins/subman/gsd-subscription-manager.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c +index aaccbbc6..be978fc3 100644 +--- a/plugins/subman/gsd-subscription-manager.c ++++ b/plugins/subman/gsd-subscription-manager.c +@@ -1045,7 +1045,7 @@ gsd_subscription_manager_init (GsdSubscriptionManager *manager) + _("Add or renew a subscription to continue receiving software updates."), + NULL); + notify_notification_set_app_name (priv->notification_expired, _("Subscription")); +- notify_notification_set_hint_string (priv->notification_expired, "desktop-entry", "subman-panel"); ++ notify_notification_set_hint_string (priv->notification_expired, "desktop-entry", "gnome-info-overview-panel"); + notify_notification_set_hint_string (priv->notification_expired, "x-gnome-privacy-scope", "system"); + notify_notification_set_urgency (priv->notification_expired, NOTIFY_URGENCY_CRITICAL); + notify_notification_add_action (priv->notification_expired, +@@ -1061,7 +1061,7 @@ gsd_subscription_manager_init (GsdSubscriptionManager *manager) + _("The system has been registered and software updates have been enabled."), + NULL); + notify_notification_set_app_name (priv->notification_registered, _("Subscription")); +- notify_notification_set_hint_string (priv->notification_registered, "desktop-entry", "subman-panel"); ++ notify_notification_set_hint_string (priv->notification_registered, "desktop-entry", "gnome-info-overview-panel"); + notify_notification_set_hint_string (priv->notification_registered, "x-gnome-privacy-scope", "system"); + notify_notification_set_urgency (priv->notification_registered, NOTIFY_URGENCY_CRITICAL); + g_signal_connect (priv->notification_registered, "closed", +@@ -1073,7 +1073,7 @@ gsd_subscription_manager_init (GsdSubscriptionManager *manager) + _("Please register your system to receive software updates."), + NULL); + notify_notification_set_app_name (priv->notification_registration_required, _("Subscription")); +- notify_notification_set_hint_string (priv->notification_registration_required, "desktop-entry", "subman-panel"); ++ notify_notification_set_hint_string (priv->notification_registration_required, "desktop-entry", "gnome-info-overview-panel"); + notify_notification_set_hint_string (priv->notification_registration_required, "x-gnome-privacy-scope", "system"); + notify_notification_set_urgency (priv->notification_registration_required, NOTIFY_URGENCY_CRITICAL); + notify_notification_add_action (priv->notification_registration_required, +-- +2.37.0 + + +From 3b21bc12315dba099d7377b55109bc5f942960f2 Mon Sep 17 00:00:00 2001 +From: Kalev Lember +Date: Wed, 8 Sep 2021 13:25:07 +0200 +Subject: [PATCH 19/20] subman: Use preferences-system icon for notifications + +Use it as a placeholder until we get a new icon for subscription +management. +--- + plugins/subman/gsd-subscription-manager.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/plugins/subman/gsd-subscription-manager.c b/plugins/subman/gsd-subscription-manager.c +index be978fc3..dbb81098 100644 +--- a/plugins/subman/gsd-subscription-manager.c ++++ b/plugins/subman/gsd-subscription-manager.c +@@ -1043,7 +1043,7 @@ gsd_subscription_manager_init (GsdSubscriptionManager *manager) + priv->notification_expired = + notify_notification_new (_("Subscription Has Expired"), + _("Add or renew a subscription to continue receiving software updates."), +- NULL); ++ "preferences-system"); + notify_notification_set_app_name (priv->notification_expired, _("Subscription")); + notify_notification_set_hint_string (priv->notification_expired, "desktop-entry", "gnome-info-overview-panel"); + notify_notification_set_hint_string (priv->notification_expired, "x-gnome-privacy-scope", "system"); +@@ -1059,7 +1059,7 @@ gsd_subscription_manager_init (GsdSubscriptionManager *manager) + priv->notification_registered = + notify_notification_new (_("Registration Successful"), + _("The system has been registered and software updates have been enabled."), +- NULL); ++ "preferences-system"); + notify_notification_set_app_name (priv->notification_registered, _("Subscription")); + notify_notification_set_hint_string (priv->notification_registered, "desktop-entry", "gnome-info-overview-panel"); + notify_notification_set_hint_string (priv->notification_registered, "x-gnome-privacy-scope", "system"); +@@ -1071,7 +1071,7 @@ gsd_subscription_manager_init (GsdSubscriptionManager *manager) + priv->notification_registration_required = + notify_notification_new (_("System Not Registered"), + _("Please register your system to receive software updates."), +- NULL); ++ "preferences-system"); + notify_notification_set_app_name (priv->notification_registration_required, _("Subscription")); + notify_notification_set_hint_string (priv->notification_registration_required, "desktop-entry", "gnome-info-overview-panel"); + notify_notification_set_hint_string (priv->notification_registration_required, "x-gnome-privacy-scope", "system"); +-- +2.37.0 + + +From b7da34ad4cfb05a3d50495da65a7d76abacc965f Mon Sep 17 00:00:00 2001 +From: Felipe Borges +Date: Fri, 15 Jul 2022 15:25:14 +0200 +Subject: [PATCH 20/20] subman: Set "enable_content" option only for Register + +The "enable_content" option doesn't work for +RegisterWithActivationKey. +--- + plugins/subman/gsd-subman-helper.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/plugins/subman/gsd-subman-helper.c b/plugins/subman/gsd-subman-helper.c +index ddfe389f..bc56a8c2 100644 +--- a/plugins/subman/gsd-subman-helper.c ++++ b/plugins/subman/gsd-subman-helper.c +@@ -299,8 +299,6 @@ main (int argc, char *argv[]) + /* enable_content=1 auto attaches the subscription */ + subman_options = g_variant_builder_new (G_VARIANT_TYPE("a{ss}")); + +- g_variant_builder_add (subman_options, "{ss}", "enable_content", "1"); +- + /* set registration server */ + if (hostname == NULL || hostname[0] == '\0') + hostname = g_strdup ("subscription.rhsm.redhat.com"); +@@ -361,6 +359,8 @@ main (int argc, char *argv[]) + g_autoptr(GVariant) res = NULL; + gchar password[PIPE_BUF + 1] = ""; + ++ g_variant_builder_add (subman_options, "{ss}", "enable_content", "1"); ++ + if (username == NULL) { + g_printerr ("Required --username\n"); + return G_IO_ERROR_INVALID_DATA; +-- +2.37.0 + diff --git a/SPECS/gnome-settings-daemon.spec b/SPECS/gnome-settings-daemon.spec new file mode 100644 index 0000000..0631142 --- /dev/null +++ b/SPECS/gnome-settings-daemon.spec @@ -0,0 +1,1534 @@ +%global glib2_version 2.56 +%global colord_version 1.4.5 +%global geocode_glib_version 3.10.0 +%global gnome_desktop_version 3.37.1 +%global gsettings_desktop_schemas_version 40 +%global gtk3_version 3.15.3 +%global libgweather_version 40~alpha +%global geoclue_version 2.3.1 + +%global tarball_version %%(echo %{version} | tr '~' '.') + +Name: gnome-settings-daemon +Version: 40.0.1 +Release: 10%{?dist} +Summary: The daemon sharing settings from GNOME to GTK+/KDE applications + +License: GPLv2+ +URL: https://download.gnome.org/sources/%{name} +Source0: https://download.gnome.org/sources/%{name}/40/%{name}-%{tarball_version}.tar.xz +Source1: org.gnome.settings-daemon.plugins.power.gschema.override + +BuildRequires: meson >= 0.44.0 +BuildRequires: gcc +BuildRequires: cups-devel +BuildRequires: gettext +BuildRequires: perl-interpreter +BuildRequires: pkgconfig(alsa) +BuildRequires: pkgconfig(colord) >= %{colord_version} +BuildRequires: pkgconfig(fontconfig) +BuildRequires: pkgconfig(gcr-base-3) +BuildRequires: pkgconfig(geoclue-2.0) >= %{geoclue_version} +BuildRequires: pkgconfig(geocode-glib-1.0) >= %{geocode_glib_version} +BuildRequires: pkgconfig(glib-2.0) >= %{glib2_version} +BuildRequires: pkgconfig(gnome-desktop-3.0) >= %{gnome_desktop_version} +BuildRequires: pkgconfig(gsettings-desktop-schemas) >= %{gsettings_desktop_schemas_version} +BuildRequires: pkgconfig(gtk+-3.0) >= %{gtk3_version} +BuildRequires: pkgconfig(gudev-1.0) +BuildRequires: pkgconfig(gweather-3.0) >= %{libgweather_version} +BuildRequires: pkgconfig(json-glib-1.0) +BuildRequires: pkgconfig(lcms2) >= 2.2 +BuildRequires: pkgconfig(libcanberra-gtk3) +BuildRequires: pkgconfig(libgeoclue-2.0) +BuildRequires: pkgconfig(libnm) +BuildRequires: pkgconfig(libnotify) +BuildRequires: pkgconfig(libpulse) +BuildRequires: pkgconfig(libpulse-mainloop-glib) +BuildRequires: pkgconfig(librsvg-2.0) +BuildRequires: pkgconfig(mm-glib) +BuildRequires: pkgconfig(nss) +BuildRequires: pkgconfig(polkit-gobject-1) +BuildRequires: pkgconfig(upower-glib) +BuildRequires: pkgconfig(x11) +BuildRequires: pkgconfig(xi) +BuildRequires: pkgconfig(wayland-client) +%ifnarch s390 s390x +BuildRequires: pkgconfig(libwacom) >= 0.7 +BuildRequires: pkgconfig(xorg-wacom) +%endif + +Requires: colord >= %{colord_version} +Requires: iio-sensor-proxy +Requires: geoclue2 >= %{geoclue_version} +Requires: geocode-glib%{?_isa} >= %{geocode_glib_version} +Requires: glib2%{?_isa} >= %{glib2_version} +Requires: gnome-desktop3%{?_isa} >= %{gnome_desktop_version} +Requires: gsettings-desktop-schemas%{?_isa} >= %{gsettings_desktop_schemas_version} +Requires: gtk3%{?_isa} >= %{gtk3_version} +Requires: libgweather%{?_isa} >= %{libgweather_version} + +Patch00001: 0001-power-Enable-power-saver-profile-when-low-on-battery.patch +Patch00002: subscription-manager-support.patch +Patch00003: im-module-setting-fix.patch +Patch00004: print-notifications-clear-in-stop.patch +Patch00005: 0001-power-Respect-the-nothing-power-button-action-for-VM.patch +Patch00006: 0001-Make-power-button-action-always-power-off-when-chass.patch + +%description +A daemon to share settings from GNOME to other applications. It also +handles global keybindings, as well as a number of desktop-wide settings. + +%package devel +Summary: Development files for %{name} +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description devel +The %{name}-devel package contains libraries and header files for +developing applications that use %{name}. + +%prep +%autosetup -p1 -n %{name}-%{tarball_version} + +%build +%meson +%meson_build + +%install +%meson_install + +cp %{SOURCE1} $RPM_BUILD_ROOT%{_datadir}/glib-2.0/schemas + +%find_lang %{name} --with-gnome + +%files -f %{name}.lang +%license COPYING +%doc AUTHORS NEWS + +# list daemons explicitly, so we notice if one goes missing +# some of these don't have a separate gschema +%{_libexecdir}/gsd-datetime +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.Datetime.desktop + +%{_libexecdir}/gsd-housekeeping +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.Housekeeping.desktop +%{_datadir}/glib-2.0/schemas/org.gnome.settings-daemon.plugins.housekeeping.gschema.xml + +%{_libexecdir}/gsd-keyboard +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.Keyboard.desktop + +%{_libexecdir}/gsd-media-keys +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.MediaKeys.desktop +%{_datadir}/glib-2.0/schemas/org.gnome.settings-daemon.plugins.media-keys.gschema.xml + +%{_libexecdir}/gsd-backlight-helper +%{_datadir}/polkit-1/actions/org.gnome.settings-daemon.plugins.power.policy +%{_libexecdir}/gsd-power +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.Power.desktop +%{_datadir}/glib-2.0/schemas/org.gnome.settings-daemon.plugins.power.gschema.xml +%{_datadir}/glib-2.0/schemas/org.gnome.settings-daemon.plugins.power.gschema.override + +%{_libexecdir}/gsd-print-notifications +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.PrintNotifications.desktop +%{_libexecdir}/gsd-printer + +%{_libexecdir}/gsd-rfkill +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.Rfkill.desktop + +%{_libexecdir}/gsd-screensaver-proxy +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.ScreensaverProxy.desktop + +%{_libexecdir}/gsd-smartcard +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.Smartcard.desktop + +%{_libexecdir}/gsd-sound +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.Sound.desktop + +%{_libexecdir}/gsd-usb-protection +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.UsbProtection.desktop + +%{_datadir}/glib-2.0/schemas/org.gnome.settings-daemon.peripherals.gschema.xml +%{_datadir}/glib-2.0/schemas/org.gnome.settings-daemon.peripherals.wacom.gschema.xml +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.Wacom.desktop + +%ifnarch s390 s390x +%{_libexecdir}/gsd-wacom +%{_libexecdir}/gsd-wacom-oled-helper +%{_datadir}/polkit-1/actions/org.gnome.settings-daemon.plugins.wacom.policy +%endif + +%{_libexecdir}/gsd-xsettings +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.XSettings.desktop +%{_datadir}/glib-2.0/schemas/org.gnome.settings-daemon.plugins.xsettings.gschema.xml + +%{_libexecdir}/gsd-a11y-settings +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.A11ySettings.desktop + +%{_libexecdir}/gsd-color +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.Color.desktop +%{_datadir}/glib-2.0/schemas/org.gnome.settings-daemon.plugins.color.gschema.xml + +%{_libexecdir}/gsd-sharing +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.Sharing.desktop +%{_datadir}/glib-2.0/schemas/org.gnome.settings-daemon.plugins.sharing.gschema.xml + +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.Wwan.desktop +%{_libexecdir}/gsd-wwan +%{_datadir}/glib-2.0/schemas/org.gnome.settings-daemon.plugins.wwan.gschema.xml + +%{_sysconfdir}/xdg/autostart/org.gnome.SettingsDaemon.Subscription.desktop +%{_libexecdir}/gsd-subman +%{_libexecdir}/gsd-subman-helper +%{_datadir}/polkit-1/actions/org.gnome.settings-daemon.plugins.subman.policy +%{_datadir}/polkit-1/rules.d/org.gnome.settings-daemon.plugins.subman.rules + +%dir %{_libdir}/gnome-settings-daemon-40 +%{_libdir}/gnome-settings-daemon-40/libgsd.so + +%{_sysconfdir}/xdg/Xwayland-session.d/00-xrdb +%{_userunitdir}/* +/usr/lib/udev/rules.d/*.rules +%{_datadir}/gnome-settings-daemon/ +%{_datadir}/GConf/gsettings/gnome-settings-daemon.convert + +%{_datadir}/glib-2.0/schemas/org.gnome.settings-daemon.enums.xml +%{_datadir}/glib-2.0/schemas/org.gnome.settings-daemon.plugins.gschema.xml + +%files devel +%{_includedir}/gnome-settings-daemon-40 +%{_libdir}/pkgconfig/gnome-settings-daemon.pc + +%changelog +* Fri Apr 14 2023 MSVSphere Packaging Team - 40.0.1-10 +- Rebuilt for MSVSphere 9.2 beta + +* Wed Feb 22 2023 Felipe Borges - 40.0.1-10 +- Default power-button-action to poweroff on servers + (except when power-button-action=nothing) + Resolves: #1885639 + +* Mon Feb 20 2023 Marek Kasik - 40.0.1-9 +- Clear members of GsdPrintNotificationsManager in stop() + Resolves: #2166842 + +* Mon Aug 01 2022 Felipe Borges - 40.0.1-8 +- Fix registration with activation key + Resolves: #2100467 + +* Wed Jul 13 2022 Carlos Garnacho - 40.0.1-7 +- Manage im-context Xsetting dynamically + Resolves: #2087031 + +* Mon Feb 14 2022 Ray Strode - 40.0.1-6 +- Update for non-deprecated subscription management API + Resolves: #2049734 + +* Wed Sep 08 2021 Kalev Lember - 40.0.1-5 +- Fix the icon shown for subscription manager notifications +- Related: #1937113 + +* Thu Sep 02 2021 Kalev Lember - 40.0.1-4 +- Forward port subscription manager support from RHEL 8 +- Resolves: #1937113 + +* Thu Aug 19 2021 Carlos Garnacho - 40.0.1-3 +- Backport power saving changes + Resolves: #1994476 + +* Mon Aug 09 2021 Mohan Boddu - 40.0.1-2 +- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags + Related: rhbz#1991688 + +* Fri May 07 2021 Kalev Lember - 40.0.1-1 +- Update to 40.0.1 + +* Thu Apr 15 2021 Mohan Boddu - 40.0-2 +- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937 + +* Mon Mar 22 2021 Kalev Lember - 40.0-1 +- Update to 40.0 +- Drop old obsoletes/conflicts + +* Mon Mar 15 2021 Kalev Lember - 40~rc-1 +- Update to 40.rc + +* Mon Feb 15 2021 Kalev Lember - 40~beta-2 +- Fix loading gtk modules +- Update versioned dependencies + +* Mon Feb 15 2021 Florian Müllner - 40~beta-1 +- Update to 40.beta + +* Mon Feb 15 2021 Florian Müllner - 40~alpha.1-1 +- Update to 40.alpha.1 + +* Tue Jan 26 2021 Fedora Release Engineering - 3.38.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Fri Oct 9 2020 Kalev Lember - 3.38.1-1 +- Update to 3.38.1 + +* Mon Sep 14 2020 Kalev Lember - 3.38.0-1 +- Update to 3.38.0 + +* Mon Sep 07 2020 Kalev Lember - 3.37.92-1 +- Update to 3.37.92 + +* Sat Aug 29 2020 Kalev Lember - 3.37.1-1 +- Update to 3.37.1 + +* Mon Aug 17 2020 Kalev Lember - 3.37.0-1 +- Update to 3.37.0 + +* Sat Aug 01 2020 Fedora Release Engineering - 3.36.1-3 +- Second attempt - Rebuilt for + https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Mon Jul 27 2020 Fedora Release Engineering - 3.36.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Thu Apr 30 2020 Kalev Lember - 3.36.1-1 +- Update to 3.36.1 + +* Mon Mar 09 2020 Kalev Lember - 3.36.0-1 +- Update to 3.36.0 + +* Mon Mar 02 2020 Kalev Lember - 3.35.92-1 +- Update to 3.35.92 + +* Tue Feb 18 2020 Kalev Lember - 3.35.91-1 +- Update to 3.35.91 + +* Tue Jan 28 2020 Fedora Release Engineering - 3.35.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Thu Jan 16 2020 Kalev Lember - 3.35.0-2 +- Rebuilt for libgnome-desktop soname bump + +* Tue Jan 07 2020 Kalev Lember - 3.35.0-1 +- Update to 3.35.0 + +* Mon Oct 14 2019 Kalev Lember - 3.34.1-1 +- Update to 3.34.1 + +* Mon Sep 09 2019 Kalev Lember - 3.34.0-1 +- Update to 3.34.0 + +* Fri Sep 06 2019 Kalev Lember - 3.33.92-1 +- Update to 3.33.92 + +* Mon Aug 26 2019 Kalev Lember - 3.33.90-1 +- Update to 3.33.90 +- Drop old versioned conflicts + +* Thu Jul 25 2019 Fedora Release Engineering - 3.33.0-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Sun Jul 21 2019 Kalev Lember - 3.33.0-3 +- Rebuilt for libgnome-desktop soname bump + +* Mon Jul 08 2019 Kalev Lember - 3.33.0-2 +- Rebuilt for libgweather soname bump + +* Tue Jun 25 2019 Kalev Lember - 3.33.0-1 +- Update to 3.33.0 + +* Wed Jun 19 2019 Kalev Lember - 3.32.1-1 +- Update to 3.32.1 + +* Tue May 28 2019 Marek Kasik - 3.32.0-2 +- Fix NSS crash at smartcard plugin (#1688791) + +* Mon Mar 11 2019 Kalev Lember - 3.32.0-1 +- Update to 3.32.0 + +* Wed Mar 06 2019 Kalev Lember - 3.31.92-1 +- Update to 3.31.92 + +* Wed Feb 20 2019 Kalev Lember - 3.31.91-1 +- Update to 3.31.91 + +* Wed Feb 06 2019 Kalev Lember - 3.31.90-1 +- Update to 3.31.90 + +* Thu Jan 31 2019 Fedora Release Engineering - 3.31.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Wed Jan 09 2019 Kalev Lember - 3.31.2-1 +- Update to 3.31.2 + +* Tue Nov 20 2018 Pete Walter - 3.30.1.2-3 +- Move gnome-remote-desktop recommends to gnome-control-center + +* Fri Nov 09 2018 Ray Strode - 3.30.1.2-2 +- Add recommends for gnome-remote-desktop after irc discussion + +* Thu Oct 04 2018 Kalev Lember - 3.30.1.2-1 +- Update to 3.30.1.2 + +* Fri Sep 28 2018 Kalev Lember - 3.30.1.1-1 +- Update to 3.30.1.1 + +* Thu Sep 06 2018 Kalev Lember - 3.30.0-1 +- Update to 3.30.0 + +* Sun Aug 12 2018 Kalev Lember - 3.29.90.1-1 +- Update to 3.29.90.1 + +* Tue Jul 31 2018 Florian Weimer - 3.28.1-3 +- Rebuild with fixed binutils + +* Fri Jul 13 2018 Fedora Release Engineering - 3.28.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Thu Apr 12 2018 Kalev Lember - 3.28.1-1 +- Update to 3.28.1 + +* Tue Apr 10 2018 Michael Catanzaro - 3.28.0-2 +- Disable automatic suspend, except when on battery power + +* Mon Mar 12 2018 Kalev Lember - 3.28.0-1 +- Update to 3.28.0 + +* Mon Mar 05 2018 Kalev Lember - 3.27.92-1 +- Update to 3.27.92 + +* Fri Mar 02 2018 Kalev Lember - 3.27.91-1 +- Update to 3.27.91 + +* Sat Feb 10 2018 Bastien Nocera - 3.27.90-4 ++ gnome-settings-daemon-3.27.90-4 +- Rebuild against newer gnome-desktop3 package + +* Fri Feb 09 2018 Bastien Nocera - 3.27.90-3 ++ gnome-settings-daemon-3.27.90-3 +- Really fix gsd-* helper linkage +- Build fix for highly parallel builds + +* Wed Feb 07 2018 Kalev Lember - 3.27.90-2 +- Fix missing libcommon.so library + +* Tue Feb 06 2018 Kalev Lember - 3.27.90-1 +- Update to 3.27.90 +- Switch to meson build system + +* Mon Feb 05 2018 Kalev Lember - 3.26.2-5 +- Rebuilt for libgweather soname bump + +* Sat Jan 20 2018 Björn Esser - 3.26.2-4 +- Rebuilt for switch to libxcrypt + +* Fri Jan 12 2018 Bastien Nocera - 3.26.2-3 +- Fix gdm session trying to change the backlight, resulting in a lot + of spurious error messages (#1322588) + +* Fri Jan 05 2018 Igor Gnatenko - 3.26.2-2 +- Remove obsolete scriptlets + +* Thu Nov 02 2017 Kalev Lember - 3.26.2-1 +- Update to 3.26.2 + +* Sun Oct 08 2017 Kalev Lember - 3.26.1-1 +- Update to 3.26.1 + +* Wed Sep 13 2017 Kalev Lember - 3.26.0-1 +- Update to 3.26.0 + +* Tue Sep 05 2017 Kalev Lember - 3.25.92-1 +- Update to 3.25.92 + +* Thu Aug 24 2017 Kalev Lember - 3.25.91-1 +- Update to 3.25.91 + +* Tue Aug 15 2017 Kalev Lember - 3.25.90-1 +- Update to 3.25.90 + +* Mon Jul 31 2017 Kalev Lember - 3.25.4-2 +- Add explicit conflicts to not break older gdm, gnome-session and gnome-shell + +* Mon Jul 31 2017 Kalev Lember - 3.25.4-1 +- Update to 3.25.4 + +* Wed Jul 26 2017 Fedora Release Engineering - 3.25.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Mon Jun 12 2017 Kalev Lember - 3.25.2-1 +- Update to 3.25.2 + +* Wed May 10 2017 Kalev Lember - 3.24.2-1 +- Update to 3.24.2 + +* Wed Apr 12 2017 Kalev Lember - 3.24.1-1 +- Update to 3.24.1 + +* Tue Mar 21 2017 Kalev Lember - 3.24.0-1 +- Update to 3.24.0 + +* Thu Mar 16 2017 Kalev Lember - 3.23.92-1 +- Update to 3.23.92 + +* Wed Feb 15 2017 Richard Hughes - 3.23.90-1 +- Update to 3.23.90 + +* Fri Feb 10 2017 Fedora Release Engineering - 3.23.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Thu Jan 12 2017 Bastien Nocera - 3.23.3-1 ++ gnome-settings-daemon-3.23.3-1 +- Update to 3.23.3 + +* Tue Oct 11 2016 Bastien Nocera - 3.23.2-1 ++ gnome-settings-daemon-3.23.2-1 +- Update to 3.23.2 + +* Thu Sep 22 2016 Kalev Lember - 3.22.0-1 +- Update to 3.22.0 + +* Wed Sep 14 2016 Kalev Lember - 3.21.92.1-1 +- Update to 3.21.92.1 + +* Wed Sep 14 2016 Kalev Lember - 3.21.92-1 +- Update to 3.21.92 +- Don't set group tags + +* Fri Aug 26 2016 Kalev Lember - 3.21.90-1 +- Update to 3.21.90 + +* Sun Apr 17 2016 Bastien Nocera - 3.20.1-3 +- Fix crasher in newly enabled audio device selection dialogue + +* Sun Apr 17 2016 Bastien Nocera - 3.20.1-2 +- Require alsa to enable the audio device selection dialogue + +* Wed Apr 13 2016 Kalev Lember - 3.20.1-1 +- Update to 3.20.1 + +* Tue Mar 22 2016 Kalev Lember - 3.20.0-1 +- Update to 3.20.0 + +* Thu Mar 17 2016 Kalev Lember - 3.19.92-1 +- Update to 3.19.92 + +* Fri Mar 04 2016 Kalev Lember - 3.19.91-1 +- Update to 3.19.91 + +* Wed Feb 17 2016 Richard Hughes - 3.19.90-1 +- Update to 3.19.90 + +* Wed Feb 03 2016 Fedora Release Engineering - 3.19.5-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Wed Jan 20 2016 Kalev Lember - 3.19.5-1 +- Update to 3.19.5 + +* Thu Dec 17 2015 Kalev Lember - 3.19.4-1 +- Update to 3.19.4 + +* Tue Dec 15 2015 Kalev Lember - 3.19.3-1 +- Update to 3.19.3 + +* Tue Nov 10 2015 Kalev Lember - 3.18.2-1 +- Update to 3.18.2 + +* Mon Oct 12 2015 Kalev Lember - 3.18.1-1 +- Update to 3.18.1 + +* Mon Sep 21 2015 Kalev Lember - 3.18.0-1 +- Update to 3.18.0 + +* Mon Sep 14 2015 Kalev Lember - 3.17.92-1 +- Update to 3.17.92 + +* Mon Aug 17 2015 Kalev Lember - 3.17.90-1 +- Update to 3.17.90 +- Use make_install macro + +* Wed Jul 22 2015 David King - 3.17.3-1 +- Update to 3.17.3 +- Use pkgconfig for BuildRequires + +* Wed Jun 17 2015 Fedora Release Engineering - 3.17.2-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Thu Jun 11 2015 Richard Hughes - 3.17.2-2 +- Add runtime dep on iio-sensor-proxy for the ambient light sensor + +* Fri Jun 05 2015 Kalev Lember - 3.17.2-1 +- Update to 3.17.2 + +* Tue May 12 2015 Kalev Lember - 3.16.2-1 +- Update to 3.16.2 + +* Tue Apr 14 2015 Kalev Lember - 3.16.1-1 +- Update to 3.16.1 + +* Mon Mar 23 2015 Kalev Lember - 3.16.0-1 +- Update to 3.16.0 + +* Tue Mar 17 2015 Kalev Lember - 3.15.92-1 +- Update to 3.15.92 + +* Tue Mar 03 2015 Kalev Lember - 3.15.91-1 +- Update to 3.15.91 +- Use the %%license macro for the COPYING file + +* Tue Feb 17 2015 Richard Hughes - 3.15.90-1 +- Update to 3.15.90 + +* Thu Jan 22 2015 Richard Hughes - 3.15.4-1 +- Update to 3.15.4 + +* Thu Nov 27 2014 Kalev Lember - 3.15.1-1 +- Update to 3.15.1 + +* Tue Nov 11 2014 Kalev Lember - 3.14.2-1 +- Update to 3.14.2 + +* Sat Nov 01 2014 Richard Hughes - 3.14.1-3 +- Fix compile on RHEL + +* Sun Oct 26 2014 Kalev Lember - 3.14.1-2 +- Obsolete drwright + +* Tue Oct 14 2014 Rui Matos - 3.14.1-1 +- Update to 3.14.1 + +* Mon Sep 22 2014 Kalev Lember - 3.14.0-1 +- Update to 3.14.0 + +* Tue Sep 16 2014 Kalev Lember - 3.13.92-1 +- Update to 3.13.92 + +* Wed Sep 03 2014 Kalev Lember - 3.13.91-1 +- Update to 3.13.91 + +* Mon Aug 18 2014 Kalev Lember - 3.13.90-1 +- Update to 3.13.90 + +* Sat Aug 16 2014 Fedora Release Engineering - 3.13.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Wed Jul 23 2014 Kalev Lember - 3.13.4-1 +- Update to 3.13.4 + +* Thu Jun 26 2014 Richard Hughes - 3.13.3-1 +- Update to 3.13.3 + +* Wed Jun 25 2014 Richard Hughes - 3.13.2-1 +- Update to 3.13.2 + +* Sat Jun 07 2014 Fedora Release Engineering - 3.13.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Thu May 01 2014 Kalev Lember - 3.13.1-1 +- Update to 3.13.1 +- Remove and obsolete the updates plugin + +* Wed Apr 16 2014 Kalev Lember - 3.12.1-1 +- Update to 3.12.1 +- Tighten subpackage deps + +* Mon Apr 14 2014 Kalev Lember - 3.12.0.1-3 +- Drop control-center-filesystem dependency + +* Sat Apr 05 2014 Kalev Lember - 3.12.0.1-2 +- Update dep versions + +* Wed Mar 26 2014 Richard Hughes - 3.12.0.1-1 +- Update to 3.12.0.1 + +* Mon Mar 24 2014 Richard Hughes - 3.12.0-1 +- Update to 3.12.0 + +* Tue Mar 18 2014 Richard Hughes - 3.11.92-1 +- Update to 3.11.92 + +* Tue Mar 04 2014 Richard Hughes - 3.11.91-1 +- Update to 3.11.91 + +* Wed Feb 19 2014 Richard Hughes - 3.11.90-2 +- Rebuilt for gnome-desktop soname bump + +* Tue Feb 18 2014 Richard Hughes - 3.11.90-1 +- Update to 3.11.90 + +* Tue Feb 04 2014 Richard Hughes - 3.11.5-1 +- Update to 3.11.5 + +* Thu Jan 30 2014 Richard Hughes - 3.11.3-2 +- Rebuild for libpackagekit-glib soname bump + +* Tue Dec 17 2013 Richard Hughes - 3.11.3-1 +- Update to 3.11.3 + +* Mon Nov 25 2013 Richard Hughes - 3.11.2-1 +- Update to 3.11.2 + +* Thu Oct 31 2013 Florian Müllner - 3.11.1-1 +- Update to 3.11.1 + +* Mon Oct 28 2013 Richard Hughes - 3.10.1-1 +- Update to 3.10.1 + +* Fri Oct 11 2013 Richard Hughes - 3.10.0-3 +- Apply the previous patch on Fedora too. + +* Fri Oct 11 2013 Richard Hughes - 3.10.0-2 +- Grab a patch from upstream to fix the multiple notifications about updates. +- Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1009132 + +* Tue Sep 24 2013 Kalev Lember - 3.10.0-1 +- Update to 3.10.0 + +* Wed Sep 18 2013 Kalev Lember - 3.9.92-1 +- Update to 3.9.92 + +* Tue Sep 17 2013 Richard Hughes - 3.9.91.1-2 +- Grab a patch from upstream so that the offline updates feature can + actually work when reboot returns with success. + +* Tue Sep 03 2013 Matthias Clasen - 3.9.91.1-1 +- Update to 3.9.91.1 + +* Tue Sep 03 2013 Kalev Lember - 3.9.91-1 +- Update to 3.9.91 +- Include the new datetime plugin + +* Fri Aug 23 2013 Kalev Lember - 3.9.90-2 +- Keep middle click paste enabled for now + +* Thu Aug 22 2013 Kalev Lember - 3.9.90-1 +- Update to 3.9.90 + +* Fri Aug 09 2013 Kalev Lember - 3.9.5-1 +- Update to 3.9.5 +- Remove empty /etc/gnome-settings-daemon directory +- Install new rfkill plugin and add back the smartcard plugin + +* Tue Jul 30 2013 Richard Hughes - 3.9.3-3 +- Rebuild for colord soname bump + +* Mon Jul 22 2013 Bastien Nocera 3.9.3-2 +- Remove obsolete GStreamer 0.10 BRs + +* Thu Jun 20 2013 Kalev Lember - 3.9.3-1 +- Update to 3.9.3 + +* Sun Jun 02 2013 Kalev Lember - 3.9.2-1 +- Update to 3.9.2 +- Drop the ibus-kkc-libpinyin patch; the hardcoded input sources + list is gone from g-s-d +- Set the minimum required gnome-desktop3 version + +* Tue May 14 2013 Richard Hughes - 3.8.2-1 +- Update to 3.8.2 + +* Thu May 9 2013 Jens Petersen - 3.8.1-2 +- default ibus engine in Fedora is now kkc for Japanese + and libpinyin for Chinese (#948117) + +* Tue Apr 16 2013 Richard Hughes - 3.8.1-1 +- Update to 3.8.1 + +* Tue Mar 26 2013 Richard Hughes - 3.8.0-1 +- Update to 3.8.0 + +* Tue Mar 19 2013 Matthias Clasen - 3.7.92-1 +- Update to 3.7.92 + +* Tue Mar 5 2013 Matthias Clasen - 3.7.91-1 +- Update to 3.7.91 + +* Wed Feb 20 2013 Richard Hughes - 3.7.90-1 +- Update to 3.7.90 + +* Thu Feb 07 2013 Richard Hughes - 3.7.5.1-1 +- Update to 3.7.5.1 + +* Wed Feb 06 2013 Debarshi Ray - 3.7.5-2 +- Bump the gtk3 BuildRequires + +* Tue Feb 05 2013 Richard Hughes - 3.7.5-1 +- Update to 3.7.5 + +* Wed Jan 16 2013 Richard Hughes - 3.7.4-1 +- Update to 3.7.4 + +* Mon Dec 31 2012 Dan Horák - 3.7.3-2 +- fix filelist for s390(x) (and ppc/ppc64 in RHEL) + +* Thu Dec 20 2012 Kalev Lember - 3.7.3-1 +- Update to 3.7.3 +- Adjust the spec file for the (temporarly) disabled smartcard plugin + +* Tue Nov 20 2012 Richard Hughes - 3.7.1-1 +- Update to 3.7.1 +- Remove upstreamed patches + +* Wed Nov 14 2012 Kalev Lember - 3.6.3-1 +- Update to 3.6.3 +- Drop the static man page patch and BR docbook-style-xsl instead + +* Thu Nov 08 2012 Bastien Nocera 3.6.2-1 +- Update to 3.6.2 + +* Thu Oct 18 2012 Matthias Clasen - 3.6.1-3 +- Fix a typo in the suspend patch (#858259) + +* Mon Oct 08 2012 Dan Horák - 3.6.1-2 +- fix build on s390(x) + +* Mon Oct 08 2012 Bastien Nocera 3.6.1-1 +- Update to 3.6.1 + +* Fri Oct 5 2012 Olivier Fourdan - 3.6.0-5 +- Adds Wacom OSD window from upstream bug #679062 + +* Wed Oct 3 2012 Matthias Clasen - 3.6.0-4 +- Fix an inhibitor leak in the previous patch + +* Tue Oct 2 2012 Matthias Clasen - 3.6.0-3 +- Fix lid close handling with new systemd + +* Fri Sep 28 2012 Peter Robinson - 3.6.0-2 +- Split out PackageKit into a sub package. Fixes #699348 + +* Tue Sep 25 2012 Richard Hughes - 3.6.0-1 +- Update to 3.6.0 + +* Wed Sep 19 2012 Richard Hughes - 3.5.92-1 +- Update to 3.5.92 + +* Wed Sep 05 2012 Cosimo Cecchi - 3.5.91-1 +- Update to 3.5.91 + +* Wed Aug 22 2012 Richard Hughes - 3.5.90-1 +- Update to 3.5.90 + +* Tue Aug 21 2012 Richard Hughes - 3.5.6-1 +- Update to 3.5.6 + +* Fri Jul 27 2012 Fedora Release Engineering - 3.5.5-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Tue Jul 24 2012 Dan Horák - 3.5.5-3 +- fix build without wacom + +* Thu Jul 19 2012 Matthias Clasen - 3.5.5-2 +- Fix the updates plugin to load + +* Thu Jul 19 2012 Matthias Clasen - 3.5.5-1 +- Update to 3.5.5 + +* Tue Jul 17 2012 Dan Horák - 3.5.4-3 +- fix build on s390(x) - cherry-picked from f17 branch +- allow build without wacom on ppc/ppc64 + +* Tue Jul 17 2012 Matthias Clasen - 3.5.4-2 +- Rebuild against new PackageKit + +* Wed Jun 27 2012 Richard Hughes - 3.5.4-1 +- Update to 3.5.4 + +* Tue Jun 26 2012 Richard Hughes - 3.5.3-1 +- Update to 3.5.3 + +* Thu Jun 14 2012 Matthias Clasen - 3.5.2-4 +- Drop calculator patch, no longer needed + +* Thu Jun 07 2012 Matthias Clasen - 3.5.2-3 +- Fix file lists + +* Thu Jun 07 2012 Richard Hughes - 3.5.2-2 +- Add missing BR + +* Wed Jun 06 2012 Richard Hughes - 3.5.2-1 +- Update to 3.5.2 + +* Fri May 18 2012 Richard Hughes - 3.4.2-1 +- Update to 3.4.2 + +* Mon Apr 16 2012 Richard Hughes - 3.4.1-1 +- Update to 3.4.1 + +* Mon Mar 26 2012 Richard Hughes - 3.4.0-1 +- New upstream version. + +* Tue Mar 20 2012 Richard Hughes 3.3.92-1 +- Update to 3.3.92 + +* Mon Mar 05 2012 Bastien Nocera 3.3.91-1 +- Update to 3.3.91 + +* Wed Feb 22 2012 Bastien Nocera 3.3.90.1-1 +- Update to 3.3.90.1 + +* Thu Feb 9 2012 Matthias Clasen 3.3.5-2 +- Use systemd for session tracking + +* Tue Feb 7 2012 Matthias Clasen 3.3.5-1 +- Update to 3.3.5 + +* Fri Jan 20 2012 Matthias Clasen 3.3.4-2 +- Some crash fixes + +* Tue Jan 17 2012 Bastien Nocera 3.3.4-1 +- Update to 3.3.4 + +* Fri Jan 13 2012 Fedora Release Engineering - 3.3.3.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Tue Dec 27 2011 Matthias Clasen - 3.3.3.1-2 +- Fix a path problem in the gnome-settings-daemon autostart file + +* Fri Dec 23 2011 Matthias Clasen - 3.3.3.1-1 +- Update to 3.3.3.1 + +* Wed Dec 21 2011 Matthias Clasen - 3.3.3-1 +- Update to 3.3.3 + +* Wed Nov 23 2011 Matthias Clasen - 3.3.2-1 +- Update to 3.3.2 + +* Fri Nov 11 2011 Bastien Nocera 3.2.2-1 +- Update to 3.2.2 + +* Wed Oct 26 2011 Fedora Release Engineering - 3.2.1-4 +- Rebuilt for glibc bug#747377 + +* Tue Oct 25 2011 Marek Kasik - 3.2.1-3 +- Fix a typo in registration of an object on DBus (#747318) + +* Mon Oct 24 2011 Matthias Clasen - 3.2.1-2 +- Fix calculator keybinding (#745367) + +* Mon Oct 17 2011 Bastien Nocera 3.2.1-1 +- Update to 3.2.1 + +* Wed Oct 12 2011 Adam Williamson - 3.2.0-2 +- backport some greatest hits from git to stop the same bugs being + reported over and over (all will be in 3.2.1) + +* Tue Sep 27 2011 Ray - 3.2.0-1 +- Update to 3.2.0 + +* Tue Sep 20 2011 Matthias Clasen - 3.1.92-1 +- Update to 3.1.92 + +* Tue Sep 6 2011 Matthias Clasen - 3.1.91-1 +- Update to 3.1.91 + +* Tue Jul 26 2011 Cosimo Cecchi - 3.1.4-2 +- Add a patch to make the fallback mounter to build correctly +- Include the new power plugin + +* Mon Jul 25 2011 Matthias Clasen - 3.1.4-1 +- Update to 3.1.4 + +* Fri Jul 22 2011 Tomas Bzatek - 3.1.3-2 +- Add support for chrony (#723212) + +* Mon Jul 04 2011 Bastien Nocera 3.1.3-1 +- Update to 3.1.3 + +* Tue Jun 21 2011 Tomas Bzatek - 3.1.2-2 +- Fix fortify fail in gsd-color-manager.c (#714625) + +* Wed Jun 15 2011 Tomas Bzatek - 3.1.2-1 +- Update to 3.1.2 + +* Wed Jun 15 2011 Bastien Nocera 3.1.1-3 +- Rebuild for new gnome-desktop3 libs + +* Mon Jun 13 2011 Marek Kasik 3.1.1-2 +- Remove requirement of system-config-printer-udev (#704381) + +* Wed May 11 2011 Tomas Bzatek - 3.1.1-1 +- Update to 3.1.1 + +* Sat May 07 2011 Christopher Aillon - 3.0.1-5 +- Update gsettings schema scriptlet + +* Mon May 2 2011 Matthias Clasen 3.0.1-4 +- Try to fix a crash (#698533) + +* Thu Apr 28 2011 Bastien Nocera 3.0.1-2 +- Fix setting ntpd usage with SystemD + +* Tue Apr 26 2011 Bastien Nocera 3.0.1-1 +- Update to 3.0.1 + +* Wed Apr 06 2011 Bastien Nocera 3.0.0.1-1 +- Update to 3.0.0.1 + +* Mon Apr 04 2011 Bastien Nocera 3.0.0-1 +- Update to 3.0.0 + +* Wed Mar 30 2011 Marek Kasik 2.91.93-2 +- Make CUPS' subscriptions expirable + +* Fri Mar 25 2011 Bastien Nocera 2.91.93-1 +- Update to 2.91.93 + +* Mon Mar 21 2011 Matthias Clasen 2.91.92-1 +- Update 2.91.92 + +* Wed Mar 16 2011 Richard Hughes 2.91.91-3 +- Add a patch from upstream to fix the updates plugin. + +* Fri Mar 11 2011 Bastien Nocera 2.91.91-2 +- Add libXxf86misc-devel requires so that key repeat/delay works + +* Tue Mar 08 2011 Bastien Nocera 2.91.91-1 +- Update to 2.91.91 + +* Fri Feb 25 2011 Matthias Clasen - 2.91.90-4 +- Fix undefined symbols in the updates plugin + +* Wed Feb 23 2011 Matthias Clasen - 2.91.90-3 +- BR PackageKit and cups +- Explicitly list plugins so we notice if they go missing + +* Wed Feb 23 2011 Cosimo Cecchi - 2.91.90-2 +- Include an upstream patch to fix a possible crasher + +* Tue Feb 22 2011 Matthias Clasen 2.91.90-1 +- Update to 2.91.90 + +* Wed Feb 16 2011 Bastien Nocera 2.91.9-6 +- Fix crasher when media keys GSettings value changes + +* Sun Feb 13 2011 Christopher Aillon - 2.91.9-5 +- Rebuild for new libxklavier + +* Fri Feb 11 2011 Matthias Clasen 2.91.9-4 +- Rebuild against newer gtk + +* Tue Feb 08 2011 Fedora Release Engineering - 2.91.9-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Tue Feb 08 2011 Bastien Nocera 2.91.9-2 +- Fix setting timezones in the date & time panel (#674999) + +* Wed Feb 2 2011 Matthias Clasen 2.91.9-1 +- 2.91.9 + +* Tue Jan 11 2011 Matthias Clasen 2.91.8-1 +- 2.91.8 + +* Tue Jan 11 2011 Matthias Clasen 2.91.7-2 +- Own %%{_libdir}/gnome-settings-daemon-3.0/gtk-modules + +* Mon Jan 10 2011 Matthias Clasen 2.91.7-1 +- Update to 2.91.7 + +* Sat Jan 8 2011 Matthias Clasen 2.91.6.2-1 +- Update to 2.91.6.2 + +* Fri Dec 3 2010 Matthias Clasen 2.91.5.1-1 +- Update to 2.91.5.1 + +* Thu Dec 2 2010 Dan Williams - 2.91.5-4 +- Re-add patch handling org.gnome.media-handling gsettings schema rename + +* Wed Dec 1 2010 Dan Williams - 2.91.5-3 +- Fix various cases of forgetting to draw the background + +* Tue Nov 30 2010 Owen Taylor - 2.91.5-2 +- Add a patch handling org.gnome.media-handling gsettings schema rename + +* Tue Nov 30 2010 Tomas Bzatek 2.91.5-1 +- Update to 2.91.5 + +* Fri Nov 26 2010 Bastien Nocera 2.91.4-2 +- Fix crasher on startup + +* Thu Nov 25 2010 Bastien Nocera 2.91.4-1 +- Update to 2.91.4 + +* Wed Nov 17 2010 Richard Hughes 2.91.3-1 +- Update to 2.91.3 + +* Wed Nov 10 2010 Bastien Nocera 2.91.2.1-0.4. +- Update to 2.91.2.1 + +* Wed Nov 3 2010 Matthias Clasen 2.91.2-0.4.20101102 +- Rebuild against new libnotify + +* Tue Nov 2 2010 Matthias Clasen 2.91.2-0.3.20101102 +- Make theme changing work + +* Tue Nov 02 2010 Richard Hughes 2.91.2-0.2.20101102 +- Add BR gsettings-desktop-schemas-devel + +* Tue Nov 02 2010 Richard Hughes 2.91.2-0.1.20101102 +- Update to a git snapshot to fix rawhide. + +* Wed Oct 06 2010 Richard Hughes 2.91.0-3 +- Fix the pkgconfig file manually + +* Wed Oct 06 2010 Richard Hughes 2.91.0-2 +- Rebuild against the new libgnomekbd library + +* Mon Oct 4 2010 Matthias Clasen - 2.91.0-1 +- Update to 2.91.0 + +* Wed Sep 29 2010 jkeating - 2.90.1-2 +- Rebuilt for gcc bug 634757 + +* Wed Sep 22 2010 Bastien Nocera 2.90.1-1 +- Update to 2.90.1 + +* Tue Aug 31 2010 Matthias Clasen 2.31.91-1 +- Update to 2.31.91 + +* Fri Aug 27 2010 Matthias Clasen 2.31.6-2 +- Fix a problem with warning bubbles in virtual machines (#624624) + +* Tue Aug 3 2010 Matthias Clasen 2.31.6-1 +- Update to 2.31.6 + +* Tue Jul 13 2010 Matthias Clasen 2.31.5.1-1 +- Update to 2.31.5.1 + +* Mon Jul 12 2010 Matthias Clasen 2.31.5-1 +- Update to 2.31.5 + +* Wed Jun 30 2010 Matthias Clasen 2.31.4.2-1 +- Update to 2.31.4.2 + +* Tue Jun 29 2010 Matthias Clasen 2.31.4.1-1 +- Update to 2.31.4.1 + +* Tue Jun 29 2010 Matthias Clasen 2.31.4-1 +- Update to 2.31.4 + +* Mon Jun 28 2010 Bastien Nocera 2.31.3-3 +- Don't remove the sound plugin if we want the caches to be + updated + +* Tue Jun 8 2010 Matthias Clasen 2.31.3-1 +- Update to 2.31.3 + +* Thu May 27 2010 Matthias Clasen 2.31.2-1 +- Update to 2.31.2 + +* Sun May 16 2010 Matthias Clasen 2.31.1-1 +- Update to 2.31.1 + +* Fri Apr 30 2010 Matthias Clasen 2.30.1-4 +- Waah, one more mistake in these macros + +* Tue Apr 27 2010 Matthias Clasen 2.30.1-3 +- Nobody understands macro processors... + +* Tue Apr 27 2010 Matthias Clasen 2.30.1-2 +- Fix a typo + +* Mon Apr 26 2010 Matthias Clasen 2.30.1-1 +- Update to 2.30.1 +- Spec file cleanups + +* Mon Mar 29 2010 Matthias Clasen 2.30.0-1 +- Update to 2.30.0 + +* Mon Mar 22 2010 Bastien Nocera 2.29.92-3 +- Disable the font plugin by default + +* Wed Mar 10 2010 Bastien Nocera 2.29.92-2 +- Remove unneeded icons, already upstream + +* Tue Mar 09 2010 Bastien Nocera 2.29.92-1 +- Update to 2.29.92 + +* Sat Feb 27 2010 Matthias Clasen 2.29.91.1-2 +- Fix Fn-F8 OSD icon +- Modernize scriptlets + +* Wed Feb 24 2010 Matthias Clasen 2.29.91.1-1 +- Update to 2.29.91.1 + +* Wed Feb 17 2010 Matthias Clasen 2.29.90-2 +- Set a name for the keyboard statusicon + +* Wed Feb 10 2010 Tomas Bzatek 2.29.90-1 +- Update to 2.29.90 + +* Tue Jan 26 2010 Matthias Clasen 2.29.6-1 +- Update to 2.29.6 + +* Fri Dec 18 2009 Matthias Clasen 2.28.1-10 +- Avoid warning messages from the OSD code + +* Tue Dec 15 2009 Matthias Clasen 2.28.1-9 +- Survive when running without XKB (#547780) + +* Thu Nov 12 2009 Matthias Clasen 2.28.1-8 +- Avoid a 'whitespace leak' around the display statusicon (gnome #601696) + +* Mon Nov 9 2009 Matthias Clasen 2.28.1-7 +- React to screen changes when showing the background (gnome #601203) + +* Thu Nov 05 2009 Bastien Nocera 2.28.1-6 +- Fix the volume going over 100% in the OSD + +* Wed Oct 28 2009 Bastien Nocera 2.28.1-5 +- Update OSD code again + +* Tue Oct 27 2009 Bastien Nocera 2.28.1-4 +- Fix bluriness in OSD + +* Mon Oct 26 2009 Matthias Clasen - 2.28.1-3 +- Change default font rendering to use slight hinting + +* Mon Oct 26 2009 Peter Hutterer 2.28.1-2 +- left-handed-touchpad.patch: change physical touchpad buttons to + left-handed, not tapping though (#498249) + +* Mon Oct 19 2009 Matthias Clasen - 2.28.1-1 +- Update to 2.28.1 + +* Thu Oct 1 2009 Matthias Clasen - 2.28.0-4 +- Fix keyboard variant handling + +* Fri Sep 25 2009 Matthias Clasen - 2.28.0-3 +- Align the OSD visuals with the notification theme + +* Tue Sep 22 2009 Adam Jackson 2.28.0-2 +- BuildRequires: libcanberra-devel + +* Mon Sep 21 2009 Matthias Clasen - 2.28.0-1 +- Update to 2.28.0 + +* Wed Sep 09 2009 Bastien Nocera 2.27.92-2 +- Update left-hand touchpad patch + +* Mon Sep 7 2009 Matthias Clasen - 2.27.92-1 +- Update to 2.27.92 + +* Sun Aug 30 2009 Matthias Clasen - 2.27.91-3 +- Make 'Locate Pointer' work with metacity again + +* Wed Aug 26 2009 Peter Hutterer 2.27.91-2 +- buttonmapping.patch: Don't check for IsXExtensionDevice, only skip button + mappings for core devices instead (#502129). + +* Mon Aug 24 2009 Bastien Nocera 2.27.91-1 +- Update to 2.27.91 + +* Fri Aug 14 2009 Bastien Nocera 2.27.90-2 +- Update gnome-volume-control code + +* Fri Aug 14 2009 Bastien Nocera 2.27.90-1 +- Update to 2.27.90 + +* Tue Jul 28 2009 Matthias Clasen 2.27.5-1 +- Update to 2.27.5 + +* Fri Jul 24 2009 Fedora Release Engineering - 2.27.4-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Tue Jul 21 2009 Matthias Clasen 2.27.4-3 +- Make locate-pointer not interfere with media keys + +* Wed Jul 15 2009 Matthias Clasen 2.27.4-2 +- Rebuild against new libgnomekbd + +* Tue Jul 14 2009 Matthias Clasen 2.27.4-1 +- Update ot 2.27.4 + +* Tue Jun 30 2009 Matthias Clasen 2.27.3-2 +- Rebuild against new libxklavier + +* Tue Jun 16 2009 Matthias Clasen 2.27.3-1 +- Update to 2.27.3 + +* Mon Jun 8 2009 Matthias Clasen 2.27.1-2 +- Make the 'locate pointer' effect cope with changing compositing + managers + +* Sat May 16 2009 Matthias Clasen 2.27.1-1 +- Update to 2.27.1 + +* Fri May 08 2009 Bastien Nocera 2.26.1-4 +- Remove useless patch, see: +http://bugzilla.gnome.org/show_bug.cgi?id=580761 for details + +* Wed Apr 29 2009 Bastien Nocera 2.26.1-3 +- Don't set touchpads to be left-handed, otherwise the tap + behaves like the 2nd mouse button (#483639) + +* Mon Apr 27 2009 Matthias Clasen - 2.26.1-2 +- Don't drop schemas translations from po files + +* Tue Apr 14 2009 Matthias Clasen - 2.26.1-1 +- Update to 2.26.1 + +* Wed Apr 8 2009 Matthias Clasen - 2.26.0-2 +- Support touchpads + +* Mon Mar 16 2009 Matthias Clasen - 2.26.0-1 +- Update to 2.26.0 + +* Mon Mar 2 2009 Matthias Clasen - 2.25.92-1 +- Update to 2.25.92 + +* Tue Feb 24 2009 Fedora Release Engineering - 2.25.90-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Thu Feb 5 2009 Matthias Clasen - 2.25.90-2 +- Fix a warning (#484132) + +* Wed Feb 4 2009 Matthias Clasen - 2.25.90-1 +- Update to 2.25.90 + +* Mon Jan 19 2009 - Ray Strode - 2.25.3-4 +- Update fade patch for new gnome-desktop release + +* Thu Dec 18 2008 - Bastien Nocera - 2.25.3-3 +- Rebuild + +* Thu Dec 18 2008 - Ray Strode - 2.25.3-2 +- Drop touchpad patch for now + +* Thu Dec 18 2008 - Bastien Nocera - 2.25.3-1 +- Update to 2.25.3 + +* Thu Dec 18 2008 - Bastien Nocera - 2.25.2-11 +- Fix touchpad patches + +* Wed Dec 17 2008 Matthias Clasen - 2.25.2-10 +- Rebuild against new gnome-desktop + +* Wed Dec 10 2008 Ray Strode - 2.25.2-9 +- Don't call SetPointerMapping when using Xinput since + it duplicates effort but gets touchpads wrong (bug 324721) + +* Wed Dec 10 2008 Ray Strode - 2.25.2-8 +- Shutdown cleanly when bus goes away (bug 445898 again) + +* Wed Dec 10 2008 Ray Strode - 2.25.2-7 +- Don't map touch pad tap to right-click for left-handed + users (bug 324721) + +* Wed Dec 10 2008 Ray Strode - 2.25.2-6 +- Listen for DeviceAdded signals when configuring mouse + (in addition to DeviceEnabled). This may help with + bug 474758. + +* Tue Dec 9 2008 Ray Strode - 2.25.2-5 +- Shutdown cleanly on TERM signal (bug 445898) + +* Sun Dec 7 2008 Behdad Esfahbod - 2.25.2-4 +- Add gnome-settings-daemon-2.24.1-umask.patch + +* Thu Dec 4 2008 Ray Strode - 2.25.2-2 +- Rebase fade patch to apply with Behdad's updates to + g-s-d + +* Wed Dec 3 2008 Matthias Clasen - 2.25.2-1 +- Ypdate to 2.25.2 + +* Thu Nov 13 2008 Matthias Clasen - 2.25.1-4 +- Rebuild + +* Wed Nov 12 2008 Matthias Clasen - 2.25.1-2 +- Update to 2.25.1 + +* Fri Oct 24 2008 Ray Strode - 2.24.0-14 +- At fontconfig-devel buildrequires (bug 468304) + +* Wed Oct 15 2008 Matthias Clasen - 2.24.0-13 +- Save some space + +* Tue Oct 14 2008 Ray Strode - 2.24.0-12 +- Hold off on settings-daemon fade if nautilus is going to do + it anyway. + +* Tue Oct 14 2008 Matthias Clasen - 2.24.0-11 +- Show the shutdown dialog when the power button is pressed + +* Tue Oct 14 2008 Matthias Clasen - 2.24.0-9 +- Drop a patch that is no longer needed with the evdev ruleset + in xkeyboard-config + +* Sun Oct 12 2008 Matthias Clasen - 2.24.0-7 +- Try harder not to override peoples configured keyboard layouts + +* Sun Oct 12 2008 Ray Strode - 2.24.0-6 +- Update fade patch to skip crossfade when changing frames in + slideshow background. + +* Fri Oct 10 2008 Matthias Clasen - 2.24.0-5 +- Fix the picking up of the gdm keyboard layout even more + +* Tue Sep 30 2008 Matthias Clasen - 2.24.0-3 +- Fix the picking up of the gdm keyboard layout + +* Sun Sep 28 2008 Ray Strode - 2.24.0-2 +- Don't draw background twice at startup + +* Tue Sep 23 2008 Matthias Clasen - 2.24.0-1 +- Update to 2.24.0 + +* Thu Sep 18 2008 Ray Strode - 2.23.92-3 +- When switching desktop backgrounds fade between them + +* Thu Sep 11 2008 Soren Sandmann - 2.23.92-2 +- Fix various bugs in the fn-F7 support + +* Mon Sep 8 2008 Matthias Clasen - 2.23.92-1 +- Update to 2.23.92 + +* Fri Sep 5 2008 Matthias Clasen - 2.23.91-5 +- Try harder to use the keyboard layout that gdm tells us + +* Thu Sep 04 2008 Soren Sandmann - 2.23.91-4 +- Use the fn-F7 key, not the F7 key. + +* Wed Sep 03 2008 Soren Sandmann - 2.23.91-3 +- Bump gnome-desktop requirement + +* Wed Sep 03 2008 Soren Sandmann - 2.23.91-2 +- Add patch to do fn-f7 cycling + +* Mon Sep 01 2008 - Bastien Nocera - 2.23.91-1 +- Update to 2.23.91 + +* Thu Aug 28 2008 Jon McCann - 2.23.91-0.2008.08.28.2 +- BuildRequires libnotify-devel + +* Thu Aug 28 2008 Jon McCann - 2.23.91-0.2008.08.28.1 +- Update to snapshot + +* Fri Aug 22 2008 Matthias Clasen - 2.23.90-1 +- Update to 2.23.90 + +* Thu Aug 14 2008 Lennart Poettering - 2.23.6-3 +- Rerun autotools after patching configure.ac + +* Thu Aug 14 2008 Lennart Poettering - 2.23.6-2 +- Apply patch from gnome bug 545386. This hasn't been accepted in this form yet + by upstream, will however very likely be merged in a similar form. +- Disable esd/sounds module since we don't need it to start PA anymore + +* Tue Aug 5 2008 Matthias Clasen - 2.23.6-1 +- Update to 2.23.6 + +* Fri Jul 25 2008 Matthias Clasen - 2.23.5-3 +- Use standard icon names in the volume OSD + +* Fri Jul 25 2008 - Bastien Nocera - 2.23.5-2 +- Fix build, call gtk-update-icon-cache as required + +* Thu Jul 24 2008 Soren Sandmann - 2.23.5-1 +- Update to 2.23.5 + +* Wed Jun 18 2008 Matthias Clasen - 2.23.4-1 +- Update to 2.23.4 + +* Tue Jun 17 2008 Colin Walters - 2.23.3-2 +- Add (now upstreamed) patch to legacy ESD preference; see + http://bugzilla.gnome.org/show_bug.cgi?id=533198 + https://bugzilla.redhat.com/show_bug.cgi?id=430624 + +* Wed Jun 4 2008 Matthias Clasen - 2.23.3-1 +- Update to 2.23.3 + +* Wed May 14 2008 Matthias Clasen - 2.23.2-0.2008.05.14.2 +- Fix BuildRequires + +* Wed May 14 2008 Jon McCann - 2.23.2-0.2008.05.14.1 +- Build snapshot + +* Tue May 13 2008 Matthias Clasen - 2.23.1-1-5 +- Rebuild + +* Mon May 5 2008 Matthias Clasen - 2.23.1-1-4 +- Pick up the keyboard layout from the login screen + +* Mon May 5 2008 Matthias Clasen - 2.23.1-1-3 +- Fix background drawing without nautilus + +* Tue Apr 29 2008 - Bastien Nocera - 2.23.1.1-2 +- Add patch from upstream to avoid the Stop button triggering an Eject (#346201) + +* Fri Apr 25 2008 Matthias Clasen - 2.23.1.1-1 +- Update to 2.23.1.1 + +* Tue Apr 22 2008 Matthias Clasen - 2.22.1-2008.03.26.6 +- Make the xrandr plugin survive the absence of Xrandr + +* Sat Apr 5 2008 - Soren Sandmann - 2.22.1-2008.03.26.5 +- Update randr plugin + +* Mon Mar 31 2008 - Ray Strode - 2.22.1-0.2008.03.26.4 +- Over the releases we've accumulated default.png, default-wide.png default-5_4.png + and default.jpg. We haven't been able to drop them because it would leave some + users with white backgrounds on upgrade. This patch just falls back to the + default image if the user's background doesn't exist. + +* Wed Mar 26 2008 - Bastien Nocera - 2.22.1-0.2008.03.26.3 +- Add patch for the mouse plugin not to eat multimedia key events (#438942) + +* Wed Mar 26 2008 Jon McCann - 2.22.1-0.2008.03.26.2 +- Rebuild + +* Wed Mar 26 2008 Jon McCann - 2.22.1-0.2008.03.26.1 +- Update to snapshot +- Enable profiling + +* Wed Mar 26 2008 - Bastien Nocera - 2.22.0-3 +- apps_gnome_settings_daemon_default_editor.schemas is obsolete (#438937) + +* Thu Mar 20 2008 Matthias Clasen 2.22.0-2 +- Fix interaction between "Locate Pointer" and volume keys + +* Mon Mar 10 2008 Matthias Clasen 2.22.0-1 +- Update to 2.22.0 + +* Sun Mar 9 2008 Ray Strode - 2.21.92-3 +- Don't set keyboard model on startup from gconf if evdev is being used. + Evdev needs to use its own keyboard model to work right. + +* Sun Mar 2 2008 Soren Sandmann - 2.21.92-2 +- Update randr patch to handle video key + +* Fri Feb 29 2008 Jon McCann - 2.21.92-1 +- Update to 2.21.92 + +* Tue Feb 12 2008 Soren Sandmann - 2.21.91-3 +- Add patch to make the xrandr plugin listen for client messages from + the control panel and reread the configuration file. + +* Mon Feb 11 2008 Matthias Clasen - 2.21.91-2 +- Remove obsolete control-center translations + +* Mon Feb 11 2008 - Bastien Nocera - 2.21.91-1 +- Update to 2.21.91 +- Remove obsolete patches + +* Thu Feb 7 2008 Matthias Clasen - 2.21.90.1-3 +- Load xkb settings initially + +* Thu Jan 31 2008 - Bastien Nocera - 2.21.90.1-2 +- Fix the path for g-s-d, from upstream patch + +* Tue Jan 29 2008 - Bastien Nocera - 2.21.90.1-1 +- Update to 2.21.90.1 + +* Tue Jan 29 2008 - Bastien Nocera - 2.21.90-1 +- Update to 2.21.90 + +* Tue Jan 15 2008 Matthias Clasen - 2.21.5.2-2 +- Incorporate review feedback (#428833) + +* Tue Jan 15 2008 Matthias Clasen - 2.21.5.2-1 +- Update to 2.21.5.2 + +* Tue Jan 15 2008 Matthias Clasen - 2.21.5.1-1 +- Update to 2.21.5.1 +- Fix up BuildRequires + +* Thu Dec 06 2007 - Bastien Nocera - 2.21.5-1 +- First package +