tor-browser

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

browser_navigator_clipboard_read.js (6751B)


      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 =
     10  kBaseUrlForContent + "simple_navigator_clipboard_read.html";
     11 
     12 // @param aBrowser browser object of the content tab.
     13 // @param aMultipleReadTextCalls if false, exactly one call is made, two
     14 //                               otherwise.
     15 function promiseClickContentToTriggerClipboardRead(
     16  aBrowser,
     17  aMultipleReadTextCalls
     18 ) {
     19  return promiseClickContentElement(
     20    aBrowser,
     21    aMultipleReadTextCalls ? "invokeReadTwiceId" : "invokeReadOnceId"
     22  );
     23 }
     24 
     25 // @param aBrowser browser object of the content tab.
     26 function promiseMutatedReadResultFromContentElement(aBrowser) {
     27  return promiseMutatedTextContentFromContentElement(aBrowser, "readResultId");
     28 }
     29 
     30 add_setup(async function () {
     31  await SpecialPowers.pushPrefEnv({
     32    set: [["test.events.async.enabled", true]],
     33  });
     34 });
     35 
     36 add_task(async function test_paste_button_position() {
     37  // Ensure there's text on the clipboard.
     38  await promiseWritingRandomTextToClipboard();
     39 
     40  await BrowserTestUtils.withNewTab(kContentFileUrl, async function (browser) {
     41    const pasteButtonIsShown = promisePasteButtonIsShown();
     42    const coordsOfClickInContentRelativeToScreenInDevicePixels =
     43      await promiseClickContentToTriggerClipboardRead(browser, false);
     44    info(
     45      "coordsOfClickInContentRelativeToScreenInDevicePixels: " +
     46        coordsOfClickInContentRelativeToScreenInDevicePixels.x +
     47        ", " +
     48        coordsOfClickInContentRelativeToScreenInDevicePixels.y
     49    );
     50 
     51    const pasteButtonCoordsRelativeToScreenInDevicePixels =
     52      await pasteButtonIsShown;
     53    info(
     54      "pasteButtonCoordsRelativeToScreenInDevicePixels: " +
     55        pasteButtonCoordsRelativeToScreenInDevicePixels.x +
     56        ", " +
     57        pasteButtonCoordsRelativeToScreenInDevicePixels.y
     58    );
     59 
     60    const mouseCoordsRelativeToScreenInDevicePixels =
     61      getMouseCoordsRelativeToScreenInDevicePixels();
     62    info(
     63      "mouseCoordsRelativeToScreenInDevicePixels: " +
     64        mouseCoordsRelativeToScreenInDevicePixels.x +
     65        ", " +
     66        mouseCoordsRelativeToScreenInDevicePixels.y
     67    );
     68 
     69    // Asserting not overlapping is important; otherwise, when the
     70    // "Paste" button is shown via a `mousedown` event, the following
     71    // `mouseup` event could accept the "Paste" button unnoticed by the
     72    // user.
     73    ok(
     74      isCloselyLeftOnTopOf(
     75        mouseCoordsRelativeToScreenInDevicePixels,
     76        pasteButtonCoordsRelativeToScreenInDevicePixels
     77      ),
     78      "'Paste' button is closely left on top of the mouse pointer."
     79    );
     80    ok(
     81      isCloselyLeftOnTopOf(
     82        coordsOfClickInContentRelativeToScreenInDevicePixels,
     83        pasteButtonCoordsRelativeToScreenInDevicePixels
     84      ),
     85      "Coords of click in content are closely left on top of the 'Paste' button."
     86    );
     87 
     88    // To avoid disturbing subsequent tests.
     89    const pasteButtonIsHidden = promisePasteButtonIsHidden();
     90    await promiseClickPasteButton();
     91    await pasteButtonIsHidden;
     92  });
     93 });
     94 
     95 add_task(async function test_accepting_paste_button() {
     96  // Randomized text to avoid overlappings with other tests.
     97  const clipboardText = await promiseWritingRandomTextToClipboard();
     98 
     99  await BrowserTestUtils.withNewTab(kContentFileUrl, async function (browser) {
    100    const pasteButtonIsShown = promisePasteButtonIsShown();
    101    await promiseClickContentToTriggerClipboardRead(browser, false);
    102    await pasteButtonIsShown;
    103    const pasteButtonIsHidden = promisePasteButtonIsHidden();
    104    const mutatedReadResultFromContentElement =
    105      promiseMutatedReadResultFromContentElement(browser);
    106    await promiseClickPasteButton();
    107    await pasteButtonIsHidden;
    108    await mutatedReadResultFromContentElement.then(value => {
    109      is(
    110        value,
    111        "Resolved: " + clipboardText,
    112        "Text returned from `navigator.clipboard.read()` is as expected."
    113      );
    114    });
    115  });
    116 });
    117 
    118 add_task(async function test_dismissing_paste_button() {
    119  await BrowserTestUtils.withNewTab(kContentFileUrl, async function (browser) {
    120    const pasteButtonIsShown = promisePasteButtonIsShown();
    121    await promiseClickContentToTriggerClipboardRead(browser, false);
    122    await pasteButtonIsShown;
    123    const pasteButtonIsHidden = promisePasteButtonIsHidden();
    124    const mutatedReadResultFromContentElement =
    125      promiseMutatedReadResultFromContentElement(browser);
    126    await promiseDismissPasteButton();
    127    await pasteButtonIsHidden;
    128    await mutatedReadResultFromContentElement.then(value => {
    129      is(
    130        value,
    131        "Rejected: Clipboard read operation is not allowed.",
    132        "`navigator.clipboard.read()` rejected after dismissing the 'Paste' button"
    133      );
    134    });
    135  });
    136 });
    137 
    138 add_task(
    139  async function test_multiple_read_invocations_for_same_user_activation() {
    140    // Randomized text to avoid overlappings with other tests.
    141    const clipboardText = await promiseWritingRandomTextToClipboard();
    142 
    143    await BrowserTestUtils.withNewTab(
    144      kContentFileUrl,
    145      async function (browser) {
    146        const pasteButtonIsShown = promisePasteButtonIsShown();
    147        await promiseClickContentToTriggerClipboardRead(browser, true);
    148        await pasteButtonIsShown;
    149        const mutatedReadResultFromContentElement =
    150          promiseMutatedReadResultFromContentElement(browser);
    151        const pasteButtonIsHidden = promisePasteButtonIsHidden();
    152        await promiseClickPasteButton();
    153        await mutatedReadResultFromContentElement.then(value => {
    154          is(
    155            value,
    156            "Resolved 1: " + clipboardText + "; Resolved 2: " + clipboardText,
    157            "Two calls of `navigator.clipboard.read()` both resolved with the expected text."
    158          );
    159        });
    160 
    161        // To avoid disturbing subsequent tests.
    162        await pasteButtonIsHidden;
    163      }
    164    );
    165  }
    166 );
    167 
    168 add_task(async function test_new_user_activation_shows_paste_button_again() {
    169  await BrowserTestUtils.withNewTab(kContentFileUrl, async function (browser) {
    170    // Ensure there's text on the clipboard.
    171    await promiseWritingRandomTextToClipboard();
    172 
    173    for (let i = 0; i < 2; ++i) {
    174      const pasteButtonIsShown = promisePasteButtonIsShown();
    175      // A click initiates a new user activation.
    176      await promiseClickContentToTriggerClipboardRead(browser, false);
    177      await pasteButtonIsShown;
    178 
    179      const pasteButtonIsHidden = promisePasteButtonIsHidden();
    180      await promiseClickPasteButton();
    181      await pasteButtonIsHidden;
    182    }
    183  });
    184 });