1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/b2g/components/SystemAppProxy.jsm Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,114 @@ 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 file, 1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +'use strict'; 1.9 + 1.10 +const { classes: Cc, interfaces: Ci, utils: Cu } = Components; 1.11 + 1.12 +Cu.import('resource://gre/modules/XPCOMUtils.jsm'); 1.13 +Cu.import('resource://gre/modules/Services.jsm'); 1.14 + 1.15 +this.EXPORTED_SYMBOLS = ['SystemAppProxy']; 1.16 + 1.17 +let SystemAppProxy = { 1.18 + _frame: null, 1.19 + _isReady: false, 1.20 + _pendingEvents: [], 1.21 + _pendingListeners: [], 1.22 + 1.23 + // To call when a new system app iframe is created 1.24 + registerFrame: function (frame) { 1.25 + this._isReady = false; 1.26 + this._frame = frame; 1.27 + 1.28 + // Register all DOM event listeners added before we got a ref to the app iframe 1.29 + this._pendingListeners 1.30 + .forEach((args) => 1.31 + this.addEventListener.apply(this, args)); 1.32 + this._pendingListeners = []; 1.33 + }, 1.34 + 1.35 + // To call when it is ready to receive events 1.36 + setIsReady: function () { 1.37 + if (this._isReady) { 1.38 + Cu.reportError('SystemApp has already been declared as being ready.'); 1.39 + } 1.40 + this._isReady = true; 1.41 + 1.42 + // Dispatch all events being queued while the system app was still loading 1.43 + this._pendingEvents 1.44 + .forEach(([type, details]) => 1.45 + this._sendCustomEvent(type, details)); 1.46 + this._pendingEvents = []; 1.47 + }, 1.48 + 1.49 + /* 1.50 + * Common way to send an event to the system app. 1.51 + * 1.52 + * // In gecko code: 1.53 + * SystemAppProxy.sendCustomEvent('foo', { data: 'bar' }); 1.54 + * // In system app: 1.55 + * window.addEventListener('foo', function (event) { 1.56 + * event.details == 'bar' 1.57 + * }); 1.58 + */ 1.59 + _sendCustomEvent: function systemApp_sendCustomEvent(type, details) { 1.60 + let content = this._frame ? this._frame.contentWindow : null; 1.61 + 1.62 + // If the system app isn't ready yet, 1.63 + // queue events until someone calls setIsLoaded 1.64 + if (!this._isReady || !content) { 1.65 + this._pendingEvents.push([type, details]); 1.66 + return null; 1.67 + } 1.68 + 1.69 + let event = content.document.createEvent('CustomEvent'); 1.70 + 1.71 + let payload; 1.72 + // If the root object already has __exposedProps__, 1.73 + // we consider the caller already wrapped (correctly) the object. 1.74 + if ('__exposedProps__' in details) { 1.75 + payload = details; 1.76 + } else { 1.77 + payload = details ? Cu.cloneInto(details, content) : {}; 1.78 + } 1.79 + 1.80 + event.initCustomEvent(type, true, false, payload); 1.81 + content.dispatchEvent(event); 1.82 + 1.83 + return event; 1.84 + }, 1.85 + 1.86 + // Now deprecated, use sendCustomEvent with a custom event name 1.87 + dispatchEvent: function systemApp_sendChromeEvent(details) { 1.88 + return this._sendCustomEvent('mozChromeEvent', details); 1.89 + }, 1.90 + 1.91 + // Listen for dom events on the system app 1.92 + addEventListener: function systemApp_addEventListener() { 1.93 + let content = this._frame ? this._frame.contentWindow : null; 1.94 + if (!content) { 1.95 + this._pendingListeners.push(arguments); 1.96 + return false; 1.97 + } 1.98 + 1.99 + content.addEventListener.apply(content, arguments); 1.100 + return true; 1.101 + }, 1.102 + 1.103 + removeEventListener: function systemApp_removeEventListener(name, listener) { 1.104 + let content = this._frame ? this._frame.contentWindow : null; 1.105 + if (content) { 1.106 + content.removeEventListener.apply(content, arguments); 1.107 + } else { 1.108 + let idx = this._pendingListeners.indexOf(listener); 1.109 + if (idx != -1) { 1.110 + this._pendingListeners.splice(idx, 1); 1.111 + } 1.112 + } 1.113 + } 1.114 + 1.115 +}; 1.116 +this.SystemAppProxy = SystemAppProxy; 1.117 +