[gnome-shell] extensionSystem: Turn into a class



commit ea177407191c17e6e386e5b36bad2508c8cbcdcb
Author: Florian Müllner <fmuellner gnome org>
Date:   Thu Mar 7 01:45:45 2019 +0100

    extensionSystem: Turn into a class
    
    The extension system started out as a set of simple functions, but
    gained more state later, and even some hacks to emit signals without
    having an object to emit them on.
    
    There is no good reason for that weirdness, so rather than imitating an
    object, wrap the existing system into a real ExtensionManager object.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=789852

 js/ui/extensionDownloader.js |  17 +-
 js/ui/extensionSystem.js     | 567 +++++++++++++++++++++----------------------
 js/ui/lookingGlass.js        |   5 +-
 js/ui/main.js                |   3 +-
 js/ui/shellDBus.js           |   7 +-
 5 files changed, 297 insertions(+), 302 deletions(-)
---
diff --git a/js/ui/extensionDownloader.js b/js/ui/extensionDownloader.js
index c6502d501..25027a3aa 100644
--- a/js/ui/extensionDownloader.js
+++ b/js/ui/extensionDownloader.js
@@ -7,6 +7,7 @@ const Dialog = imports.ui.dialog;
 const ExtensionUtils = imports.misc.extensionUtils;
 const ExtensionSystem = imports.ui.extensionSystem;
 const FileUtils = imports.misc.fileUtils;
+const Main = imports.ui.main;
 const ModalDialog = imports.ui.modalDialog;
 
 var REPOSITORY_URL_BASE = 'https://extensions.gnome.org';
