summaryrefslogtreecommitdiffstats
path: root/toolkit/components/extensions/test/xpcshell/test_ext_dnr_api.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/extensions/test/xpcshell/test_ext_dnr_api.js')
-rw-r--r--toolkit/components/extensions/test/xpcshell/test_ext_dnr_api.js383
1 files changed, 383 insertions, 0 deletions
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_dnr_api.js b/toolkit/components/extensions/test/xpcshell/test_ext_dnr_api.js
new file mode 100644
index 0000000000..0fc92dcb94
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_dnr_api.js
@@ -0,0 +1,383 @@
+"use strict";
+
+ChromeUtils.defineESModuleGetters(this, {
+ ExtensionDNRLimits: "resource://gre/modules/ExtensionDNRLimits.sys.mjs",
+});
+
+AddonTestUtils.init(this);
+
+const PREF_DNR_FEEDBACK_DEFAULT_VALUE = Services.prefs.getBoolPref(
+ "extensions.dnr.feedback",
+ false
+);
+
+// To distinguish from testMatchOutcome, undefined vs resolving vs rejecting.
+const kTestMatchOutcomeNotAllowed = "kTestMatchOutcomeNotAllowed";
+
+async function testAvailability({
+ allowDNRFeedback = false,
+ testExpectations,
+ ...extensionData
+}) {
+ async function background(testExpectations) {
+ let {
+ // declarativeNetRequest should be available if "declarativeNetRequest" or
+ // "declarativeNetRequestWithHostAccess" permission is requested.
+ // (and always unavailable when "extensions.dnr.enabled" pref is false)
+ declarativeNetRequest_available = false,
+ // testMatchOutcome is available when the "declarativeNetRequestFeedback"
+ // permission is granted AND the "extensions.dnr.feedback" pref is true.
+ // (and always unavailable when "extensions.dnr.enabled" pref is false)
+ // testMatchOutcome_available: true - permission granted + pref true.
+ // testMatchOutcome_available: false - no permission, pref doesn't matter.
+ // testMatchOutcome_available: kTestMatchOutcomeNotAllowed - permission
+ // granted, but pref is false.
+ testMatchOutcome_available = false,
+ } = testExpectations;
+ browser.test.assertEq(
+ declarativeNetRequest_available,
+ !!browser.declarativeNetRequest,
+ "declarativeNetRequest API namespace availability"
+ );
+
+ // Dummy param for testMatchOutcome:
+ const dummyRequest = { url: "https://example.com/", type: "other" };
+
+ if (!testMatchOutcome_available) {
+ browser.test.assertEq(
+ undefined,
+ browser.declarativeNetRequest?.testMatchOutcome,
+ "declarativeNetRequest.testMatchOutcome availability"
+ );
+ } else if (testMatchOutcome_available === "kTestMatchOutcomeNotAllowed") {
+ await browser.test.assertRejects(
+ browser.declarativeNetRequest.testMatchOutcome(dummyRequest),
+ `declarativeNetRequest.testMatchOutcome is only available when the "extensions.dnr.feedback" preference is set to true.`,
+ "declarativeNetRequest.testMatchOutcome is unavailable"
+ );
+ } else {
+ browser.test.assertDeepEq(
+ { matchedRules: [] },
+ await browser.declarativeNetRequest.testMatchOutcome(dummyRequest),
+ "declarativeNetRequest.testMatchOutcome is available"
+ );
+ }
+ browser.test.sendMessage("done");
+ }
+ let extension = ExtensionTestUtils.loadExtension({
+ ...extensionData,
+ manifest: {
+ manifest_version: 3,
+ ...extensionData.manifest,
+ },
+ background: `(${background})(${JSON.stringify(testExpectations)});`,
+ });
+ Services.prefs.setBoolPref("extensions.dnr.feedback", allowDNRFeedback);
+ try {
+ await extension.startup();
+ await extension.awaitMessage("done");
+ await extension.unload();
+ } finally {
+ Services.prefs.clearUserPref("extensions.dnr.feedback");
+ }
+}
+
+add_setup(async () => {
+ Services.prefs.setBoolPref("extensions.manifestV3.enabled", true);
+
+ // test_optional_declarativeNetRequestFeedback calls permission.request().
+ // We don't care about the UI, only about the effect of being granted.
+ Services.prefs.setBoolPref(
+ "extensions.webextOptionalPermissionPrompts",
+ false
+ );
+});
+
+add_task(
+ {
+ pref_set: [["extensions.dnr.enabled", false]],
+ },
+ async function extensions_dnr_enabled_pref_disabled_dnr_feature() {
+ let { messages } = await promiseConsoleOutput(async () => {
+ await testAvailability({
+ allowDNRFeedback: PREF_DNR_FEEDBACK_DEFAULT_VALUE,
+ testExpectations: {
+ declarativeNetRequest_available: false,
+ },
+ manifest: {
+ permissions: [
+ "declarativeNetRequest",
+ "declarativeNetRequestFeedback",
+ "declarativeNetRequestWithHostAccess",
+ ],
+ },
+ });
+ });
+
+ AddonTestUtils.checkMessages(messages, {
+ expected: [
+ {
+ message:
+ /Reading manifest: Invalid extension permission: declarativeNetRequest$/,
+ },
+ {
+ message:
+ /Reading manifest: Invalid extension permission: declarativeNetRequestFeedback/,
+ },
+ {
+ message:
+ /Reading manifest: Invalid extension permission: declarativeNetRequestWithHostAccess/,
+ },
+ ],
+ });
+ }
+);
+
+add_task(async function dnr_feedback_apis_disabled_by_default() {
+ let { messages } = await promiseConsoleOutput(async () => {
+ await testAvailability({
+ allowDNRFeedback: PREF_DNR_FEEDBACK_DEFAULT_VALUE,
+ testExpectations: {
+ declarativeNetRequest_available: true,
+ testMatchOutcome_available: kTestMatchOutcomeNotAllowed,
+ },
+ manifest: {
+ permissions: [
+ "declarativeNetRequest",
+ "declarativeNetRequestFeedback",
+ "declarativeNetRequestWithHostAccess",
+ ],
+ },
+ });
+ });
+
+ AddonTestUtils.checkMessages(messages, {
+ forbidden: [
+ {
+ message:
+ /Reading manifest: Invalid extension permission: declarativeNetRequest$/,
+ },
+ {
+ message:
+ /Reading manifest: Invalid extension permission: declarativeNetRequestFeedback/,
+ },
+ {
+ message:
+ /Reading manifest: Invalid extension permission: declarativeNetRequestWithHostAccess/,
+ },
+ ],
+ });
+});
+
+add_task(async function dnr_available_in_mv2() {
+ await testAvailability({
+ allowDNRFeedback: true,
+ testExpectations: {
+ declarativeNetRequest_available: true,
+ testMatchOutcome_available: true,
+ },
+ manifest: {
+ manifest_version: 2,
+ permissions: [
+ "declarativeNetRequest",
+ "declarativeNetRequestFeedback",
+ "declarativeNetRequestWithHostAccess",
+ ],
+ },
+ });
+});
+
+add_task(async function with_declarativeNetRequest_permission() {
+ await testAvailability({
+ allowDNRFeedback: true,
+ testExpectations: {
+ declarativeNetRequest_available: true,
+ // feature allowed, but missing declarativeNetRequestFeedback:
+ testMatchOutcome_available: false,
+ },
+ manifest: {
+ permissions: ["declarativeNetRequest"],
+ },
+ });
+});
+
+add_task(async function with_declarativeNetRequestWithHostAccess_permission() {
+ await testAvailability({
+ allowDNRFeedback: true,
+ testExpectations: {
+ declarativeNetRequest_available: true,
+ // feature allowed, but missing declarativeNetRequestFeedback:
+ testMatchOutcome_available: false,
+ },
+ manifest: {
+ permissions: ["declarativeNetRequestWithHostAccess"],
+ },
+ });
+});
+
+add_task(async function with_all_declarativeNetRequest_permissions() {
+ await testAvailability({
+ allowDNRFeedback: true,
+ testExpectations: {
+ declarativeNetRequest_available: true,
+ // feature allowed, but missing declarativeNetRequestFeedback:
+ testMatchOutcome_available: false,
+ },
+ manifest: {
+ permissions: [
+ "declarativeNetRequest",
+ "declarativeNetRequestWithHostAccess",
+ ],
+ },
+ });
+});
+
+add_task(async function no_declarativeNetRequest_permission() {
+ await testAvailability({
+ allowDNRFeedback: true,
+ testExpectations: {
+ // Just declarativeNetRequestFeedback should not unlock the API.
+ declarativeNetRequest_available: false,
+ },
+ manifest: {
+ permissions: ["declarativeNetRequestFeedback"],
+ },
+ });
+});
+
+add_task(async function with_declarativeNetRequestFeedback_permission() {
+ await testAvailability({
+ allowDNRFeedback: true,
+ testExpectations: {
+ declarativeNetRequest_available: true,
+ // feature allowed, and all permissions specified:
+ testMatchOutcome_available: true,
+ },
+ manifest: {
+ permissions: ["declarativeNetRequest", "declarativeNetRequestFeedback"],
+ },
+ });
+});
+
+add_task(async function declarativeNetRequestFeedback_without_feature() {
+ await testAvailability({
+ allowDNRFeedback: false,
+ testExpectations: {
+ declarativeNetRequest_available: true,
+ // all permissions set, but DNR feedback feature not allowed.
+ testMatchOutcome_available: kTestMatchOutcomeNotAllowed,
+ },
+ manifest: {
+ permissions: ["declarativeNetRequest", "declarativeNetRequestFeedback"],
+ },
+ });
+});
+
+add_task(
+ { pref_set: [["extensions.dnr.feedback", true]] },
+ async function declarativeNetRequestFeedback_is_optional() {
+ async function background() {
+ async function assertTestMatchOutcomeEnabled(expected, description) {
+ let enabled;
+ try {
+ // testAvailability already checks the errors etc, so here we only
+ // care about the method working vs not working.
+ await browser.declarativeNetRequest.testMatchOutcome({
+ url: "https://example.com/",
+ type: "other",
+ });
+ enabled = true;
+ } catch (e) {
+ enabled = false;
+ }
+ browser.test.assertEq(expected, enabled, description);
+ }
+
+ await assertTestMatchOutcomeEnabled(false, "disabled when not granted");
+
+ await new Promise(resolve => {
+ // browser.test.withHandlingUserInput would have been simpler, but due
+ // to bug 1598804 it cannot be used.
+ browser.test.onMessage.addListener(async msg => {
+ browser.test.assertEq("withHandlingUserInput_ok", msg, "Resuming");
+ await browser.permissions.request({
+ permissions: ["declarativeNetRequestFeedback"],
+ });
+ browser.test.sendMessage("withHandlingUserInput_done");
+ resolve();
+ });
+ browser.test.sendMessage("withHandlingUserInput_wanted");
+ });
+
+ await assertTestMatchOutcomeEnabled(true, "enabled by permission");
+
+ await browser.permissions.remove({
+ permissions: ["declarativeNetRequestFeedback"],
+ });
+ await assertTestMatchOutcomeEnabled(false, "disabled after perm removal");
+
+ browser.test.sendMessage("done");
+ }
+ let extension = ExtensionTestUtils.loadExtension({
+ background,
+ manifest: {
+ manifest_version: 3,
+ permissions: ["declarativeNetRequestWithHostAccess"],
+ optional_permissions: ["declarativeNetRequestFeedback"],
+ },
+ });
+ await extension.startup();
+ await extension.awaitMessage("withHandlingUserInput_wanted");
+ await withHandlingUserInput(extension, async () => {
+ extension.sendMessage("withHandlingUserInput_ok");
+ await extension.awaitMessage("withHandlingUserInput_done");
+ });
+ await extension.awaitMessage("done");
+ await extension.unload();
+ }
+);
+
+add_task(async function test_dnr_limits_namespace_properties() {
+ let extension = ExtensionTestUtils.loadExtension({
+ manifest: {
+ manifest_version: 3,
+ permissions: ["declarativeNetRequest"],
+ },
+ background() {
+ browser.test.assertEq(
+ "_dynamic",
+ browser.declarativeNetRequest.DYNAMIC_RULESET_ID,
+ "Value of DYNAMIC_RULESET_ID constant"
+ );
+ browser.test.assertEq(
+ "_session",
+ browser.declarativeNetRequest.SESSION_RULESET_ID,
+ "Value of SESSION_RULESET_ID constant"
+ );
+ const {
+ GUARANTEED_MINIMUM_STATIC_RULES,
+ MAX_NUMBER_OF_STATIC_RULESETS,
+ MAX_NUMBER_OF_ENABLED_STATIC_RULESETS,
+ MAX_NUMBER_OF_DYNAMIC_AND_SESSION_RULES,
+ MAX_NUMBER_OF_REGEX_RULES,
+ } = browser.declarativeNetRequest;
+ browser.test.sendMessage("dnr-namespace-properties", {
+ GUARANTEED_MINIMUM_STATIC_RULES,
+ MAX_NUMBER_OF_STATIC_RULESETS,
+ MAX_NUMBER_OF_ENABLED_STATIC_RULESETS,
+ MAX_NUMBER_OF_DYNAMIC_AND_SESSION_RULES,
+ MAX_NUMBER_OF_REGEX_RULES,
+ });
+ },
+ });
+
+ await extension.startup();
+
+ Assert.deepEqual(
+ await extension.awaitMessage("dnr-namespace-properties"),
+ ExtensionDNRLimits,
+ "Got the expected limits values set on the dnr namespace"
+ );
+
+ await extension.unload();
+});