Chrome扩展MV3点击Zip链接跳转异常,求修正至MV2效果
Chrome扩展MV3实现Zip链接直接跳转的修复方案
问题背景
MV2版本的扩展可在用户点击Zip文件链接时直接跳转到扩展内的web/main.html页面;但MV3版本首次点击会弹出“另存为”对话框,再次点击同一链接才会触发跳转,其他Zip文件也存在相同问题。
原MV2代码实现
manifest.json
{ "name": "Test app mv2", "version": "0.1", "manifest_version": 2, "description": "test mv2", "background": { "scripts": [ "background.js" ] }, "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'", "icons": { "128": "128.png" }, "permissions": [ "webRequest", "webRequestBlocking", "<all_urls>" ], "web_accessible_resources": [ "web/main.html" ] }
background.js
function getHeaderFromHeaders(headers, headerName) { for (var i=0; i<headers.length; ++i) { var header = headers[i]; if (header.name.toLowerCase() === headerName) { return header; } } } function isAllowed(details) { var header = getHeaderFromHeaders(details.responseHeaders, 'content-type'); if (header) { var headerValue = header.value.toLowerCase().split(';',1)[0].trim(); var mimeTypes = [ 'application/zip' ]; return (mimeTypes.indexOf(headerValue) !== -1); } } chrome.webRequest.onHeadersReceived.addListener( function(details) { if (details.method !== 'GET') { return; } if (!isAllowed(details)) { return; } return { redirectUrl: chrome.runtime.getURL('web/main.html') }; }, { urls: [ "<all_urls>" ], types: ['main_frame', 'sub_frame'] }, ['blocking','responseHeaders'] );
原MV3代码实现(存在问题)
manifest.json
{ "name": "Test app mv3", "manifest_version": 3, "version": "0.1", "background": { "service_worker": "./background.js" }, "action": { "default_title": "SW3" }, "host_permissions": [ "<all_urls>" ], "permissions": [ "webRequest", "declarativeNetRequest", "declarativeNetRequestFeedback", "declarativeNetRequestWithHostAccess" ], "web_accessible_resources": [{ "resources": ["web/main.html"], "matches": ["<all_urls>"] }], "content_security_policy": { "extension_pages": "script-src 'self'; object-src 'self'" } }
background.js
function getHeaderFromHeaders(headers, headerName) { for (var i=0; i<headers.length; ++i) { var header = headers[i]; if (header.name.toLowerCase() === headerName) { return header; } } } function isAllowed(details) { var header = getHeaderFromHeaders(details.responseHeaders, 'content-type'); if (header) { var headerValue = header.value.toLowerCase().split(';',1)[0].trim(); var mimeTypes = [ 'application/zip' ]; return (mimeTypes.indexOf(headerValue) !== -1); } } chrome.webRequest.onHeadersReceived.addListener( function(details) { if (details.method !== 'GET') { return; } if (!isAllowed(details)) { return; } chrome.declarativeNetRequest.updateSessionRules({ addRules: [{ 'id': 2001, 'priority': 1, 'action': { 'type': 'redirect', 'redirect': { url: chrome.runtime.getURL('web/main.html') } }, 'condition': { 'urlFilter': details.url, 'resourceTypes': ['main_frame'] } }], removeRuleIds: [2001] }); return { redirectUrl: chrome.runtime.getURL('web/main.html') }; }, { urls: [ "<all_urls>" ], types: ['main_frame', 'sub_frame'] }, ['responseHeaders'] );
修复后的MV3代码
1. 修改manifest.json
添加webRequestBlocking权限,移除无需使用的declarativeNetRequest相关权限:
{ "name": "Test app mv3", "manifest_version": 3, "version": "0.1", "background": { "service_worker": "./background.js" }, "action": { "default_title": "SW3" }, "host_permissions": [ "<all_urls>" ], "permissions": [ "webRequest", "webRequestBlocking" ], "web_accessible_resources": [{ "resources": ["web/main.html"], "matches": ["<all_urls>"] }], "content_security_policy": { "extension_pages": "script-src 'self'; object-src 'self'" } }
2. 修改background.js
移除declarativeNetRequest相关代码,在onHeadersReceived监听参数中添加'blocking':
function getHeaderFromHeaders(headers, headerName) { for (var i=0; i<headers.length; ++i) { var header = headers[i]; if (header.name.toLowerCase() === headerName) { return header; } } } function isAllowed(details) { var header = getHeaderFromHeaders(details.responseHeaders, 'content-type'); if (header) { var headerValue = header.value.toLowerCase().split(';',1)[0].trim(); var mimeTypes = [ 'application/zip' ]; return (mimeTypes.indexOf(headerValue) !== -1); } } chrome.webRequest.onHeadersReceived.addListener( function(details) { if (details.method !== 'GET') { return; } if (!isAllowed(details)) { return; } return { redirectUrl: chrome.runtime.getURL('web/main.html') }; }, { urls: [ "<all_urls>" ], types: ['main_frame', 'sub_frame'] }, ['blocking', 'responseHeaders'] );
修复原理
MV3中webRequest.onHeadersReceived监听默认是非阻塞模式,此时返回redirectUrl不会生效,浏览器会触发默认的下载行为。添加webRequestBlocking权限并在监听参数中声明'blocking'后,扩展可在请求处理流程中拦截并修改响应,实现和MV2完全一致的即时跳转效果,无需依赖动态规则。
内容的提问来源于stack exchange,提问作者jinnee
相关产品推荐
相关产品推荐

