forked from mirrors/gecko-dev
Depends on D179819 Differential Revision: https://phabricator.services.mozilla.com/D179820
432 lines
11 KiB
JavaScript
432 lines
11 KiB
JavaScript
"use strict";
|
|
|
|
ChromeUtils.defineESModuleGetters(this, {
|
|
ExtensionParent: "resource://gre/modules/ExtensionParent.sys.mjs",
|
|
Management: "resource://gre/modules/Extension.sys.mjs",
|
|
});
|
|
|
|
const { AddonTestUtils } = ChromeUtils.importESModule(
|
|
"resource://testing-common/AddonTestUtils.sys.mjs"
|
|
);
|
|
|
|
AddonTestUtils.init(this);
|
|
AddonTestUtils.overrideCertDB();
|
|
AddonTestUtils.createAppInfo(
|
|
"xpcshell@tests.mozilla.org",
|
|
"XPCShell",
|
|
"42",
|
|
"42"
|
|
);
|
|
|
|
Services.prefs.setBoolPref("extensions.eventPages.enabled", true);
|
|
|
|
function getExtension(id, background, useAddonManager) {
|
|
return ExtensionTestUtils.loadExtension({
|
|
useAddonManager,
|
|
manifest: {
|
|
browser_specific_settings: { gecko: { id } },
|
|
permissions: ["menus"],
|
|
background: { persistent: false },
|
|
},
|
|
background,
|
|
});
|
|
}
|
|
|
|
async function expectCached(extension, expect) {
|
|
let { StartupCache } = ExtensionParent;
|
|
let cached = await StartupCache.menus.get(extension.id);
|
|
let createProperties = Array.from(cached.values());
|
|
equal(cached.size, expect.length, "menus saved in cache");
|
|
// The menus startupCache is a map and the order is significant
|
|
// for recreating menus on startup. Ensure that they are in
|
|
// the expected order. We only verify specific keys here rather
|
|
// than all menu properties.
|
|
for (let i in createProperties) {
|
|
Assert.deepEqual(
|
|
createProperties[i],
|
|
expect[i],
|
|
"expected cached properties exist"
|
|
);
|
|
}
|
|
}
|
|
|
|
function promiseExtensionEvent(wrapper, event) {
|
|
return new Promise(resolve => {
|
|
wrapper.extension.once(event, (kind, data) => {
|
|
resolve(data);
|
|
});
|
|
});
|
|
}
|
|
|
|
add_setup(async () => {
|
|
await AddonTestUtils.promiseStartupManager();
|
|
});
|
|
|
|
add_task(async function test_menu_onInstalled() {
|
|
async function background() {
|
|
browser.runtime.onInstalled.addListener(async () => {
|
|
const parentId = browser.menus.create({
|
|
contexts: ["all"],
|
|
title: "parent",
|
|
id: "test-parent",
|
|
});
|
|
browser.menus.create({
|
|
parentId,
|
|
title: "click A",
|
|
id: "test-click-a",
|
|
});
|
|
browser.menus.create(
|
|
{
|
|
parentId,
|
|
title: "click B",
|
|
id: "test-click-b",
|
|
},
|
|
() => {
|
|
browser.test.sendMessage("onInstalled");
|
|
}
|
|
);
|
|
});
|
|
browser.menus.create(
|
|
{
|
|
contexts: ["tab"],
|
|
title: "top-level",
|
|
id: "test-top-level",
|
|
},
|
|
() => {
|
|
browser.test.sendMessage("create", browser.runtime.lastError?.message);
|
|
}
|
|
);
|
|
|
|
browser.test.onMessage.addListener(async msg => {
|
|
browser.test.log(`onMessage ${msg}`);
|
|
if (msg == "updatemenu") {
|
|
await browser.menus.update("test-click-a", { title: "click updated" });
|
|
} else if (msg == "removemenu") {
|
|
await browser.menus.remove("test-click-b");
|
|
} else if (msg == "removeall") {
|
|
await browser.menus.removeAll();
|
|
}
|
|
browser.test.sendMessage("updated");
|
|
});
|
|
}
|
|
|
|
const extension = getExtension(
|
|
"test-persist@mochitest",
|
|
background,
|
|
"permanent"
|
|
);
|
|
|
|
await extension.startup();
|
|
let lastError = await extension.awaitMessage("create");
|
|
Assert.equal(lastError, undefined, "no error creating menu");
|
|
await extension.awaitMessage("onInstalled");
|
|
await extension.terminateBackground();
|
|
|
|
await expectCached(extension, [
|
|
{
|
|
contexts: ["tab"],
|
|
id: "test-top-level",
|
|
title: "top-level",
|
|
},
|
|
{ contexts: ["all"], id: "test-parent", title: "parent" },
|
|
{
|
|
id: "test-click-a",
|
|
parentId: "test-parent",
|
|
title: "click A",
|
|
},
|
|
{
|
|
id: "test-click-b",
|
|
parentId: "test-parent",
|
|
title: "click B",
|
|
},
|
|
]);
|
|
|
|
await extension.wakeupBackground();
|
|
lastError = await extension.awaitMessage("create");
|
|
Assert.equal(
|
|
lastError,
|
|
"The menu id test-top-level already exists in menus.create.",
|
|
"correct error creating menu"
|
|
);
|
|
|
|
await AddonTestUtils.promiseRestartManager();
|
|
await extension.awaitStartup();
|
|
|
|
// verify the startupcache
|
|
await expectCached(extension, [
|
|
{
|
|
contexts: ["tab"],
|
|
id: "test-top-level",
|
|
title: "top-level",
|
|
},
|
|
{ contexts: ["all"], id: "test-parent", title: "parent" },
|
|
{
|
|
id: "test-click-a",
|
|
parentId: "test-parent",
|
|
title: "click A",
|
|
},
|
|
{
|
|
id: "test-click-b",
|
|
parentId: "test-parent",
|
|
title: "click B",
|
|
},
|
|
]);
|
|
|
|
equal(
|
|
extension.extension.backgroundState,
|
|
"stopped",
|
|
"background is not running"
|
|
);
|
|
await extension.wakeupBackground();
|
|
lastError = await extension.awaitMessage("create");
|
|
Assert.equal(
|
|
lastError,
|
|
"The menu id test-top-level already exists in menus.create.",
|
|
"correct error creating menu"
|
|
);
|
|
|
|
extension.sendMessage("updatemenu");
|
|
await extension.awaitMessage("updated");
|
|
await extension.terminateBackground();
|
|
|
|
// Title change is cached
|
|
await expectCached(extension, [
|
|
{
|
|
contexts: ["tab"],
|
|
id: "test-top-level",
|
|
title: "top-level",
|
|
},
|
|
{ contexts: ["all"], id: "test-parent", title: "parent" },
|
|
{
|
|
id: "test-click-a",
|
|
parentId: "test-parent",
|
|
title: "click updated",
|
|
},
|
|
{
|
|
id: "test-click-b",
|
|
parentId: "test-parent",
|
|
title: "click B",
|
|
},
|
|
]);
|
|
|
|
await extension.wakeupBackground();
|
|
lastError = await extension.awaitMessage("create");
|
|
Assert.equal(
|
|
lastError,
|
|
"The menu id test-top-level already exists in menus.create.",
|
|
"correct error creating menu"
|
|
);
|
|
|
|
extension.sendMessage("removemenu");
|
|
await extension.awaitMessage("updated");
|
|
await extension.terminateBackground();
|
|
|
|
// menu removed
|
|
await expectCached(extension, [
|
|
{
|
|
contexts: ["tab"],
|
|
id: "test-top-level",
|
|
title: "top-level",
|
|
},
|
|
{ contexts: ["all"], id: "test-parent", title: "parent" },
|
|
{
|
|
id: "test-click-a",
|
|
parentId: "test-parent",
|
|
title: "click updated",
|
|
},
|
|
]);
|
|
|
|
await extension.wakeupBackground();
|
|
lastError = await extension.awaitMessage("create");
|
|
Assert.equal(
|
|
lastError,
|
|
"The menu id test-top-level already exists in menus.create.",
|
|
"correct error creating menu"
|
|
);
|
|
|
|
extension.sendMessage("removeall");
|
|
await extension.awaitMessage("updated");
|
|
await extension.terminateBackground();
|
|
|
|
// menus removed
|
|
await expectCached(extension, []);
|
|
|
|
await extension.unload();
|
|
});
|
|
|
|
add_task(async function test_menu_nested() {
|
|
async function background() {
|
|
browser.test.onMessage.addListener(async (action, properties) => {
|
|
browser.test.log(`onMessage ${action}`);
|
|
switch (action) {
|
|
case "create":
|
|
await new Promise(resolve => {
|
|
browser.menus.create(properties, resolve);
|
|
});
|
|
break;
|
|
case "update":
|
|
{
|
|
let { id, ...update } = properties;
|
|
await browser.menus.update(id, update);
|
|
}
|
|
break;
|
|
case "remove":
|
|
{
|
|
let { id } = properties;
|
|
await browser.menus.remove(id);
|
|
}
|
|
break;
|
|
case "removeAll":
|
|
await browser.menus.removeAll();
|
|
break;
|
|
}
|
|
browser.test.sendMessage("updated");
|
|
});
|
|
}
|
|
|
|
const extension = getExtension(
|
|
"test-nesting@mochitest",
|
|
background,
|
|
"permanent"
|
|
);
|
|
await extension.startup();
|
|
|
|
extension.sendMessage("create", {
|
|
id: "first",
|
|
contexts: ["all"],
|
|
title: "first",
|
|
});
|
|
await extension.awaitMessage("updated");
|
|
await expectCached(extension, [
|
|
{ contexts: ["all"], id: "first", title: "first" },
|
|
]);
|
|
|
|
extension.sendMessage("create", {
|
|
id: "second",
|
|
contexts: ["all"],
|
|
title: "second",
|
|
});
|
|
await extension.awaitMessage("updated");
|
|
await expectCached(extension, [
|
|
{ contexts: ["all"], id: "first", title: "first" },
|
|
{ contexts: ["all"], id: "second", title: "second" },
|
|
]);
|
|
|
|
extension.sendMessage("create", {
|
|
id: "third",
|
|
contexts: ["all"],
|
|
title: "third",
|
|
parentId: "first",
|
|
});
|
|
await extension.awaitMessage("updated");
|
|
await expectCached(extension, [
|
|
{ contexts: ["all"], id: "first", title: "first" },
|
|
{ contexts: ["all"], id: "second", title: "second" },
|
|
{
|
|
contexts: ["all"],
|
|
id: "third",
|
|
parentId: "first",
|
|
title: "third",
|
|
},
|
|
]);
|
|
|
|
extension.sendMessage("create", {
|
|
id: "fourth",
|
|
contexts: ["all"],
|
|
title: "fourth",
|
|
});
|
|
await extension.awaitMessage("updated");
|
|
await expectCached(extension, [
|
|
{ contexts: ["all"], id: "first", title: "first" },
|
|
{ contexts: ["all"], id: "second", title: "second" },
|
|
{
|
|
contexts: ["all"],
|
|
id: "third",
|
|
parentId: "first",
|
|
title: "third",
|
|
},
|
|
{ contexts: ["all"], id: "fourth", title: "fourth" },
|
|
]);
|
|
|
|
extension.sendMessage("update", {
|
|
id: "first",
|
|
parentId: "second",
|
|
});
|
|
await extension.awaitMessage("updated");
|
|
await expectCached(extension, [
|
|
{ contexts: ["all"], id: "second", title: "second" },
|
|
{ contexts: ["all"], id: "fourth", title: "fourth" },
|
|
{
|
|
contexts: ["all"],
|
|
id: "first",
|
|
title: "first",
|
|
parentId: "second",
|
|
},
|
|
{
|
|
contexts: ["all"],
|
|
id: "third",
|
|
parentId: "first",
|
|
title: "third",
|
|
},
|
|
]);
|
|
|
|
await AddonTestUtils.promiseShutdownManager();
|
|
// We need to attach an event listener before the
|
|
// startup event is emitted. Fortunately, we
|
|
// emit via Management before emitting on extension.
|
|
let promiseMenus;
|
|
Management.once("startup", (kind, ext) => {
|
|
info(`management ${kind} ${ext.id}`);
|
|
promiseMenus = promiseExtensionEvent(
|
|
{ extension: ext },
|
|
"webext-menus-created"
|
|
);
|
|
});
|
|
await AddonTestUtils.promiseStartupManager();
|
|
await extension.awaitStartup();
|
|
await extension.wakeupBackground();
|
|
|
|
await expectCached(extension, [
|
|
{ contexts: ["all"], id: "second", title: "second" },
|
|
{ contexts: ["all"], id: "fourth", title: "fourth" },
|
|
{
|
|
contexts: ["all"],
|
|
id: "first",
|
|
title: "first",
|
|
parentId: "second",
|
|
},
|
|
{
|
|
contexts: ["all"],
|
|
id: "third",
|
|
parentId: "first",
|
|
title: "third",
|
|
},
|
|
]);
|
|
// validate nesting
|
|
let menus = await promiseMenus;
|
|
equal(menus.get("first").parentId, "second", "menuitem parent is correct");
|
|
equal(
|
|
menus.get("second").children.length,
|
|
1,
|
|
"menuitem parent has correct number of children"
|
|
);
|
|
equal(
|
|
menus.get("second").root.children.length,
|
|
2, // second and forth
|
|
"menuitem root has correct number of children"
|
|
);
|
|
|
|
extension.sendMessage("remove", {
|
|
id: "second",
|
|
});
|
|
await extension.awaitMessage("updated");
|
|
await expectCached(extension, [
|
|
{ contexts: ["all"], id: "fourth", title: "fourth" },
|
|
]);
|
|
|
|
extension.sendMessage("removeAll");
|
|
await extension.awaitMessage("updated");
|
|
await expectCached(extension, []);
|
|
|
|
await extension.unload();
|
|
});
|