toolkit/components/exthelper/extApplication.js

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
michael@0 6 Components.utils.import("resource://gre/modules/AddonManager.jsm");
michael@0 7
michael@0 8 //=================================================
michael@0 9 // Console constructor
michael@0 10 function Console() {
michael@0 11 this._console = Components.classes["@mozilla.org/consoleservice;1"]
michael@0 12 .getService(Ci.nsIConsoleService);
michael@0 13 }
michael@0 14
michael@0 15 //=================================================
michael@0 16 // Console implementation
michael@0 17 Console.prototype = {
michael@0 18 log: function cs_log(aMsg) {
michael@0 19 this._console.logStringMessage(aMsg);
michael@0 20 },
michael@0 21
michael@0 22 open: function cs_open() {
michael@0 23 var wMediator = Components.classes["@mozilla.org/appshell/window-mediator;1"]
michael@0 24 .getService(Ci.nsIWindowMediator);
michael@0 25 var console = wMediator.getMostRecentWindow("global:console");
michael@0 26 if (!console) {
michael@0 27 var wWatch = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
michael@0 28 .getService(Ci.nsIWindowWatcher);
michael@0 29 wWatch.openWindow(null, "chrome://global/content/console.xul", "_blank",
michael@0 30 "chrome,dialog=no,all", null);
michael@0 31 } else {
michael@0 32 // console was already open
michael@0 33 console.focus();
michael@0 34 }
michael@0 35 },
michael@0 36
michael@0 37 QueryInterface: XPCOMUtils.generateQI([Ci.extIConsole])
michael@0 38 };
michael@0 39
michael@0 40
michael@0 41 //=================================================
michael@0 42 // EventItem constructor
michael@0 43 function EventItem(aType, aData) {
michael@0 44 this._type = aType;
michael@0 45 this._data = aData;
michael@0 46 }
michael@0 47
michael@0 48 //=================================================
michael@0 49 // EventItem implementation
michael@0 50 EventItem.prototype = {
michael@0 51 _cancel: false,
michael@0 52
michael@0 53 get type() {
michael@0 54 return this._type;
michael@0 55 },
michael@0 56
michael@0 57 get data() {
michael@0 58 return this._data;
michael@0 59 },
michael@0 60
michael@0 61 preventDefault: function ei_pd() {
michael@0 62 this._cancel = true;
michael@0 63 },
michael@0 64
michael@0 65 QueryInterface: XPCOMUtils.generateQI([Ci.extIEventItem])
michael@0 66 };
michael@0 67
michael@0 68
michael@0 69 //=================================================
michael@0 70 // Events constructor
michael@0 71 function Events(notifier) {
michael@0 72 this._listeners = [];
michael@0 73 this._notifier = notifier;
michael@0 74 }
michael@0 75
michael@0 76 //=================================================
michael@0 77 // Events implementation
michael@0 78 Events.prototype = {
michael@0 79 addListener: function evts_al(aEvent, aListener) {
michael@0 80 function hasFilter(element) {
michael@0 81 return element.event == aEvent && element.listener == aListener;
michael@0 82 }
michael@0 83
michael@0 84 if (this._listeners.some(hasFilter))
michael@0 85 return;
michael@0 86
michael@0 87 this._listeners.push({
michael@0 88 event: aEvent,
michael@0 89 listener: aListener
michael@0 90 });
michael@0 91
michael@0 92 if (this._notifier) {
michael@0 93 this._notifier(aEvent, aListener);
michael@0 94 }
michael@0 95 },
michael@0 96
michael@0 97 removeListener: function evts_rl(aEvent, aListener) {
michael@0 98 function hasFilter(element) {
michael@0 99 return (element.event != aEvent) || (element.listener != aListener);
michael@0 100 }
michael@0 101
michael@0 102 this._listeners = this._listeners.filter(hasFilter);
michael@0 103 },
michael@0 104
michael@0 105 dispatch: function evts_dispatch(aEvent, aEventItem) {
michael@0 106 var eventItem = new EventItem(aEvent, aEventItem);
michael@0 107
michael@0 108 this._listeners.forEach(function(key){
michael@0 109 if (key.event == aEvent) {
michael@0 110 key.listener.handleEvent ?
michael@0 111 key.listener.handleEvent(eventItem) :
michael@0 112 key.listener(eventItem);
michael@0 113 }
michael@0 114 });
michael@0 115
michael@0 116 return !eventItem._cancel;
michael@0 117 },
michael@0 118
michael@0 119 QueryInterface: XPCOMUtils.generateQI([Ci.extIEvents])
michael@0 120 };
michael@0 121
michael@0 122 //=================================================
michael@0 123 // PreferenceObserver (internal class)
michael@0 124 //
michael@0 125 // PreferenceObserver is a global singleton which watches the browser's
michael@0 126 // preferences and sends you events when things change.
michael@0 127
michael@0 128 function PreferenceObserver() {
michael@0 129 this._observersDict = {};
michael@0 130 }
michael@0 131
michael@0 132 PreferenceObserver.prototype = {
michael@0 133 /**
michael@0 134 * Add a preference observer.
michael@0 135 *
michael@0 136 * @param aPrefs the nsIPrefBranch onto which we'll install our listener.
michael@0 137 * @param aDomain the domain our listener will watch (a string).
michael@0 138 * @param aEvent the event to listen to (you probably want "change").
michael@0 139 * @param aListener the function to call back when the event fires. This
michael@0 140 * function will receive an EventData argument.
michael@0 141 */
michael@0 142 addListener: function po_al(aPrefs, aDomain, aEvent, aListener) {
michael@0 143 var root = aPrefs.root;
michael@0 144 if (!this._observersDict[root]) {
michael@0 145 this._observersDict[root] = {};
michael@0 146 }
michael@0 147 var observer = this._observersDict[root][aDomain];
michael@0 148
michael@0 149 if (!observer) {
michael@0 150 observer = {
michael@0 151 events: new Events(),
michael@0 152 observe: function po_observer_obs(aSubject, aTopic, aData) {
michael@0 153 this.events.dispatch("change", aData);
michael@0 154 },
michael@0 155 QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
michael@0 156 Ci.nsISupportsWeakReference])
michael@0 157 };
michael@0 158 observer.prefBranch = aPrefs;
michael@0 159 observer.prefBranch.addObserver(aDomain, observer, /* ownsWeak = */ true);
michael@0 160
michael@0 161 // Notice that the prefBranch keeps a weak reference to the observer;
michael@0 162 // it's this._observersDict which keeps the observer alive.
michael@0 163 this._observersDict[root][aDomain] = observer;
michael@0 164 }
michael@0 165 observer.events.addListener(aEvent, aListener);
michael@0 166 },
michael@0 167
michael@0 168 /**
michael@0 169 * Remove a preference observer.
michael@0 170 *
michael@0 171 * This function's parameters are identical to addListener's.
michael@0 172 */
michael@0 173 removeListener: function po_rl(aPrefs, aDomain, aEvent, aListener) {
michael@0 174 var root = aPrefs.root;
michael@0 175 if (!this._observersDict[root] ||
michael@0 176 !this._observersDict[root][aDomain]) {
michael@0 177 return;
michael@0 178 }
michael@0 179 var observer = this._observersDict[root][aDomain];
michael@0 180 observer.events.removeListener(aEvent, aListener);
michael@0 181
michael@0 182 if (observer.events._listeners.length == 0) {
michael@0 183 // nsIPrefBranch objects are not singletons -- we can have two
michael@0 184 // nsIPrefBranch'es for the same branch. There's no guarantee that
michael@0 185 // aPrefs is the same object as observer.prefBranch, so we have to call
michael@0 186 // removeObserver on observer.prefBranch.
michael@0 187 observer.prefBranch.removeObserver(aDomain, observer);
michael@0 188 delete this._observersDict[root][aDomain];
michael@0 189 if (Object.keys(this._observersDict[root]).length == 0) {
michael@0 190 delete this._observersDict[root];
michael@0 191 }
michael@0 192 }
michael@0 193 }
michael@0 194 };
michael@0 195
michael@0 196 //=================================================
michael@0 197 // PreferenceBranch constructor
michael@0 198 function PreferenceBranch(aBranch) {
michael@0 199 if (!aBranch)
michael@0 200 aBranch = "";
michael@0 201
michael@0 202 this._root = aBranch;
michael@0 203 this._prefs = Components.classes["@mozilla.org/preferences-service;1"]
michael@0 204 .getService(Ci.nsIPrefService)
michael@0 205 .QueryInterface(Ci.nsIPrefBranch);
michael@0 206
michael@0 207 if (aBranch)
michael@0 208 this._prefs = this._prefs.getBranch(aBranch);
michael@0 209
michael@0 210 let prefs = this._prefs;
michael@0 211 this._events = {
michael@0 212 addListener: function pb_al(aEvent, aListener) {
michael@0 213 gPreferenceObserver.addListener(prefs, "", aEvent, aListener);
michael@0 214 },
michael@0 215 removeListener: function pb_rl(aEvent, aListener) {
michael@0 216 gPreferenceObserver.removeListener(prefs, "", aEvent, aListener);
michael@0 217 },
michael@0 218 QueryInterface: XPCOMUtils.generateQI([Ci.extIEvents])
michael@0 219 };
michael@0 220 }
michael@0 221
michael@0 222 //=================================================
michael@0 223 // PreferenceBranch implementation
michael@0 224 PreferenceBranch.prototype = {
michael@0 225 get root() {
michael@0 226 return this._root;
michael@0 227 },
michael@0 228
michael@0 229 get all() {
michael@0 230 return this.find({});
michael@0 231 },
michael@0 232
michael@0 233 get events() {
michael@0 234 return this._events;
michael@0 235 },
michael@0 236
michael@0 237 // XXX: Disabled until we can figure out the wrapped object issues
michael@0 238 // name: "name" or /name/
michael@0 239 // path: "foo.bar." or "" or /fo+\.bar/
michael@0 240 // type: Boolean, Number, String (getPrefType)
michael@0 241 // locked: true, false (prefIsLocked)
michael@0 242 // modified: true, false (prefHasUserValue)
michael@0 243 find: function prefs_find(aOptions) {
michael@0 244 var retVal = [];
michael@0 245 var items = this._prefs.getChildList("");
michael@0 246
michael@0 247 for (var i = 0; i < items.length; i++) {
michael@0 248 retVal.push(new Preference(items[i], this));
michael@0 249 }
michael@0 250
michael@0 251 return retVal;
michael@0 252 },
michael@0 253
michael@0 254 has: function prefs_has(aName) {
michael@0 255 return (this._prefs.getPrefType(aName) != Ci.nsIPrefBranch.PREF_INVALID);
michael@0 256 },
michael@0 257
michael@0 258 get: function prefs_get(aName) {
michael@0 259 return this.has(aName) ? new Preference(aName, this) : null;
michael@0 260 },
michael@0 261
michael@0 262 getValue: function prefs_gv(aName, aValue) {
michael@0 263 var type = this._prefs.getPrefType(aName);
michael@0 264
michael@0 265 switch (type) {
michael@0 266 case Ci.nsIPrefBranch.PREF_STRING:
michael@0 267 aValue = this._prefs.getComplexValue(aName, Ci.nsISupportsString).data;
michael@0 268 break;
michael@0 269 case Ci.nsIPrefBranch.PREF_BOOL:
michael@0 270 aValue = this._prefs.getBoolPref(aName);
michael@0 271 break;
michael@0 272 case Ci.nsIPrefBranch.PREF_INT:
michael@0 273 aValue = this._prefs.getIntPref(aName);
michael@0 274 break;
michael@0 275 }
michael@0 276
michael@0 277 return aValue;
michael@0 278 },
michael@0 279
michael@0 280 setValue: function prefs_sv(aName, aValue) {
michael@0 281 var type = aValue != null ? aValue.constructor.name : "";
michael@0 282
michael@0 283 switch (type) {
michael@0 284 case "String":
michael@0 285 var str = Components.classes["@mozilla.org/supports-string;1"]
michael@0 286 .createInstance(Ci.nsISupportsString);
michael@0 287 str.data = aValue;
michael@0 288 this._prefs.setComplexValue(aName, Ci.nsISupportsString, str);
michael@0 289 break;
michael@0 290 case "Boolean":
michael@0 291 this._prefs.setBoolPref(aName, aValue);
michael@0 292 break;
michael@0 293 case "Number":
michael@0 294 this._prefs.setIntPref(aName, aValue);
michael@0 295 break;
michael@0 296 default:
michael@0 297 throw("Unknown preference value specified.");
michael@0 298 }
michael@0 299 },
michael@0 300
michael@0 301 reset: function prefs_reset() {
michael@0 302 this._prefs.resetBranch("");
michael@0 303 },
michael@0 304
michael@0 305 QueryInterface: XPCOMUtils.generateQI([Ci.extIPreferenceBranch])
michael@0 306 };
michael@0 307
michael@0 308
michael@0 309 //=================================================
michael@0 310 // Preference constructor
michael@0 311 function Preference(aName, aBranch) {
michael@0 312 this._name = aName;
michael@0 313 this._branch = aBranch;
michael@0 314
michael@0 315 var self = this;
michael@0 316 this._events = {
michael@0 317 addListener: function pref_al(aEvent, aListener) {
michael@0 318 gPreferenceObserver.addListener(self._branch._prefs, self._name, aEvent, aListener);
michael@0 319 },
michael@0 320 removeListener: function pref_rl(aEvent, aListener) {
michael@0 321 gPreferenceObserver.removeListener(self._branch._prefs, self._name, aEvent, aListener);
michael@0 322 },
michael@0 323 QueryInterface: XPCOMUtils.generateQI([Ci.extIEvents])
michael@0 324 };
michael@0 325 }
michael@0 326
michael@0 327 //=================================================
michael@0 328 // Preference implementation
michael@0 329 Preference.prototype = {
michael@0 330 get name() {
michael@0 331 return this._name;
michael@0 332 },
michael@0 333
michael@0 334 get type() {
michael@0 335 var value = "";
michael@0 336 var type = this.branch._prefs.getPrefType(this._name);
michael@0 337
michael@0 338 switch (type) {
michael@0 339 case Ci.nsIPrefBranch.PREF_STRING:
michael@0 340 value = "String";
michael@0 341 break;
michael@0 342 case Ci.nsIPrefBranch.PREF_BOOL:
michael@0 343 value = "Boolean";
michael@0 344 break;
michael@0 345 case Ci.nsIPrefBranch.PREF_INT:
michael@0 346 value = "Number";
michael@0 347 break;
michael@0 348 }
michael@0 349
michael@0 350 return value;
michael@0 351 },
michael@0 352
michael@0 353 get value() {
michael@0 354 return this.branch.getValue(this._name, null);
michael@0 355 },
michael@0 356
michael@0 357 set value(aValue) {
michael@0 358 return this.branch.setValue(this._name, aValue);
michael@0 359 },
michael@0 360
michael@0 361 get locked() {
michael@0 362 return this.branch._prefs.prefIsLocked(this.name);
michael@0 363 },
michael@0 364
michael@0 365 set locked(aValue) {
michael@0 366 this.branch._prefs[ aValue ? "lockPref" : "unlockPref" ](this.name);
michael@0 367 },
michael@0 368
michael@0 369 get modified() {
michael@0 370 return this.branch._prefs.prefHasUserValue(this.name);
michael@0 371 },
michael@0 372
michael@0 373 get branch() {
michael@0 374 return this._branch;
michael@0 375 },
michael@0 376
michael@0 377 get events() {
michael@0 378 return this._events;
michael@0 379 },
michael@0 380
michael@0 381 reset: function pref_reset() {
michael@0 382 this.branch._prefs.clearUserPref(this.name);
michael@0 383 },
michael@0 384
michael@0 385 QueryInterface: XPCOMUtils.generateQI([Ci.extIPreference])
michael@0 386 };
michael@0 387
michael@0 388
michael@0 389 //=================================================
michael@0 390 // SessionStorage constructor
michael@0 391 function SessionStorage() {
michael@0 392 this._storage = {};
michael@0 393 this._events = new Events();
michael@0 394 }
michael@0 395
michael@0 396 //=================================================
michael@0 397 // SessionStorage implementation
michael@0 398 SessionStorage.prototype = {
michael@0 399 get events() {
michael@0 400 return this._events;
michael@0 401 },
michael@0 402
michael@0 403 has: function ss_has(aName) {
michael@0 404 return this._storage.hasOwnProperty(aName);
michael@0 405 },
michael@0 406
michael@0 407 set: function ss_set(aName, aValue) {
michael@0 408 this._storage[aName] = aValue;
michael@0 409 this._events.dispatch("change", aName);
michael@0 410 },
michael@0 411
michael@0 412 get: function ss_get(aName, aDefaultValue) {
michael@0 413 return this.has(aName) ? this._storage[aName] : aDefaultValue;
michael@0 414 },
michael@0 415
michael@0 416 QueryInterface : XPCOMUtils.generateQI([Ci.extISessionStorage])
michael@0 417 };
michael@0 418
michael@0 419 //=================================================
michael@0 420 // ExtensionObserver constructor (internal class)
michael@0 421 //
michael@0 422 // ExtensionObserver is a global singleton which watches the browser's
michael@0 423 // extensions and sends you events when things change.
michael@0 424
michael@0 425 function ExtensionObserver() {
michael@0 426 this._eventsDict = {};
michael@0 427
michael@0 428 AddonManager.addAddonListener(this);
michael@0 429 AddonManager.addInstallListener(this);
michael@0 430 }
michael@0 431
michael@0 432 //=================================================
michael@0 433 // ExtensionObserver implementation (internal class)
michael@0 434 ExtensionObserver.prototype = {
michael@0 435 onDisabling: function eo_onDisabling(addon, needsRestart) {
michael@0 436 this._dispatchEvent(addon.id, "disable");
michael@0 437 },
michael@0 438
michael@0 439 onEnabling: function eo_onEnabling(addon, needsRestart) {
michael@0 440 this._dispatchEvent(addon.id, "enable");
michael@0 441 },
michael@0 442
michael@0 443 onUninstalling: function eo_onUninstalling(addon, needsRestart) {
michael@0 444 this._dispatchEvent(addon.id, "uninstall");
michael@0 445 },
michael@0 446
michael@0 447 onOperationCancelled: function eo_onOperationCancelled(addon) {
michael@0 448 this._dispatchEvent(addon.id, "cancel");
michael@0 449 },
michael@0 450
michael@0 451 onInstallEnded: function eo_onInstallEnded(install, addon) {
michael@0 452 this._dispatchEvent(addon.id, "upgrade");
michael@0 453 },
michael@0 454
michael@0 455 addListener: function eo_al(aId, aEvent, aListener) {
michael@0 456 var events = this._eventsDict[aId];
michael@0 457 if (!events) {
michael@0 458 events = new Events();
michael@0 459 this._eventsDict[aId] = events;
michael@0 460 }
michael@0 461 events.addListener(aEvent, aListener);
michael@0 462 },
michael@0 463
michael@0 464 removeListener: function eo_rl(aId, aEvent, aListener) {
michael@0 465 var events = this._eventsDict[aId];
michael@0 466 if (!events) {
michael@0 467 return;
michael@0 468 }
michael@0 469 events.removeListener(aEvent, aListener);
michael@0 470 if (events._listeners.length == 0) {
michael@0 471 delete this._eventsDict[aId];
michael@0 472 }
michael@0 473 },
michael@0 474
michael@0 475 _dispatchEvent: function eo_dispatchEvent(aId, aEvent) {
michael@0 476 var events = this._eventsDict[aId];
michael@0 477 if (events) {
michael@0 478 events.dispatch(aEvent, aId);
michael@0 479 }
michael@0 480 }
michael@0 481 };
michael@0 482
michael@0 483 //=================================================
michael@0 484 // Extension constructor
michael@0 485 function Extension(aItem) {
michael@0 486 this._item = aItem;
michael@0 487 this._firstRun = false;
michael@0 488 this._prefs = new PreferenceBranch("extensions." + this.id + ".");
michael@0 489 this._storage = new SessionStorage();
michael@0 490
michael@0 491 let id = this.id;
michael@0 492 this._events = {
michael@0 493 addListener: function ext_events_al(aEvent, aListener) {
michael@0 494 gExtensionObserver.addListener(id, aEvent, aListener);
michael@0 495 },
michael@0 496 removeListener: function ext_events_rl(aEvent, aListener) {
michael@0 497 gExtensionObserver.addListener(id, aEvent, aListener);
michael@0 498 },
michael@0 499 QueryInterface: XPCOMUtils.generateQI([Ci.extIEvents])
michael@0 500 };
michael@0 501
michael@0 502 var installPref = "install-event-fired";
michael@0 503 if (!this._prefs.has(installPref)) {
michael@0 504 this._prefs.setValue(installPref, true);
michael@0 505 this._firstRun = true;
michael@0 506 }
michael@0 507 }
michael@0 508
michael@0 509 //=================================================
michael@0 510 // Extension implementation
michael@0 511 Extension.prototype = {
michael@0 512 get id() {
michael@0 513 return this._item.id;
michael@0 514 },
michael@0 515
michael@0 516 get name() {
michael@0 517 return this._item.name;
michael@0 518 },
michael@0 519
michael@0 520 get enabled() {
michael@0 521 return this._item.isActive;
michael@0 522 },
michael@0 523
michael@0 524 get version() {
michael@0 525 return this._item.version;
michael@0 526 },
michael@0 527
michael@0 528 get firstRun() {
michael@0 529 return this._firstRun;
michael@0 530 },
michael@0 531
michael@0 532 get storage() {
michael@0 533 return this._storage;
michael@0 534 },
michael@0 535
michael@0 536 get prefs() {
michael@0 537 return this._prefs;
michael@0 538 },
michael@0 539
michael@0 540 get events() {
michael@0 541 return this._events;
michael@0 542 },
michael@0 543
michael@0 544 QueryInterface: XPCOMUtils.generateQI([Ci.extIExtension])
michael@0 545 };
michael@0 546
michael@0 547
michael@0 548 //=================================================
michael@0 549 // Extensions constructor
michael@0 550 function Extensions(addons) {
michael@0 551 this._cache = {};
michael@0 552
michael@0 553 addons.forEach(function (addon) {
michael@0 554 this._cache[addon.id] = new Extension(addon);
michael@0 555 }, this);
michael@0 556 }
michael@0 557
michael@0 558 //=================================================
michael@0 559 // Extensions implementation
michael@0 560 Extensions.prototype = {
michael@0 561 get all() {
michael@0 562 return this.find({});
michael@0 563 },
michael@0 564
michael@0 565 // XXX: Disabled until we can figure out the wrapped object issues
michael@0 566 // id: "some@id" or /id/
michael@0 567 // name: "name" or /name/
michael@0 568 // version: "1.0.1"
michael@0 569 // minVersion: "1.0"
michael@0 570 // maxVersion: "2.0"
michael@0 571 find: function exts_find(aOptions) {
michael@0 572 return [e for each (e in this._cache)];
michael@0 573 },
michael@0 574
michael@0 575 has: function exts_has(aId) {
michael@0 576 return aId in this._cache;
michael@0 577 },
michael@0 578
michael@0 579 get: function exts_get(aId) {
michael@0 580 return this.has(aId) ? this._cache[aId] : null;
michael@0 581 },
michael@0 582
michael@0 583 QueryInterface: XPCOMUtils.generateQI([Ci.extIExtensions])
michael@0 584 };
michael@0 585
michael@0 586 //=================================================
michael@0 587 // Application globals
michael@0 588
michael@0 589 gExtensionObserver = new ExtensionObserver();
michael@0 590 gPreferenceObserver = new PreferenceObserver();
michael@0 591
michael@0 592 //=================================================
michael@0 593 // extApplication constructor
michael@0 594 function extApplication() {
michael@0 595 }
michael@0 596
michael@0 597 //=================================================
michael@0 598 // extApplication implementation
michael@0 599 extApplication.prototype = {
michael@0 600 initToolkitHelpers: function extApp_initToolkitHelpers() {
michael@0 601 XPCOMUtils.defineLazyServiceGetter(this, "_info",
michael@0 602 "@mozilla.org/xre/app-info;1",
michael@0 603 "nsIXULAppInfo");
michael@0 604
michael@0 605 this._obs = Cc["@mozilla.org/observer-service;1"].
michael@0 606 getService(Ci.nsIObserverService);
michael@0 607 this._obs.addObserver(this, "xpcom-shutdown", /* ownsWeak = */ true);
michael@0 608 this._registered = {"unload": true};
michael@0 609 },
michael@0 610
michael@0 611 classInfo: XPCOMUtils.generateCI({interfaces: [Ci.extIApplication,
michael@0 612 Ci.nsIObserver],
michael@0 613 flags: Ci.nsIClassInfo.SINGLETON}),
michael@0 614
michael@0 615 // extIApplication
michael@0 616 get id() {
michael@0 617 return this._info.ID;
michael@0 618 },
michael@0 619
michael@0 620 get name() {
michael@0 621 return this._info.name;
michael@0 622 },
michael@0 623
michael@0 624 get version() {
michael@0 625 return this._info.version;
michael@0 626 },
michael@0 627
michael@0 628 // for nsIObserver
michael@0 629 observe: function app_observe(aSubject, aTopic, aData) {
michael@0 630 if (aTopic == "app-startup") {
michael@0 631 this.events.dispatch("load", "application");
michael@0 632 }
michael@0 633 else if (aTopic == "final-ui-startup") {
michael@0 634 this.events.dispatch("ready", "application");
michael@0 635 }
michael@0 636 else if (aTopic == "quit-application-requested") {
michael@0 637 // we can stop the quit by checking the return value
michael@0 638 if (this.events.dispatch("quit", "application") == false)
michael@0 639 aSubject.data = true;
michael@0 640 }
michael@0 641 else if (aTopic == "xpcom-shutdown") {
michael@0 642 this.events.dispatch("unload", "application");
michael@0 643 gExtensionObserver = null;
michael@0 644 gPreferenceObserver = null;
michael@0 645 }
michael@0 646 },
michael@0 647
michael@0 648 get console() {
michael@0 649 let console = new Console();
michael@0 650 this.__defineGetter__("console", function () console);
michael@0 651 return this.console;
michael@0 652 },
michael@0 653
michael@0 654 get storage() {
michael@0 655 let storage = new SessionStorage();
michael@0 656 this.__defineGetter__("storage", function () storage);
michael@0 657 return this.storage;
michael@0 658 },
michael@0 659
michael@0 660 get prefs() {
michael@0 661 let prefs = new PreferenceBranch("");
michael@0 662 this.__defineGetter__("prefs", function () prefs);
michael@0 663 return this.prefs;
michael@0 664 },
michael@0 665
michael@0 666 getExtensions: function(callback) {
michael@0 667 AddonManager.getAddonsByTypes(["extension"], function (addons) {
michael@0 668 callback.callback(new Extensions(addons));
michael@0 669 });
michael@0 670 },
michael@0 671
michael@0 672 get events() {
michael@0 673
michael@0 674 // This ensures that FUEL only registers for notifications as needed
michael@0 675 // by callers. Note that the unload (xpcom-shutdown) event is listened
michael@0 676 // for by default, as it's needed for cleanup purposes.
michael@0 677 var self = this;
michael@0 678 function registerCheck(aEvent) {
michael@0 679 var rmap = { "load": "app-startup",
michael@0 680 "ready": "final-ui-startup",
michael@0 681 "quit": "quit-application-requested"};
michael@0 682 if (!(aEvent in rmap) || aEvent in self._registered)
michael@0 683 return;
michael@0 684
michael@0 685 self._obs.addObserver(self, rmap[aEvent], /* ownsWeak = */ true);
michael@0 686 self._registered[aEvent] = true;
michael@0 687 }
michael@0 688
michael@0 689 let events = new Events(registerCheck);
michael@0 690 this.__defineGetter__("events", function () events);
michael@0 691 return this.events;
michael@0 692 },
michael@0 693
michael@0 694 // helper method for correct quitting/restarting
michael@0 695 _quitWithFlags: function app__quitWithFlags(aFlags) {
michael@0 696 let cancelQuit = Components.classes["@mozilla.org/supports-PRBool;1"]
michael@0 697 .createInstance(Components.interfaces.nsISupportsPRBool);
michael@0 698 let quitType = aFlags & Components.interfaces.nsIAppStartup.eRestart ? "restart" : null;
michael@0 699 this._obs.notifyObservers(cancelQuit, "quit-application-requested", quitType);
michael@0 700 if (cancelQuit.data)
michael@0 701 return false; // somebody canceled our quit request
michael@0 702
michael@0 703 let appStartup = Components.classes['@mozilla.org/toolkit/app-startup;1']
michael@0 704 .getService(Components.interfaces.nsIAppStartup);
michael@0 705 appStartup.quit(aFlags);
michael@0 706 return true;
michael@0 707 },
michael@0 708
michael@0 709 quit: function app_quit() {
michael@0 710 return this._quitWithFlags(Components.interfaces.nsIAppStartup.eAttemptQuit);
michael@0 711 },
michael@0 712
michael@0 713 restart: function app_restart() {
michael@0 714 return this._quitWithFlags(Components.interfaces.nsIAppStartup.eAttemptQuit |
michael@0 715 Components.interfaces.nsIAppStartup.eRestart);
michael@0 716 },
michael@0 717
michael@0 718 QueryInterface: XPCOMUtils.generateQI([Ci.extIApplication, Ci.nsISupportsWeakReference])
michael@0 719 };

mercurial