diff options
author | Will Thompson <wjt@endlessos.org> | 2022-01-26 10:43:13 +0000 |
---|---|---|
committer | Will Thompson <wjt@endlessos.org> | 2022-01-26 10:53:04 +0000 |
commit | 142a0f406b39d8a6262030b71c04d5c15d3521c5 (patch) | |
tree | 31d643cd46238da134ab30e2f864da91b498ed65 | |
parent | 0812722a5bd4948e320f7c73d2b4910bd3807dce (diff) | |
download | gnome-shell-wip/wjt/eos-updater.tar.gz |
endSessionDialog: Support eos-updater [DRAFT]wip/wjt/eos-updater
eos-updater is used in Endless OS and GNOME OS.
Much more invasive changes will be needed since the eos-updater state
machine looks very different to the packagekit state machine. The update
is staged in the background; once staged, the next clean
shutdown/startup or reboot will boot straight into the new version.
-rw-r--r-- | data/dbus-interfaces/com.endlessm.Updater.xml | 292 | ||||
-rw-r--r-- | data/gnome-shell-dbus-interfaces.gresource.xml | 1 | ||||
-rw-r--r-- | js/ui/endSessionDialog.js | 34 |
3 files changed, 327 insertions, 0 deletions
diff --git a/data/dbus-interfaces/com.endlessm.Updater.xml b/data/dbus-interfaces/com.endlessm.Updater.xml new file mode 100644 index 000000000..014a3526c --- /dev/null +++ b/data/dbus-interfaces/com.endlessm.Updater.xml @@ -0,0 +1,292 @@ +<!DOCTYPE node PUBLIC +'-//freedesktop//DTD D-BUS Object Introspection 1.0//EN' +'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'> +<node> + <!-- + com.endlessm.Updater: + @short_description: Endless OS updater control interface + + Interface to query the state of the OS updater, and to control it: checking + for, downloading and applying updates. + + The updater moves through a series of states (see the `State` property and + `StateChanged` signal), with state transitions triggered by the appropriate + method call, or by an error in an operation. It will return a + `com.endlessm.Updater.Error.WrongState` error if you attempt to perform an + invalid state transition. + --> + <interface name="com.endlessm.Updater"> + <!-- + Poll: + + Check for updates. This may be performed from the `Ready`, + `UpdateAvailable`, `UpdateReady` or `Error` states. It will immediately + transition to the `Polling` state. If an update is then successfully + found, it will transition to the `UpdateAvailable` state. If no update is + available, it will transition to the `Ready` state. If there is an error + checking for an update, it will transition to the `Error` state. + + If an update is found, its details will be reported through the updater’s + properties once the updater reaches the `UpdateAvailable` state. In + particular, through the `UpdateID`, `UpdateRefspec`, `UpdateLabel` and + `UpdateMessage` properties. + --> + <method name="Poll"></method> + + <!-- + PollVolume: + @path: Absolute path to the root directory of a volume to check. + + Like `Poll`, except this polls a specific removable volume (such as a USB + stick), rather than the internet. + + If a `.ostree/repo` directory is available beneath @path, and it contains + a valid OSTree repository, that repository will be checked for updates. + If no such directory exists, the updater will transition to state `Ready` + as no update is available. + --> + <method name="PollVolume"> + <arg name="path" type="s" direction="in"/> + </method> + + <!-- + Fetch: + + Download an update. This may be performed from the `UpdateAvailable` state + only. It will immediately transition to the `Fetching` state. If the + update is successfully downloaded, it will transition to the `UpdateReady` + state; if there was an error it will transition to `Error`. + + Download progress will be reported through the updater’s properties; in + particular, `DownloadedBytes`. + --> + <method name="Fetch"></method> + + <!-- + FetchFull: + @options: Potentially empty dictionary of options. + + Like `Fetch`, except options may be provided to affect its behaviour. + Currently, the following options are supported (unsupported options are + ignored): + + * `force` (type: `b`): If true, force the download without scheduling + it through the system’s metered data scheduler. Typically, this would + be true in response to an explicit user action, and false otherwise. + * `scheduling-timeout-seconds` (type: `u`): Number of seconds to wait + for permission to download from the system’s metered data scheduler, + before returning a `com.endlessm.Updater.Error.MeteredConnection` + error and cancelling the download. Pass zero to disable the timeout. + --> + <method name="FetchFull"> + <arg name="options" type="a{sv}" direction="in"/> + </method> + + <!-- + Apply: + + Apply a downloaded update so that it’s available to boot into on the next + boot. This may be performed from the `UpdateReady` state only. It will + immediately transition to the `Applying` state. If the update is + successfully applied, it will transition to the `UpdateApplied` state; if + there was an error it will transition to `Error`. + --> + <method name="Apply"></method> + + <!-- + Cancel: + + Cancel the ongoing poll, fetch or apply operation. This may be performed + from the `Polling`, `Fetching` or `ApplyingUpdate` states. It will cancel + the operation then transition to the `Error` state, with the error + `com.endlessm.Updater.Error.Cancelled`. + --> + <method name="Cancel"></method> + + <!-- + State: + + Current state of the updater. This will be one of the following: + + * `0` (`None`): No state. + * `1` (`Ready`): Ready to perform an action. + * `2` (`Error`): An error occurred. See the `ErrorName` and + `ErrorMessage` properties for details. + * `3` (`Polling`): Checking for updates. + * `4` (`UpdateAvailable`): An update is available. See the `UpdateID`, + `UpdateRefspec`, `UpdateLabel` and `UpdateMessage` properties for + details. + * `5` (`Fetching`): Downloading an update. See the `DownloadedBytes` + property for progress updates. + * `6` (`UpdateReady`): Update downloaded and ready to apply. + * `7` (`ApplyingUpdate`): Applying an update. + * `8` (`UpdateApplied`): Update applied and ready to reboot into. + + State changes are notified using the `StateChanged` signal. + --> + <property name="State" type="u" access="read"/> + + <!-- + UpdateID: + + Checksum of the OSTree commit available as an update, or the empty string + if no update is available. + --> + <property name="UpdateID" type="s" access="read"/> + + <!-- + UpdateRefspec: + + Refspec (remote name and branch name) of the OSTree commit available as an + update, or the empty string if no update is available. + --> + <property name="UpdateRefspec" type="s" access="read"/> + + <!-- + OriginalRefspec: + + Refspec (remote name and branch name) of the currently booted OSTree + commit. + --> + <property name="OriginalRefspec" type="s" access="read"/> + + <!-- + CurrentID: + + Checksum of the currently booted OSTree commit. + --> + <property name="CurrentID" type="s" access="read"/> + + <!-- + UpdateLabel: + + Subject of the OSTree commit available as an update, or the empty string + if it’s not set or if no update is available. This is the title of the + update. + --> + <property name="UpdateLabel" type="s" access="read"/> + + <!-- + UpdateMessage: + + Description body of the OSTree commit available as an update, or the empty + string if it’s not set or if no update is available. This is the + description of the update. + --> + <property name="UpdateMessage" type="s" access="read"/> + + <!-- + Version: + + Version number of the OSTree commit available as an update, or the empty + string if it’s not set or if no update is available. + --> + <property name="Version" type="s" access="read"/> + + <!-- + DownloadSize: + + Size (in bytes) of the update when downloaded, or `-1` if an update is + available but its download size is unknown. `0` if no update is available. + --> + <property name="DownloadSize" type="x" access="read"/> + + <!-- + DownloadedBytes: + + Number of bytes of the update which have already been downloaded. This + will be `0` before a download starts, and could be `-1` if the + `DownloadSize` is unknown. + --> + <property name="DownloadedBytes" type="x" access="read"/> + + <!-- + UnpackedSize: + + Size (in bytes) of the update when unpacked, or `-1` if an update is + available but its unpacked size is unknown. `0` if no update is available. + --> + <property name="UnpackedSize" type="x" access="read"/> + + <!-- + FullDownloadSize: + + Version of `DownloadSize` which also includes the sizes of parts of the + update which are already present locally (and hence which don’t need to + be downloaded again). + --> + <property name="FullDownloadSize" type="x" access="read"/> + + <!-- + FullUnpackedSize: + + Version of `UnpackedSize` which also includes the sizes of parts of the + update which are already unpacked locally (and hence which won’t occupy + further disk space once the update is applied). + --> + <property name="FullUnpackedSize" type="x" access="read"/> + + <!-- + ErrorCode: + + Error code of the current error, or `0` if no error has been reported. + This is in an unspecified error domain, and hence is useless. + + Deprecated: Use `ErrorName` instead. + --> + <property name="ErrorCode" type="u" access="read"> + <annotation name="org.freedesktop.DBus.Deprecated" value="true"/> + </property> + + <!-- + ErrorName: + + A fully-qualified D-Bus error name, as might be returned from a D-Bus + method. + + This is the empty string if no error has been reported. + + Known errors include: + + * `com.endlessm.Updater.Error.WrongState`: Method was called in a state + which doesn’t support that method. + * `com.endlessm.Updater.Error.LiveBoot`: The updater cannot be used + because the current system is a live boot. + * `com.endlessm.Updater.Error.WrongConfiguration`: A configuration file + contains an error. + * `com.endlessm.Updater.Error.NotOstreeSystem`: The updater cannot be + used because the current system is not booted from an OSTree commit. + * `com.endlessm.Updater.Error.Fetching`: Error when downloading an + update. + * `com.endlessm.Updater.Error.MalformedAutoinstallSpec`: An autoinstall + specification in the pending update contains an error. + * `com.endlessm.Updater.Error.UnknownEntryInAutoinstallSpec`: An + autoinstall specification in the pending update contains an unknown + entry. + * `com.endlessm.Updater.Error.FlatpakRemoteConflict`: An autoinstall + specification in the pending update contains a remote name which + doesn’t match the system’s configuration. + * `com.endlessm.Updater.Error.MeteredConnection`: A fetch operation timed + out while waiting for permission to download. + --> + <property name="ErrorName" type="s" access="read"/> + + <!-- + ErrorMessage: + + A human-readable (but unlocalised) error message, or the empty string if + no error has been reported. + --> + <property name="ErrorMessage" type="s" access="read"/> + + <!-- + StateChanged: + @state: The new state. + + Signal notifying of a change in the `State` property. + --> + <signal name="StateChanged"> + <arg type="u" name="state"/> + </signal> + </interface> +</node> diff --git a/data/gnome-shell-dbus-interfaces.gresource.xml b/data/gnome-shell-dbus-interfaces.gresource.xml index 6682c462d..c7629ee09 100644 --- a/data/gnome-shell-dbus-interfaces.gresource.xml +++ b/data/gnome-shell-dbus-interfaces.gresource.xml @@ -1,6 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <gresources> <gresource prefix="/org/gnome/shell/dbus-interfaces"> + <file preprocess="xml-stripblanks">com.endlessm.Updater.xml</file> <file preprocess="xml-stripblanks">net.hadess.PowerProfiles.xml</file> <file preprocess="xml-stripblanks">net.hadess.SensorProxy.xml</file> <file preprocess="xml-stripblanks">net.reactivated.Fprint.Device.xml</file> diff --git a/js/ui/endSessionDialog.js b/js/ui/endSessionDialog.js index 1fdbd11b9..edc04b1e3 100644 --- a/js/ui/endSessionDialog.js +++ b/js/ui/endSessionDialog.js @@ -159,6 +159,9 @@ const LogindSession = Gio.DBusProxy.makeProxyWrapper(LogindSessionIface); const PkOfflineIface = loadInterfaceXML('org.freedesktop.PackageKit.Offline'); const PkOfflineProxy = Gio.DBusProxy.makeProxyWrapper(PkOfflineIface); +const EosUpdaterIface = loadInterfaceXML('com.endlessm.Updater'); +const EosUpdaterProxy = Gio.DBusProxy.makeProxyWrapper(EosUpdaterIface); + const UPowerIface = loadInterfaceXML('org.freedesktop.UPower.Device'); const UPowerProxy = Gio.DBusProxy.makeProxyWrapper(UPowerIface); @@ -244,6 +247,11 @@ class EndSessionDialog extends ModalDialog.ModalDialog { '/org/freedesktop/PackageKit', this._onPkOfflineProxyCreated.bind(this)); + this._eosUpdaterProxy = new EosUpdaterProxy(Gio.DBus.system, + 'com.endlessm.Updater', + '/com/endlessm/Updater', + this._onEosUpdaterProxyCreated.bind(this)); + this._powerProxy = new UPowerProxy(Gio.DBus.system, 'org.freedesktop.UPower', '/org/freedesktop/UPower/devices/DisplayDevice', @@ -326,6 +334,21 @@ class EndSessionDialog extends ModalDialog.ModalDialog { } } + _onEosUpdaterProxyCreated(proxy, error) { + if (error) { + log(error.message); + return; + } + + // Creating a D-Bus proxy won't propagate SERVICE_UNKNOWN or NAME_HAS_NO_OWNER + // errors if eos-updater is not available, but the GIO implementation will make + // sure in that case that the proxy's g-name-owner is set to null, so check that. + if (this._eosUpdaterProxy.g_name_owner === null) { + this._eosUpdaterProxy = null; + return; + } + } + _onDestroy() { this._user.disconnect(this._userLoadedId); this._user.disconnect(this._userChangedId); @@ -398,6 +421,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog { } // Fall back to regular description + // TODO: dialogContent.description is not a function if (!description) description = dialogContent.description(displayTime); @@ -747,6 +771,16 @@ class EndSessionDialog extends ModalDialog.ModalDialog { this._type = DialogType.UPDATE_RESTART; else if (this._updateInfo.UpgradeTriggered) this._type = DialogType.UPGRADE_RESTART; + } else if (this._eosUpdaterProxy && this._type == DialogType.RESTART) { + var x = this._eosUpdaterProxy.get_cached_property("State"); + if (x != null && x.get_uint32() === 8) { + this._type = DialogType.UPGRADE_RESTART; + this._updateInfo.PreparedUpgrade = { + // TODO: GNOME OS? + name: "Endless OS", + version: this._eosUpdaterProxy.get_cached_property("Version").get_string(), + }; + } } this._applications = []; |