# 基于Chrome插件的开发工具链

在项目开发过程中，时不时会碰上需要使用一些工具来做一些自动操作或者附加功能。特别是有一些外部组件只会提供Web工具，或者如果产品会发布在Web上的时候，在线上的产品中加调试指令显然是不安全的（前段时间刚好有携程线上服务器暴露的调试接口，导致用户信息泄露的事故）。这时候我们就可以借助Chrome来制作一些特别的小工具。 使用Chrome来自作工具有几个好处：其一是对熟悉Web开发的人而言，它用得全是Javascript(当然你也可以用Go语言)和HTML，没有太多额外的学习成本，而且现在的Chrome对HTML5标准支持得也比较好，基本的功能都可以实现；其二是不需要花多少时间在UI方面（作为一个后台开发表示The easier the better）；其三是在需要的时候，还能开发为App，直接运行（另外还有一个项目叫[Nodejs-webkit](https://github.com/rogerwang/node-webkit/)，提供了打包成不依赖Chrome本地应用的功能，而且底层用了nodejs，提供了更加强大的系统资源访问的功能)。总而言之，作为开发工具而言已经绰绰有余了。

> 我是在写第二个Chrome插件的时候写下这篇类似记录的东西，一是有些资源找起来方便，二是下次开发插件的时候不需要从头回顾。第一次写插件刚好是一个页游，为了帮助在页面上抓错误包和快速检查与各个平台之间的交互参数，这一次则是有一个组件提供的管理工具操作太繁琐，写个工具Hack进去然后实现一键操作的。 好啦话不多说，直接上Chrome插件开发流程，Chrome的app开发大同小异，这里就不再另外给出。

## 概述

### 资源

* [chrome 官方开发文档](https://developer.chrome.com)
* [文档的中文翻译](https://code.google.com/p/crxdoczh/) 里面主要是两部分 [chrome插件开发文档](https://crxdoc-zh.appspot.com/extensions/) 和 [chrome 应用开发文档](https://crxdoc-zh.appspot.com/apps/)

不幸地是这两个文档在中国被无情地和谐啦，所以不方便翻墙的话，还可以参考一下某数字公司copy了一份作为它的浏览器的插件开发文档的页面，不过它很久没更新了，缺失比较严重。

### 执行环境

chrome插件的执行环境主要有三种，一种是后台页，一种是popup页面，还有一种叫内容脚本( content script )。 这三种执行环境分别在三个不同的沙箱中执行。但是可以通过chrome提供的消息管道的形式相互访问。

#### 后台页

后台页当然是运行在后台，也分两种，一种是按需加载的“事件页面”（生命周期的形式有点像手机应用开发），另一种是只要chrome进程存在就会一直保持在线的后台页。 后台页可以用来控制整个插件的功能和处理一些非UI方面的功能。

#### popup页面

popup页面是存在于浏览器右上角的插件页面（很多插件，比如adblock在右上角都会有一个图标）。 这个页面在点击图标的时候加载，并弹出页面，在页面隐藏的时候被关闭。**要注意的是每次点击的时候都会重新加载** popup页面里的某些html属性的权限被安全限制所拦截，但是基本上都可以通过脚本解决。

#### 内容脚本

前面所提到的两种执行环境并不能直接操作网页内容，而这个内容脚本其实就是一个解决这个问题的特殊的脚本环境。 内容脚本必须指定所支持的网页地址，并且在所有匹配的地址中载入这些脚本。并且这些脚本可以直接访问页面里的dom。 不过值得注意的是这个content script并不能直接操纵网页里的脚本的变量，因为**它们执行在不同的沙箱中**。 并且除非通过addListener的方式注册事件，html里的类似onclick的属性也不会直接访问content script中的函数。

## 软件结构

### 入口

chrome插件只有一个必须文件：**清单文件mainfest.json**。看后缀就知道是JSON格式的，具体内容可以参照文档里&#x7684;**“清单文件格式”**&#x90E8;分。值得一提的是，无论是清单文件格式还是popup页面还是载入脚本的api，路径都是相对于插件根目录的。 唯一有一点不一样的是，在content script中如果要获取插件中的资源文件，需要通过*chrome.extension.getURL*接口来获得完整路径。 而其他的诸如权限控制、不同执行环境的配置、资源引用控制都在mainfest.json里完成。

### URL权限匹配表达式

插件可以访问哪些页面是要通过匹配表达式指定的，这个表达式有点像通配符，但是又不是通配符。 它的匹配表达式分为 协议、主机和路径三部分。

* 协议部分可以指定某一个（http、https、file等）&#x6216;*，但是不能类似http*这样
* 主机部分每一个第一个.之前可以用\*表示匹配全部，也可以指定某个域名
* 路径部分可以就是字符和\*组成的通配符

### 关于权限和API

插件的几个执行环境都是按mainfest.json的顺序载入的，另外使用方式和一般的网页开发无异。 但是还是有一点点区别。首先，不同环境的拥有的API略有不同，content script中没有大多数全局控制的API；其次，API和开启的权限有关，比如如果开启了tabs权限，popup的执行环境里就会有*chrome.tabs*包；另外，chrome拓展了一些内部接口，比如原生支持JSON类和webkit的一些API。

### 关于存储

chrome提供了HTML5本地存储，也提供了sync存储。前者可以用来保存离线数据，后者可以用来保存可以被Google帐号同步的应用配置。这是还比较有意思的云存储。

### 关于通信

由于不同的执行环境（后台、popup、centent script和网页原生的脚本环境）在不同的沙箱中，他们之间要进行通信可以使用chrome的消息管道API。 chrome提供了**类似TCP的用于长链接connect API**和**类似UDP的用于短连接的sendMessage API**，具体使用方式请参照文档。 另外有一点特殊的地方在于，网页原生的脚本环境一般不受控制，想要和原生的脚本环境交互一般通过**脚本注入**的方式。所幸chrome的function对象都有**totring( )**&#x65B9;法。然后通过向页面添加一个script节点的方式可以很容易地实现脚本注入( 当然调试起来麻烦一点点，这也是那个火车票订票插件和视屏网站广告屏蔽插件干的事呦)。

## 调试

chrome的调试已经非常强大了，在扩展页面上打开开发者模式，可以载入正在开发中的插件的文件夹。 后台页的调试可以在扩张页面点击插件下面的地址打开调试面板。 popup页可以在插件上右键点击“审查弹出内容”打开调试面板。 content script可以在网页上打开网页的脚本调试面板，然后脚本列表那里有个tab是Content scripts

## 打包和自动更新

chrome浏览器自带了打包工具，在扩展页面上就有。 第一次打包会生成一个密钥文件然后分配一个插件ID，以后每次打包使用这个密钥文件插件ID就不会再变。 如果使用自己的自动更新服务器，自动更新的xml里要填写这个插件ID的，具体的还是看文档吧。比较简单。

\_PS:好多干货啊，但是文档是可以选版本的，就没贴很多文档引用链接

再PS:这是我第一次用latex写blog，这玩意虽然功能强大，但是真不怎么方便啊，考虑考虑下次还是markdown算了\_
