tor-browser

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

browser_document_command_paste_contextmenu_suppression.js (4764B)


      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 
      9 const kContentFileUrl = kBaseUrlForContent + "simple_page_ext.html";
     10 const kIsMac = navigator.platform.indexOf("Mac") > -1;
     11 
     12 const kSuppressionTests = [
     13  {
     14    description: "Trigger paste command from keyboard shortcut",
     15    triggerPasteFun: async () => {
     16      await EventUtils.synthesizeAndWaitKey(
     17        "v",
     18        kIsMac ? { accelKey: true } : { ctrlKey: true }
     19      );
     20    },
     21  },
     22  {
     23    description: "Trigger paste command",
     24    triggerPasteFun: async aBrowser => {
     25      await SpecialPowers.spawn(aBrowser, [], async () => {
     26        await SpecialPowers.doCommand(content.window, "cmd_paste");
     27      });
     28    },
     29  },
     30 ];
     31 
     32 async function promiseClipboardDataFromPasteEvent(aBrowser, aTriggerPasteFun) {
     33  const promisePasteEvent = SpecialPowers.spawn(aBrowser, [], () => {
     34    return new Promise(resolve => {
     35      content.document.addEventListener(
     36        "paste",
     37        e => {
     38          const clipboardData = e.clipboardData.getData("text/plain");
     39          resolve(clipboardData);
     40        },
     41        { once: true }
     42      );
     43    });
     44  });
     45  // Enuse the event listener is registered on remote target.
     46  await SpecialPowers.spawn(aBrowser, [], async () => {
     47    await new Promise(resolve => {
     48      SpecialPowers.executeSoon(resolve);
     49    });
     50  });
     51  const result = await aTriggerPasteFun(aBrowser);
     52  const clipboardData = await promisePasteEvent;
     53  return { result, clipboardData };
     54 }
     55 
     56 add_setup(async function () {
     57  await SpecialPowers.pushPrefEnv({
     58    set: [
     59      ["test.events.async.enabled", true],
     60      // Disable the paste contextmenu delay to make the test run faster.
     61      ["security.dialog_enable_delay", 0],
     62    ],
     63  });
     64 
     65  // Paste contextmenu should not be shown during the test.
     66  let listener = function (e) {
     67    if (e.target.getAttribute("id") == kPasteMenuPopupId) {
     68      ok(false, "paste contextmenu should not be shown");
     69    }
     70  };
     71  document.addEventListener("popupshown", listener);
     72 
     73  registerCleanupFunction(() => {
     74    document.removeEventListener("popupshown", listener);
     75  });
     76 });
     77 
     78 kPasteCommandTests.forEach(test => {
     79  describe(test.description, () => {
     80    it("Same-origin data", async () => {
     81      const clipboardText = "X" + Math.random();
     82 
     83      await BrowserTestUtils.withNewTab(
     84        kContentFileUrl,
     85        async function (aBrowser) {
     86          if (test.setupFn) {
     87            info(`Setup`);
     88            await test.setupFn(aBrowser);
     89          }
     90 
     91          info(`Write clipboard data`);
     92          await SpecialPowers.spawn(aBrowser, [clipboardText], async text => {
     93            content.document.notifyUserGestureActivation();
     94            return content.eval(`navigator.clipboard.writeText("${text}");`);
     95          });
     96 
     97          info(`Trigger execCommand("paste")`);
     98          const { result, clipboardData } =
     99            await promiseClipboardDataFromPasteEvent(aBrowser, async () => {
    100              return SpecialPowers.spawn(aBrowser, [], () => {
    101                content.document.notifyUserGestureActivation();
    102                return Cu.waiveXrays(content.document).execCommand("paste");
    103              });
    104            });
    105          ok(result, `execCommand("paste") should be succeed`);
    106          is(clipboardData, clipboardText, `Check clipboard data`);
    107 
    108          if (test.additionalCheckFunc) {
    109            info(`Additional checks`);
    110            await test.additionalCheckFunc(aBrowser, clipboardText);
    111          }
    112        }
    113      );
    114    });
    115 
    116    describe("cross-origin data", () => {
    117      kSuppressionTests.forEach(subTest => {
    118        it(subTest.description, async () => {
    119          const clipboardText = await promiseWritingRandomTextToClipboard();
    120 
    121          await BrowserTestUtils.withNewTab(
    122            kContentFileUrl,
    123            async function (aBrowser) {
    124              if (test.setupFn) {
    125                info(`Setup`);
    126                await test.setupFn(aBrowser);
    127              }
    128 
    129              info(`Trigger paste command`);
    130              const { clipboardData } =
    131                await promiseClipboardDataFromPasteEvent(
    132                  aBrowser,
    133                  subTest.triggerPasteFun
    134                );
    135              is(clipboardData, clipboardText, `Check clipboard data`);
    136 
    137              if (test.additionalCheckFunc) {
    138                info(`Additional checks`);
    139                await test.additionalCheckFunc(aBrowser, clipboardText);
    140              }
    141            }
    142          );
    143        });
    144      });
    145    });
    146  });
    147 });