b2g/components/SystemAppProxy.jsm

changeset 0
6474c204b198
     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 +

mercurial