tor-browser

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

browser_toolbox_textbox_context_menu.js (5183B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 * http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 // HTML inputs don't automatically get the 'edit' context menu, so we have
      7 // a helper on the toolbox to do so. Make sure that shows menu items in the
      8 // right state, and that it works for an input inside of a panel.
      9 
     10 const URL = "data:text/html;charset=utf8,test for textbox context menu";
     11 const textboxToolId = "testtool1";
     12 
     13 registerCleanupFunction(() => {
     14  gDevTools.unregisterTool(textboxToolId);
     15 });
     16 
     17 add_task(async function checkMenuEntryStates() {
     18  info("Checking the state of edit menuitems with an empty clipboard");
     19  const toolbox = await openNewTabAndToolbox(URL, "inspector");
     20 
     21  emptyClipboard();
     22 
     23  // Make sure the focus is predictable.
     24  const inspector = toolbox.getPanel("inspector");
     25  const onFocus = once(inspector.searchBox, "focus");
     26  inspector.searchBox.focus();
     27  await onFocus;
     28 
     29  info("Opening context menu");
     30  const onContextMenuPopup = toolbox.once("menu-open");
     31  synthesizeContextMenuEvent(inspector.searchBox);
     32  await onContextMenuPopup;
     33 
     34  const textboxContextMenu = toolbox.getTextBoxContextMenu();
     35  ok(textboxContextMenu, "The textbox context menu is loaded in the toolbox");
     36 
     37  const cmdUndo = textboxContextMenu.querySelector("#editmenu-undo");
     38  const cmdDelete = textboxContextMenu.querySelector("#editmenu-delete");
     39  const cmdSelectAll = textboxContextMenu.querySelector("#editmenu-selectAll");
     40  const cmdCut = textboxContextMenu.querySelector("#editmenu-cut");
     41  const cmdCopy = textboxContextMenu.querySelector("#editmenu-copy");
     42  const cmdPaste = textboxContextMenu.querySelector("#editmenu-paste");
     43 
     44  is(cmdUndo.getAttribute("disabled"), "true", "cmdUndo is disabled");
     45  is(cmdDelete.getAttribute("disabled"), "true", "cmdDelete is disabled");
     46  is(cmdSelectAll.getAttribute("disabled"), "true", "cmdSelectAll is disabled");
     47  is(cmdCut.getAttribute("disabled"), "true", "cmdCut is disabled");
     48  is(cmdCopy.getAttribute("disabled"), "true", "cmdCopy is disabled");
     49 
     50  if (isWindows()) {
     51    // emptyClipboard only works on Windows (666254), assert paste only for this OS.
     52    is(cmdPaste.getAttribute("disabled"), "true", "cmdPaste is disabled");
     53  }
     54 
     55  const onContextMenuHidden = toolbox.once("menu-close");
     56  if (Services.prefs.getBoolPref("widget.macos.native-context-menus", false)) {
     57    info("Using hidePopup semantics because of macOS native context menus.");
     58    textboxContextMenu.hidePopup();
     59  } else {
     60    EventUtils.sendKey("ESCAPE", toolbox.win);
     61  }
     62  await onContextMenuHidden;
     63 });
     64 
     65 add_task(async function automaticallyBindTexbox() {
     66  info(
     67    "Registering a tool with an input field and making sure the context menu works"
     68  );
     69  gDevTools.registerTool({
     70    id: textboxToolId,
     71    isToolSupported: () => true,
     72    url: CHROME_URL_ROOT + "doc_textbox_tool.html",
     73    label: "Context menu works without tool intervention",
     74    build(iframeWindow, toolbox) {
     75      this.panel = createTestPanel(iframeWindow, toolbox);
     76      return this.panel.open();
     77    },
     78  });
     79 
     80  const toolbox = await openNewTabAndToolbox(URL, textboxToolId);
     81  is(toolbox.currentToolId, textboxToolId, "The custom tool has been opened");
     82 
     83  const doc = toolbox.getCurrentPanel().document;
     84  await checkTextBox(doc.querySelector("input[type=text]"), toolbox);
     85  await checkTextBox(doc.querySelector("textarea"), toolbox);
     86  await checkTextBox(doc.querySelector("input[type=search]"), toolbox);
     87  await checkTextBox(doc.querySelector("input:not([type])"), toolbox);
     88  await checkNonTextInput(doc.querySelector("input[type=radio]"), toolbox);
     89 });
     90 
     91 async function checkNonTextInput(input, toolbox) {
     92  let textboxContextMenu = toolbox.getTextBoxContextMenu();
     93  ok(!textboxContextMenu, "The menu is closed");
     94 
     95  info(
     96    "Simulating context click on the non text input and expecting no menu to open"
     97  );
     98  const eventBubbledUp = new Promise(resolve => {
     99    input.ownerDocument.addEventListener("contextmenu", resolve, {
    100      once: true,
    101    });
    102  });
    103  synthesizeContextMenuEvent(input);
    104  info("Waiting for event");
    105  await eventBubbledUp;
    106 
    107  textboxContextMenu = toolbox.getTextBoxContextMenu();
    108  ok(!textboxContextMenu, "The menu is still closed");
    109 }
    110 
    111 async function checkTextBox(textBox, toolbox) {
    112  let textboxContextMenu = toolbox.getTextBoxContextMenu();
    113  ok(!textboxContextMenu, "The menu is closed");
    114 
    115  info(
    116    "Simulating context click on the textbox and expecting the menu to open"
    117  );
    118  const onContextMenu = toolbox.once("menu-open");
    119  synthesizeContextMenuEvent(textBox);
    120  await onContextMenu;
    121 
    122  textboxContextMenu = toolbox.getTextBoxContextMenu();
    123  ok(textboxContextMenu, "The menu is now visible");
    124 
    125  info("Closing the menu");
    126  const onContextMenuHidden = toolbox.once("menu-close");
    127  if (Services.prefs.getBoolPref("widget.macos.native-context-menus", false)) {
    128    info("Using hidePopup semantics because of macOS native context menus.");
    129    textboxContextMenu.hidePopup();
    130  } else {
    131    EventUtils.sendKey("ESCAPE", toolbox.win);
    132  }
    133  await onContextMenuHidden;
    134 
    135  textboxContextMenu = toolbox.getTextBoxContextMenu();
    136  ok(!textboxContextMenu, "The menu is closed again");
    137 }