tor-browser

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

AppUiTestDelegate.sys.mjs (4129B)


      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 const lazy = {};
      6 
      7 ChromeUtils.defineESModuleGetters(lazy, {
      8  EventDispatcher: "resource://gre/modules/Messaging.sys.mjs",
      9  GeckoViewTabBridge: "resource://gre/modules/GeckoViewTab.sys.mjs",
     10  mobileWindowTracker: "resource://gre/modules/GeckoViewWebExtension.sys.mjs",
     11 });
     12 
     13 const TEST_SUPPORT_EXTENSION_ID = "test-runner-support@tests.mozilla.org";
     14 
     15 /**
     16 * The implementation of AppUiTestDelegate. All implementations need to be kept
     17 * in sync. For details, see:
     18 * testing/specialpowers/content/AppTestDelegateParent.sys.mjs
     19 *
     20 * This implementation mostly forwards calls to TestRunnerApiEngine in
     21 * mobile/android/test_runner/src/main/java/org/mozilla/geckoview/test_runner/TestRunnerApiEngine.java
     22 */
     23 class Delegate {
     24  _sendMessageToApp(data) {
     25    // "GeckoView:WebExtension:Message" with the "nativeApp" property set is a
     26    // message usually emitted by the runtime.sendNativeMessage implementation.
     27    //
     28    // Although a dummy extension with ID TEST_SUPPORT_EXTENSION_ID is installed
     29    // by TestRunnerActivity, the sendNativeMessage API is not used directly.
     30    // Instead, we forge a message in the same (internal) format here.
     31    //
     32    // The message is ultimately received and handled by TestRunnerApiEngine at
     33    // mobile/android/test_runner/src/main/java/org/mozilla/geckoview/test_runner/TestRunnerApiEngine.java
     34    const message = {
     35      type: "GeckoView:WebExtension:Message",
     36      sender: {
     37        envType: "addon_child",
     38        url: "test-runner-support:///",
     39      },
     40      data,
     41      extensionId: TEST_SUPPORT_EXTENSION_ID,
     42      nativeApp: "test-runner-support",
     43    };
     44 
     45    return lazy.EventDispatcher.instance.sendRequestForResult(message);
     46  }
     47 
     48  clickPageAction(window, extensionId) {
     49    return this._sendMessageToApp({ type: "clickPageAction", extensionId });
     50  }
     51 
     52  clickBrowserAction(window, extensionId) {
     53    return this._sendMessageToApp({ type: "clickBrowserAction", extensionId });
     54  }
     55 
     56  closePageAction(window, extensionId) {
     57    return this._sendMessageToApp({ type: "closePageAction", extensionId });
     58  }
     59 
     60  closeBrowserAction(window, extensionId) {
     61    return this._sendMessageToApp({ type: "closeBrowserAction", extensionId });
     62  }
     63 
     64  awaitExtensionPanel(window, extensionId) {
     65    return this._sendMessageToApp({ type: "awaitExtensionPanel", extensionId });
     66  }
     67 
     68  async removeTab(tab) {
     69    const window = tab.browser.ownerGlobal;
     70    await lazy.GeckoViewTabBridge.closeTab({
     71      window,
     72      extensionId: TEST_SUPPORT_EXTENSION_ID,
     73    });
     74  }
     75 
     76  async openNewForegroundTab(window, url, waitForLoad = true) {
     77    const tab = await lazy.GeckoViewTabBridge.createNewTab({
     78      extensionId: TEST_SUPPORT_EXTENSION_ID,
     79      createProperties: {
     80        url,
     81        active: true,
     82      },
     83    });
     84 
     85    const { browser } = tab;
     86    const triggeringPrincipal =
     87      Services.scriptSecurityManager.createContentPrincipal(
     88        Services.io.newURI(url),
     89        {}
     90      );
     91 
     92    browser.fixupAndLoadURIString(url, {
     93      loadFlags: Ci.nsIWebNavigation.LOAD_FLAGS_NONE,
     94      triggeringPrincipal,
     95    });
     96 
     97    const newWindow = browser.ownerGlobal;
     98    lazy.mobileWindowTracker.setTabActive(newWindow, true);
     99 
    100    if (!waitForLoad) {
    101      return tab;
    102    }
    103 
    104    return new Promise(resolve => {
    105      const listener = ev => {
    106        const { browsingContext, internalURL } = ev.detail;
    107 
    108        // Sometimes we arrive here without an internalURL. If that's the
    109        // case, just keep waiting until we get one.
    110        if (!internalURL || internalURL == "about:blank") {
    111          return;
    112        }
    113 
    114        // Ignore subframes
    115        if (browsingContext !== browsingContext.top) {
    116          return;
    117        }
    118 
    119        resolve(tab);
    120        browser.removeEventListener("AppTestDelegate:load", listener, true);
    121      };
    122      browser.addEventListener("AppTestDelegate:load", listener, true);
    123    });
    124  }
    125 }
    126 
    127 export var AppUiTestDelegate = new Delegate();