1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/components/exthelper/extApplication.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,719 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); 1.9 +Components.utils.import("resource://gre/modules/AddonManager.jsm"); 1.10 + 1.11 +//================================================= 1.12 +// Console constructor 1.13 +function Console() { 1.14 + this._console = Components.classes["@mozilla.org/consoleservice;1"] 1.15 + .getService(Ci.nsIConsoleService); 1.16 +} 1.17 + 1.18 +//================================================= 1.19 +// Console implementation 1.20 +Console.prototype = { 1.21 + log: function cs_log(aMsg) { 1.22 + this._console.logStringMessage(aMsg); 1.23 + }, 1.24 + 1.25 + open: function cs_open() { 1.26 + var wMediator = Components.classes["@mozilla.org/appshell/window-mediator;1"] 1.27 + .getService(Ci.nsIWindowMediator); 1.28 + var console = wMediator.getMostRecentWindow("global:console"); 1.29 + if (!console) { 1.30 + var wWatch = Components.classes["@mozilla.org/embedcomp/window-watcher;1"] 1.31 + .getService(Ci.nsIWindowWatcher); 1.32 + wWatch.openWindow(null, "chrome://global/content/console.xul", "_blank", 1.33 + "chrome,dialog=no,all", null); 1.34 + } else { 1.35 + // console was already open 1.36 + console.focus(); 1.37 + } 1.38 + }, 1.39 + 1.40 + QueryInterface: XPCOMUtils.generateQI([Ci.extIConsole]) 1.41 +}; 1.42 + 1.43 + 1.44 +//================================================= 1.45 +// EventItem constructor 1.46 +function EventItem(aType, aData) { 1.47 + this._type = aType; 1.48 + this._data = aData; 1.49 +} 1.50 + 1.51 +//================================================= 1.52 +// EventItem implementation 1.53 +EventItem.prototype = { 1.54 + _cancel: false, 1.55 + 1.56 + get type() { 1.57 + return this._type; 1.58 + }, 1.59 + 1.60 + get data() { 1.61 + return this._data; 1.62 + }, 1.63 + 1.64 + preventDefault: function ei_pd() { 1.65 + this._cancel = true; 1.66 + }, 1.67 + 1.68 + QueryInterface: XPCOMUtils.generateQI([Ci.extIEventItem]) 1.69 +}; 1.70 + 1.71 + 1.72 +//================================================= 1.73 +// Events constructor 1.74 +function Events(notifier) { 1.75 + this._listeners = []; 1.76 + this._notifier = notifier; 1.77 +} 1.78 + 1.79 +//================================================= 1.80 +// Events implementation 1.81 +Events.prototype = { 1.82 + addListener: function evts_al(aEvent, aListener) { 1.83 + function hasFilter(element) { 1.84 + return element.event == aEvent && element.listener == aListener; 1.85 + } 1.86 + 1.87 + if (this._listeners.some(hasFilter)) 1.88 + return; 1.89 + 1.90 + this._listeners.push({ 1.91 + event: aEvent, 1.92 + listener: aListener 1.93 + }); 1.94 + 1.95 + if (this._notifier) { 1.96 + this._notifier(aEvent, aListener); 1.97 + } 1.98 + }, 1.99 + 1.100 + removeListener: function evts_rl(aEvent, aListener) { 1.101 + function hasFilter(element) { 1.102 + return (element.event != aEvent) || (element.listener != aListener); 1.103 + } 1.104 + 1.105 + this._listeners = this._listeners.filter(hasFilter); 1.106 + }, 1.107 + 1.108 + dispatch: function evts_dispatch(aEvent, aEventItem) { 1.109 + var eventItem = new EventItem(aEvent, aEventItem); 1.110 + 1.111 + this._listeners.forEach(function(key){ 1.112 + if (key.event == aEvent) { 1.113 + key.listener.handleEvent ? 1.114 + key.listener.handleEvent(eventItem) : 1.115 + key.listener(eventItem); 1.116 + } 1.117 + }); 1.118 + 1.119 + return !eventItem._cancel; 1.120 + }, 1.121 + 1.122 + QueryInterface: XPCOMUtils.generateQI([Ci.extIEvents]) 1.123 +}; 1.124 + 1.125 +//================================================= 1.126 +// PreferenceObserver (internal class) 1.127 +// 1.128 +// PreferenceObserver is a global singleton which watches the browser's 1.129 +// preferences and sends you events when things change. 1.130 + 1.131 +function PreferenceObserver() { 1.132 + this._observersDict = {}; 1.133 +} 1.134 + 1.135 +PreferenceObserver.prototype = { 1.136 + /** 1.137 + * Add a preference observer. 1.138 + * 1.139 + * @param aPrefs the nsIPrefBranch onto which we'll install our listener. 1.140 + * @param aDomain the domain our listener will watch (a string). 1.141 + * @param aEvent the event to listen to (you probably want "change"). 1.142 + * @param aListener the function to call back when the event fires. This 1.143 + * function will receive an EventData argument. 1.144 + */ 1.145 + addListener: function po_al(aPrefs, aDomain, aEvent, aListener) { 1.146 + var root = aPrefs.root; 1.147 + if (!this._observersDict[root]) { 1.148 + this._observersDict[root] = {}; 1.149 + } 1.150 + var observer = this._observersDict[root][aDomain]; 1.151 + 1.152 + if (!observer) { 1.153 + observer = { 1.154 + events: new Events(), 1.155 + observe: function po_observer_obs(aSubject, aTopic, aData) { 1.156 + this.events.dispatch("change", aData); 1.157 + }, 1.158 + QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, 1.159 + Ci.nsISupportsWeakReference]) 1.160 + }; 1.161 + observer.prefBranch = aPrefs; 1.162 + observer.prefBranch.addObserver(aDomain, observer, /* ownsWeak = */ true); 1.163 + 1.164 + // Notice that the prefBranch keeps a weak reference to the observer; 1.165 + // it's this._observersDict which keeps the observer alive. 1.166 + this._observersDict[root][aDomain] = observer; 1.167 + } 1.168 + observer.events.addListener(aEvent, aListener); 1.169 + }, 1.170 + 1.171 + /** 1.172 + * Remove a preference observer. 1.173 + * 1.174 + * This function's parameters are identical to addListener's. 1.175 + */ 1.176 + removeListener: function po_rl(aPrefs, aDomain, aEvent, aListener) { 1.177 + var root = aPrefs.root; 1.178 + if (!this._observersDict[root] || 1.179 + !this._observersDict[root][aDomain]) { 1.180 + return; 1.181 + } 1.182 + var observer = this._observersDict[root][aDomain]; 1.183 + observer.events.removeListener(aEvent, aListener); 1.184 + 1.185 + if (observer.events._listeners.length == 0) { 1.186 + // nsIPrefBranch objects are not singletons -- we can have two 1.187 + // nsIPrefBranch'es for the same branch. There's no guarantee that 1.188 + // aPrefs is the same object as observer.prefBranch, so we have to call 1.189 + // removeObserver on observer.prefBranch. 1.190 + observer.prefBranch.removeObserver(aDomain, observer); 1.191 + delete this._observersDict[root][aDomain]; 1.192 + if (Object.keys(this._observersDict[root]).length == 0) { 1.193 + delete this._observersDict[root]; 1.194 + } 1.195 + } 1.196 + } 1.197 +}; 1.198 + 1.199 +//================================================= 1.200 +// PreferenceBranch constructor 1.201 +function PreferenceBranch(aBranch) { 1.202 + if (!aBranch) 1.203 + aBranch = ""; 1.204 + 1.205 + this._root = aBranch; 1.206 + this._prefs = Components.classes["@mozilla.org/preferences-service;1"] 1.207 + .getService(Ci.nsIPrefService) 1.208 + .QueryInterface(Ci.nsIPrefBranch); 1.209 + 1.210 + if (aBranch) 1.211 + this._prefs = this._prefs.getBranch(aBranch); 1.212 + 1.213 + let prefs = this._prefs; 1.214 + this._events = { 1.215 + addListener: function pb_al(aEvent, aListener) { 1.216 + gPreferenceObserver.addListener(prefs, "", aEvent, aListener); 1.217 + }, 1.218 + removeListener: function pb_rl(aEvent, aListener) { 1.219 + gPreferenceObserver.removeListener(prefs, "", aEvent, aListener); 1.220 + }, 1.221 + QueryInterface: XPCOMUtils.generateQI([Ci.extIEvents]) 1.222 + }; 1.223 +} 1.224 + 1.225 +//================================================= 1.226 +// PreferenceBranch implementation 1.227 +PreferenceBranch.prototype = { 1.228 + get root() { 1.229 + return this._root; 1.230 + }, 1.231 + 1.232 + get all() { 1.233 + return this.find({}); 1.234 + }, 1.235 + 1.236 + get events() { 1.237 + return this._events; 1.238 + }, 1.239 + 1.240 + // XXX: Disabled until we can figure out the wrapped object issues 1.241 + // name: "name" or /name/ 1.242 + // path: "foo.bar." or "" or /fo+\.bar/ 1.243 + // type: Boolean, Number, String (getPrefType) 1.244 + // locked: true, false (prefIsLocked) 1.245 + // modified: true, false (prefHasUserValue) 1.246 + find: function prefs_find(aOptions) { 1.247 + var retVal = []; 1.248 + var items = this._prefs.getChildList(""); 1.249 + 1.250 + for (var i = 0; i < items.length; i++) { 1.251 + retVal.push(new Preference(items[i], this)); 1.252 + } 1.253 + 1.254 + return retVal; 1.255 + }, 1.256 + 1.257 + has: function prefs_has(aName) { 1.258 + return (this._prefs.getPrefType(aName) != Ci.nsIPrefBranch.PREF_INVALID); 1.259 + }, 1.260 + 1.261 + get: function prefs_get(aName) { 1.262 + return this.has(aName) ? new Preference(aName, this) : null; 1.263 + }, 1.264 + 1.265 + getValue: function prefs_gv(aName, aValue) { 1.266 + var type = this._prefs.getPrefType(aName); 1.267 + 1.268 + switch (type) { 1.269 + case Ci.nsIPrefBranch.PREF_STRING: 1.270 + aValue = this._prefs.getComplexValue(aName, Ci.nsISupportsString).data; 1.271 + break; 1.272 + case Ci.nsIPrefBranch.PREF_BOOL: 1.273 + aValue = this._prefs.getBoolPref(aName); 1.274 + break; 1.275 + case Ci.nsIPrefBranch.PREF_INT: 1.276 + aValue = this._prefs.getIntPref(aName); 1.277 + break; 1.278 + } 1.279 + 1.280 + return aValue; 1.281 + }, 1.282 + 1.283 + setValue: function prefs_sv(aName, aValue) { 1.284 + var type = aValue != null ? aValue.constructor.name : ""; 1.285 + 1.286 + switch (type) { 1.287 + case "String": 1.288 + var str = Components.classes["@mozilla.org/supports-string;1"] 1.289 + .createInstance(Ci.nsISupportsString); 1.290 + str.data = aValue; 1.291 + this._prefs.setComplexValue(aName, Ci.nsISupportsString, str); 1.292 + break; 1.293 + case "Boolean": 1.294 + this._prefs.setBoolPref(aName, aValue); 1.295 + break; 1.296 + case "Number": 1.297 + this._prefs.setIntPref(aName, aValue); 1.298 + break; 1.299 + default: 1.300 + throw("Unknown preference value specified."); 1.301 + } 1.302 + }, 1.303 + 1.304 + reset: function prefs_reset() { 1.305 + this._prefs.resetBranch(""); 1.306 + }, 1.307 + 1.308 + QueryInterface: XPCOMUtils.generateQI([Ci.extIPreferenceBranch]) 1.309 +}; 1.310 + 1.311 + 1.312 +//================================================= 1.313 +// Preference constructor 1.314 +function Preference(aName, aBranch) { 1.315 + this._name = aName; 1.316 + this._branch = aBranch; 1.317 + 1.318 + var self = this; 1.319 + this._events = { 1.320 + addListener: function pref_al(aEvent, aListener) { 1.321 + gPreferenceObserver.addListener(self._branch._prefs, self._name, aEvent, aListener); 1.322 + }, 1.323 + removeListener: function pref_rl(aEvent, aListener) { 1.324 + gPreferenceObserver.removeListener(self._branch._prefs, self._name, aEvent, aListener); 1.325 + }, 1.326 + QueryInterface: XPCOMUtils.generateQI([Ci.extIEvents]) 1.327 + }; 1.328 +} 1.329 + 1.330 +//================================================= 1.331 +// Preference implementation 1.332 +Preference.prototype = { 1.333 + get name() { 1.334 + return this._name; 1.335 + }, 1.336 + 1.337 + get type() { 1.338 + var value = ""; 1.339 + var type = this.branch._prefs.getPrefType(this._name); 1.340 + 1.341 + switch (type) { 1.342 + case Ci.nsIPrefBranch.PREF_STRING: 1.343 + value = "String"; 1.344 + break; 1.345 + case Ci.nsIPrefBranch.PREF_BOOL: 1.346 + value = "Boolean"; 1.347 + break; 1.348 + case Ci.nsIPrefBranch.PREF_INT: 1.349 + value = "Number"; 1.350 + break; 1.351 + } 1.352 + 1.353 + return value; 1.354 + }, 1.355 + 1.356 + get value() { 1.357 + return this.branch.getValue(this._name, null); 1.358 + }, 1.359 + 1.360 + set value(aValue) { 1.361 + return this.branch.setValue(this._name, aValue); 1.362 + }, 1.363 + 1.364 + get locked() { 1.365 + return this.branch._prefs.prefIsLocked(this.name); 1.366 + }, 1.367 + 1.368 + set locked(aValue) { 1.369 + this.branch._prefs[ aValue ? "lockPref" : "unlockPref" ](this.name); 1.370 + }, 1.371 + 1.372 + get modified() { 1.373 + return this.branch._prefs.prefHasUserValue(this.name); 1.374 + }, 1.375 + 1.376 + get branch() { 1.377 + return this._branch; 1.378 + }, 1.379 + 1.380 + get events() { 1.381 + return this._events; 1.382 + }, 1.383 + 1.384 + reset: function pref_reset() { 1.385 + this.branch._prefs.clearUserPref(this.name); 1.386 + }, 1.387 + 1.388 + QueryInterface: XPCOMUtils.generateQI([Ci.extIPreference]) 1.389 +}; 1.390 + 1.391 + 1.392 +//================================================= 1.393 +// SessionStorage constructor 1.394 +function SessionStorage() { 1.395 + this._storage = {}; 1.396 + this._events = new Events(); 1.397 +} 1.398 + 1.399 +//================================================= 1.400 +// SessionStorage implementation 1.401 +SessionStorage.prototype = { 1.402 + get events() { 1.403 + return this._events; 1.404 + }, 1.405 + 1.406 + has: function ss_has(aName) { 1.407 + return this._storage.hasOwnProperty(aName); 1.408 + }, 1.409 + 1.410 + set: function ss_set(aName, aValue) { 1.411 + this._storage[aName] = aValue; 1.412 + this._events.dispatch("change", aName); 1.413 + }, 1.414 + 1.415 + get: function ss_get(aName, aDefaultValue) { 1.416 + return this.has(aName) ? this._storage[aName] : aDefaultValue; 1.417 + }, 1.418 + 1.419 + QueryInterface : XPCOMUtils.generateQI([Ci.extISessionStorage]) 1.420 +}; 1.421 + 1.422 +//================================================= 1.423 +// ExtensionObserver constructor (internal class) 1.424 +// 1.425 +// ExtensionObserver is a global singleton which watches the browser's 1.426 +// extensions and sends you events when things change. 1.427 + 1.428 +function ExtensionObserver() { 1.429 + this._eventsDict = {}; 1.430 + 1.431 + AddonManager.addAddonListener(this); 1.432 + AddonManager.addInstallListener(this); 1.433 +} 1.434 + 1.435 +//================================================= 1.436 +// ExtensionObserver implementation (internal class) 1.437 +ExtensionObserver.prototype = { 1.438 + onDisabling: function eo_onDisabling(addon, needsRestart) { 1.439 + this._dispatchEvent(addon.id, "disable"); 1.440 + }, 1.441 + 1.442 + onEnabling: function eo_onEnabling(addon, needsRestart) { 1.443 + this._dispatchEvent(addon.id, "enable"); 1.444 + }, 1.445 + 1.446 + onUninstalling: function eo_onUninstalling(addon, needsRestart) { 1.447 + this._dispatchEvent(addon.id, "uninstall"); 1.448 + }, 1.449 + 1.450 + onOperationCancelled: function eo_onOperationCancelled(addon) { 1.451 + this._dispatchEvent(addon.id, "cancel"); 1.452 + }, 1.453 + 1.454 + onInstallEnded: function eo_onInstallEnded(install, addon) { 1.455 + this._dispatchEvent(addon.id, "upgrade"); 1.456 + }, 1.457 + 1.458 + addListener: function eo_al(aId, aEvent, aListener) { 1.459 + var events = this._eventsDict[aId]; 1.460 + if (!events) { 1.461 + events = new Events(); 1.462 + this._eventsDict[aId] = events; 1.463 + } 1.464 + events.addListener(aEvent, aListener); 1.465 + }, 1.466 + 1.467 + removeListener: function eo_rl(aId, aEvent, aListener) { 1.468 + var events = this._eventsDict[aId]; 1.469 + if (!events) { 1.470 + return; 1.471 + } 1.472 + events.removeListener(aEvent, aListener); 1.473 + if (events._listeners.length == 0) { 1.474 + delete this._eventsDict[aId]; 1.475 + } 1.476 + }, 1.477 + 1.478 + _dispatchEvent: function eo_dispatchEvent(aId, aEvent) { 1.479 + var events = this._eventsDict[aId]; 1.480 + if (events) { 1.481 + events.dispatch(aEvent, aId); 1.482 + } 1.483 + } 1.484 +}; 1.485 + 1.486 +//================================================= 1.487 +// Extension constructor 1.488 +function Extension(aItem) { 1.489 + this._item = aItem; 1.490 + this._firstRun = false; 1.491 + this._prefs = new PreferenceBranch("extensions." + this.id + "."); 1.492 + this._storage = new SessionStorage(); 1.493 + 1.494 + let id = this.id; 1.495 + this._events = { 1.496 + addListener: function ext_events_al(aEvent, aListener) { 1.497 + gExtensionObserver.addListener(id, aEvent, aListener); 1.498 + }, 1.499 + removeListener: function ext_events_rl(aEvent, aListener) { 1.500 + gExtensionObserver.addListener(id, aEvent, aListener); 1.501 + }, 1.502 + QueryInterface: XPCOMUtils.generateQI([Ci.extIEvents]) 1.503 + }; 1.504 + 1.505 + var installPref = "install-event-fired"; 1.506 + if (!this._prefs.has(installPref)) { 1.507 + this._prefs.setValue(installPref, true); 1.508 + this._firstRun = true; 1.509 + } 1.510 +} 1.511 + 1.512 +//================================================= 1.513 +// Extension implementation 1.514 +Extension.prototype = { 1.515 + get id() { 1.516 + return this._item.id; 1.517 + }, 1.518 + 1.519 + get name() { 1.520 + return this._item.name; 1.521 + }, 1.522 + 1.523 + get enabled() { 1.524 + return this._item.isActive; 1.525 + }, 1.526 + 1.527 + get version() { 1.528 + return this._item.version; 1.529 + }, 1.530 + 1.531 + get firstRun() { 1.532 + return this._firstRun; 1.533 + }, 1.534 + 1.535 + get storage() { 1.536 + return this._storage; 1.537 + }, 1.538 + 1.539 + get prefs() { 1.540 + return this._prefs; 1.541 + }, 1.542 + 1.543 + get events() { 1.544 + return this._events; 1.545 + }, 1.546 + 1.547 + QueryInterface: XPCOMUtils.generateQI([Ci.extIExtension]) 1.548 +}; 1.549 + 1.550 + 1.551 +//================================================= 1.552 +// Extensions constructor 1.553 +function Extensions(addons) { 1.554 + this._cache = {}; 1.555 + 1.556 + addons.forEach(function (addon) { 1.557 + this._cache[addon.id] = new Extension(addon); 1.558 + }, this); 1.559 +} 1.560 + 1.561 +//================================================= 1.562 +// Extensions implementation 1.563 +Extensions.prototype = { 1.564 + get all() { 1.565 + return this.find({}); 1.566 + }, 1.567 + 1.568 + // XXX: Disabled until we can figure out the wrapped object issues 1.569 + // id: "some@id" or /id/ 1.570 + // name: "name" or /name/ 1.571 + // version: "1.0.1" 1.572 + // minVersion: "1.0" 1.573 + // maxVersion: "2.0" 1.574 + find: function exts_find(aOptions) { 1.575 + return [e for each (e in this._cache)]; 1.576 + }, 1.577 + 1.578 + has: function exts_has(aId) { 1.579 + return aId in this._cache; 1.580 + }, 1.581 + 1.582 + get: function exts_get(aId) { 1.583 + return this.has(aId) ? this._cache[aId] : null; 1.584 + }, 1.585 + 1.586 + QueryInterface: XPCOMUtils.generateQI([Ci.extIExtensions]) 1.587 +}; 1.588 + 1.589 +//================================================= 1.590 +// Application globals 1.591 + 1.592 +gExtensionObserver = new ExtensionObserver(); 1.593 +gPreferenceObserver = new PreferenceObserver(); 1.594 + 1.595 +//================================================= 1.596 +// extApplication constructor 1.597 +function extApplication() { 1.598 +} 1.599 + 1.600 +//================================================= 1.601 +// extApplication implementation 1.602 +extApplication.prototype = { 1.603 + initToolkitHelpers: function extApp_initToolkitHelpers() { 1.604 + XPCOMUtils.defineLazyServiceGetter(this, "_info", 1.605 + "@mozilla.org/xre/app-info;1", 1.606 + "nsIXULAppInfo"); 1.607 + 1.608 + this._obs = Cc["@mozilla.org/observer-service;1"]. 1.609 + getService(Ci.nsIObserverService); 1.610 + this._obs.addObserver(this, "xpcom-shutdown", /* ownsWeak = */ true); 1.611 + this._registered = {"unload": true}; 1.612 + }, 1.613 + 1.614 + classInfo: XPCOMUtils.generateCI({interfaces: [Ci.extIApplication, 1.615 + Ci.nsIObserver], 1.616 + flags: Ci.nsIClassInfo.SINGLETON}), 1.617 + 1.618 + // extIApplication 1.619 + get id() { 1.620 + return this._info.ID; 1.621 + }, 1.622 + 1.623 + get name() { 1.624 + return this._info.name; 1.625 + }, 1.626 + 1.627 + get version() { 1.628 + return this._info.version; 1.629 + }, 1.630 + 1.631 + // for nsIObserver 1.632 + observe: function app_observe(aSubject, aTopic, aData) { 1.633 + if (aTopic == "app-startup") { 1.634 + this.events.dispatch("load", "application"); 1.635 + } 1.636 + else if (aTopic == "final-ui-startup") { 1.637 + this.events.dispatch("ready", "application"); 1.638 + } 1.639 + else if (aTopic == "quit-application-requested") { 1.640 + // we can stop the quit by checking the return value 1.641 + if (this.events.dispatch("quit", "application") == false) 1.642 + aSubject.data = true; 1.643 + } 1.644 + else if (aTopic == "xpcom-shutdown") { 1.645 + this.events.dispatch("unload", "application"); 1.646 + gExtensionObserver = null; 1.647 + gPreferenceObserver = null; 1.648 + } 1.649 + }, 1.650 + 1.651 + get console() { 1.652 + let console = new Console(); 1.653 + this.__defineGetter__("console", function () console); 1.654 + return this.console; 1.655 + }, 1.656 + 1.657 + get storage() { 1.658 + let storage = new SessionStorage(); 1.659 + this.__defineGetter__("storage", function () storage); 1.660 + return this.storage; 1.661 + }, 1.662 + 1.663 + get prefs() { 1.664 + let prefs = new PreferenceBranch(""); 1.665 + this.__defineGetter__("prefs", function () prefs); 1.666 + return this.prefs; 1.667 + }, 1.668 + 1.669 + getExtensions: function(callback) { 1.670 + AddonManager.getAddonsByTypes(["extension"], function (addons) { 1.671 + callback.callback(new Extensions(addons)); 1.672 + }); 1.673 + }, 1.674 + 1.675 + get events() { 1.676 + 1.677 + // This ensures that FUEL only registers for notifications as needed 1.678 + // by callers. Note that the unload (xpcom-shutdown) event is listened 1.679 + // for by default, as it's needed for cleanup purposes. 1.680 + var self = this; 1.681 + function registerCheck(aEvent) { 1.682 + var rmap = { "load": "app-startup", 1.683 + "ready": "final-ui-startup", 1.684 + "quit": "quit-application-requested"}; 1.685 + if (!(aEvent in rmap) || aEvent in self._registered) 1.686 + return; 1.687 + 1.688 + self._obs.addObserver(self, rmap[aEvent], /* ownsWeak = */ true); 1.689 + self._registered[aEvent] = true; 1.690 + } 1.691 + 1.692 + let events = new Events(registerCheck); 1.693 + this.__defineGetter__("events", function () events); 1.694 + return this.events; 1.695 + }, 1.696 + 1.697 + // helper method for correct quitting/restarting 1.698 + _quitWithFlags: function app__quitWithFlags(aFlags) { 1.699 + let cancelQuit = Components.classes["@mozilla.org/supports-PRBool;1"] 1.700 + .createInstance(Components.interfaces.nsISupportsPRBool); 1.701 + let quitType = aFlags & Components.interfaces.nsIAppStartup.eRestart ? "restart" : null; 1.702 + this._obs.notifyObservers(cancelQuit, "quit-application-requested", quitType); 1.703 + if (cancelQuit.data) 1.704 + return false; // somebody canceled our quit request 1.705 + 1.706 + let appStartup = Components.classes['@mozilla.org/toolkit/app-startup;1'] 1.707 + .getService(Components.interfaces.nsIAppStartup); 1.708 + appStartup.quit(aFlags); 1.709 + return true; 1.710 + }, 1.711 + 1.712 + quit: function app_quit() { 1.713 + return this._quitWithFlags(Components.interfaces.nsIAppStartup.eAttemptQuit); 1.714 + }, 1.715 + 1.716 + restart: function app_restart() { 1.717 + return this._quitWithFlags(Components.interfaces.nsIAppStartup.eAttemptQuit | 1.718 + Components.interfaces.nsIAppStartup.eRestart); 1.719 + }, 1.720 + 1.721 + QueryInterface: XPCOMUtils.generateQI([Ci.extIApplication, Ci.nsISupportsWeakReference]) 1.722 +};