tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ASRouterChild.sys.mjs (3548B)


      1 /* vim: set ts=2 sw=2 sts=2 et tw=80: */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 // We use importESModule here instead of static import so that
      7 // the Karma test environment won't choke on this module. This
      8 // is because the Karma test environment already stubs out
      9 // MESSAGE_TYPE_LIST and MESSAGE_TYPE_HASH, and overrides importESModule
     10 // to be a no-op (which can't be done for a static import statement).
     11 
     12 // eslint-disable-next-line mozilla/use-static-import
     13 const { MESSAGE_TYPE_LIST, MESSAGE_TYPE_HASH: msg } =
     14  ChromeUtils.importESModule("resource:///modules/asrouter/ActorConstants.mjs");
     15 
     16 const VALID_TYPES = new Set(MESSAGE_TYPE_LIST);
     17 
     18 export class ASRouterChild extends JSWindowActorChild {
     19  constructor() {
     20    super();
     21    this.observers = new Set();
     22  }
     23 
     24  didDestroy() {
     25    this.observers.clear();
     26  }
     27 
     28  actorCreated() {
     29    // NOTE: DOMDocElementInserted may be called multiple times per
     30    // PWindowGlobal due to the initial about:blank document's window global
     31    // being re-used.
     32    const window = this.contentWindow;
     33    Cu.exportFunction(this.asRouterMessage.bind(this), window, {
     34      defineAs: "ASRouterMessage",
     35    });
     36    Cu.exportFunction(this.addParentListener.bind(this), window, {
     37      defineAs: "ASRouterAddParentListener",
     38    });
     39    Cu.exportFunction(this.removeParentListener.bind(this), window, {
     40      defineAs: "ASRouterRemoveParentListener",
     41    });
     42  }
     43 
     44  handleEvent() {
     45    // DOMDocElementCreated is only used to create the actor.
     46  }
     47 
     48  addParentListener(listener) {
     49    this.observers.add(listener);
     50  }
     51 
     52  removeParentListener(listener) {
     53    this.observers.delete(listener);
     54  }
     55 
     56  receiveMessage({ name, data }) {
     57    switch (name) {
     58      case "UpdateAdminState":
     59      case "ClearProviders": {
     60        this.observers.forEach(listener => {
     61          let result = Cu.cloneInto(
     62            {
     63              type: name,
     64              data,
     65            },
     66            this.contentWindow
     67          );
     68          listener(result);
     69        });
     70        break;
     71      }
     72    }
     73  }
     74 
     75  wrapPromise(promise) {
     76    return new this.contentWindow.Promise((resolve, reject) =>
     77      promise.then(resolve, reject)
     78    );
     79  }
     80 
     81  sendQuery(aName, aData = null) {
     82    return this.wrapPromise(
     83      new Promise(resolve => {
     84        super.sendQuery(aName, aData).then(result => {
     85          resolve(Cu.cloneInto(result, this.contentWindow));
     86        });
     87      })
     88    );
     89  }
     90 
     91  asRouterMessage({ type, data }) {
     92    // Some legacy privileged addons send this message, but it got removed from
     93    // VALID_TYPES in bug 1715158. Thankfully, these addons don't appear to
     94    // require any actions from this message - just a Promise that resolves.
     95    if (type === "NEWTAB_MESSAGE_REQUEST") {
     96      return this.wrapPromise(Promise.resolve());
     97    }
     98 
     99    if (VALID_TYPES.has(type)) {
    100      switch (type) {
    101        case msg.DISABLE_PROVIDER:
    102        case msg.ENABLE_PROVIDER:
    103        case msg.EXPIRE_QUERY_CACHE:
    104        case msg.FORCE_PRIVATE_BROWSING_WINDOW:
    105        case msg.IMPRESSION:
    106        case msg.RESET_PROVIDER_PREF:
    107        case msg.SET_PROVIDER_USER_PREF:
    108        case msg.USER_ACTION: {
    109          return this.sendAsyncMessage(type, data);
    110        }
    111        default: {
    112          // these messages need a response
    113          return this.sendQuery(type, data);
    114        }
    115      }
    116    }
    117    throw new Error(`Unexpected type "${type}"`);
    118  }
    119 }