tor-browser

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

AppTestDelegateParent.sys.mjs (4976B)


      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
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 /**
      6 * This module provides the bridge between the "AppTestDelegate" helper in
      7 * mochitests and the supporting implementations in AppUiTestDelegate.sys.mjs.
      8 *
      9 * "AppTestDelegate" is documented in AppTestDelegate.sys.mjs and enables
     10 * mochitests to invoke common functionality whose implementation is different
     11 * (e.g. in browser/ and mobile/ instead of toolkit/).
     12 * Tests can use this common interface after importing AppTestDelegate.sys.mjs:
     13 *
     14 *     // head.js, in the scope of a plain mochitest:
     15 *     var { AppTestDelegate } = SpecialPowers.ChromeUtils.importESModule(
     16 *       "resource://specialpowers/AppTestDelegate.sys.mjs"
     17 *     );
     18 *
     19 *     // test usage example: open and close a tab.
     20 *     let tab = await AppTestDelegate.openNewForegroundTab(window, url);
     21 *     await AppTestDelegate.removeTab(window, tab);
     22 *
     23 * ## Overview of files supporting "AppTestDelegate":
     24 *
     25 * MOZ_BUILD_APP-specific AppUiTestDelegate.sys.mjs implementations:
     26 * - browser/components/extensions/test/AppUiTestDelegate.sys.mjs
     27 * - mobile/shared/modules/test/AppUiTestDelegate.sys.mjs
     28 * - mail/components/extensions/test/AppUiTestDelegate.sys.mjs (in comm-central)
     29 *
     30 * Glue between AppUiTestDelegate.sys.mjs in parent and test code in child:
     31 * - testing/specialpowers/content/AppTestDelegateParent.sys.mjs (this file)
     32 * - testing/specialpowers/content/AppTestDelegateChild.sys.mjs
     33 * - testing/specialpowers/content/AppTestDelegate.sys.mjs
     34 *
     35 * Setup for usage by test code in child (i.e. plain mochitests):
     36 * - Import AppTestDelegate.sys.mjs (e.g. in head.js or the test)
     37 *
     38 * Note: some browser-chrome tests import AppUiTestDelegate.sys.mjs directly,
     39 * but that is not part of this API contract. They merely reuse code.
     40 *
     41 * ## How to add new AppTestDelegate methods
     42 *
     43 * - Add the method to AppTestDelegate.sys.mjs
     44 * - Add a message forwarder in AppTestDelegateChild.sys.mjs
     45 * - Add a message handler in AppTestDelegateParent.sys.mjs
     46 * - Add an implementation in AppUiTestDelegate.sys.mjs for each MOZ_BUILD_APP,
     47 *   by defining the method on the exported AppUiTestDelegate object.
     48 *   All AppUiTestDelegate implementations must be kept in sync to have the
     49 *   same interface!
     50 *
     51 * You should use the same method name across all of these files for ease of
     52 * lookup and maintainability.
     53 */
     54 
     55 const lazy = {};
     56 
     57 ChromeUtils.defineESModuleGetters(lazy, {
     58  // Each app needs to implement this - see above comment.
     59  AppUiTestDelegate: "resource://testing-common/AppUiTestDelegate.sys.mjs",
     60 });
     61 
     62 export class AppTestDelegateParent extends JSWindowActorParent {
     63  constructor() {
     64    super();
     65    this._tabs = new Map();
     66  }
     67 
     68  get browser() {
     69    return this.browsingContext.top.embedderElement;
     70  }
     71 
     72  get window() {
     73    return this.browser.ownerGlobal;
     74  }
     75 
     76  async receiveMessage(message) {
     77    const { extensionId, url, waitForLoad, tabId } = message.data;
     78    switch (message.name) {
     79      case "DOMContentLoaded":
     80      case "load": {
     81        return this.browser?.dispatchEvent(
     82          new CustomEvent(`AppTestDelegate:${message.name}`, {
     83            detail: {
     84              browsingContext: this.browsingContext,
     85              ...message.data,
     86            },
     87          })
     88        );
     89      }
     90      case "clickPageAction":
     91        return lazy.AppUiTestDelegate.clickPageAction(this.window, extensionId);
     92      case "clickBrowserAction":
     93        return lazy.AppUiTestDelegate.clickBrowserAction(
     94          this.window,
     95          extensionId
     96        );
     97      case "closePageAction":
     98        return lazy.AppUiTestDelegate.closePageAction(this.window, extensionId);
     99      case "closeBrowserAction":
    100        return lazy.AppUiTestDelegate.closeBrowserAction(
    101          this.window,
    102          extensionId
    103        );
    104      case "awaitExtensionPanel":
    105        // The desktop delegate returns a <browser>, but that cannot be sent
    106        // over IPC, so just ignore it. The promise resolves when the panel and
    107        // its content is fully loaded.
    108        await lazy.AppUiTestDelegate.awaitExtensionPanel(
    109          this.window,
    110          extensionId
    111        );
    112        return null;
    113      case "openNewForegroundTab": {
    114        // We cannot send the tab object across process so let's store it with
    115        // a unique ID here.
    116        const uuid = Services.uuid.generateUUID().toString();
    117        const tab = await lazy.AppUiTestDelegate.openNewForegroundTab(
    118          this.window,
    119          url,
    120          waitForLoad
    121        );
    122        this._tabs.set(uuid, tab);
    123        return uuid;
    124      }
    125      case "removeTab": {
    126        const tab = this._tabs.get(tabId);
    127        this._tabs.delete(tabId);
    128        return lazy.AppUiTestDelegate.removeTab(tab);
    129      }
    130 
    131      default:
    132        throw new Error(`Unknown Test API: ${message.name}.`);
    133    }
    134  }
    135 }