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 file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
9 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
10 Cu.import('resource://gre/modules/Services.jsm');
12 this.EXPORTED_SYMBOLS = ['SystemAppProxy'];
14 let SystemAppProxy = {
18 _pendingListeners: [],
20 // To call when a new system app iframe is created
21 registerFrame: function (frame) {
22 this._isReady = false;
25 // Register all DOM event listeners added before we got a ref to the app iframe
26 this._pendingListeners
28 this.addEventListener.apply(this, args));
29 this._pendingListeners = [];
32 // To call when it is ready to receive events
33 setIsReady: function () {
35 Cu.reportError('SystemApp has already been declared as being ready.');
39 // Dispatch all events being queued while the system app was still loading
41 .forEach(([type, details]) =>
42 this._sendCustomEvent(type, details));
43 this._pendingEvents = [];
47 * Common way to send an event to the system app.
50 * SystemAppProxy.sendCustomEvent('foo', { data: 'bar' });
52 * window.addEventListener('foo', function (event) {
53 * event.details == 'bar'
56 * @param type The custom event type.
57 * @param details The event details.
58 * @param noPending Set to true to emit this event even before the system
61 _sendCustomEvent: function systemApp_sendCustomEvent(type,
65 let content = this._frame ? this._frame.contentWindow : null;
67 // If the system app isn't ready yet,
68 // queue events until someone calls setIsReady
69 if (!content || (!this._isReady && !noPending)) {
70 this._pendingEvents.push([type, details]);
74 let event = content.document.createEvent('CustomEvent');
77 // If the root object already has __exposedProps__,
78 // we consider the caller already wrapped (correctly) the object.
79 if ('__exposedProps__' in details) {
82 payload = details ? Cu.cloneInto(details, content) : {};
85 event.initCustomEvent(type, true, false, payload);
86 (target || content).dispatchEvent(event);
91 // Now deprecated, use sendCustomEvent with a custom event name
92 dispatchEvent: function systemApp_sendChromeEvent(details, target) {
93 return this._sendCustomEvent('mozChromeEvent', details, false, target);
96 // Listen for dom events on the system app
97 addEventListener: function systemApp_addEventListener() {
98 let content = this._frame ? this._frame.contentWindow : null;
100 this._pendingListeners.push(arguments);
104 content.addEventListener.apply(content, arguments);
108 removeEventListener: function systemApp_removeEventListener(name, listener) {
109 let content = this._frame ? this._frame.contentWindow : null;
111 content.removeEventListener.apply(content, arguments);
113 let idx = this._pendingListeners.indexOf(listener);
115 this._pendingListeners.splice(idx, 1);
120 getAppFrames: function systemApp_getAppFrames() {
121 let systemAppFrame = this._frame;
122 if (!systemAppFrame) {
126 let list = [systemAppFrame];
128 // List all app frames hosted in the system app: the homescreen,
129 // all regular apps, activities, rocket bar, attention screen and the keyboard.
130 // Bookmark apps and other system app internal frames like captive portal
131 // are also hosted in system app, but they are not using mozapp attribute.
132 let frames = systemAppFrame.contentDocument.querySelectorAll("iframe[mozapp]");
133 for (let i = 0; i < frames.length; i++) {
134 list.push(frames[i]);
140 this.SystemAppProxy = SystemAppProxy;