Bug 1801566 - Refactor primary context menus. r=aleca

This moves code for context menus (and some other pop-ups) into more logical files, and renames the context menu for web content from `mailContext` to `browserContext` to avoid confusion.

Differential Revision: https://phabricator.services.mozilla.com/D162529

--HG--
rename : mail/base/content/mainPopupSet.inc.xhtml => mail/base/content/widgets/browserPopups.inc.xhtml
rename : mail/base/content/nsContextMenu.js => mail/base/content/widgets/browserPopups.js
rename : mail/base/test/browser/browser_mailContext.js => mail/base/test/browser/browser_browserContext.js
extra : rebase_source : f41e4d7b72eda7fed35a1ebcee01e9ae22297ed9
extra : amend_source : e89748ed265ee97cf933e35cf3056231c04c790e
This commit is contained in:
Geoff Lankow 2022-11-11 15:39:33 +13:00
Родитель d625f9380f
Коммит 2f689e5a2f
29 изменённых файлов: 737 добавлений и 662 удалений

Просмотреть файл

@ -17,14 +17,14 @@ export class ContextMenuParent extends JSWindowActorParent {
let tabmail = win.document.getElementById("tabmail");
if (tabmail) {
let chromeBrowser = tabmail.currentTabInfo.chromeBrowser;
if (chromeBrowser) {
chromeBrowser.contentWindow.openContextMenu(message, browser, this);
if (
chromeBrowser?.contentWindow.openContextMenu(message, browser, this)
) {
return;
}
}
let messageBrowser = win.document.getElementById("messageBrowser");
if (messageBrowser) {
messageBrowser.contentWindow.openContextMenu(message, browser, this);
if (messageBrowser?.contentWindow.openContextMenu(message, browser, this)) {
return;
}

Просмотреть файл

@ -76,6 +76,7 @@
hidden="true"
remote="true"
remoteType="web"
context="browserContext"
forcemessagemanager="true"
messagemanagergroup="browsers"
maychangeremoteness="true" />

Просмотреть файл

@ -203,6 +203,7 @@ function displayMessage(uri, viewWrapper) {
gMessage = null;
gViewWrapper = null;
gDBView = null;
messageHeaderSink.mSaveHdr = null;
HideMessageHeaderPane();
// Don't use MailE10SUtils.loadURI here, it will try to change remoteness
// and we don't want that.

Просмотреть файл

@ -26,8 +26,8 @@
height="500"
orient="vertical">
<popupset id="mainPopupSet">
#define BROWSER_POPUPS_ONLY
#include ../../base/content/mainPopupSet.inc.xhtml
#define NO_BROWSERCONTEXT
#include widgets/browserPopups.inc.xhtml
</popupset>
<script src="chrome://global/content/globalOverlay.js"/>

Просмотреть файл

@ -46,17 +46,19 @@ window.addEventListener("DOMContentLoaded", event => {
/**
* Called by ContextMenuParent if this window is about:3pane, or is
* about:message but not contained by about:3pane.
*
* @returns {boolean} true if this function opened the context menu
*/
function openContextMenu({ data, target }) {
if (window.browsingContext.parent != window.browsingContext.top) {
// Not sure how we'd get here, but let's not continue if we do.
return;
return false;
}
// TODO we'll want the context menu in non-mail pages, when they work.
const MESSAGE_PROTOCOLS = ["imap", "mailbox", "news", "nntp", "snews"];
if (!MESSAGE_PROTOCOLS.includes(target.browsingContext.currentURI.scheme)) {
return;
return false;
}
mailContextMenu.fillMessageContextMenu(data, target.browsingContext);
@ -64,6 +66,8 @@ function openContextMenu({ data, target }) {
let screenY = data.context.screenYDevPx / window.devicePixelRatio;
let popup = document.getElementById("mailContext");
popup.openPopupAtScreen(screenX, screenY, true);
return true;
}
var mailContextMenu = {
@ -115,7 +119,7 @@ var mailContextMenu = {
let mailContext = document.getElementById("mailContext");
mailContext.addEventListener("popupshowing", event => {
if (event.target == mailContext) {
this.fillMailContextMenu();
this.fillMailContextMenu(event);
}
});
mailContext.addEventListener("command", event =>
@ -233,7 +237,6 @@ var mailContextMenu = {
for (let id of [
"mailContext-openInBrowser",
"mailContext-savelink",
"mailContext-openContainingFolder",
"mailContext-recalculateJunkScore",
"mailContext-copyMessageUrl",
"mailContext-calendar-convert-menu",
@ -249,6 +252,10 @@ var mailContextMenu = {
enableItem(id, commandController.isCommandEnabled(command));
}
let inAbout3Pane = !!window.threadTree;
let inThreadTree = window.threadTree?.contains(
event.explicitOriginalTarget
);
let isDummyMessage = !gFolder;
let message = isDummyMessage
? window.messageHeaderSink.dummyMsgHeader
@ -263,10 +270,16 @@ var mailContextMenu = {
numSelectedMessages >= 1 && !isNewsgroup && gFolder?.canDeleteMessages;
let canCopy = numSelectedMessages >= 1;
setSingleSelection("mailContext-openNewTab");
setSingleSelection("mailContext-openNewWindow");
// setSingleSelection("mailContext-openContainingFolder");
setSingleSelection("mailContext-openNewTab", inThreadTree);
setSingleSelection("mailContext-openNewWindow", inThreadTree);
setSingleSelection("mailContext-openContainingFolder", !inAbout3Pane);
setSingleSelection("mailContext-forwardAsMenu");
showItem(
"mailContext-multiForwardAsAttachment",
numSelectedMessages > 1 &&
commandController.isCommandEnabled("cmd_forwardAttachment")
);
if (isDummyMessage) {
enableItem("mailContext-tags", false);
} else {
@ -430,9 +443,11 @@ var mailContextMenu = {
gViewWrapper
);
break;
// case "mailContext-openContainingFolder":
// MailUtils.displayMessageInFolderTab(gMessage);
// break;
case "mailContext-openContainingFolder":
LazyModules.MailUtils.displayMessageInFolderTab(
gDBView.hdrForFirstSelectedMessage
);
break;
// Move/copy/archive/convert/delete
// (Move and Copy sub-menus are handled in the default case.)

Просмотреть файл

@ -1,88 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* import-globals-from commandglue.js */
/* import-globals-from mailWindow.js */
/* import-globals-from nsContextMenu.js */
var { PluralForm } = ChromeUtils.importESModule(
"resource://gre/modules/PluralForm.sys.mjs"
);
var { MailServices } = ChromeUtils.import(
"resource:///modules/MailServices.jsm"
);
var gContextMenu;
/**
* Function to clear out the global nsContextMenu.
*
* @param {Event} event - The onpopuphiding event.
*/
function mailContextOnPopupHiding(aEvent) {
// Don't do anything if it's a submenu's onpopuphiding that's just bubbling
// up to the top.
if (aEvent.target != aEvent.currentTarget) {
return;
}
gContextMenu.hiding();
gContextMenu = null;
}
/**
* Function to set the global nsContextMenu.
*
* @param {Event} event - The onpopupshowing event.
*/
function fillMailContextMenu(event) {
gContextMenu = new nsContextMenu(event.target, event.shiftKey);
return gContextMenu.shouldDisplay;
}
// message pane context menu helper methods
function addEmail(url = gContextMenu.linkURL) {
let addresses = getEmail(url);
toAddressBook({
action: "create",
address: addresses,
});
}
function composeEmailTo(linkURL, identity) {
let fields = Cc[
"@mozilla.org/messengercompose/composefields;1"
].createInstance(Ci.nsIMsgCompFields);
let params = Cc[
"@mozilla.org/messengercompose/composeparams;1"
].createInstance(Ci.nsIMsgComposeParams);
fields.to = getEmail(linkURL);
params.type = Ci.nsIMsgCompType.New;
params.format = Ci.nsIMsgCompFormat.Default;
if (identity) {
params.identity = identity;
}
params.composeFields = fields;
MailServices.compose.OpenComposeWindowWithParams(null, params);
}
// Extracts email address from url string
function getEmail(url) {
var mailtolength = 7;
var qmark = url.indexOf("?");
var addresses;
if (qmark > mailtolength) {
addresses = url.substring(mailtolength, qmark);
} else {
addresses = url.substr(mailtolength);
}
// Let's try to unescape it using a character set
try {
addresses = Services.textToSubURI.unEscapeURIForUI(addresses);
} catch (ex) {
// Do nothing.
}
return addresses;
}

Просмотреть файл

@ -4,7 +4,6 @@
/* import-globals-from commandglue.js */
/* import-globals-from mail3PaneWindowCommands.js */
/* import-globals-from mailContextMenus.js */
/* import-globals-from mailWindow.js */
/* import-globals-from mailWindowOverlay.js */
/* import-globals-from msgMail3PaneWindow.js */

Просмотреть файл

@ -10,7 +10,6 @@
/* import-globals-from contentAreaClick.js */
/* import-globals-from mail3PaneWindowCommands.js */
/* import-globals-from mailCommands.js */
/* import-globals-from mailContextMenus.js */
/* import-globals-from mailCore.js */
/* import-globals-from mailWindow.js */
/* import-globals-from utilityOverlay.js */

Просмотреть файл

@ -156,7 +156,9 @@
</keyset>
<popupset id="mainPopupSet">
#include mainPopupSet.inc.xhtml
#define NO_BROWSERCONTEXT
#include widgets/browserPopups.inc.xhtml
#include widgets/toolbarContext.inc.xhtml
<!-- The panelUI is for the appmenu. -->
#include ../../components/customizableui/content/panelUI.inc.xhtml
</popupset>

Просмотреть файл

@ -107,8 +107,7 @@
<script defer="defer" src="chrome://messenger/content/searchBar.js"></script>
<script defer="defer" src="chrome://messenger/content/mail3PaneWindowCommands.js"></script>
<script defer="defer" src="chrome://global/content/contentAreaUtils.js"></script>
<script defer="defer" src="chrome://messenger/content/nsContextMenu.js"></script>
<script defer="defer" src="chrome://messenger/content/mailContextMenus.js"></script>
<script defer="defer" src="chrome://messenger/content/browserPopups.js"></script>
<script defer="defer" src="chrome://messenger/content/accountUtils.js"></script>
<script defer="defer" src="chrome://messenger/content/folderPane.js"></script>
<script defer="defer" src="chrome://communicator/content/contentAreaClick.js"></script>
@ -332,7 +331,33 @@
#include ../../../calendar/base/content/calendar-keys.inc.xhtml
<popupset id="mainPopupSet">
#include mainPopupSet.inc.xhtml
#include widgets/browserPopups.inc.xhtml
#include widgets/toolbarContext.inc.xhtml
<menupopup id="aboutPagesContext"
onpopupshowing="goUpdateCommand('cmd_copy'); goUpdateCommand('cmd_paste'); goUpdateCommand('cmd_selectAll');">
<menuitem id="aboutPagesContext-copy"
data-l10n-id="text-action-copy"
command="cmd_copy"/>
<menuitem id="aboutPagesContext-paste"
data-l10n-id="text-action-paste"
command="cmd_paste"/>
<menuitem id="aboutPagesContext-selectall"
data-l10n-id="text-action-select-all"
command="cmd_selectAll"/>
</menupopup>
<tooltip id="qfb-text-search-upsell" level="parent">
<vbox>
<label id="qfb-upsell-line-one"
class="header"
fmt="&quickFilterBar.glodaUpsell.continueSearch;"
value=""/>
<label id="qfb-upsell-line-two"
fmt="&quickFilterBar.glodaUpsell.pressEnterAndCurrent;"
value=""/>
</vbox>
</tooltip>
<!-- The panelUI is for the appmenu. -->
#include ../../components/customizableui/content/panelUI.inc.xhtml
#include ../../components/unifiedToolbar/content/unifiedToolbarPopups.inc.xhtml

Просмотреть файл

@ -915,7 +915,7 @@ var specialTabs = {
aTab.browser.setAttribute("autocompletepopup", "PopupAutoComplete");
aTab.browser.setAttribute("datetimepicker", "DateTimePickerPanel");
aTab.browser.setAttribute("selectmenulist", "ContentSelectDropdown");
aTab.browser.setAttribute("context", "mailContext");
aTab.browser.setAttribute("context", "browserContext");
aTab.browser.setAttribute("maychangeremoteness", "true");
aTab.browser.setAttribute("onclick", "return contentAreaClick(event);");
aTab.browser.openWindowInfo = aArgs.openWindowInfo || null;

Просмотреть файл

@ -13,7 +13,6 @@
lastfoldersent="false"
keepcurrentinview="true"
disableKeyNavigation="true"
context="mailContext"
onkeydown="ThreadPaneKeyDown(event);"
onselect="ThreadPaneSelectionChanged();">
#ifdef MAIN_WINDOW

Просмотреть файл

@ -134,3 +134,32 @@ function ViewSourceSavePage() {
Services.scriptSecurityManager.getSystemPrincipal()
);
}
/** Called by ContextMenuParent.sys.mjs */
function openContextMenu({ data }, browser, actor) {
let popup = browser.ownerDocument.getElementById("viewSourceContextMenu");
let newEvent = document.createEvent("MouseEvent");
let screenX = data.context.screenXDevPx / window.devicePixelRatio;
let screenY = data.context.screenYDevPx / window.devicePixelRatio;
newEvent.initNSMouseEvent(
"contextmenu",
true,
true,
null,
0,
screenX,
screenY,
0,
0,
false,
false,
false,
false,
2,
null,
0,
data.context.mozInputSource
);
popup.openPopupAtScreen(newEvent.screenX, newEvent.screenY, true, newEvent);
}

Просмотреть файл

@ -45,7 +45,6 @@
<script src="chrome://messenger/content/viewSource.js"/>
<script src="chrome://messenger/content/viewZoomOverlay.js"/>
<script src="chrome://global/content/editMenuOverlay.js"/>
<script src="chrome://messenger/content/nsContextMenu.js"/>
<stringbundle id="viewSourceBundle" src="chrome://messenger/locale/viewSource.properties"/>
@ -235,7 +234,6 @@
flex="1"
primary="true"
disableglobalhistory="true"
context="viewSourceContextMenu"
showcaret="true"
tooltip="aHTMLTooltip"
maychangeremoteness="true"

Просмотреть файл

@ -2,175 +2,131 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef NO_MAILCONTEXT
<!-- "Please keep all items and separators up to date in nsContextMenu.js when making changes here" -->
<menupopup id="mailContext"
onpopupshowing="return fillMailContextMenu(event);"
onpopuphiding="mailContextOnPopupHiding(event);">
#ifndef NO_BROWSERCONTEXT
<menupopup id="browserContext"
onpopupshowing="return browserContextOnShowing(event);"
onpopuphiding="browserContextOnHiding(event);">
<!-- Spellchecking suggestions -->
<menuitem id="mailContext-spell-no-suggestions"
<menuitem id="browserContext-spell-no-suggestions"
disabled="true"
data-l10n-id="text-action-spell-no-suggestions"/>
<menuitem id="mailContext-spell-add-to-dictionary"
<menuitem id="browserContext-spell-add-to-dictionary"
data-l10n-id="text-action-spell-add-to-dictionary"
oncommand="gSpellChecker.addToDictionary();"/>
<menuitem id="mailContext-spell-undo-add-to-dictionary"
<menuitem id="browserContext-spell-undo-add-to-dictionary"
data-l10n-id="text-action-spell-undo-add-to-dictionary"
oncommand="gSpellChecker.undoAddToDictionary();" />
<menuseparator id="mailContext-spell-suggestions-separator"/>
<menuseparator id="browserContext-spell-suggestions-separator"/>
<menuitem id="mailContext-openInBrowser"
<menuitem id="browserContext-openInBrowser"
label="&openInBrowser.label;"
accesskey="&openInBrowser.accesskey;"
oncommand="gContextMenu.openInBrowser();"/>
<menuitem id="mailContext-openLinkInBrowser"
<menuitem id="browserContext-openLinkInBrowser"
label="&openLinkInBrowser.label;"
accesskey="&openLinkInBrowser.accesskey;"
oncommand="gContextMenu.openLinkInBrowser();"/>
<menuseparator id="mailContext-sep-open-browser"/>
<menuitem id="mailContext-reload"
<menuseparator id="browserContext-sep-open-browser"/>
<menuitem id="browserContext-reload"
label="&reloadCmd.label;"
accesskey="&reloadCmd.accesskey;"
command="cmd_reload"/>
<menuitem id="mailContext-stop"
<menuitem id="browserContext-stop"
label="&stopCmd.label;"
accesskey="&stopCmd.accesskey;"
command="cmd_stop"/>
<menuseparator id="mailContext-sep-link"/>
<menuitem id="mailContext-undo"
<menuseparator id="browserContext-sep-link"/>
<menuitem id="browserContext-undo"
label="&undoDefaultCmd.label;"
accesskey="&undoDefaultCmd.accesskey;"
command="cmd_undo"/>
<menuseparator id="mailContext-sep-undo"/>
<menuitem id="mailContext-cut"
<menuseparator id="browserContext-sep-undo"/>
<menuitem id="browserContext-cut"
data-l10n-id="text-action-cut"
command="cmd_copy"/>
<menuitem id="mailContext-copy"
<menuitem id="browserContext-copy"
data-l10n-id="text-action-copy"
command="cmd_copy"/>
<menuitem id="mailContext-paste"
<menuitem id="browserContext-paste"
data-l10n-id="text-action-paste"
command="cmd_paste"/>
<menuitem id="mailContext-selectall"
<menuitem id="browserContext-selectall"
data-l10n-id="text-action-select-all"
command="cmd_selectAll"/>
<menuseparator id="mailContext-sep-clipboard"/>
<menuseparator id="browserContext-sep-clipboard"/>
<menuitem id="mailContext-searchTheWeb"
<menuitem id="browserContext-searchTheWeb"
label="[glodaComplete.webSearch1.label]"
oncommand="openWebSearch(event.target.value)"/>
<!-- Spellchecking general menu items (enable, add dictionaries...) -->
<menuseparator id="mailContext-spell-separator"/>
<menuitem id="mailContext-spell-check-enabled"
<menuseparator id="browserContext-spell-separator"/>
<menuitem id="browserContext-spell-check-enabled"
data-l10n-id="text-action-spell-check-toggle"
type="checkbox"
oncommand="gSpellChecker.toggleEnabled();"/>
<menuitem id="mailContext-spell-add-dictionaries-main"
<menuitem id="browserContext-spell-add-dictionaries-main"
label="&spellAddDictionaries.label;"
accesskey="&spellAddDictionaries.accesskey;"
oncommand="gContextMenu.addDictionaries();"/>
<menu id="mailContext-spell-dictionaries"
<menu id="browserContext-spell-dictionaries"
data-l10n-id="text-action-spell-dictionaries">
<menupopup id="mailContext-spell-dictionaries-menu">
<menuseparator id="mailContext-spell-language-separator"/>
<menuitem id="mailContext-spell-add-dictionaries"
<menupopup id="browserContext-spell-dictionaries-menu">
<menuseparator id="browserContext-spell-language-separator"/>
<menuitem id="browserContext-spell-add-dictionaries"
label="&spellAddDictionaries.label;"
accesskey="&spellAddDictionaries.accesskey;"
oncommand="gContextMenu.addDictionaries();"/>
</menupopup>
</menu>
<menuitem id="mailContext-media-play"
<menuitem id="browserContext-media-play"
label="&contextPlay.label;"
accesskey="&contextPlay.accesskey;"
oncommand="gContextMenu.mediaCommand('play');"/>
<menuitem id="mailContext-media-pause"
<menuitem id="browserContext-media-pause"
label="&contextPause.label;"
accesskey="&contextPause.accesskey;"
oncommand="gContextMenu.mediaCommand('pause');"/>
<menuitem id="mailContext-media-mute"
<menuitem id="browserContext-media-mute"
label="&contextMute.label;"
accesskey="&contextMute.accesskey;"
oncommand="gContextMenu.mediaCommand('mute');"/>
<menuitem id="mailContext-media-unmute"
<menuitem id="browserContext-media-unmute"
label="&contextUnmute.label;"
accesskey="&contextUnmute.accesskey;"
oncommand="gContextMenu.mediaCommand('unmute');"/>
<menuseparator id="mailContext-sep-edit"/>
<menuitem id="mailContext-copylink"
<menuseparator id="browserContext-sep-edit"/>
<menuitem id="browserContext-copylink"
label="&copyLinkCmd.label;"
accesskey="&copyLinkCmd.accesskey;"
command="cmd_copyLink"/>
<menuitem id="mailContext-copyimage"
<menuitem id="browserContext-copyimage"
label="&copyImageAllCmd.label;"
accesskey="&copyImageAllCmd.accesskey;"
command="cmd_copyImage"/>
<menuitem id="mailContext-addemail"
<menuitem id="browserContext-addemail"
label="&AddToAddressBook.label;"
accesskey="&AddToAddressBook.accesskey;"
oncommand="addEmail();"/>
<menuitem id="mailContext-composeemailto"
<menuitem id="browserContext-composeemailto"
label="&SendMessageTo.label;"
accesskey="&SendMessageTo.accesskey;"
oncommand="composeEmailTo(gContextMenu.linkURL);"/>
<menuitem id="mailContext-copyemail"
<menuitem id="browserContext-copyemail"
label="&copyEmailCmd.label;"
accesskey="&copyEmailCmd.accesskey;"
oncommand="gContextMenu.copyEmail();"/>
<menuseparator id="mailContext-sep-copy"/>
<menuitem id="mailContext-savelink"
<menuseparator id="browserContext-sep-copy"/>
<menuitem id="browserContext-savelink"
label="&saveLinkAsCmd.label;"
accesskey="&saveLinkAsCmd.accesskey;"
oncommand="gContextMenu.saveLink();"/>
<menuitem id="mailContext-saveimage"
<menuitem id="browserContext-saveimage"
label="&saveImageAsCmd.label;"
accesskey="&saveImageAsCmd.accesskey;"
oncommand="gContextMenu.saveImage();"/>
</menupopup>
#endif
#ifndef BROWSER_POPUPS_ONLY
<menupopup id="aboutPagesContext"
onpopupshowing="goUpdateCommand('cmd_copy'); goUpdateCommand('cmd_paste'); goUpdateCommand('cmd_selectAll');">
<menuitem id="aboutPagesContext-copy"
data-l10n-id="text-action-copy"
command="cmd_copy"/>
<menuitem id="aboutPagesContext-paste"
data-l10n-id="text-action-paste"
command="cmd_paste"/>
<menuitem id="aboutPagesContext-selectall"
data-l10n-id="text-action-select-all"
command="cmd_selectAll"/>
</menupopup>
<menupopup id="toolbar-context-menu"
onpopupshowing="calendarOnToolbarsPopupShowing(event); ToolbarContextMenu.updateExtension(this);">
<menuseparator id="customizeMailToolbarMenuSeparator"/>
<menuitem id="CustomizeMailToolbar"
command="cmd_CustomizeMailToolbar"
label="&customizeToolbar.label;"
accesskey="&customizeToolbar.accesskey;"/>
<menuseparator id="extensionsMailToolbarMenuSeparator"/>
<menuitem oncommand="ToolbarContextMenu.openAboutAddonsForContextAction(this.parentElement)"
data-l10n-id="toolbar-context-menu-manage-extension"
class="customize-context-manageExtension"/>
<menuitem oncommand="ToolbarContextMenu.removeExtensionForContextAction(this.parentElement)"
data-l10n-id="toolbar-context-menu-remove-extension"
class="customize-context-removeExtension"/>
</menupopup>
<tooltip id="qfb-text-search-upsell"
level="parent">
<vbox>
<label id="qfb-upsell-line-one"
class="header"
fmt="&quickFilterBar.glodaUpsell.continueSearch;"
value=""/>
<label id="qfb-upsell-line-two"
fmt="&quickFilterBar.glodaUpsell.pressEnterAndCurrent;"
value=""/>
</vbox>
</tooltip>
#endif
<panel id="DateTimePickerPanel"
type="arrow"

Просмотреть файл

@ -1,11 +1,8 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
* file, you can obtain one at http://mozilla.org/MPL/2.0/. */
/* import-globals-from mailTabs.js */
/* import-globals-from mailWindow.js */
/* import-globals-from utilityOverlay.js */
/* import-globals-from ../utilityOverlay.js */
var { InlineSpellChecker, SpellCheckHelper } = ChromeUtils.importESModule(
"resource://gre/modules/InlineSpellChecker.sys.mjs"
@ -28,6 +25,7 @@ var { E10SUtils } = ChromeUtils.importESModule(
"resource://gre/modules/E10SUtils.sys.mjs"
);
var gContextMenu;
var gSpellChecker = new InlineSpellChecker();
/** Called by ContextMenuParent.sys.mjs */
@ -83,9 +81,9 @@ function openContextMenu({ data }, browser, actor) {
webExtContextData: data.webExtContextData,
};
let popup = browser.ownerDocument.getElementById(
browser.getAttribute("context")
);
// Note: `popup` must be in `document`, but `browser` might be in a
// different document, such as about:3pane.
let popup = document.getElementById(browser.getAttribute("context"));
let context = nsContextMenu.contentData.context;
// We don't have access to the original event here, as that happened in
@ -108,7 +106,7 @@ function openContextMenu({ data }, browser, actor) {
false,
false,
false,
0,
2,
null,
0,
context.mozInputSource
@ -116,7 +114,35 @@ function openContextMenu({ data }, browser, actor) {
popup.openPopupAtScreen(newEvent.screenX, newEvent.screenY, true, newEvent);
}
/** Called by a popupshowing event via fillMailContextMenu x3. */
/**
* Function to set the global nsContextMenu. Called by popupshowing on browserContext.
*
* @param {Event} event - The onpopupshowing event.
* @returns {boolean}
*/
function browserContextOnShowing(event) {
if (event.target.id != "browserContext") {
return true;
}
gContextMenu = new nsContextMenu(event.target, event.shiftKey);
return gContextMenu.shouldDisplay;
}
/**
* Function to clear out the global nsContextMenu.
*
* @param {Event} event - The onpopuphiding event.
*/
function browserContextOnHiding(event) {
if (event.target.id != "browserContext") {
return;
}
gContextMenu.hiding();
gContextMenu = null;
}
class nsContextMenu {
constructor(aXulMenu, aIsShift) {
this.xulMenu = aXulMenu;
@ -178,7 +204,7 @@ class nsContextMenu {
// If all items in the menu are hidden, set this.shouldDisplay to false
// so that the callers know to not even display the empty menu.
let contextPopup = document.getElementById("mailContext");
let contextPopup = document.getElementById("browserContext");
for (let item of contextPopup.children) {
if (!item.hidden) {
return;
@ -300,8 +326,8 @@ class nsContextMenu {
this.actor.manager
);
let canSpell = gSpellChecker.canSpellCheck && this.canSpellCheck;
this.showItem("mailContext-spell-check-enabled", canSpell);
this.showItem("mailContext-spell-separator", canSpell);
this.showItem("browserContext-spell-check-enabled", canSpell);
this.showItem("browserContext-spell-separator", canSpell);
}
}
@ -335,62 +361,68 @@ class nsContextMenu {
let showDictionaries = canSpell && gSpellChecker.enabled;
let onMisspelling = gSpellChecker.overMisspelling;
let showUndo = canSpell && gSpellChecker.canUndo();
this.showItem("mailContext-spell-check-enabled", canSpell);
this.showItem("mailContext-spell-separator", canSpell);
this.showItem("browserContext-spell-check-enabled", canSpell);
this.showItem("browserContext-spell-separator", canSpell);
document
.getElementById("mailContext-spell-check-enabled")
.getElementById("browserContext-spell-check-enabled")
.setAttribute("checked", canSpell && gSpellChecker.enabled);
this.showItem("mailContext-spell-add-to-dictionary", onMisspelling);
this.showItem("mailContext-spell-undo-add-to-dictionary", showUndo);
this.showItem("browserContext-spell-add-to-dictionary", onMisspelling);
this.showItem("browserContext-spell-undo-add-to-dictionary", showUndo);
// suggestion list
this.showItem(
"mailContext-spell-suggestions-separator",
"browserContext-spell-suggestions-separator",
onMisspelling || showUndo
);
if (onMisspelling) {
let addMenuItem = document.getElementById(
"mailContext-spell-add-to-dictionary"
"browserContext-spell-add-to-dictionary"
);
let suggestionCount = gSpellChecker.addSuggestionsToMenu(
addMenuItem.parentNode,
addMenuItem,
this.spellSuggestions
);
this.showItem("mailContext-spell-no-suggestions", suggestionCount == 0);
this.showItem(
"browserContext-spell-no-suggestions",
suggestionCount == 0
);
} else {
this.showItem("mailContext-spell-no-suggestions", false);
this.showItem("browserContext-spell-no-suggestions", false);
}
// dictionary list
this.showItem("mailContext-spell-dictionaries", showDictionaries);
this.showItem("browserContext-spell-dictionaries", showDictionaries);
if (canSpell) {
let dictMenu = document.getElementById(
"mailContext-spell-dictionaries-menu"
"browserContext-spell-dictionaries-menu"
);
let dictSep = document.getElementById(
"mailContext-spell-language-separator"
"browserContext-spell-language-separator"
);
let count = gSpellChecker.addDictionaryListToMenu(dictMenu, dictSep);
this.showItem(dictSep, count > 0);
this.showItem("mailContext-spell-add-dictionaries-main", false);
this.showItem("browserContext-spell-add-dictionaries-main", false);
} else if (this.onSpellcheckable) {
// when there is no spellchecker but we might be able to spellcheck
// add the add to dictionaries item. This will ensure that people
// with no dictionaries will be able to download them
this.showItem("mailContext-spell-language-separator", showDictionaries);
this.showItem(
"mailContext-spell-add-dictionaries-main",
"browserContext-spell-language-separator",
showDictionaries
);
this.showItem(
"browserContext-spell-add-dictionaries-main",
showDictionaries
);
} else {
this.showItem("mailContext-spell-add-dictionaries-main", false);
this.showItem("browserContext-spell-add-dictionaries-main", false);
}
}
initSaveItems() {
this.showItem("mailContext-savelink", this.onSaveableLink);
this.showItem("mailContext-saveimage", this.onLoadedImage);
this.showItem("browserContext-savelink", this.onSaveableLink);
this.showItem("browserContext-saveimage", this.onLoadedImage);
}
initClipboardItems() {
// Copy depends on whether there is selected text.
@ -399,33 +431,31 @@ class nsContextMenu {
goUpdateGlobalEditMenuItems();
this.showItem("mailContext-cut", this.onTextInput);
this.showItem("browserContext-cut", this.onTextInput);
this.showItem(
"mailContext-copy",
"browserContext-copy",
!this.onPlayableMedia && (this.isContentSelected || this.onTextInput)
);
this.showItem("mailContext-paste", this.onTextInput);
this.showItem("browserContext-paste", this.onTextInput);
this.showItem("mailContext-undo", this.onTextInput);
this.showItem("browserContext-undo", this.onTextInput);
// Select all not available in the thread pane or on playable media.
this.showItem("mailContext-selectall", !this.onPlayableMedia);
this.showItem("mailContext-copyemail", this.onMailtoLink);
this.showItem("mailContext-copylink", this.onLink && !this.onMailtoLink);
this.showItem("mailContext-copyimage", this.onImage);
this.showItem("browserContext-selectall", !this.onPlayableMedia);
this.showItem("browserContext-copyemail", this.onMailtoLink);
this.showItem("browserContext-copylink", this.onLink && !this.onMailtoLink);
this.showItem("browserContext-copyimage", this.onImage);
this.showItem("mailContext-composeemailto", this.onMailtoLink);
this.showItem("mailContext-addemail", this.onMailtoLink);
this.showItem("browserContext-composeemailto", this.onMailtoLink);
this.showItem("browserContext-addemail", this.onMailtoLink);
let searchTheWeb = document.getElementById("mailContext-searchTheWeb");
let searchTheWeb = document.getElementById("browserContext-searchTheWeb");
this.showItem(
searchTheWeb,
!this.onPlayableMedia && this.isContentSelected
);
if (!searchTheWeb.hidden) {
let selection = document.commandDispatcher.focusedWindow
.getSelection()
.toString();
let selection = this.textSelected;
let bundle = document.getElementById("bundle_messenger");
let key = "openSearch.label";
@ -447,18 +477,18 @@ class nsContextMenu {
initMediaPlayerItems() {
let onMedia = this.onVideo || this.onAudio;
// Several mutually exclusive items.... play/pause, mute/unmute, show/hide
this.showItem("mailContext-media-play", onMedia && this.target.paused);
this.showItem("mailContext-media-pause", onMedia && !this.target.paused);
this.showItem("mailContext-media-mute", onMedia && !this.target.muted);
this.showItem("mailContext-media-unmute", onMedia && this.target.muted);
this.showItem("browserContext-media-play", onMedia && this.target.paused);
this.showItem("browserContext-media-pause", onMedia && !this.target.paused);
this.showItem("browserContext-media-mute", onMedia && !this.target.muted);
this.showItem("browserContext-media-unmute", onMedia && this.target.muted);
if (onMedia) {
let hasError =
this.target.error != null ||
this.target.networkState == this.target.NETWORK_NO_SOURCE;
this.setItemAttr("mailContext-media-play", "disabled", hasError);
this.setItemAttr("mailContext-media-pause", "disabled", hasError);
this.setItemAttr("mailContext-media-mute", "disabled", hasError);
this.setItemAttr("mailContext-media-unmute", "disabled", hasError);
this.setItemAttr("browserContext-media-play", "disabled", hasError);
this.setItemAttr("browserContext-media-pause", "disabled", hasError);
this.setItemAttr("browserContext-media-mute", "disabled", hasError);
this.setItemAttr("browserContext-media-unmute", "disabled", hasError);
}
}
initBrowserItems() {
@ -480,8 +510,8 @@ class nsContextMenu {
}
// These only needs showing if we're not on something special.
this.showItem("mailContext-stop", notOnSpecialItem);
this.showItem("mailContext-reload", notOnSpecialItem);
this.showItem("browserContext-stop", notOnSpecialItem);
this.showItem("browserContext-reload", notOnSpecialItem);
let loadedProtocol = "";
if (this.target && this.target.ownerGlobal?.top.location) {
@ -493,14 +523,14 @@ class nsContextMenu {
// unlikely to show the same thing as we do (if at all), so therefore don't
// offer the option.
this.showItem(
"mailContext-openInBrowser",
"browserContext-openInBrowser",
notOnSpecialItem && ["http:", "https:"].includes(loadedProtocol)
);
// Only show mailContext-openLinkInBrowser if we're on a link and it isn't
// Only show browserContext-openLinkInBrowser if we're on a link and it isn't
// a mailto link.
this.showItem(
"mailContext-openLinkInBrowser",
"browserContext-openLinkInBrowser",
this.onLink && ["http", "https"].includes(this.linkProtocol)
);
}

Просмотреть файл

@ -0,0 +1,19 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at http://mozilla.org/MPL/2.0/.
<menupopup id="toolbar-context-menu"
onpopupshowing="calendarOnToolbarsPopupShowing(event); ToolbarContextMenu.updateExtension(this);">
<menuseparator id="customizeMailToolbarMenuSeparator"/>
<menuitem id="CustomizeMailToolbar"
command="cmd_CustomizeMailToolbar"
label="&customizeToolbar.label;"
accesskey="&customizeToolbar.accesskey;"/>
<menuseparator id="extensionsMailToolbarMenuSeparator"/>
<menuitem oncommand="ToolbarContextMenu.openAboutAddonsForContextAction(this.parentElement)"
data-l10n-id="toolbar-context-menu-manage-extension"
class="customize-context-manageExtension"/>
<menuitem oncommand="ToolbarContextMenu.removeExtensionForContextAction(this.parentElement)"
data-l10n-id="toolbar-context-menu-remove-extension"
class="customize-context-removeExtension"/>
</menupopup>

Просмотреть файл

@ -47,7 +47,6 @@ messenger.jar:
content/messenger/mail3PaneWindowCommands.js (content/mail3PaneWindowCommands.js)
content/messenger/mailCommands.js (content/mailCommands.js)
content/messenger/mailContext.js (content/mailContext.js)
content/messenger/mailContextMenus.js (content/mailContextMenus.js)
content/messenger/mailCore.js (content/mailCore.js)
content/messenger/mailTabs.js (content/mailTabs.js)
content/messenger/mailWindow.js (content/mailWindow.js)
@ -70,7 +69,6 @@ messenger.jar:
content/messenger/multimessageview.xhtml (content/multimessageview.xhtml)
content/messenger/newTagDialog.js (content/newTagDialog.js)
* content/messenger/newTagDialog.xhtml (content/newTagDialog.xhtml)
content/messenger/nsContextMenu.js (content/nsContextMenu.js)
content/messenger/printUtils.js (content/printUtils.js)
content/messenger/protovis-r2.6-modded.js (content/protovis-r2.6-modded.js)
content/messenger/quickFilterBar.js (content/quickFilterBar.js)
@ -94,6 +92,7 @@ messenger.jar:
content/messenger/viewSource.js (content/viewSource.js)
* content/messenger/viewSource.xhtml (content/viewSource.xhtml)
content/messenger/viewZoomOverlay.js (content/viewZoomOverlay.js)
content/messenger/browserPopups.js (content/widgets/browserPopups.js)
content/messenger/customizable-toolbar.js (content/widgets/customizable-toolbar.js)
content/messenger/foldersummary.js (content/widgets/foldersummary.js)
content/messenger/gloda-autocomplete-input.js (content/widgets/gloda-autocomplete-input.js)

Просмотреть файл

@ -12,13 +12,15 @@ subsuite = thunderbird
support-files = files/**
[browser_3paneTelemetry.js]
[browser_browserContext.js]
tags = contextmenu webextensions
[browser_browserRequestWindow.js]
[browser_formPickers.js]
tags = webextensions
[browser_interactionTelemetry.js]
[browser_linkHandler.js]
[browser_mailContext.js]
tags = contextmenu webextensions
tags = contextmenu
[browser_mailTabs.js]
[browser_menulist.js]
skip-if = os == 'mac'

Просмотреть файл

@ -0,0 +1,362 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at http://mozilla.org/MPL/2.0/. */
/* eslint-env webextensions */
var { MailServices } = ChromeUtils.import(
"resource:///modules/MailServices.jsm"
);
var { MessageGenerator } = ChromeUtils.import(
"resource://testing-common/mailnews/MessageGenerator.jsm"
);
const TEST_DOCUMENT_URL =
"http://mochi.test:8888/browser/comm/mail/base/test/browser/files/sampleContent.html";
const TEST_MESSAGE_URL =
"http://mochi.test:8888/browser/comm/mail/base/test/browser/files/sampleContent.eml";
const TEST_IMAGE_URL =
"http://mochi.test:8888/browser/comm/mail/base/test/browser/files/tb-logo.png";
let about3Pane, testFolder;
async function getImageArrayBuffer() {
let response = await fetch(TEST_IMAGE_URL);
let blob = await response.blob();
return new Promise((resolve, reject) => {
let reader = new FileReader();
reader.addEventListener("loadend", event => {
resolve(event.target.result);
});
reader.readAsArrayBuffer(blob);
});
}
function checkMenuitems(menu, ...expectedItems) {
if (expectedItems.length == 0) {
// Menu should not be shown.
Assert.equal(menu.state, "closed");
return;
}
Assert.notEqual(menu.state, "closed");
let actualItems = [];
for (let item of menu.children) {
if (["menu", "menuitem"].includes(item.localName) && !item.hidden) {
actualItems.push(item.id);
}
}
Assert.deepEqual(actualItems, expectedItems);
}
async function checkABrowser(browser, doc = browser.ownerDocument) {
if (
browser.webProgress?.isLoadingDocument ||
browser.currentURI?.spec == "about:blank"
) {
await BrowserTestUtils.browserLoaded(browser);
}
let browserContext = doc.getElementById("browserContext");
// Just some text.
let shownPromise = BrowserTestUtils.waitForEvent(
browserContext,
"popupshown"
);
await BrowserTestUtils.synthesizeMouseAtCenter(
"p",
{ type: "contextmenu" },
browser
);
await shownPromise;
checkMenuitems(
browserContext,
"browserContext-reload",
"browserContext-stop",
"browserContext-selectall"
);
browserContext.hidePopup();
// A link.
shownPromise = BrowserTestUtils.waitForEvent(browserContext, "popupshown");
await BrowserTestUtils.synthesizeMouseAtCenter(
"a",
{ type: "contextmenu" },
browser
);
await shownPromise;
checkMenuitems(
browserContext,
"browserContext-openLinkInBrowser",
"browserContext-selectall",
"browserContext-copylink",
"browserContext-savelink"
);
browserContext.hidePopup();
// A text input widget.
await BrowserTestUtils.synthesizeMouseAtCenter("input", {}, browser);
shownPromise = BrowserTestUtils.waitForEvent(browserContext, "popupshown");
await BrowserTestUtils.synthesizeMouseAtCenter(
"input",
{ type: "contextmenu" },
browser
);
await shownPromise;
checkMenuitems(
browserContext,
"browserContext-undo",
"browserContext-cut",
"browserContext-copy",
"browserContext-paste",
"browserContext-selectall",
"browserContext-spell-check-enabled"
);
browserContext.hidePopup();
// An image. Also checks Save Image As works.
shownPromise = BrowserTestUtils.waitForEvent(browserContext, "popupshown");
await BrowserTestUtils.synthesizeMouseAtCenter(
"img",
{ type: "contextmenu" },
browser
);
await shownPromise;
checkMenuitems(
browserContext,
"browserContext-selectall",
"browserContext-copyimage",
"browserContext-saveimage"
);
let pickerPromise = new Promise(resolve => {
SpecialPowers.MockFilePicker.init(window);
SpecialPowers.MockFilePicker.showCallback = picker => {
resolve(picker.defaultString);
return Ci.nsIFilePicker.returnCancel;
};
});
browserContext.activateItem(doc.getElementById("browserContext-saveimage"));
Assert.equal(await pickerPromise, "tb-logo.png");
SpecialPowers.MockFilePicker.cleanup();
}
add_setup(async function() {
MailServices.accounts.createLocalMailAccount();
let account = MailServices.accounts.accounts[0];
account.addIdentity(MailServices.accounts.createIdentity());
let rootFolder = account.incomingServer.rootFolder;
rootFolder.createSubfolder("browserContextFolder", null);
testFolder = rootFolder
.getChildNamed("browserContextFolder")
.QueryInterface(Ci.nsIMsgLocalMailFolder);
let message = await fetch(TEST_MESSAGE_URL).then(r => r.text());
testFolder.addMessageBatch([message]);
let messages = new MessageGenerator().makeMessages({ count: 5 });
let messageStrings = messages.map(message => message.toMboxString());
testFolder.addMessageBatch(messageStrings);
about3Pane = document.getElementById("tabmail").currentAbout3Pane;
about3Pane.restoreState({
folderURI: testFolder.URI,
messagePaneVisible: true,
});
registerCleanupFunction(() => {
MailServices.accounts.removeAccount(account, true);
});
});
add_task(async function testMessagePane() {
about3Pane.displayWebPage(TEST_DOCUMENT_URL);
await checkABrowser(about3Pane.webBrowser, document);
});
add_task(async function testContentTab() {
let tab = window.openContentTab(TEST_DOCUMENT_URL);
await checkABrowser(tab.browser);
let tabmail = document.getElementById("tabmail");
tabmail.closeTab(tab);
});
add_task(async function testExtensionTab() {
let extension = ExtensionTestUtils.loadExtension({
background: async () => {
await browser.tabs.create({ url: "sampleContent.html" });
browser.test.notifyPass("ready");
},
files: {
"sampleContent.html": await fetch(TEST_DOCUMENT_URL).then(response =>
response.text()
),
"tb-logo.png": await getImageArrayBuffer(),
},
});
await extension.startup();
await extension.awaitFinish("ready");
let tabmail = document.getElementById("tabmail");
await checkABrowser(tabmail.tabInfo[1].browser);
tabmail.closeOtherTabs(tabmail.tabInfo[0]);
await extension.unload();
});
add_task(async function testExtensionPopupWindow() {
let extension = ExtensionTestUtils.loadExtension({
background: async () => {
await browser.windows.create({
url: "sampleContent.html",
type: "popup",
width: 800,
height: 500,
});
browser.test.notifyPass("ready");
},
files: {
"sampleContent.html": await fetch(TEST_DOCUMENT_URL).then(response =>
response.text()
),
"tb-logo.png": await getImageArrayBuffer(),
},
});
await extension.startup();
await extension.awaitFinish("ready");
let extensionPopup = Services.wm.getMostRecentWindow("mail:extensionPopup");
// extensionPopup.xhtml needs time to initialise properly.
await new Promise(resolve => extensionPopup.setTimeout(resolve, 500));
await checkABrowser(extensionPopup.document.getElementById("requestFrame"));
await BrowserTestUtils.closeWindow(extensionPopup);
await extension.unload();
});
add_task(async function testExtensionBrowserAction() {
let extension = ExtensionTestUtils.loadExtension({
files: {
"sampleContent.html": await fetch(TEST_DOCUMENT_URL).then(response =>
response.text()
),
"tb-logo.png": await getImageArrayBuffer(),
},
manifest: {
applications: {
gecko: {
id: "browsercontext@mochi.test",
},
},
browser_action: {
default_popup: "sampleContent.html",
},
},
});
await extension.startup();
let { panel, browser } = await openExtensionPopup(
window,
"browsercontext_mochi_test-browserAction-toolbarbutton"
);
await TestUtils.waitForCondition(
() => browser.clientWidth > 100,
"waiting for browser to resize"
);
await checkABrowser(browser);
panel.hidePopup();
await extension.unload();
}).skip(); // TODO: No toolbar, no browser action.
add_task(async function testExtensionComposeAction() {
let extension = ExtensionTestUtils.loadExtension({
files: {
"sampleContent.html": await fetch(TEST_DOCUMENT_URL).then(response =>
response.text()
),
"tb-logo.png": await getImageArrayBuffer(),
},
manifest: {
applications: {
gecko: {
id: "browsercontext@mochi.test",
},
},
compose_action: {
default_popup: "sampleContent.html",
},
},
});
await extension.startup();
let params = Cc[
"@mozilla.org/messengercompose/composeparams;1"
].createInstance(Ci.nsIMsgComposeParams);
params.composeFields = Cc[
"@mozilla.org/messengercompose/composefields;1"
].createInstance(Ci.nsIMsgCompFields);
let composeWindowPromise = BrowserTestUtils.domWindowOpened();
MailServices.compose.OpenComposeWindowWithParams(null, params);
let composeWindow = await composeWindowPromise;
await BrowserTestUtils.waitForEvent(composeWindow, "load");
let { panel, browser } = await openExtensionPopup(
composeWindow,
"browsercontext_mochi_test-composeAction-toolbarbutton"
);
await checkABrowser(browser);
panel.hidePopup();
await extension.unload();
await BrowserTestUtils.closeWindow(composeWindow);
});
add_task(async function testExtensionMessageDisplayAction() {
let extension = ExtensionTestUtils.loadExtension({
files: {
"sampleContent.html": await fetch(TEST_DOCUMENT_URL).then(response =>
response.text()
),
"tb-logo.png": await getImageArrayBuffer(),
},
manifest: {
applications: {
gecko: {
id: "browsercontext@mochi.test",
},
},
message_display_action: {
default_popup: "sampleContent.html",
},
},
});
await extension.startup();
let messageWindowPromise = BrowserTestUtils.domWindowOpened();
window.MsgOpenNewWindowForMessage([...testFolder.messages][0]);
let messageWindow = await messageWindowPromise;
await BrowserTestUtils.waitForEvent(messageWindow, "load");
let { panel, browser } = await openExtensionPopup(
messageWindow,
"browsercontext_mochi_test-messageDisplayAction-toolbarbutton"
);
await checkABrowser(browser);
panel.hidePopup();
await extension.unload();
await BrowserTestUtils.closeWindow(messageWindow);
}).skip(); // TODO: Toolbar broken.

Просмотреть файл

@ -4,9 +4,6 @@
/* eslint-env webextensions */
var { MailE10SUtils } = ChromeUtils.import(
"resource:///modules/MailE10SUtils.jsm"
);
var { MailServices } = ChromeUtils.import(
"resource:///modules/MailServices.jsm"
);
@ -14,27 +11,10 @@ var { MessageGenerator } = ChromeUtils.import(
"resource://testing-common/mailnews/MessageGenerator.jsm"
);
const TEST_DOCUMENT_URL =
"http://mochi.test:8888/browser/comm/mail/base/test/browser/files/sampleContent.html";
const TEST_MESSAGE_URL =
"http://mochi.test:8888/browser/comm/mail/base/test/browser/files/sampleContent.eml";
const TEST_IMAGE_URL =
"http://mochi.test:8888/browser/comm/mail/base/test/browser/files/tb-logo.png";
let testFolder;
async function getImageArrayBuffer() {
let response = await fetch(TEST_IMAGE_URL);
let blob = await response.blob();
return new Promise((resolve, reject) => {
let reader = new FileReader();
reader.addEventListener("loadend", event => {
resolve(event.target.result);
});
reader.readAsArrayBuffer(blob);
});
}
let about3Pane, mailContext, testFolder, threadTree;
function checkMenuitems(menu, ...expectedItems) {
if (expectedItems.length == 0) {
@ -54,110 +34,14 @@ function checkMenuitems(menu, ...expectedItems) {
Assert.deepEqual(actualItems, expectedItems);
}
async function checkABrowser(browser) {
if (
browser.webProgress?.isLoadingDocument ||
browser.currentURI?.spec == "about:blank"
) {
await BrowserTestUtils.browserLoaded(browser);
}
let mailContext = browser.ownerDocument.getElementById("mailContext");
// Just some text.
let shownPromise = BrowserTestUtils.waitForEvent(mailContext, "popupshown");
await BrowserTestUtils.synthesizeMouseAtCenter(
"p",
{ type: "contextmenu" },
browser
);
await shownPromise;
checkMenuitems(
mailContext,
"mailContext-reload",
"mailContext-stop",
"mailContext-selectall"
);
mailContext.hidePopup();
// A link.
shownPromise = BrowserTestUtils.waitForEvent(mailContext, "popupshown");
await BrowserTestUtils.synthesizeMouseAtCenter(
"a",
{ type: "contextmenu" },
browser
);
await shownPromise;
checkMenuitems(
mailContext,
"mailContext-openLinkInBrowser",
"mailContext-selectall",
"mailContext-copylink",
"mailContext-savelink"
);
mailContext.hidePopup();
// A text input widget.
await BrowserTestUtils.synthesizeMouseAtCenter("input", {}, browser);
shownPromise = BrowserTestUtils.waitForEvent(mailContext, "popupshown");
await BrowserTestUtils.synthesizeMouseAtCenter(
"input",
{ type: "contextmenu" },
browser
);
await shownPromise;
checkMenuitems(
mailContext,
"mailContext-undo",
"mailContext-cut",
"mailContext-copy",
"mailContext-paste",
"mailContext-selectall",
"mailContext-spell-check-enabled"
);
mailContext.hidePopup();
// An image. Also checks Save Image As works.
shownPromise = BrowserTestUtils.waitForEvent(mailContext, "popupshown");
await BrowserTestUtils.synthesizeMouseAtCenter(
"img",
{ type: "contextmenu" },
browser
);
await shownPromise;
checkMenuitems(
mailContext,
"mailContext-selectall",
"mailContext-copyimage",
"mailContext-saveimage"
);
let pickerPromise = new Promise(resolve => {
SpecialPowers.MockFilePicker.init(window);
SpecialPowers.MockFilePicker.showCallback = picker => {
resolve(picker.defaultString);
return Ci.nsIFilePicker.returnCancel;
};
});
mailContext.activateItem(
browser.ownerDocument.getElementById("mailContext-saveimage")
);
Assert.equal(await pickerPromise, "tb-logo.png");
SpecialPowers.MockFilePicker.cleanup();
}
add_setup(async function() {
MailServices.accounts.createLocalMailAccount();
let account = MailServices.accounts.accounts[0];
account.addIdentity(MailServices.accounts.createIdentity());
let rootFolder = account.incomingServer.rootFolder;
rootFolder.createSubfolder("mailContextFolder", null);
rootFolder.createSubfolder("browserContextFolder", null);
testFolder = rootFolder
.getChildNamed("mailContextFolder")
.getChildNamed("browserContextFolder")
.QueryInterface(Ci.nsIMsgLocalMailFolder);
let message = await fetch(TEST_MESSAGE_URL).then(r => r.text());
testFolder.addMessageBatch([message]);
@ -165,57 +49,76 @@ add_setup(async function() {
let messageStrings = messages.map(message => message.toMboxString());
testFolder.addMessageBatch(messageStrings);
about3Pane = document.getElementById("tabmail").currentAbout3Pane;
about3Pane.restoreState({
folderURI: testFolder.URI,
messagePaneVisible: true,
});
mailContext = about3Pane.document.getElementById("mailContext");
threadTree = about3Pane.threadTree;
registerCleanupFunction(() => {
MailServices.accounts.removeAccount(account, true);
});
});
add_task(async function testMessagePane() {
window.gFolderTreeView.selectFolder(testFolder);
if (window.IsMessagePaneCollapsed()) {
window.MsgToggleMessagePane();
}
/**
* Tests the mailContext menu on the thread tree and message pane when no
* messages are selected.
*/
add_task(async function testNoMessages() {
about3Pane.displayMessages();
// No messages are selected.
// The message pane browser isn't visible.
let mailContext = document.getElementById("mailContext");
let messagePane = document.getElementById("messagepane");
Assert.equal(messagePane.currentURI.spec, "about:blank");
EventUtils.synthesizeMouseAtCenter(messagePane, { type: "contextmenu" });
checkMenuitems(mailContext);
// A web page is shown in the message pane.
MailE10SUtils.loadURI(messagePane, TEST_DOCUMENT_URL);
await checkABrowser(messagePane);
let tree = window.gFolderDisplay.tree;
let coords = tree.getCoordsForCellItem(6, tree.columns.subjectCol, "cell");
let treeChildren = tree.lastElementChild;
EventUtils.synthesizeMouse(
treeChildren,
coords.x + coords.width / 2,
coords.y + coords.height / 2,
{
type: "contextmenu",
}
Assert.ok(BrowserTestUtils.is_hidden(about3Pane.messageBrowser));
Assert.equal(about3Pane.messageBrowser.currentURI.spec, "about:message");
Assert.equal(
about3Pane.messageBrowser.contentWindow.content.currentURI.spec,
"about:blank"
);
EventUtils.synthesizeMouseAtCenter(
about3Pane.document.getElementById("messageBrowserPane"),
{ type: "contextmenu" }
);
checkMenuitems(mailContext);
// One message is selected (the message is not encrypted)
// Open the menu from an empty part of the thread pane.
window.gFolderDisplay.selectViewIndex(0);
await BrowserTestUtils.browserLoaded(messagePane);
let treeRect = threadTree.getBoundingClientRect();
EventUtils.synthesizeMouse(
threadTree,
treeRect.x + treeRect.width / 2,
treeRect.bottom - 10,
{
type: "contextmenu",
},
about3Pane
);
checkMenuitems(mailContext);
});
/**
* Tests the mailContext menu on the thread tree and message pane when one
* message is selected.
*/
add_task(async function testSingleMessage() {
let loadedPromise = BrowserTestUtils.browserLoaded(about3Pane.messageBrowser);
about3Pane.threadTree.selectedIndex = 0;
await loadedPromise;
// Open the menu from the message pane.
Assert.ok(BrowserTestUtils.is_visible(about3Pane.messageBrowser));
let shownPromise = BrowserTestUtils.waitForEvent(mailContext, "popupshown");
await BrowserTestUtils.synthesizeMouseAtCenter(
":root",
{ type: "contextmenu" },
messagePane
about3Pane.messageBrowser
);
await shownPromise;
let messageItems = [
"mailContext-selectall",
"mailContext-openContainingFolder",
"mailContext-replySender",
"mailContext-replyAll",
"mailContext-replyList",
@ -229,7 +132,7 @@ add_task(async function testMessagePane() {
"mailContext-moveMenu",
"mailContext-copyMenu",
"mailContext-moveToFolderAgain",
"mailContext-calendar-convert-menu",
// "mailContext-calendar-convert-menu",
"mailContext-delete",
"mailContext-ignoreThread",
"mailContext-ignoreSubthread",
@ -240,20 +143,23 @@ add_task(async function testMessagePane() {
checkMenuitems(mailContext, ...messageItems);
mailContext.hidePopup();
// Open the menu from the thread pane.
shownPromise = BrowserTestUtils.waitForEvent(mailContext, "popupshown");
let treeRect = threadTree.getBoundingClientRect();
EventUtils.synthesizeMouse(
treeChildren,
coords.x + coords.width / 2,
coords.y + coords.height / 2,
threadTree,
treeRect.x + treeRect.width / 2,
treeRect.y + 10,
{
type: "contextmenu",
}
},
about3Pane
);
await shownPromise;
let treeItems = [
"threadPaneContext-openNewTab",
"mailContext-openNewTab",
"mailContext-openNewWindow",
"mailContext-openContainingFolder",
"mailContext-replySender",
"mailContext-replyAll",
"mailContext-replyList",
@ -267,7 +173,7 @@ add_task(async function testMessagePane() {
"mailContext-moveMenu",
"mailContext-copyMenu",
"mailContext-moveToFolderAgain",
"mailContext-calendar-convert-menu",
// "mailContext-calendar-convert-menu",
"mailContext-delete",
"mailContext-ignoreThread",
"mailContext-ignoreSubthread",
@ -277,18 +183,36 @@ add_task(async function testMessagePane() {
];
checkMenuitems(mailContext, ...treeItems);
mailContext.hidePopup();
});
// Multiple messages are selected.
/**
* Tests the mailContext menu on the thread tree and message pane when more
* than one message is selected.
*/
add_task(async function testMultipleMessages() {
threadTree.selectedIndices = [1, 2, 3];
tree.view.selection.rangedSelect(1, 3, false);
// The message pane browser isn't visible.
Assert.ok(BrowserTestUtils.is_hidden(about3Pane.messageBrowser));
Assert.ok(BrowserTestUtils.is_visible(about3Pane.multiMessageBrowser));
EventUtils.synthesizeMouseAtCenter(
about3Pane.document.getElementById("messageBrowserPane"),
{ type: "contextmenu" }
);
checkMenuitems(mailContext);
// Open the menu from the thread pane.
let treeRect = threadTree.getBoundingClientRect();
EventUtils.synthesizeMouse(
treeChildren,
coords.x + coords.width / 2,
coords.y + coords.height / 2,
threadTree,
treeRect.x + treeRect.width / 2,
treeRect.y + 30,
{
type: "contextmenu",
}
},
about3Pane
);
checkMenuitems(
mailContext,
@ -299,198 +223,14 @@ add_task(async function testMessagePane() {
"mailContext-moveMenu",
"mailContext-copyMenu",
"mailContext-moveToFolderAgain",
"mailContext-decryptToFolder",
// "mailContext-decryptToFolder",
"mailContext-delete",
"mailContext-ignoreThread",
"mailContext-ignoreSubthread",
"mailContext-watchThread",
"mailContext-saveAs",
"mailContext-print",
"downloadSelected"
"mailContext-downloadSelected"
);
mailContext.hidePopup();
window.gFolderDisplay.selectMessages([]);
}).skip(); // TODO: Too much broken.
add_task(async function testContentTab() {
let tab = window.openContentTab(TEST_DOCUMENT_URL);
await checkABrowser(tab.browser);
let tabmail = document.getElementById("tabmail");
tabmail.closeTab(tab);
});
add_task(async function testExtensionTab() {
let extension = ExtensionTestUtils.loadExtension({
background: async () => {
await browser.tabs.create({ url: "sampleContent.html" });
browser.test.notifyPass("ready");
},
files: {
"sampleContent.html": await fetch(TEST_DOCUMENT_URL).then(response =>
response.text()
),
"tb-logo.png": await getImageArrayBuffer(),
},
});
await extension.startup();
await extension.awaitFinish("ready");
let tabmail = document.getElementById("tabmail");
await checkABrowser(tabmail.tabInfo[1].browser);
tabmail.closeOtherTabs(tabmail.tabInfo[0]);
await extension.unload();
});
add_task(async function testExtensionPopupWindow() {
let extension = ExtensionTestUtils.loadExtension({
background: async () => {
await browser.windows.create({
url: "sampleContent.html",
type: "popup",
width: 800,
height: 500,
});
browser.test.notifyPass("ready");
},
files: {
"sampleContent.html": await fetch(TEST_DOCUMENT_URL).then(response =>
response.text()
),
"tb-logo.png": await getImageArrayBuffer(),
},
});
await extension.startup();
await extension.awaitFinish("ready");
let extensionPopup = Services.wm.getMostRecentWindow("mail:extensionPopup");
// extensionPopup.xhtml needs time to initialise properly.
await new Promise(resolve => extensionPopup.setTimeout(resolve, 500));
await checkABrowser(extensionPopup.document.getElementById("requestFrame"));
await BrowserTestUtils.closeWindow(extensionPopup);
await extension.unload();
});
add_task(async function testExtensionBrowserAction() {
let extension = ExtensionTestUtils.loadExtension({
files: {
"sampleContent.html": await fetch(TEST_DOCUMENT_URL).then(response =>
response.text()
),
"tb-logo.png": await getImageArrayBuffer(),
},
manifest: {
applications: {
gecko: {
id: "mailcontext@mochi.test",
},
},
browser_action: {
default_popup: "sampleContent.html",
},
},
});
await extension.startup();
let { panel, browser } = await openExtensionPopup(
window,
"mailcontext_mochi_test-browserAction-toolbarbutton"
);
await TestUtils.waitForCondition(
() => browser.clientWidth > 100,
"waiting for browser to resize"
);
await checkABrowser(browser);
panel.hidePopup();
await extension.unload();
}).skip(); // TODO: No toolbar, no browser action.
add_task(async function testExtensionComposeAction() {
let extension = ExtensionTestUtils.loadExtension({
files: {
"sampleContent.html": await fetch(TEST_DOCUMENT_URL).then(response =>
response.text()
),
"tb-logo.png": await getImageArrayBuffer(),
},
manifest: {
applications: {
gecko: {
id: "mailcontext@mochi.test",
},
},
compose_action: {
default_popup: "sampleContent.html",
},
},
});
await extension.startup();
let params = Cc[
"@mozilla.org/messengercompose/composeparams;1"
].createInstance(Ci.nsIMsgComposeParams);
params.composeFields = Cc[
"@mozilla.org/messengercompose/composefields;1"
].createInstance(Ci.nsIMsgCompFields);
let composeWindowPromise = BrowserTestUtils.domWindowOpened();
MailServices.compose.OpenComposeWindowWithParams(null, params);
let composeWindow = await composeWindowPromise;
await BrowserTestUtils.waitForEvent(composeWindow, "load");
let { panel, browser } = await openExtensionPopup(
composeWindow,
"mailcontext_mochi_test-composeAction-toolbarbutton"
);
await checkABrowser(browser);
panel.hidePopup();
await extension.unload();
await BrowserTestUtils.closeWindow(composeWindow);
});
add_task(async function testExtensionMessageDisplayAction() {
let extension = ExtensionTestUtils.loadExtension({
files: {
"sampleContent.html": await fetch(TEST_DOCUMENT_URL).then(response =>
response.text()
),
"tb-logo.png": await getImageArrayBuffer(),
},
manifest: {
applications: {
gecko: {
id: "mailcontext@mochi.test",
},
},
message_display_action: {
default_popup: "sampleContent.html",
},
},
});
await extension.startup();
let messageWindowPromise = BrowserTestUtils.domWindowOpened();
window.MsgOpenNewWindowForMessage([...testFolder.messages][0]);
let messageWindow = await messageWindowPromise;
await BrowserTestUtils.waitForEvent(messageWindow, "load");
let { panel, browser } = await openExtensionPopup(
messageWindow,
"mailcontext_mochi_test-messageDisplayAction-toolbarbutton"
);
await checkABrowser(browser);
panel.hidePopup();
await extension.unload();
await BrowserTestUtils.closeWindow(messageWindow);
}).skip(); // TODO: Toolbar broken.

Просмотреть файл

@ -80,7 +80,6 @@
<vbox id="searchResults" persist="height">
<vbox id="searchResultListBox" flex="1" >
<tree id="abResultsTree" flex="1" enableColumnDrag="true" class="plain"
context="mailContext"
onclick="AbResultsPaneOnClick(event);"
onkeypress="AbResultsPaneKeyPress(event);"
onselect="this.view.selectionChanged();"

Просмотреть файл

@ -8,10 +8,10 @@
/* import-globals-from ../../../base/content/contentAreaClick.js */
/* import-globals-from ../../../base/content/mailCore.js */
/* import-globals-from ../../../base/content/messenger-customization.js */
/* import-globals-from ../../../base/content/nsContextMenu.js */
/* import-globals-from ../../../base/content/toolbarIconColor.js */
/* import-globals-from ../../../base/content/utilityOverlay.js */
/* import-globals-from ../../../base/content/viewZoomOverlay.js */
/* import-globals-from ../../../base/content/widgets/browserPopups.js */
/* import-globals-from ../../../extensions/openpgp/content/ui/keyAssistant.js */
/* import-globals-from addressingWidgetOverlay.js */
/* import-globals-from cloudAttachmentLinkManager.js */
@ -1869,7 +1869,11 @@ function showMessageComposeSecurityStatus(isSending = false) {
}
}
function openEditorContextMenu(popup) {
function msgComposeContextOnShowing(event) {
if (event.target.id != "msgComposeContext") {
return;
}
// gSpellChecker handles all spell checking related to the context menu,
// except whether or not spell checking is enabled. We need the editor's
// spell checker for that.
@ -1980,7 +1984,7 @@ function openEditorContextMenu(popup) {
}
let subject = {
menu: popup,
menu: event.target,
tab: window,
isContentSelected,
isTextSelected,
@ -2001,7 +2005,11 @@ function openEditorContextMenu(popup) {
Services.obs.notifyObservers(subject, "on-build-contextmenu");
}
function closeEditorContextMenu() {
function msgComposeContextOnHiding(event) {
if (event.target.id != "msgComposeContext") {
return;
}
if (nsContextMenu.contentData.actor) {
nsContextMenu.contentData.actor.hiding();
}
@ -11118,16 +11126,6 @@ function loadBlockedImage(aURL, aReturnDataURL = false) {
return null;
}
function mailContextOnContextMenu(event) {
document.getElementById("mailContext").target =
event.composedTarget || event.target;
}
function fillMailContextMenu(event) {
gContextMenu = new nsContextMenu(event.target, event.shiftKey);
return gContextMenu.shouldDisplay;
}
function mailContextOnPopupHiding() {}
function showSendEncryptedAndSigned() {
let encToggle = document.getElementById("button-encryption");
if (encToggle) {

Просмотреть файл

@ -75,7 +75,7 @@
<script defer="defer" src="chrome://messenger/content/messengercompose/cloudAttachmentLinkManager.js"></script>
<script defer="defer" src="chrome://messenger/content/messenger-customization.js"></script>
<script defer="defer" src="chrome://messenger/content/customizable-toolbar.js"></script>
<script defer="defer" src="chrome://messenger/content/nsContextMenu.js"></script>
<script defer="defer" src="chrome://messenger/content/browserPopups.js"></script>
<script defer="defer" src="chrome://messenger/content/addressbook/abDragDrop.js"></script>
<script defer="defer" src="chrome://messenger/content/messengercompose/addressingWidgetOverlay.js"></script>
<script defer="defer" src="chrome://global/content/contentAreaUtils.js"></script>
@ -527,8 +527,7 @@
</keyset>
<popupset id="mainPopupSet">
#define BROWSER_POPUPS_ONLY
#include ../../../base/content/mainPopupSet.inc.xhtml
#include ../../../base/content/widgets/browserPopups.inc.xhtml
</popupset>
<!-- Reorder Attachments Panel -->
@ -620,8 +619,8 @@
</menupopup>
<menupopup id="msgComposeContext"
onpopupshowing="if (event.target != this) { return true; } openEditorContextMenu(this);"
onpopuphiding="if (event.target != this) { return true; } closeEditorContextMenu();">
onpopupshowing="msgComposeContextOnShowing(event);"
onpopuphiding="msgComposeContextOnHiding(event);">
<!-- Spellchecking menu items -->
<menuitem id="spellCheckNoSuggestions"

Просмотреть файл

@ -259,7 +259,7 @@ class BasePopup {
browser.setAttribute("class", "webextension-popup-browser");
browser.setAttribute("webextension-view-type", "popup");
browser.setAttribute("tooltip", "aHTMLTooltip");
browser.setAttribute("context", "mailContext");
browser.setAttribute("context", "browserContext");
browser.setAttribute("autocompletepopup", "PopupAutoComplete");
browser.setAttribute("selectmenulist", "ContentSelectDropdown");
browser.setAttribute("selectmenuconstrained", "false");

Просмотреть файл

@ -21,7 +21,7 @@ ChromeUtils.defineESModuleGetters(this, {
var gContextMenu;
/* globals nsContextMenu, reporterListener */
/* globals reporterListener */
function loadRequestedUrl() {
let browser = document.getElementById("requestFrame");
@ -107,11 +107,6 @@ this.__defineGetter__("browser", getBrowser);
function getBrowser() {
return gBrowser.selectedBrowser;
}
function fillMailContextMenu(event) {
gContextMenu = new nsContextMenu(event.target, event.shiftKey);
return gContextMenu.shouldDisplay;
}
function mailContextOnPopupHiding() {}
var gBrowserInit = {
onDOMContentLoaded() {

Просмотреть файл

@ -35,14 +35,13 @@
<script defer="defer" src="chrome://global/content/globalOverlay.js"></script>
<script defer="defer" src="chrome://messenger/content/viewZoomOverlay.js"></script>
<script defer="defer" src="chrome://messenger/content/browserRequest.js"></script>
<script defer="defer" src="chrome://messenger/content/nsContextMenu.js"></script>
<script defer="defer" src="chrome://messenger/content/browserPopups.js"></script>
<script defer="defer" src="chrome://messenger/content/extensionPopup.js"></script>
</head>
<html:body xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<popupset>
#define BROWSER_POPUPS_ONLY
#include ../../base/content/mainPopupSet.inc.xhtml
#include ../../base/content/widgets/browserPopups.inc.xhtml
</popupset>
<commandset>
@ -71,7 +70,7 @@
src="about:blank"
flex="1"
autocompletepopup="PopupAutoComplete"
context="mailContext"
context="browserContext"
datetimepicker="DateTimePickerPanel"
selectmenulist="ContentSelectDropdown"
messagemanagergroup="browsers"/>

Просмотреть файл

@ -4,7 +4,7 @@
// This file is loaded in messenger.xhtml.
/* globals gatherTextUnder, goUpdateGlobalEditMenuItems, makeURLAbsolute, Services */
/* import-globals-from ../../../base/content/nsContextMenu.js */
/* import-globals-from ../../../base/content/widgets/browserPopups.js */
var gChatContextMenu = null;

Просмотреть файл

@ -77,11 +77,11 @@ add_task(async function test_spellcheck_in_content_tabs() {
{ type: "contextmenu" },
mc.tabmail.selectedTab.browser
);
let mailContext = mc.e("mailContext");
await wait_for_popup_to_open(mailContext);
assert_element_visible("mailContext-spell-dictionaries");
assert_element_visible("mailContext-spell-check-enabled");
await close_popup(mc, mailContext);
let browserContext = mc.e("browserContext");
await wait_for_popup_to_open(browserContext);
assert_element_visible("browserContext-spell-dictionaries");
assert_element_visible("browserContext-spell-check-enabled");
await close_popup(mc, browserContext);
// Different test
BrowserTestUtils.synthesizeMouseAtCenter(
@ -89,11 +89,10 @@ add_task(async function test_spellcheck_in_content_tabs() {
{ type: "contextmenu" },
mc.tabmail.selectedTab.browser
);
mailContext = mc.e("mailContext");
await wait_for_popup_to_open(mailContext);
assert_element_not_visible("mailContext-spell-dictionaries");
assert_element_not_visible("mailContext-spell-check-enabled");
await close_popup(mc, mailContext);
await wait_for_popup_to_open(browserContext);
assert_element_not_visible("browserContext-spell-dictionaries");
assert_element_not_visible("browserContext-spell-check-enabled");
await close_popup(mc, browserContext);
// Right-click on "zombocom" and add to dictionary
BrowserTestUtils.synthesizeMouse(
@ -103,14 +102,13 @@ add_task(async function test_spellcheck_in_content_tabs() {
{ type: "contextmenu", button: 2 },
mc.tabmail.selectedTab.browser
);
mailContext = mc.e("mailContext");
await wait_for_popup_to_open(mailContext);
await wait_for_popup_to_open(browserContext);
let suggestions = mc.window.document.getElementsByClassName(
"spell-suggestion"
);
Assert.ok(suggestions.length > 0, "What, is zombocom a registered word now?");
mc.click(mc.e("mailContext-spell-add-to-dictionary"));
await close_popup(mc, mailContext);
mc.click(mc.e("browserContext-spell-add-to-dictionary"));
await close_popup(mc, browserContext);
// Now check we don't have any suggestionss
BrowserTestUtils.synthesizeMouse(
@ -120,11 +118,10 @@ add_task(async function test_spellcheck_in_content_tabs() {
{ type: "contextmenu", button: 2 },
mc.tabmail.selectedTab.browser
);
mailContext = mc.e("mailContext");
await wait_for_popup_to_open(mailContext);
await wait_for_popup_to_open(browserContext);
suggestions = mc.window.document.getElementsByClassName("spell-suggestion");
Assert.ok(suggestions.length == 0, "But I just taught you this word!");
await close_popup(mc, mailContext);
await close_popup(mc, browserContext);
});
add_task(function test_content_tab_default_favicon() {