Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
requestLongerTimeout(2);
add_task(async function () {
let win1 = await BrowserTestUtils.openNewBrowserWindow();
await focusWindow(win1);
let extension = ExtensionTestUtils.loadExtension({
manifest: {
permissions: ["tabs"],
content_scripts: [
{
js: ["content-script.js"],
run_at: "document_start",
},
],
},
background: function () {
let pageURL =
let expectedSequence = [
{ status: "loading" },
{ status: "loading", url: pageURL },
{ status: "complete" },
];
let collectedSequence = [];
browser.tabs.onUpdated.addListener(function (tabId, updatedInfo) {
// onUpdated also fires with updatedInfo.faviconUrl, so explicitly
// check for updatedInfo.status before recording the event.
if ("status" in updatedInfo) {
collectedSequence.push(updatedInfo);
}
});
browser.runtime.onMessage.addListener(function () {
if (collectedSequence.length !== expectedSequence.length) {
browser.test.assertEq(
JSON.stringify(expectedSequence),
JSON.stringify(collectedSequence),
"got unexpected number of updateInfo data"
);
} else {
for (let i = 0; i < expectedSequence.length; i++) {
browser.test.assertEq(
expectedSequence[i].status,
collectedSequence[i].status,
"check updatedInfo status"
);
if (expectedSequence[i].url || collectedSequence[i].url) {
browser.test.assertEq(
expectedSequence[i].url,
collectedSequence[i].url,
"check updatedInfo url"
);
}
}
}
browser.test.notifyPass("tabs.onUpdated");
});
browser.tabs.create({ url: pageURL });
},
files: {
"content-script.js": `
window.addEventListener("message", function(evt) {
if (evt.data == "frame-updated") {
browser.runtime.sendMessage("load-completed");
}
}, true);
`,
},
});
await Promise.all([
extension.startup(),
extension.awaitFinish("tabs.onUpdated"),
]);
await extension.unload();
await BrowserTestUtils.closeWindow(win1);
});
async function do_test_update(background, withPermissions = true) {
let win1 = await BrowserTestUtils.openNewBrowserWindow();
await focusWindow(win1);
let manifest = {};
if (withPermissions) {
manifest.permissions = ["tabs", "http://mochi.test/"];
}
let extension = ExtensionTestUtils.loadExtension({ manifest, background });
await extension.startup();
await extension.awaitFinish("finish");
await extension.unload();
await BrowserTestUtils.closeWindow(win1);
}
add_task(async function test_pinned() {
await do_test_update(function background() {
// Create a new tab for testing update.
browser.tabs.create({}, function (tab) {
browser.tabs.onUpdated.addListener(function onUpdated(tabId, changeInfo) {
// Check callback
browser.test.assertEq(tabId, tab.id, "Check tab id");
browser.test.log("onUpdate: " + JSON.stringify(changeInfo));
if ("pinned" in changeInfo) {
browser.test.assertTrue(changeInfo.pinned, "Check changeInfo.pinned");
browser.tabs.onUpdated.removeListener(onUpdated);
// Remove created tab.
browser.tabs.remove(tabId);
browser.test.notifyPass("finish");
}
});
browser.tabs.update(tab.id, { pinned: true });
});
});
});
add_task(async function test_unpinned() {
await do_test_update(function background() {
// Create a new tab for testing update.
browser.tabs.create({ pinned: true }, function (tab) {
browser.tabs.onUpdated.addListener(function onUpdated(tabId, changeInfo) {
// Check callback
browser.test.assertEq(tabId, tab.id, "Check tab id");
browser.test.log("onUpdate: " + JSON.stringify(changeInfo));
if ("pinned" in changeInfo) {
browser.test.assertFalse(
changeInfo.pinned,
"Check changeInfo.pinned"
);
browser.tabs.onUpdated.removeListener(onUpdated);
// Remove created tab.
browser.tabs.remove(tabId);
browser.test.notifyPass("finish");
}
});
browser.tabs.update(tab.id, { pinned: false });
});
});
});
add_task(async function test_url() {
await do_test_update(function background() {
// Create a new tab for testing update.
browser.tabs.create({ url: "about:blank?initial_url=1" }, function (tab) {
const expectedUpdatedURL = "about:blank?updated_url=1";
browser.tabs.onUpdated.addListener(function onUpdated(tabId, changeInfo) {
// Wait for the tabs.onUpdated events related to the updated url (because
// there is a good chance that we may still be receiving events related to
// the browser.tabs.create API call above before we are able to start
// loading the new url from the browser.tabs.update API call below).
if ("url" in changeInfo && changeInfo.url === expectedUpdatedURL) {
browser.test.assertEq(
expectedUpdatedURL,
changeInfo.url,
"Got tabs.onUpdated event for the expected url"
);
browser.tabs.onUpdated.removeListener(onUpdated);
// Remove created tab.
browser.tabs.remove(tabId);
browser.test.notifyPass("finish");
}
// Check callback
browser.test.assertEq(tabId, tab.id, "Check tab id");
browser.test.log("onUpdate: " + JSON.stringify(changeInfo));
});
browser.tabs.update(tab.id, { url: expectedUpdatedURL });
});
});
});
add_task(async function test_title() {
await do_test_update(async function background() {
const url =
const tab = await browser.tabs.create({ url });
browser.tabs.onUpdated.addListener(function onUpdated(tabId, changeInfo) {
browser.test.assertEq(tabId, tab.id, "Check tab id");
browser.test.log(`onUpdated: ${JSON.stringify(changeInfo)}`);
if ("title" in changeInfo && changeInfo.title === "New Message (1)") {
browser.test.log("changeInfo.title is correct");
browser.tabs.onUpdated.removeListener(onUpdated);
browser.tabs.remove(tabId);
browser.test.notifyPass("finish");
}
});
browser.tabs.executeScript(tab.id, {
code: "document.title = 'New Message (1)'",
});
});
});
add_task(async function test_without_tabs_permission() {
await do_test_update(async function background() {
const url =
let tab = null;
let count = 0;
browser.tabs.onUpdated.addListener(function onUpdated(tabId, changeInfo) {
// An attention change can happen during tabs.create, so
// we can't compare against tab yet.
if (!("attention" in changeInfo)) {
browser.test.assertEq(tabId, tab.id, "Check tab id");
}
browser.test.log(`onUpdated: ${JSON.stringify(changeInfo)}`);
browser.test.assertFalse(
"url" in changeInfo,
"url should not be included without tabs permission"
);
browser.test.assertFalse(
"favIconUrl" in changeInfo,
"favIconUrl should not be included without tabs permission"
);
browser.test.assertFalse(
"title" in changeInfo,
"title should not be included without tabs permission"
);
if (changeInfo.status == "complete") {
count++;
if (count === 1) {
browser.tabs.reload(tabId);
} else {
browser.test.log("Reload complete");
browser.tabs.onUpdated.removeListener(onUpdated);
browser.tabs.remove(tabId);
browser.test.notifyPass("finish");
}
}
});
tab = await browser.tabs.create({ url });
}, false /* withPermissions */);
});
add_task(async function test_onUpdated_after_onRemoved() {
let extension = ExtensionTestUtils.loadExtension({
manifest: {
permissions: ["tabs"],
},
async background() {
const url =
let removed = false;
let tab;
// If remove happens fast and we never receive onUpdated, that is ok, but
// we never want to receive onUpdated after onRemoved.
browser.tabs.onUpdated.addListener(function onUpdated(tabId) {
if (!tab || tab.id !== tabId) {
return;
}
browser.test.assertFalse(
removed,
"tab has not been removed before onUpdated"
);
});
browser.tabs.onRemoved.addListener(tabId => {
if (!tab || tab.id !== tabId) {
return;
}
removed = true;
browser.test.notifyPass("onRemoved");
});
tab = await browser.tabs.create({ url });
browser.tabs.remove(tab.id);
},
});
await extension.startup();
await extension.awaitFinish("onRemoved");
await extension.unload();
});
// Regression test for Bug 1852391.
add_task(async function test_pin_discarded_tab() {
let extension = ExtensionTestUtils.loadExtension({
manifest: {
permissions: ["tabs"],
},
async background() {
const url = "http://mochi.test:8888";
const newTab = await browser.tabs.create({
url,
active: false,
discarded: true,
});
browser.tabs.onUpdated.addListener(
async (tabId, changeInfo) => {
browser.test.assertEq(
tabId,
newTab.id,
"Expect onUpdated to be fired for the expected tab"
);
browser.test.assertEq(
changeInfo.pinned,
true,
"Expect pinned to be set to true"
);
await browser.tabs.remove(newTab.id);
browser.test.notifyPass("onPinned");
},
{ properties: ["pinned"] }
);
await browser.tabs.update(newTab.id, { pinned: true }).catch(err => {
browser.test.fail(`Got unexpected rejection from tabs.update: ${err}`);
browser.test.notifyFail("onPinned");
});
},
});
await extension.startup();
await extension.awaitFinish("onPinned");
await extension.unload();
});
add_task(forceGC);