weather: Stop accessing app settings directly
Our current Weather integration depends on poking around the app's settings, which we cannot do when the app is sandboxed (as its filesystem is "hidden away" in a container in that case). So instead, use our own GSettings schema for the settings, and sync it with GNOME Weather via a custom D-Bus interface. https://gitlab.gnome.org/GNOME/gnome-shell/issues/1158
This commit is contained in:
parent
8f3554ff3e
commit
933c037c6e
16
data/dbus-interfaces/org.gnome.Shell.WeatherIntegration.xml
Normal file
16
data/dbus-interfaces/org.gnome.Shell.WeatherIntegration.xml
Normal file
@ -0,0 +1,16 @@
|
||||
<node>
|
||||
|
||||
<!--
|
||||
org.gnome.Shell.WeatherIntegration:
|
||||
@short_description: Weather integration interface
|
||||
|
||||
The interface used for exporting location settings to GNOME Shell's
|
||||
weather integration.
|
||||
-->
|
||||
<interface name="org.gnome.Shell.WeatherIntegration">
|
||||
|
||||
<property name="AutomaticLocation" type="b" access="read"/>
|
||||
<property name="Locations" type="av" access="read"/>
|
||||
|
||||
</interface>
|
||||
</node>
|
@ -48,6 +48,7 @@
|
||||
<file preprocess="xml-stripblanks">org.gnome.Shell.Screencast.xml</file>
|
||||
<file preprocess="xml-stripblanks">org.gnome.Shell.Screenshot.xml</file>
|
||||
<file preprocess="xml-stripblanks">org.gnome.Shell.Wacom.PadOsd.xml</file>
|
||||
<file preprocess="xml-stripblanks">org.gnome.Shell.WeatherIntegration.xml</file>
|
||||
<file preprocess="xml-stripblanks">org.gnome.Shell.xml</file>
|
||||
<file preprocess="xml-stripblanks">org.Gtk.MountOperationHandler.xml</file>
|
||||
<file preprocess="xml-stripblanks">org.gtk.Notifications.xml</file>
|
||||
|
@ -233,6 +233,25 @@
|
||||
</key>
|
||||
</schema>
|
||||
|
||||
<schema id="org.gnome.shell.weather" path="/org/gnome/shell/weather/"
|
||||
gettext-domain="@GETTEXT_PACKAGE@">
|
||||
<key name="automatic-location" type="b">
|
||||
<summary>Automatic location</summary>
|
||||
<description>
|
||||
Whether to fetch the current location or not
|
||||
</description>
|
||||
<default>false</default>
|
||||
</key>
|
||||
|
||||
<key name="locations" type="av">
|
||||
<summary>Location</summary>
|
||||
<description>
|
||||
The location for which to show a forecast
|
||||
</description>
|
||||
<default>[]</default>
|
||||
</key>
|
||||
</schema>
|
||||
|
||||
<!-- unused, change 00_org.gnome.shell.gschema.override instead -->
|
||||
<schema id="org.gnome.shell.overrides" path="/org/gnome/shell/overrides/"
|
||||
gettext-domain="@GETTEXT_PACKAGE@">
|
||||
|
@ -1,10 +1,19 @@
|
||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
||||
|
||||
const { Geoclue, Gio, GLib, GWeather } = imports.gi;
|
||||
const { Geoclue, Gio, GLib, GWeather, Shell } = imports.gi;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const PermissionStore = imports.misc.permissionStore;
|
||||
const Util = imports.misc.util;
|
||||
|
||||
const { loadInterfaceXML } = imports.misc.fileUtils;
|
||||
|
||||
const WeatherIntegrationIface = loadInterfaceXML('org.gnome.Shell.WeatherIntegration');
|
||||
|
||||
const WEATHER_BUS_NAME = 'org.gnome.Weather';
|
||||
const WEATHER_OBJECT_PATH = '/org/gnome/Weather';
|
||||
const WEATHER_INTEGRATION_IFACE = 'org.gnome.Shell.WeatherIntegration';
|
||||
|
||||
const WEATHER_APP_ID = 'org.gnome.Weather.desktop';
|
||||
|
||||
// Minimum time between updates to show loading indication
|
||||
var UPDATE_THRESHOLD = 10 * GLib.TIME_SPAN_MINUTE;
|
||||
@ -66,17 +75,36 @@ var WeatherClient = class {
|
||||
this.emit('changed');
|
||||
});
|
||||
|
||||
this._weatherAppMon = new Util.AppSettingsMonitor('org.gnome.Weather.desktop',
|
||||
'org.gnome.Weather');
|
||||
this._weatherAppMon.connect('available-changed', () => this.emit('changed'));
|
||||
this._weatherAppMon.watchSetting('automatic-location',
|
||||
this._weatherApp = null;
|
||||
this._weatherProxy = null;
|
||||
|
||||
let nodeInfo = Gio.DBusNodeInfo.new_for_xml(WeatherIntegrationIface);
|
||||
Gio.DBusProxy.new(
|
||||
Gio.DBus.session,
|
||||
Gio.DBusProxyFlags.DO_NOT_AUTO_START | Gio.DBusProxyFlags.GET_INVALIDATED_PROPERTIES,
|
||||
nodeInfo.lookup_interface(WEATHER_INTEGRATION_IFACE),
|
||||
WEATHER_BUS_NAME,
|
||||
WEATHER_OBJECT_PATH,
|
||||
WEATHER_INTEGRATION_IFACE,
|
||||
null,
|
||||
this._onWeatherProxyReady.bind(this));
|
||||
|
||||
this._settings = new Gio.Settings({
|
||||
schema_id: 'org.gnome.shell.weather'
|
||||
});
|
||||
this._settings.connect('changed::automatic-location',
|
||||
this._onAutomaticLocationChanged.bind(this));
|
||||
this._weatherAppMon.watchSetting('locations',
|
||||
this._settings.connect('changed::locations',
|
||||
this._onLocationsChanged.bind(this));
|
||||
|
||||
this._appSystem = Shell.AppSystem.get_default();
|
||||
this._appSystem.connect('installed-changed',
|
||||
this._onInstalledChanged.bind(this));
|
||||
this._onInstalledChanged();
|
||||
}
|
||||
|
||||
get available() {
|
||||
return this._weatherAppMon.available;
|
||||
return this._weatherApp != null;
|
||||
}
|
||||
|
||||
get loading() {
|
||||
@ -92,7 +120,8 @@ var WeatherClient = class {
|
||||
}
|
||||
|
||||
activateApp() {
|
||||
this._weatherAppMon.activateApp();
|
||||
if (this._weatherApp)
|
||||
this._weatherApp.activate();
|
||||
}
|
||||
|
||||
update() {
|
||||
@ -114,6 +143,37 @@ var WeatherClient = class {
|
||||
this._weatherAuthorized;
|
||||
}
|
||||
|
||||
_onWeatherProxyReady(o, res) {
|
||||
try {
|
||||
this._weatherProxy = Gio.DBusProxy.new_finish(res);
|
||||
} catch (e) {
|
||||
log(`Failed to create GNOME Weather proxy: ${e}`);
|
||||
return;
|
||||
}
|
||||
|
||||
this._weatherProxy.connect('g-properties-changed',
|
||||
this._onWeatherPropertiesChanged.bind(this));
|
||||
|
||||
if (this._weatherProxy.g_owner != null)
|
||||
this._onWeatherPropertiesChanged();
|
||||
}
|
||||
|
||||
_onWeatherPropertiesChanged() {
|
||||
this._settings.set_boolean('automatic-location',
|
||||
this._weatherProxy.AutomaticLocation);
|
||||
this._settings.set_value('locations',
|
||||
new GLib.Variant('av', this._weatherProxy.Locations));
|
||||
}
|
||||
|
||||
_onInstalledChanged() {
|
||||
let hadApp = (this._weatherApp != null);
|
||||
this._weatherApp = this._appSystem.lookup_app(WEATHER_APP_ID);
|
||||
let haveApp = (this._weatherApp != null);
|
||||
|
||||
if (hadApp !== haveApp)
|
||||
this.emit('changed');
|
||||
}
|
||||
|
||||
_loadInfo() {
|
||||
let id = this._weatherInfo.connect('updated', () => {
|
||||
this._weatherInfo.disconnect(id);
|
||||
|
Loading…
Reference in New Issue
Block a user