浏览器扩展编写指北

浏览器扩展编写指北

浏览器扩展

目前主流的浏览器主要有几大类:

  • 以 Chromium 为基础的浏览器,如 Chrome、Microsoft Edge、各种国产浏览器。
  • 以 Safari 为代表的 webkit 内核浏览器。拿出来单独说是因为其与 Chromium 相似但不完全一致。
  • 以 Gecko 为内核的浏览器,主要是 Firefox。因为 Firefox 的开源协议是 MPL,基于其商业化的浏览器较少,但也有一些其他的浏览器,例如洋葱浏览器。
  • Trident 内核,代表就是 IE 浏览器,现在已经基本不用考虑。

在 Firefox 52 之前,Firefox 的扩展引擎是自己单独的一套——语法是 js,但各类 API 等却是源自于自家的各种 XUL、JSM 等。从 Firefox 52 开始,其支持了 Web Extension,基本就与 Chrome 一致了。

初始浏览器扩展

一个浏览器扩展,基本上可以包含几种东西:

  • HTML 页面和相关的样式、脚本,一般是用于自己的介绍、设置等
  • background 页面,会随着浏览器启动,持续的在后台运行
  • content 脚本,可以将其注入到特定的网页中运行
  • 一个描述文件
  • 其他杂杂的资源文件等

当然,从 Manifest V3 开始,其 background 页面就变成了一个 Service Worker,就和普通的 Web 开发更为相似了。

浏览器扩展可以通过 content 脚本,往网页中注入内容。其不受网站本身的 CSP 限制。扩展还可以通过浏览器提供的诸多 API,实现例如读写书签和历史记录、控制右键菜单、控制 Cookie、下载文件、操作标签页、控制请求等功能。但是,一般来说:

  • 背景页面的权限是最高的。所有申请过的权限,均可以在其中使用。
  • 其次是扩展本身的 HTML 页面,其可以运行大部分 API。
  • content 脚本是权限最低的,只能运行有限的部分 API。所以很多时候要与背景页面通信,来达成一些目的。

从 manifest 开始

浏览器扩展最重要的一个文件,就是 manifest 描述文件。它告诉了浏览器你的扩展有哪些部分组成,申请什么权限等。

一般来说,我们会包括几个键值:

  • browser_action:显示在浏览器地址栏旁边的按钮,和相关的配置。当然,你也可以不写,调用 API 动态进行。
  • content_scripts:声明扩展所需要注入的脚本和对应的网站。这部分脚本浏览器会自动进行注入,不需要额外操作。
  • icons:扩展图标。
  • manifest_version:目前最新的版本是 V3
  • permissions:声明该扩展所需要的权限。在安装扩展的时候,浏览器会根据此对用户进行提示。
  • web_accessible_resources:声明一些可以被普通网站直接访问到的资源。 更多内容请查看官方文档

写一个重定向扩展!

我们简单的写一个重定向扩展,来实现日常中最常见的重定向 Google 公共库到国内镜像

首先新建一个文件人,然后在 manifest 中声明权限。

  • 在 manifest V3 中,操作请求相关的 API 大部分都在 declarativeNetRequest 下,因此需要申请此权限。
  • 我们需要操作的域名是 ajax.googleapis.com,因此需要申请相应的主机权限。
{
  // 省略其他信息
  "permissions": ["declarativeNetRequest", "*://ajax.googleapis.com/*"]
}

declarativeNetRequest API 只能被背景页面调用,因此,我们新建一个 background.js:

chrome.declarativeNetRequest.updateDynamicRules({
  addRules: [
    {
      id: 1,
      condition: {
        domains: "ajax.googleapis.com",
        regexFilter: "https?://ajax.googleapis.com/(.*)",
      },
      action: {
        type: "redirect",
        redirect: {
          regexSubstitution: "https://gapis.geekzu.org/ajax/\\1",
        },
      },
    },
  ],
});

DNR 还有很多参数,例如,我只希望重定向由 script 标签和 link stylesheet 发起的请求,则可以在 condition 中加上 resourceTypes:

condition: {
  domains: "ajax.googleapis.com",
  regexFilter: "https?://ajax.googleapis.com/(.*)",
  resourceTypes: ["script", "stylesheet"],
}

更多的 API,可以参考Chrome 文档MDN 文档

接下来,我们打开chrome://extensions/,点击“加载已解压的扩展程序”,选择我们的目录,就可以看到我们的扩展出现在了浏览器中。如果初始化加载的过程中出现错误,浏览器会有相应提示。对于背景页面,可以点击查看视图 - 背景页进行调试。

1

在这里,我们可以直接尝试调用有权限的 API:

2

再往后需要干什么?当然就是不停地重载、调试了,直到扩展符合你的预期。

扩展的发布和上架

扩展的发布有两种渠道:

  • 一种是各浏览器的官方商店,例如 Chrome 网上应用商店、Firefox Addons。其一般对于扩展有特定要求,例如某些 API 会被严格限制,要求提供源代码等。
  • 另一种是自分发渠道。

先说说自分发。自分发渠道中,各浏览器也需要保证扩展是由相应的作者发布的。因此,其也有相应的签名方式。Firefox 需要将扩展提交到其开发者站点上,其自动签名并提供下载。Chrome 则使用浏览器的“打包扩展程序”进行。

3

自分发的好处是,你可以不受限制的调用各类 API,而无需顾忌各自平台的审核。坏处就是其他用户无法在商店中找到它,并且更新也需要自己进行。

再说说发布到 Chrome 商店的过程。打开 Chrome 商店,点击右上角的小齿轮 - 开发者信息中心。如果之前没有注册过开发者,Google 可能还会要你交 5 美元的“注册费”。

在注册完成后,点击“上传新内容”,填写相关信息,然后就静等 Google 审核吧。

最后打个广告:欢迎体验一下 Header Editor