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
This commit is contained in:
parent
fa593a3e15
commit
7db92ad5d9
@ -3,6 +3,7 @@
|
|||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
const Signals = imports.signals;
|
const Signals = imports.signals;
|
||||||
|
|
||||||
|
const Clutter = imports.gi.Clutter;
|
||||||
const GLib = imports.gi.GLib;
|
const GLib = imports.gi.GLib;
|
||||||
const Gio = imports.gi.Gio;
|
const Gio = imports.gi.Gio;
|
||||||
const St = imports.gi.St;
|
const St = imports.gi.St;
|
||||||
@ -11,6 +12,7 @@ const Soup = imports.gi.Soup;
|
|||||||
|
|
||||||
const Config = imports.misc.config;
|
const Config = imports.misc.config;
|
||||||
const FileUtils = imports.misc.fileUtils;
|
const FileUtils = imports.misc.fileUtils;
|
||||||
|
const ModalDialog = imports.ui.modalDialog;
|
||||||
|
|
||||||
const API_VERSION = 1;
|
const API_VERSION = 1;
|
||||||
|
|
||||||
@ -110,24 +112,18 @@ function versionCheck(required, current) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function installExtensionFromUUID(uuid, version_tag) {
|
function installExtensionFromUUID(uuid, version_tag) {
|
||||||
let meta = { uuid: uuid,
|
let params = { uuid: uuid,
|
||||||
state: ExtensionState.DOWNLOADING,
|
version_tag: version_tag,
|
||||||
error: '' };
|
|
||||||
|
|
||||||
extensionMeta[uuid] = meta;
|
|
||||||
|
|
||||||
_signals.emit('extension-state-changed', meta);
|
|
||||||
|
|
||||||
let params = { version_tag: version_tag,
|
|
||||||
shell_version: Config.PACKAGE_VERSION,
|
shell_version: Config.PACKAGE_VERSION,
|
||||||
api_version: API_VERSION.toString() };
|
api_version: API_VERSION.toString() };
|
||||||
|
|
||||||
let url = REPOSITORY_URL_DOWNLOAD.format(uuid);
|
let message = Soup.form_request_new_from_hash('GET', REPOSITORY_URL_INFO, params);
|
||||||
let message = Soup.form_request_new_from_hash('GET', url, params);
|
|
||||||
|
|
||||||
_httpSession.queue_message(message,
|
_httpSession.queue_message(message,
|
||||||
function(session, 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);
|
_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());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user