I have a MV2 extension with chrome.webRequest that works perfectly but fail on MV3 declarativeNetRequest getting around iframes.
The extension is like a multi-messenger that opens multiple iframes for various sites to merge in a single extension all popular messengers.
So I have a domain "example.com" and there I open multiple iframes, for example open an iframe with Twitter.com or Telegram.org. Since twitter.com or telegram.org set the X-Frame-Options to DENY those iframes don't show anything. With MV2 we could run chrome.webRequest and remove those headers:
chrome.webRequest.onHeadersReceived.addListener(
function (details)
{
if (details.tabId && (details.tabId === tabId || details.tabId === -1 || tabMultiId.includes(details.tabId))) {
var b = details.responseHeaders.filter((details) => !['x-frame-options', 'content-security-policy', 'x-content-security-policy', 'strict-transport-security', 'frame-ancestors'].includes(details.name.toLowerCase()));
b.forEach(function(e){
"set-cookie" === e.name && -1 !== e.value.indexOf("Secure") && (-1 !== e.value.indexOf("SameSite=Strict") ?
(e.value = e.value.replace(/SameSite=Strict/g, "SameSite=None"))
: -1 !== e.value.indexOf("SameSite=Lax")
? (e.value = e.value.replace(/SameSite=Lax/g, "SameSite=None"))
: (e.value = e.value.replace(/; Secure/g, "; SameSite=None; Secure")));
});
return {
responseHeaders: b
}
}
},
{
urls: [ "<all_urls>" ],
tabId: tabId
},
["blocking", "responseHeaders", "extraHeaders"]
);
I have tried to do exactly the same with MV3 but keep failing. My 2 attemps:
async function NetRequest() {
var blockUrls = ["*://*.twitter.com/*","*://*.telegram.org/*"];
var tabId = await getObjectFromLocalStorage('tabId');
var tabMultiId = [];
tabMultiId = JSON.parse(await getObjectFromLocalStorage('tabMultiId'));
tabMultiId.push(tabId);
blockUrls.forEach((domain, index) => {
let id = index + 1;
chrome.declarativeNetRequest.updateSessionRules({
addRules:[
{
"id": id,
"priority": 1,
"action": { "type": "modifyHeaders",
"responseHeaders": [
{ "header": "X-Frame-Options", "operation": "remove" },
{ "header": "Frame-Options", "operation": "remove" },
{ "header": "content-security-policy", "operation": "remove" },
{ "header": "content-security-policy-report-only", "operation": "remove" },
{ "header": "x-content-security-policy", "operation": "remove" },
{ "header": "strict-transport-security", "operation": "remove" },
{ "header": "frame-ancestors", "operation": "remove" },
{ "header": "set-cookie", "operation": "set", "value": "SameSite=None; Secure" }
]
},
"condition": {"urlFilter": domain, "resourceTypes": ["image","media","main_frame","sub_frame","stylesheet","script","font","xmlhttprequest","ping","websocket","other"],
"tabIds" : tabMultiId }
}
],
removeRuleIds: [id]
});
});
}
async function launchWindow(newURL, windowDimensions, urlWindow, isIncognitoWindow, windowType) {
chrome.windows.create({ url: newURL, type: windowType, incognito: isIncognitoWindow, width: windowDimensions.width, height: windowDimensions.height, left: windowDimensions.left, top: windowDimensions.top },
async function (chromeWindow) {
if (urlWindow != "install" || urlWindow != "update") {
chrome.storage.local.set({ 'extensionWindowId': chromeWindow.id }, function () { });
chrome.storage.local.set({ 'tabId': chromeWindow.tabs[0].id }, function () { });
NetRequest();
}
});
}
Also tried:
const iframeHosts = [
'twitter.com', 'telegram.org'
];
const RULE = {
id: 1,
condition: {
initiatorDomains: ['example.com'],
requestDomains: iframeHosts,
resourceTypes: ['sub_frame', 'main_frame'],
},
action: {
type: 'modifyHeaders',
responseHeaders: [
{header: 'X-Frame-Options', operation: 'remove'},
{header: 'Frame-Options', operation: 'remove'},
],
},
};
chrome.declarativeNetRequest.updateDynamicRules({
removeRuleIds: [RULE.id],
addRules: [RULE],
});
Permissions:
"permissions": [
"system.display",
"scripting",
"activeTab",
"notifications",
"contextMenus",
"unlimitedStorage",
"storage",
"declarativeNetRequestWithHostAccess",
"webNavigation",
"alarms"
],
"host_permissions": [
"<all_urls>"
],
Any of this attempts worked. Greetings and thank you very much for anyone that try to help.
urlFilter
is different, so your "*://*.twitter.com/*"
is incorrect and should be "||twitter.com/"
, however a better solution is to use requestDomains
because it allows specifying multiple sites in just one rule.// manifest.json
"permissions": ["browsingData", "declarativeNetRequest"],
"host_permissions": ["*://*.twitter.com/", "*://*.telegram.org/"],
// extension script
async function configureNetRequest(tabId) {
const domains = [
'twitter.com',
'telegram.org',
];
const headers = [
'X-Frame-Options',
'Frame-Options',
];
await chrome.declarativeNetRequest.updateSessionRules({
removeRuleIds: [1],
addRules: [{
id: 1,
action: {
type: 'modifyHeaders',
responseHeaders: headers.map(h => ({ header: h, operation: 'remove'})),
},
condition: {
requestDomains: domains,
resourceTypes: ['sub_frame'],
tabIds: [tabId],
},
}],
});
await chrome.browsingData.remove({
origins: domains.map(d => `https://${d}`),
}, {
serviceWorkers: true,
// cacheStorage: true, // shouldn't be necessary normally
});
}
// Usage
chrome.windows.create({ url: 'about:blank' }, async w => {
await configureNetRequest(w.tabs[0].id);
await chrome.tabs.update(w.tabs[0].id, { url: 'https://some.real.url/' });
});