Bug 1706398 support internal command _execute_action r=robwu

Differential Revision: https://phabricator.services.mozilla.com/D114028
This commit is contained in:
Shane Caraveo 2021-06-15 14:51:12 +00:00
Родитель 957cb7e5e2
Коммит 5d0fc14d5e
6 изменённых файлов: 186 добавлений и 35 удалений

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

@ -436,16 +436,22 @@ var gMenuBuilder = {
info.button = event.button; info.button = event.button;
let _execute_action =
item.extension.manifestVersion < 3
? "_execute_browser_action"
: "_execute_action";
// Allow menus to open various actions supported in webext prior // Allow menus to open various actions supported in webext prior
// to notifying onclicked. // to notifying onclicked.
let actionFor = { let actionFor = {
[_execute_action]: global.browserActionFor,
_execute_page_action: global.pageActionFor, _execute_page_action: global.pageActionFor,
_execute_browser_action: global.browserActionFor,
_execute_sidebar_action: global.sidebarActionFor, _execute_sidebar_action: global.sidebarActionFor,
}[item.command]; }[item.command];
if (actionFor) { if (actionFor) {
let win = event.target.ownerGlobal; let win = event.target.ownerGlobal;
actionFor(item.extension).triggerAction(win); actionFor(item.extension).triggerAction(win);
return;
} }
item.extension.emit( item.extension.emit(

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

@ -278,9 +278,23 @@
"description": "Whether this context menu item is enabled or disabled. Defaults to true." "description": "Whether this context menu item is enabled or disabled. Defaults to true."
}, },
"command": { "command": {
"type": "string", "choices": [
{ "type": "string" },
{
"type": "string",
"enum": ["_execute_browser_action", "_execute_page_action", "_execute_sidebar_action"],
"max_manifest_version": 2,
"description": "Manifest V2 supports internal commands _execute_page_action, _execute_browser_action and _execute_sidebar_action."
},
{
"type": "string",
"enum": ["_execute_action", "_execute_page_action", "_execute_sidebar_action"],
"min_manifest_version": 3,
"description": "Manifest V3 supports internal commands _execute_page_action, _execute_action and _execute_sidebar_action."
}
],
"optional": true, "optional": true,
"description": "Specifies a command to issue for the context click. Currently supports internal commands _execute_page_action, _execute_browser_action and _execute_sidebar_action." "description": "Specifies a command to issue for the context click."
} }
} }
}, },

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

