tor-browser

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

browser_navigator_clipboard_contextmenu_suppression_ext.js (4498B)


      1 /* -*- Mode: JavaScript; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 "use strict";
      8 requestLongerTimeout(2);
      9 
     10 const kContentFileUrl = kBaseUrlForContent + "file_toplevel.html";
     11 const kIsMac = navigator.platform.indexOf("Mac") > -1;
     12 
     13 async function waitForPasteContextMenu() {
     14  await waitForPasteMenuPopupEvent("shown");
     15  let pasteButton = document.getElementById(kPasteMenuItemId);
     16  info("Wait for paste button enabled");
     17  await BrowserTestUtils.waitForMutationCondition(
     18    pasteButton,
     19    { attributeFilter: ["disabled"] },
     20    () => !pasteButton.disabled,
     21    "Wait for paste button enabled"
     22  );
     23 }
     24 
     25 async function readText(aBrowser) {
     26  return SpecialPowers.spawn(aBrowser, [], async () => {
     27    content.document.notifyUserGestureActivation();
     28    return content.eval(`navigator.clipboard.readText();`);
     29  });
     30 }
     31 
     32 async function testPasteContextMenu(
     33  aBrowser,
     34  aClipboardText,
     35  aShouldShow = true
     36 ) {
     37  let pasteButtonIsShown;
     38  if (aShouldShow) {
     39    pasteButtonIsShown = waitForPasteContextMenu();
     40  }
     41  let readTextRequest = readText(aBrowser);
     42  if (aShouldShow) {
     43    await pasteButtonIsShown;
     44  }
     45 
     46  info("Click paste button, request should be resolved");
     47  if (aShouldShow) {
     48    await promiseClickPasteButton();
     49  }
     50  is(await readTextRequest, aClipboardText, "Request should be resolved");
     51 }
     52 
     53 async function installAndStartExtension(aContentScript) {
     54  let extension = ExtensionTestUtils.loadExtension({
     55    manifest: {
     56      content_scripts: [
     57        {
     58          js: ["content_script.js"],
     59          matches: ["https://example.com/*/file_toplevel.html"],
     60        },
     61      ],
     62    },
     63    files: {
     64      "content_script.js": aContentScript,
     65    },
     66  });
     67 
     68  await extension.startup();
     69 
     70  return extension;
     71 }
     72 
     73 function testExtensionContentScript(aContentScript, aMessage) {
     74  add_task(async function test_context_menu_suppression_ext() {
     75    info(`${aMessage}`);
     76    const extension = await installAndStartExtension(aContentScript);
     77    await BrowserTestUtils.withNewTab(
     78      kContentFileUrl,
     79      async function (browser) {
     80        const clipboardText = "X" + Math.random();
     81        await SpecialPowers.spawn(browser, [clipboardText], async text => {
     82          info(`Set clipboard text to ${text}`);
     83          let div = content.document.createElement("div");
     84          div.id = "container";
     85          div.innerText = text;
     86          content.document.documentElement.appendChild(div);
     87        });
     88 
     89        let writePromise = extension.awaitMessage("write-data-ready");
     90        // trigger keyboard shortcut to copy.
     91        await EventUtils.synthesizeAndWaitKey(
     92          "c",
     93          kIsMac ? { accelKey: true } : { ctrlKey: true }
     94        );
     95        // Wait a bit for clipboard write.
     96        await writePromise;
     97 
     98        info("Test read from same frame");
     99        await testPasteContextMenu(browser, clipboardText, false);
    100 
    101        info("Test read from same-origin subframe");
    102        await testPasteContextMenu(
    103          browser.browsingContext.children[0],
    104          clipboardText,
    105          false
    106        );
    107 
    108        info("Test read from cross-origin subframe");
    109        await testPasteContextMenu(
    110          browser.browsingContext.children[1],
    111          clipboardText,
    112          true
    113        );
    114      }
    115    );
    116 
    117    await extension.unload();
    118  });
    119 }
    120 
    121 add_setup(async function () {
    122  await SpecialPowers.pushPrefEnv({
    123    set: [
    124      ["test.events.async.enabled", true],
    125      // Avoid paste button delay enabling making test too long.
    126      ["security.dialog_enable_delay", 0],
    127    ],
    128  });
    129 });
    130 
    131 testExtensionContentScript(() => {
    132  document.addEventListener("copy", function (e) {
    133    e.preventDefault();
    134    let div = document.getElementById("container");
    135    let text = div.innerText;
    136    e.clipboardData.setData("text/plain", text);
    137    browser.test.sendMessage("write-data-ready");
    138  });
    139 }, "Write data by DataTransfer API in extension");
    140 
    141 testExtensionContentScript(() => {
    142  document.addEventListener("copy", async function (e) {
    143    e.preventDefault();
    144    let div = document.getElementById("container");
    145    let text = div.innerText;
    146    await navigator.clipboard.writeText(text);
    147    browser.test.sendMessage("write-data-ready");
    148  });
    149 }, "Write data by Async Clipboard API in extension");