[gnome-shell] extensionSystem: Move extension loading into ExtensionManager



commit 1d6ddf060b8672481eda6d673d064b9cdc2bb1ba
Author: Florian Müllner <fmuellner gnome org>
Date:   Sun Jul 7 23:38:27 2019 +0200

    extensionSystem: Move extension loading into ExtensionManager
    
    Now that extension loading and the extensions map are no longer shared
    between the gnome-shell and gnome-shell-extension-prefs processes, we
    can move both into the ExtensionManager which makes much more sense
    conceptually.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=789852

 js/misc/extensionUtils.js    |  93 ++----------------------------------
 js/ui/extensionDownloader.js |  12 ++---
 js/ui/extensionSystem.js     | 110 ++++++++++++++++++++++++++++++++++++-------
 js/ui/lookingGlass.js        |   4 +-
 js/ui/main.js                |   1 +
 js/ui/shellDBus.js           |   8 ++--
 6 files changed, 111 insertions(+), 117 deletions(-)
---
diff --git a/js/misc/extensionUtils.js b/js/misc/extensionUtils.js
index 96431b1f2..d17aee9fb 100644
--- a/js/misc/extensionUtils.js
+++ b/js/misc/extensionUtils.js
@@ -7,10 +7,8 @@ const { Gio, GLib } = imports.gi;
 
 const Gettext = imports.gettext;
 const Lang = imports.lang;
-const Signals = imports.signals;
 
 const Config = imports.misc.config;
