Bug 1616143 - Allow setting of properties per tab on action buttons. r=mkmelin
--HG-- extra : rebase_source : 188814385f1072d4761fc6846e3e8d3bec47633c extra : histedit_source : 8992fd666c41be66bb175d4cb5811d299d0a7ebb
This commit is contained in:
Родитель
84ff495b42
Коммит
71f9fa4ccf
|
@ -43,6 +43,14 @@ XPCOMUtils.defineLazyGlobalGetters(this, ["InspectorUtils"]);
|
|||
var DEFAULT_ICON = "chrome://messenger/content/extension.svg";
|
||||
|
||||
this.ToolbarButtonAPI = class extends ExtensionAPI {
|
||||
constructor(extension, global) {
|
||||
super(extension);
|
||||
this.global = global;
|
||||
this.tabContext = new this.global.TabContext(target =>
|
||||
this.getContextData(null)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the extension is enabled.
|
||||
*
|
||||
|
@ -235,8 +243,9 @@ this.ToolbarButtonAPI = class extends ExtensionAPI {
|
|||
async triggerAction(window) {
|
||||
let { document } = window;
|
||||
let button = document.getElementById(this.id);
|
||||
let popupURL = this.getProperty(this.globals, "popup");
|
||||
let enabled = this.getProperty(this.globals, "enabled");
|
||||
let { popup: popupURL, enabled } = this.getContextData(
|
||||
this.getTargetFromWindow(window)
|
||||
);
|
||||
|
||||
if (button && popupURL && enabled) {
|
||||
let popup =
|
||||
|
@ -262,6 +271,9 @@ this.ToolbarButtonAPI = class extends ExtensionAPI {
|
|||
this.triggerAction(window);
|
||||
}
|
||||
break;
|
||||
case "TabSelect":
|
||||
this.updateWindow(window);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -428,7 +440,10 @@ this.ToolbarButtonAPI = class extends ExtensionAPI {
|
|||
async updateWindow(window) {
|
||||
let button = window.document.getElementById(this.id);
|
||||
if (button) {
|
||||
this.updateButton(button, this.globals);
|
||||
this.updateButton(
|
||||
button,
|
||||
this.getContextData(this.getTargetFromWindow(window))
|
||||
);
|
||||
}
|
||||
await new Promise(window.requestAnimationFrame);
|
||||
}
|
||||
|
@ -444,7 +459,7 @@ this.ToolbarButtonAPI = class extends ExtensionAPI {
|
|||
*/
|
||||
async updateOnChange(target) {
|
||||
if (target) {
|
||||
let window = target.ownerGlobal;
|
||||
let window = Cu.getGlobalForObject(target);
|
||||
if (target === window || target.selected) {
|
||||
await this.updateWindow(window);
|
||||
}
|
||||
|
@ -460,38 +475,55 @@ this.ToolbarButtonAPI = class extends ExtensionAPI {
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets the target object and its associated values corresponding to
|
||||
* the `details` parameter of the various get* and set* API methods.
|
||||
* Gets the active tab of the passed window if the window has tabs, or the
|
||||
* window itself.
|
||||
*
|
||||
* @param {ChromeWindow} window
|
||||
* @returns {XULElement|ChromeWindow}
|
||||
*/
|
||||
getTargetFromWindow(window) {
|
||||
let tabmail = window.document.getElementById("tabmail");
|
||||
if (tabmail) {
|
||||
return tabmail.currentTabInfo;
|
||||
}
|
||||
return window;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the target object corresponding to the `details` parameter of the various
|
||||
* get* and set* API methods.
|
||||
*
|
||||
* @param {Object} details
|
||||
* An object with optional `tabId` or `windowId` properties.
|
||||
* @throws if both `tabId` and `windowId` are specified, or if they are invalid.
|
||||
* @returns {Object}
|
||||
* An object with two properties: `target` and `values`.
|
||||
* - If a `tabId` was specified, `target` will be the corresponding
|
||||
* XULElement tab. If a `windowId` was specified, `target` will be
|
||||
* the corresponding ChromeWindow. Otherwise it will be `null`.
|
||||
* - `values` will contain the icon, title, badge, etc. associated with
|
||||
* the target.
|
||||
* @throws if `windowId` is specified, this is not valid in Thunderbird.
|
||||
* @returns {XULElement|ChromeWindow|null}
|
||||
* If a `tabId` was specified, the corresponding XULElement tab.
|
||||
* If a `windowId` was specified, the corresponding ChromeWindow.
|
||||
* Otherwise, `null`.
|
||||
*/
|
||||
getContextData({ tabId, windowId }) {
|
||||
if (tabId != null && windowId != null) {
|
||||
throw new ExtensionError(
|
||||
"Only one of tabId and windowId can be specified."
|
||||
);
|
||||
getTargetFromDetails({ tabId, windowId }) {
|
||||
if (windowId != null) {
|
||||
throw new ExtensionError("windowId is not allowed, use tabId instead.");
|
||||
}
|
||||
let target, values;
|
||||
// if (tabId != null) {
|
||||
// target = tabTracker.getTab(tabId);
|
||||
// values = this.tabContext.get(target);
|
||||
// } else if (windowId != null) {
|
||||
// target = windowTracker.getWindow(windowId);
|
||||
// values = this.tabContext.get(target);
|
||||
// } else {
|
||||
target = null;
|
||||
values = this.globals;
|
||||
// }
|
||||
return { target, values };
|
||||
if (tabId != null) {
|
||||
return this.global.tabTracker.getTab(tabId);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the data associated with a tab, window, or the global one.
|
||||
*
|
||||
* @param {XULElement|ChromeWindow|null} target
|
||||
* A XULElement tab, a ChromeWindow, or null for the global data.
|
||||
* @returns {Object}
|
||||
* The icon, title, badge, etc. associated with the target.
|
||||
*/
|
||||
getContextData(target) {
|
||||
if (target) {
|
||||
return this.tabContext.get(target);
|
||||
}
|
||||
return this.globals;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -506,7 +538,8 @@ this.ToolbarButtonAPI = class extends ExtensionAPI {
|
|||
* Value for prop.
|
||||
*/
|
||||
async setProperty(details, prop, value) {
|
||||
let { target, values } = this.getContextData(details);
|
||||
let target = this.getTargetFromDetails(details);
|
||||
let values = this.getContextData(target);
|
||||
if (value === null) {
|
||||
delete values[prop];
|
||||
} else {
|
||||
|
@ -528,7 +561,7 @@ this.ToolbarButtonAPI = class extends ExtensionAPI {
|
|||
* Value of prop.
|
||||
*/
|
||||
getProperty(details, prop) {
|
||||
return this.getContextData(details).values[prop];
|
||||
return this.getContextData(this.getTargetFromDetails(details))[prop];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -23,6 +23,7 @@ this.browserAction = class extends ToolbarButtonAPI {
|
|||
close() {
|
||||
super.close();
|
||||
browserActionMap.delete(this.extension);
|
||||
windowTracker.removeListener("TabSelect", this);
|
||||
}
|
||||
|
||||
static onUninstall(extensionId) {
|
||||
|
@ -49,13 +50,14 @@ this.browserAction = class extends ToolbarButtonAPI {
|
|||
}
|
||||
|
||||
constructor(extension) {
|
||||
super(extension);
|
||||
super(extension, global);
|
||||
this.manifest_name = "browser_action";
|
||||
this.manifestName = "browserAction";
|
||||
this.windowURLs = ["chrome://messenger/content/messenger.xhtml"];
|
||||
this.toolboxId = "mail-toolbox";
|
||||
this.toolbarId = "mail-bar3";
|
||||
this.global = global;
|
||||
|
||||
windowTracker.addListener("TabSelect", this);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ ChromeUtils.defineModuleGetter(
|
|||
|
||||
this.composeAction = class extends ToolbarButtonAPI {
|
||||
constructor(extension) {
|
||||
super(extension);
|
||||
super(extension, global);
|
||||
this.manifest_name = "compose_action";
|
||||
this.manifestName = "composeAction";
|
||||
this.windowURLs = [
|
||||
|
@ -25,8 +25,6 @@ this.composeAction = class extends ToolbarButtonAPI {
|
|||
if (format) {
|
||||
this.paint = this.paintFormatToolbar;
|
||||
}
|
||||
|
||||
this.global = global;
|
||||
}
|
||||
|
||||
paintFormatToolbar(window) {
|
||||
|
|
|
@ -164,6 +164,50 @@ function getTabBrowser(nativeTabInfo) {
|
|||
}
|
||||
global.getTabBrowser = getTabBrowser;
|
||||
|
||||
/**
|
||||
* Manages tab-specific and window-specific context data, and dispatches
|
||||
* tab select events across all windows.
|
||||
*/
|
||||
global.TabContext = class extends EventEmitter {
|
||||
/**
|
||||
* @param {Function} getDefaultPrototype
|
||||
* Provides the prototype of the context value for a tab or window when there is none.
|
||||
* Called with a XULElement or ChromeWindow argument.
|
||||
* Should return an object or null.
|
||||
*/
|
||||
constructor(getDefaultPrototype) {
|
||||
super();
|
||||
this.getDefaultPrototype = getDefaultPrototype;
|
||||
this.tabData = new WeakMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the context data associated with `keyObject`.
|
||||
*
|
||||
* @param {XULElement|ChromeWindow} keyObject
|
||||
* Browser tab or browser chrome window.
|
||||
* @returns {Object}
|
||||
*/
|
||||
get(keyObject) {
|
||||
if (!this.tabData.has(keyObject)) {
|
||||
let data = Object.create(this.getDefaultPrototype(keyObject));
|
||||
this.tabData.set(keyObject, data);
|
||||
}
|
||||
|
||||
return this.tabData.get(keyObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the context data associated with `keyObject`.
|
||||
*
|
||||
* @param {XULElement|ChromeWindow} keyObject
|
||||
* Browser tab or browser chrome window.
|
||||
*/
|
||||
clear(keyObject) {
|
||||
this.tabData.delete(keyObject);
|
||||
}
|
||||
};
|
||||
|
||||
/* global searchInitialized */
|
||||
// This promise is used to wait for the search service to be initialized.
|
||||
// None of the code in the WebExtension modules requests that initialization.
|
||||
|
|
|
@ -25,10 +25,11 @@ this.messageDisplayAction = class extends ToolbarButtonAPI {
|
|||
close() {
|
||||
super.close();
|
||||
messageDisplayActionMap.delete(this.extension);
|
||||
windowTracker.removeListener("TabSelect", this);
|
||||
}
|
||||
|
||||
constructor(extension) {
|
||||
super(extension);
|
||||
super(extension, global);
|
||||
this.manifest_name = "message_display_action";
|
||||
this.manifestName = "messageDisplayAction";
|
||||
this.windowURLs = [
|
||||
|
@ -37,6 +38,8 @@ this.messageDisplayAction = class extends ToolbarButtonAPI {
|
|||
];
|
||||
this.toolboxId = "header-view-toolbox";
|
||||
this.toolbarId = "header-view-toolbar";
|
||||
|
||||
windowTracker.addListener("TabSelect", this);
|
||||
}
|
||||
|
||||
makeButton(window) {
|
||||
|
|
|
@ -16,6 +16,7 @@ tags = webextensions
|
|||
|
||||
[browser_ext_addressBooksUI.js]
|
||||
[browser_ext_browserAction.js]
|
||||
[browser_ext_browserAction_properties.js]
|
||||
[browser_ext_commands_execute_browser_action.js]
|
||||
[browser_ext_commands_getAll.js]
|
||||
[browser_ext_commands_onCommand.js]
|
||||
|
@ -24,6 +25,7 @@ tags = webextensions
|
|||
[browser_ext_compose_details.js]
|
||||
[browser_ext_compose_onBeforeSend.js]
|
||||
[browser_ext_composeAction.js]
|
||||
[browser_ext_composeAction_properties.js]
|
||||
[browser_ext_mailTabs.js]
|
||||
[browser_ext_menus.js]
|
||||
support-files = data/content.html
|
||||
|
@ -31,6 +33,7 @@ support-files = data/content.html
|
|||
[browser_ext_menus_replace_menu_context.js]
|
||||
[browser_ext_messageDisplay.js]
|
||||
[browser_ext_messageDisplayAction.js]
|
||||
[browser_ext_messageDisplayAction_properties.js]
|
||||
[browser_ext_quickFilter.js]
|
||||
[browser_ext_windows.js]
|
||||
[browser_ext_windows_types.js]
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
/* 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/. */
|
||||
|
||||
add_task(async () => {
|
||||
let account = createAccount();
|
||||
addIdentity(account);
|
||||
let rootFolder = account.incomingServer.rootFolder;
|
||||
|
||||
window.gFolderTreeView.selectFolder(rootFolder);
|
||||
await new Promise(resolve => executeSoon(resolve));
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
background: async () => {
|
||||
async function checkProperty(property, expectedDefault, ...expected) {
|
||||
browser.test.log(
|
||||
`${property}: ${expectedDefault}, ${expected.join(", ")}`
|
||||
);
|
||||
|
||||
browser.test.assertEq(
|
||||
expectedDefault,
|
||||
await browser.browserAction[property]({})
|
||||
);
|
||||
for (let i = 0; i < 3; i++) {
|
||||
browser.test.assertEq(
|
||||
expected[i],
|
||||
await browser.browserAction[property]({ tabId: tabIDs[i] })
|
||||
);
|
||||
}
|
||||
|
||||
await new Promise(resolve => {
|
||||
browser.test.onMessage.addListener(function listener() {
|
||||
browser.test.onMessage.removeListener(listener);
|
||||
resolve();
|
||||
});
|
||||
browser.test.sendMessage("checkProperty", property, expected);
|
||||
});
|
||||
}
|
||||
|
||||
let tabs = await browser.mailTabs.query({});
|
||||
let tabIDs = tabs.map(t => t.id);
|
||||
|
||||
await checkProperty("isEnabled", true, true, true, true);
|
||||
await browser.browserAction.disable();
|
||||
await checkProperty("isEnabled", false, false, false, false);
|
||||
await browser.browserAction.enable(tabIDs[0]);
|
||||
await checkProperty("isEnabled", false, true, false, false);
|
||||
await browser.browserAction.enable();
|
||||
await checkProperty("isEnabled", true, true, true, true);
|
||||
await browser.browserAction.disable();
|
||||
await checkProperty("isEnabled", false, true, false, false);
|
||||
await browser.browserAction.disable(tabIDs[0]);
|
||||
await checkProperty("isEnabled", false, false, false, false);
|
||||
await browser.browserAction.enable();
|
||||
await checkProperty("isEnabled", true, false, true, true);
|
||||
|
||||
await checkProperty(
|
||||
"getTitle",
|
||||
"default",
|
||||
"default",
|
||||
"default",
|
||||
"default"
|
||||
);
|
||||
await browser.browserAction.setTitle({ tabId: tabIDs[2], title: "tab2" });
|
||||
await checkProperty("getTitle", "default", "default", "default", "tab2");
|
||||
await browser.browserAction.setTitle({ title: "new" });
|
||||
await checkProperty("getTitle", "new", "new", "new", "tab2");
|
||||
await browser.browserAction.setTitle({ tabId: tabIDs[1], title: "tab1" });
|
||||
await checkProperty("getTitle", "new", "new", "tab1", "tab2");
|
||||
await browser.browserAction.setTitle({ tabId: tabIDs[2], title: null });
|
||||
await checkProperty("getTitle", "new", "new", "tab1", "new");
|
||||
await browser.browserAction.setTitle({ title: null });
|
||||
await checkProperty("getTitle", "default", "default", "tab1", "default");
|
||||
await browser.browserAction.setTitle({ tabId: tabIDs[1], title: null });
|
||||
await checkProperty(
|
||||
"getTitle",
|
||||
"default",
|
||||
"default",
|
||||
"default",
|
||||
"default"
|
||||
);
|
||||
|
||||
await browser.tabs.remove(tabIDs[0]);
|
||||
await browser.tabs.remove(tabIDs[1]);
|
||||
await browser.tabs.remove(tabIDs[2]);
|
||||
browser.test.notifyPass("finished");
|
||||
},
|
||||
manifest: {
|
||||
applications: {
|
||||
gecko: {
|
||||
id: "test1@mochi.test",
|
||||
},
|
||||
},
|
||||
browser_action: {
|
||||
default_title: "default",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
|
||||
let tabmail = document.getElementById("tabmail");
|
||||
tabmail.openTab("folder", { folder: rootFolder, background: false });
|
||||
tabmail.openTab("folder", { folder: rootFolder, background: false });
|
||||
|
||||
let mailTabs = tabmail.tabInfo;
|
||||
is(mailTabs.length, 3);
|
||||
|
||||
let button = document.getElementById(
|
||||
"test1_mochi_test-browserAction-toolbarbutton"
|
||||
);
|
||||
|
||||
extension.onMessage("checkProperty", async (property, expected) => {
|
||||
for (let i = 0; i < 3; i++) {
|
||||
tabmail.switchToTab(mailTabs[i]);
|
||||
await new Promise(resolve => requestAnimationFrame(resolve));
|
||||
switch (property) {
|
||||
case "isEnabled":
|
||||
is(button.disabled, !expected[i], `button ${i} enabled state`);
|
||||
break;
|
||||
case "getTitle":
|
||||
is(button.getAttribute("label"), expected[i], `button ${i} label`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
extension.sendMessage();
|
||||
});
|
||||
|
||||
await extension.awaitFinish("finished");
|
||||
await extension.unload();
|
||||
|
||||
tabmail.closeTab(mailTabs[2]);
|
||||
tabmail.closeTab(mailTabs[1]);
|
||||
is(tabmail.tabInfo.length, 1);
|
||||
});
|
|
@ -0,0 +1,130 @@
|
|||
/* 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/. */
|
||||
|
||||
add_task(async () => {
|
||||
let account = createAccount();
|
||||
addIdentity(account);
|
||||
let rootFolder = account.incomingServer.rootFolder;
|
||||
|
||||
window.gFolderTreeView.selectFolder(rootFolder);
|
||||
await new Promise(resolve => executeSoon(resolve));
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
background: async () => {
|
||||
async function checkProperty(property, expectedDefault, ...expected) {
|
||||
browser.test.log(
|
||||
`${property}: ${expectedDefault}, ${expected.join(", ")}`
|
||||
);
|
||||
|
||||
browser.test.assertEq(
|
||||
expectedDefault,
|
||||
await browser.composeAction[property]({})
|
||||
);
|
||||
for (let i = 0; i < 3; i++) {
|
||||
browser.test.assertEq(
|
||||
expected[i],
|
||||
await browser.composeAction[property]({ tabId: tabIDs[i] })
|
||||
);
|
||||
}
|
||||
|
||||
await new Promise(resolve => {
|
||||
browser.test.onMessage.addListener(function listener() {
|
||||
browser.test.onMessage.removeListener(listener);
|
||||
resolve();
|
||||
});
|
||||
browser.test.sendMessage("checkProperty", property, expected);
|
||||
});
|
||||
}
|
||||
|
||||
await browser.compose.beginNew();
|
||||
await browser.compose.beginNew();
|
||||
await browser.compose.beginNew();
|
||||
let windows = await browser.windows.getAll({
|
||||
populate: true,
|
||||
windowTypes: ["messageCompose"],
|
||||
});
|
||||
let tabIDs = windows.map(w => w.tabs[0].id);
|
||||
|
||||
await checkProperty("isEnabled", true, true, true, true);
|
||||
await browser.composeAction.disable();
|
||||
await checkProperty("isEnabled", false, false, false, false);
|
||||
await browser.composeAction.enable(tabIDs[0]);
|
||||
await checkProperty("isEnabled", false, true, false, false);
|
||||
await browser.composeAction.enable();
|
||||
await checkProperty("isEnabled", true, true, true, true);
|
||||
await browser.composeAction.disable();
|
||||
await checkProperty("isEnabled", false, true, false, false);
|
||||
await browser.composeAction.disable(tabIDs[0]);
|
||||
await checkProperty("isEnabled", false, false, false, false);
|
||||
await browser.composeAction.enable();
|
||||
await checkProperty("isEnabled", true, false, true, true);
|
||||
|
||||
await checkProperty(
|
||||
"getTitle",
|
||||
"default",
|
||||
"default",
|
||||
"default",
|
||||
"default"
|
||||
);
|
||||
await browser.composeAction.setTitle({ tabId: tabIDs[2], title: "tab2" });
|
||||
await checkProperty("getTitle", "default", "default", "default", "tab2");
|
||||
await browser.composeAction.setTitle({ title: "new" });
|
||||
await checkProperty("getTitle", "new", "new", "new", "tab2");
|
||||
await browser.composeAction.setTitle({ tabId: tabIDs[1], title: "tab1" });
|
||||
await checkProperty("getTitle", "new", "new", "tab1", "tab2");
|
||||
await browser.composeAction.setTitle({ tabId: tabIDs[2], title: null });
|
||||
await checkProperty("getTitle", "new", "new", "tab1", "new");
|
||||
await browser.composeAction.setTitle({ title: null });
|
||||
await checkProperty("getTitle", "default", "default", "tab1", "default");
|
||||
await browser.composeAction.setTitle({ tabId: tabIDs[1], title: null });
|
||||
await checkProperty(
|
||||
"getTitle",
|
||||
"default",
|
||||
"default",
|
||||
"default",
|
||||
"default"
|
||||
);
|
||||
|
||||
await browser.tabs.remove(tabIDs[0]);
|
||||
await browser.tabs.remove(tabIDs[1]);
|
||||
await browser.tabs.remove(tabIDs[2]);
|
||||
browser.test.notifyPass("finished");
|
||||
},
|
||||
manifest: {
|
||||
applications: {
|
||||
gecko: {
|
||||
id: "test1@mochi.test",
|
||||
},
|
||||
},
|
||||
compose_action: {
|
||||
default_title: "default",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
extension.onMessage("checkProperty", async (property, expected) => {
|
||||
let composeWindows = [...Services.wm.getEnumerator("msgcompose")];
|
||||
is(composeWindows.length, 3);
|
||||
|
||||
for (let i = 0; i < 3; i++) {
|
||||
let button = composeWindows[i].document.getElementById(
|
||||
"test1_mochi_test-composeAction-toolbarbutton"
|
||||
);
|
||||
switch (property) {
|
||||
case "isEnabled":
|
||||
is(button.disabled, !expected[i], `button ${i} enabled state`);
|
||||
break;
|
||||
case "getTitle":
|
||||
is(button.getAttribute("label"), expected[i], `button ${i} label`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
extension.sendMessage();
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
await extension.awaitFinish("finished");
|
||||
await extension.unload();
|
||||
});
|
|
@ -0,0 +1,174 @@
|
|||
/* 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/. */
|
||||
|
||||
add_task(async () => {
|
||||
let account = createAccount();
|
||||
addIdentity(account);
|
||||
let rootFolder = account.incomingServer.rootFolder;
|
||||
rootFolder.createSubfolder("test", null);
|
||||
let folder = rootFolder.getChildNamed("test");
|
||||
createMessages(folder, 1);
|
||||
|
||||
window.gFolderTreeView.selectFolder(folder);
|
||||
window.gFolderDisplay.selectViewIndex(0);
|
||||
|
||||
window.MsgOpenSelectedMessages();
|
||||
window.MsgOpenNewWindowForMessage();
|
||||
await new Promise(resolve => executeSoon(resolve));
|
||||
|
||||
let extension = ExtensionTestUtils.loadExtension({
|
||||
background: async () => {
|
||||
async function checkProperty(property, expectedDefault, ...expected) {
|
||||
browser.test.log(
|
||||
`${property}: ${expectedDefault}, ${expected.join(", ")}`
|
||||
);
|
||||
|
||||
browser.test.assertEq(
|
||||
expectedDefault,
|
||||
await browser.messageDisplayAction[property]({})
|
||||
);
|
||||
for (let i = 0; i < 3; i++) {
|
||||
browser.test.assertEq(
|
||||
expected[i],
|
||||
await browser.messageDisplayAction[property]({ tabId: tabIDs[i] })
|
||||
);
|
||||
}
|
||||
|
||||
await new Promise(resolve => {
|
||||
browser.test.onMessage.addListener(function listener() {
|
||||
browser.test.onMessage.removeListener(listener);
|
||||
resolve();
|
||||
});
|
||||
browser.test.sendMessage("checkProperty", property, expected);
|
||||
});
|
||||
}
|
||||
|
||||
let tabs = await browser.tabs.query({});
|
||||
browser.test.assertEq(3, tabs.length);
|
||||
let tabIDs = tabs.map(t => t.id);
|
||||
|
||||
await checkProperty("isEnabled", true, true, true, true);
|
||||
await browser.messageDisplayAction.disable();
|
||||
await checkProperty("isEnabled", false, false, false, false);
|
||||
await browser.messageDisplayAction.enable(tabIDs[0]);
|
||||
await checkProperty("isEnabled", false, true, false, false);
|
||||
await browser.messageDisplayAction.enable();
|
||||
await checkProperty("isEnabled", true, true, true, true);
|
||||
await browser.messageDisplayAction.disable();
|
||||
await checkProperty("isEnabled", false, true, false, false);
|
||||
await browser.messageDisplayAction.disable(tabIDs[0]);
|
||||
await checkProperty("isEnabled", false, false, false, false);
|
||||
await browser.messageDisplayAction.enable();
|
||||
await checkProperty("isEnabled", true, false, true, true);
|
||||
|
||||
await checkProperty(
|
||||
"getTitle",
|
||||
"default",
|
||||
"default",
|
||||
"default",
|
||||
"default"
|
||||
);
|
||||
await browser.messageDisplayAction.setTitle({
|
||||
tabId: tabIDs[2],
|
||||
title: "tab2",
|
||||
});
|
||||
await checkProperty("getTitle", "default", "default", "default", "tab2");
|
||||
await browser.messageDisplayAction.setTitle({ title: "new" });
|
||||
await checkProperty("getTitle", "new", "new", "new", "tab2");
|
||||
await browser.messageDisplayAction.setTitle({
|
||||
tabId: tabIDs[1],
|
||||
title: "tab1",
|
||||
});
|
||||
await checkProperty("getTitle", "new", "new", "tab1", "tab2");
|
||||
await browser.messageDisplayAction.setTitle({
|
||||
tabId: tabIDs[2],
|
||||
title: null,
|
||||
});
|
||||
await checkProperty("getTitle", "new", "new", "tab1", "new");
|
||||
await browser.messageDisplayAction.setTitle({ title: null });
|
||||
await checkProperty("getTitle", "default", "default", "tab1", "default");
|
||||
await browser.messageDisplayAction.setTitle({
|
||||
tabId: tabIDs[1],
|
||||
title: null,
|
||||
});
|
||||
await checkProperty(
|
||||
"getTitle",
|
||||
"default",
|
||||
"default",
|
||||
"default",
|
||||
"default"
|
||||
);
|
||||
|
||||
await browser.tabs.remove(tabIDs[0]);
|
||||
await browser.tabs.remove(tabIDs[1]);
|
||||
await browser.tabs.remove(tabIDs[2]);
|
||||
browser.test.notifyPass("finished");
|
||||
},
|
||||
manifest: {
|
||||
applications: {
|
||||
gecko: {
|
||||
id: "test1@mochi.test",
|
||||
},
|
||||
},
|
||||
message_display_action: {
|
||||
default_title: "default",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await extension.startup();
|
||||
|
||||
let tabmail = document.getElementById("tabmail");
|
||||
let mainWindowTabs = tabmail.tabInfo;
|
||||
is(mainWindowTabs.length, 2);
|
||||
|
||||
let mainWindowButton = document.getElementById(
|
||||
"test1_mochi_test-messageDisplayAction-toolbarbutton"
|
||||
);
|
||||
|
||||
let messageWindow = Services.wm.getMostRecentWindow("mail:messageWindow");
|
||||
let messageWindowButton = messageWindow.document.getElementById(
|
||||
"test1_mochi_test-messageDisplayAction-toolbarbutton"
|
||||
);
|
||||
|
||||
extension.onMessage("checkProperty", async (property, expected) => {
|
||||
function checkButton(button, expectedIndex) {
|
||||
switch (property) {
|
||||
case "isEnabled":
|
||||
is(
|
||||
button.disabled,
|
||||
!expected[expectedIndex],
|
||||
`button ${expectedIndex} enabled state`
|
||||
);
|
||||
break;
|
||||
case "getTitle":
|
||||
is(
|
||||
button.getAttribute("label"),
|
||||
expected[expectedIndex],
|
||||
`button ${expectedIndex} label`
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < 2; i++) {
|
||||
tabmail.switchToTab(mainWindowTabs[i]);
|
||||
await new Promise(resolve => requestAnimationFrame(resolve));
|
||||
checkButton(mainWindowButton, i);
|
||||
}
|
||||
checkButton(messageWindowButton, 2);
|
||||
|
||||
extension.sendMessage();
|
||||
});
|
||||
|
||||
await extension.awaitFinish("finished");
|
||||
await extension.unload();
|
||||
|
||||
messageWindow.close();
|
||||
tabmail.closeTab(mainWindowTabs[1]);
|
||||
is(tabmail.tabInfo.length, 1);
|
||||
|
||||
document.getElementById("folderTree").focus();
|
||||
await new Promise(resolve => executeSoon(resolve));
|
||||
});
|
Загрузка…
Ссылка в новой задаче