2014-01-28 17:41:26 +00:00
|
|
|
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
|
|
|
2023-07-10 09:53:00 +00:00
|
|
|
import Clutter from 'gi://Clutter';
|
|
|
|
import Gio from 'gi://Gio';
|
|
|
|
import GLib from 'gi://GLib';
|
|
|
|
import GObject from 'gi://GObject';
|
|
|
|
import Shell from 'gi://Shell';
|
|
|
|
import St from 'gi://St';
|
2014-01-28 17:41:26 +00:00
|
|
|
|
2023-07-10 09:53:00 +00:00
|
|
|
import * as Dialog from '../dialog.js';
|
|
|
|
import * as ModalDialog from '../modalDialog.js';
|
|
|
|
import * as PermissionStore from '../../misc/permissionStore.js';
|
|
|
|
import {SystemIndicator} from '../quickSettings.js';
|
2014-01-28 17:41:26 +00:00
|
|
|
|
2023-07-10 09:53:00 +00:00
|
|
|
import {loadInterfaceXML} from '../../misc/fileUtils.js';
|
2018-09-06 00:55:20 +00:00
|
|
|
|
2014-08-09 15:03:11 +00:00
|
|
|
const LOCATION_SCHEMA = 'org.gnome.system.location';
|
2014-02-16 15:06:55 +00:00
|
|
|
const MAX_ACCURACY_LEVEL = 'max-accuracy-level';
|
2014-08-06 16:04:00 +00:00
|
|
|
const ENABLED = 'enabled';
|
2014-02-16 15:06:55 +00:00
|
|
|
|
2021-08-11 20:54:39 +00:00
|
|
|
const APP_PERMISSIONS_TABLE = 'location';
|
|
|
|
const APP_PERMISSIONS_ID = 'location';
|
2016-02-15 19:45:38 +00:00
|
|
|
|
2023-07-30 12:56:59 +00:00
|
|
|
/** @enum {number} */
|
2023-07-10 09:53:00 +00:00
|
|
|
const GeoclueAccuracyLevel = {
|
2014-09-11 13:57:15 +00:00
|
|
|
NONE: 0,
|
|
|
|
COUNTRY: 1,
|
|
|
|
CITY: 4,
|
|
|
|
NEIGHBORHOOD: 5,
|
|
|
|
STREET: 6,
|
2019-08-20 21:43:54 +00:00
|
|
|
EXACT: 8,
|
2014-09-11 13:57:15 +00:00
|
|
|
};
|
|
|
|
|
2016-02-15 19:45:38 +00:00
|
|
|
function accuracyLevelToString(accuracyLevel) {
|
|
|
|
for (let key in GeoclueAccuracyLevel) {
|
|
|
|
if (GeoclueAccuracyLevel[key] == accuracyLevel)
|
|
|
|
return key;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 'NONE';
|
|
|
|
}
|
|
|
|
|
2023-07-10 09:53:00 +00:00
|
|
|
const GeoclueIface = loadInterfaceXML('org.freedesktop.GeoClue2.Manager');
|
2014-01-28 17:41:26 +00:00
|
|
|
const GeoclueManager = Gio.DBusProxy.makeProxyWrapper(GeoclueIface);
|
|
|
|
|
2023-07-10 09:53:00 +00:00
|
|
|
const AgentIface = loadInterfaceXML('org.freedesktop.GeoClue2.Agent');
|
2014-02-13 17:50:32 +00:00
|
|
|
|
2021-07-16 16:23:58 +00:00
|
|
|
let _geoclueAgent = null;
|
2023-07-10 09:53:00 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @returns {GeoclueAgent} - the GeoclueAgent singleton
|
|
|
|
*/
|
|
|
|
export function getGeoclueAgent() {
|
2021-07-16 16:23:58 +00:00
|
|
|
if (_geoclueAgent === null)
|
|
|
|
_geoclueAgent = new GeoclueAgent();
|
|
|
|
return _geoclueAgent;
|
|
|
|
}
|
|
|
|
|
2023-07-10 09:53:00 +00:00
|
|
|
const GeoclueAgent = GObject.registerClass({
|
2021-07-16 16:21:22 +00:00
|
|
|
Properties: {
|
|
|
|
'enabled': GObject.ParamSpec.boolean(
|
|
|
|
'enabled', 'Enabled', 'Enabled',
|
|
|
|
GObject.ParamFlags.READWRITE,
|
|
|
|
false),
|
|
|
|
'in-use': GObject.ParamSpec.boolean(
|
|
|
|
'in-use', 'In use', 'In use',
|
|
|
|
GObject.ParamFlags.READABLE,
|
|
|
|
false),
|
|
|
|
'max-accuracy-level': GObject.ParamSpec.int(
|
|
|
|
'max-accuracy-level', 'Max accuracy level', 'Max accuracy level',
|
|
|
|
GObject.ParamFlags.READABLE,
|
|
|
|
0, 8, 0),
|
|
|
|
},
|
2021-07-16 16:23:58 +00:00
|
|
|
}, class GeoclueAgent extends GObject.Object {
|
2019-07-16 09:24:13 +00:00
|
|
|
_init() {
|
|
|
|
super._init();
|
2014-01-28 17:41:26 +00:00
|
|
|
|
2023-08-06 22:40:20 +00:00
|
|
|
this._settings = new Gio.Settings({schema_id: LOCATION_SCHEMA});
|
2021-08-15 22:36:59 +00:00
|
|
|
this._settings.connectObject(
|
|
|
|
`changed::${ENABLED}`, () => this.notify('enabled'),
|
|
|
|
`changed::${MAX_ACCURACY_LEVEL}`, () => this._onMaxAccuracyLevelChanged(),
|
|
|
|
this);
|
2014-02-16 15:06:55 +00:00
|
|
|
|
2014-02-13 17:50:32 +00:00
|
|
|
this._agent = Gio.DBusExportedObject.wrapJSObject(AgentIface, this);
|
2014-02-24 18:26:46 +00:00
|
|
|
this._agent.export(Gio.DBus.system, '/org/freedesktop/GeoClue2/Agent');
|
2014-02-13 17:50:32 +00:00
|
|
|
|
2021-07-16 16:21:22 +00:00
|
|
|
this.connect('notify::enabled', this._onMaxAccuracyLevelChanged.bind(this));
|
|
|
|
|
2014-01-28 17:41:26 +00:00
|
|
|
this._watchId = Gio.bus_watch_name(Gio.BusType.SYSTEM,
|
|
|
|
'org.freedesktop.GeoClue2',
|
|
|
|
0,
|
2017-12-02 00:27:35 +00:00
|
|
|
this._connectToGeoclue.bind(this),
|
|
|
|
this._onGeoclueVanished.bind(this));
|
2014-02-16 15:06:55 +00:00
|
|
|
this._onMaxAccuracyLevelChanged();
|
2014-02-13 17:50:32 +00:00
|
|
|
this._connectToGeoclue();
|
2016-02-15 19:50:25 +00:00
|
|
|
this._connectToPermissionStore();
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2014-01-28 17:41:26 +00:00
|
|
|
|
2021-07-16 16:21:22 +00:00
|
|
|
get enabled() {
|
|
|
|
return this._settings.get_boolean(ENABLED);
|
|
|
|
}
|
|
|
|
|
|
|
|
set enabled(value) {
|
|
|
|
this._settings.set_boolean(ENABLED, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
get inUse() {
|
|
|
|
return this._managerProxy?.InUse ?? false;
|
|
|
|
}
|
|
|
|
|
|
|
|
get maxAccuracyLevel() {
|
|
|
|
if (this.enabled) {
|
|
|
|
let level = this._settings.get_string(MAX_ACCURACY_LEVEL);
|
|
|
|
|
|
|
|
return GeoclueAccuracyLevel[level.toUpperCase()] ||
|
|
|
|
GeoclueAccuracyLevel.NONE;
|
|
|
|
} else {
|
|
|
|
return GeoclueAccuracyLevel.NONE;
|
|
|
|
}
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2014-02-13 17:50:32 +00:00
|
|
|
|
2022-07-08 03:24:18 +00:00
|
|
|
async AuthorizeAppAsync(params, invocation) {
|
2016-02-15 19:50:25 +00:00
|
|
|
let [desktopId, reqAccuracyLevel] = params;
|
2014-02-13 17:50:32 +00:00
|
|
|
|
2016-02-15 19:50:25 +00:00
|
|
|
let authorizer = new AppAuthorizer(desktopId,
|
2021-07-16 16:21:22 +00:00
|
|
|
reqAccuracyLevel, this._permStoreProxy, this.maxAccuracyLevel);
|
2016-02-15 19:50:25 +00:00
|
|
|
|
2022-07-08 03:24:18 +00:00
|
|
|
const accuracyLevel = await authorizer.authorize();
|
|
|
|
const ret = accuracyLevel !== GeoclueAccuracyLevel.NONE;
|
|
|
|
invocation.return_value(GLib.Variant.new('(bu)', [ret, accuracyLevel]));
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2014-02-13 17:50:32 +00:00
|
|
|
|
2021-07-16 16:21:22 +00:00
|
|
|
get MaxAccuracyLevel() {
|
|
|
|
return this.maxAccuracyLevel;
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2014-01-28 17:41:26 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_connectToGeoclue() {
|
2016-02-15 19:54:55 +00:00
|
|
|
if (this._managerProxy != null || this._connecting)
|
2014-02-15 15:17:58 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
this._connecting = true;
|
2014-02-15 13:42:43 +00:00
|
|
|
new GeoclueManager(Gio.DBus.system,
|
|
|
|
'org.freedesktop.GeoClue2',
|
|
|
|
'/org/freedesktop/GeoClue2/Manager',
|
2017-12-02 00:27:35 +00:00
|
|
|
this._onManagerProxyReady.bind(this));
|
2014-02-15 15:17:58 +00:00
|
|
|
return true;
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2014-02-15 13:42:43 +00:00
|
|
|
|
2022-06-23 12:53:29 +00:00
|
|
|
async _onManagerProxyReady(proxy, error) {
|
2014-02-15 13:42:43 +00:00
|
|
|
if (error != null) {
|
2014-02-16 13:55:17 +00:00
|
|
|
log(error.message);
|
2014-02-13 17:50:32 +00:00
|
|
|
this._connecting = false;
|
2014-02-15 13:42:43 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-02-15 19:54:55 +00:00
|
|
|
this._managerProxy = proxy;
|
2021-08-15 22:36:59 +00:00
|
|
|
this._managerProxy.connectObject('g-properties-changed',
|
|
|
|
this._onGeocluePropsChanged.bind(this), this);
|
2014-01-28 17:41:26 +00:00
|
|
|
|
2021-07-16 16:21:22 +00:00
|
|
|
this.notify('in-use');
|
2014-02-13 17:50:32 +00:00
|
|
|
|
2022-06-23 12:53:29 +00:00
|
|
|
try {
|
|
|
|
await this._managerProxy.AddAgentAsync('gnome-shell');
|
|
|
|
this._connecting = false;
|
|
|
|
this._notifyMaxAccuracyLevel();
|
|
|
|
} catch (e) {
|
|
|
|
log(e.message);
|
|
|
|
}
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2014-01-28 17:41:26 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_onGeoclueVanished() {
|
status/location: Handle geoclue not being activatable
In GNOME OS, due to a misconfiguration, geoclue was configured without
systemd support. In that configuration, geoclue does not install its
systemd .service file (geoclue.service) but it (incorrectly) includes
the following line in its D-Bus service file:
SystemdService=geoclue.service
As a result, when dbus-daemon tried to activate it at gnome-shell's
request, it would fail with:
Unit geoclue.service not found
Then, GeoclueAgent._onGeoclueVanished() would be called, as the
name_vanished_handler passed to Gio.bus_watch_name(). This is consistent
with Gio.bus_watch_name()'s documentation:
> You are guaranteed that one of the handlers will be invoked after
> calling this function.
But that function assumed that this._managerProxy is defined, leading
to:
JS ERROR: TypeError: this._managerProxy is undefined
_onGeoclueVanished@resource:///org/gnome/shell/ui/status/location.js:163:9
Fix this by checking for nullishness of this._managerProxy. (Strictly
speaking, it's undefined rather than being null, but other code in this
file already uses the vaguer '!= null' test, which considers undefined
to be null.)
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2689>
2023-03-08 20:44:36 +00:00
|
|
|
this._managerProxy?.disconnectObject(this);
|
2016-02-15 19:54:55 +00:00
|
|
|
this._managerProxy = null;
|
2014-01-28 17:41:26 +00:00
|
|
|
|
2021-07-16 16:21:22 +00:00
|
|
|
this.notify('in-use');
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2014-02-13 17:50:32 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_onMaxAccuracyLevelChanged() {
|
2021-07-16 16:21:22 +00:00
|
|
|
this.notify('max-accuracy-level');
|
2014-02-13 17:50:32 +00:00
|
|
|
|
|
|
|
// Gotta ensure geoclue is up and we are registered as agent to it
|
|
|
|
// before we emit the notify for this property change.
|
|
|
|
if (!this._connectToGeoclue())
|
|
|
|
this._notifyMaxAccuracyLevel();
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2014-02-13 17:50:32 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_notifyMaxAccuracyLevel() {
|
2021-07-16 16:21:22 +00:00
|
|
|
let variant = new GLib.Variant('u', this.maxAccuracyLevel);
|
2014-02-16 13:55:17 +00:00
|
|
|
this._agent.emit_property_changed('MaxAccuracyLevel', variant);
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2014-02-15 15:46:07 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_onGeocluePropsChanged(proxy, properties) {
|
2022-08-10 09:44:42 +00:00
|
|
|
const inUseChanged = !!properties.lookup_value('InUse', null);
|
|
|
|
if (inUseChanged)
|
2021-07-16 16:21:22 +00:00
|
|
|
this.notify('in-use');
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2016-02-15 19:50:25 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_connectToPermissionStore() {
|
2016-02-15 19:50:25 +00:00
|
|
|
this._permStoreProxy = null;
|
2017-12-02 00:27:35 +00:00
|
|
|
new PermissionStore.PermissionStore(this._onPermStoreProxyReady.bind(this));
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2016-02-15 19:50:25 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_onPermStoreProxyReady(proxy, error) {
|
2016-02-15 19:50:25 +00:00
|
|
|
if (error != null) {
|
|
|
|
log(error.message);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._permStoreProxy = proxy;
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2019-07-16 09:24:13 +00:00
|
|
|
});
|
2014-02-13 17:50:32 +00:00
|
|
|
|
2023-07-10 09:53:00 +00:00
|
|
|
export const Indicator = GObject.registerClass(
|
2022-07-27 02:43:39 +00:00
|
|
|
class Indicator extends SystemIndicator {
|
2021-07-16 16:23:58 +00:00
|
|
|
_init() {
|
|
|
|
super._init();
|
|
|
|
|
2023-07-10 09:53:00 +00:00
|
|
|
this._agent = getGeoclueAgent();
|
2021-07-16 16:23:58 +00:00
|
|
|
|
|
|
|
this._indicator = this._addIndicator();
|
2022-08-18 08:13:00 +00:00
|
|
|
this._indicator.icon_name = 'location-services-active-symbolic';
|
2021-07-16 16:23:58 +00:00
|
|
|
this._agent.bind_property('in-use',
|
|
|
|
this._indicator,
|
|
|
|
'visible',
|
|
|
|
GObject.BindingFlags.SYNC_CREATE);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2023-07-10 09:53:00 +00:00
|
|
|
class AppAuthorizer {
|
2017-10-31 01:19:44 +00:00
|
|
|
constructor(desktopId, reqAccuracyLevel, permStoreProxy, maxAccuracyLevel) {
|
2016-02-15 19:45:38 +00:00
|
|
|
this.desktopId = desktopId;
|
|
|
|
this.reqAccuracyLevel = reqAccuracyLevel;
|
|
|
|
this._permStoreProxy = permStoreProxy;
|
|
|
|
this._maxAccuracyLevel = maxAccuracyLevel;
|
2017-02-15 10:47:45 +00:00
|
|
|
this._permissions = {};
|
2016-02-15 19:45:38 +00:00
|
|
|
|
|
|
|
this._accuracyLevel = GeoclueAccuracyLevel.NONE;
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2016-02-15 19:45:38 +00:00
|
|
|
|
2022-07-08 03:24:18 +00:00
|
|
|
async authorize() {
|
2016-02-15 19:45:38 +00:00
|
|
|
let appSystem = Shell.AppSystem.get_default();
|
2022-02-07 14:14:06 +00:00
|
|
|
this._app = appSystem.lookup_app(`${this.desktopId}.desktop`);
|
2022-07-08 03:24:18 +00:00
|
|
|
if (this._app == null || this._permStoreProxy == null)
|
|
|
|
return this._completeAuth();
|
|
|
|
|
|
|
|
try {
|
|
|
|
[this._permissions] = await this._permStoreProxy.LookupAsync(
|
|
|
|
APP_PERMISSIONS_TABLE,
|
|
|
|
APP_PERMISSIONS_ID);
|
|
|
|
} catch (error) {
|
|
|
|
if (error.domain === Gio.DBusError) {
|
2016-02-15 19:45:38 +00:00
|
|
|
// Likely no xdg-app installed, just authorize the app
|
|
|
|
this._accuracyLevel = this.reqAccuracyLevel;
|
|
|
|
this._permStoreProxy = null;
|
2022-07-08 03:24:18 +00:00
|
|
|
return this._completeAuth();
|
2016-02-15 19:45:38 +00:00
|
|
|
} else {
|
|
|
|
// Currently xdg-app throws an error if we lookup for
|
|
|
|
// unknown ID (which would be the case first time this code
|
|
|
|
// runs) so we continue with user authorization as normal
|
|
|
|
// and ID is added to the store if user says "yes".
|
|
|
|
log(error.message);
|
|
|
|
this._permissions = {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let permission = this._permissions[this.desktopId];
|
|
|
|
|
2016-02-23 17:29:47 +00:00
|
|
|
if (permission == null) {
|
2022-07-08 03:24:18 +00:00
|
|
|
await this._userAuthorizeApp();
|
2016-02-23 17:29:47 +00:00
|
|
|
} else {
|
|
|
|
let [levelStr] = permission || ['NONE'];
|
|
|
|
this._accuracyLevel = GeoclueAccuracyLevel[levelStr] ||
|
|
|
|
GeoclueAccuracyLevel.NONE;
|
|
|
|
}
|
2022-07-08 03:24:18 +00:00
|
|
|
|
|
|
|
return this._completeAuth();
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2016-02-15 19:45:38 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_userAuthorizeApp() {
|
2016-02-15 19:45:38 +00:00
|
|
|
let name = this._app.get_name();
|
|
|
|
let appInfo = this._app.get_app_info();
|
2023-08-06 22:34:20 +00:00
|
|
|
let reason = appInfo.get_locale_string('X-Geoclue-Reason');
|
2016-02-15 19:45:38 +00:00
|
|
|
|
2022-07-08 03:24:18 +00:00
|
|
|
this._dialog =
|
|
|
|
new GeolocationDialog(name, reason, this.reqAccuracyLevel);
|
|
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
|
const responseId = this._dialog.connect('response',
|
|
|
|
(dialog, level) => {
|
|
|
|
this._dialog.disconnect(responseId);
|
|
|
|
this._accuracyLevel = level;
|
|
|
|
resolve();
|
|
|
|
});
|
|
|
|
this._dialog.open();
|
2017-10-31 00:38:18 +00:00
|
|
|
});
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2016-02-15 19:45:38 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_completeAuth() {
|
2016-02-15 19:45:38 +00:00
|
|
|
if (this._accuracyLevel != GeoclueAccuracyLevel.NONE) {
|
2020-06-02 03:41:43 +00:00
|
|
|
this._accuracyLevel = Math.clamp(this._accuracyLevel,
|
|
|
|
0, this._maxAccuracyLevel);
|
2016-02-15 19:45:38 +00:00
|
|
|
}
|
|
|
|
this._saveToPermissionStore();
|
|
|
|
|
2022-07-08 03:24:18 +00:00
|
|
|
return this._accuracyLevel;
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2016-02-15 19:45:38 +00:00
|
|
|
|
2022-06-23 12:53:29 +00:00
|
|
|
async _saveToPermissionStore() {
|
2016-02-15 19:45:38 +00:00
|
|
|
if (this._permStoreProxy == null)
|
|
|
|
return;
|
|
|
|
|
2016-02-23 17:29:47 +00:00
|
|
|
let levelStr = accuracyLevelToString(this._accuracyLevel);
|
|
|
|
let dateStr = Math.round(Date.now() / 1000).toString();
|
|
|
|
this._permissions[this.desktopId] = [levelStr, dateStr];
|
|
|
|
|
2016-02-15 19:45:38 +00:00
|
|
|
let data = GLib.Variant.new('av', {});
|
|
|
|
|
2022-06-23 12:53:29 +00:00
|
|
|
try {
|
|
|
|
await this._permStoreProxy.SetAsync(
|
|
|
|
APP_PERMISSIONS_TABLE,
|
|
|
|
true,
|
|
|
|
APP_PERMISSIONS_ID,
|
|
|
|
this._permissions,
|
|
|
|
data);
|
|
|
|
} catch (error) {
|
|
|
|
log(error.message);
|
|
|
|
}
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2023-07-10 09:53:00 +00:00
|
|
|
}
|
2016-02-15 19:42:09 +00:00
|
|
|
|
2023-07-10 09:53:00 +00:00
|
|
|
export const GeolocationDialog = GObject.registerClass({
|
2023-08-06 22:40:20 +00:00
|
|
|
Signals: {'response': {param_types: [GObject.TYPE_UINT]}},
|
2019-05-23 20:45:44 +00:00
|
|
|
}, class GeolocationDialog extends ModalDialog.ModalDialog {
|
2020-01-27 21:38:49 +00:00
|
|
|
_init(name, reason, reqAccuracyLevel) {
|
2023-08-06 22:40:20 +00:00
|
|
|
super._init({styleClass: 'geolocation-dialog'});
|
2016-02-15 19:42:09 +00:00
|
|
|
this.reqAccuracyLevel = reqAccuracyLevel;
|
|
|
|
|
2020-01-27 21:38:49 +00:00
|
|
|
let content = new Dialog.MessageDialogContent({
|
|
|
|
title: _('Allow location access'),
|
|
|
|
/* Translators: %s is an application name */
|
|
|
|
description: _('The app %s wants to access your location').format(name),
|
|
|
|
});
|
2016-02-15 19:42:09 +00:00
|
|
|
|
2020-01-27 21:38:49 +00:00
|
|
|
let reasonLabel = new St.Label({
|
|
|
|
text: reason,
|
|
|
|
style_class: 'message-dialog-description',
|
|
|
|
});
|
|
|
|
content.add_child(reasonLabel);
|
2016-03-03 18:57:02 +00:00
|
|
|
|
2020-01-13 13:04:40 +00:00
|
|
|
let infoLabel = new St.Label({
|
|
|
|
text: _('Location access can be changed at any time from the privacy settings.'),
|
2020-01-27 21:38:49 +00:00
|
|
|
style_class: 'message-dialog-description',
|
2020-01-13 13:04:40 +00:00
|
|
|
});
|
|
|
|
content.add_child(infoLabel);
|
|
|
|
|
2020-01-27 21:38:49 +00:00
|
|
|
this.contentLayout.add_child(content);
|
|
|
|
|
2020-03-29 21:51:13 +00:00
|
|
|
const button = this.addButton({
|
|
|
|
label: _('Deny Access'),
|
|
|
|
action: this._onDenyClicked.bind(this),
|
|
|
|
key: Clutter.KEY_Escape,
|
|
|
|
});
|
|
|
|
this.addButton({
|
|
|
|
label: _('Grant Access'),
|
|
|
|
action: this._onGrantClicked.bind(this),
|
|
|
|
});
|
2016-02-15 19:42:09 +00:00
|
|
|
|
|
|
|
this.setInitialKeyFocus(button);
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2016-02-15 19:42:09 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_onGrantClicked() {
|
2016-02-15 19:42:09 +00:00
|
|
|
this.emit('response', this.reqAccuracyLevel);
|
|
|
|
this.close();
|
2017-10-31 01:19:44 +00:00
|
|
|
}
|
2016-02-15 19:42:09 +00:00
|
|
|
|
2017-10-31 00:03:21 +00:00
|
|
|
_onDenyClicked() {
|
2016-02-15 19:42:09 +00:00
|
|
|
this.emit('response', GeoclueAccuracyLevel.NONE);
|
|
|
|
this.close();
|
|
|
|
}
|
2019-05-23 20:45:44 +00:00
|
|
|
});
|