教程:迁移至清单文件版本 2

清单文件版本 1 在 Chrome 18 中弃用,对它的支持将根据清单文件版本 1 支持计划逐渐减少。从版本 1 到版本 2 的更改分为两大类:API 更改和安全性更改。

该文档提供了将您的 Chrome 扩展程序从清单文件版本 1 迁移到版本 2 所需要做的事情清单,并提供有关这些改变会带来什么以及为什么作出这些改变的更多详细摘要。

API 更改清单

  • 您使用 browser_actions 属性或 chrome.browserActions API 吗?
    • 请用单数形式的 browser_action 属性替换 browser_actions
    • 请用 chrome.browserAction 替换 chrome.browserActions
    • 请用 default_icon 替换 icons 属性。
    • 请用 default_title 替换 name 属性。
    • 请用 default_popup 替换 popup 属性(并且现在它必须为字符串)。
  • 您使用 page_actions 属性或者 chrome.pageActions API吗?
    • 请用 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() API 吗?
    • 请替换为 chrome.extension.getViews( { "type" : "tab" } )
  • 您的扩展程序使用后台网页吗?
    • 请将 background_page 属性替换为 background 属性。
    • 请添加 scriptspage 属性,包含页面的代码。
    • 添加 persistent 属性,并将它设置为 false,将您的后台网页转换为事件页面

安全性更改清单

  • 您在 HTML 页面中使用内嵌脚本块吗?
    • 移除 <script> 标签内的 JavaScript 代码并将它放在外部的 JS 文件中。
  • 您使用内嵌事件处理器吗(例如 onclick 等)?
    • 将它们从 HTML 代码中移除,移动至外部的 JS 文件,并改用 addEventListener()
  • 您的扩展程序会向网页中插入需要访问包含在扩展程序包内的资源(例如图片与脚本)的内容脚本吗?
    • 定义 web_accessible_resources 属性,并列出这些资源(以及可选的单独用于这些资源的内容安全策略)。
  • 您的扩展程序嵌入外部网页吗?
  • 您的代码或库使用 eval()new Function()innerHTMLsetTimeout()或者通过其他方式传递动态求值的 JavaScript 代码字符串吗?
    • 如果您需要将 JSON 代码分析为对象请使用 JSON.parse()
    • 使用CSP(内容安全策略)友好的库,例如 AngularJS
    • 在您的清单文件中创建一个沙箱项,在沙箱中运行受到影响的代码,使用 postMessage() 与受沙箱保护的页面通信。
  • 您从外部加载代码,例如 jQuery 或 Google Analytics(分析)吗?
    • 考虑下载库文件并将它与扩展程序一起打包,并从本地包中加载。
    • 在清单文件的 "content_security_policy" 部分将托管资源的 HTTPS 域名加入白名单。

API 更改摘要

清单文件版本 2 引入了对浏览器按钮与页面按钮 API 的一些更改,并将少量旧的 API 用新的来代替。

对浏览器按钮的更改

浏览器按钮 API 引入了某些名称上的更改:

  • browser_actionschrome.browserActions 属性已替换为它们的单数形式 browser_actionchrome.browserAction
  • 在旧的 browser_actions 属性下,有 iconsnamepopup 属性,它们已替换为:
    • default_icon,用于浏览器按钮的图标。
    • default_name,用于您将鼠标悬停在图标上时出现在工具提示中的文字。
    • default_popup,用于表示浏览器按钮用户界面的HTML网页(并且必须为字符串,不能是对象)。

对页面按钮的更改

类似于浏览器按钮的更改,页面按钮 API 也有变化:

  • page_actionschrome.pageActions 属性已替换为它们的单数形式 page_actionchrome.pageAction
  • 在旧的 page_actions 属性下,有 iconsnamepopup 属性,它们已替换为:
    • default_icon,用于页面按钮的图标。
    • default_name,用于您将鼠标悬停在图标上时出现在工具提示中的文字。
    • default_popup用于表示页面按钮用户界面的 HTML 网页(并且必须为字符串,不能是对象)。

移除和更改的 API

一些扩展程序 API 已经移除,并用对应的新 API 替换:

  • background_page 属性已替换为 background
  • chrome.self 属性已移除,请使用 chrome.extension
  • Port.tab 属性已替换为 Port.sender
  • chrome.extension.getTabContentses() chrome.extension.getExtensionTabs() API 已替换为 chrome.extension.getViews( { "type" : "tab" } )

