chrome插件技术开发总结
这也是一个总结贴,关于最近一个月来利用空余时间写的chrome插件的方方面面。
12月初第一个周六上午在浏览豆瓣时心血来潮想写chrome插件,因为之前有在豆瓣为网页写一些零碎的JS脚本(豆瓣是内置使用jquery的),来实现一些特殊的比如“只看楼主”、“批量上传/下载图片”等等之类的JS脚本,在初略的读了下chrome插件的开发文档的gettingstarttutorial以后,决定把之前写的那些JS脚变直接变成插件里的某段程序,于是开始研究chrome插件机制及相关的API。
自己写的豆瓣精灵插件googlecode地址:http://code.google.com/p/douban-demon/,可以通过svn下载全部源代码。包括豆瓣精灵和RssSnack两个插件,其中前者一直有在慢慢更新,而后者是在一次大学同学技术讨论RSS相关时做的一个快速DEMO来谈插件实现的技术可能性,暂无更新了,不过这个插件使用到了jqueryUI和定制chrome插件鼠标右键的功能,具有一定的参考价值。
以下是chrome插件技术的一些tip总结,更多内容参考官方文档。
关于manifest.json
manifest.json故名思义,是用来管理整个插件的核心配置文件。包括插件的权限设置、名字、版本号、以及所有用到的资源,都需要在这里面指定,下面是豆瓣精灵的manifest.json:
{ "name" : "豆瓣精灵", //extension名称 "version" : "1.6.0", //版本号(自动更新时需要用到) "update_url": "http://douban-demon.googlecode.com/svn/updates.xml", //自动更新时的对比配置文件 "description" : "【豆瓣精灵】有什么问题或意见或建议,请联系[email protected],或豆瓣ID:http://www.douban.com/people/3811658/", "options_page": "html/options.html", //选项页面。可以在扩展程序——选项里访问到的 "permissions": ["tabs", "notifications","http://*/*", "https://*/*"], //插件访问权限,tabs是指打开的标签页,notifications是指桌面弹出窗口,其它两个是可以访问的链接地址。 "background_page" : "html/background.html", //后台运行的页面,所有的跨域请求应该放在这里面执行。 "page_action" : //插件小图标的一些相关配置 { "default_icon" : "image/demon-19.gif", "default_title" : "" }, "content_scripts" : [ //content_script.js只对哪些页面生效、需要哪些JS文件 { "matches" : [ "http://*.douban.com/*", "http://api.t.sina.com.cn/oauth/*" ], "js": ["js/jquery.js","js/jquery-ui.js", "js/contentscript.js"], "run_at" : "document_idle", "all_frames" : false } ], "icons" : { "48" : "image/demon-48.gif" } }
关于插件自动升级
需要提供一个xml文件,用于记录升级的配置属性。
需要指定一个appid,对应于生成的chrome插件唯一ID(记住是加上了.pem文件一起打包扩展程序的ID,而不是开发版的ID),以及下载地址、版本号,以下是豆瓣精灵的例子:
<?xml version='1.0' encoding='UTF-8'?> <gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'> <app appid='hldoefihoaojobhlpfmnkjodjkmpicha'> <updatecheck codebase='http://douban-demon.googlecode.com/files/DoubanDemon-v1.6.0.crx' version='1.6.0' /> </app> </gupdate>
关于跨域提交请求
chrome浏览器禁止跨域提交ajax请求(除非是jsonp方式),但是在插件的backgroupd页面是可以直接跨域提交ajax请求的!比如说如果想在contentscript.js中在豆瓣的页面访问新浪微博的链接,这样是不行的,chrome会提示你禁止访问,这个时候需要把它放到background.html中来做。
另外要注意的是,有些网站跨域提交POST数据被直接被禁止,所以需要使用这些网站提供的API来实现对应的功能,验证方式建议可以的话尽量使用oauth一劳永逸的方式。
关于localStorage
可以让程序员来编程存储用户浏览器数据,也就是说用户就算关闭浏览器,下次再打开时,localStorage的数据仍然存在。但是如果用户执行了清理所有浏览器数据及cookie时,存在localStorage里的数据将消失。
每个网站都有自己的localStorage存放在chrome缓存中互不冲突。而插件仍然也保存了一份不冲突的localStorage。也就是说:如果在豆瓣的contentscript.js中执行对localStorage的操作,只能取到豆瓣的localStorage,而无法取到插件的localStorage,如果要执行对插件的localStorage的读写操作,需要使用chrome的chrome.extensions.sendMessage()来存取。
另外,localStorage只能存二维数据。但是可以通过JSON.parse(normalString)来让它解压更复杂的json数据,相应的可以通过JSON.stringify(jsonString)来序列化一串JSON数据。
关于oauth协议
OAuth协议的详细内容可以参考RFC文档或者oauth官方网站的文档,以下我在研究过程中能记得的一些小TIP:
官方OAUTH文档是说所有的OAUTH实现应该可以放在HTTPHEADER或者POSTFORM或者URLGET中,但是很多网站提供的AIP都只支持其中一种,比如豆瓣和新浪的api是放在httpheader中,而腾迅微博的API的OAUTH数据是只能附加上URL上做为GET的请求数据。这个需要仔细查看对应网站的API文档,以免走错路。
计算签名时,有些数据是必须放到basicString中做为签名的一部分来签名的,比如说新浪微博的发表新微博,需要把发表的内容转码后以status作为KEY,内容作为value成为basicString的一部分,然后再计算签名。此外签名时参数的顺序也不能错。否则会出现签名认错失败的情况。
虽然很多网站的APIOAUTH认证的文档写得不详细,但是容易出错的地方还是可以到他们的网站上找到的,一旦出错了,先到文档上找找是不是有什么特别的提示,这样可能可以更快的发现错误。