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: */
/* global gBrowser SessionStore */
"use strict";
const triggeringPrincipal_base64 = E10SUtils.SERIALIZED_SYSTEMPRINCIPAL;
let lazyTabState = {
entries: [
{
triggeringPrincipal_base64,
title: "Example Domain",
},
],
};
add_task(async function test_discarded() {
let extension = ExtensionTestUtils.loadExtension({
manifest: {
permissions: ["tabs", "webNavigation"],
},
background() {
browser.webNavigation.onCompleted.addListener(
async details => {
browser.test.log(`webNav onCompleted received for ${details.tabId}`);
let updatedTab = await browser.tabs.get(details.tabId);
browser.test.assertEq(
false,
updatedTab.discarded,
"lazy to non-lazy update discard property"
);
browser.test.notifyPass("test-finished");
},
{ url: [{ hostContains: "example.com" }] }
);
browser.tabs.onCreated.addListener(function (tab) {
browser.test.assertEq(
true,
tab.discarded,
"non-lazy tab onCreated discard property"
);
browser.tabs.update(tab.id, { active: true });
});
},
});
await extension.startup();
let testTab = BrowserTestUtils.addTab(gBrowser, "about:blank", {
createLazyBrowser: true,
});
SessionStore.setTabState(testTab, lazyTabState);
await extension.awaitFinish("test-finished");
await extension.unload();
BrowserTestUtils.removeTab(testTab);
});
// Regression test for Bug 1819794.
add_task(async function test_create_discarded_with_cookieStoreId() {
let extension = ExtensionTestUtils.loadExtension({
manifest: {
permissions: ["contextualIdentities", "cookies"],
},
async background() {
const [{ cookieStoreId }] = await browser.contextualIdentities.query({});
browser.test.assertEq(
"firefox-container-1",
cookieStoreId,
"Got expected cookieStoreId"
);
await browser.tabs.create({
url: `http://example.com/#${cookieStoreId}`,
cookieStoreId,
discarded: true,
});
await browser.tabs.create({
discarded: true,
});
},
// Needed by ExtensionSettingsStore (as a side-effect of contextualIdentities permission).
useAddonManager: "temporary",
});
const tabContainerPromise = BrowserTestUtils.waitForEvent(
window,
"TabOpen",
false,
evt => {
return evt.target.getAttribute("usercontextid", "1");
}
).then(evt => evt.target);
const tabDefaultPromise = BrowserTestUtils.waitForEvent(
window,
"TabOpen",
false,
evt => {
return !evt.target.hasAttribute("usercontextid");
}
).then(evt => evt.target);
await extension.startup();
const tabContainer = await tabContainerPromise;
ok(
tabContainer.hasAttribute("pending"),
"new container tab should be discarded"
);
const tabContainerState = SessionStore.getTabState(tabContainer);
is(
JSON.parse(tabContainerState).userContextId,
1,
`Expect a userContextId associated to the new discarded container tab: ${tabContainerState}`
);
const tabDefault = await tabDefaultPromise;
ok(
tabDefault.hasAttribute("pending"),
"new non-container tab should be discarded"
);
const tabDefaultState = SessionStore.getTabState(tabDefault);
is(
JSON.parse(tabDefaultState).userContextId,
0,
`Expect userContextId 0 associated to the new discarded non-container tab: ${tabDefaultState}`
);
BrowserTestUtils.removeTab(tabContainer);
BrowserTestUtils.removeTab(tabDefault);
await extension.unload();
});
// If discard is called immediately after creating a new tab, the new tab may not have loaded,
// and the sessionstore for that tab is not ready for discarding. The result was a corrupted
// sessionstore for the tab, which when the tab was activated, resulted in a tab with partial
// state.
add_task(async function test_create_then_discard() {
let extension = ExtensionTestUtils.loadExtension({
manifest: {
permissions: ["tabs", "webNavigation"],
},
background: async function () {
let createdTab;
browser.tabs.onUpdated.addListener((tabId, updatedInfo) => {
if (!updatedInfo.discarded) {
return;
}
browser.webNavigation.onCompleted.addListener(
async details => {
browser.test.assertEq(
createdTab.id,
details.tabId,
"created tab navigation is completed"
);
let activeTab = await browser.tabs.get(details.tabId);
browser.test.assertEq(
details.url,
"created tab url is correct"
);
browser.test.assertEq(
activeTab.url,
"created tab url is correct"
);
browser.tabs.remove(details.tabId);
browser.test.notifyPass("test-finished");
},
{ url: [{ hostContains: "example.com" }] }
);
browser.tabs.update(tabId, { active: true });
});
createdTab = await browser.tabs.create({
active: false,
});
browser.tabs.discard(createdTab.id);
},
});
await extension.startup();
await extension.awaitFinish("test-finished");
await extension.unload();
});
add_task(async function test_create_discarded() {
let extension = ExtensionTestUtils.loadExtension({
manifest: {
permissions: ["tabs", "webNavigation"],
},
background() {
let tabOpts = {
active: false,
discarded: true,
title: "discarded tab",
};
browser.webNavigation.onCompleted.addListener(
async details => {
let activeTab = await browser.tabs.get(details.tabId);
browser.test.assertEq(
tabOpts.url,
activeTab.url,
"restored tab url matches active tab url"
);
browser.test.assertEq(
"mochitest index /",
activeTab.title,
"restored tab title is correct"
);
browser.tabs.remove(details.tabId);
browser.test.notifyPass("test-finished");
},
{ url: [{ hostContains: "example.com" }] }
);
browser.tabs.onCreated.addListener(tab => {
browser.test.assertEq(
tabOpts.active,
tab.active,
"lazy tab is not active"
);
browser.test.assertEq(
tabOpts.discarded,
tab.discarded,
"lazy tab is discarded"
);
browser.test.assertEq(tabOpts.url, tab.url, "lazy tab url is correct");
browser.test.assertEq(
tabOpts.title,
tab.title,
"lazy tab title is correct"
);
browser.tabs.update(tab.id, { active: true });
});
browser.tabs.create(tabOpts);
},
});
await extension.startup();
await extension.awaitFinish("test-finished");
await extension.unload();
});
add_task(async function test_discarded_private_tab_restored() {
let extension = ExtensionTestUtils.loadExtension({
incognitoOverride: "spanning",
background() {
let isDiscarding = false;
browser.tabs.onUpdated.addListener(
async function listener(tabId, changeInfo, tab) {
const { active, discarded, incognito } = tab;
if (!incognito || active || discarded || isDiscarding) {
return;
}
// Remove the onUpdated listener to prevent intermittent failure
// to be hit if the listener gets called again for unrelated
// tabs.onUpdated events that may get fired after the test case got
// the tab-discarded test message that was expecting.
isDiscarding = true;
browser.tabs.onUpdated.removeListener(listener);
browser.test.log(
`Test extension discarding ${tabId}: ${JSON.stringify(changeInfo)}`
);
await browser.tabs.discard(tabId);
browser.test.sendMessage("tab-discarded");
},
{ properties: ["status"] }
);
},
});
// Open a private browsing window.
const privateWin = await BrowserTestUtils.openNewBrowserWindow({
private: true,
});
await extension.startup();
const newTab = await BrowserTestUtils.addTab(
privateWin.gBrowser,
);
await extension.awaitMessage("tab-discarded");
is(newTab.getAttribute("pending"), "true", "private tab should be discarded");
const promiseTabLoaded = BrowserTestUtils.browserLoaded(newTab.linkedBrowser);
info("Switching to the discarded background tab");
await BrowserTestUtils.switchTab(privateWin.gBrowser, newTab);
info("Wait for the restored tab to complete loading");
await promiseTabLoaded;
is(
newTab.hasAttribute("pending"),
false,
"discarded private tab should have been restored"
);
is(
newTab.linkedBrowser.currentURI.spec,
"Got the expected url on the restored tab"
);
await extension.unload();
await BrowserTestUtils.closeWindow(privateWin);
});
add_task(async function test_update_discarded() {
let extension = ExtensionTestUtils.loadExtension({
manifest: {
permissions: ["tabs", "<all_urls>"],
},
background() {
browser.test.onMessage.addListener(async msg => {
let [tab] = await browser.tabs.query({ url: "http://example.com/" });
if (msg == "update") {
await browser.tabs.update(tab.id, { url: "https://example.com/" });
} else {
browser.test.fail(`Unexpected message received: ${msg}`);
}
});
browser.test.sendMessage("ready");
},
});
await extension.startup();
await extension.awaitMessage("ready");
let lazyTab = BrowserTestUtils.addTab(gBrowser, "http://example.com/", {
createLazyBrowser: true,
lazyTabTitle: "Example Domain",
});
let tabBrowserInsertedPromise = BrowserTestUtils.waitForEvent(
lazyTab,
"TabBrowserInserted"
);
SimpleTest.waitForExplicitFinish();
let waitForConsole = new Promise(resolve => {
SimpleTest.monitorConsole(resolve, [
{
message:
/Lazy browser prematurely inserted via 'loadURI' property access:/,
forbid: true,
},
]);
});
extension.sendMessage("update");
await tabBrowserInsertedPromise;
await BrowserTestUtils.waitForBrowserStateChange(
lazyTab.linkedBrowser,
stateFlags => {
return (
stateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW &&
stateFlags & Ci.nsIWebProgressListener.STATE_STOP
);
}
);
await TestUtils.waitForTick();
BrowserTestUtils.removeTab(lazyTab);
await extension.unload();
SimpleTest.endMonitorConsole();
await waitForConsole;
});