安全性更改摘要

清单文件版本 1 到版本 2 的转换伴随着一系列安全性相关的更改。许多这些更改来源于 Chrome 浏览器对内容安全策略的采用,您应该了解这一策略的更多信息来理解它带来的影响。

禁止使用内嵌脚本和事件处理器

由于内容安全策略的使用,您不能继续使用 HTML 内容中内嵌的 <script> 标签,它们必须移动至外部的 JS 文件中去。此外,内嵌的事件处理器也不支持。例如,假设您的扩展程序中有如下代码:

<html>
<head>
  <script>
    function myFunc() { ... }
  </script>
</head>
</html>

这一代码在运行时会产生错误。要修复它,请将 <script> 标签的内容移至外部文件,并使用 src='文件路径.js' 属性引用它们。

类似地,常见的内嵌事件处理器尽管是许多 Web 开发者为了方便而使用的特性,但它们不会执行。例如,考虑如下常见情况:

<body onload="initialize()">
<button onclick="handleClick()" id="button1">

它们不能在清单文件版本 2 的扩展程序中工作。请移除内嵌的事件处理器,将它们放在您的外部 JS 文件中,并使用 addEventListener() 为它们注册事件处理器。例如,在您的 JavaScript 代码中使用:

window.addEventListener("load", initialize);
...
document.getElementById("button1").addEventListener("click",handleClick);

这样将您的扩展程序的行为与用户界面标记分离的做法要整洁得多。

嵌入内容

在某些情况下,您的扩展程序可能会嵌入可以在外部使用或者来自外部来源的内容:

网页中的扩展程序内容:
如果您的扩展程序插入网页中的内容脚本嵌入资源(例如图片、脚本、CSS 样式等),您需要使用 web_accessible_resources 属性将这些资源加入白名单,这样外部网页才能使用它们:

{ 
...
  "web_accessible_resources": [
    "images/image1.png",
    "script/myscript.js"
  ],
...
}

嵌入外部内容:
内容安全策略仅允许从您的扩展程序包中加载本地脚本与对象,以免外部攻击者向您的扩展程序引入未知代码。然而,有时候您需要加载外部托管的资源,例如 jQuery 或 Google Analytics(分析)代码。有两种方式可以实现:

  1. 下载相关的库(例如 jQuery)并将它与您的扩展程序一起打包。
  2. 您也可以有限地放宽 CSP(内容安全策略),在您的清单文件中的 "content_security_policy" 部分将 HTTPS 来源加入白名单。要包含像 Google Analytics(分析)之类的库,可以采用如下方式:
    {
      ...,
      "content_security_policy": "script-src 'self'
      https://ssl.google-analytics.com; object-src 'self'",
      ...
    }
    

使用动态脚本求值

也许在新的清单文件版本 2 架构中最大的变化之一就是扩展程序不能继续使用动态脚本求值技术,例如 evalnew Function() 或者将 JavaScript 代码字符串传递给会使用 eval() 的函数,例如 setTimeout()。此外,已知某些常用的 JavaScript 库,例如 Google Maps 以及一些模板库,会使用这些技术。

Chrome 浏览器为页面提供了沙箱,以便在它们自己的来源中运行,拒绝访问 chrome.* API。为了在新的内容安全策略下使用 eval() 及类似技术:

  1. 在您的清单文件中创建一个 sandbox 项。
  2. 在 sandbox 项中列出您希望在沙箱中运行的页面。
  3. 通过 postMessage() 使用消息传递和沙箱中的页面通信。

有关如何做这些的更多详情,请参见受沙箱保护的 eval 文档

进一步的阅读

清单文件版本 2 带来的更改是为了引导开发人员建立更安全、架构更健壮的扩展程序和应用。要查看清单文件版本 1 至版本 2 的完整更改列表,请参见清单文件版本文档。有关使用沙箱隔离不安全代码的更多信息,请阅读受沙箱保护的 eval 文章。您可以访问我们与扩展程序相关的教程以及 HTML5Rocks 上一个很棒的简介(英文)了解有关内容安全策略的更多内容。