mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-01 17:23:59 +00:00
Bug 1634042, Part 2: lazify page action panel r=Gijs
Differential Revision: https://phabricator.services.mozilla.com/D91187
This commit is contained in:
parent
d9711aa658
commit
7fb79b4804
@ -14,6 +14,7 @@ ChromeUtils.defineModuleGetter(
|
||||
);
|
||||
|
||||
var BrowserPageActions = {
|
||||
_panelNode: null,
|
||||
/**
|
||||
* The main page action button in the urlbar (DOM node)
|
||||
*/
|
||||
@ -26,8 +27,12 @@ var BrowserPageActions = {
|
||||
* The main page action panel DOM node (DOM node)
|
||||
*/
|
||||
get panelNode() {
|
||||
// Lazy load the page action panel the first time we need to display it
|
||||
if (!this._panelNode) {
|
||||
this.initializePanel();
|
||||
}
|
||||
delete this.panelNode;
|
||||
return (this.panelNode = document.getElementById("pageActionPanel"));
|
||||
return (this.panelNode = this._panelNode);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -64,16 +69,12 @@ var BrowserPageActions = {
|
||||
* Inits. Call to init.
|
||||
*/
|
||||
init() {
|
||||
this.placeAllActions();
|
||||
this.placeAllActionsInUrlbar();
|
||||
this._onPanelShowing = this._onPanelShowing.bind(this);
|
||||
this.panelNode.addEventListener("popupshowing", this._onPanelShowing);
|
||||
this.panelNode.addEventListener("popuphiding", () => {
|
||||
this.mainButtonNode.removeAttribute("open");
|
||||
});
|
||||
},
|
||||
|
||||
_onPanelShowing() {
|
||||
this.placeLazyActionsInPanel();
|
||||
this.initializePanel();
|
||||
for (let action of PageActions.actionsInPanel(window)) {
|
||||
let buttonNode = this.panelButtonNodeForActionID(action.id);
|
||||
action.onShowingInPanel(buttonNode);
|
||||
@ -93,19 +94,36 @@ var BrowserPageActions = {
|
||||
_actionsToLazilyPlaceInPanel: [],
|
||||
|
||||
/**
|
||||
* Places all registered actions.
|
||||
* Places all registered actions in the urlbar.
|
||||
*/
|
||||
placeAllActions() {
|
||||
let panelActions = PageActions.actionsInPanel(window);
|
||||
for (let action of panelActions) {
|
||||
this.placeActionInPanel(action);
|
||||
}
|
||||
placeAllActionsInUrlbar() {
|
||||
let urlbarActions = PageActions.actionsInUrlbar(window);
|
||||
for (let action of urlbarActions) {
|
||||
this.placeActionInUrlbar(action);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Initializes the panel if necessary.
|
||||
*/
|
||||
initializePanel() {
|
||||
// Lazy load the page action panel the first time we need to display it
|
||||
if (!this._panelNode) {
|
||||
let template = document.getElementById("pageActionPanelTemplate");
|
||||
template.replaceWith(template.content);
|
||||
this._panelNode = document.getElementById("pageActionPanel");
|
||||
this._panelNode.addEventListener("popupshowing", this._onPanelShowing);
|
||||
this._panelNode.addEventListener("popuphiding", () => {
|
||||
this.mainButtonNode.removeAttribute("open");
|
||||
});
|
||||
}
|
||||
|
||||
for (let action of PageActions.actionsInPanel(window)) {
|
||||
this.placeActionInPanel(action);
|
||||
}
|
||||
this.placeLazyActionsInPanel();
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds or removes as necessary DOM nodes for the given action.
|
||||
*
|
||||
@ -124,7 +142,7 @@ var BrowserPageActions = {
|
||||
* The action to place.
|
||||
*/
|
||||
placeActionInPanel(action) {
|
||||
if (this.panelNode.state != "closed") {
|
||||
if (this._panelNode && this.panelNode.state != "closed") {
|
||||
this._placeActionInPanelNow(action);
|
||||
} else {
|
||||
// Lazily place the action in the panel the next time it opens.
|
||||
|
@ -551,25 +551,27 @@
|
||||
<hbox id="ctrlTab-showAll-container" pack="center"/>
|
||||
</panel>
|
||||
|
||||
<panel id="pageActionPanel"
|
||||
class="cui-widget-panel panel-no-padding"
|
||||
role="group"
|
||||
type="arrow"
|
||||
hidden="true"
|
||||
flip="slide"
|
||||
position="bottomcenter topright"
|
||||
tabspecific="true"
|
||||
noautofocus="true">
|
||||
<panelmultiview id="pageActionPanelMultiView"
|
||||
mainViewId="pageActionPanelMainView"
|
||||
viewCacheId="appMenu-viewCache">
|
||||
<panelview id="pageActionPanelMainView"
|
||||
context="pageActionContextMenu"
|
||||
class="PanelUI-subView">
|
||||
<vbox class="panel-subview-body"/>
|
||||
</panelview>
|
||||
</panelmultiview>
|
||||
</panel>
|
||||
<html:template id="pageActionPanelTemplate">
|
||||
<panel id="pageActionPanel"
|
||||
class="cui-widget-panel panel-no-padding"
|
||||
role="group"
|
||||
type="arrow"
|
||||
hidden="true"
|
||||
flip="slide"
|
||||
position="bottomcenter topright"
|
||||
tabspecific="true"
|
||||
noautofocus="true">
|
||||
<panelmultiview id="pageActionPanelMultiView"
|
||||
mainViewId="pageActionPanelMainView"
|
||||
viewCacheId="appMenu-viewCache">
|
||||
<panelview id="pageActionPanelMainView"
|
||||
context="pageActionContextMenu"
|
||||
class="PanelUI-subView">
|
||||
<vbox class="panel-subview-body"/>
|
||||
</panelview>
|
||||
</panelmultiview>
|
||||
</panel>
|
||||
</html:template>
|
||||
|
||||
<html:template id="confirmation-hint-wrapper">
|
||||
<panel id="confirmation-hint"
|
||||
|
@ -115,9 +115,9 @@ add_task(async function testPageActionsButtonPress() {
|
||||
await BrowserTestUtils.withNewTab("https://example.com", async function() {
|
||||
let button = document.getElementById("pageActionButton");
|
||||
forceFocus(button);
|
||||
EventUtils.synthesizeKey(" ");
|
||||
let view = document.getElementById("pageActionPanelMainView");
|
||||
let focused = BrowserTestUtils.waitForEvent(view, "focus", true);
|
||||
EventUtils.synthesizeKey(" ");
|
||||
await focused;
|
||||
ok(true, "Focus inside Page Actions menu after toolbar button pressed");
|
||||
let hidden = BrowserTestUtils.waitForEvent(document, "popuphidden", true);
|
||||
|
@ -34,6 +34,45 @@ async function openAndCheckMenu(menu, target) {
|
||||
menu.hidePopup();
|
||||
}
|
||||
|
||||
async function openAndCheckLazyMenu(id, target) {
|
||||
let menu = document.getElementById(id);
|
||||
|
||||
EventUtils.synthesizeNativeTapAtCenter(target);
|
||||
let ev = await BrowserTestUtils.waitForEvent(
|
||||
window,
|
||||
"popupshown",
|
||||
true,
|
||||
e => e.target.id == id
|
||||
);
|
||||
menu = ev.target;
|
||||
|
||||
is(menu.state, "open", `Menu panel (${menu.id}) is open.`);
|
||||
is(
|
||||
menu.getAttribute("touchmode"),
|
||||
"true",
|
||||
`Menu panel (${menu.id}) is in touchmode.`
|
||||
);
|
||||
|
||||
menu.hidePopup();
|
||||
|
||||
EventUtils.synthesizeNativeTapAtCenter(target);
|
||||
ev = await BrowserTestUtils.waitForEvent(
|
||||
window,
|
||||
"popupshown",
|
||||
true,
|
||||
e => e.target.id == id
|
||||
);
|
||||
menu = ev.target;
|
||||
|
||||
is(menu.state, "open", `Menu panel (${menu.id}) is open.`);
|
||||
ok(
|
||||
!menu.hasAttribute("touchmode"),
|
||||
`Menu panel (${menu.id}) is not in touchmode.`
|
||||
);
|
||||
|
||||
menu.hidePopup();
|
||||
}
|
||||
|
||||
// The customization UI menu is not attached to the document when it is
|
||||
// closed and hence requires special attention.
|
||||
async function openAndCheckCustomizationUIMenu(target) {
|
||||
@ -96,9 +135,8 @@ add_task(async function test_main_menu_touch() {
|
||||
add_task(async function test_page_action_panel_touch() {
|
||||
// The page action menu only appears on a web page.
|
||||
await BrowserTestUtils.withNewTab("https://example.com", async function() {
|
||||
let pageActionPanel = document.getElementById("pageActionPanel");
|
||||
let target = document.getElementById("pageActionButton");
|
||||
await openAndCheckMenu(pageActionPanel, target);
|
||||
await openAndCheckLazyMenu("pageActionPanel", target);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -55,10 +55,10 @@ async function openSSB(uri) {
|
||||
async function openSSBFromBrowserWindow(win = window) {
|
||||
let doc = win.document;
|
||||
let pageActionButton = doc.getElementById("pageActionButton");
|
||||
EventUtils.synthesizeMouseAtCenter(pageActionButton, {}, win);
|
||||
let panel = doc.getElementById("pageActionPanel");
|
||||
let popupShown = BrowserTestUtils.waitForEvent(panel, "popupshown");
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(pageActionButton, {}, win);
|
||||
await popupShown;
|
||||
|
||||
let openItem = doc.getElementById("pageAction-panel-launchSSB");
|
||||
|
@ -372,6 +372,12 @@ var UITour = {
|
||||
}
|
||||
|
||||
case "showHighlight": {
|
||||
if (data.target.startsWith("pageAction-")) {
|
||||
// The page action panel is lazily loaded, so we will need to initialize it
|
||||
// and place actions in the panel before showing the highlight for a panel
|
||||
// node.
|
||||
window.BrowserPageActions.initializePanel();
|
||||
}
|
||||
let targetPromise = this.getTarget(window, data.target);
|
||||
targetPromise
|
||||
.then(target => {
|
||||
|
@ -76,11 +76,11 @@ var PageActions = {
|
||||
|
||||
// Now place them all in each window. Instead of splitting the register and
|
||||
// place steps, we could simply call addAction, which does both, but doing
|
||||
// it this way means that all windows initially place their actions the same
|
||||
// way -- placeAllActions -- regardless of whether they're open when this
|
||||
// method is called or opened later.
|
||||
// it this way means that all windows initially place their actions in the
|
||||
// urlbar the same way -- placeAllActions -- regardless of whether they're
|
||||
// open when this method is called or opened later.
|
||||
for (let bpa of allBrowserPageActions()) {
|
||||
bpa.placeAllActions();
|
||||
bpa.placeAllActionsInUrlbar();
|
||||
}
|
||||
|
||||
// These callbacks are deferred until init happens and all built-in actions
|
||||
|
@ -19,6 +19,7 @@ skip-if = (debug && os == "linux" && bits == 64 && os_version == "18.04") # Bug
|
||||
[browser_EveryWindow.js]
|
||||
[browser_LiveBookmarkMigrator.js]
|
||||
[browser_PageActions.js]
|
||||
[browser_PageActions_contextMenus.js]
|
||||
[browser_PartnerLinkAttribution.js]
|
||||
support-files =
|
||||
search-engines/basic/manifest.json
|
||||
|
@ -1270,6 +1270,10 @@ add_task(async function perWindowState() {
|
||||
Assert.equal(action.getTitle(window), newGlobalTitle, "Title: old window");
|
||||
Assert.equal(action.getTitle(newWindow), newGlobalTitle, "Title: new window");
|
||||
|
||||
// Initialize panel nodes in the new window
|
||||
newWindow.document.getElementById("pageActionButton").click();
|
||||
await BrowserTestUtils.waitForEvent(newWindow.document, "popupshowing", true);
|
||||
|
||||
// The action's panel button nodes should be updated in both windows.
|
||||
let panelButtonID = BrowserPageActions.panelButtonNodeIDForActionID(
|
||||
action.id
|
||||
@ -1509,356 +1513,6 @@ add_task(async function removeRetainState() {
|
||||
testAction.remove();
|
||||
});
|
||||
|
||||
// Opens the context menu on a non-built-in action. (The context menu for
|
||||
// built-in actions is tested in browser_page_action_menu.js.)
|
||||
add_task(async function contextMenu() {
|
||||
Services.telemetry.clearEvents();
|
||||
|
||||
// Add a test action.
|
||||
let action = PageActions.addAction(
|
||||
new PageActions.Action({
|
||||
id: "test-contextMenu",
|
||||
title: "Test contextMenu",
|
||||
pinnedToUrlbar: true,
|
||||
})
|
||||
);
|
||||
|
||||
// Open the panel and then open the context menu on the action's item.
|
||||
await promiseOpenPageActionPanel();
|
||||
let panelButton = BrowserPageActions.panelButtonNodeForActionID(action.id);
|
||||
let contextMenuPromise = promisePanelShown("pageActionContextMenu");
|
||||
EventUtils.synthesizeMouseAtCenter(panelButton, {
|
||||
type: "contextmenu",
|
||||
button: 2,
|
||||
});
|
||||
await contextMenuPromise;
|
||||
|
||||
// The context menu should show the "remove" item and the "manage" item. The
|
||||
// 4th item is "remove extension" but it is hidden in this test case because
|
||||
// the page action isn't bound to an addon. Click the "remove" item.
|
||||
let menuItems = collectContextMenuItems();
|
||||
Assert.equal(menuItems.length, 4, "Context menu has 4 children");
|
||||
Assert.equal(
|
||||
menuItems[0].label,
|
||||
"Remove from Address Bar",
|
||||
"Context menu is in the 'remove' state"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[1].localName,
|
||||
"menuseparator",
|
||||
"menuseparator is present"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[2].label,
|
||||
"Manage Extension\u2026",
|
||||
"'Manage' item is present"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[3].label,
|
||||
"Remove Extension",
|
||||
"'Remove' item is present"
|
||||
);
|
||||
Assert.ok(menuItems[3].hidden, "'Remove' item is hidden");
|
||||
|
||||
contextMenuPromise = promisePanelHidden("pageActionContextMenu");
|
||||
EventUtils.synthesizeMouseAtCenter(menuItems[0], {});
|
||||
await contextMenuPromise;
|
||||
|
||||
// The action should be removed from the urlbar.
|
||||
await BrowserTestUtils.waitForCondition(() => {
|
||||
return !BrowserPageActions.urlbarButtonNodeForActionID(action.id);
|
||||
}, "Waiting for urlbar button to be removed");
|
||||
|
||||
// Open the context menu again on the action's button in the panel. (The
|
||||
// panel should still be open.)
|
||||
contextMenuPromise = promisePanelShown("pageActionContextMenu");
|
||||
EventUtils.synthesizeMouseAtCenter(panelButton, {
|
||||
type: "contextmenu",
|
||||
button: 2,
|
||||
});
|
||||
await contextMenuPromise;
|
||||
|
||||
// The context menu should show the "add" item and the "manage" item. The 4th
|
||||
// item is "remove extension" but it is hidden. Click the "add" item.
|
||||
menuItems = collectContextMenuItems();
|
||||
Assert.equal(menuItems.length, 4, "Context menu has 4 children");
|
||||
Assert.equal(
|
||||
menuItems[0].label,
|
||||
"Add to Address Bar",
|
||||
"Context menu is in the 'add' state"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[1].localName,
|
||||
"menuseparator",
|
||||
"menuseparator is present"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[2].label,
|
||||
"Manage Extension\u2026",
|
||||
"'Manage' item is present"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[3].label,
|
||||
"Remove Extension",
|
||||
"'Remove' item is present"
|
||||
);
|
||||
Assert.ok(menuItems[3].hidden, "'Remove' item is hidden");
|
||||
|
||||
contextMenuPromise = promisePanelHidden("pageActionContextMenu");
|
||||
EventUtils.synthesizeMouseAtCenter(menuItems[0], {});
|
||||
await contextMenuPromise;
|
||||
|
||||
// The action should be added back to the urlbar.
|
||||
await BrowserTestUtils.waitForCondition(() => {
|
||||
return BrowserPageActions.urlbarButtonNodeForActionID(action.id);
|
||||
}, "Waiting for urlbar button to be added back");
|
||||
|
||||
// Open the context menu again on the action's button in the panel. (The
|
||||
// panel should still be open.)
|
||||
contextMenuPromise = promisePanelShown("pageActionContextMenu");
|
||||
EventUtils.synthesizeMouseAtCenter(panelButton, {
|
||||
type: "contextmenu",
|
||||
button: 2,
|
||||
});
|
||||
await contextMenuPromise;
|
||||
|
||||
// The context menu should show the "remove" item and the "manage" item. The
|
||||
// 4th item is "remove extension" but it is hidden. Click the "manage" item.
|
||||
// about:addons should open.
|
||||
menuItems = collectContextMenuItems();
|
||||
Assert.equal(menuItems.length, 4, "Context menu has 4 children");
|
||||
Assert.equal(
|
||||
menuItems[0].label,
|
||||
"Remove from Address Bar",
|
||||
"Context menu is in the 'remove' state"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[1].localName,
|
||||
"menuseparator",
|
||||
"menuseparator is present"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[2].label,
|
||||
"Manage Extension\u2026",
|
||||
"'Manage' item is present"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[3].label,
|
||||
"Remove Extension",
|
||||
"'Remove' item is present"
|
||||
);
|
||||
Assert.ok(menuItems[3].hidden, "'Remove' item is hidden");
|
||||
|
||||
// Click the "manage" item, about:addons should open.
|
||||
contextMenuPromise = promisePanelHidden("pageActionContextMenu");
|
||||
let aboutAddonsPromise = BrowserTestUtils.waitForNewTab(
|
||||
gBrowser,
|
||||
"about:addons"
|
||||
);
|
||||
EventUtils.synthesizeMouseAtCenter(menuItems[2], {});
|
||||
let values = await Promise.all([aboutAddonsPromise, contextMenuPromise]);
|
||||
let aboutAddonsTab = values[0];
|
||||
BrowserTestUtils.removeTab(aboutAddonsTab);
|
||||
|
||||
// Open the context menu on the action's urlbar button.
|
||||
let urlbarButton = BrowserPageActions.urlbarButtonNodeForActionID(action.id);
|
||||
contextMenuPromise = promisePanelShown("pageActionContextMenu");
|
||||
EventUtils.synthesizeMouseAtCenter(urlbarButton, {
|
||||
type: "contextmenu",
|
||||
button: 2,
|
||||
});
|
||||
await contextMenuPromise;
|
||||
|
||||
// The context menu should show the "remove" item and the "manage" item. The
|
||||
// 4th item is "remove extension" but it is hidden. Click the "manage" item.
|
||||
// about:addons should open.
|
||||
menuItems = collectContextMenuItems();
|
||||
Assert.equal(menuItems.length, 4, "Context menu has 4 children");
|
||||
Assert.equal(
|
||||
menuItems[0].label,
|
||||
"Remove from Address Bar",
|
||||
"Context menu is in the 'remove' state"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[1].localName,
|
||||
"menuseparator",
|
||||
"menuseparator is present"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[2].label,
|
||||
"Manage Extension\u2026",
|
||||
"'Manage' item is present"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[3].label,
|
||||
"Remove Extension",
|
||||
"'Remove' item is present"
|
||||
);
|
||||
Assert.ok(menuItems[3].hidden, "'Remove' item is hidden");
|
||||
|
||||
contextMenuPromise = promisePanelHidden("pageActionContextMenu");
|
||||
EventUtils.synthesizeMouseAtCenter(menuItems[0], {});
|
||||
await contextMenuPromise;
|
||||
|
||||
// The action should be removed from the urlbar.
|
||||
await BrowserTestUtils.waitForCondition(() => {
|
||||
return !BrowserPageActions.urlbarButtonNodeForActionID(action.id);
|
||||
}, "Waiting for urlbar button to be removed");
|
||||
|
||||
// Open the panel and then open the context menu on the action's item.
|
||||
await promiseOpenPageActionPanel();
|
||||
contextMenuPromise = promisePanelShown("pageActionContextMenu");
|
||||
EventUtils.synthesizeMouseAtCenter(panelButton, {
|
||||
type: "contextmenu",
|
||||
button: 2,
|
||||
});
|
||||
await contextMenuPromise;
|
||||
|
||||
// The context menu should show the "remove" item and the "manage" item. The
|
||||
// 4th item is "remove extension" but it is hidden. Click the "remove" item.
|
||||
menuItems = collectContextMenuItems();
|
||||
Assert.equal(menuItems.length, 4, "Context menu has 4 children");
|
||||
Assert.equal(
|
||||
menuItems[0].label,
|
||||
"Add to Address Bar",
|
||||
"Context menu is in the 'add' state"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[1].localName,
|
||||
"menuseparator",
|
||||
"menuseparator is present"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[2].label,
|
||||
"Manage Extension\u2026",
|
||||
"'Manage' item is present"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[3].label,
|
||||
"Remove Extension",
|
||||
"'Remove' item is present"
|
||||
);
|
||||
Assert.ok(menuItems[3].hidden, "'Remove' item is hidden");
|
||||
|
||||
contextMenuPromise = promisePanelHidden("pageActionContextMenu");
|
||||
EventUtils.synthesizeMouseAtCenter(menuItems[0], {});
|
||||
await contextMenuPromise;
|
||||
|
||||
// The action should be added back to the urlbar.
|
||||
await BrowserTestUtils.waitForCondition(() => {
|
||||
return BrowserPageActions.urlbarButtonNodeForActionID(action.id);
|
||||
}, "Waiting for urlbar button to be added back");
|
||||
|
||||
// Open the context menu on the action's urlbar button.
|
||||
urlbarButton = BrowserPageActions.urlbarButtonNodeForActionID(action.id);
|
||||
contextMenuPromise = promisePanelShown("pageActionContextMenu");
|
||||
EventUtils.synthesizeMouseAtCenter(urlbarButton, {
|
||||
type: "contextmenu",
|
||||
button: 2,
|
||||
});
|
||||
await contextMenuPromise;
|
||||
|
||||
// The context menu should show the "add" item and the "manage" item. The 4th
|
||||
// item is "remove extension" but it is hidden. Click the "add" item.
|
||||
menuItems = collectContextMenuItems();
|
||||
Assert.equal(menuItems.length, 4, "Context menu has 4 children");
|
||||
Assert.equal(
|
||||
menuItems[0].label,
|
||||
"Remove from Address Bar",
|
||||
"Context menu is in the 'remove' state"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[1].localName,
|
||||
"menuseparator",
|
||||
"menuseparator is present"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[2].label,
|
||||
"Manage Extension\u2026",
|
||||
"'Manage' item is present"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[3].label,
|
||||
"Remove Extension",
|
||||
"'Remove' item is present"
|
||||
);
|
||||
Assert.ok(menuItems[3].hidden, "'Remove' item is hidden");
|
||||
|
||||
// Click the "manage" item, about:addons should open.
|
||||
contextMenuPromise = promisePanelHidden("pageActionContextMenu");
|
||||
aboutAddonsPromise = BrowserTestUtils.waitForNewTab(gBrowser, "about:addons");
|
||||
EventUtils.synthesizeMouseAtCenter(menuItems[2], {});
|
||||
values = await Promise.all([aboutAddonsPromise, contextMenuPromise]);
|
||||
aboutAddonsTab = values[0];
|
||||
BrowserTestUtils.removeTab(aboutAddonsTab);
|
||||
|
||||
// Done, clean up.
|
||||
action.remove();
|
||||
|
||||
// Check the telemetry was collected properly.
|
||||
let snapshot = Services.telemetry.snapshotEvents(
|
||||
Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS,
|
||||
true
|
||||
);
|
||||
ok(
|
||||
snapshot.parent && !!snapshot.parent.length,
|
||||
"Got parent telemetry events in the snapshot"
|
||||
);
|
||||
let relatedEvents = snapshot.parent
|
||||
.filter(
|
||||
([timestamp, category, method]) =>
|
||||
category == "addonsManager" && method == "action"
|
||||
)
|
||||
.map(relatedEvent => relatedEvent.slice(3, 6));
|
||||
Assert.deepEqual(relatedEvents, [
|
||||
["pageAction", null, { action: "manage" }],
|
||||
["pageAction", null, { action: "manage" }],
|
||||
]);
|
||||
|
||||
// urlbar tests that run after this one can break if the mouse is left over
|
||||
// the area where the urlbar popup appears, which seems to happen due to the
|
||||
// above synthesized mouse events. Move it over the urlbar.
|
||||
EventUtils.synthesizeMouseAtCenter(gURLBar.inputField, { type: "mousemove" });
|
||||
gURLBar.focus();
|
||||
});
|
||||
|
||||
// The context menu shouldn't open on separators in the panel.
|
||||
add_task(async function contextMenuOnSeparator() {
|
||||
// Open the panel and get the bookmark separator.
|
||||
await promiseOpenPageActionPanel();
|
||||
let separator = BrowserPageActions.panelButtonNodeForActionID(
|
||||
PageActions.ACTION_ID_BOOKMARK_SEPARATOR
|
||||
);
|
||||
Assert.ok(separator, "The bookmark separator should be in the panel");
|
||||
|
||||
// Context-click it. popupshowing should be fired, but by the time the event
|
||||
// reaches this listener, preventDefault should have been called on it.
|
||||
let showingPromise = BrowserTestUtils.waitForEvent(
|
||||
document.getElementById("pageActionContextMenu"),
|
||||
"popupshowing",
|
||||
false
|
||||
);
|
||||
EventUtils.synthesizeMouseAtCenter(separator, {
|
||||
type: "contextmenu",
|
||||
button: 2,
|
||||
});
|
||||
let event = await showingPromise;
|
||||
Assert.ok(
|
||||
event.defaultPrevented,
|
||||
"defaultPrevented should be true on popupshowing event"
|
||||
);
|
||||
|
||||
// Click the main button to hide the main panel.
|
||||
EventUtils.synthesizeMouseAtCenter(BrowserPageActions.mainButtonNode, {});
|
||||
await promisePageActionPanelHidden();
|
||||
|
||||
// urlbar tests that run after this one can break if the mouse is left over
|
||||
// the area where the urlbar popup appears, which seems to happen due to the
|
||||
// above synthesized mouse events. Move it over the urlbar.
|
||||
EventUtils.synthesizeMouseAtCenter(gURLBar.inputField, { type: "mousemove" });
|
||||
gURLBar.focus();
|
||||
});
|
||||
|
||||
// Tests transient actions.
|
||||
add_task(async function transient() {
|
||||
let initialActionsInPanel = PageActions.actionsInPanel(window);
|
||||
@ -2144,117 +1798,3 @@ add_task(async function action_disablePrivateBrowsing() {
|
||||
|
||||
privateWindow.close();
|
||||
});
|
||||
|
||||
function assertActivatedPageActionPanelHidden() {
|
||||
Assert.ok(
|
||||
!document.getElementById(BrowserPageActions._activatedActionPanelID)
|
||||
);
|
||||
}
|
||||
|
||||
function promiseOpenPageActionPanel() {
|
||||
let dwu = window.windowUtils;
|
||||
return BrowserTestUtils.waitForCondition(() => {
|
||||
// Wait for the main page action button to become visible. It's hidden for
|
||||
// some URIs, so depending on when this is called, it may not yet be quite
|
||||
// visible. It's up to the caller to make sure it will be visible.
|
||||
info("Waiting for main page action button to have non-0 size");
|
||||
let bounds = dwu.getBoundsWithoutFlushing(
|
||||
BrowserPageActions.mainButtonNode
|
||||
);
|
||||
return bounds.width > 0 && bounds.height > 0;
|
||||
})
|
||||
.then(() => {
|
||||
// Wait for the panel to become open, by clicking the button if necessary.
|
||||
info("Waiting for main page action panel to be open");
|
||||
if (BrowserPageActions.panelNode.state == "open") {
|
||||
return Promise.resolve();
|
||||
}
|
||||
let shownPromise = promisePageActionPanelShown();
|
||||
EventUtils.synthesizeMouseAtCenter(BrowserPageActions.mainButtonNode, {});
|
||||
return shownPromise;
|
||||
})
|
||||
.then(() => {
|
||||
// Wait for items in the panel to become visible.
|
||||
return promisePageActionViewChildrenVisible(
|
||||
BrowserPageActions.mainViewNode
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function promisePageActionPanelShown() {
|
||||
return promisePanelShown(BrowserPageActions.panelNode);
|
||||
}
|
||||
|
||||
function promisePageActionPanelHidden() {
|
||||
return promisePanelHidden(BrowserPageActions.panelNode);
|
||||
}
|
||||
|
||||
function promisePanelShown(panelIDOrNode) {
|
||||
return promisePanelEvent(panelIDOrNode, "popupshown");
|
||||
}
|
||||
|
||||
function promisePanelHidden(panelIDOrNode) {
|
||||
return promisePanelEvent(panelIDOrNode, "popuphidden");
|
||||
}
|
||||
|
||||
function promisePanelEvent(panelIDOrNode, eventType) {
|
||||
return new Promise(resolve => {
|
||||
let panel = panelIDOrNode;
|
||||
if (typeof panel == "string") {
|
||||
panel = document.getElementById(panelIDOrNode);
|
||||
if (!panel) {
|
||||
throw new Error(`Panel with ID "${panelIDOrNode}" does not exist.`);
|
||||
}
|
||||
}
|
||||
if (
|
||||
(eventType == "popupshown" && panel.state == "open") ||
|
||||
(eventType == "popuphidden" && panel.state == "closed")
|
||||
) {
|
||||
executeSoon(resolve);
|
||||
return;
|
||||
}
|
||||
panel.addEventListener(
|
||||
eventType,
|
||||
() => {
|
||||
executeSoon(resolve);
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function promisePageActionViewShown() {
|
||||
info("promisePageActionViewShown waiting for ViewShown");
|
||||
return BrowserTestUtils.waitForEvent(
|
||||
BrowserPageActions.panelNode,
|
||||
"ViewShown"
|
||||
).then(async event => {
|
||||
let panelViewNode = event.originalTarget;
|
||||
await promisePageActionViewChildrenVisible(panelViewNode);
|
||||
return panelViewNode;
|
||||
});
|
||||
}
|
||||
|
||||
function promisePageActionViewChildrenVisible(panelViewNode) {
|
||||
info(
|
||||
"promisePageActionViewChildrenVisible waiting for a child node to be visible"
|
||||
);
|
||||
let dwu = window.windowUtils;
|
||||
return BrowserTestUtils.waitForCondition(() => {
|
||||
let bodyNode = panelViewNode.firstElementChild;
|
||||
for (let childNode of bodyNode.children) {
|
||||
let bounds = dwu.getBoundsWithoutFlushing(childNode);
|
||||
if (bounds.width > 0 && bounds.height > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
function collectContextMenuItems() {
|
||||
let contextMenu = document.getElementById("pageActionContextMenu");
|
||||
return Array.prototype.filter.call(contextMenu.children, node => {
|
||||
return window.getComputedStyle(node).visibility == "visible";
|
||||
});
|
||||
}
|
||||
|
380
browser/modules/test/browser/browser_PageActions_contextMenus.js
Normal file
380
browser/modules/test/browser/browser_PageActions_contextMenus.js
Normal file
@ -0,0 +1,380 @@
|
||||
"use strict";
|
||||
|
||||
// This is a test for PageActions.jsm, specifically the context menus.
|
||||
|
||||
// Initialization. Must run first.
|
||||
add_task(async function init() {
|
||||
// The page action urlbar button, and therefore the panel, is only shown when
|
||||
// the current tab is actionable -- i.e., a normal web page. about:blank is
|
||||
// not, so open a new tab first thing, and close it when this test is done.
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab({
|
||||
gBrowser,
|
||||
url: "http://example.com/",
|
||||
});
|
||||
|
||||
await disableNonReleaseActions();
|
||||
registerCleanupFunction(async () => {
|
||||
BrowserTestUtils.removeTab(tab);
|
||||
});
|
||||
|
||||
// Ensure screenshots is really disabled (bug 1498738)
|
||||
const addon = await AddonManager.getAddonByID("screenshots@mozilla.org");
|
||||
await addon.disable({ allowSystemAddons: true });
|
||||
});
|
||||
|
||||
// Opens the context menu on a non-built-in action. (The context menu for
|
||||
// built-in actions is tested in browser_page_action_menu.js.)
|
||||
add_task(async function contextMenu() {
|
||||
Services.telemetry.clearEvents();
|
||||
|
||||
// Add a test action.
|
||||
let action = PageActions.addAction(
|
||||
new PageActions.Action({
|
||||
id: "test-contextMenu",
|
||||
title: "Test contextMenu",
|
||||
pinnedToUrlbar: true,
|
||||
})
|
||||
);
|
||||
|
||||
// Open the panel and then open the context menu on the action's item.
|
||||
await promiseOpenPageActionPanel();
|
||||
let panelButton = BrowserPageActions.panelButtonNodeForActionID(action.id);
|
||||
let contextMenuPromise = promisePanelShown("pageActionContextMenu");
|
||||
EventUtils.synthesizeMouseAtCenter(panelButton, {
|
||||
type: "contextmenu",
|
||||
button: 2,
|
||||
});
|
||||
await contextMenuPromise;
|
||||
|
||||
// The context menu should show the "remove" item and the "manage" item. The
|
||||
// 4th item is "remove extension" but it is hidden in this test case because
|
||||
// the page action isn't bound to an addon. Click the "remove" item.
|
||||
let menuItems = collectContextMenuItems();
|
||||
Assert.equal(menuItems.length, 4, "Context menu has 4 children");
|
||||
Assert.equal(
|
||||
menuItems[0].label,
|
||||
"Remove from Address Bar",
|
||||
"Context menu is in the 'remove' state"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[1].localName,
|
||||
"menuseparator",
|
||||
"menuseparator is present"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[2].label,
|
||||
"Manage Extension\u2026",
|
||||
"'Manage' item is present"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[3].label,
|
||||
"Remove Extension",
|
||||
"'Remove' item is present"
|
||||
);
|
||||
Assert.ok(menuItems[3].hidden, "'Remove' item is hidden");
|
||||
|
||||
contextMenuPromise = promisePanelHidden("pageActionContextMenu");
|
||||
EventUtils.synthesizeMouseAtCenter(menuItems[0], {});
|
||||
await contextMenuPromise;
|
||||
|
||||
// The action should be removed from the urlbar.
|
||||
await BrowserTestUtils.waitForCondition(() => {
|
||||
return !BrowserPageActions.urlbarButtonNodeForActionID(action.id);
|
||||
}, "Waiting for urlbar button to be removed");
|
||||
|
||||
// Open the context menu again on the action's button in the panel. (The
|
||||
// panel should still be open.)
|
||||
contextMenuPromise = promisePanelShown("pageActionContextMenu");
|
||||
EventUtils.synthesizeMouseAtCenter(panelButton, {
|
||||
type: "contextmenu",
|
||||
button: 2,
|
||||
});
|
||||
await contextMenuPromise;
|
||||
|
||||
// The context menu should show the "add" item and the "manage" item. The 4th
|
||||
// item is "remove extension" but it is hidden. Click the "add" item.
|
||||
menuItems = collectContextMenuItems();
|
||||
Assert.equal(menuItems.length, 4, "Context menu has 4 children");
|
||||
Assert.equal(
|
||||
menuItems[0].label,
|
||||
"Add to Address Bar",
|
||||
"Context menu is in the 'add' state"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[1].localName,
|
||||
"menuseparator",
|
||||
"menuseparator is present"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[2].label,
|
||||
"Manage Extension\u2026",
|
||||
"'Manage' item is present"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[3].label,
|
||||
"Remove Extension",
|
||||
"'Remove' item is present"
|
||||
);
|
||||
Assert.ok(menuItems[3].hidden, "'Remove' item is hidden");
|
||||
|
||||
contextMenuPromise = promisePanelHidden("pageActionContextMenu");
|
||||
EventUtils.synthesizeMouseAtCenter(menuItems[0], {});
|
||||
await contextMenuPromise;
|
||||
|
||||
// The action should be added back to the urlbar.
|
||||
await BrowserTestUtils.waitForCondition(() => {
|
||||
return BrowserPageActions.urlbarButtonNodeForActionID(action.id);
|
||||
}, "Waiting for urlbar button to be added back");
|
||||
|
||||
// Open the context menu again on the action's button in the panel. (The
|
||||
// panel should still be open.)
|
||||
contextMenuPromise = promisePanelShown("pageActionContextMenu");
|
||||
EventUtils.synthesizeMouseAtCenter(panelButton, {
|
||||
type: "contextmenu",
|
||||
button: 2,
|
||||
});
|
||||
await contextMenuPromise;
|
||||
|
||||
// The context menu should show the "remove" item and the "manage" item. The
|
||||
// 4th item is "remove extension" but it is hidden. Click the "manage" item.
|
||||
// about:addons should open.
|
||||
menuItems = collectContextMenuItems();
|
||||
Assert.equal(menuItems.length, 4, "Context menu has 4 children");
|
||||
Assert.equal(
|
||||
menuItems[0].label,
|
||||
"Remove from Address Bar",
|
||||
"Context menu is in the 'remove' state"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[1].localName,
|
||||
"menuseparator",
|
||||
"menuseparator is present"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[2].label,
|
||||
"Manage Extension\u2026",
|
||||
"'Manage' item is present"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[3].label,
|
||||
"Remove Extension",
|
||||
"'Remove' item is present"
|
||||
);
|
||||
Assert.ok(menuItems[3].hidden, "'Remove' item is hidden");
|
||||
|
||||
// Click the "manage" item, about:addons should open.
|
||||
contextMenuPromise = promisePanelHidden("pageActionContextMenu");
|
||||
let aboutAddonsPromise = BrowserTestUtils.waitForNewTab(
|
||||
gBrowser,
|
||||
"about:addons"
|
||||
);
|
||||
EventUtils.synthesizeMouseAtCenter(menuItems[2], {});
|
||||
let values = await Promise.all([aboutAddonsPromise, contextMenuPromise]);
|
||||
let aboutAddonsTab = values[0];
|
||||
BrowserTestUtils.removeTab(aboutAddonsTab);
|
||||
|
||||
// Open the context menu on the action's urlbar button.
|
||||
let urlbarButton = BrowserPageActions.urlbarButtonNodeForActionID(action.id);
|
||||
contextMenuPromise = promisePanelShown("pageActionContextMenu");
|
||||
EventUtils.synthesizeMouseAtCenter(urlbarButton, {
|
||||
type: "contextmenu",
|
||||
button: 2,
|
||||
});
|
||||
await contextMenuPromise;
|
||||
|
||||
// The context menu should show the "remove" item and the "manage" item. The
|
||||
// 4th item is "remove extension" but it is hidden. Click the "manage" item.
|
||||
// about:addons should open.
|
||||
menuItems = collectContextMenuItems();
|
||||
Assert.equal(menuItems.length, 4, "Context menu has 4 children");
|
||||
Assert.equal(
|
||||
menuItems[0].label,
|
||||
"Remove from Address Bar",
|
||||
"Context menu is in the 'remove' state"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[1].localName,
|
||||
"menuseparator",
|
||||
"menuseparator is present"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[2].label,
|
||||
"Manage Extension\u2026",
|
||||
"'Manage' item is present"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[3].label,
|
||||
"Remove Extension",
|
||||
"'Remove' item is present"
|
||||
);
|
||||
Assert.ok(menuItems[3].hidden, "'Remove' item is hidden");
|
||||
|
||||
contextMenuPromise = promisePanelHidden("pageActionContextMenu");
|
||||
EventUtils.synthesizeMouseAtCenter(menuItems[0], {});
|
||||
await contextMenuPromise;
|
||||
|
||||
// The action should be removed from the urlbar.
|
||||
await BrowserTestUtils.waitForCondition(() => {
|
||||
return !BrowserPageActions.urlbarButtonNodeForActionID(action.id);
|
||||
}, "Waiting for urlbar button to be removed");
|
||||
|
||||
// Open the panel and then open the context menu on the action's item.
|
||||
await promiseOpenPageActionPanel();
|
||||
contextMenuPromise = promisePanelShown("pageActionContextMenu");
|
||||
EventUtils.synthesizeMouseAtCenter(panelButton, {
|
||||
type: "contextmenu",
|
||||
button: 2,
|
||||
});
|
||||
await contextMenuPromise;
|
||||
|
||||
// The context menu should show the "remove" item and the "manage" item. The
|
||||
// 4th item is "remove extension" but it is hidden. Click the "remove" item.
|
||||
menuItems = collectContextMenuItems();
|
||||
Assert.equal(menuItems.length, 4, "Context menu has 4 children");
|
||||
Assert.equal(
|
||||
menuItems[0].label,
|
||||
"Add to Address Bar",
|
||||
"Context menu is in the 'add' state"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[1].localName,
|
||||
"menuseparator",
|
||||
"menuseparator is present"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[2].label,
|
||||
"Manage Extension\u2026",
|
||||
"'Manage' item is present"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[3].label,
|
||||
"Remove Extension",
|
||||
"'Remove' item is present"
|
||||
);
|
||||
Assert.ok(menuItems[3].hidden, "'Remove' item is hidden");
|
||||
|
||||
contextMenuPromise = promisePanelHidden("pageActionContextMenu");
|
||||
EventUtils.synthesizeMouseAtCenter(menuItems[0], {});
|
||||
await contextMenuPromise;
|
||||
|
||||
// The action should be added back to the urlbar.
|
||||
await BrowserTestUtils.waitForCondition(() => {
|
||||
return BrowserPageActions.urlbarButtonNodeForActionID(action.id);
|
||||
}, "Waiting for urlbar button to be added back");
|
||||
|
||||
// Open the context menu on the action's urlbar button.
|
||||
urlbarButton = BrowserPageActions.urlbarButtonNodeForActionID(action.id);
|
||||
contextMenuPromise = promisePanelShown("pageActionContextMenu");
|
||||
EventUtils.synthesizeMouseAtCenter(urlbarButton, {
|
||||
type: "contextmenu",
|
||||
button: 2,
|
||||
});
|
||||
await contextMenuPromise;
|
||||
|
||||
// The context menu should show the "add" item and the "manage" item. The 4th
|
||||
// item is "remove extension" but it is hidden. Click the "add" item.
|
||||
menuItems = collectContextMenuItems();
|
||||
Assert.equal(menuItems.length, 4, "Context menu has 4 children");
|
||||
Assert.equal(
|
||||
menuItems[0].label,
|
||||
"Remove from Address Bar",
|
||||
"Context menu is in the 'remove' state"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[1].localName,
|
||||
"menuseparator",
|
||||
"menuseparator is present"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[2].label,
|
||||
"Manage Extension\u2026",
|
||||
"'Manage' item is present"
|
||||
);
|
||||
Assert.equal(
|
||||
menuItems[3].label,
|
||||
"Remove Extension",
|
||||
"'Remove' item is present"
|
||||
);
|
||||
Assert.ok(menuItems[3].hidden, "'Remove' item is hidden");
|
||||
|
||||
// Click the "manage" item, about:addons should open.
|
||||
contextMenuPromise = promisePanelHidden("pageActionContextMenu");
|
||||
aboutAddonsPromise = BrowserTestUtils.waitForNewTab(gBrowser, "about:addons");
|
||||
EventUtils.synthesizeMouseAtCenter(menuItems[2], {});
|
||||
values = await Promise.all([aboutAddonsPromise, contextMenuPromise]);
|
||||
aboutAddonsTab = values[0];
|
||||
BrowserTestUtils.removeTab(aboutAddonsTab);
|
||||
|
||||
// Done, clean up.
|
||||
action.remove();
|
||||
|
||||
// Check the telemetry was collected properly.
|
||||
let snapshot = Services.telemetry.snapshotEvents(
|
||||
Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS,
|
||||
true
|
||||
);
|
||||
ok(
|
||||
snapshot.parent && !!snapshot.parent.length,
|
||||
"Got parent telemetry events in the snapshot"
|
||||
);
|
||||
let relatedEvents = snapshot.parent
|
||||
.filter(
|
||||
([timestamp, category, method]) =>
|
||||
category == "addonsManager" && method == "action"
|
||||
)
|
||||
.map(relatedEvent => relatedEvent.slice(3, 6));
|
||||
Assert.deepEqual(relatedEvents, [
|
||||
["pageAction", null, { action: "manage" }],
|
||||
["pageAction", null, { action: "manage" }],
|
||||
]);
|
||||
|
||||
// urlbar tests that run after this one can break if the mouse is left over
|
||||
// the area where the urlbar popup appears, which seems to happen due to the
|
||||
// above synthesized mouse events. Move it over the urlbar.
|
||||
EventUtils.synthesizeMouseAtCenter(gURLBar.inputField, { type: "mousemove" });
|
||||
gURLBar.focus();
|
||||
});
|
||||
|
||||
// The context menu shouldn't open on separators in the panel.
|
||||
add_task(async function contextMenuOnSeparator() {
|
||||
// Open the panel and get the bookmark separator.
|
||||
await promiseOpenPageActionPanel();
|
||||
let separator = BrowserPageActions.panelButtonNodeForActionID(
|
||||
PageActions.ACTION_ID_BOOKMARK_SEPARATOR
|
||||
);
|
||||
Assert.ok(separator, "The bookmark separator should be in the panel");
|
||||
|
||||
// Context-click it. popupshowing should be fired, but by the time the event
|
||||
// reaches this listener, preventDefault should have been called on it.
|
||||
let showingPromise = BrowserTestUtils.waitForEvent(
|
||||
document.getElementById("pageActionContextMenu"),
|
||||
"popupshowing",
|
||||
false
|
||||
);
|
||||
EventUtils.synthesizeMouseAtCenter(separator, {
|
||||
type: "contextmenu",
|
||||
button: 2,
|
||||
});
|
||||
let event = await showingPromise;
|
||||
Assert.ok(
|
||||
event.defaultPrevented,
|
||||
"defaultPrevented should be true on popupshowing event"
|
||||
);
|
||||
|
||||
// Click the main button to hide the main panel.
|
||||
EventUtils.synthesizeMouseAtCenter(BrowserPageActions.mainButtonNode, {});
|
||||
await promisePageActionPanelHidden();
|
||||
|
||||
// urlbar tests that run after this one can break if the mouse is left over
|
||||
// the area where the urlbar popup appears, which seems to happen due to the
|
||||
// above synthesized mouse events. Move it over the urlbar.
|
||||
EventUtils.synthesizeMouseAtCenter(gURLBar.inputField, { type: "mousemove" });
|
||||
gURLBar.focus();
|
||||
});
|
||||
|
||||
function collectContextMenuItems() {
|
||||
let contextMenu = document.getElementById("pageActionContextMenu");
|
||||
return Array.prototype.filter.call(contextMenu.children, node => {
|
||||
return window.getComputedStyle(node).visibility == "visible";
|
||||
});
|
||||
}
|
@ -212,3 +212,110 @@ async function disableNonReleaseActions() {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function assertActivatedPageActionPanelHidden() {
|
||||
Assert.ok(
|
||||
!document.getElementById(BrowserPageActions._activatedActionPanelID)
|
||||
);
|
||||
}
|
||||
|
||||
function promiseOpenPageActionPanel() {
|
||||
let dwu = window.windowUtils;
|
||||
return BrowserTestUtils.waitForCondition(() => {
|
||||
// Wait for the main page action button to become visible. It's hidden for
|
||||
// some URIs, so depending on when this is called, it may not yet be quite
|
||||
// visible. It's up to the caller to make sure it will be visible.
|
||||
info("Waiting for main page action button to have non-0 size");
|
||||
let bounds = dwu.getBoundsWithoutFlushing(
|
||||
BrowserPageActions.mainButtonNode
|
||||
);
|
||||
return bounds.width > 0 && bounds.height > 0;
|
||||
})
|
||||
.then(() => {
|
||||
// Wait for the panel to become open, by clicking the button if necessary.
|
||||
info("Waiting for main page action panel to be open");
|
||||
if (BrowserPageActions.panelNode.state == "open") {
|
||||
return Promise.resolve();
|
||||
}
|
||||
let shownPromise = promisePageActionPanelShown();
|
||||
EventUtils.synthesizeMouseAtCenter(BrowserPageActions.mainButtonNode, {});
|
||||
return shownPromise;
|
||||
})
|
||||
.then(() => {
|
||||
// Wait for items in the panel to become visible.
|
||||
return promisePageActionViewChildrenVisible(
|
||||
BrowserPageActions.mainViewNode
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function promisePageActionPanelShown() {
|
||||
return promisePanelShown(BrowserPageActions.panelNode);
|
||||
}
|
||||
|
||||
function promisePageActionPanelHidden() {
|
||||
return promisePanelHidden(BrowserPageActions.panelNode);
|
||||
}
|
||||
|
||||
function promisePanelShown(panelIDOrNode) {
|
||||
return promisePanelEvent(panelIDOrNode, "popupshown");
|
||||
}
|
||||
|
||||
function promisePanelHidden(panelIDOrNode) {
|
||||
return promisePanelEvent(panelIDOrNode, "popuphidden");
|
||||
}
|
||||
|
||||
function promisePanelEvent(panelIDOrNode, eventType) {
|
||||
return new Promise(resolve => {
|
||||
let panel = panelIDOrNode;
|
||||
if (typeof panel == "string") {
|
||||
panel = document.getElementById(panelIDOrNode);
|
||||
if (!panel) {
|
||||
throw new Error(`Panel with ID "${panelIDOrNode}" does not exist.`);
|
||||
}
|
||||
}
|
||||
if (
|
||||
(eventType == "popupshown" && panel.state == "open") ||
|
||||
(eventType == "popuphidden" && panel.state == "closed")
|
||||
) {
|
||||
executeSoon(resolve);
|
||||
return;
|
||||
}
|
||||
panel.addEventListener(
|
||||
eventType,
|
||||
() => {
|
||||
executeSoon(resolve);
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function promisePageActionViewShown() {
|
||||
info("promisePageActionViewShown waiting for ViewShown");
|
||||
return BrowserTestUtils.waitForEvent(
|
||||
BrowserPageActions.panelNode,
|
||||
"ViewShown"
|
||||
).then(async event => {
|
||||
let panelViewNode = event.originalTarget;
|
||||
await promisePageActionViewChildrenVisible(panelViewNode);
|
||||
return panelViewNode;
|
||||
});
|
||||
}
|
||||
|
||||
function promisePageActionViewChildrenVisible(panelViewNode) {
|
||||
info(
|
||||
"promisePageActionViewChildrenVisible waiting for a child node to be visible"
|
||||
);
|
||||
let dwu = window.windowUtils;
|
||||
return BrowserTestUtils.waitForCondition(() => {
|
||||
let bodyNode = panelViewNode.firstElementChild;
|
||||
for (let childNode of bodyNode.children) {
|
||||
let bounds = dwu.getBoundsWithoutFlushing(childNode);
|
||||
if (bounds.width > 0 && bounds.height > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user