教程:升级到 Manifest V2
内容导航
从Chrome 18版本开始,Manifest V1就开始进入了淘汰的过程。Chrome内核对 Manifest V1 的支持计划具体可参见 Google 开发者网站上的日程表:manifest version 1 support schedule。
此文档提供了从 Manifest V1 升级到 V2 需要注意的检查清单,详细展示出在版本升级中发生的改动已经它们的意义。
API变化检查清单
- 您是否使用了
browser_actions
属性或chrome.browserActions
接口? - 使用单数形式的
browser_action
属性代替browser_actions
- 使用
chrome.browserAction
代替chrome.browserActions
- 使用
default_icon
代替icons
属性 - 使用
default_title
代替name
属性 - 使用
default_popup
代替popup
属性 - 您是否使用了
page_actions
属性或chrome.pageActions
接口? - 使用
page_action
代替page_actions
- 使用
chrome.pageAction
代替chrome.pageActions
- 使用
default_icon
代替icons
属性 - 使用
default_title
代替name
属性 - 使用
default_popup
代替popup
属性 - 您是否使用了
chrome.self
属性? - 请改用
chrome.extension
来代替它 - 您是否使用了
Port.tab
属性? - 请改用
Port.sender
来代替它 - 您是否使用了
chrome.extension.getTabContentses()
或chrome.extension.getExtensionTabs()
接口? - 请改为
chrome.extension.getViews( { “type” : “tab” } )
- 您的扩展是否使用了背景页?
- 使用
background
属性来代替background_page
属性 - 增加一个
scripts
或page
属性用来指定背景页的代码 - 增加一个
persistent
属性并将其值设为false
将背景页转化为一个 event page
安全性变化检查清单
- 您是否在HTML页面中使用了行内脚本?
- 删除所有使用 <script> 标签嵌入的行内脚本,将它放入一个单独的外部JS文件中
- 您是否使用了内联事件处理程序(譬如onclick)?
- 从HTML代码中将它们删除,放入一个外部JS文件中,并使用
addEventListener()
来代替 - 您的扩展是否向网页注入脚本,而此脚本需要使用扩展代码包里的资源(如图片或者脚本)?
- 设置 web_accessible_resources 属性并列出这些需要被访问的资源文件(也可考虑为这些资源文件设置一个单独的Content Security Policy规则)
- 您的扩展是否内嵌了外部页面?
- 请指定 sandbox 属性
- 您的代码或JS库中是否使用了
eval()
、newFunction()
、innerHTML
、setTimeout()
或其他方法将JS代码以字符串形式传递并运行? - 如果您是为了将JSON代码解析为对象,请使用
JSON.parse()
- 使用符合Content Security Policy规则的库,如 AngularJS
- 在你的Manifest文件中增加“sandbox”项,并将相关代码运行在沙箱中,使用
postMessage()
与运行在沙箱中的页面通信 - 您是否记载了外部代码,如 jQuery 或 Google Analytics?
- 考虑将这些外部库下载下来并打包在扩展代码里
- 在Manifest文件的“content_security_policy”项中列出这些HTTPS域名
API变化小结
Manifest V2 在 browser action 和 page action 的接口方面做了一些改动,并将一些老的接口改成了新的接口。
Browser actions 的改动
名称上的变化有:
browser_actions
和chrome.browserActions
属性被它们的单数形式browser_action
和chrome.browserAction
取代- 在原来的
browser_actions
中,有icons
、name
、popup
属性,它们现在变为: default_icon
表示 browser action 的显示图标default_name
表示 tooltip 文字,当你把鼠标移动到 browser action 的图标上的时候就能看到它default_popup
表示 browser action UI 的 HTML 页面(必须是字符串)
Page actions 的改动
与 browser actions 一样,page actions 的接口也做了一些调整:
page_actions
和chrome.pageActions
属性被它们的单数形式page_action
及chrome.pageAction
所取代- 在原来的
page_actions
属性中,有icons
、name
、popup
属性,它们现在变为: default_icon
表示 page action 的图标default_name
表示 tooltip 文字,当你把鼠标移动到 page action 的图标上的时候就能看到它<default_popup
表示 prowser action UI 的 HTML 页面(必须是字符串)
其它废弃或改动的API
background_page
属性更改为 backgroundchrome.self
属性被废除,请使用chrome.extension
来代替Port.tab
属性被Port.sender
取代chrome.extension.getTabContentses()
和chrome.extension.getExtensionTabs()
接口被chrome.extension.getViews( { “type” : “tab” } )
取代
安全性变化小结
Manifest 升级到 V2 带来了一系列安全性方面的变化,而这些变化中有很多源自 Chrome 开始采用了 规则。如果您有兴趣了解更多关于此规则的影响,请阅读此规则的详细介绍。
行内脚本和内联事件处理程序被禁止
由于 Content Security Policy 的限制,行内脚本和内联事件处理程序被严格禁止,您必须使用外部的JS文件来进行处理。例如,原来您的代码里可能存在类似下面的写法:
<html> <head> <script> function myFunc() { ... } </script> </head> </html>
这段代码现在在运行时会报错,您需要将 <script> 标签里的内容放到一个外部文件中,并通过 src=’path_to_file.js’
来引用它。
同样的,内联事件处理程序也不会再被执行。例如下面这段代码在普通的页面中非常常见:
<body onload=”initialize()”> <button onclick=”handleClick()” id=”button1”>
上面这段代码在 Manifest V2 的扩展中也无法执行。请删除内联事件处理程序,将它们放入外部JS文件中,并使用 addEventListener()
来注册事件处理程序。如下面的代码所示:
window.addEventListener(“load”, initialize); ... document.getElementById(“button1”).addEventListener(“click”,handleClick);
这样可以更好更清楚地将您的扩展的处理逻辑与它的UI分离开。
嵌入的内容
有些时候,您的扩展可能需要嵌入能被外部使用或来自外部的内容。
被使用在外部页面中的扩展的资源:
如果您的扩展包含会被 content scripts 注入到外部页面中的资源,您需要使用 web_accessible_resources 属性一一列出这些资源。
{ // manifest file ... "web_accessible_resources": [ "images/image1.png", "script/myscript.js" ], ... }
嵌入外部的内容:
Content Security Policy 只允许加载扩展包中的脚本和对象,这样可以避免外部代码通过引入一些不确定的代码带来的攻击。然后,有些时候您需要加载外部的资源如 jQuery 或 Google Analytics,有两个方法来解决:
- 将相关的库(如 jQuery)代码下载到本地并将其打包在您的扩展中。
- 您也可以在Manifest文件中的“content_security_policy”部分列出这些HTTPS域名来对CSP限定做一些放松。以加载 Google Analytics 库为例,您可以使用下面的方法:
{ // manifest file ..., "content_security_policy": "script-src 'self' https://ssl.google-analytics.com; object-src 'self'", ... }
动态脚本的执行
在 Manifest V2 中最大的变化可能应该是扩展不再允许使用将脚本作为字符串传递并运行的方法,如 eval()
、new Function()
、setTimeout()
。值得注意的是,一些常用的JS库,如
Google Maps 及其他模板库中经常会用到这些技术。
Chrome 提供了一种机制,让页面运行在它们自己的源所在的沙箱中,但这些运行在沙箱中的页面不允许访问 chrome.* 接口。这种机制使得在新的 Content Security Policy 规则下,依然可以使用 eval()
一类的技术:
- 在您的Manifest文件中增加“sandbox”项
- 在“sandbox”项中,列出您需要运行在沙箱中的页面
- 通过
postMessage()
实现沙箱内外的页面之间的通讯
您可以通过阅读 Sandboxing Eval 文档来了解更多关于沙箱的知识。
深入阅读
Manifest V2 带来的这些变化是为了指导开发者开发出更安全、结构更健壮的扩展和应用。您可以从 Google 开发者文档 manifest file 了解所有V1到V2的变化及支持时间表。关于如何使用沙箱隔离代码运行环境,可以参考 sandboxing eval 文档。若想了解更多关于 Content Security Policy 的内容,您可以阅读扩展相关的文档或HTML5Rocks网站上关于它的介绍。