[gnome-shell/wip/loc-apps: 2/2] tmp



commit 1c4ced66985f6f987478ca2ea473887040d464bd
Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
Date:   Tue Feb 9 17:16:08 2016 +0000

    tmp

 js/ui/status/location.js |  207 ++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 180 insertions(+), 27 deletions(-)
---
diff --git a/js/ui/status/location.js b/js/ui/status/location.js
index 1aae47a..0f12215 100644
--- a/js/ui/status/location.js
+++ b/js/ui/status/location.js
@@ -7,12 +7,15 @@ const Lang = imports.lang;
 const Main = imports.ui.main;
 const PanelMenu = imports.ui.panelMenu;
 const PopupMenu = imports.ui.popupMenu;
+const ModalDialog = imports.ui.modalDialog;
 const Shell = imports.gi.Shell;
+const St = imports.gi.St;
 
 const LOCATION_SCHEMA = 'org.gnome.system.location';
 const MAX_ACCURACY_LEVEL = 'max-accuracy-level';
 const ENABLED = 'enabled';
-const APPS = 'applications';
+
+const APP_PERMISSIONS = 'geolocation-app-permissions';
 
 const GeoclueAccuracyLevel = {
     NONE: 0,
@@ -47,6 +50,26 @@ var AgentIface = '<node> \
   </interface> \
 </node>';
 
+var XdgAppIface = '<node> \
+  <interface name="org.freedesktop.XdgApp.PermissionStore"> \
+    <method name="Lookup"> \
+      <arg name="table" type="s" direction="in"/> \
+      <arg name="id" type="s" direction="in"/> \
+      <arg name="permissions" type="a{sas}" direction="out"/> \
+      <arg name="data" type="v" direction="out"/> \
+    </method> \
+    <method name="SetPermission"> \
+      <arg name="table" type="s" direction="in"/> \
+      <arg name="create" type="b" direction="in"/> \
+      <arg name="id" type="s" direction="in"/> \
+      <arg name="app" type="s" direction="in"/> \
+      <arg name="permissions" type="as" direction="in"/> \
+    </method> \
+  </interface> \
+</node>';
+
+const PermissionStore = Gio.DBusProxy.makeProxyWrapper(XdgAppIface);
+
 const Indicator = new Lang.Class({
     Name: 'LocationIndicator',
     Extends: PanelMenu.SystemIndicator,
@@ -84,73 +107,145 @@ const Indicator = new Lang.Class({
         this._onSessionUpdated();
         this._onMaxAccuracyLevelChanged();
         this._connectToGeoclue();
+        this._connectToPermissionStore();
     },
 
     get MaxAccuracyLevel() {
         return this._getMaxAccuracyLevel();
     },
 
-    AuthorizeApp: function(desktop_id, reqAccuracyLevel) {
-        let apps = this._settings.get_value(APPS);
-        let nApps = apps.n_children();
+    AuthorizeAppAsync: function(params, invocation) {
+        let [desktop_id, reqAccuracyLevel] = params;
+        log("%s is requesting location".format(desktop_id));
+        let level = this._fetchAccuracyLevelFromStore(desktop_id);
+        if (level >= GeoclueAccuracyLevel.NONE) {
+            log("%s is in store".format(desktop_id));
+            let accuracyLevel = clamp(reqAccuracyLevel, 0, level);
+            this._completeAuthorizeApp(accuracyLevel, invocation);
+        } else {
+            log("%s not in store".format(desktop_id));
+            this._userAuthorizeApp(desktop_id, reqAccuracyLevel, invocation);
+        }
+    },
 
-        for (let i = 0; i < nApps; i++) {
-            let [app, levelStr] = apps.get_child_value(i).deep_unpack();
-            if (app != desktop_id)
-                continue;
+    _userAuthorizeApp: function(desktop_id, reqAccuracyLevel, invocation) {
+        var appSystem = Shell.AppSystem.get_default();
+        var app = appSystem.lookup_app(desktop_id + ".desktop");
+        if (app == null) {
+            this._completeAuthorizeApp(GeoclueAccuracyLevel.NONE, invocation);
+            return;
+        }
+
+        var name = app.get_name();
+        var icon = app.get_app_info().get_icon();
+        var allowCallback = function() {
+            this._completeAuthorizeApp(reqAccuracyLevel, invocation);
+        };
+        var denyCallback = function() {
+            this._completeAuthorizeApp(GeoclueAccuracyLevel.NONE, invocation);
+        };
+
+        this._showAppAuthDialog(name,
+                                icon,
+                                Lang.bind(this, allowCallback),
+                                Lang.bind(this, denyCallback));
+    },
+
+    _showAppAuthDialog: function(name, icon, allowCallback, denyCallback) {
+        if (this._dialog == null)
+            this._dialog = new GeolocationDialog(name, icon);
+        else
+            this._dialog.update(name, icon);
+
+        let closedId = this._dialog.connect('closed', function() {
+            this._dialog.disconnect(closedId);
+            if (this._dialog.allowed)
+                allowCallback ();
+            else
+                denyCallback ();
+        }.bind(this));
+
+        this._dialog.open(global.get_current_time ());
+    },
+
+    _completeAuthorizeApp: function(accuracyLevel, invocation) {
+        if (accuracyLevel == GeoclueAccuracyLevel.NONE) {
+            invocation.return_value(GLib.Variant.new('(bu)',
+                                                     [false, accuracyLevel]));
+            return;
+        }
+
+        let allowedAccuracyLevel = clamp(accuracyLevel,
+                                         0,
+                                         this._getMaxAccuracyLevel());
+        invocation.return_value(GLib.Variant.new('(bu)',
+                                                 [true, allowedAccuracyLevel]));
+    },
 
-            level = GeoclueAccuracyLevel[levelStr.toUpperCase()] ||
-                    GeoclueAccuracyLevel.NONE;
-            if (level == GeoclueAccuracyLevel.NONE)
-                return [false, 0];
+    _fetchAccuracyLevelFromStore: function(desktop_id) {
+        if (this._permStoreProxy == null)
+            return -1;
 
-            let allowedAccuracyLevel = clamp(reqAccuracyLevel, 0, level);
-            allowedAccuracyLevel = clamp(allowedAccuracyLevel, 0, this._getMaxAccuracyLevel());
+        let permissions;
+        try {
+            let data;
 
-            return [true, allowedAccuracyLevel];
+            [permissions, data] =
+                this._permStoreProxy.LookupSync(APP_PERMISSIONS, desktop_id);
+        } catch (e) {
+            log(e);
+            return -1;
         }
 
-        return [false, 0];
+        if (permissions == null)
+            return -1;
+
+        let levelStr = permissions['AccuracyLevel'];
+        if (levelStr == null)
+            return -1;
+
+        return GeoclueAccuracyLevel[levelStr.toUpperCase()] ||
+               GeoclueAccuracyLevel.NONE;
     },
 
     _syncIndicator: function() {
-        if (this._proxy == null) {
+        if (this._managerProxy == null) {
             this._indicator.visible = false;
             this._item.actor.visible = false;
             return;
         }
 
-        this._indicator.visible = this._proxy.InUse;
+        this._indicator.visible = this._managerProxy.InUse;
         this._item.actor.visible = this._indicator.visible;
         this._updateMenuLabels();
     },
 
     _connectToGeoclue: function() {
-        if (this._proxy != null || this._connecting)
+        if (this._managerProxy != null || this._connecting)
             return false;
 
         this._connecting = true;
         new GeoclueManager(Gio.DBus.system,
                            'org.freedesktop.GeoClue2',
                            '/org/freedesktop/GeoClue2/Manager',
-                           Lang.bind(this, this._onProxyReady));
+                           Lang.bind(this, this._onManagerProxyReady));
         return true;
     },
 
-    _onProxyReady: function(proxy, error) {
+    _onManagerProxyReady: function(proxy, error) {
         if (error != null) {
             log(error.message);
             this._connecting = false;
             return;
         }
 
-        this._proxy = proxy;
-        this._propertiesChangedId = this._proxy.connect('g-properties-changed',
+        this._managerProxy = proxy;
+        this._propertiesChangedId = this._managerProxy.connect('g-properties-changed',
                                                         Lang.bind(this, this._onGeocluePropsChanged));
 
         this._syncIndicator();
 
-        this._proxy.AddAgentRemote('gnome-shell', Lang.bind(this, this._onAgentRegistered));
+        this._managerProxy.AddAgentRemote('gnome-shell', Lang.bind(this, this._onAgentRegistered));
     },
 
     _onAgentRegistered: function(result, error) {
@@ -163,10 +258,10 @@ const Indicator = new Lang.Class({
 
     _onGeoclueVanished: function() {
         if (this._propertiesChangedId) {
-            this._proxy.disconnect(this._propertiesChangedId);
+            this._managerProxy.disconnect(this._propertiesChangedId);
             this._propertiesChangedId = 0;
         }
-        this._proxy = null;
+        this._managerProxy = null;
 
         this._syncIndicator();
     },
@@ -221,9 +316,67 @@ const Indicator = new Lang.Class({
         let unpacked = properties.deep_unpack();
         if ("InUse" in unpacked)
             this._syncIndicator();
-    }
+    },
+
+    _connectToPermissionStore: function() {
+        this._permStoreProxy = null;
+        new PermissionStore(Gio.DBus.session,
+                           'org.freedesktop.XdgApp',
+                           '/org/freedesktop/XdgApp/PermissionStore',
+                           Lang.bind(this, this._onPermStoreProxyReady));
+    },
+
+    _onPermStoreProxyReady: function(proxy, error) {
+        if (error != null) {
+            log(error.message);
+            return;
+        }
+
+        this._permStoreProxy = proxy;
+    },
 });
 
 function clamp(value, min, max) {
     return Math.max(min, Math.min(max, value));
 }
+
+const GeolocationDialog = new Lang.Class({
+    Name: 'GeolocationDialog',
+    Extends: ModalDialog.ModalDialog,
+
+    // FIXME: Would be nice to show the application icon too
+    _init: function(name, icon) {
+        this.parent({ destroyOnClose: false });
+
+        let text = _("'%s' is requesting access to location data.").format (name);
+        this._label = new St.Label({ style_class: 'prompt-dialog-description',
+                                     text: text });
+
+        this.contentLayout.add(this._label, {});
+
+        this._allowButton = this.addButton({ label: _("Confirm"),
+                                             action: this._onAllowClicked.bind(this),
+                                             default: false },
+                                           { expand: true, x_fill: false, x_align: St.Align.END });
+        this._denyButton = this.addButton({ label: _("Cancel"),
+                                            action: this._onDisallowClicked.bind(this),
+                                            default: true },
+                                          { expand: true, x_fill: false, x_align: St.Align.START });
+    },
+
+    update: function(name, icon) {
+        let text = _("'%s' is requesting access to location data.").format (name);
+        this._label = new St.Label({ style_class: 'prompt-dialog-description',
+                                     text: text });
+    },
+
+    _onAllowClicked: function() {
+        this.allowed = true;
+        this.close();
+    },
+
+    _onDisallowClicked: function() {
+        this.allowed = false;
+        this.close();
+    }
+});


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]