[gnome-shell] extensionSystem: Add an explicit approval dialog



commit 7db92ad5d9e0e9114ed13041b14cdfbdc18e89ce
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Mon Sep 12 14:17:09 2011 -0400

    extensionSystem: Add an explicit approval dialog
    
    Pop up a dialog when trying to install an extension so that users are aware
    they are installing one. This is a security precaution in the case that an XSS
    exploit has been found on the website, which could cause someone to inject a
    <script> tag and silently install an extension.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=658612

 js/ui/extensionSystem.js |   90 +++++++++++++++++++++++++++++++++++++++------
 1 files changed, 78 insertions(+), 12 deletions(-)
---
diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js
index cc2510f..52ab2ab 100644
--- a/js/ui/extensionSystem.js
+++ b/js/ui/extensionSystem.js
@@ -3,6 +3,7 @@
 const Lang = imports.lang;
 const Signals = imports.signals;
 
+const Clutter = imports.gi.Clutter;
 const GLib = imports.gi.GLib;
 const Gio = imports.gi.Gio;
 const St = imports.gi.St;
@@ -11,6 +12,7 @@ const Soup = imports.gi.Soup;
 
 const Config = imports.misc.config;
 const FileUtils = imports.misc.fileUtils;
+const ModalDialog = imports.ui.modalDialog;
 
 const API_VERSION = 1;
 
@@ -110,24 +112,18 @@ function versionCheck(required, current) {
 }
 
 function installExtensionFromUUID(uuid, version_tag) {
-    let meta = { uuid: uuid,
-                 state: ExtensionState.DOWNLOADING,
-                 error: '' };
-
-    extensionMeta[uuid] = meta;
-
-    _signals.emit('extension-state-changed', meta);
-
-    let params = { version_tag: version_tag,
+    let params = { uuid: uuid,
+                   version_tag: version_tag,
                    shell_version: Config.PACKAGE_VERSION,
                    api_version: API_VERSION.toString() };
 
-    let url = REPOSITORY_URL_DOWNLOAD.format(uuid);
-    let message = Soup.form_request_new_from_hash('GET', url, params);
+    let message = Soup.form_request_new_from_hash('GET', REPOSITORY_URL_INFO, params);
 
     _httpSession.queue_message(message,
                                function(session, message) {
-                                   gotExtensionZipFile(session, message, uuid);
+                                   let info = JSON.parse(message.response_body.data);
+                                   let dialog = new InstallExtensionDialog(uuid, version_tag, info.name);
+                                   dialog.open(global.get_current_time());
                                });
 }
 
@@ -463,3 +459,73 @@ function loadExtensions() {
             _loadExtensionsIn(dir, ExtensionType.SYSTEM);
     }
 }
+
+function InstallExtensionDialog(uuid, version_tag, name) {
+    this._init(uuid, version_tag, name);
+}
+
+InstallExtensionDialog.prototype = {
+    __proto__: ModalDialog.ModalDialog.prototype,
+
+    _init: function(uuid, version_tag, name) {
+        ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'extension-dialog' });
+
+        this._uuid = uuid;
+        this._version_tag = version_tag;
+        this._name = name;
+
+        this.setButtons([{ label: _("Cancel"),
+                           action: Lang.bind(this, this._onCancelButtonPressed),
+                           key:    Clutter.Escape
+                         },
+                         { label:  _("Install"),
+                           action: Lang.bind(this, this._onInstallButtonPressed)
+                         }]);
+
+        let message = _("Download and install '%s' from extensions.gnome.org?").format(name);
+
+        this._descriptionLabel = new St.Label({ text: message });
+
+        this.contentLayout.add(this._descriptionLabel,
+                               { y_fill:  true,
+                                 y_align: St.Align.START });
+    },
+
+    _onCancelButtonPressed: function(button, event) {
+        this.close(global.get_current_time());
+
+        // Even though the extension is already "uninstalled", send through
+        // a state-changed signal for any users who want to know if the install
+        // went through correctly -- using proper async DBus would block more
+        // traditional clients like the plugin
+        let meta = { uuid: this._uuid,
+                     state: ExtensionState.UNINSTALLED,
+                     error: '' };
+
+        _signals.emit('extension-state-changed', meta);
+    },
+
+    _onInstallButtonPressed: function(button, event) {
+        let meta = { uuid: this._uuid,
+                     state: ExtensionState.DOWNLOADING,
+                     error: '' };
+
+        extensionMeta[this._uuid] = meta;
+
+        _signals.emit('extension-state-changed', meta);
+
+        let params = { version_tag: this._version_tag,
+                       shell_version: Config.PACKAGE_VERSION,
+                       api_version: API_VERSION.toString() };
+
+        let url = REPOSITORY_URL_DOWNLOAD.format(this._uuid);
+        let message = Soup.form_request_new_from_hash('GET', url, params);
+
+        _httpSession.queue_message(message,
+                                   Lang.bind(this, function(session, message) {
+                                       gotExtensionZipFile(session, message, this._uuid);
+                                   }));
+
+        this.close(global.get_current_time());
+    }
+};



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