@@ -24,7 +25,7 @@ function installExtension(uuid, invocation) {
 
     _httpSession.queue_message(message, (session, message) => {
         if (message.status_code != Soup.KnownStatusCode.OK) {
-            ExtensionSystem.logExtensionError(uuid, `downloading info: ${message.status_code}`);
+            Main.extensionManager.logExtensionError(uuid, `downloading info: ${message.status_code}`);
             invocation.return_dbus_error('org.gnome.Shell.DownloadInfoError', 
message.status_code.toString());
             return;
         }
@@ -33,7 +34,7 @@ function installExtension(uuid, invocation) {
         try {
             info = JSON.parse(message.response_body.data);
         } catch (e) {
-            ExtensionSystem.logExtensionError(uuid, `parsing info: ${e}`);
+            Main.extensionManager.logExtensionError(uuid, `parsing info: ${e}`);
             invocation.return_dbus_error('org.gnome.Shell.ParseInfoError', e.toString());
             return;
         }
@@ -52,7 +53,7 @@ function uninstallExtension(uuid) {
     if (extension.type != ExtensionUtils.ExtensionType.PER_USER)
         return false;
 
-    if (!ExtensionSystem.unloadExtension(extension))
+    if (!Main.extensionManager.unloadExtension(extension))
         return false;
 
     FileUtils.recursivelyDeleteDir(extension.dir, true);
@@ -116,7 +117,7 @@ function updateExtension(uuid) {
             let oldExtension = ExtensionUtils.extensions[uuid];
             let extensionDir = oldExtension.dir;
 
-            if (!ExtensionSystem.unloadExtension(oldExtension))
+            if (!Main.extensionManager.unloadExtension(oldExtension))
                 return;
 
             FileUtils.recursivelyMoveDir(extensionDir, oldExtensionTmpDir);
@@ -126,10 +127,10 @@ function updateExtension(uuid) {
 
             try {
                 extension = ExtensionUtils.createExtensionObject(uuid, extensionDir, 
ExtensionUtils.ExtensionType.PER_USER);
-                ExtensionSystem.loadExtension(extension);
+                Main.extensionManager.loadExtension(extension);
             } catch (e) {
                 if (extension)
-                    ExtensionSystem.unloadExtension(extension);
+                    Main.extensionManager.unloadExtension(extension);
 
                 logError(e, 'Error loading extension %s'.format(uuid));
 
@@ -138,7 +139,7 @@ function updateExtension(uuid) {
 
                 // Restore what was there before. We can't do much if we
                 // fail here.
-                ExtensionSystem.loadExtension(oldExtension);
+                Main.extensionManager.loadExtension(oldExtension);
                 return;
             }
 
@@ -233,7 +234,7 @@ class InstallExtensionDialog extends ModalDialog.ModalDialog {
 
             try {
                 let extension = ExtensionUtils.createExtensionObject(uuid, dir, 
ExtensionUtils.ExtensionType.PER_USER);
-                ExtensionSystem.loadExtension(extension);
+                Main.extensionManager.loadExtension(extension);
             } catch (e) {
                 uninstallExtension(uuid);
                 errback('LoadExtensionError', e);
diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js
index 3aeed1bd7..d5bc609ae 100644
--- a/js/ui/extensionSystem.js
+++ b/js/ui/extensionSystem.js
@@ -8,356 +8,351 @@ const Main = imports.ui.main;
 
 const { ExtensionState } = ExtensionUtils;
 
-// Arrays of uuids
-var enabledExtensions;
-// Contains the order that extensions were enabled in.
-var extensionOrder = [];
-
-// We don't really have a class to add signals on. So, create
-// a simple dummy object, add the signal methods, and export those
-// publically.
-var _signals = {};
-Signals.addSignalMethods(_signals);
-
-var connect = _signals.connect.bind(_signals);
-var disconnect = _signals.disconnect.bind(_signals);
-
 const ENABLED_EXTENSIONS_KEY = 'enabled-extensions';
 const DISABLE_USER_EXTENSIONS_KEY = 'disable-user-extensions';
 const EXTENSION_DISABLE_VERSION_CHECK_KEY = 'disable-extension-version-validation';
 
-var initted = false;
-var enabled;
+var ExtensionManager = class {
+    constructor() {
+        this._initted = false;
+        this._enabled = false;
 
-function disableExtension(uuid) {
-    let extension = ExtensionUtils.extensions[uuid];
-    if (!extension)
-        return;
+        this._enabledExtensions = [];
+        this._extensionOrder = [];
 
-    if (extension.state != ExtensionState.ENABLED)
-        return;
+        Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
+        this._sessionUpdated();
+    }
 
-    // "Rebase" the extension order by disabling and then enabling extensions
-    // in order to help prevent conflicts.
+    disableExtension(uuid) {
+        let extension = ExtensionUtils.extensions[uuid];
+        if (!extension)
+            return;
 
-    // Example:
-    //   order = [A, B, C, D, E]
-    //   user disables C
-    //   this should: disable E, disable D, disable C, enable D, enable E
+        if (extension.state != ExtensionState.ENABLED)
+            return;
 
-    let orderIdx = extensionOrder.indexOf(uuid);
-    let order = extensionOrder.slice(orderIdx + 1);
-    let orderReversed = order.slice().reverse();
+        // "Rebase" the extension order by disabling and then enabling extensions
+        // in order to help prevent conflicts.
+
+        // Example:
+        //   order = [A, B, C, D, E]
+        //   user disables C
+        //   this should: disable E, disable D, disable C, enable D, enable E
+
+        let orderIdx = this._extensionOrder.indexOf(uuid);
+        let order = this._extensionOrder.slice(orderIdx + 1);
+        let orderReversed = order.slice().reverse();
+
+        for (let i = 0; i < orderReversed.length; i++) {
+            let uuid = orderReversed[i];
+            try {
+                ExtensionUtils.extensions[uuid].stateObj.disable();
+            } catch (e) {
+                this.logExtensionError(uuid, e);
+            }
+        }
+
+        if (extension.stylesheet) {
+            let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
+            theme.unload_stylesheet(extension.stylesheet);
+            delete extension.stylesheet;
+        }
 
-    for (let i = 0; i < orderReversed.length; i++) {
-        let uuid = orderReversed[i];
         try {
-            ExtensionUtils.extensions[uuid].stateObj.disable();
+            extension.stateObj.disable();
         } catch (e) {
-            logExtensionError(uuid, e);
+            this.logExtensionError(uuid, e);
         }
-    }
 
-    if (extension.stylesheet) {
-        let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
-        theme.unload_stylesheet(extension.stylesheet);
-        delete extension.stylesheet;
-    }
+        for (let i = 0; i < order.length; i++) {
+            let uuid = order[i];
+            try {
+                ExtensionUtils.extensions[uuid].stateObj.enable();
+            } catch (e) {
+                this.logExtensionError(uuid, e);
+            }
+        }
 
-    try {
-        extension.stateObj.disable();
-    } catch (e) {
-        logExtensionError(uuid, e);
-    }
+        this._extensionOrder.splice(orderIdx, 1);
 
-    for (let i = 0; i < order.length; i++) {
-        let uuid = order[i];
-        try {
-            ExtensionUtils.extensions[uuid].stateObj.enable();
-        } catch (e) {
-            logExtensionError(uuid, e);
+        if (extension.state != ExtensionState.ERROR) {
+            extension.state = ExtensionState.DISABLED;
+            this.emit('extension-state-changed', extension);
         }
     }
 
-    extensionOrder.splice(orderIdx, 1);
-
-    if ( extension.state != ExtensionState.ERROR ) {
-        extension.state = ExtensionState.DISABLED;
-        _signals.emit('extension-state-changed', extension);
-    }
-}
+    enableExtension(uuid) {
+        let extension = ExtensionUtils.extensions[uuid];
+        if (!extension)
+            return;
 
-function enableExtension(uuid) {
-    let extension = ExtensionUtils.extensions[uuid];
-    if (!extension)
-        return;
+        if (extension.state == ExtensionState.INITIALIZED)
+            this.initExtension(uuid);
 
-    if (extension.state == ExtensionState.INITIALIZED)
-        initExtension(uuid);
+        if (extension.state != ExtensionState.DISABLED)
+            return;
 
-    if (extension.state != ExtensionState.DISABLED)
-        return;
+        this._extensionOrder.push(uuid);
 
-    extensionOrder.push(uuid);
+        let stylesheetNames = [`${global.session_mode}.css`, 'stylesheet.css'];
+        let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
+        for (let i = 0; i < stylesheetNames.length; i++) {
+            try {
+                let stylesheetFile = extension.dir.get_child(stylesheetNames[i]);
+                theme.load_stylesheet(stylesheetFile);
+                extension.stylesheet = stylesheetFile;
+                break;
+            } catch (e) {
+                if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
+                    continue; // not an error
+                log(`Failed to load stylesheet for extension ${uuid}: ${e.message}`);
+                return;
+            }
+        }
 
-    let stylesheetNames = [`${global.session_mode}.css`, 'stylesheet.css'];
-    let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
-    for (let i = 0; i < stylesheetNames.length; i++) {
         try {
-            let stylesheetFile = extension.dir.get_child(stylesheetNames[i]);
-            theme.load_stylesheet(stylesheetFile);
-            extension.stylesheet = stylesheetFile;
-            break;
+            extension.stateObj.enable();
+            extension.state = ExtensionState.ENABLED;
+            this.emit('extension-state-changed', extension);
+            return;
         } catch (e) {
-            if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
-                continue; // not an error
-            log(`Failed to load stylesheet for extension ${uuid}: ${e.message}`);
+            if (extension.stylesheet) {
+                theme.unload_stylesheet(extension.stylesheet);
+                delete extension.stylesheet;
+            }
+            this.logExtensionError(uuid, e);
             return;
         }
     }
 
-    try {
-        extension.stateObj.enable();
-        extension.state = ExtensionState.ENABLED;
-        _signals.emit('extension-state-changed', extension);
-        return;
-    } catch (e) {
-        if (extension.stylesheet) {
-            theme.unload_stylesheet(extension.stylesheet);
-            delete extension.stylesheet;
-        }
-        logExtensionError(uuid, e);
-        return;
-    }
-}
-
-function logExtensionError(uuid, error) {
-    let extension = ExtensionUtils.extensions[uuid];
-    if (!extension)
-        return;
+    logExtensionError(uuid, error) {
+        let extension = ExtensionUtils.extensions[uuid];
+        if (!extension)
+            return;
 
-    let message = `${error}`;
+        let message = `${error}`;
 
-    extension.state = ExtensionState.ERROR;
-    if (!extension.errors)
-        extension.errors = [];
-    extension.errors.push(message);
+        extension.state = ExtensionState.ERROR;
+        if (!extension.errors)
+            extension.errors = [];
+        extension.errors.push(message);
 
-    log('Extension "%s" had error: %s'.format(uuid, message));
-    _signals.emit('extension-state-changed', { uuid: uuid,
+        log('Extension "%s" had error: %s'.format(uuid, message));
+        this.emit('extension-state-changed', { uuid: uuid,
                                                error: message,
                                                state: extension.state });
-}
+    }
 
-function loadExtension(extension) {
-    // Default to error, we set success as the last step
-    extension.state = ExtensionState.ERROR;
+    loadExtension(extension) {
+        // Default to error, we set success as the last step
+        extension.state = ExtensionState.ERROR;
 
-    let checkVersion = !global.settings.get_boolean(EXTENSION_DISABLE_VERSION_CHECK_KEY);
+        let checkVersion = !global.settings.get_boolean(EXTENSION_DISABLE_VERSION_CHECK_KEY);
 
-    if (checkVersion && ExtensionUtils.isOutOfDate(extension)) {
-        extension.state = ExtensionState.OUT_OF_DATE;
-    } else {
-        let enabled = enabledExtensions.includes(extension.uuid);
-        if (enabled) {
-            if (!initExtension(extension.uuid))
-                return;
-            if (extension.state == ExtensionState.DISABLED)
-                enableExtension(extension.uuid);
+        if (checkVersion && ExtensionUtils.isOutOfDate(extension)) {
+            extension.state = ExtensionState.OUT_OF_DATE;
         } else {
-            extension.state = ExtensionState.INITIALIZED;
+            let enabled = this._enabledExtensions.includes(extension.uuid);
+            if (enabled) {
+                if (!this.initExtension(extension.uuid))
+                    return;
+                if (extension.state == ExtensionState.DISABLED)
+                    this.enableExtension(extension.uuid);
+            } else {
+                extension.state = ExtensionState.INITIALIZED;
+            }
         }
+
+        this.emit('extension-state-changed', extension);
     }
 
-    _signals.emit('extension-state-changed', extension);
-}
-
-function unloadExtension(extension) {
-    // Try to disable it -- if it's ERROR'd, we can't guarantee that,
-    // but it will be removed on next reboot, and hopefully nothing
-    // broke too much.
-    disableExtension(extension.uuid);
-
-    extension.state = ExtensionState.UNINSTALLED;
-    _signals.emit('extension-state-changed', extension);
-
-    delete ExtensionUtils.extensions[extension.uuid];
-    return true;
-}
-
-function reloadExtension(oldExtension) {
-    // Grab the things we'll need to pass to createExtensionObject
-    // to reload it.
-    let { uuid: uuid, dir: dir, type: type } = oldExtension;
-
-    // Then unload the old extension.
-    unloadExtension(oldExtension);
-
-    // Now, recreate the extension and load it.
-    let newExtension;
-    try {
-        newExtension = ExtensionUtils.createExtensionObject(uuid, dir, type);
-    } catch (e) {
-        logExtensionError(uuid, e);
-        return;
+    unloadExtension(extension) {
+        // Try to disable it -- if it's ERROR'd, we can't guarantee that,
+        // but it will be removed on next reboot, and hopefully nothing
+        // broke too much.
+        this.disableExtension(extension.uuid);
+
+        extension.state = ExtensionState.UNINSTALLED;
+        this.emit('extension-state-changed', extension);
+
+        delete ExtensionUtils.extensions[extension.uuid];
+        return true;
     }
 
-    loadExtension(newExtension);
-}
+    reloadExtension(oldExtension) {
+        // Grab the things we'll need to pass to createExtensionObject
+        // to reload it.
+        let { uuid: uuid, dir: dir, type: type } = oldExtension;
 
-function initExtension(uuid) {
-    let extension = ExtensionUtils.extensions[uuid];
-    let dir = extension.dir;
+        // Then unload the old extension.
+        this.unloadExtension(oldExtension);
 
-    if (!extension)
-        throw new Error("Extension was not properly created. Call loadExtension first");
+        // Now, recreate the extension and load it.
+        let newExtension;
+        try {
+            newExtension = ExtensionUtils.createExtensionObject(uuid, dir, type);
+        } catch (e) {
+            this.logExtensionError(uuid, e);
+            return;
+        }
 
-    let extensionJs = dir.get_child('extension.js');
-    if (!extensionJs.query_exists(null)) {
-        logExtensionError(uuid, new Error('Missing extension.js'));
-        return false;
+        this.loadExtension(newExtension);
     }
 
-    let extensionModule;
-    let extensionState = null;
+    initExtension(uuid) {
+        let extension = ExtensionUtils.extensions[uuid];
+        let dir = extension.dir;
 
-    ExtensionUtils.installImporter(extension);
-    try {
-        extensionModule = extension.imports.extension;
-    } catch (e) {
-        logExtensionError(uuid, e);
-        return false;
-    }
+        if (!extension)
+            throw new Error("Extension was not properly created. Call loadExtension first");
+
+        let extensionJs = dir.get_child('extension.js');
+        if (!extensionJs.query_exists(null)) {
+            this.logExtensionError(uuid, new Error('Missing extension.js'));
+            return false;
+        }
+
+        let extensionModule;
+        let extensionState = null;
 
-    if (extensionModule.init) {
+        ExtensionUtils.installImporter(extension);
         try {
-            extensionState = extensionModule.init(extension);
+            extensionModule = extension.imports.extension;
         } catch (e) {
-            logExtensionError(uuid, e);
+            this.logExtensionError(uuid, e);
             return false;
         }
+
+        if (extensionModule.init) {
+            try {
+                extensionState = extensionModule.init(extension);
+            } catch (e) {
+                this.logExtensionError(uuid, e);
+                return false;
+            }
+        }
+
+        if (!extensionState)
+            extensionState = extensionModule;
+        extension.stateObj = extensionState;
+
+        extension.state = ExtensionState.DISABLED;
+        this.emit('extension-loaded', uuid);
+        return true;
     }
 
-    if (!extensionState)
-        extensionState = extensionModule;
-    extension.stateObj = extensionState;
-
-    extension.state = ExtensionState.DISABLED;
-    _signals.emit('extension-loaded', uuid);
-    return true;
-}
-
-function getEnabledExtensions() {
-    let extensions;
-    if (Array.isArray(Main.sessionMode.enabledExtensions))
-        extensions = Main.sessionMode.enabledExtensions;
-    else
-        extensions = [];
-
-    if (global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY))
-        return extensions;
-
-    return extensions.concat(global.settings.get_strv(ENABLED_EXTENSIONS_KEY));
-}
-
-function onEnabledExtensionsChanged() {
-    let newEnabledExtensions = getEnabledExtensions();
-
-    if (!enabled)
-        return;
-
-    // Find and enable all the newly enabled extensions: UUIDs found in the
-    // new setting, but not in the old one.
-    newEnabledExtensions.filter(
-        uuid => !enabledExtensions.includes(uuid)
-    ).forEach(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(
-        item => !newEnabledExtensions.includes(item)
-    ).forEach(uuid => {
-        disableExtension(uuid);
-    });
-
-    enabledExtensions = newEnabledExtensions;
-}
-
-function _onVersionValidationChanged() {
-    // we want to reload all extensions, but only enable
-    // extensions when allowed by the sessionMode, so
-    // temporarily disable them all
-    enabledExtensions = [];
-    for (let uuid in ExtensionUtils.extensions)
-        reloadExtension(ExtensionUtils.extensions[uuid]);
-    enabledExtensions = getEnabledExtensions();
-
-    if (Main.sessionMode.allowExtensions) {
-        enabledExtensions.forEach(uuid => {
-            enableExtension(uuid);
-        });
+    _getEnabledExtensions() {
+        let extensions;
+        if (Array.isArray(Main.sessionMode.enabledExtensions))
+            extensions = Main.sessionMode.enabledExtensions;
+        else
+            extensions = [];
+
+        if (global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY))
+            return extensions;
+
+        return extensions.concat(global.settings.get_strv(ENABLED_EXTENSIONS_KEY));
     }
-}
-
-function _loadExtensions() {
-    global.settings.connect(`changed::${ENABLED_EXTENSIONS_KEY}`, onEnabledExtensionsChanged);
-    global.settings.connect(`changed::${DISABLE_USER_EXTENSIONS_KEY}`, onEnabledExtensionsChanged);
-    global.settings.connect(`changed::${EXTENSION_DISABLE_VERSION_CHECK_KEY}`, _onVersionValidationChanged);
-
-    enabledExtensions = getEnabledExtensions();
-
-    let finder = new ExtensionUtils.ExtensionFinder();
-    finder.connect('extension-found', (finder, extension) => {
-        loadExtension(extension);
-    });
-    finder.scanExtensions();
-}
-
-function enableAllExtensions() {
-    if (enabled)
-        return;
-
-    if (!initted) {
-        _loadExtensions();
-        initted = true;
-    } else {
-        enabledExtensions.forEach(uuid => {
-            enableExtension(uuid);
+
+    _onEnabledExtensionsChanged() {
+        let newEnabledExtensions = this._getEnabledExtensions();
+
+        if (!this._enabled)
+            return;
+
+        // Find and enable all the newly enabled extensions: UUIDs found in the
+        // new setting, but not in the old one.
+        newEnabledExtensions.filter(
+            uuid => !this._enabledExtensions.includes(uuid)
+        ).forEach(uuid => {
+            this.enableExtension(uuid);
         });
+
+        // Find and disable all the newly disabled extensions: UUIDs found in the
+        // old setting, but not in the new one.
+        this._enabledExtensions.filter(
+            item => !newEnabledExtensions.includes(item)
+        ).forEach(uuid => {
+            this.disableExtension(uuid);
+        });
+
+        this._enabledExtensions = newEnabledExtensions;
+    }
+
+    _onVersionValidationChanged() {
+        // we want to reload all extensions, but only enable
+        // extensions when allowed by the sessionMode, so
+        // temporarily disable them all
+        this._enabledExtensions = [];
+        for (let uuid in ExtensionUtils.extensions)
+            this.reloadExtension(ExtensionUtils.extensions[uuid]);
+        this._enabledExtensions = this._getEnabledExtensions();
+
+        if (Main.sessionMode.allowExtensions) {
+            this._enabledExtensions.forEach(uuid => {
+                this.enableExtension(uuid);
+            });
+        }
     }
-    enabled = true;
-}
 
-function disableAllExtensions() {
-    if (!enabled)
-        return;
+    _loadExtensions() {
+        global.settings.connect(`changed::${ENABLED_EXTENSIONS_KEY}`,
+            this._onEnabledExtensionsChanged.bind(this));
+        global.settings.connect(`changed::${DISABLE_USER_EXTENSIONS_KEY}`,
+            this._onEnabledExtensionsChanged.bind(this));
+        global.settings.connect(`changed::${EXTENSION_DISABLE_VERSION_CHECK_KEY}`,
+            this._onVersionValidationChanged.bind(this));
+
+        this._enabledExtensions = this._getEnabledExtensions();
 
-    if (initted) {
-        extensionOrder.slice().reverse().forEach(uuid => {
-            disableExtension(uuid);
+        let finder = new ExtensionUtils.ExtensionFinder();
+        finder.connect('extension-found', (finder, extension) => {
+            this.loadExtension(extension);
         });
+        finder.scanExtensions();
+    }
+
+    enableAllExtensions() {
+        if (this._enabled)
+            return;
+
+        if (!this._initted) {
+            this._loadExtensions();
+            this._initted = true;
+        } else {
+            this._enabledExtensions.forEach(uuid => {
+                this.enableExtension(uuid);
+            });
+        }
+        this._enabled = true;
     }
 
-    enabled = false;
-}
-
-function _sessionUpdated() {
-    // For now sessionMode.allowExtensions controls extensions from both the
-    // 'enabled-extensions' preference and the sessionMode.enabledExtensions
-    // property; it might make sense to make enabledExtensions independent
-    // from allowExtensions in the future
-    if (Main.sessionMode.allowExtensions) {
-        if (initted)
-            enabledExtensions = getEnabledExtensions();
-        enableAllExtensions();
-    } else {
-        disableAllExtensions();
+    disableAllExtensions() {
+        if (!this._enabled)
+            return;
+
+        if (this._initted) {
+            this._extensionOrder.slice().reverse().forEach(uuid => {
+                this.disableExtension(uuid);
+            });
+        }
+
+        this._enabled = false;
     }
-}
 
-function init() {
-    Main.sessionMode.connect('updated', _sessionUpdated);
-    _sessionUpdated();
-}
+    _sessionUpdated() {
+        // For now sessionMode.allowExtensions controls extensions from both the
+        // 'enabled-extensions' preference and the sessionMode.enabledExtensions
+        // property; it might make sense to make enabledExtensions independent
+        // from allowExtensions in the future
+        if (Main.sessionMode.allowExtensions) {
+            if (this._initted)
+                this._enabledExtensions = this._getEnabledExtensions();
+            this.enableAllExtensions();
+        } else {
+            this.disableAllExtensions();
+        }
+    }
+};
+Signals.addSignalMethods(ExtensionManager.prototype);
diff --git a/js/ui/lookingGlass.js b/js/ui/lookingGlass.js
index f15988e6b..9aeeaceb4 100644
--- a/js/ui/lookingGlass.js
+++ b/js/ui/lookingGlass.js
@@ -7,7 +7,6 @@ const Signals = imports.signals;
 const System = imports.system;
 
 const History = imports.misc.history;
-const ExtensionSystem = imports.ui.extensionSystem;
 const ExtensionUtils = imports.misc.extensionUtils;
 const ShellEntry = imports.ui.shellEntry;
 const Tweener = imports.ui.tweener;
@@ -628,8 +627,8 @@ var Extensions = class Extensions {
         for (let uuid in ExtensionUtils.extensions)
             this._loadExtension(null, uuid);
 
-        ExtensionSystem.connect('extension-loaded',
-                                this._loadExtension.bind(this));
+        Main.extensionManager.connect('extension-loaded',
+                                      this._loadExtension.bind(this));
     }
 
     _loadExtension(o, uuid) {
diff --git a/js/ui/main.js b/js/ui/main.js
index bd522973f..1566d2fe1 100644
--- a/js/ui/main.js
+++ b/js/ui/main.js
@@ -46,6 +46,7 @@ const LOG_DOMAIN = 'GNOME Shell';
 const GNOMESHELL_STARTED_MESSAGE_ID = 'f3ea493c22934e26811cd62abe8e203a';
 
 var componentManager = null;
+var extensionManager = null;
 var panel = null;
 var overview = null;
 var runDialog = null;
@@ -226,7 +227,7 @@ function _initializeUI() {
     _startDate = new Date();
 
     ExtensionDownloader.init();
-    ExtensionSystem.init();
+    extensionManager = new ExtensionSystem.ExtensionManager();
 
     if (sessionMode.isGreeter && screenShield) {
         layoutManager.connect('startup-prepared', () => {
diff --git a/js/ui/shellDBus.js b/js/ui/shellDBus.js
index 1db5f551c..7976eeaae 100644
--- a/js/ui/shellDBus.js
+++ b/js/ui/shellDBus.js
@@ -4,7 +4,6 @@ const { Gio, GLib, Meta, Shell } = imports.gi;
 const Lang = imports.lang;
 
 const Config = imports.misc.config;
-const ExtensionSystem = imports.ui.extensionSystem;
 const ExtensionDownloader = imports.ui.extensionDownloader;
 const ExtensionUtils = imports.misc.extensionUtils;
 const Main = imports.ui.main;
@@ -251,8 +250,8 @@ var GnomeShellExtensions = class {
     constructor() {
         this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(GnomeShellExtensionsIface, this);
         this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell');
-        ExtensionSystem.connect('extension-state-changed',
-                                this._extensionStateChanged.bind(this));
+        Main.extensionManager.connect('extension-state-changed',
+                                      this._extensionStateChanged.bind(this));
     }
 
     ListExtensions() {
@@ -335,7 +334,7 @@ var GnomeShellExtensions = class {
         if (!extension)
             return;
 
-        ExtensionSystem.reloadExtension(extension);
+        Main.extensionManager.reloadExtension(extension);
     }
 
     CheckForUpdates() {


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