Chrome浏览器扩展插件教程:从MV2迁移到Manifest V3
Chrome Web Store于2021年1月已经开始接受Manifest V3扩展的提交。如果你还在使用MV2版本,那么一定要在官方弃用之前,尽快更新到MV3版本。
Chrome浏览器从88版本开始支持MV3啦(即Manifest Version 3),目前查看官方文档时默认已经是MV3版本。
我们这篇文章主要了解3个问题
1、MV2的弃用时间表
2、了解MV3的新特性
3、如何将MV2迁移到MV3
一、Manifest V2弃用时间表
此图表指定了弃用Manifest V2(MV2)的时间表
- 2022年1月份开始不接受新的MV2版本(除了”私人”可见类型),开发者可以更新已经存在的MV2扩展插件
- 2022年6月份不接受新的MV2版本,开发者可以更新已经存在的MV2扩展插件
- 2023年1月份开始,开发者不能更新MV2的扩展插件,MV2也不能在Chrome浏览器运行(除了个别的企业版)
- 2023年6月份MV2版本将不能在Chrome浏览器运行
二、Manifest V3新特性
Manifest V3是十年前推出扩展平台以来最大的转变之一。Manifest V3的新的扩展规范将在安全性、私密性和性能方面得到增强;也可以使用Manifest V3中采用的更现代的开放网络技术,比如Service Worker和Promises。并会逐步淘汰Manifest V2。
MV3新特性概要
- Service worker替换Background Page
- 网络请求修改使用新的
declarativentrequest API
来处理。 - 不再允许执行远程托管的代码;只能执行扩展包内包含的JavaScript。
- Promises 已经被添加到许多方法中,目前回调仍然支持作为一种替代方法。(最终将支持所有Promises)
- Action API整合:Browser Action API 和Page Action APIs被统一为一个单独的Action API。
- Web可访问的资源:资源只对指定的站点和扩展可用。
- 内容安全策略(CSP):现在可以为单个对象中的不同执行上下文指定单独的CSP,并且某些特定的策略是不被允许的。
- executeScript的变化:扩展不能再执行任意字符串,只能执行脚本文件和函数。这种方法也从Tabs API迁移到新的Scripting API。
三、如何将MV2迁移到MV3
1、修改manifest.json
1)manifest.json版本号
显而易见第一步需求修改 manifest.json 文件
{
...,
"manifest_version": 3,
...
}
2)Host Permissions
在Manifest V2中,有两种方法为你的api或任何主机获得权限,要么在 permissions
数组或 optional_permissions
数组。
在Manifest V3中,所有主机权限现在都单独存在一个新数组中,该数组的键为 host_permissions
。主机权限不再与其他权限一起添加。
MV2
{
...,
"permissions": [
"https://tahub.app/*"
],
...
}
MV3
{
...,
"host_permissions": [
"https://tahub.app/*"
],
...
}
3)Background Scripts
Manifest V3用Service Worker替换了 background scripts。
MV2 Background对象目前看起来是这样的:
{
...,
"background": {
"scripts": ["assets/js/background.js"],
"persistent": false
},
...
}
我们需要做的是把 script
数组的键改为 service_worker
,替换多个background pages或scripts。所以,它应该是这样的:
{
...,
"background": {
"service_worker": "assets/js/background.js"
},
...
}
注意,我们不再需要添加 persistent
了。
4)Actions
Actions
过去是 browser_action
和 page_action
,但现在它们在Manifest V3中统一为 Actions
。这是因为随着时间的推移,分开他们变得没有必要。
MV2
// Manifest V2
// manifest.json
{
"browser_action": { … },
"page_action": { … }
}
// background.js
chrome.browserAction.onClicked.addListener(tab => { … });
chrome.pageAction.onClicked.addListener(tab => { … });
MV3
// Manifest V3
// manifest.json
{
"action": { … }
}
// background.js
chrome.action.onClicked.addListener(tab => { … });
5)Content Security Policy (CSP)
你需要改变它从一个String(在Manifest V2)到一个Object(在Manifest v3)。
MV2
// Manifest V2
"content_security_policy": "..."
MV3
// Manifest V3
"content_security_policy": {
"extension_pages": "...",
"sandbox": "..."
}
6)Web-Accessible Resources
将 web_accessible_resources
数组更改为一个详细描述所有资源的对象,每个对象都可以映射到到一组url或扩展id。下面是V3版本的一个例子:
MV2
// Manifest V2
"web_accessible_resources": [
RESOURCE_PATHS
]
MV3
// Manifest V3
"web_accessible_resources": [{
"resources": [RESOURCE_PATHS]
}]
此外还支持其它的属性,用于设定不同的规则: matches
、 extension_ids
、 use_dynamic_url
2、将 Background Scripts 改造成 Service Workers
首先,什么是service worker,它和background scripts有什么不同?
background scripts在几乎所有扩展中都是必不可少的。允许执行一些操作或执行代码,而不需要用户打开某个页面或执行某些操作。这可以用于发送通知、与content scripts通信等等。后台脚本通常总是在后台运行。
Service worker在需要的时候被执行。与后台脚本不同,它们并不总是在后台运行。在最顶层,service worker将监听器注册到一些事件中,以允许它们稍后被执行。
从background scripts到service worker的转换依赖于扩展中的代码。一些扩展可能需要大量的工作,而另一些则不需要这么多。
需要做的第一步是将以前作为background scripts文件移动到根目录。
{
...,
"background": {
"service_worker": "background.js"
},
...
}
现在,让我们看看代码。以前的background script如下:
chrome.runtime.onMessage.addListener(function(message, sender, senderResponse){
if(message.msg === "image"){
fetch('https://some-random-api.com/img/xxx')
.then(response => response.text())
.then(data => {
let dataObj = JSON.parse(data);
senderResponse({data: dataObj, index: message.index});
})
.catch(error => console.log("error", error))
return true;
}
});
基本上,我们的后台脚本使用 chrome.runtime.onMessage.addListener
来监听一个消息,如果该消息请求一个图片,它将向API发送一个请求,然后将数据返回给我们的content script。
这个background script实际上不需要任何额外的更改。因为service worker的后台脚本只是注册了一个事件监听器,并在事件发生时执行代码,这正是service worker应该做的。
但并不是所有的扩展都是这样的,因为有不同的情况。以下是你在background script中需要检查和修改的内容:
1) 全局变量
以前的后台脚本总是在后台运行。如果有以下代码:
let count = 0;
chrome.runtime.onMessage.addListener( (message) => {
count++;
console.log(count);
});
每当service worker收到一条消息时,count就会增加。一开始是0,然后是1,然后是2,以此类推。
在service worker中,这将不再有效。service worker只会在需要时运行,并在完成工作时终止。因此,上述代码将始终在控制台打印“1”。
在上面的例子中,计数可以在background script和content script之间来回传递,以获得所需的结果。更好的方法是使用Chrome的存储API。
2) Timers and Alarms
Timers在后台脚本中使用没有问题,因为它们总是在后台运行。然而,这不适用于服务工作者。你应该用 Alarms API 替换所有的计时器。
3) 访问DOM
Service worker不能访问windows或DOM。如果你的扩展需要,你可以使用类似 jsdom 的库或使用chrome.windows.create和chrome.tabs.create。这取决于你的具体使用场景。
如果你的background scripts有录制音频或视频,这也是需要修改的,因为这在service worker中是不可以的。
4) 创建Canvas
如果你的background scripts之前创建了画布,你仍然可以用 offscreenenccanvas API 来做。你所要做的就是用 OffscreenCanvas
替换 document
。
MV2
let canvas = document.createElement('canvas');
MV3
let canvas = new OffscreenCanvas(width, height);
在完成这些修改之后,需要将你的background scripts 修改为service worker,在浏览器中重新加载你的扩展,看看它是否正常工作。
5) 执行脚本executeScript
如果你的代码使用executeScript的code属性执行任意字符串,有两种方法来更改它。同时,不使用chrome.tabs.execute脚本,需要用 script
替换标签,这样它将是 chrome.script .executeScript
。
将代码移植到文件
你需要将代码的值移动到一个新文件,并使用executeScript的 file
属性。
之前
chrome.tabs.executeScript({
code: alert("Hello, World!")
});
修改为
将 alert(“Hello, World!”)
放到一个新文件(让我们叫它 Hello - World .js
):
alert("Hello, World!");
chrome.scripting.executeScript({
file: 'hello-world.js'
});
将代码放到Function中
如果你的代码可以放在一个函数中,可以将它移动到同一个文件中的一个函数中,然后将execute escripts的 function
属性赋值给你创建的函数:
function greeting() {
alert("Hello, World!");
}
chrome.scripting.executeScript({
function: greeting
});
3、其它需求检查的
这里有一个列表,列出了你需要在代码中寻找的要更改的内容:
1、如果你的扩展使用 webRequest API
,它通常用于强制安装扩展的企业设置,你需要用declarativentrequest API 替换它。
2、如果你在内容脚本中发出任何CORS请求,请将它们移动到service worker中。
3、不再允许远程托管代码。你需要找到另一种方法来执行远程托管的代码。Chrome的文档建议使用 配置驱动功能和逻辑,这个意思就是说将配置本地化,然后执行用远程的web服务来执行。
4、请查看 API参考,了解可能正在使用的已弃用的API或方法。
好了,以上就是本篇主要内容,Manifest V3的新特性让扩展更安全,其实长远看是有好处的,这样浏览器扩展也不会被滥用,只是之前的MV2一些用法和写法需要做一些调整,工作量应该不会很大,逐条检查自己产品中存在的问题,相信问题一定能够解决,祝大家产品越做越好!