Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Errors

/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
async function test_clickData({ manifest_version, persistent }) {
const action = manifest_version < 3 ? "browser_action" : "action";
const background = { scripts: ["background.js"] };
if (persistent != null) {
background.persistent = persistent;
}
let extension = ExtensionTestUtils.loadExtension({
manifest: {
manifest_version,
[action]: {},
background,
},
files: {
"background.js": function backgroundScript() {
function onClicked(tab, info) {
let button = info.button;
let modifiers = info.modifiers;
browser.test.sendMessage("onClick", { button, modifiers });
}
const apiNS =
browser.runtime.getManifest().manifest_version >= 3
? "action"
: "browserAction";
browser[apiNS].onClicked.addListener(onClicked);
browser.test.sendMessage("ready");
},
},
});
const map = {
shiftKey: "Shift",
altKey: "Alt",
metaKey: "Command",
ctrlKey: "Ctrl",
};
function assertSingleModifier(info, modifier, area) {
if (modifier === "ctrlKey" && AppConstants.platform === "macosx") {
is(
info.modifiers.length,
2,
`MacCtrl modifier with control click on Mac`
);
is(
info.modifiers[1],
"MacCtrl",
`MacCtrl modifier with control click on Mac`
);
} else {
is(
info.modifiers.length,
1,
`No unnecessary modifiers for exactly one key on event`
);
}
is(info.modifiers[0], map[modifier], `Correct modifier on ${area} click`);
}
await extension.startup();
await extension.awaitMessage("ready");
if (manifest_version >= 3 || persistent === false) {
// NOTE: even in MV3 where the API namespace is technically "action",
// the event listeners will be persisted into the startup data
// with "browserAction" as the module, because that is the name
// of the module shared by both MV2 browserAction and MV3 action APIs.
assertPersistentListeners(extension, "browserAction", "onClicked", {
primed: false,
});
await extension.terminateBackground();
assertPersistentListeners(extension, "browserAction", "onClicked", {
primed: true,
});
}
for (let area of [CustomizableUI.AREA_NAVBAR, getCustomizableUIPanelID()]) {
let widget = getBrowserActionWidget(extension);
CustomizableUI.addWidgetToArea(widget.id, area);
for (let modifier of Object.keys(map)) {
for (let i = 0; i < 2; i++) {
info(`test click with button ${i} modifier ${modifier}`);
let clickEventData = { button: i };
clickEventData[modifier] = true;
await clickBrowserAction(extension, window, clickEventData);
let details = await extension.awaitMessage("onClick");
is(details.button, i, `Correct button in ${area} click`);
assertSingleModifier(details, modifier, area);
}
info(`test keypress with modifier ${modifier}`);
let keypressEventData = {};
keypressEventData[modifier] = true;
await triggerBrowserActionWithKeyboard(extension, " ", keypressEventData);
let details = await extension.awaitMessage("onClick");
is(details.button, 0, `Key command emulates left click`);
assertSingleModifier(details, modifier, area);
}
}
if (manifest_version >= 3 || persistent === false) {
// The background event page is expected to have been
// spawned again to handle the action onClicked event.
await extension.awaitMessage("ready");
}
await extension.unload();
}
async function test_clickData_reset({ manifest_version }) {
const action = manifest_version < 3 ? "browser_action" : "action";
const browser_action_command =
manifest_version < 3 ? "_execute_browser_action" : "_execute_action";
const browser_action_key = "j";
let extension = ExtensionTestUtils.loadExtension({
manifest: {
manifest_version,
[action]: {
default_area: "navbar",
},
page_action: {},
commands: {
[browser_action_command]: {
suggested_key: {
default: "Alt+Shift+J",
},
},
},
},
async background() {
function onBrowserActionClicked(tab, info) {
browser.test.sendMessage("onClick", info);
}
function onPageActionClicked() {
browser.test.sendMessage("open-popup");
}
const { manifest_version } = browser.runtime.getManifest();
const apiNS = manifest_version >= 3 ? "action" : "browserAction";
browser[apiNS].onClicked.addListener(onBrowserActionClicked);
// pageAction should only be available in MV2 extensions.
if (manifest_version < 3) {
browser.pageAction.onClicked.addListener(onPageActionClicked);
let [tab] = await browser.tabs.query({
active: true,
currentWindow: true,
});
await browser.pageAction.show(tab.id);
}
browser.test.sendMessage("ready");
},
});
// Pollute the state of the browserAction's lastClickInfo
async function clickBrowserActionWithModifiers() {
await clickBrowserAction(extension, window, { button: 1, shiftKey: true });
let info = await extension.awaitMessage("onClick");
is(info.button, 1, "Got expected ClickData button details");
is(info.modifiers[0], "Shift", "Got expected ClickData modifiers details");
}
function assertInfoReset(info) {
is(info.button, 0, `ClickData button reset properly`);
is(info.modifiers.length, 0, `ClickData modifiers reset properly`);
}
await extension.startup();
await extension.awaitMessage("ready");
if (manifest_version >= 3) {
// NOTE: even in MV3 where the API namespace is technically "action",
// the event listeners will be persisted into the startup data
// with "browserAction" as the module, because that is the name
// of the module shared by both MV2 browserAction and MV3 action APIs.
assertPersistentListeners(extension, "browserAction", "onClicked", {
primed: false,
});
await extension.terminateBackground();
assertPersistentListeners(extension, "browserAction", "onClicked", {
primed: true,
});
}
await clickBrowserActionWithModifiers();
if (manifest_version >= 3) {
// The background event page is expected to have been
// spawned again to handle the action onClicked event.
await extension.awaitMessage("ready");
} else {
extension.onMessage("open-popup", () => {
EventUtils.synthesizeKey(browser_action_key, {
altKey: true,
shiftKey: true,
});
});
// pageAction should only be available in MV2 extensions.
await clickPageAction(extension);
// NOTE: the pageAction event listener then triggers browserAction.onClicked
assertInfoReset(await extension.awaitMessage("onClick"));
}
await clickBrowserActionWithModifiers();
await triggerBrowserActionWithKeyboard(extension, " ");
assertInfoReset(await extension.awaitMessage("onClick"));
await clickBrowserActionWithModifiers();
await triggerBrowserActionWithKeyboard(extension, " ");
assertInfoReset(await extension.awaitMessage("onClick"));
await extension.unload();
}
add_task(function test_clickData_MV2() {
return test_clickData({ manifest_version: 2 });
});
add_task(async function test_clickData_MV2_eventpage() {
await SpecialPowers.pushPrefEnv({
set: [["extensions.eventPages.enabled", true]],
});
await test_clickData({
manifest_version: 2,
persistent: false,
});
await SpecialPowers.popPrefEnv();
});
add_task(async function test_clickData_MV3() {
await SpecialPowers.pushPrefEnv({
set: [["extensions.manifestV3.enabled", true]],
});
await test_clickData({ manifest_version: 3 });
await SpecialPowers.popPrefEnv();
});
add_task(function test_clickData_reset_MV2() {
return test_clickData_reset({ manifest_version: 2 });
});
add_task(async function test_clickData_reset_MV3() {
await SpecialPowers.pushPrefEnv({
set: [["extensions.manifestV3.enabled", true]],
});
await test_clickData_reset({ manifest_version: 3 });
await SpecialPowers.popPrefEnv();
});