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