这篇博客以讲解Chrome的Content Scripts扩展开发过程为主,并在该过程中穿插与Greasemonkey用户脚本的比较。本人初次尝试Content Scripts类型的扩展,有不足之处,请不吝指出。
现在使用Chrome浏览器的用户越来越多,在写用户脚本的时候有时候必须得同时考虑多个浏览器的兼容情况(当然比起前端开发要简单多了)。我一般仅考虑Firefox和Chrome两个浏览器,原因有以下几个:
Firefox用户要使用用户脚本(UserScripts),首先需要安装Greasemonkey或者Scriptish扩展,而Chrome在非常早的版本中就已经原生支持类似Greasemonkey扩展的功能,因此可以避免安装额外的扩展。用户只要将后缀为.user.js的用户脚本拖拽到浏览器中就可以安装。
而事实上,Chrome会将用户脚本转换成Content Scripts,并以扩展的形式存在(这个说法未必准确)。当你安装完成一个用户脚本之后,可以到以下目录找到你所安装的脚本:
AppData\Local\Google\Chrome\User Data\Default\Extensions
例如,假设编写一个HelloWorld的用户脚本,将其拖拽安装到Chrome中,示例代码如下:
|
可见,Chrome中用户脚本的Metadata Block(注释部分)与Firefox下GM或者Scriptish扩展所支持的形式是几乎一致的,这也是为什么Firefox下的用户脚本可以很好的兼容Chrome的一个重要的原因。
安装完成后,脚本出现在扩展程序列表中,在Chrome的扩展目录中,该添加的HelloWorld脚本(或者扩展)以以下的方式存在:
其中顶部圈住的那串字符串是该扩展的id,称为appid。manifest.json是JSON格式的manifest文件,提供扩展相关的描述信息,比如版本、名称等。scripts.js就是Content Script,它的内容和最初安装的用户脚本相同。manifest.json的内容如下所示:
|
这个文件比较简单,其中converted_from_user_script
意思是指该扩展是由用户脚本转换而来,content_scripts中描述了该扩展中的Content Script相关的信息:
js
指名所包含的JavaScript文件,在这里只有一个文件。matches
, exclude_globs
, include_globs
均是用来指名在哪些网页上该脚本生效的匹配模式。run_at
是指该脚本运行的时机,默认为document_end
关于manifest文件的格式,可以参考官方文档:在这里。其中Content Scripts的概念是比较简单的,前面的文档中描述得也比较详细,其实它就是一段注入到页面文件中的JavaScript代码,可以完成一些简单的任务,比如改变页面背景颜色之类的。对于用户脚本来说,Content Scripts的功能已经足够了,也没必要开发一个真正的扩展用到Chrome的诸多API。
国内比较知名的浏览器公司,例如Sogou和360等均采用了Webkit内核,它们的扩展开发都或多或少借鉴了Chrome的形式(其实几乎一样了),不信你可以比较下这两者与上面Chrome的文档的区别:搜狗的开发文档和360的开发文档。
对比Firefox的用户脚本,其实感觉Chrome的更加灵活。
在Greasemonkey中如果要添加一段比较长的CSS样式,可以选择使用GM_addStyle
(一般我选择自己实现该函数,尽量不用GM的API函数),另外一种方法是将样式文件分离到独立的style.css文件中,然后在Metadata Block中使用以下增加一个资源文件,格式为”@resource 名称 地址(相对与用户脚本的地址或者绝对地址)”:
|
并在用户脚本中使用GM_getResourceText('style.css')
来获取该资源的文本内容。
如果需要增加图片类型的资源,使用同样的方法在Metadata Block中添加,但是需要用GM_getResourceURL(resourceName)
来获取该资源的地址,图片返回它的Data URL(base64编码内容)。
如果需要依赖额外的JavaScript库,可以使用@require导入,例如jQuery:
|
而在Chrome中并不支持@require和@resource这些标记,但是可以使用Content Scripts的形式包装用户脚本,额外的CSS文件和JS库文件可以非常方便的通过manifest.json整合到扩展里,会在扩展生效的时候注入到页面中,参考CC98 Reply Improved脚本的manifest.json:
|
一切都是非常清晰自然,在”js”和”css”字段中增加所需要的js和css文件即可,其余就同GM脚本一样。
对于图片文件,可以将图片文件放到与扩展相同的目录(与manifest.json文件在同一层)中,然后利用Chrome提供的API访问即可,该API为chrome.extension.getURL
,参数为图片所在的相对路径,例如图片放在images/your.png,则通过以下方法 调用:
|
当脚本功能完成之后,剩下的就是将其打包成扩展.crx形式,关于打包的方法可以参考官方文档中的打包说明。如果想使用例如Shell脚本来自动化打包的过程,可以通过Chrome本身提供的命令行参数:
# chrome --no-message-box --pack-extension=$CHROME_BUILD_DIR \ --pack-extension-key=$SRC_DIR/reply_improved.pem
其中--no-message-box
是指不显示打包完成的提示框,--pack-extension
指定扩展的源代码目录,--pack-extension-key
指定扩展的pem文件。
这里需要注意的是,后两者的目录必须使用绝对路径(我没在Linux下试过,是在Cygwin中运行的)。当然,因为Google对crx的具体格式规范都有详细的说明,因此网上可以找到非常多的辅助打包工具, Kyle L. Huff在该页面中罗列了其中主要的几个工具,其中也包括他自己用C语言开启的buildcrx工具。