Bumping manifests a=b2g-bump
[gecko.git] / b2g / components / SystemAppProxy.jsm
blob54bdb2b699167dd98ab2b5cc4f0032d3a87bfdf2
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/. */
5 'use strict';
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 = {
15   _frame: null,
16   _isReady: false,
17   _pendingEvents: [],
18   _pendingListeners: [],
20   // To call when a new system app iframe is created
21   registerFrame: function (frame) {
22     this._isReady = false;
23     this._frame = frame;
25     // Register all DOM event listeners added before we got a ref to the app iframe
26     this._pendingListeners
27         .forEach((args) =>
28                  this.addEventListener.apply(this, args));
29     this._pendingListeners = [];
30   },
32   // To call when it is ready to receive events
33   setIsReady: function () {
34     if (this._isReady) {
35       Cu.reportError('SystemApp has already been declared as being ready.');
36     }
37     this._isReady = true;
39     // Dispatch all events being queued while the system app was still loading
40     this._pendingEvents
41         .forEach(([type, details]) =>
42                  this._sendCustomEvent(type, details));
43     this._pendingEvents = [];
44   },
46   /*
47    * Common way to send an event to the system app.
48    *
49    * // In gecko code:
50    *   SystemAppProxy.sendCustomEvent('foo', { data: 'bar' });
51    * // In system app:
52    *   window.addEventListener('foo', function (event) {
53    *     event.details == 'bar'
54    *   });
55    *
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
59    *                    app is ready.
60    */
61   _sendCustomEvent: function systemApp_sendCustomEvent(type,
62                                                        details,
63                                                        noPending,
64                                                        target) {
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]);
71       return null;
72     }
74     let event = content.document.createEvent('CustomEvent');
76     let payload;
77     // If the root object already has __exposedProps__,
78     // we consider the caller already wrapped (correctly) the object.
79     if ('__exposedProps__' in details) {
80       payload = details;
81     } else {
82       payload = details ? Cu.cloneInto(details, content) : {};
83     }
85     event.initCustomEvent(type, true, false, payload);
86     (target || content).dispatchEvent(event);
88     return event;
89   },
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);
94   },
96   // Listen for dom events on the system app
97   addEventListener: function systemApp_addEventListener() {
98     let content = this._frame ? this._frame.contentWindow : null;
99     if (!content) {
100       this._pendingListeners.push(arguments);
101       return false;
102     }
104     content.addEventListener.apply(content, arguments);
105     return true;
106   },
108   removeEventListener: function systemApp_removeEventListener(name, listener) {
109     let content = this._frame ? this._frame.contentWindow : null;
110     if (content) {
111       content.removeEventListener.apply(content, arguments);
112     } else {
113       let idx = this._pendingListeners.indexOf(listener);
114       if (idx != -1) {
115         this._pendingListeners.splice(idx, 1);
116       }
117     }
118   },
120   getAppFrames: function systemApp_getAppFrames() {
121     let systemAppFrame = this._frame;
122     if (!systemAppFrame) {
123       return [];
124     }
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]);
135     }
137     return list;
138   }
140 this.SystemAppProxy = SystemAppProxy;