extensionSystem: Implement new live enable/disable system
The rough sketches of the system are outlined here: http://mail.gnome.org/archives/gnome-shell-list/2011-June/msg00283.html Additionally, enable/disable extensions when the 'enabled-extensions' setting changes. Two new DBus methods, "EnableExtension" and "DisableExtension" allow users to manipulate this setting quite easily. https://bugzilla.gnome.org/show_bug.cgi?id=654770
This commit is contained in:
parent
6d3434f3a5
commit
2d813cbdd8
@ -14,7 +14,11 @@ const ExtensionState = {
|
|||||||
ENABLED: 1,
|
ENABLED: 1,
|
||||||
DISABLED: 2,
|
DISABLED: 2,
|
||||||
ERROR: 3,
|
ERROR: 3,
|
||||||
OUT_OF_DATE: 4
|
OUT_OF_DATE: 4,
|
||||||
|
|
||||||
|
// Used as an error state for operations on unknown extensions,
|
||||||
|
// should never be in a real extensionMeta object.
|
||||||
|
UNINSTALLED: 99
|
||||||
};
|
};
|
||||||
|
|
||||||
const ExtensionType = {
|
const ExtensionType = {
|
||||||
@ -26,6 +30,8 @@ const ExtensionType = {
|
|||||||
const extensionMeta = {};
|
const extensionMeta = {};
|
||||||
// Maps uuid -> importer object (extension directory tree)
|
// Maps uuid -> importer object (extension directory tree)
|
||||||
const extensions = {};
|
const extensions = {};
|
||||||
|
// Maps uuid -> extension state object (returned from init())
|
||||||
|
const extensionStateObjs = {};
|
||||||
// Arrays of uuids
|
// Arrays of uuids
|
||||||
var enabledExtensions;
|
var enabledExtensions;
|
||||||
// GFile for user extensions
|
// GFile for user extensions
|
||||||
@ -75,6 +81,46 @@ function versionCheck(required, current) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function disableExtension(uuid) {
|
||||||
|
let meta = extensionMeta[uuid];
|
||||||
|
if (!meta)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (meta.state != ExtensionState.ENABLED)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let extensionState = extensionStateObjs[uuid];
|
||||||
|
|
||||||
|
try {
|
||||||
|
extensionState.disable();
|
||||||
|
} catch(e) {
|
||||||
|
logExtensionError(uuid, e.toString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
meta.state = ExtensionState.DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
function enableExtension(uuid) {
|
||||||
|
let meta = extensionMeta[uuid];
|
||||||
|
if (!meta)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (meta.state != ExtensionState.DISABLED)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let extensionState = extensionStateObjs[uuid];
|
||||||
|
|
||||||
|
try {
|
||||||
|
extensionState.enable();
|
||||||
|
} catch(e) {
|
||||||
|
logExtensionError(uuid, e.toString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
meta.state = ExtensionState.ENABLED;
|
||||||
|
}
|
||||||
|
|
||||||
function logExtensionError(uuid, message) {
|
function logExtensionError(uuid, message) {
|
||||||
if (!errors[uuid]) errors[uuid] = [];
|
if (!errors[uuid]) errors[uuid] = [];
|
||||||
errors[uuid].push(message);
|
errors[uuid].push(message);
|
||||||
@ -136,16 +182,12 @@ function loadExtension(dir, enabled, type) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
extensionMeta[meta.uuid] = meta;
|
extensionMeta[uuid] = meta;
|
||||||
extensionMeta[meta.uuid].type = type;
|
meta.type = type;
|
||||||
extensionMeta[meta.uuid].path = dir.get_path();
|
meta.path = dir.get_path();
|
||||||
if (!enabled) {
|
|
||||||
extensionMeta[meta.uuid].state = ExtensionState.DISABLED;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default to error, we set success as the last step
|
// Default to error, we set success as the last step
|
||||||
extensionMeta[meta.uuid].state = ExtensionState.ERROR;
|
meta.state = ExtensionState.ERROR;
|
||||||
|
|
||||||
let extensionJs = dir.get_child('extension.js');
|
let extensionJs = dir.get_child('extension.js');
|
||||||
if (!extensionJs.query_exists(null)) {
|
if (!extensionJs.query_exists(null)) {
|
||||||
@ -166,6 +208,7 @@ function loadExtension(dir, enabled, type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let extensionModule;
|
let extensionModule;
|
||||||
|
let extensionState = null;
|
||||||
try {
|
try {
|
||||||
global.add_extension_importer('imports.ui.extensionSystem.extensions', meta.uuid, dir.get_path());
|
global.add_extension_importer('imports.ui.extensionSystem.extensions', meta.uuid, dir.get_path());
|
||||||
extensionModule = extensions[meta.uuid].extension;
|
extensionModule = extensions[meta.uuid].extension;
|
||||||
@ -175,24 +218,65 @@ function loadExtension(dir, enabled, type) {
|
|||||||
logExtensionError(uuid, e);
|
logExtensionError(uuid, e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!extensionModule.main) {
|
|
||||||
logExtensionError(uuid, 'missing \'main\' function');
|
if (!extensionModule.init) {
|
||||||
|
logExtensionError(uuid, 'missing \'init\' function');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
extensionModule.main(meta);
|
extensionState = extensionModule.init(meta);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (stylesheetPath != null)
|
if (stylesheetPath != null)
|
||||||
theme.unload_stylesheet(stylesheetPath);
|
theme.unload_stylesheet(stylesheetPath);
|
||||||
logExtensionError(uuid, 'Failed to evaluate init function:' + e);
|
logExtensionError(uuid, 'Failed to evaluate init function:' + e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
extensionMeta[meta.uuid].state = ExtensionState.ENABLED;
|
|
||||||
|
if (!extensionState)
|
||||||
|
extensionState = extensionModule;
|
||||||
|
extensionStateObjs[uuid] = extensionState;
|
||||||
|
|
||||||
|
if (!extensionState.enable) {
|
||||||
|
logExtensionError(uuid, 'missing \'enable\' function');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!extensionState.disable) {
|
||||||
|
logExtensionError(uuid, 'missing \'disable\' function');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
meta.state = ExtensionState.DISABLED;
|
||||||
|
|
||||||
|
if (enabled)
|
||||||
|
enableExtension(uuid);
|
||||||
|
|
||||||
_signals.emit('extension-loaded', meta.uuid);
|
_signals.emit('extension-loaded', meta.uuid);
|
||||||
global.log('Loaded extension ' + meta.uuid);
|
global.log('Loaded extension ' + meta.uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onEnabledExtensionsChanged() {
|
||||||
|
let newEnabledExtensions = global.settings.get_strv(ENABLED_EXTENSIONS_KEY);
|
||||||
|
|
||||||
|
// Find and enable all the newly enabled extensions: UUIDs found in the
|
||||||
|
// new setting, but not in the old one.
|
||||||
|
newEnabledExtensions.filter(function(uuid) {
|
||||||
|
return enabledExtensions.indexOf(uuid) == -1;
|
||||||
|
}).forEach(function(uuid) {
|
||||||
|
enableExtension(uuid);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Find and disable all the newly disabled extensions: UUIDs found in the
|
||||||
|
// old setting, but not in the new one.
|
||||||
|
enabledExtensions.filter(function(item) {
|
||||||
|
return newEnabledExtensions.indexOf(item) == -1;
|
||||||
|
}).forEach(function(uuid) {
|
||||||
|
disableExtension(uuid);
|
||||||
|
});
|
||||||
|
|
||||||
|
enabledExtensions = newEnabledExtensions;
|
||||||
|
}
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
let userExtensionsPath = GLib.build_filenamev([global.userdatadir, 'extensions']);
|
let userExtensionsPath = GLib.build_filenamev([global.userdatadir, 'extensions']);
|
||||||
userExtensionsDir = Gio.file_new_for_path(userExtensionsPath);
|
userExtensionsDir = Gio.file_new_for_path(userExtensionsPath);
|
||||||
@ -202,6 +286,7 @@ function init() {
|
|||||||
global.logError('' + e);
|
global.logError('' + e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
global.settings.connect('changed::' + ENABLED_EXTENSIONS_KEY, onEnabledExtensionsChanged);
|
||||||
enabledExtensions = global.settings.get_strv(ENABLED_EXTENSIONS_KEY);
|
enabledExtensions = global.settings.get_strv(ENABLED_EXTENSIONS_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,14 @@ const GnomeShellIface = {
|
|||||||
{ name: 'Screenshot',
|
{ name: 'Screenshot',
|
||||||
inSignature: 's',
|
inSignature: 's',
|
||||||
outSignature: 'b'
|
outSignature: 'b'
|
||||||
|
},
|
||||||
|
{ name: 'EnableExtension',
|
||||||
|
inSignature: 's',
|
||||||
|
outSignature: ''
|
||||||
|
},
|
||||||
|
{ name: 'DisableExtension',
|
||||||
|
inSignature: 's',
|
||||||
|
outSignature: ''
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
signals: [],
|
signals: [],
|
||||||
@ -144,6 +152,20 @@ GnomeShell.prototype = {
|
|||||||
return ExtensionSystem.errors[uuid] || [];
|
return ExtensionSystem.errors[uuid] || [];
|
||||||
},
|
},
|
||||||
|
|
||||||
|
EnableExtension: function(uuid) {
|
||||||
|
let enabledExtensions = global.settings.get_strv(ExtensionSystem.ENABLED_EXTENSIONS_KEY);
|
||||||
|
if (enabledExtensions.indexOf(uuid) == -1)
|
||||||
|
enabledExtensions.push(uuid);
|
||||||
|
global.settings.set_strv(ExtensionSystem.ENABLED_EXTENSIONS_KEY, enabledExtensions);
|
||||||
|
},
|
||||||
|
|
||||||
|
DisableExtension: function(uuid) {
|
||||||
|
let enabledExtensions = global.settings.get_strv(ExtensionSystem.ENABLED_EXTENSIONS_KEY);
|
||||||
|
while (enabledExtensions.indexOf(uuid) != -1)
|
||||||
|
enabledExtensions.splice(enabledExtensions.indexOf(uuid), 1);
|
||||||
|
global.settings.set_strv(ExtensionSystem.ENABLED_EXTENSIONS_KEY, enabledExtensions);
|
||||||
|
},
|
||||||
|
|
||||||
get OverviewActive() {
|
get OverviewActive() {
|
||||||
return Main.overview.visible;
|
return Main.overview.visible;
|
||||||
},
|
},
|
||||||
|
@ -33,7 +33,7 @@ const St = imports.gi.St;
|
|||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const Tweener = imports.ui.tweener;
|
const Tweener = imports.ui.tweener;
|
||||||
|
|
||||||
let text;
|
let text, button;
|
||||||
|
|
||||||
function _hideHello() {
|
function _hideHello() {
|
||||||
Main.uiGroup.remove_actor(text);
|
Main.uiGroup.remove_actor(text);
|
||||||
@ -60,22 +60,28 @@ function _showHello() {
|
|||||||
onComplete: _hideHello });
|
onComplete: _hideHello });
|
||||||
}
|
}
|
||||||
|
|
||||||
function main() {
|
function init() {
|
||||||
let button = new St.Bin({ style_class: 'panel-button',
|
button = new St.Bin({ style_class: 'panel-button',
|
||||||
reactive: true,
|
reactive: true,
|
||||||
can_focus: true,
|
can_focus: true,
|
||||||
x_fill: true,
|
x_fill: true,
|
||||||
y_fill: false,
|
y_fill: false,
|
||||||
track_hover: true });
|
track_hover: true });
|
||||||
let icon = new St.Icon({ icon_name: 'system-run',
|
let icon = new St.Icon({ icon_name: 'system-run',
|
||||||
icon_type: St.IconType.SYMBOLIC,
|
icon_type: St.IconType.SYMBOLIC,
|
||||||
style_class: 'system-status-icon' });
|
style_class: 'system-status-icon' });
|
||||||
|
|
||||||
button.set_child(icon);
|
button.set_child(icon);
|
||||||
button.connect('button-press-event', _showHello);
|
button.connect('button-press-event', _showHello);
|
||||||
|
}
|
||||||
|
|
||||||
|
function enable() {
|
||||||
Main.panel._rightBox.insert_actor(button, 0);
|
Main.panel._rightBox.insert_actor(button, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function disable() {
|
||||||
|
Main.panel._rightBox.remove_actor(button);
|
||||||
|
}
|
||||||
""",
|
""",
|
||||||
|
|
||||||
"stylesheet.css": """
|
"stylesheet.css": """
|
||||||
|
Loading…
Reference in New Issue
Block a user