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";
loadTestSubscript("head_pageAction.js");
add_task(async function testTabSwitchContext() {
await runTests({
manifest: {
name: "Foo Extension",
page_action: {
default_icon: "default.png",
default_popup: "__MSG_popup__",
default_title: "Default __MSG_title__ \u263a",
},
default_locale: "en",
permissions: ["tabs"],
},
files: {
"_locales/en/messages.json": {
popup: {
message: "default.html",
description: "Popup",
},
title: {
message: "Title",
description: "Title",
},
},
"_locales/es_ES/messages.json": {
popup: {
message: "default.html",
description: "Popup",
},
title: {
message: "T\u00edtulo",
description: "Title",
},
},
"default.png": imageBuffer,
"1.png": imageBuffer,
"2.png": imageBuffer,
},
getTests: function (tabs) {
let details = [
{
icon: browser.runtime.getURL("default.png"),
popup: browser.runtime.getURL("default.html"),
title: "Default T\u00edtulo \u263a",
},
{
icon: browser.runtime.getURL("1.png"),
popup: browser.runtime.getURL("default.html"),
title: "Default T\u00edtulo \u263a",
},
{
icon: browser.runtime.getURL("2.png"),
popup: browser.runtime.getURL("2.html"),
title: "Title 2",
},
{ icon: defaultIcon, popup: "", title: "" },
];
let promiseTabLoad = details => {
return new Promise(resolve => {
browser.tabs.onUpdated.addListener(function listener(tabId, changed) {
if (tabId == details.id && changed.url == details.url) {
browser.tabs.onUpdated.removeListener(listener);
resolve();
}
});
});
};
return [
expect => {
browser.test.log("Initial state. No icon visible.");
expect(null);
},
async expect => {
browser.test.log(
"Show the icon on the first tab, expect default properties."
);
await browser.pageAction.show(tabs[0]);
expect(details[0]);
},
expect => {
browser.test.log(
"Change the icon. Expect default properties excluding the icon."
);
browser.pageAction.setIcon({ tabId: tabs[0], path: "1.png" });
expect(details[1]);
},
async expect => {
browser.test.log("Create a new tab. No icon visible.");
let tab = await browser.tabs.create({
active: true,
url: "about:blank?0",
});
tabs.push(tab.id);
expect(null);
},
async expect => {
browser.test.log("Await tab load. No icon visible.");
let promise = promiseTabLoad({ id: tabs[1], url: "about:blank?0" });
let { url } = await browser.tabs.get(tabs[1]);
if (url === "about:blank") {
await promise;
}
expect(null);
},
async expect => {
browser.test.log("Change properties. Expect new properties.");
let tabId = tabs[1];
await browser.pageAction.show(tabId);
browser.pageAction.setIcon({ tabId, path: "2.png" });
browser.pageAction.setPopup({ tabId, popup: "2.html" });
browser.pageAction.setTitle({ tabId, title: "Title 2" });
expect(details[2]);
},
async expect => {
browser.test.log("Change the hash. Expect same properties.");
let promise = promiseTabLoad({
id: tabs[1],
url: "about:blank?0#ref",
});
browser.tabs.update(tabs[1], { url: "about:blank?0#ref" });
await promise;
expect(details[2]);
},
expect => {
browser.test.log(
"Set empty string values. Expect empty strings but default icon."
);
browser.pageAction.setIcon({ tabId: tabs[1], path: "" });
browser.pageAction.setPopup({ tabId: tabs[1], popup: "" });
browser.pageAction.setTitle({ tabId: tabs[1], title: "" });
expect(details[3]);
},
expect => {
browser.test.log("Clear the values. Expect default ones.");
browser.pageAction.setIcon({ tabId: tabs[1], path: null });
browser.pageAction.setPopup({ tabId: tabs[1], popup: null });
browser.pageAction.setTitle({ tabId: tabs[1], title: null });
expect(details[0]);
},
async expect => {
browser.test.log("Navigate to a new page. Expect icon hidden.");
// TODO: This listener should not be necessary, but the |tabs.update|
// callback currently fires too early in e10s windows.
let promise = promiseTabLoad({ id: tabs[1], url: "about:blank?1" });
browser.tabs.update(tabs[1], { url: "about:blank?1" });
await promise;
expect(null);
},
async expect => {
browser.test.log("Show the icon. Expect default properties again.");
await browser.pageAction.show(tabs[1]);
expect(details[0]);
},
async expect => {
browser.test.log(
"Switch back to the first tab. Expect previously set properties."
);
await browser.tabs.update(tabs[0], { active: true });
expect(details[1]);
},
async expect => {
browser.test.log(
"Hide the icon on tab 2. Switch back, expect hidden."
);
await browser.pageAction.hide(tabs[1]);
await browser.tabs.update(tabs[1], { active: true });
expect(null);
},
async expect => {
browser.test.log(
"Switch back to tab 1. Expect previous results again."
);
await browser.tabs.remove(tabs[1]);
expect(details[1]);
},
async expect => {
browser.test.log("Hide the icon. Expect hidden.");
await browser.pageAction.hide(tabs[0]);
expect(null);
},
async expect => {
browser.test.assertRejects(
browser.pageAction.setPopup({
tabId: tabs[0],
popup: "about:addons",
}),
/Access denied for URL about:addons/,
"unable to set popup to about:addons"
);
expect(null);
},
];
},
});
});
add_task(async function testMultipleWindows() {
// Disable newtab preloading, so that the tabs.create call below will always
// trigger a new load that can be detected by webNavigation.onCompleted.
await SpecialPowers.pushPrefEnv({
set: [["browser.newtab.preload", false]],
});
await runTests({
manifest: {
page_action: {
default_icon: "default.png",
default_popup: "default.html",
default_title: "Default Title",
},
permissions: ["webNavigation"],
},
files: {
"default.png": imageBuffer,
"tab.png": imageBuffer,
},
getTests: function (tabs, windows) {
let details = [
{
icon: browser.runtime.getURL("default.png"),
popup: browser.runtime.getURL("default.html"),
title: "Default Title",
},
{
icon: browser.runtime.getURL("tab.png"),
popup: browser.runtime.getURL("tab.html"),
title: "tab",
},
];
function promiseWebNavigationCompleted(url) {
return new Promise(resolve => {
// The pageAction visibility state is reset when the location changes.
// The webNavigation.onCompleted event is triggered when that happens.
browser.webNavigation.onCompleted.addListener(
function listener() {
browser.webNavigation.onCompleted.removeListener(listener);
resolve();
},
{
url: [{ urlEquals: url }],
}
);
});
}
return [
async expect => {
browser.test.log("Create a new tab, expect hidden pageAction.");
let promise = promiseWebNavigationCompleted("about:newtab");
let tab = await browser.tabs.create({ active: true });
await promise;
tabs.push(tab.id);
expect(null);
},
async expect => {
browser.test.log("Show the pageAction, expect default values.");
await browser.pageAction.show(tabs[1]);
expect(details[0]);
},
async expect => {
browser.test.log("Set tab-specific values, expect them.");
await browser.pageAction.setIcon({ tabId: tabs[1], path: "tab.png" });
await browser.pageAction.setPopup({
tabId: tabs[1],
popup: "tab.html",
});
await browser.pageAction.setTitle({ tabId: tabs[1], title: "tab" });
expect(details[1]);
},
async expect => {
browser.test.log("Open a new window, expect hidden pageAction.");
let { id } = await browser.windows.create();
windows.push(id);
expect(null);
},
async expect => {
browser.test.log(
"Move tab from old window to the new one, expect old values."
);
await browser.tabs.move(tabs[1], { windowId: windows[1], index: -1 });
await browser.tabs.update(tabs[1], { active: true });
expect(details[1]);
},
async expect => {
browser.test.log("Close the initial tab of the new window.");
let [{ id }] = await browser.tabs.query({
windowId: windows[1],
index: 0,
});
await browser.tabs.remove(id);
expect(details[1]);
},
async expect => {
browser.test.log(
"Move the previous tab to a 3rd window, the 2nd one will close."
);
await browser.windows.create({ tabId: tabs[1] });
expect(details[1]);
},
async expect => {
browser.test.log("Close the tab, go back to the 1st window.");
await browser.tabs.remove(tabs[1]);
expect(null);
},
];
},
});
await SpecialPowers.popPrefEnv();
});
add_task(async function testNavigationClearsData() {
let url = "http://example.com/";
let default_title = "Default title";
let tab_title = "Tab title";
const {
Management: {
global: { tabTracker },
},
} = ChromeUtils.importESModule("resource://gre/modules/Extension.sys.mjs");
let extension,
tabs = [];
async function addTab(...args) {
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, ...args);
tabs.push(tab);
return tab;
}
async function sendMessage(method, param, expect, msg) {
extension.sendMessage({ method, param, expect, msg });
await extension.awaitMessage("done");
}
async function expectTabSpecificData(tab, msg) {
let tabId = tabTracker.getId(tab);
await sendMessage("isShown", { tabId }, true, msg);
await sendMessage("getTitle", { tabId }, tab_title, msg);
}
async function expectDefaultData(tab, msg) {
let tabId = tabTracker.getId(tab);
await sendMessage("isShown", { tabId }, false, msg);
await sendMessage("getTitle", { tabId }, default_title, msg);
}
async function setTabSpecificData(tab) {
let tabId = tabTracker.getId(tab);
await expectDefaultData(
tab,
"Expect default data before setting tab-specific data."
);
await sendMessage("show", tabId);
await sendMessage("setTitle", { tabId, title: tab_title });
await expectTabSpecificData(
tab,
"Expect tab-specific data after setting it."
);
}
info("Load a tab before installing the extension");
let tab1 = await addTab(url, true, true);
extension = ExtensionTestUtils.loadExtension({
manifest: {
page_action: { default_title },
},
background: function () {
browser.test.onMessage.addListener(
async ({ method, param, expect, msg }) => {
let result = await browser.pageAction[method](param);
if (expect !== undefined) {
browser.test.assertEq(expect, result, msg);
}
browser.test.sendMessage("done");
}
);
},
});
await extension.startup();
info("Set tab-specific data to the existing tab.");
await setTabSpecificData(tab1);
info("Add a hash. Does not cause navigation.");
await navigateTab(tab1, url + "#hash");
await expectTabSpecificData(
tab1,
"Adding a hash does not clear tab-specific data"
);
info("Remove the hash. Causes navigation.");
await navigateTab(tab1, url);
await expectDefaultData(tab1, "Removing hash clears tab-specific data");
info("Open a new tab, set tab-specific data to it.");
let tab2 = await addTab("about:newtab", false, false);
await setTabSpecificData(tab2);
info("Load a page in that tab.");
await navigateTab(tab2, url);
await expectDefaultData(tab2, "Loading a page clears tab-specific data.");
info("Set tab-specific data.");
await setTabSpecificData(tab2);
info("Push history state. Does not cause navigation.");
await historyPushState(tab2, url + "/path");
await expectTabSpecificData(
tab2,
"history.pushState() does not clear tab-specific data"
);
info("Navigate when the tab is not selected");
gBrowser.selectedTab = tab1;
await navigateTab(tab2, url);
await expectDefaultData(
tab2,
"Navigating clears tab-specific data, even when not selected."
);
for (let tab of tabs) {
BrowserTestUtils.removeTab(tab);
}
await extension.unload();
});