@ -2,6 +2,12 @@
/* vim: set sts=2 sw=2 et tw=80: */ /* vim: set sts=2 sw=2 et tw=80: */
"use strict"; "use strict";
add_task(async function testTabSwitchActionContext() {
await SpecialPowers.pushPrefEnv({
set: [["extensions.manifestV3.enabled", true]],
});
});
async function testExecuteBrowserActionWithOptions(options = {}) { async function testExecuteBrowserActionWithOptions(options = {}) {
// Make sure the mouse isn't hovering over the browserAction widget. // Make sure the mouse isn't hovering over the browserAction widget.
EventUtils.synthesizeMouseAtCenter( EventUtils.synthesizeMouseAtCenter(
@ -12,21 +18,34 @@ async function testExecuteBrowserActionWithOptions(options = {}) {
let extensionOptions = {}; let extensionOptions = {};
let browser_action =
options.manifest_version > 2 ? "action" : "browser_action";
let browser_action_key = options.manifest_version > 2 ? "a" : "j";
// We accept any command in the manifest, so here we add commands for
// both V2 and V3, but only the command that matches the manifest version
// should ever work.
extensionOptions.manifest = { extensionOptions.manifest = {
manifest_version: options.manifest_version || 2,
commands: { commands: {
_execute_browser_action: { _execute_browser_action: {
suggested_key: { suggested_key: {
default: "Alt+Shift+J", default: "Alt+Shift+J",
}, },
}, },
_execute_action: {
suggested_key: {
default: "Alt+Shift+A",
},
},
}, },
browser_action: { [browser_action]: {
browser_style: true, browser_style: true,
}, },
}; };
if (options.withPopup) { if (options.withPopup) {
extensionOptions.manifest.browser_action.default_popup = "popup.html"; extensionOptions.manifest[browser_action].default_popup = "popup.html";
extensionOptions.files = { extensionOptions.files = {
"popup.html": ` "popup.html": `
@ -46,25 +65,36 @@ async function testExecuteBrowserActionWithOptions(options = {}) {
} }
extensionOptions.background = () => { extensionOptions.background = () => {
browser.test.onMessage.addListener((message, withPopup) => { let manifest = browser.runtime.getManifest();
let { manifest_version } = manifest;
const action = manifest_version < 3 ? "browserAction" : "action";
browser.test.onMessage.addListener((message, options) => {
browser.commands.onCommand.addListener(commandName => { browser.commands.onCommand.addListener(commandName => {
if (commandName == "_execute_browser_action") { if (
browser.test.fail( ["_execute_browser_action", "_execute_action"].includes(commandName)
"The onCommand listener should never fire for _execute_browser_action." ) {
browser.test.assertEq(
commandName,
options.expectedCommand,
`The onCommand listener fired for ${commandName}.`
); );
browser[action].openPopup();
} }
}); });
browser.browserAction.onClicked.addListener(() => { if (!options.expectedCommand) {
if (withPopup) { browser[action].onClicked.addListener(() => {
browser.test.fail( if (options.withPopup) {
"The onClick listener should never fire if the browserAction has a popup." browser.test.fail(
); "The onClick listener should never fire if the browserAction has a popup."
browser.test.notifyFail("execute-browser-action-on-clicked-fired"); );
} else { browser.test.notifyFail("execute-browser-action-on-clicked-fired");
browser.test.notifyPass("execute-browser-action-on-clicked-fired"); } else {
} browser.test.notifyPass("execute-browser-action-on-clicked-fired");
}); }
});
}
browser.runtime.onMessage.addListener(msg => { browser.runtime.onMessage.addListener(msg => {
if (msg == "from-browser-action-popup") { if (msg == "from-browser-action-popup") {
@ -79,7 +109,10 @@ async function testExecuteBrowserActionWithOptions(options = {}) {
let extension = ExtensionTestUtils.loadExtension(extensionOptions); let extension = ExtensionTestUtils.loadExtension(extensionOptions);
extension.onMessage("send-keys", () => { extension.onMessage("send-keys", () => {
EventUtils.synthesizeKey("j", { altKey: true, shiftKey: true }); EventUtils.synthesizeKey(browser_action_key, {
altKey: true,
shiftKey: true,
});
}); });
await extension.startup(); await extension.startup();
@ -91,7 +124,7 @@ async function testExecuteBrowserActionWithOptions(options = {}) {
CustomizableUI.addWidgetToArea(widget.id, options.inArea); CustomizableUI.addWidgetToArea(widget.id, options.inArea);
} }
extension.sendMessage("withPopup", options.withPopup); extension.sendMessage("options", options);
if (options.withPopup) { if (options.withPopup) {
await extension.awaitFinish("execute-browser-action-popup-opened"); await extension.awaitFinish("execute-browser-action-popup-opened");
@ -116,6 +149,33 @@ add_task(async function test_execute_browser_action_without_popup() {
await testExecuteBrowserActionWithOptions(); await testExecuteBrowserActionWithOptions();
}); });
add_task(async function test_execute_browser_action_command() {
await testExecuteBrowserActionWithOptions({
withPopup: true,
expectedCommand: "_execute_browser_action",
});
});
add_task(async function test_execute_action_with_popup() {
await testExecuteBrowserActionWithOptions({
withPopup: true,
manifest_version: 3,
});
});
add_task(async function test_execute_action_without_popup() {
await testExecuteBrowserActionWithOptions({
manifest_version: 3,
});
});
add_task(async function test_execute_action_command() {
await testExecuteBrowserActionWithOptions({
withPopup: true,
expectedCommand: "_execute_action",
});
});
add_task( add_task(
async function test_execute_browser_action_in_hamburger_menu_with_popup() { async function test_execute_browser_action_in_hamburger_menu_with_popup() {
await testExecuteBrowserActionWithOptions({ await testExecuteBrowserActionWithOptions({

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

@ -2,7 +2,13 @@
/* vim: set sts=2 sw=2 et tw=80: */ /* vim: set sts=2 sw=2 et tw=80: */
"use strict"; "use strict";
add_task(async function() { add_task(async function testTabSwitchActionContext() {
await SpecialPowers.pushPrefEnv({
set: [["extensions.manifestV3.enabled", true]],
});
});
add_task(async function test_actions_context_menu() {
function background() { function background() {
browser.contextMenus.create({ browser.contextMenus.create({
title: "open_browser_action", title: "open_browser_action",
@ -22,6 +28,9 @@ add_task(async function() {
browser.tabs.onUpdated.addListener((tabId, changeInfo, tab) => { browser.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
browser.pageAction.show(tabId); browser.pageAction.show(tabId);
}); });
browser.contextMenus.onClicked.addListener(() => {
browser.test.fail(`menu onClicked should not have been received`);
});
browser.test.sendMessage("ready"); browser.test.sendMessage("ready");
} }
@ -86,3 +95,62 @@ add_task(async function() {
BrowserTestUtils.removeTab(tab); BrowserTestUtils.removeTab(tab);
await extension.unload(); await extension.unload();
}); });
add_task(async function test_v3_action_context_menu() {
let extension = ExtensionTestUtils.loadExtension({
manifest: {
name: "contextMenus commands",
manifest_version: 3,
permissions: ["contextMenus"],
action: {
default_title: "Test Action",
default_popup: "test.html",
browser_style: true,
},
},
background() {
browser.contextMenus.onClicked.addListener(() => {
browser.test.fail(`menu onClicked should not have been received`);
});
browser.contextMenus.create(
{
title: "open_action",
contexts: ["all"],
command: "_execute_action",
},
() => {
browser.test.sendMessage("ready");
}
);
},
files: {
"test.html": `<!DOCTYPE html><meta charset="utf-8"><script src="test.js"></script>`,
"test.js": () => {
window.onload = () => {
browser.test.sendMessage("test-opened", true);
};
},
},
});
async function testContext(id) {
const menu = await openContextMenu();
const items = menu.getElementsByAttribute("label", id);
is(items.length, 1, `exactly one menu item found`);
await closeExtensionContextMenu(items[0]);
return extension.awaitMessage("test-opened");
}
await extension.startup();
await extension.awaitMessage("ready");
const PAGE =
"http://mochi.test:8888/browser/browser/components/extensions/test/browser/context.html?test=commands";
const tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, PAGE);
ok(await testContext("open_action"), "_execute_action worked");
BrowserTestUtils.removeTab(tab);
await extension.unload();
});

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

@ -51,8 +51,6 @@ XPCOMUtils.defineLazyGetter(this, "sidebarActionFor", () => {
const { ExtensionError, DefaultMap } = ExtensionUtils; const { ExtensionError, DefaultMap } = ExtensionUtils;
const { makeWidgetId } = ExtensionCommon; const { makeWidgetId } = ExtensionCommon;
const EXECUTE_PAGE_ACTION = "_execute_page_action";
const EXECUTE_BROWSER_ACTION = "_execute_browser_action";
const EXECUTE_SIDEBAR_ACTION = "_execute_sidebar_action"; const EXECUTE_SIDEBAR_ACTION = "_execute_sidebar_action";
function normalizeShortcut(shortcut) { function normalizeShortcut(shortcut) {
@ -444,20 +442,24 @@ class ExtensionShortcuts {
// therefore the listeners for these elements will be garbage collected. // therefore the listeners for these elements will be garbage collected.
keyElement.addEventListener("command", event => { keyElement.addEventListener("command", event => {
let action; let action;
if (name == EXECUTE_PAGE_ACTION) { let _execute_action =
action = pageActionFor(this.extension); this.extension.manifestVersion < 3
} else if (name == EXECUTE_BROWSER_ACTION) { ? "_execute_browser_action"
action = browserActionFor(this.extension); : "_execute_action";
} else if (name == EXECUTE_SIDEBAR_ACTION) {
action = sidebarActionFor(this.extension); let actionFor = {
[_execute_action]: browserActionFor,
_execute_page_action: pageActionFor,
_execute_sidebar_action: sidebarActionFor,
}[name];
if (actionFor) {
action = actionFor(this.extension);
let win = event.target.ownerGlobal;
action.triggerAction(win);
} else { } else {
this.extension.tabManager.addActiveTabPermission(); this.extension.tabManager.addActiveTabPermission();
this.onCommand(name); this.onCommand(name);
return;
}
if (action) {
let win = event.target.ownerGlobal;
action.triggerAction(win);
} }
}); });
/* eslint-enable mozilla/balanced-listeners */ /* eslint-enable mozilla/balanced-listeners */

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

@ -44,6 +44,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
} }
let builtInNames = new Map([ let builtInNames = new Map([
["_execute_action", "shortcuts-browserAction2"],
["_execute_browser_action", "shortcuts-browserAction2"], ["_execute_browser_action", "shortcuts-browserAction2"],
["_execute_page_action", "shortcuts-pageAction"], ["_execute_page_action", "shortcuts-pageAction"],
["_execute_sidebar_action", "shortcuts-sidebarAction"], ["_execute_sidebar_action", "shortcuts-sidebarAction"],