tor-browser

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

special-paste.html (5026B)


      1 <!doctype html>
      2 <html>
      3 <head>
      4 <meta charset="utf-8">
      5 <meta name="timeout" content="long">
      6 <meta name="variant" content="?white-space=normal">
      7 <meta name="variant" content="?white-space=pre">
      8 <meta name="variant" content="?white-space=pre-line">
      9 <meta name="variant" content="?white-space=pre-wrap">
     10 <title>Pasting rich text into contenteditable=plaintext-only</title>
     11 <script src="/resources/testharness.js"></script>
     12 <script src="/resources/testharnessreport.js"></script>
     13 <script src="/resources/testdriver.js"></script>
     14 <script src="/resources/testdriver-vendor.js"></script>
     15 <script src="/resources/testdriver-actions.js"></script>
     16 <script src="../../../editing/include/editor-test-utils.js"></script>
     17 <script>
     18 "use strict";
     19 
     20 const searchParams = new URLSearchParams(document.location.search);
     21 const whiteSpace = searchParams.get("white-space");
     22 const useBR = whiteSpace == "normal";
     23 const isMac = navigator.platform.includes("Mac");
     24 
     25 addEventListener("load", () => {
     26  const placeholderForCopy = document.createElement("div");
     27  document.body.appendChild(placeholderForCopy);
     28  const editingHost = document.createElement("div");
     29  editingHost.style.whiteSpace = whiteSpace;
     30  editingHost.contentEditable = "plaintext-only";
     31  document.body.appendChild(editingHost);
     32  editingHost.focus();
     33  editingHost.getBoundingClientRect();
     34  const utils = new EditorTestUtils(editingHost);
     35  let lastBeforeInput;
     36  editingHost.addEventListener("beforeinput", event => lastBeforeInput = event);
     37 
     38  promise_test(async t => {
     39    placeholderForCopy.innerHTML = "<b>abc</b>";
     40    document.activeElement?.blur();
     41    getSelection().selectAllChildren(placeholderForCopy);
     42    await utils.sendCopyShortcutKey();
     43    utils.setupEditingHost("A[]B");
     44    lastBeforeInput = undefined;
     45    await new test_driver.Actions()
     46      .keyDown(isMac ? utils.kMeta : utils.kControl)
     47      .keyDown(utils.kShift)
     48      .keyDown("v")
     49      .keyUp("v")
     50      .keyUp(utils.kShift)
     51      .keyUp(isMac ? utils.kMeta : utils.kControl)
     52      .send();
     53    test(() => {
     54      assert_equals(lastBeforeInput?.inputType, "insertFromPaste", `inputType should be "insertFromPaste"`);
     55      assert_equals(lastBeforeInput?.data, null, `data should be null`);
     56      assert_true(
     57        String(lastBeforeInput?.dataTransfer?.getData("text/html")).includes(placeholderForCopy.innerHTML),
     58        `dataTransfer should have the copied HTML source`
     59      );
     60    }, `${t.name}: beforeinput`);
     61    test(() => {
     62      assert_equals(editingHost.innerHTML, "AabcB", "<b> should not be pasted");
     63    }, `${t.name}: pasted result`);
     64  }, "Pasting without format");
     65 
     66  // FIXME: I don't know why Ctrl-middle click fails on macOS (it's not Command).
     67  if (!navigator.platform.includes("Mac")) {
     68    promise_test(async t => {
     69      placeholderForCopy.innerHTML = "<b>abc</b>";
     70      document.activeElement?.blur();
     71      getSelection().selectAllChildren(placeholderForCopy);
     72      await utils.sendCopyShortcutKey();
     73      // For primary selection on Linux, we need to select text with user input emulation.
     74      getSelection().collapse(placeholderForCopy, 0);
     75      const arrowRight = "\uE014";
     76      await new test_driver.Actions()
     77        .keyDown(utils.kShift)
     78        .keyDown(arrowRight)
     79        .keyUp(arrowRight)
     80        .keyDown(arrowRight)
     81        .keyUp(arrowRight)
     82        .keyDown(arrowRight)
     83        .keyUp(arrowRight)
     84        .keyUp(utils.kShift)
     85        .send();
     86      utils.setupEditingHost("{}<br>");
     87      lastBeforeInput = undefined;
     88      const actions = new test_driver.Actions();
     89      await actions
     90        .pointerMove(1, 1, {origin: "viewport"})
     91        .pointerMove(0, 0, {origin: editingHost})
     92        .keyDown(utils.kControl)
     93        .pointerDown({button: actions.ButtonType.MIDDLE})
     94        .pointerUp({button: actions.ButtonType.MIDDLE})
     95        .keyUp(utils.kControl)
     96        .send();
     97      test(() => {
     98        assert_equals(
     99          lastBeforeInput?.inputType,
    100          "insertFromPasteAsQuotation",
    101          `inputType should be "insertFromPasteAsQuotation"`
    102        );
    103        assert_equals(lastBeforeInput?.data, null, `data should be null`);
    104        assert_true(
    105          String(lastBeforeInput?.dataTransfer?.getData("text/html")).includes(placeholderForCopy.innerHTML),
    106          `dataTransfer should have the copied HTML source`
    107        );
    108      }, `${t.name}: beforeinput`);
    109      test(() => {
    110        if (useBR) {
    111          assert_equals(editingHost.innerHTML, "&gt; abc<br><br><br>", "<b> should not be pasted");
    112        } else {
    113          assert_in_array(
    114            editingHost.innerHTML,
    115            // The last break is a padding line break to make the last empty line visible.
    116            // Therefore, it should not appear in `.textContent`.  So, only the last line
    117            // break should be <br>.
    118            "&gt; abc\n\n<br>",
    119            "<b> should not be pasted"
    120          );
    121        }
    122      }, `${t.name}: pasted result`);
    123    }, "Pasting as quotation");
    124  }
    125 }, {once: true});
    126 </script>
    127 </head>
    128 <body></body>
    129 </html>