-const FileUtils = imports.misc.fileUtils;
 
 var ExtensionType = {
     SYSTEM: 1,
@@ -32,9 +30,6 @@ var ExtensionState = {
 
 const SERIALIZED_PROPERTIES = ['type', 'state', 'path', 'error', 'hasPrefs', 'canChange'];
 
-// Maps uuid -> metadata object
-var extensions = {};
-
 /**
  * getCurrentExtension:
  *
@@ -65,13 +60,17 @@ function getCurrentExtension() {
     if (!match)
         return null;
 
+    // local import, as the module is used from outside the gnome-shell process
+    // as well (not this function though)
+    let extensionManager = imports.ui.main.extensionManager;
+
     let path = match[1];
     let file = Gio.File.new_for_path(path);
 
     // Walk up the directory tree, looking for an extension with
     // the same UUID as a directory name.
     while (file != null) {
-        let extension = extensions[file.get_basename()];
+        let extension = extensionManager.extensions[file.get_basename()];
         if (extension !== undefined)
             return extension;
         file = file.get_parent();
@@ -177,55 +176,6 @@ function isOutOfDate(extension) {
     return false;
 }
 
-function createExtensionObject(uuid, dir, type) {
-    let metadataFile = dir.get_child('metadata.json');
-    if (!metadataFile.query_exists(null)) {
-        throw new Error('Missing metadata.json');
-    }
-
-    let metadataContents, success, tag;
-    try {
-        [success, metadataContents, tag] = metadataFile.load_contents(null);
-        if (metadataContents instanceof Uint8Array)
-            metadataContents = imports.byteArray.toString(metadataContents);
-    } catch (e) {
-        throw new Error(`Failed to load metadata.json: ${e}`);
-    }
-    let meta;
-    try {
-        meta = JSON.parse(metadataContents);
-    } catch (e) {
-        throw new Error(`Failed to parse metadata.json: ${e}`);
-    }
-
-    let requiredProperties = ['uuid', 'name', 'description', 'shell-version'];
-    for (let i = 0; i < requiredProperties.length; i++) {
-        let prop = requiredProperties[i];
-        if (!meta[prop]) {
-            throw new Error(`missing "${prop}" property in metadata.json`);
-        }
-    }
-
-    if (uuid != meta.uuid) {
-        throw new Error(`uuid "${meta.uuid}" from metadata.json does not match directory name "${uuid}"`);
-    }
-
-    let extension = {};
-
-    extension.metadata = meta;
-    extension.uuid = meta.uuid;
-    extension.type = type;
-    extension.dir = dir;
-    extension.path = dir.get_path();
-    extension.error = '';
-    extension.hasPrefs = dir.get_child('prefs.js').query_exists(null);
-    extension.canChange = false;
-
-    extensions[uuid] = extension;
-
-    return extension;
-}
-
 function serializeExtension(extension) {
     let obj = {};
     Lang.copyProperties(extension.metadata, obj);
@@ -280,36 +230,3 @@ function installImporter(extension) {
     extension.imports = imports[extension.uuid];
     imports.searchPath = oldSearchPath;
 }
-
-var ExtensionFinder = class {
-    _loadExtension(extensionDir, info, perUserDir) {
-        let fileType = info.get_file_type();
-        if (fileType != Gio.FileType.DIRECTORY)
-            return;
-        let uuid = info.get_name();
-        let existing = extensions[uuid];
-        if (existing) {
-            log('Extension %s already installed in %s. %s will not be loaded'.format(uuid, existing.path, 
extensionDir.get_path()));
-            return;
-        }
-
-        let extension;
-        let type = extensionDir.has_prefix(perUserDir) ? ExtensionType.PER_USER
-                                                       : ExtensionType.SYSTEM;
-        try {
-            extension = createExtensionObject(uuid, extensionDir, type);
-        } catch (e) {
-            logError(e, 'Could not load extension %s'.format(uuid));
-            return;
-        }
-        this.emit('extension-found', extension);
-    }
-
-    scanExtensions() {
-        let perUserDir = Gio.File.new_for_path(global.userdatadir);
-        FileUtils.collectFromDatadirs('extensions', true, (dir, info) => {
-            this._loadExtension(dir, info, perUserDir);
-        });
-    }
-};
-Signals.addSignalMethods(ExtensionFinder.prototype);
diff --git a/js/ui/extensionDownloader.js b/js/ui/extensionDownloader.js
index aa5d7b94d..ca9de0e18 100644
--- a/js/ui/extensionDownloader.js
+++ b/js/ui/extensionDownloader.js
@@ -44,7 +44,7 @@ function installExtension(uuid, invocation) {
 }
 
 function uninstallExtension(uuid) {
-    let extension = ExtensionUtils.extensions[uuid];
+    let extension = Main.extensionManager.extensions[uuid];
     if (!extension)
         return false;
 
@@ -113,7 +113,7 @@ function updateExtension(uuid) {
 
     _httpSession.queue_message(message, (session, message) => {
         gotExtensionZipFile(session, message, uuid, newExtensionTmpDir, () => {
-            let oldExtension = ExtensionUtils.extensions[uuid];
+            let oldExtension = Main.extensionManager.extensions[uuid];
             let extensionDir = oldExtension.dir;
 
             if (!Main.extensionManager.unloadExtension(oldExtension))
@@ -125,7 +125,7 @@ function updateExtension(uuid) {
             let extension = null;
 
             try {
-                extension = ExtensionUtils.createExtensionObject(uuid, extensionDir, 
ExtensionUtils.ExtensionType.PER_USER);
+                extension = Main.extensionManager.createExtensionObject(uuid, extensionDir, 
ExtensionUtils.ExtensionType.PER_USER);
                 Main.extensionManager.loadExtension(extension);
             } catch (e) {
                 if (extension)
@@ -151,8 +151,8 @@ function updateExtension(uuid) {
 
 function checkForUpdates() {
     let metadatas = {};
-    for (let uuid in ExtensionUtils.extensions) {
-        metadatas[uuid] = ExtensionUtils.extensions[uuid].metadata;
+    for (let uuid in Main.extensionManager.extensions) {
+        metadatas[uuid] = Main.extensionManager.extensions[uuid].metadata;
     }
 
     let params = { shell_version: Config.PACKAGE_VERSION,
@@ -225,7 +225,7 @@ class InstallExtensionDialog extends ModalDialog.ModalDialog {
 
         function callback() {
             try {
-                let extension = ExtensionUtils.createExtensionObject(uuid, dir, 
ExtensionUtils.ExtensionType.PER_USER);
+                let extension = Main.extensionManager.createExtensionObject(uuid, dir, 
ExtensionUtils.ExtensionType.PER_USER);
                 Main.extensionManager.loadExtension(extension);
                 if (!Main.extensionManager.enableExtension(uuid))
                     throw new Error(`Cannot add ${uuid} to enabled extensions gsettings key`);
diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js
index 6d842dc16..ba1d12a4e 100644
--- a/js/ui/extensionSystem.js
+++ b/js/ui/extensionSystem.js
@@ -4,9 +4,10 @@ const { Gio, St } = imports.gi;
 const Signals = imports.signals;
 
 const ExtensionUtils = imports.misc.extensionUtils;
+const FileUtils = imports.misc.fileUtils;
 const Main = imports.ui.main;
 
-const { ExtensionState } = ExtensionUtils;
+const { ExtensionState, ExtensionType } = ExtensionUtils;
 
 const ENABLED_EXTENSIONS_KEY = 'enabled-extensions';
 const DISABLE_USER_EXTENSIONS_KEY = 'disable-user-extensions';
@@ -17,15 +18,23 @@ var ExtensionManager = class {
         this._initted = false;
         this._enabled = false;
 
+        this._extensions = {};
         this._enabledExtensions = [];
         this._extensionOrder = [];
 
         Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
+    }
+
+    init() {
         this._sessionUpdated();
     }
 
+    get extensions() {
+        return this._extensions;
+    }
+
     _callExtensionDisable(uuid) {
-        let extension = ExtensionUtils.extensions[uuid];
+        let extension = this._extensions[uuid];
         if (!extension)
             return;
 
@@ -47,7 +56,7 @@ var ExtensionManager = class {
         for (let i = 0; i < orderReversed.length; i++) {
             let uuid = orderReversed[i];
             try {
-                ExtensionUtils.extensions[uuid].stateObj.disable();
+                this._extensions[uuid].stateObj.disable();
             } catch (e) {
                 this.logExtensionError(uuid, e);
             }
@@ -68,7 +77,7 @@ var ExtensionManager = class {
         for (let i = 0; i < order.length; i++) {
             let uuid = order[i];
             try {
-                ExtensionUtils.extensions[uuid].stateObj.enable();
+                this._extensions[uuid].stateObj.enable();
             } catch (e) {
                 this.logExtensionError(uuid, e);
             }
@@ -83,7 +92,7 @@ var ExtensionManager = class {
     }
 
     _callExtensionEnable(uuid) {
-        let extension = ExtensionUtils.extensions[uuid];
+        let extension = this._extensions[uuid];
         if (!extension)
             return;
 
@@ -127,7 +136,7 @@ var ExtensionManager = class {
     }
 
     enableExtension(uuid) {
-        if (!ExtensionUtils.extensions[uuid])
+        if (!this._extensions[uuid])
             return false;
 
         let enabledExtensions = global.settings.get_strv(ENABLED_EXTENSIONS_KEY);
@@ -140,7 +149,7 @@ var ExtensionManager = class {
     }
 
     disableExtension(uuid) {
-        if (!ExtensionUtils.extensions[uuid])
+        if (!this._extensions[uuid])
             return false;
 
         let enabledExtensions = global.settings.get_strv(ENABLED_EXTENSIONS_KEY);
@@ -153,7 +162,7 @@ var ExtensionManager = class {
     }
 
     logExtensionError(uuid, error) {
-        let extension = ExtensionUtils.extensions[uuid];
+        let extension = this._extensions[uuid];
         if (!extension)
             return;
 
@@ -169,6 +178,54 @@ var ExtensionManager = class {
         this.emit('extension-state-changed', extension);
     }
 
+    createExtensionObject(uuid, dir, type) {
+        let metadataFile = dir.get_child('metadata.json');
+        if (!metadataFile.query_exists(null)) {
+            throw new Error('Missing metadata.json');
+        }
+
+        let metadataContents, success;
+        try {
+            [success, metadataContents] = metadataFile.load_contents(null);
+            if (metadataContents instanceof Uint8Array)
+                metadataContents = imports.byteArray.toString(metadataContents);
+        } catch (e) {
+            throw new Error(`Failed to load metadata.json: ${e}`);
+        }
+        let meta;
+        try {
+            meta = JSON.parse(metadataContents);
+        } catch (e) {
+            throw new Error(`Failed to parse metadata.json: ${e}`);
+        }
+
+        let requiredProperties = ['uuid', 'name', 'description', 'shell-version'];
+        for (let i = 0; i < requiredProperties.length; i++) {
+            let prop = requiredProperties[i];
+            if (!meta[prop]) {
+                throw new Error(`missing "${prop}" property in metadata.json`);
+            }
+        }
+
+        if (uuid != meta.uuid) {
+            throw new Error(`uuid "${meta.uuid}" from metadata.json does not match directory name 
"${uuid}"`);
+        }
+
+        let extension = {
+            metadata: meta,
+            uuid: meta.uuid,
+            type,
+            dir,
+            path: dir.get_path(),
+            error: '',
+            hasPrefs: dir.get_child('prefs.js').query_exists(null),
+            canChange: false
+        };
+        this._extensions[uuid] = extension;
+
+        return extension;
+    }
+
     loadExtension(extension) {
         // Default to error, we set success as the last step
         extension.state = ExtensionState.ERROR;
@@ -202,7 +259,7 @@ var ExtensionManager = class {
         extension.state = ExtensionState.UNINSTALLED;
         this.emit('extension-state-changed', extension);
 
-        delete ExtensionUtils.extensions[extension.uuid];
+        delete this._extensions[extension.uuid];
         return true;
     }
 
@@ -217,7 +274,7 @@ var ExtensionManager = class {
         // Now, recreate the extension and load it.
         let newExtension;
         try {
-            newExtension = ExtensionUtils.createExtensionObject(uuid, dir, type);
+            newExtension = this.createExtensionObject(uuid, dir, type);
         } catch (e) {
             this.logExtensionError(uuid, e);
             return;
@@ -227,7 +284,7 @@ var ExtensionManager = class {
     }
 
     _callExtensionInit(uuid) {
-        let extension = ExtensionUtils.extensions[uuid];
+        let extension = this._extensions[uuid];
         let dir = extension.dir;
 
         if (!extension)
@@ -328,7 +385,7 @@ var ExtensionManager = class {
     }
 
     _onSettingsWritableChanged() {
-        for (let uuid in ExtensionUtils.extensions) {
+        for (let uuid in this._extensions) {
             let extension = ExtensionUtils.extensions[uuid];
             this._updateCanChange(extension);
             this.emit('extension-state-changed', extension);
@@ -340,8 +397,8 @@ var ExtensionManager = class {
         // extensions when allowed by the sessionMode, so
         // temporarily disable them all
         this._enabledExtensions = [];
-        for (let uuid in ExtensionUtils.extensions)
-            this.reloadExtension(ExtensionUtils.extensions[uuid]);
+        for (let uuid in this._extensions)
+            this.reloadExtension(this._extensions[uuid]);
         this._enabledExtensions = this._getEnabledExtensions();
 
         if (Main.sessionMode.allowExtensions) {
@@ -363,11 +420,30 @@ var ExtensionManager = class {
 
         this._enabledExtensions = this._getEnabledExtensions();
 
-        let finder = new ExtensionUtils.ExtensionFinder();
-        finder.connect('extension-found', (finder, extension) => {
+        let perUserDir = Gio.File.new_for_path(global.userdatadir);
+        FileUtils.collectFromDatadirs('extensions', true, (dir, info) => {
+            let fileType = info.get_file_type();
+            if (fileType != Gio.FileType.DIRECTORY)
+                return;
+            let uuid = info.get_name();
+            let existing = this._extensions[uuid];
+            if (existing) {
+                log(`Extension ${uuid} already installed in ${existing.path}. ${dir.get_path()} will not be 
loaded`);
+                return;
+            }
+
+            let extension;
+            let type = dir.has_prefix(perUserDir)
+                ? ExtensionType.PER_USER
+                : ExtensionType.SYSTEM;
+            try {
+                extension = this.createExtensionObject(uuid, dir, type);
+            } catch (e) {
+                logError(e, `Could not load extension ${uuid}`);
+                return;
+            }
             this.loadExtension(extension);
         });
-        finder.scanExtensions();
     }
 
     _enableAllExtensions() {
diff --git a/js/ui/lookingGlass.js b/js/ui/lookingGlass.js
index 9aeeaceb4..b99b701e1 100644
--- a/js/ui/lookingGlass.js
+++ b/js/ui/lookingGlass.js
@@ -624,7 +624,7 @@ var Extensions = class Extensions {
         this._extensionsList.add(this._noExtensions);
         this.actor.add(this._extensionsList);
 
-        for (let uuid in ExtensionUtils.extensions)
+        for (let uuid in Main.extensionManager.extensions)
             this._loadExtension(null, uuid);
 
         Main.extensionManager.connect('extension-loaded',
@@ -632,7 +632,7 @@ var Extensions = class Extensions {
     }
 
     _loadExtension(o, uuid) {
-        let extension = ExtensionUtils.extensions[uuid];
+        let extension = Main.extensionManager.extensions[uuid];
         // There can be cases where we create dummy extension metadata
         // that's not really a proper extension. Don't bother with these.
         if (!extension.metadata.name)
diff --git a/js/ui/main.js b/js/ui/main.js
index 1566d2fe1..2fd49962e 100644
--- a/js/ui/main.js
+++ b/js/ui/main.js
@@ -228,6 +228,7 @@ function _initializeUI() {
 
     ExtensionDownloader.init();
     extensionManager = new ExtensionSystem.ExtensionManager();
+    extensionManager.init();
 
     if (sessionMode.isGreeter && screenShield) {
         layoutManager.connect('startup-prepared', () => {
diff --git a/js/ui/shellDBus.js b/js/ui/shellDBus.js
index 424aef567..2288d0cfd 100644
--- a/js/ui/shellDBus.js
+++ b/js/ui/shellDBus.js
@@ -255,7 +255,7 @@ var GnomeShellExtensions = class {
 
     ListExtensions() {
         let out = {};
-        for (let uuid in ExtensionUtils.extensions) {
+        for (let uuid in Main.extensionManager.extensions) {
             let dbusObj = this.GetExtensionInfo(uuid);
             out[uuid] = dbusObj;
         }
@@ -263,12 +263,12 @@ var GnomeShellExtensions = class {
     }
 
     GetExtensionInfo(uuid) {
-        let extension = ExtensionUtils.extensions[uuid] || {};
+        let extension = Main.extensionManager.extensions[uuid] || {};
         return ExtensionUtils.serializeExtension(extension);
     }
 
     GetExtensionErrors(uuid) {
-        let extension = ExtensionUtils.extensions[uuid];
+        let extension = Main.extensionManager.extensions[uuid];
         if (!extension)
             return [];
 
@@ -304,7 +304,7 @@ var GnomeShellExtensions = class {
     }
 
     ReloadExtension(uuid) {
-        let extension = ExtensionUtils.extensions[uuid];
+        let extension = Main.extensionManager.extensions[uuid];
         if (!extension)
             return;
 


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