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); + } + + for (let i = 0; i < order.length; i++) { + let uuid = order[i]; + try { + ExtensionUtils.extensions[uuid].stateObj.enable(); + } catch (e) { + this.logExtensionError(uuid, e); + } + } + + this._extensionOrder.splice(orderIdx, 1); + + if (extension.state != ExtensionState.ERROR) { + extension.state = ExtensionState.DISABLED; + this.emit('extension-state-changed', extension); } } - if (extension.stylesheet) { + enableExtension(uuid) { + let extension = ExtensionUtils.extensions[uuid]; + if (!extension) + return; + + if (extension.state == ExtensionState.INITIALIZED) + this.initExtension(uuid); + + if (extension.state != ExtensionState.DISABLED) + return; + + this._extensionOrder.push(uuid); + + let stylesheetNames = [`${global.session_mode}.css`, 'stylesheet.css']; let theme = St.ThemeContext.get_for_stage(global.stage).get_theme(); - theme.unload_stylesheet(extension.stylesheet); - delete extension.stylesheet; - } - - try { - extension.stateObj.disable(); - } catch (e) { - logExtensionError(uuid, e); - } - - for (let i = 0; i < order.length; i++) { - let uuid = order[i]; - try { - ExtensionUtils.extensions[uuid].stateObj.enable(); - } catch (e) { - logExtensionError(uuid, e); + 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; + } } - } - extensionOrder.splice(orderIdx, 1); - - if ( extension.state != ExtensionState.ERROR ) { - extension.state = ExtensionState.DISABLED; - _signals.emit('extension-state-changed', extension); - } -} - -function enableExtension(uuid) { - let extension = ExtensionUtils.extensions[uuid]; - if (!extension) - return; - - if (extension.state == ExtensionState.INITIALIZED) - initExtension(uuid); - - if (extension.state != ExtensionState.DISABLED) - return; - - 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; + 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; - } -} + logExtensionError(uuid, error) { + let extension = ExtensionUtils.extensions[uuid]; + if (!extension) + return; -function 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); -} + 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); -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; + this.emit('extension-state-changed', extension); - 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; + 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"); - - let extensionJs = dir.get_child('extension.js'); - if (!extensionJs.query_exists(null)) { - logExtensionError(uuid, new Error('Missing extension.js')); - return false; - } - - let extensionModule; - let extensionState = null; - - ExtensionUtils.installImporter(extension); - try { - extensionModule = extension.imports.extension; - } catch (e) { - logExtensionError(uuid, e); - return false; - } - - if (extensionModule.init) { + // Now, recreate the extension and load it. + let newExtension; try { - extensionState = extensionModule.init(extension); + newExtension = ExtensionUtils.createExtensionObject(uuid, dir, type); } catch (e) { - logExtensionError(uuid, e); + this.logExtensionError(uuid, e); + return; + } + + this.loadExtension(newExtension); + } + + initExtension(uuid) { + let extension = ExtensionUtils.extensions[uuid]; + let dir = extension.dir; + + 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; + + ExtensionUtils.installImporter(extension); + try { + extensionModule = extension.imports.extension; + } catch (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; + _getEnabledExtensions() { + let extensions; + if (Array.isArray(Main.sessionMode.enabledExtensions)) + extensions = Main.sessionMode.enabledExtensions; + else + extensions = []; - extension.state = ExtensionState.DISABLED; - _signals.emit('extension-loaded', uuid); - return true; -} + if (global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY)) + return extensions; -function getEnabledExtensions() { - let extensions; - if (Array.isArray(Main.sessionMode.enabledExtensions)) - extensions = Main.sessionMode.enabledExtensions; - else - extensions = []; + return extensions.concat(global.settings.get_strv(ENABLED_EXTENSIONS_KEY)); + } - if (global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY)) - return extensions; + _onEnabledExtensionsChanged() { + let newEnabledExtensions = this._getEnabledExtensions(); - return extensions.concat(global.settings.get_strv(ENABLED_EXTENSIONS_KEY)); -} + if (!this._enabled) + return; -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); + // 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); }); - } -} -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); + // 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; } - enabled = true; -} -function disableAllExtensions() { - if (!enabled) - return; + _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 (initted) { - extensionOrder.slice().reverse().forEach(uuid => { - disableExtension(uuid); + if (Main.sessionMode.allowExtensions) { + this._enabledExtensions.forEach(uuid => { + this.enableExtension(uuid); + }); + } + } + + _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(); + + let finder = new ExtensionUtils.ExtensionFinder(); + finder.connect('extension-found', (finder, extension) => { + this.loadExtension(extension); }); + finder.scanExtensions(); } - enabled = false; -} + enableAllExtensions() { + if (this._enabled) + return; -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(); + if (!this._initted) { + this._loadExtensions(); + this._initted = true; + } else { + this._enabledExtensions.forEach(uuid => { + this.enableExtension(uuid); + }); + } + this._enabled = true; } -} -function init() { - Main.sessionMode.connect('updated', _sessionUpdated); - _sessionUpdated(); -} + disableAllExtensions() { + if (!this._enabled) + return; + + if (this._initted) { + this._extensionOrder.slice().reverse().forEach(uuid => { + this.disableExtension(uuid); + }); + } + + this._enabled = false; + } + + _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() {