tor-browser

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

browser_contextmenu.js (60899B)


      1 "use strict";
      2 
      3 let contextMenu;
      4 let LOGIN_FILL_ITEMS = ["---", null, "manage-saved-logins", true];
      5 let NAVIGATION_ITEMS =
      6  AppConstants.platform == "macosx"
      7    ? [
      8        "context-back",
      9        false,
     10        "context-forward",
     11        false,
     12        "context-reload",
     13        true,
     14        "---",
     15        null,
     16        "context-bookmarkpage",
     17        true,
     18      ]
     19    : [
     20        "context-navigation",
     21        null,
     22        [
     23          "context-back",
     24          false,
     25          "context-forward",
     26          false,
     27          "context-reload",
     28          true,
     29          "context-bookmarkpage",
     30          true,
     31        ],
     32        null,
     33        "---",
     34        null,
     35      ];
     36 
     37 const askChatMenu = [
     38  "context-ask-chat",
     39  true,
     40  // Need a blank entry here because the Ask Chat submenu is dynamically built with no ids.
     41  "",
     42  null,
     43 ];
     44 let hasStripOnShare = Services.prefs.getBoolPref(
     45  "privacy.query_stripping.strip_on_share.enabled"
     46 );
     47 let hasContainers =
     48  Services.prefs.getBoolPref("privacy.userContext.enabled") &&
     49  ContextualIdentityService.getPublicIdentities().length;
     50 
     51 const hasSelectTranslations =
     52  Services.prefs.getBoolPref("browser.translations.enable") &&
     53  Services.prefs.getBoolPref("browser.translations.select.enable");
     54 
     55 const example_base =
     56  // eslint-disable-next-line @microsoft/sdl/no-insecure-url
     57  "http://example.com/browser/browser/base/content/test/contextMenu/";
     58 const about_preferences_base = "about:preferences";
     59 const chrome_base =
     60  "chrome://mochitests/content/browser/browser/base/content/test/contextMenu/";
     61 const head_base =
     62  "chrome://mochitests/content/browser/browser/base/content/test/contextMenu/";
     63 
     64 /* import-globals-from contextmenu_common.js */
     65 Services.scriptloader.loadSubScript(
     66  chrome_base + "contextmenu_common.js",
     67  this
     68 );
     69 
     70 function getThisFrameSubMenu(base_menu) {
     71  if (AppConstants.NIGHTLY_BUILD) {
     72    let osPidItem = ["context-frameOsPid", false];
     73    base_menu = base_menu.concat(osPidItem);
     74  }
     75  return base_menu;
     76 }
     77 
     78 add_setup(async function () {
     79  await SpecialPowers.pushPrefEnv({
     80    set: [
     81      ["test.wait300msAfterTabSwitch", true],
     82      ["browser.search.separatePrivateDefault.ui.enabled", true],
     83    ],
     84  });
     85 });
     86 
     87 // Below are test cases for XUL element
     88 add_task(async function test_xul_text_link_label() {
     89  let url = chrome_base + "subtst_contextmenu_xul.xhtml";
     90 
     91  await BrowserTestUtils.openNewForegroundTab({
     92    gBrowser,
     93    url,
     94    waitForLoad: true,
     95    waitForStateStop: true,
     96  });
     97 
     98  await test_contextmenu(
     99    "#test-xul-text-link-label",
    100    [
    101      "context-openlinkintab",
    102      true,
    103      ...(hasContainers ? ["context-openlinkinusercontext-menu", true] : []),
    104      // We need a blank entry here because the containers submenu is
    105      // dynamically generated with no ids.
    106      ...(hasContainers ? ["", null] : []),
    107      "context-openlink",
    108      true,
    109      "context-openlinkprivate",
    110      true,
    111      "context-previewlink",
    112      true,
    113      "---",
    114      null,
    115      "context-bookmarklink",
    116      true,
    117      "context-savelink",
    118      true,
    119      "context-copylink",
    120      true,
    121      ...(hasStripOnShare ? ["context-stripOnShareLink", false] : []),
    122      "---",
    123      null,
    124      "context-searchselect",
    125      true,
    126      "context-searchselect-private",
    127      true,
    128      ...askChatMenu,
    129    ],
    130    {
    131      awaitOnMenuBuilt: {
    132        id: "context-ask-chat",
    133      },
    134    }
    135  );
    136 
    137  // Clean up so won't affect HTML element test cases.
    138  lastElementSelector = null;
    139  gBrowser.removeCurrentTab();
    140 });
    141 
    142 // Below are test cases for HTML element.
    143 
    144 add_task(async function test_setup_html() {
    145  let url = example_base + "subtst_contextmenu.html";
    146 
    147  await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
    148 
    149  await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
    150    let doc = content.document;
    151    let audioIframe = doc.querySelector("#test-audio-in-iframe");
    152    // media documents always use a <video> tag.
    153    let audio = audioIframe.contentDocument.querySelector("video");
    154    let videoIframe = doc.querySelector("#test-video-in-iframe");
    155    let video = videoIframe.contentDocument.querySelector("video");
    156 
    157    audio.loop = true;
    158    audio.src = "audio.ogg";
    159    video.loop = true;
    160    video.src = "video.webm";
    161 
    162    let awaitPause = ContentTaskUtils.waitForEvent(audio, "pause");
    163    await ContentTaskUtils.waitForCondition(
    164      () => !audio.paused,
    165      "Making sure audio is playing before calling pause"
    166    );
    167    audio.pause();
    168    await awaitPause;
    169 
    170    awaitPause = ContentTaskUtils.waitForEvent(video, "pause");
    171    await ContentTaskUtils.waitForCondition(
    172      () => !video.paused,
    173      "Making sure video is playing before calling pause"
    174    );
    175    video.pause();
    176    await awaitPause;
    177  });
    178 });
    179 
    180 let plainTextItems;
    181 add_task(async function test_plaintext() {
    182  await test_contextmenu("#test-text", [
    183    ...NAVIGATION_ITEMS,
    184    "context-savepage",
    185    true,
    186    "context-selectall",
    187    true,
    188    "---",
    189    null,
    190    "context-take-screenshot",
    191    true,
    192    "---",
    193    null,
    194    ...askChatMenu,
    195    "---",
    196    null,
    197    "context-viewsource",
    198    true,
    199  ]);
    200 });
    201 
    202 const kLinkItems = [
    203  "context-openlinkintab",
    204  true,
    205  ...(hasContainers ? ["context-openlinkinusercontext-menu", true] : []),
    206  // We need a blank entry here because the containers submenu is
    207  // dynamically generated with no ids.
    208  ...(hasContainers ? ["", null] : []),
    209  "context-openlink",
    210  true,
    211  "context-openlinkprivate",
    212  true,
    213  "context-previewlink",
    214  true,
    215  "---",
    216  null,
    217  "context-bookmarklink",
    218  true,
    219  "context-savelink",
    220  true,
    221  "context-copylink",
    222  true,
    223  ...(hasStripOnShare ? ["context-stripOnShareLink", false] : []),
    224  "---",
    225  null,
    226  "context-searchselect",
    227  true,
    228  "context-searchselect-private",
    229  true,
    230 ];
    231 
    232 add_task(async function test_link() {
    233  await test_contextmenu(
    234    "#test-link",
    235    [
    236      ...kLinkItems,
    237      ...(hasSelectTranslations ? ["context-translate-selection", true] : []),
    238      ...askChatMenu,
    239    ],
    240    {
    241      awaitOnMenuBuilt: {
    242        id: "context-ask-chat",
    243      },
    244    }
    245  );
    246 });
    247 
    248 add_task(async function test_link_in_shadow_dom() {
    249  await test_contextmenu(
    250    "#shadow-host",
    251    [
    252      ...kLinkItems,
    253      ...(hasSelectTranslations ? ["context-translate-selection", true] : []),
    254      ...askChatMenu,
    255    ],
    256    {
    257      offsetX: 6,
    258      offsetY: 6,
    259      awaitOnMenuBuilt: {
    260        id: "context-ask-chat",
    261      },
    262    }
    263  );
    264 });
    265 
    266 add_task(async function test_linkpreviewcommand() {
    267  await SpecialPowers.pushPrefEnv({
    268    set: [["browser.ml.linkPreview.prefetchOnEnable", false]],
    269  });
    270  await SpecialPowers.pushPrefEnv({
    271    set: [["browser.ml.linkPreview.enabled", true]],
    272  });
    273  await test_contextmenu(
    274    "#test-link",
    275    [
    276      "context-openlinkintab",
    277      true,
    278      ...(hasContainers ? ["context-openlinkinusercontext-menu", true] : []),
    279      // We need a blank entry here because the containers submenu is
    280      // dynamically generated with no ids.
    281      ...(hasContainers ? ["", null] : []),
    282      "context-openlink",
    283      true,
    284      "context-openlinkprivate",
    285      true,
    286      "context-previewlink",
    287      true,
    288      "---",
    289      null,
    290      "context-bookmarklink",
    291      true,
    292      "context-savelink",
    293      true,
    294      "context-copylink",
    295      true,
    296      ...(hasStripOnShare ? ["context-stripOnShareLink", false] : []),
    297      "---",
    298      null,
    299      "context-searchselect",
    300      true,
    301      "context-searchselect-private",
    302      true,
    303      ...(hasSelectTranslations ? ["context-translate-selection", true] : []),
    304      ...askChatMenu,
    305    ],
    306    {
    307      awaitOnMenuBuilt: {
    308        id: "context-ask-chat",
    309      },
    310    }
    311  );
    312 
    313  await SpecialPowers.popPrefEnv();
    314 });
    315 
    316 add_task(async function test_linkpreviewcommand_disabled() {
    317  await SpecialPowers.pushPrefEnv({
    318    set: [["browser.ml.linkPreview.enabled", false]],
    319  });
    320  await test_contextmenu(
    321    "#test-link",
    322    [
    323      "context-openlinkintab",
    324      true,
    325      ...(hasContainers ? ["context-openlinkinusercontext-menu", true] : []),
    326      // We need a blank entry here because the containers submenu is
    327      // dynamically generated with no ids.
    328      ...(hasContainers ? ["", null] : []),
    329      "context-openlink",
    330      true,
    331      "context-openlinkprivate",
    332      true,
    333      //missing context-previewlink is expected
    334      "---",
    335      null,
    336      "context-bookmarklink",
    337      true,
    338      "context-savelink",
    339      true,
    340      "context-copylink",
    341      true,
    342      ...(hasStripOnShare ? ["context-stripOnShareLink", false] : []),
    343      "---",
    344      null,
    345      "context-searchselect",
    346      true,
    347      "context-searchselect-private",
    348      true,
    349      ...(hasSelectTranslations ? ["context-translate-selection", true] : []),
    350      ...askChatMenu,
    351    ],
    352    {
    353      awaitOnMenuBuilt: {
    354        id: "context-ask-chat",
    355      },
    356    }
    357  );
    358  await SpecialPowers.popPrefEnv();
    359 });
    360 
    361 add_task(async function test_linkpreviewcommand_not_on_text() {
    362  await SpecialPowers.pushPrefEnv({
    363    set: [["browser.ml.linkPreview.prefetchOnEnable", false]],
    364  });
    365  await SpecialPowers.pushPrefEnv({
    366    set: [["browser.ml.linkPreview.enabled", true]],
    367  });
    368 
    369  // Verify that context-previewlink doesn't appear in the context menu for text elements
    370  await test_contextmenu(
    371    "#test-text",
    372    [
    373      ...NAVIGATION_ITEMS,
    374      "context-savepage",
    375      true,
    376      "context-selectall",
    377      true,
    378      "---",
    379      null,
    380      "context-take-screenshot",
    381      true,
    382      "---",
    383      null,
    384      ...askChatMenu,
    385      "---",
    386      null,
    387      "context-viewsource",
    388      true,
    389    ],
    390    {
    391      awaitOnMenuBuilt: {
    392        id: "context-ask-chat",
    393      },
    394    }
    395  );
    396 
    397  await SpecialPowers.popPrefEnv();
    398 });
    399 
    400 add_task(async function test_link_over_shadow_dom() {
    401  await test_contextmenu(
    402    "#shadow-host-in-link",
    403    [...kLinkItems, ...askChatMenu],
    404    {
    405      offsetX: 6,
    406      offsetY: 6,
    407      awaitOnMenuBuilt: {
    408        id: "context-ask-chat",
    409      },
    410    }
    411  );
    412 });
    413 
    414 add_task(async function test_mailto() {
    415  await test_contextmenu(
    416    "#test-mailto",
    417    [
    418      "context-copyemail",
    419      true,
    420      "---",
    421      null,
    422      "context-searchselect",
    423      true,
    424      "context-searchselect-private",
    425      true,
    426      ...(hasSelectTranslations ? ["context-translate-selection", true] : []),
    427      ...askChatMenu,
    428    ],
    429    {
    430      awaitOnMenuBuilt: {
    431        id: "context-ask-chat",
    432      },
    433    }
    434  );
    435 });
    436 
    437 add_task(async function test_tel() {
    438  await test_contextmenu(
    439    "#test-tel",
    440    [
    441      "context-copyphone",
    442      true,
    443      "---",
    444      null,
    445      "context-searchselect",
    446      true,
    447      "context-searchselect-private",
    448      true,
    449      ...(hasSelectTranslations ? ["context-translate-selection", true] : []),
    450      ...askChatMenu,
    451    ],
    452    {
    453      awaitOnMenuBuilt: {
    454        id: "context-ask-chat",
    455      },
    456    }
    457  );
    458 });
    459 
    460 add_task(async function test_image() {
    461  for (let selector of ["#test-image", "#test-svg-image"]) {
    462    await test_contextmenu(
    463      selector,
    464      [
    465        "context-viewimage",
    466        true,
    467        "context-saveimage",
    468        true,
    469        "context-copyimage-contents",
    470        true,
    471        "context-copyimage",
    472        true,
    473        "context-sendimage",
    474        true,
    475        ...getTextRecognitionItems(),
    476        ...(Services.prefs.getBoolPref("browser.menu.showViewImageInfo", false)
    477          ? ["context-viewimageinfo", true]
    478          : []),
    479        ...// The visual-search menu item is not shown on SVGs.
    480        (selector != "#test-svg-image" &&
    481        Services.prefs.getBoolPref("browser.search.visualSearch.featureGate")
    482          ? ["context-visual-search", true]
    483          : []),
    484        "---",
    485        null,
    486        "context-setDesktopBackground",
    487        true,
    488        "---",
    489        null,
    490        "context-take-screenshot",
    491        true,
    492        "---",
    493        null,
    494        ...askChatMenu,
    495      ],
    496      {
    497        onContextMenuShown() {
    498          is(
    499            typeof gContextMenu.imageInfo.height,
    500            "number",
    501            "Should have height"
    502          );
    503          is(
    504            typeof gContextMenu.imageInfo.width,
    505            "number",
    506            "Should have width"
    507          );
    508        },
    509        awaitOnMenuBuilt: {
    510          id: "context-ask-chat",
    511        },
    512      }
    513    );
    514  }
    515 });
    516 
    517 add_task(async function test_canvas() {
    518  await test_contextmenu(
    519    "#test-canvas",
    520    [
    521      "context-viewimage",
    522      true,
    523      "context-saveimage",
    524      true,
    525      "---",
    526      null,
    527      "context-selectall",
    528      true,
    529      "---",
    530      null,
    531      "context-take-screenshot",
    532      true,
    533      "---",
    534      null,
    535      ...askChatMenu,
    536    ],
    537    {
    538      awaitOnMenuBuilt: {
    539        id: "context-ask-chat",
    540      },
    541    }
    542  );
    543 });
    544 
    545 add_task(async function test_video_ok() {
    546  await SpecialPowers.pushPrefEnv({
    547    set: [["media.videocontrols.picture-in-picture.enabled", true]],
    548  });
    549 
    550  await test_contextmenu(
    551    "#test-video-ok",
    552    [
    553      "context-media-play",
    554      true,
    555      "context-media-mute",
    556      true,
    557      "context-media-playbackrate",
    558      null,
    559      [
    560        "context-media-playbackrate-050x",
    561        true,
    562        "context-media-playbackrate-100x",
    563        true,
    564        "context-media-playbackrate-125x",
    565        true,
    566        "context-media-playbackrate-150x",
    567        true,
    568        "context-media-playbackrate-200x",
    569        true,
    570      ],
    571      null,
    572      "context-media-loop",
    573      true,
    574      "context-video-fullscreen",
    575      true,
    576      "context-media-hidecontrols",
    577      true,
    578      "---",
    579      null,
    580      "context-viewvideo",
    581      true,
    582      "context-video-pictureinpicture",
    583      true,
    584      "---",
    585      null,
    586      "context-video-saveimage",
    587      true,
    588      "context-savevideo",
    589      true,
    590      "context-copyvideourl",
    591      true,
    592      "context-sendvideo",
    593      true,
    594      "---",
    595      null,
    596      "context-take-screenshot",
    597      true,
    598      "---",
    599      null,
    600      ...askChatMenu,
    601    ],
    602    {
    603      awaitOnMenuBuilt: {
    604        id: "context-ask-chat",
    605      },
    606    }
    607  );
    608 
    609  await SpecialPowers.popPrefEnv();
    610 
    611  await SpecialPowers.pushPrefEnv({
    612    set: [["media.videocontrols.picture-in-picture.enabled", false]],
    613  });
    614 
    615  await test_contextmenu(
    616    "#test-video-ok",
    617    [
    618      "context-media-play",
    619      true,
    620      "context-media-mute",
    621      true,
    622      "context-media-playbackrate",
    623      null,
    624      [
    625        "context-media-playbackrate-050x",
    626        true,
    627        "context-media-playbackrate-100x",
    628        true,
    629        "context-media-playbackrate-125x",
    630        true,
    631        "context-media-playbackrate-150x",
    632        true,
    633        "context-media-playbackrate-200x",
    634        true,
    635      ],
    636      null,
    637      "context-media-loop",
    638      true,
    639      "context-video-fullscreen",
    640      true,
    641      "context-media-hidecontrols",
    642      true,
    643      "---",
    644      null,
    645      "context-viewvideo",
    646      true,
    647      "---",
    648      null,
    649      "context-video-saveimage",
    650      true,
    651      "context-savevideo",
    652      true,
    653      "context-copyvideourl",
    654      true,
    655      "context-sendvideo",
    656      true,
    657      "---",
    658      null,
    659      "context-take-screenshot",
    660      true,
    661      "---",
    662      null,
    663      ...askChatMenu,
    664    ],
    665    {
    666      awaitOnMenuBuilt: {
    667        id: "context-ask-chat",
    668      },
    669    }
    670  );
    671 
    672  await SpecialPowers.popPrefEnv();
    673 });
    674 
    675 add_task(async function test_audio_in_video() {
    676  await test_contextmenu(
    677    "#test-audio-in-video",
    678    [
    679      "context-media-play",
    680      true,
    681      "context-media-mute",
    682      true,
    683      "context-media-playbackrate",
    684      null,
    685      [
    686        "context-media-playbackrate-050x",
    687        true,
    688        "context-media-playbackrate-100x",
    689        true,
    690        "context-media-playbackrate-125x",
    691        true,
    692        "context-media-playbackrate-150x",
    693        true,
    694        "context-media-playbackrate-200x",
    695        true,
    696      ],
    697      null,
    698      "context-media-loop",
    699      true,
    700      "context-media-showcontrols",
    701      true,
    702      "---",
    703      null,
    704      "context-saveaudio",
    705      true,
    706      "context-copyaudiourl",
    707      true,
    708      "context-sendaudio",
    709      true,
    710      "---",
    711      null,
    712      ...askChatMenu,
    713    ],
    714    {
    715      awaitOnMenuBuilt: {
    716        id: "context-ask-chat",
    717      },
    718    }
    719  );
    720 });
    721 
    722 add_task(async function test_video_bad() {
    723  await SpecialPowers.pushPrefEnv({
    724    set: [["media.videocontrols.picture-in-picture.enabled", true]],
    725  });
    726 
    727  await test_contextmenu(
    728    "#test-video-bad",
    729    [
    730      "context-media-play",
    731      false,
    732      "context-media-mute",
    733      false,
    734      "context-media-playbackrate",
    735      null,
    736      [
    737        "context-media-playbackrate-050x",
    738        false,
    739        "context-media-playbackrate-100x",
    740        false,
    741        "context-media-playbackrate-125x",
    742        false,
    743        "context-media-playbackrate-150x",
    744        false,
    745        "context-media-playbackrate-200x",
    746        false,
    747      ],
    748      null,
    749      "context-media-loop",
    750      true,
    751      "context-video-fullscreen",
    752      false,
    753      "context-media-hidecontrols",
    754      false,
    755      "---",
    756      null,
    757      "context-viewvideo",
    758      true,
    759      "---",
    760      null,
    761      "context-video-saveimage",
    762      false,
    763      "context-savevideo",
    764      true,
    765      "context-copyvideourl",
    766      true,
    767      "context-sendvideo",
    768      true,
    769      "---",
    770      null,
    771      "context-take-screenshot",
    772      true,
    773      "---",
    774      null,
    775      ...askChatMenu,
    776    ],
    777    {
    778      awaitOnMenuBuilt: {
    779        id: "context-ask-chat",
    780      },
    781    }
    782  );
    783 
    784  await SpecialPowers.popPrefEnv();
    785 
    786  await SpecialPowers.pushPrefEnv({
    787    set: [["media.videocontrols.picture-in-picture.enabled", false]],
    788  });
    789 
    790  await test_contextmenu(
    791    "#test-video-bad",
    792    [
    793      "context-media-play",
    794      false,
    795      "context-media-mute",
    796      false,
    797      "context-media-playbackrate",
    798      null,
    799      [
    800        "context-media-playbackrate-050x",
    801        false,
    802        "context-media-playbackrate-100x",
    803        false,
    804        "context-media-playbackrate-125x",
    805        false,
    806        "context-media-playbackrate-150x",
    807        false,
    808        "context-media-playbackrate-200x",
    809        false,
    810      ],
    811      null,
    812      "context-media-loop",
    813      true,
    814      "context-video-fullscreen",
    815      false,
    816      "context-media-hidecontrols",
    817      false,
    818      "---",
    819      null,
    820      "context-viewvideo",
    821      true,
    822      "---",
    823      null,
    824      "context-video-saveimage",
    825      false,
    826      "context-savevideo",
    827      true,
    828      "context-copyvideourl",
    829      true,
    830      "context-sendvideo",
    831      true,
    832      "---",
    833      null,
    834      "context-take-screenshot",
    835      true,
    836      "---",
    837      null,
    838      "context-ask-chat",
    839      true,
    840      "",
    841      null,
    842    ],
    843    {
    844      awaitOnMenuBuilt: {
    845        id: "context-ask-chat",
    846      },
    847    }
    848  );
    849 
    850  await SpecialPowers.popPrefEnv();
    851 });
    852 
    853 add_task(async function test_video_bad2() {
    854  await SpecialPowers.pushPrefEnv({
    855    set: [["media.videocontrols.picture-in-picture.enabled", true]],
    856  });
    857 
    858  await test_contextmenu(
    859    "#test-video-bad2",
    860    [
    861      "context-media-play",
    862      false,
    863      "context-media-mute",
    864      false,
    865      "context-media-playbackrate",
    866      null,
    867      [
    868        "context-media-playbackrate-050x",
    869        false,
    870        "context-media-playbackrate-100x",
    871        false,
    872        "context-media-playbackrate-125x",
    873        false,
    874        "context-media-playbackrate-150x",
    875        false,
    876        "context-media-playbackrate-200x",
    877        false,
    878      ],
    879      null,
    880      "context-media-loop",
    881      true,
    882      "context-video-fullscreen",
    883      false,
    884      "context-media-hidecontrols",
    885      false,
    886      "---",
    887      null,
    888      "context-viewvideo",
    889      false,
    890      "---",
    891      null,
    892      "context-video-saveimage",
    893      false,
    894      "context-savevideo",
    895      false,
    896      "context-copyvideourl",
    897      false,
    898      "context-sendvideo",
    899      false,
    900      "---",
    901      null,
    902      "context-take-screenshot",
    903      true,
    904      "---",
    905      null,
    906      ...askChatMenu,
    907    ],
    908    {
    909      awaitOnMenuBuilt: {
    910        id: "context-ask-chat",
    911      },
    912    }
    913  );
    914 
    915  await SpecialPowers.popPrefEnv();
    916 
    917  await SpecialPowers.pushPrefEnv({
    918    set: [["media.videocontrols.picture-in-picture.enabled", false]],
    919  });
    920 
    921  await test_contextmenu(
    922    "#test-video-bad2",
    923    [
    924      "context-media-play",
    925      false,
    926      "context-media-mute",
    927      false,
    928      "context-media-playbackrate",
    929      null,
    930      [
    931        "context-media-playbackrate-050x",
    932        false,
    933        "context-media-playbackrate-100x",
    934        false,
    935        "context-media-playbackrate-125x",
    936        false,
    937        "context-media-playbackrate-150x",
    938        false,
    939        "context-media-playbackrate-200x",
    940        false,
    941      ],
    942      null,
    943      "context-media-loop",
    944      true,
    945      "context-video-fullscreen",
    946      false,
    947      "context-media-hidecontrols",
    948      false,
    949      "---",
    950      null,
    951      "context-viewvideo",
    952      false,
    953      "---",
    954      null,
    955      "context-video-saveimage",
    956      false,
    957      "context-savevideo",
    958      false,
    959      "context-copyvideourl",
    960      false,
    961      "context-sendvideo",
    962      false,
    963      "---",
    964      null,
    965      "context-take-screenshot",
    966      true,
    967      "---",
    968      null,
    969      ...askChatMenu,
    970    ],
    971    {
    972      awaitOnMenuBuilt: {
    973        id: "context-ask-chat",
    974      },
    975    }
    976  );
    977 
    978  await SpecialPowers.popPrefEnv();
    979 });
    980 
    981 add_task(async function test_iframe() {
    982  await test_contextmenu(
    983    "#test-iframe",
    984    [
    985      ...NAVIGATION_ITEMS,
    986      "context-savepage",
    987      true,
    988      "context-selectall",
    989      true,
    990      "---",
    991      null,
    992      "context-take-screenshot",
    993      true,
    994      "---",
    995      null,
    996      ...askChatMenu,
    997      "frame",
    998      null,
    999      getThisFrameSubMenu([
   1000        "context-showonlythisframe",
   1001        true,
   1002        "context-openframeintab",
   1003        true,
   1004        "context-openframe",
   1005        true,
   1006        "---",
   1007        null,
   1008        "context-reloadframe",
   1009        true,
   1010        "---",
   1011        null,
   1012        "context-bookmarkframe",
   1013        true,
   1014        "context-saveframe",
   1015        true,
   1016        "---",
   1017        null,
   1018        "context-printframe",
   1019        true,
   1020        "---",
   1021        null,
   1022        "context-viewframesource",
   1023        true,
   1024        "context-viewframeinfo",
   1025        true,
   1026      ]),
   1027      null,
   1028      "---",
   1029      null,
   1030      "context-viewsource",
   1031      true,
   1032    ],
   1033    {
   1034      awaitOnMenuBuilt: {
   1035        id: "context-ask-chat",
   1036      },
   1037    }
   1038  );
   1039 });
   1040 
   1041 add_task(async function test_video_in_iframe() {
   1042  await SpecialPowers.pushPrefEnv({
   1043    set: [["media.videocontrols.picture-in-picture.enabled", true]],
   1044  });
   1045 
   1046  await test_contextmenu(
   1047    "#test-video-in-iframe",
   1048    [
   1049      "context-media-play",
   1050      true,
   1051      "context-media-mute",
   1052      true,
   1053      "context-media-playbackrate",
   1054      null,
   1055      [
   1056        "context-media-playbackrate-050x",
   1057        true,
   1058        "context-media-playbackrate-100x",
   1059        true,
   1060        "context-media-playbackrate-125x",
   1061        true,
   1062        "context-media-playbackrate-150x",
   1063        true,
   1064        "context-media-playbackrate-200x",
   1065        true,
   1066      ],
   1067      null,
   1068      "context-media-loop",
   1069      true,
   1070      "context-video-fullscreen",
   1071      true,
   1072      "context-media-hidecontrols",
   1073      true,
   1074      "---",
   1075      null,
   1076      "context-viewvideo",
   1077      true,
   1078      "context-video-pictureinpicture",
   1079      true,
   1080      "---",
   1081      null,
   1082      "context-video-saveimage",
   1083      true,
   1084      "context-savevideo",
   1085      true,
   1086      "context-copyvideourl",
   1087      true,
   1088      "context-sendvideo",
   1089      true,
   1090      "---",
   1091      null,
   1092      "context-take-screenshot",
   1093      true,
   1094      "---",
   1095      null,
   1096      ...askChatMenu,
   1097      "frame",
   1098      null,
   1099      getThisFrameSubMenu([
   1100        "context-showonlythisframe",
   1101        true,
   1102        "context-openframeintab",
   1103        true,
   1104        "context-openframe",
   1105        true,
   1106        "---",
   1107        null,
   1108        "context-reloadframe",
   1109        true,
   1110        "---",
   1111        null,
   1112        "context-bookmarkframe",
   1113        true,
   1114        "context-saveframe",
   1115        true,
   1116        "---",
   1117        null,
   1118        "context-printframe",
   1119        true,
   1120        "---",
   1121        null,
   1122        "context-viewframeinfo",
   1123        true,
   1124      ]),
   1125      null,
   1126    ],
   1127    {
   1128      awaitOnMenuBuilt: {
   1129        id: "context-ask-chat",
   1130      },
   1131    }
   1132  );
   1133 
   1134  await SpecialPowers.popPrefEnv();
   1135 
   1136  await SpecialPowers.pushPrefEnv({
   1137    set: [["media.videocontrols.picture-in-picture.enabled", false]],
   1138  });
   1139 
   1140  await test_contextmenu(
   1141    "#test-video-in-iframe",
   1142    [
   1143      "context-media-play",
   1144      true,
   1145      "context-media-mute",
   1146      true,
   1147      "context-media-playbackrate",
   1148      null,
   1149      [
   1150        "context-media-playbackrate-050x",
   1151        true,
   1152        "context-media-playbackrate-100x",
   1153        true,
   1154        "context-media-playbackrate-125x",
   1155        true,
   1156        "context-media-playbackrate-150x",
   1157        true,
   1158        "context-media-playbackrate-200x",
   1159        true,
   1160      ],
   1161      null,
   1162      "context-media-loop",
   1163      true,
   1164      "context-video-fullscreen",
   1165      true,
   1166      "context-media-hidecontrols",
   1167      true,
   1168      "---",
   1169      null,
   1170      "context-viewvideo",
   1171      true,
   1172      "---",
   1173      null,
   1174      "context-video-saveimage",
   1175      true,
   1176      "context-savevideo",
   1177      true,
   1178      "context-copyvideourl",
   1179      true,
   1180      "context-sendvideo",
   1181      true,
   1182      "---",
   1183      null,
   1184      "context-take-screenshot",
   1185      true,
   1186      "---",
   1187      null,
   1188      ...askChatMenu,
   1189      "frame",
   1190      null,
   1191      getThisFrameSubMenu([
   1192        "context-showonlythisframe",
   1193        true,
   1194        "context-openframeintab",
   1195        true,
   1196        "context-openframe",
   1197        true,
   1198        "---",
   1199        null,
   1200        "context-reloadframe",
   1201        true,
   1202        "---",
   1203        null,
   1204        "context-bookmarkframe",
   1205        true,
   1206        "context-saveframe",
   1207        true,
   1208        "---",
   1209        null,
   1210        "context-printframe",
   1211        true,
   1212        "---",
   1213        null,
   1214        "context-viewframeinfo",
   1215        true,
   1216      ]),
   1217      null,
   1218    ],
   1219    {
   1220      awaitOnMenuBuilt: {
   1221        id: "context-ask-chat",
   1222      },
   1223    }
   1224  );
   1225 
   1226  await SpecialPowers.popPrefEnv();
   1227 });
   1228 
   1229 add_task(async function test_audio_in_iframe() {
   1230  await test_contextmenu(
   1231    "#test-audio-in-iframe",
   1232    [
   1233      "context-media-play",
   1234      true,
   1235      "context-media-mute",
   1236      true,
   1237      "context-media-playbackrate",
   1238      null,
   1239      [
   1240        "context-media-playbackrate-050x",
   1241        true,
   1242        "context-media-playbackrate-100x",
   1243        true,
   1244        "context-media-playbackrate-125x",
   1245        true,
   1246        "context-media-playbackrate-150x",
   1247        true,
   1248        "context-media-playbackrate-200x",
   1249        true,
   1250      ],
   1251      null,
   1252      "context-media-loop",
   1253      true,
   1254      "---",
   1255      null,
   1256      "context-saveaudio",
   1257      true,
   1258      "context-copyaudiourl",
   1259      true,
   1260      "context-sendaudio",
   1261      true,
   1262      "---",
   1263      null,
   1264      ...askChatMenu,
   1265      "frame",
   1266      null,
   1267      getThisFrameSubMenu([
   1268        "context-showonlythisframe",
   1269        true,
   1270        "context-openframeintab",
   1271        true,
   1272        "context-openframe",
   1273        true,
   1274        "---",
   1275        null,
   1276        "context-reloadframe",
   1277        true,
   1278        "---",
   1279        null,
   1280        "context-bookmarkframe",
   1281        true,
   1282        "context-saveframe",
   1283        true,
   1284        "---",
   1285        null,
   1286        "context-printframe",
   1287        true,
   1288        "---",
   1289        null,
   1290        "context-viewframeinfo",
   1291        true,
   1292      ]),
   1293      null,
   1294    ],
   1295    {
   1296      awaitOnMenuBuilt: {
   1297        id: "context-ask-chat",
   1298      },
   1299    }
   1300  );
   1301 });
   1302 
   1303 add_task(async function test_image_in_iframe() {
   1304  await test_contextmenu(
   1305    "#test-image-in-iframe",
   1306    [
   1307      "context-viewimage",
   1308      true,
   1309      "context-saveimage",
   1310      true,
   1311      "context-copyimage-contents",
   1312      true,
   1313      "context-copyimage",
   1314      true,
   1315      "context-sendimage",
   1316      true,
   1317      ...getTextRecognitionItems(),
   1318      ...(Services.prefs.getBoolPref("browser.menu.showViewImageInfo", false)
   1319        ? ["context-viewimageinfo", true]
   1320        : []),
   1321      ...(Services.prefs.getBoolPref("browser.search.visualSearch.featureGate")
   1322        ? ["context-visual-search", true]
   1323        : []),
   1324      "---",
   1325      null,
   1326      "context-setDesktopBackground",
   1327      true,
   1328      "---",
   1329      null,
   1330      "context-take-screenshot",
   1331      true,
   1332      "---",
   1333      null,
   1334      ...askChatMenu,
   1335      "frame",
   1336      null,
   1337      getThisFrameSubMenu([
   1338        "context-showonlythisframe",
   1339        true,
   1340        "context-openframeintab",
   1341        true,
   1342        "context-openframe",
   1343        true,
   1344        "---",
   1345        null,
   1346        "context-reloadframe",
   1347        true,
   1348        "---",
   1349        null,
   1350        "context-bookmarkframe",
   1351        true,
   1352        "context-saveframe",
   1353        true,
   1354        "---",
   1355        null,
   1356        "context-printframe",
   1357        true,
   1358        "---",
   1359        null,
   1360        "context-viewframeinfo",
   1361        true,
   1362      ]),
   1363      null,
   1364    ],
   1365    {
   1366      awaitOnMenuBuilt: {
   1367        id: "context-ask-chat",
   1368      },
   1369    }
   1370  );
   1371 });
   1372 
   1373 add_task(async function test_pdf_viewer_in_iframe() {
   1374  await test_contextmenu(
   1375    "#test-pdf-viewer-in-frame",
   1376    [
   1377      ...NAVIGATION_ITEMS,
   1378      "context-savepage",
   1379      true,
   1380      "context-selectall",
   1381      true,
   1382      "---",
   1383      null,
   1384      "context-take-screenshot",
   1385      true,
   1386      "---",
   1387      null,
   1388      ...askChatMenu,
   1389      "frame",
   1390      null,
   1391      getThisFrameSubMenu([
   1392        "context-showonlythisframe",
   1393        true,
   1394        "context-openframeintab",
   1395        true,
   1396        "context-openframe",
   1397        true,
   1398        "---",
   1399        null,
   1400        "context-reloadframe",
   1401        true,
   1402        "---",
   1403        null,
   1404        "context-bookmarkframe",
   1405        true,
   1406        "context-saveframe",
   1407        true,
   1408        "---",
   1409        null,
   1410        "context-printframe",
   1411        true,
   1412        "---",
   1413        null,
   1414        "context-viewframeinfo",
   1415        true,
   1416      ]),
   1417      null,
   1418      "---",
   1419      null,
   1420      "context-viewsource",
   1421      true,
   1422    ],
   1423    {
   1424      shiftkey: true,
   1425      awaitOnMenuBuilt: {
   1426        id: "context-ask-chat",
   1427      },
   1428    }
   1429  );
   1430 });
   1431 
   1432 add_task(async function test_textarea() {
   1433  // Disabled since this is seeing spell-check-enabled
   1434  // instead of spell-add-dictionaries-main
   1435  todo(false, "spell checker tests are failing, bug 1246296");
   1436 
   1437  /*
   1438  yield test_contextmenu("#test-textarea",
   1439    ["context-undo",                false,
   1440     "context-redo",                false,
   1441     "---",                         null,
   1442     "context-cut",                 true,
   1443     "context-copy",                true,
   1444     "context-paste",               null,
   1445     "context-delete",              false,
   1446     "---",                         null,
   1447     "context-selectall",           true,
   1448     "---",                         null,
   1449     "spell-add-dictionaries-main", true,
   1450    ],
   1451    {
   1452      skipFocusChange: true,
   1453    }
   1454  );
   1455  */
   1456 });
   1457 
   1458 add_task(async function test_textarea_spellcheck() {
   1459  todo(false, "spell checker tests are failing, bug 1246296");
   1460 
   1461  /*
   1462  yield test_contextmenu("#test-textarea",
   1463    ["*chubbiness",         true, // spelling suggestion
   1464     "spell-add-to-dictionary", true,
   1465     "---",                 null,
   1466     "context-undo",        false,
   1467     "context-redo",        false,
   1468     "---",                 null,
   1469     "context-cut",         true,
   1470     "context-copy",        true,
   1471     "context-paste",       null, // ignore clipboard state
   1472     "context-delete",      false,
   1473     "---",                 null,
   1474     "context-selectall",   true,
   1475     "---",                 null,
   1476     "spell-check-enabled", true,
   1477     "spell-dictionaries",  true,
   1478         ["spell-check-dictionary-en-US", true,
   1479          "---",                          null,
   1480          "spell-add-dictionaries",       true], null
   1481    ],
   1482    {
   1483      waitForSpellCheck: true,
   1484      offsetX: 6,
   1485      offsetY: 6,
   1486      postCheckContextMenuFn() {
   1487        document.getElementById("spell-add-to-dictionary").doCommand();
   1488      }
   1489    }
   1490  );
   1491  */
   1492 });
   1493 
   1494 add_task(async function test_plaintext2() {
   1495  await test_contextmenu("#test-text", plainTextItems);
   1496 });
   1497 
   1498 add_task(async function test_undo_add_to_dictionary() {
   1499  todo(false, "spell checker tests are failing, bug 1246296");
   1500 
   1501  /*
   1502  yield test_contextmenu("#test-textarea",
   1503    ["spell-undo-add-to-dictionary", true,
   1504     "---",                 null,
   1505     "context-undo",        false,
   1506     "context-redo",        false,
   1507     "---",                 null,
   1508     "context-cut",         true,
   1509     "context-copy",        true,
   1510     "context-paste",       null, // ignore clipboard state
   1511     "context-delete",      false,
   1512     "context-selectall",   true,
   1513     "---",                 null,
   1514     "spell-check-enabled", true,
   1515     "spell-dictionaries",  true,
   1516         ["spell-check-dictionary-en-US", true,
   1517          "---",                          null,
   1518          "spell-add-dictionaries",       true], null
   1519    ],
   1520    {
   1521      waitForSpellCheck: true,
   1522      postCheckContextMenuFn() {
   1523        document.getElementById("spell-undo-add-to-dictionary")
   1524                .doCommand();
   1525      }
   1526    }
   1527  );
   1528  */
   1529 });
   1530 
   1531 add_task(async function test_contenteditable() {
   1532  todo(false, "spell checker tests are failing, bug 1246296");
   1533 
   1534  /*
   1535  yield test_contextmenu("#test-contenteditable",
   1536    ["spell-no-suggestions", false,
   1537     "spell-add-to-dictionary", true,
   1538     "---",                 null,
   1539     "context-undo",        false,
   1540     "context-redo",        false,
   1541     "---",                 null,
   1542     "context-cut",         true,
   1543     "context-copy",        true,
   1544     "context-paste",       null, // ignore clipboard state
   1545     "context-delete",      false,
   1546     "context-selectall",   true,
   1547     "---",                 null,
   1548     "spell-check-enabled", true,
   1549     "spell-dictionaries",  true,
   1550         ["spell-check-dictionary-en-US", true,
   1551          "---",                          null,
   1552          "spell-add-dictionaries",       true], null
   1553    ],
   1554    {waitForSpellCheck: true}
   1555  );
   1556  */
   1557 });
   1558 
   1559 add_task(async function test_copylinkcommand() {
   1560  await test_contextmenu("#test-link", null, {
   1561    async postCheckContextMenuFn() {
   1562      document.commandDispatcher
   1563        .getControllerForCommand("cmd_copyLink")
   1564        .doCommand("cmd_copyLink");
   1565 
   1566      // The easiest way to check the clipboard is to paste the contents
   1567      // into a textbox.
   1568      await SpecialPowers.spawn(
   1569        gBrowser.selectedBrowser,
   1570        [],
   1571        async function () {
   1572          let doc = content.document;
   1573          let input = doc.getElementById("test-input");
   1574          input.focus();
   1575          input.value = "";
   1576        }
   1577      );
   1578      document.commandDispatcher
   1579        .getControllerForCommand("cmd_paste")
   1580        .doCommand("cmd_paste");
   1581      await SpecialPowers.spawn(
   1582        gBrowser.selectedBrowser,
   1583        [],
   1584        async function () {
   1585          let doc = content.document;
   1586          let input = doc.getElementById("test-input");
   1587          Assert.equal(
   1588            input.value,
   1589            // eslint-disable-next-line @microsoft/sdl/no-insecure-url
   1590            "http://mozilla.com/",
   1591            "paste for command cmd_paste"
   1592          );
   1593          // Don't keep focus, because that may affect clipboard commands in
   1594          // subsequently-opened menus.
   1595          input.blur();
   1596        }
   1597      );
   1598    },
   1599  });
   1600 });
   1601 
   1602 add_task(async function test_dom_full_screen() {
   1603  let exited = BrowserTestUtils.waitForEvent(window, "MozDOMFullscreen:Exited");
   1604 
   1605  let fullscreenItems = NAVIGATION_ITEMS.concat([
   1606    "context-leave-dom-fullscreen",
   1607    true,
   1608    "---",
   1609    null,
   1610    "context-savepage",
   1611    true,
   1612    "context-selectall",
   1613    true,
   1614    "---",
   1615    null,
   1616    "context-take-screenshot",
   1617    true,
   1618    "---",
   1619    null,
   1620    ...askChatMenu,
   1621    "---",
   1622    null,
   1623    "context-viewsource",
   1624    true,
   1625  ]);
   1626  if (AppConstants.platform == "macosx") {
   1627    // Put the bookmarks item next to save page:
   1628    const bmPageIndex = fullscreenItems.indexOf("context-bookmarkpage");
   1629    let bmPageItems = fullscreenItems.splice(bmPageIndex, 2);
   1630    fullscreenItems.splice(
   1631      fullscreenItems.indexOf("context-savepage"),
   1632      0,
   1633      ...bmPageItems
   1634    );
   1635  }
   1636  await test_contextmenu("#test-dom-full-screen", fullscreenItems, {
   1637    shiftkey: true,
   1638    async preCheckContextMenuFn() {
   1639      await SpecialPowers.pushPrefEnv({
   1640        set: [
   1641          ["full-screen-api.allow-trusted-requests-only", false],
   1642          ["full-screen-api.transition-duration.enter", "0 0"],
   1643          ["full-screen-api.transition-duration.leave", "0 0"],
   1644        ],
   1645      });
   1646      await SpecialPowers.spawn(
   1647        gBrowser.selectedBrowser,
   1648        [],
   1649        async function () {
   1650          let doc = content.document;
   1651          let win = doc.defaultView;
   1652          let full_screen_element = doc.getElementById("test-dom-full-screen");
   1653          let awaitFullScreenChange = ContentTaskUtils.waitForEvent(
   1654            win,
   1655            "fullscreenchange"
   1656          );
   1657          full_screen_element.requestFullscreen();
   1658          await awaitFullScreenChange;
   1659        }
   1660      );
   1661    },
   1662    async postCheckContextMenuFn() {
   1663      await SpecialPowers.spawn(
   1664        gBrowser.selectedBrowser,
   1665        [],
   1666        async function () {
   1667          let win = content.document.defaultView;
   1668          let awaitFullScreenChange = ContentTaskUtils.waitForEvent(
   1669            win,
   1670            "fullscreenchange"
   1671          );
   1672          content.document.exitFullscreen();
   1673          await awaitFullScreenChange;
   1674        }
   1675      );
   1676    },
   1677    awaitOnMenuBuilt: {
   1678      id: "context-ask-chat",
   1679    },
   1680  });
   1681  await exited;
   1682 
   1683  await BrowserTestUtils.waitForCondition(() => {
   1684    return !gBrowser.selectedBrowser.browsingContext.currentWindowGlobal.getActor(
   1685      "DOMFullscreen"
   1686    ).timerId;
   1687  });
   1688 
   1689  if (AppConstants.platform == "macosx") {
   1690    // On macOS, the fullscreen transition takes some extra time
   1691    // to complete, and we don't receive events for it. We need to
   1692    // wait for it to complete or else input events in the next test
   1693    // might get eaten up. This is the best we can currently do.
   1694 
   1695    // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
   1696    await new Promise(resolve => setTimeout(resolve, 2000));
   1697  }
   1698 
   1699  await SimpleTest.promiseFocus(window);
   1700 });
   1701 
   1702 add_task(async function test_pagemenu2() {
   1703  await test_contextmenu(
   1704    "#test-text",
   1705    [
   1706      ...NAVIGATION_ITEMS,
   1707      "context-savepage",
   1708      true,
   1709      "context-selectall",
   1710      true,
   1711      "---",
   1712      null,
   1713      "context-take-screenshot",
   1714      true,
   1715      "---",
   1716      null,
   1717      ...askChatMenu,
   1718      "---",
   1719      null,
   1720      "context-viewsource",
   1721      true,
   1722    ],
   1723    {
   1724      shiftkey: true,
   1725      awaitOnMenuBuilt: {
   1726        id: "context-ask-chat",
   1727      },
   1728    }
   1729  );
   1730 });
   1731 
   1732 add_task(async function test_select_text() {
   1733  await test_contextmenu(
   1734    "#test-select-text",
   1735    [
   1736      "context-copy",
   1737      true,
   1738      "context-selectall",
   1739      true,
   1740      "context-print-selection",
   1741      true,
   1742      "---",
   1743      null,
   1744      "context-copy-link-to-highlight",
   1745      null,
   1746      "context-copy-clean-link-to-highlight",
   1747      null,
   1748      "---",
   1749      null,
   1750      "context-take-screenshot",
   1751      true,
   1752      "---",
   1753      null,
   1754      "context-searchselect",
   1755      true,
   1756      "context-searchselect-private",
   1757      true,
   1758      ...(hasSelectTranslations ? ["context-translate-selection", true] : []),
   1759      ...askChatMenu,
   1760      "---",
   1761      null,
   1762      "context-viewpartialsource-selection",
   1763      true,
   1764    ],
   1765    {
   1766      offsetX: 6,
   1767      offsetY: 6,
   1768      async preCheckContextMenuFn() {
   1769        await selectText("#test-select-text");
   1770      },
   1771      awaitOnMenuBuilt: {
   1772        id: "context-ask-chat",
   1773      },
   1774    }
   1775  );
   1776 });
   1777 
   1778 add_task(async function test_select_text_search_service_not_initialized() {
   1779  let statuses = ["not initialized", "failed", "started"];
   1780  for (let status of statuses) {
   1781    Services.search.wrappedJSObject.forceInitializationStatusForTests(status);
   1782    await test_contextmenu(
   1783      "#test-select-text",
   1784      [
   1785        "context-copy",
   1786        true,
   1787        "context-selectall",
   1788        true,
   1789        "context-print-selection",
   1790        true,
   1791        "---",
   1792        null,
   1793        "context-copy-link-to-highlight",
   1794        null,
   1795        "context-copy-clean-link-to-highlight",
   1796        null,
   1797        "---",
   1798        null,
   1799        "context-take-screenshot",
   1800        true,
   1801        ...(hasSelectTranslations
   1802          ? ["---", null, "context-translate-selection", true]
   1803          : []),
   1804        ...askChatMenu,
   1805        "---",
   1806        null,
   1807        "context-viewpartialsource-selection",
   1808        true,
   1809      ],
   1810      {
   1811        offsetX: 6,
   1812        offsetY: 6,
   1813        async preCheckContextMenuFn() {
   1814          await selectText("#test-select-text");
   1815        },
   1816        awaitOnMenuBuilt: {
   1817          id: "context-ask-chat",
   1818        },
   1819      }
   1820    );
   1821  }
   1822  // Restore the search service initialization status
   1823  Services.search.wrappedJSObject.forceInitializationStatusForTests("success");
   1824 });
   1825 
   1826 add_task(async function test_select_text_link() {
   1827  await test_contextmenu(
   1828    "#test-select-text-link",
   1829    [
   1830      "context-openlinkincurrent",
   1831      true,
   1832      "context-openlinkintab",
   1833      true,
   1834      ...(hasContainers ? ["context-openlinkinusercontext-menu", true] : []),
   1835      // We need a blank entry here because the containers submenu is
   1836      // dynamically generated with no ids.
   1837      ...(hasContainers ? ["", null] : []),
   1838      "context-openlink",
   1839      true,
   1840      "context-openlinkprivate",
   1841      true,
   1842      "context-previewlink",
   1843      true,
   1844      "---",
   1845      null,
   1846      "context-bookmarklink",
   1847      true,
   1848      "context-savelink",
   1849      true,
   1850      ...(hasStripOnShare ? ["context-stripOnShareLink", false] : []),
   1851      "---",
   1852      null,
   1853      "context-copy",
   1854      true,
   1855      "context-selectall",
   1856      true,
   1857      "context-print-selection",
   1858      true,
   1859      "---",
   1860      null,
   1861      "context-copy-link-to-highlight",
   1862      null,
   1863      "context-copy-clean-link-to-highlight",
   1864      null,
   1865      "---",
   1866      null,
   1867      "context-searchselect",
   1868      true,
   1869      "context-searchselect-private",
   1870      true,
   1871      ...(hasSelectTranslations ? ["context-translate-selection", true] : []),
   1872      ...askChatMenu,
   1873      "---",
   1874      null,
   1875      "context-viewpartialsource-selection",
   1876      true,
   1877    ],
   1878    {
   1879      offsetX: 6,
   1880      offsetY: 6,
   1881      async preCheckContextMenuFn() {
   1882        await selectText("#test-select-text-link");
   1883      },
   1884      async postCheckContextMenuFn() {
   1885        await SpecialPowers.spawn(
   1886          gBrowser.selectedBrowser,
   1887          [],
   1888          async function () {
   1889            let win = content.document.defaultView;
   1890            win.getSelection().removeAllRanges();
   1891          }
   1892        );
   1893      },
   1894      awaitOnMenuBuilt: {
   1895        id: "context-ask-chat",
   1896      },
   1897    }
   1898  );
   1899 });
   1900 
   1901 add_task(async function test_imagelink() {
   1902  await test_contextmenu(
   1903    "#test-image-link",
   1904    [
   1905      "context-openlinkintab",
   1906      true,
   1907      ...(hasContainers ? ["context-openlinkinusercontext-menu", true] : []),
   1908      // We need a blank entry here because the containers submenu is
   1909      // dynamically generated with no ids.
   1910      ...(hasContainers ? ["", null] : []),
   1911      "context-openlink",
   1912      true,
   1913      "context-openlinkprivate",
   1914      true,
   1915      "context-previewlink",
   1916      true,
   1917      "---",
   1918      null,
   1919      "context-bookmarklink",
   1920      true,
   1921      "context-savelink",
   1922      true,
   1923      "context-copylink",
   1924      true,
   1925      ...(hasStripOnShare ? ["context-stripOnShareLink", false] : []),
   1926      "---",
   1927      null,
   1928      "context-viewimage",
   1929      true,
   1930      "context-saveimage",
   1931      true,
   1932      "context-copyimage-contents",
   1933      true,
   1934      "context-copyimage",
   1935      true,
   1936      "context-sendimage",
   1937      true,
   1938      ...getTextRecognitionItems(),
   1939      ...(Services.prefs.getBoolPref("browser.menu.showViewImageInfo", false)
   1940        ? ["context-viewimageinfo", true]
   1941        : []),
   1942      ...(Services.prefs.getBoolPref("browser.search.visualSearch.featureGate")
   1943        ? ["context-visual-search", true]
   1944        : []),
   1945      "---",
   1946      null,
   1947      "context-setDesktopBackground",
   1948      true,
   1949      "---",
   1950      null,
   1951      ...askChatMenu,
   1952    ],
   1953    {
   1954      awaitOnMenuBuilt: {
   1955        id: "context-ask-chat",
   1956      },
   1957    }
   1958  );
   1959 });
   1960 
   1961 add_task(async function test_select_input_text() {
   1962  todo(false, "spell checker tests are failing, bug 1246296");
   1963 
   1964  /*
   1965  yield test_contextmenu("#test-select-input-text",
   1966    ["context-undo",                 false,
   1967     "context-redo",                 false,
   1968     "---",                          null,
   1969     "context-cut",                  true,
   1970     "context-copy",                 true,
   1971     "context-paste",                null, // ignore clipboard state
   1972     "context-delete",               true,
   1973     "context-selectall",            true,
   1974     "---",                          null,
   1975     "context-searchselect",         true,
   1976     "context-searchselect-private", true,
   1977     "---",                          null,
   1978     "spell-check-enabled",          true
   1979    ].concat(LOGIN_FILL_ITEMS),
   1980    {
   1981      *preCheckContextMenuFn() {
   1982        yield ContentTask.spawn(gBrowser.selectedBrowser, null, function*() {
   1983          let doc = content.document;
   1984          let win = doc.defaultView;
   1985          win.getSelection().removeAllRanges();
   1986          let element = doc.querySelector("#test-select-input-text");
   1987          element.select();
   1988        });
   1989      }
   1990    }
   1991  );
   1992  */
   1993 });
   1994 
   1995 add_task(async function test_select_input_text_password() {
   1996  todo(false, "spell checker tests are failing, bug 1246296");
   1997 
   1998  /*
   1999  yield test_contextmenu("#test-select-input-text-type-password",
   2000    ["context-undo",        false,
   2001     "context-redo",        false,
   2002     "---",                 null,
   2003     "context-cut",         true,
   2004     "context-copy",        true,
   2005     "context-paste",       null, // ignore clipboard state
   2006     "context-delete",      true,
   2007     "context-selectall",   true,
   2008     "---",                 null,
   2009     "spell-check-enabled", true,
   2010     // spell checker is shown on input[type="password"] on this testcase
   2011     "spell-dictionaries",  true,
   2012         ["spell-check-dictionary-en-US", true,
   2013          "---",                          null,
   2014          "spell-add-dictionaries",       true], null
   2015    ].concat(LOGIN_FILL_ITEMS),
   2016    {
   2017      *preCheckContextMenuFn() {
   2018        yield ContentTask.spawn(gBrowser.selectedBrowser, null, function*() {
   2019          let doc = content.document;
   2020          let win = doc.defaultView;
   2021          win.getSelection().removeAllRanges();
   2022          let element = doc.querySelector("#test-select-input-text-type-password");
   2023          element.select();
   2024        });
   2025      },
   2026      *postCheckContextMenuFn() {
   2027        yield ContentTask.spawn(gBrowser.selectedBrowser, null, function*() {
   2028          let win = content.document.defaultView;
   2029          win.getSelection().removeAllRanges();
   2030        });
   2031      }
   2032    }
   2033  );
   2034  */
   2035 });
   2036 
   2037 add_task(async function test_longdesc() {
   2038  await test_contextmenu(
   2039    "#test-longdesc",
   2040    [
   2041      "context-viewimage",
   2042      true,
   2043      "context-saveimage",
   2044      true,
   2045      "context-copyimage-contents",
   2046      true,
   2047      "context-copyimage",
   2048      true,
   2049      "context-sendimage",
   2050      true,
   2051      ...getTextRecognitionItems(),
   2052      ...(Services.prefs.getBoolPref("browser.menu.showViewImageInfo", false)
   2053        ? ["context-viewimageinfo", true]
   2054        : []),
   2055      "context-viewimagedesc",
   2056      true,
   2057      ...(Services.prefs.getBoolPref("browser.search.visualSearch.featureGate")
   2058        ? ["context-visual-search", true]
   2059        : []),
   2060      "---",
   2061      null,
   2062      "context-setDesktopBackground",
   2063      true,
   2064      "---",
   2065      null,
   2066      "context-take-screenshot",
   2067      true,
   2068      "---",
   2069      null,
   2070      ...askChatMenu,
   2071    ],
   2072    {
   2073      awaitOnMenuBuilt: {
   2074        id: "context-ask-chat",
   2075      },
   2076    }
   2077  );
   2078 });
   2079 
   2080 add_task(async function test_srcdoc() {
   2081  await test_contextmenu(
   2082    "#test-srcdoc",
   2083    [
   2084      ...NAVIGATION_ITEMS,
   2085      "context-savepage",
   2086      true,
   2087      "context-selectall",
   2088      true,
   2089      "---",
   2090      null,
   2091      "context-take-screenshot",
   2092      true,
   2093      "---",
   2094      null,
   2095      ...askChatMenu,
   2096      "frame",
   2097      null,
   2098      getThisFrameSubMenu([
   2099        "context-reloadframe",
   2100        true,
   2101        "---",
   2102        null,
   2103        "context-saveframe",
   2104        true,
   2105        "---",
   2106        null,
   2107        "context-printframe",
   2108        true,
   2109        "---",
   2110        null,
   2111        "context-viewframesource",
   2112        true,
   2113        "context-viewframeinfo",
   2114        true,
   2115      ]),
   2116      null,
   2117      "---",
   2118      null,
   2119      "context-viewsource",
   2120      true,
   2121    ],
   2122    {
   2123      awaitOnMenuBuilt: {
   2124        id: "context-ask-chat",
   2125      },
   2126    }
   2127  );
   2128 });
   2129 
   2130 add_task(async function test_input_spell_false() {
   2131  todo(false, "spell checker tests are failing, bug 1246296");
   2132 
   2133  /*
   2134  yield test_contextmenu("#test-contenteditable-spellcheck-false",
   2135    ["context-undo",        false,
   2136     "context-redo",        false,
   2137     "---",                 null,
   2138     "context-cut",         true,
   2139     "context-copy",        true,
   2140     "context-paste",       null, // ignore clipboard state
   2141     "context-delete",      false,
   2142     "context-selectall",   true,
   2143    ]
   2144  );
   2145  */
   2146 });
   2147 
   2148 add_task(async function test_svg_link() {
   2149  await test_contextmenu(
   2150    "#svg-with-link > a",
   2151    [
   2152      "context-openlinkintab",
   2153      true,
   2154      ...(hasContainers ? ["context-openlinkinusercontext-menu", true] : []),
   2155      // We need a blank entry here because the containers submenu is
   2156      // dynamically generated with no ids.
   2157      ...(hasContainers ? ["", null] : []),
   2158      "context-openlink",
   2159      true,
   2160      "context-openlinkprivate",
   2161      true,
   2162      "context-previewlink",
   2163      true,
   2164      "---",
   2165      null,
   2166      "context-bookmarklink",
   2167      true,
   2168      "context-savelink",
   2169      true,
   2170      "context-copylink",
   2171      true,
   2172      ...(hasStripOnShare ? ["context-stripOnShareLink", false] : []),
   2173      "---",
   2174      null,
   2175      "context-searchselect",
   2176      true,
   2177      "context-searchselect-private",
   2178      true,
   2179      ...askChatMenu,
   2180    ],
   2181    {
   2182      awaitOnMenuBuilt: {
   2183        id: "context-ask-chat",
   2184      },
   2185    }
   2186  );
   2187 
   2188  await test_contextmenu(
   2189    "#svg-with-link2 > a",
   2190    [
   2191      "context-openlinkintab",
   2192      true,
   2193      ...(hasContainers ? ["context-openlinkinusercontext-menu", true] : []),
   2194      // We need a blank entry here because the containers submenu is
   2195      // dynamically generated with no ids.
   2196      ...(hasContainers ? ["", null] : []),
   2197      "context-openlink",
   2198      true,
   2199      "context-openlinkprivate",
   2200      true,
   2201      "context-previewlink",
   2202      true,
   2203      "---",
   2204      null,
   2205      "context-bookmarklink",
   2206      true,
   2207      "context-savelink",
   2208      true,
   2209      "context-copylink",
   2210      true,
   2211      ...(hasStripOnShare ? ["context-stripOnShareLink", false] : []),
   2212      "---",
   2213      null,
   2214      "context-searchselect",
   2215      true,
   2216      "context-searchselect-private",
   2217      true,
   2218      ...askChatMenu,
   2219    ],
   2220    {
   2221      awaitOnMenuBuilt: {
   2222        id: "context-ask-chat",
   2223      },
   2224    }
   2225  );
   2226 
   2227  await test_contextmenu(
   2228    "#svg-with-link3 > a",
   2229    [
   2230      "context-openlinkintab",
   2231      true,
   2232      ...(hasContainers ? ["context-openlinkinusercontext-menu", true] : []),
   2233      // We need a blank entry here because the containers submenu is
   2234      // dynamically generated with no ids.
   2235      ...(hasContainers ? ["", null] : []),
   2236      "context-openlink",
   2237      true,
   2238      "context-openlinkprivate",
   2239      true,
   2240      "context-previewlink",
   2241      true,
   2242      "---",
   2243      null,
   2244      "context-bookmarklink",
   2245      true,
   2246      "context-savelink",
   2247      true,
   2248      "context-copylink",
   2249      true,
   2250      ...(hasStripOnShare ? ["context-stripOnShareLink", false] : []),
   2251      "---",
   2252      null,
   2253      "context-searchselect",
   2254      true,
   2255      "context-searchselect-private",
   2256      true,
   2257      ...askChatMenu,
   2258    ],
   2259    {
   2260      awaitOnMenuBuilt: {
   2261        id: "context-ask-chat",
   2262      },
   2263    }
   2264  );
   2265 });
   2266 
   2267 add_task(async function test_svg_relative_link() {
   2268  await test_contextmenu(
   2269    "#svg-with-relative-link > a",
   2270    [
   2271      "context-openlinkintab",
   2272      true,
   2273      ...(hasContainers ? ["context-openlinkinusercontext-menu", true] : []),
   2274      // We need a blank entry here because the containers submenu is
   2275      // dynamically generated with no ids.
   2276      ...(hasContainers ? ["", null] : []),
   2277      "context-openlink",
   2278      true,
   2279      "context-openlinkprivate",
   2280      true,
   2281      "context-previewlink",
   2282      true,
   2283      "---",
   2284      null,
   2285      "context-bookmarklink",
   2286      true,
   2287      "context-savelink",
   2288      true,
   2289      "context-copylink",
   2290      true,
   2291      ...(hasStripOnShare ? ["context-stripOnShareLink", false] : []),
   2292      "---",
   2293      null,
   2294      "context-searchselect",
   2295      true,
   2296      "context-searchselect-private",
   2297      true,
   2298      ...askChatMenu,
   2299    ],
   2300    {
   2301      awaitOnMenuBuilt: {
   2302        id: "context-ask-chat",
   2303      },
   2304    }
   2305  );
   2306 
   2307  await test_contextmenu(
   2308    "#svg-with-relative-link2 > a",
   2309    [
   2310      "context-openlinkintab",
   2311      true,
   2312      ...(hasContainers ? ["context-openlinkinusercontext-menu", true] : []),
   2313      // We need a blank entry here because the containers submenu is
   2314      // dynamically generated with no ids.
   2315      ...(hasContainers ? ["", null] : []),
   2316      "context-openlink",
   2317      true,
   2318      "context-openlinkprivate",
   2319      true,
   2320      "context-previewlink",
   2321      true,
   2322      "---",
   2323      null,
   2324      "context-bookmarklink",
   2325      true,
   2326      "context-savelink",
   2327      true,
   2328      "context-copylink",
   2329      true,
   2330      ...(hasStripOnShare ? ["context-stripOnShareLink", false] : []),
   2331      "---",
   2332      null,
   2333      "context-searchselect",
   2334      true,
   2335      "context-searchselect-private",
   2336      true,
   2337      ...askChatMenu,
   2338    ],
   2339    {
   2340      awaitOnMenuBuilt: {
   2341        id: "context-ask-chat",
   2342      },
   2343    }
   2344  );
   2345 
   2346  await test_contextmenu(
   2347    "#svg-with-relative-link3 > a",
   2348    [
   2349      "context-openlinkintab",
   2350      true,
   2351      ...(hasContainers ? ["context-openlinkinusercontext-menu", true] : []),
   2352      // We need a blank entry here because the containers submenu is
   2353      // dynamically generated with no ids.
   2354      ...(hasContainers ? ["", null] : []),
   2355      "context-openlink",
   2356      true,
   2357      "context-openlinkprivate",
   2358      true,
   2359      "context-previewlink",
   2360      true,
   2361      "---",
   2362      null,
   2363      "context-bookmarklink",
   2364      true,
   2365      "context-savelink",
   2366      true,
   2367      "context-copylink",
   2368      true,
   2369      ...(hasStripOnShare ? ["context-stripOnShareLink", false] : []),
   2370      "---",
   2371      null,
   2372      "context-searchselect",
   2373      true,
   2374      "context-searchselect-private",
   2375      true,
   2376      ...askChatMenu,
   2377    ],
   2378    {
   2379      awaitOnMenuBuilt: {
   2380        id: "context-ask-chat",
   2381      },
   2382    }
   2383  );
   2384 });
   2385 
   2386 add_task(async function test_background_image() {
   2387  let bgImageItems = [
   2388    "context-viewimage",
   2389    true,
   2390    "context-copyimage",
   2391    true,
   2392    "context-sendimage",
   2393    true,
   2394    "---",
   2395    null,
   2396    "context-savepage",
   2397    true,
   2398    "context-selectall",
   2399    true,
   2400    "---",
   2401    null,
   2402    "context-take-screenshot",
   2403    true,
   2404    "---",
   2405    null,
   2406    ...askChatMenu,
   2407    "---",
   2408    null,
   2409    "context-viewsource",
   2410    true,
   2411  ];
   2412  if (AppConstants.platform == "macosx") {
   2413    // Back/fwd/(stop|reload) and their separator go before the image items,
   2414    // followed by the bookmark item which goes with save page - so we need
   2415    // to split up NAVIGATION_ITEMS and bgImageItems:
   2416    bgImageItems = [
   2417      ...NAVIGATION_ITEMS.slice(0, 8),
   2418      ...bgImageItems.slice(0, 8),
   2419      ...NAVIGATION_ITEMS.slice(8),
   2420      ...bgImageItems.slice(8),
   2421    ];
   2422  } else {
   2423    bgImageItems = NAVIGATION_ITEMS.concat(bgImageItems);
   2424  }
   2425  await test_contextmenu("#test-background-image", bgImageItems, {
   2426    awaitOnMenuBuilt: {
   2427      id: "context-ask-chat",
   2428    },
   2429  });
   2430 
   2431  // Don't show image related context menu commands for links with background images.
   2432  await test_contextmenu(
   2433    "#test-background-image-link",
   2434    [
   2435      "context-openlinkintab",
   2436      true,
   2437      ...(hasContainers ? ["context-openlinkinusercontext-menu", true] : []),
   2438      // We need a blank entry here because the containers submenu is
   2439      // dynamically generated with no ids.
   2440      ...(hasContainers ? ["", null] : []),
   2441      "context-openlink",
   2442      true,
   2443      "context-openlinkprivate",
   2444      true,
   2445      "context-previewlink",
   2446      true,
   2447      "---",
   2448      null,
   2449      "context-bookmarklink",
   2450      true,
   2451      "context-savelink",
   2452      true,
   2453      "context-copylink",
   2454      true,
   2455      ...(hasStripOnShare ? ["context-stripOnShareLink", false] : []),
   2456      "---",
   2457      null,
   2458      "context-searchselect",
   2459      true,
   2460      "context-searchselect-private",
   2461      true,
   2462      ...(hasSelectTranslations ? ["context-translate-selection", true] : []),
   2463      ...askChatMenu,
   2464    ],
   2465    {
   2466      awaitOnMenuBuilt: {
   2467        id: "context-ask-chat",
   2468      },
   2469    }
   2470  );
   2471 
   2472  // Don't show image related context menu commands when there is a selection
   2473  // with background images.
   2474  await test_contextmenu(
   2475    "#test-background-image",
   2476    [
   2477      "context-copy",
   2478      true,
   2479      "context-selectall",
   2480      true,
   2481      "context-print-selection",
   2482      true,
   2483      "---",
   2484      null,
   2485      "context-copy-link-to-highlight",
   2486      null,
   2487      "context-copy-clean-link-to-highlight",
   2488      null,
   2489      "---",
   2490      null,
   2491      "context-take-screenshot",
   2492      true,
   2493      "---",
   2494      null,
   2495      "context-searchselect",
   2496      true,
   2497      "context-searchselect-private",
   2498      true,
   2499      ...(hasSelectTranslations ? ["context-translate-selection", true] : []),
   2500      ...askChatMenu,
   2501      "---",
   2502      null,
   2503      "context-viewpartialsource-selection",
   2504      true,
   2505    ],
   2506    {
   2507      async preCheckContextMenuFn() {
   2508        await selectText("#test-background-image");
   2509      },
   2510      awaitOnMenuBuilt: {
   2511        id: "context-ask-chat",
   2512      },
   2513    }
   2514  );
   2515 });
   2516 
   2517 add_task(async function test_cleanup_html() {
   2518  lastElementSelector = null;
   2519  gBrowser.removeCurrentTab();
   2520 });
   2521 
   2522 /*
   2523 *   Testing that Copy without Site Tracking option does not
   2524 *   appear on internal about: pages.
   2525 */
   2526 add_task(async function test_strip_on_share_on_secure_about_page() {
   2527  let url = about_preferences_base;
   2528 
   2529  let tab = await BrowserTestUtils.openNewForegroundTab({
   2530    gBrowser,
   2531    url,
   2532  });
   2533 
   2534  let browser2 = tab.linkedBrowser;
   2535 
   2536  await SpecialPowers.spawn(browser2, [], () => {
   2537    let link = content.document.createElement("a");
   2538    link.href = "https://mozilla.com";
   2539    link.textContent = "link with query param";
   2540    link.id = "link-test-strip";
   2541    content.document.body.appendChild(link);
   2542  });
   2543 
   2544  // the Copy without Site Tracking option should not
   2545  // show up within internal about: pages
   2546  await test_contextmenu(
   2547    "#link-test-strip",
   2548    [
   2549      "context-openlinkintab",
   2550      true,
   2551      ...(hasContainers ? ["context-openlinkinusercontext-menu", true] : []),
   2552      // We need a blank entry here because the containers submenu is
   2553      // dynamically generated with no ids.
   2554      ...(hasContainers ? ["", null] : []),
   2555      "context-openlink",
   2556      true,
   2557      "context-openlinkprivate",
   2558      true,
   2559      "context-previewlink",
   2560      true,
   2561      "---",
   2562      null,
   2563      "context-bookmarklink",
   2564      true,
   2565      "context-savelink",
   2566      true,
   2567      "context-copylink",
   2568      true,
   2569      "---",
   2570      null,
   2571      "context-searchselect",
   2572      true,
   2573      "context-searchselect-private",
   2574      true,
   2575      ...(hasSelectTranslations ? ["context-translate-selection", true] : []),
   2576      ...askChatMenu,
   2577    ],
   2578    {
   2579      awaitOnMenuBuilt: {
   2580        id: "context-ask-chat",
   2581      },
   2582    }
   2583  );
   2584 
   2585  // Clean up
   2586  lastElementSelector = null;
   2587  gBrowser.removeCurrentTab();
   2588 });
   2589 
   2590 /**
   2591 * Selects the text of the element that matches the provided `selector`
   2592 *
   2593 * @param {string} selector
   2594 *        A selector passed to querySelector to find
   2595 *        the element that will be referenced.
   2596 */
   2597 async function selectText(selector) {
   2598  await SpecialPowers.spawn(
   2599    gBrowser.selectedBrowser,
   2600    [selector],
   2601    async function (contentSelector) {
   2602      info(`Selecting text of ${contentSelector}`);
   2603      let doc = content.document;
   2604      let win = doc.defaultView;
   2605      win.getSelection().removeAllRanges();
   2606      let div = doc.createRange();
   2607      let element = doc.querySelector(contentSelector);
   2608      Assert.ok(element, "Found element to select text from");
   2609      div.setStartBefore(element);
   2610      div.setEndAfter(element);
   2611      win.getSelection().addRange(div);
   2612    }
   2613  );
   2614 }
   2615 
   2616 /**
   2617 * Not all platforms support text recognition.
   2618 *
   2619 * @returns {string[]}
   2620 */
   2621 function getTextRecognitionItems() {
   2622  return Services.prefs.getBoolPref("dom.text-recognition.enabled") &&
   2623    Services.appinfo.isTextRecognitionSupported
   2624    ? ["context-imagetext", true]
   2625    : [];
   2626 }