Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

"use strict";
// This test verifies that the internals for associating requests with tabId
// are only active when a session rule with a tabId rule exists.
//
// There are tests for the logic of tabId matching in the match_tabIds task in
// toolkit/components/extensions/test/xpcshell/test_ext_dnr_testMatchOutcome.js
//
// And there are tests that verify matching with real network requests in
// toolkit/components/extensions/test/mochitest/test_ext_dnr_tabIds.html
const server = createHttpServer({ hosts: ["from", "any", "in", "ex"] });
server.registerPathHandler("/", (req, res) => {
res.setHeader("Access-Control-Allow-Origin", "*");
});
let gTabLookupSpy;
add_setup(async () => {
Services.prefs.setBoolPref("extensions.manifestV3.enabled", true);
Services.prefs.setBoolPref("extensions.dnr.enabled", true);
// Install a spy on WebRequest.getTabIdForChannelWrapper.
const { WebRequest } = ChromeUtils.importESModule(
"resource://gre/modules/WebRequest.sys.mjs"
);
const { sinon } = ChromeUtils.importESModule(
);
gTabLookupSpy = sinon.spy(WebRequest, "getTabIdForChannelWrapper");
await ExtensionTestUtils.startAddonManager();
});
function numberOfTabLookupsSinceLastCheck() {
let result = gTabLookupSpy.callCount;
gTabLookupSpy.resetHistory();
return result;
}
// This test checks that WebRequest.getTabIdForChannelWrapper is only called
// when there are any registered tabId/excludedTabIds rules. Moreover, it
// verifies that after unloading (reloading) the extension, that the method is
// still not called unnecessarily.
add_task(async function getTabIdForChannelWrapper_only_called_when_needed() {
async function background() {
const RULE_ANY_TAB_ID = {
id: 1,
condition: { requestDomains: ["from"] },
action: { type: "redirect", redirect: { url: "http://any/" } },
};
const RULE_INCLUDE_TAB_ID = {
id: 2,
condition: { requestDomains: ["from"], tabIds: [-1] },
action: { type: "redirect", redirect: { url: "http://in/" } },
priority: 2,
};
const RULE_EXCLUDE_TAB_ID = {
id: 3,
condition: { requestDomains: ["from"], excludedTabIds: [-1] },
action: { type: "redirect", redirect: { url: "http://ex/" } },
priority: 2,
};
async function promiseOneMessage(messageName) {
return new Promise(resolve => {
browser.test.onMessage.addListener(function listener(msg, result) {
if (messageName === msg) {
browser.test.onMessage.removeListener(listener);
resolve(result);
}
});
});
}
async function numberOfTabLookupsSinceLastCheck() {
let promise = promiseOneMessage("tabLookups");
browser.test.sendMessage("getTabLookups");
return promise;
}
async function testFetchUrl(url, expectedUrl, expectedCount, description) {
let res = await fetch(url);
browser.test.assertEq(expectedUrl, res.url, `Final URL for ${url}`);
browser.test.assertEq(
expectedCount,
await numberOfTabLookupsSinceLastCheck(),
`Expected number of tab lookups - ${url} - ${description}`
);
}
const startupCountPromise = promiseOneMessage("extensionStartupCount");
browser.test.sendMessage("extensionStarted");
const startupCount = await startupCountPromise;
if (startupCount !== 0) {
browser.test.assertEq(1, startupCount, "Extension restarted once");
// Note: declarativeNetRequest.updateSessionRules is intentionally not
// called here, because we want to verify that upon unloading the
// extension, that the tabId lookup logic was properly cleaned up,
// i.e. that NetworkIntegration.maybeUpdateTabIdChecker() was called.
await testFetchUrl(
0,
"No lookup because session rules should have disappeared at reload"
);
browser.test.assertDeepEq(
[],
await browser.declarativeNetRequest.getSessionRules(),
"The session rules have indeed been cleared upon reload."
);
browser.test.sendMessage("test_completed_after_reload");
return;
}
browser.test.assertEq(
0,
await numberOfTabLookupsSinceLastCheck(),
"Initially, no tab lookups"
);
await testFetchUrl(
0,
"No tab lookups without any registered DNR rules"
);
await browser.declarativeNetRequest.updateSessionRules({
addRules: [RULE_ANY_TAB_ID],
});
// Active rules now: RULE_ANY_TAB_ID
await testFetchUrl(
0,
"No tab lookups when only rule has no tabIds/excludedTabIds conditions"
);
await browser.declarativeNetRequest.updateSessionRules({
addRules: [RULE_EXCLUDE_TAB_ID],
});
// Active rules now: RULE_ANY_TAB_ID, RULE_EXCLUDE_TAB_ID
await testFetchUrl(
// should be "any" instead of "ex" because excludedTabIds: [-1] should
// exclude the background.
2, // initial request + redirect request.
"Expected tabId lookup when a tabId rule is registered"
);
await browser.declarativeNetRequest.updateSessionRules({
removeRuleIds: [RULE_ANY_TAB_ID.id],
});
// Active rules now: RULE_EXCLUDE_TAB_ID
await testFetchUrl(
// Not redirected to "ex" because excludedTabIds: [-1] does not match the
// background that has tabId -1.
1,
"Expected lookup after unregistering unrelated rule, keeping tabId rule"
);
await browser.declarativeNetRequest.updateSessionRules({
addRules: [RULE_INCLUDE_TAB_ID],
});
// Active rules now: RULE_EXCLUDE_TAB_ID, RULE_INCLUDE_TAB_ID
await testFetchUrl(
2, // initial request + redirect request.
"Expecting lookup because of 2 DNR rules with tabId and excludedTabIds"
);
await browser.declarativeNetRequest.updateSessionRules({
removeRuleIds: [RULE_EXCLUDE_TAB_ID.id],
});
// Active rules now: RULE_INCLUDE_TAB_ID
await testFetchUrl(
2, // initial request + redirect request.
"Expecting lookup because of remaining tabId DNR rule"
);
await browser.declarativeNetRequest.updateSessionRules({
removeRuleIds: [RULE_INCLUDE_TAB_ID.id],
});
// Active rules now: none
await testFetchUrl(
0,
"Expected no lookups after unregistering the last remaining rule"
);
await browser.declarativeNetRequest.updateSessionRules({
addRules: [RULE_INCLUDE_TAB_ID],
});
// Active rules now: RULE_INCLUDE_TAB_ID
await testFetchUrl(
2, // initial request + redirect request.
"Expecting lookup again because of include rule"
);
// Ending test with remaining rule: RULE_INCLUDE_TAB_ID
// Reload extension.
browser.test.sendMessage("reload_extension");
}
let extension = ExtensionTestUtils.loadExtension({
background,
useAddonManager: "temporary", // for reload and granted_host_permissions.
allowInsecureRequests: true,
manifest: {
manifest_version: 3,
host_permissions: ["*://from/*"],
granted_host_permissions: true,
permissions: ["declarativeNetRequest"],
},
});
extension.onMessage("getTabLookups", () => {
extension.sendMessage("tabLookups", numberOfTabLookupsSinceLastCheck());
});
let startupCount = 0;
extension.onMessage("extensionStarted", () => {
extension.sendMessage("extensionStartupCount", startupCount++);
});
await extension.startup();
await extension.awaitMessage("reload_extension");
await extension.addon.reload();
await extension.awaitMessage("test_completed_after_reload");
Assert.equal(
0,
numberOfTabLookupsSinceLastCheck(),
"No new tab lookups since completion of extension tests"
);
await extension.unload();
});