Bug 1809235 - Require an explicit webRequestFilterResponse data permission for MV3 extension to be allowed to call filterResponseData. r=willdurand

Depends on D166383

Differential Revision: https://phabricator.services.mozilla.com/D166384
This commit is contained in:
Luca Greco 2023-01-10 18:54:21 +00:00
Родитель 1071432476
Коммит de488d7857
7 изменённых файлов: 135 добавлений и 21 удалений

Просмотреть файл

@ -80,25 +80,40 @@ this.webRequest = class extends ExtensionAPI {
onSuspendCanceled: () => (isSuspending = false),
});
return {
webRequest: {
filterResponseData(requestId) {
if (isSuspending) {
throw new ExtensionError(
"filterResponseData method calls forbidden while background extension global is suspending"
);
}
requestId = parseInt(requestId, 10);
function filterResponseData(requestId) {
if (isSuspending) {
throw new ExtensionError(
"filterResponseData method calls forbidden while background extension global is suspending"
);
}
requestId = parseInt(requestId, 10);
let streamFilter = context.cloneScope.StreamFilter.create(
requestId,
context.extension.id
);
let streamFilter = context.cloneScope.StreamFilter.create(
requestId,
context.extension.id
);
filters.add(streamFilter);
return streamFilter;
},
},
};
filters.add(streamFilter);
return streamFilter;
}
const webRequest = {};
// For extensions with manifest_version >= 3, an additional webRequestFilterResponse permission
// is required to get access to the webRequest.filterResponseData API method.
if (
context.extension.manifestVersion < 3 ||
context.extension.hasPermission("webRequestFilterResponse")
) {
webRequest.filterResponseData = filterResponseData;
} else {
webRequest.filterResponseData = () => {
throw new ExtensionError(
'Missing required "webRequestFilterResponse" permission'
);
};
}
return { webRequest };
}
};

Просмотреть файл

@ -516,7 +516,9 @@ this.backgroundPage = class extends ExtensionAPI {
const childId = extension.backgroundContext?.childId;
if (
childId !== undefined &&
extension.hasPermission("webRequestBlocking")
extension.hasPermission("webRequestBlocking") &&
(extension.manifestVersion <= 3 ||
extension.hasPermission("webRequestFilterResponse"))
) {
// Ask to the background page context in the child process to check if there are
// StreamFilter instances active (e.g. ones with status "transferringdata" or "suspended",

Просмотреть файл

@ -13,6 +13,7 @@
"enum": [
"webRequest",
"webRequestBlocking",
"webRequestFilterResponse",
"webRequestFilterResponse.serviceWorkerScript"
]
}]

Просмотреть файл

@ -646,6 +646,7 @@ const GRANTED_WITHOUT_USER_PROMPT = [
"urlbar",
"webRequest",
"webRequestBlocking",
"webRequestFilterResponse",
"webRequestFilterResponse.serviceWorkerScript",
];

Просмотреть файл

@ -60,6 +60,7 @@ add_task(async function setup() {
"tabHide",
"tabs",
"webRequestBlocking",
"webRequestFilterResponse",
"webRequestFilterResponse.serviceWorkerScript",
];
OptionalPermissions = Schemas.getPermissionNames([

Просмотреть файл

@ -83,7 +83,10 @@ async function test_idletimeout_on_streamfilter({
manifest_version,
background: manifest_version >= 3 ? {} : { persistent: false },
granted_host_permissions: manifest_version >= 3,
permissions: ["webRequest", "webRequestBlocking"],
permissions:
manifest_version >= 3
? ["webRequest", "webRequestBlocking", "webRequestFilterResponse"]
: ["webRequest", "webRequestBlocking"],
// host_permissions are merged with permissions on a MV2 test extension.
host_permissions: ["http://example.com/*"],
},
@ -290,7 +293,10 @@ async function test_create_new_streamfilter_while_suspending({
manifest_version,
background: manifest_version >= 3 ? {} : { persistent: false },
granted_host_permissions: manifest_version >= 3,
permissions: ["webRequest", "webRequestBlocking"],
permissions:
manifest_version >= 3
? ["webRequest", "webRequestBlocking", "webRequestFilterResponse"]
: ["webRequest", "webRequestBlocking"],
// host_permissions are merged with permissions on a MV2 test extension.
host_permissions: ["http://example.com/*"],
},

Просмотреть файл

@ -521,3 +521,91 @@ add_task(async function test_alternate_cached_data() {
Services.prefs.clearUserPref("dom.script_loader.bytecode_cache.enabled");
Services.prefs.clearUserPref("dom.script_loader.bytecode_cache.strategy");
});
add_task(async function test_webRequestFilterResponse_permission() {
function background() {
browser.test.onMessage.addListener(async (msg, ...args) => {
if (msg !== "testFilterResponseData") {
browser.test.fail(`Unexpected test message: ${msg}`);
return;
}
const [{ expectMissingPermissionError }] = args;
if (expectMissingPermissionError) {
browser.test.assertThrows(
() => browser.webRequest.filterResponseData("fake-response-id"),
/Missing required "webRequestFilterResponse" permission/,
"Expected missing webRequestFilterResponse permission error"
);
} else {
// Expect the generic error raised on invalid response id
// if the missing permission error isn't expected.
browser.test.assertTrue(
browser.webRequest.filterResponseData("fake-response-id"),
"Expected no missing webRequestFilterResponse permission error"
);
}
browser.test.notifyPass();
});
}
info(
"Verify MV2 extension does not require webRequestFilterResponse permission"
);
const extMV2 = ExtensionTestUtils.loadExtension({
background,
manifest: {
manifest_version: 2,
permissions: ["webRequest", "webRequestBlocking"],
},
});
await extMV2.startup();
extMV2.sendMessage("testFilterResponseData", {
expectMissingPermissionError: false,
});
await extMV2.awaitFinish();
await extMV2.unload();
info(
"Verify filterResponseData throws on MV3 extension without webRequestFilterResponse permission"
);
const extMV3NoPerm = ExtensionTestUtils.loadExtension({
background,
manifest: {
manifest_version: 3,
permissions: ["webRequest", "webRequestBlocking"],
},
});
await extMV3NoPerm.startup();
extMV3NoPerm.sendMessage("testFilterResponseData", {
expectMissingPermissionError: true,
});
await extMV3NoPerm.awaitFinish();
await extMV3NoPerm.unload();
info(
"Verify filterResponseData does not throw on MV3 extension without webRequestFilterResponse permission"
);
const extMV3WithPerm = ExtensionTestUtils.loadExtension({
background,
manifest: {
manifest_version: 3,
permissions: [
"webRequest",
"webRequestBlocking",
"webRequestFilterResponse",
],
},
});
await extMV3WithPerm.startup();
extMV3WithPerm.sendMessage("testFilterResponseData", {
expectMissingPermissionError: false,
});
await extMV3WithPerm.awaitFinish();
await extMV3WithPerm.unload();
});