X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=common%2Fbootstrap.js;h=a5b25deb4d640ea7d1432f9993385e81caf76530;hb=refs%2Fheads%2Fupstream;hp=4d5dcca634a9e863b5afeebe2ab5fb48e325b6e5;hpb=354a049cce8415487552ce405cce167b7071fe1f;p=dactyl.git diff --git a/common/bootstrap.js b/common/bootstrap.js index 4d5dcca..a5b25de 100755 --- a/common/bootstrap.js +++ b/common/bootstrap.js @@ -1,4 +1,4 @@ -// Copyright (c) 2010-2011 by Kris Maglione +// Copyright (c) 2010-2014 by Kris Maglione // // This work is licensed for reuse under an MIT license. Details are // given in the LICENSE.txt file included with this file. @@ -21,6 +21,8 @@ var { AddonManager } = module("resource://gre/modules/AddonManager.jsm"); var { XPCOMUtils } = module("resource://gre/modules/XPCOMUtils.jsm"); var { Services } = module("resource://gre/modules/Services.jsm"); +var Timer = Components.Constructor("@mozilla.org/timer;1", "nsITimer", "initWithCallback"); + const resourceProto = Services.io.getProtocolHandler("resource") .QueryInterface(Ci.nsIResProtocolHandler); const categoryManager = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager); @@ -57,13 +59,11 @@ let addonData = null; let basePath = null; let bootstrap; let bootstrap_jsm; -let categories = []; let components = {}; -let resources = []; let getURI = null; let JSMLoader = { - SANDBOX: Cu.nukeSandbox && false, + SANDBOX: Cu.nukeSandbox, get addon() addon, @@ -134,7 +134,7 @@ let JSMLoader = { return this.modules[name] = this.globals[uri]; this.globals[uri] = this.modules[name]; - bootstrap_jsm.loadSubScript(url, this.modules[name]); + bootstrap_jsm.loadSubScript(url, this.modules[name], "UTF-8"); return; } catch (e) { @@ -172,7 +172,17 @@ let JSMLoader = { let module = this.modules[name]; if (target) for each (let symbol in module.EXPORTED_SYMBOLS) - target[symbol] = module[symbol]; + try { + Object.defineProperty(target, symbol, { + configurable: true, + enumerable: true, + writable: true, + value: module[symbol] + }); + } + catch (e) { + target[symbol] = module[symbol]; + } return module; }, @@ -180,8 +190,8 @@ let JSMLoader = { // Cuts down on stupid, fscking url mangling. get loadSubScript() bootstrap_jsm.loadSubScript, - cleanup: function unregister() { - for each (let factory in this.factories.splice(0)) + cleanup: function cleanup() { + for (let factory of this.factories.splice(0)) manager.unregisterFactory(factory.classID, factory); }, @@ -215,35 +225,29 @@ let JSMLoader = { function init() { debug("bootstrap: init"); - let manifestURI = getURI("chrome.manifest"); - let manifest = httpGet(manifestURI) - .responseText - .replace(/#(resource)#/g, "$1") - .replace(/^\s*|\s*$|#.*/g, "") - .replace(/^\s*\n/gm, ""); - - for each (let line in manifest.split("\n")) { - let fields = line.split(/\s+/); - switch (fields[0]) { - case "category": - categoryManager.addCategoryEntry(fields[1], fields[2], fields[3], false, true); - categories.push([fields[1], fields[2]]); - break; - case "component": - components[fields[1]] = new FactoryProxy(getURI(fields[2]).spec, fields[1]); - break; - case "contract": - components[fields[2]].contractID = fields[1]; - break; - - case "resource": - moduleName = moduleName || fields[1]; - resources.push(fields[1]); - resourceProto.setSubstitution(fields[1], getURI(fields[2])); - } + let manifest = JSON.parse(httpGet(getURI("config.json")) + .responseText); + + if (!manifest.categories) + manifest.categories = []; + + for (let [classID, { contract, path, categories }] of Iterator(manifest.components || {})) { + components[classID] = new FactoryProxy(getURI(path).spec, classID, contract); + if (categories) + for (let [category, id] in Iterator(categories)) + manifest.categories.push([category, id, contract]); + } + + for (let [category, id, value] of manifest.categories) + categoryManager.addCategoryEntry(category, id, value, + false, true); + + for (let [pkg, path] in Iterator(manifest.resources || {})) { + moduleName = moduleName || pkg; + resourceProto.setSubstitution(pkg, getURI(path)); } - JSMLoader.config = JSON.parse(httpGet("resource://dactyl-local/config.json").responseText); + JSMLoader.config = manifest; bootstrap_jsm = module(BOOTSTRAP); if (!JSMLoader.SANDBOX) @@ -255,22 +259,13 @@ function init() { } bootstrap.require = JSMLoader.load("base").require; - // Flush the cache if necessary, just to be paranoid let pref = "extensions.dactyl.cacheFlushCheck"; let val = addon.version; if (!Services.prefs.prefHasUserValue(pref) || Services.prefs.getCharPref(pref) != val) { var cacheFlush = true; - Services.obs.notifyObservers(null, "startupcache-invalidate", ""); Services.prefs.setCharPref(pref, val); } - try { - //JSMLoader.load("disable-acr").init(addon.id); - } - catch (e) { - reportError(e); - } - Services.obs.notifyObservers(null, "dactyl-rehash", null); JSMLoader.bootstrap = global; @@ -326,7 +321,9 @@ function updateVersion() { // Disable automatic updates when switching to nightlies, // restore the default action when switching to stable. if (!config.lastVersion || isDev(config.lastVersion) != isDev(addon.version)) - addon.applyBackgroundUpdates = AddonManager[isDev(addon.version) ? "AUTOUPDATE_DISABLE" : "AUTOUPDATE_DEFAULT"]; + addon.applyBackgroundUpdates = + AddonManager[isDev(addon.version) ? "AUTOUPDATE_DISABLE" + : "AUTOUPDATE_DEFAULT"]; } catch (e) { reportError(e); @@ -381,9 +378,10 @@ function startup(data, reason) { * @param {string} url The URL of the module housing the real factory. * @param {string} classID The CID of the class this factory represents. */ -function FactoryProxy(url, classID) { +function FactoryProxy(url, classID, contractID) { this.url = url; this.classID = Components.ID(classID); + this.contractID = contractID; } FactoryProxy.prototype = { QueryInterface: XPCOMUtils.generateQI(Ci.nsIFactory), @@ -405,18 +403,12 @@ FactoryProxy.prototype = { } } +var timer; function shutdown(data, reason) { let strReason = reasonToString(reason); debug("bootstrap: shutdown " + strReason); if (reason != APP_SHUTDOWN) { - try { - //JSMLoader.load("disable-acr").cleanup(addon.id); - } - catch (e) { - reportError(e); - } - if (~[ADDON_UPGRADE, ADDON_DOWNGRADE, ADDON_UNINSTALL].indexOf(reason)) Services.obs.notifyObservers(null, "dactyl-purge", null); @@ -426,17 +418,20 @@ function shutdown(data, reason) { JSMLoader.atexit(strReason); JSMLoader.cleanup(strReason); - if (JSMLoader.SANDBOX) - Cu.nukeSandbox(bootstrap); - bootstrap_jsm.require = null; - Cu.unload(BOOTSTRAP); - bootstrap = null; - bootstrap_jsm = null; - - for each (let [category, entry] in categories) + for each (let [category, entry] in JSMLoader.config.categories) categoryManager.deleteCategoryEntry(category, entry, false); - for each (let resource in resources) + for (let resource in JSMLoader.config.resources) resourceProto.setSubstitution(resource, null); + + timer = Timer(() => { + bootstrap_jsm.require = null; + if (JSMLoader.SANDBOX) + Cu.nukeSandbox(bootstrap); + else + Cu.unload(BOOTSTRAP); + bootstrap = null; + bootstrap_jsm = null; + }, 5000, Ci.nsITimer.TYPE_ONE_SHOT); } }