这也是一个总结贴,关于最近一个月来利用空余时间写的chrome插件的方方面面。


12月初第一个周六上午在浏览豆瓣时心血来潮想写chrome插件,因为之前有在豆瓣为网页写一些零碎的JS脚本(豆瓣是内置使用jquery的),来实现一些特殊的比如“只看楼主”、“批量上传/下载图片”等等之类的JS脚本,在初略的读了下chrome插件的开发文档的getting start tutorial以后,决定把之前写的那些JS脚变直接变成插件里的某段程序,于是开始研究chrome插件机制及相关的API。


自己写的豆瓣精灵插件google code地址:http://code.google.com/p/douban-demon/,可以通过svn下载全部源代码。包括豆瓣精灵和Rss Snack两个插件,其中前者一直有在慢慢更新,而后者是在一次大学同学技术讨论RSS相关时做的一个快速DEMO来谈插件实现的技术可能性,暂无更新了,不过这个插件使用到了jqueryUI和定制chrome插件鼠标右键的功能,具有一定的参考价值。


以下是chrome插件技术的一些tip总结,更多内容参考官方文档。

[b]关于manifest.json[/b]
manifest.json故名思义,是用来管理整个插件的核心配置文件。包括插件的权限设置、名字、版本号、以及所有用到的资源,都需要在这里面指定,下面是豆瓣精灵的manifest.json:

{
  "name" : "豆瓣精灵",   //extension名称
  "version" : "1.6.0",   //版本号(自动更新时需要用到)
  "update_url": "http://douban-demon.googlecode.com/svn/updates.xml",  //自动更新时的对比配置文件
  "description" : "【豆瓣精灵】有什么问题或意见或建议,请联系russell.liuyi@gmail.com,或豆瓣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"
  }
}




[b]关于插件自动升级[/b]


需要提供一个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>




[b]关于跨域提交请求[/b]


chrome浏览器禁止跨域提交ajax请求(除非是jsonp方式),但是在插件的backgroupd页面是可以直接跨域提交ajax请求的!比如说如果想在contentscript.js中在豆瓣的页面访问新浪微博的链接,这样是不行的,chrome会提示你禁止访问,这个时候需要把它放到background.html中来做。


另外要注意的是,有些网站跨域提交POST数据被直接被禁止,所以需要使用这些网站提供的API来实现对应的功能,验证方式建议可以的话 尽量使用oauth一劳永逸的方式。



[b]关于localStorage[/b]


可以让程序员来编程存储用户浏览器数据,也就是说用户就算关闭浏览器,下次再打开时,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数据。



[b]关于oauth协议[/b]


OAuth协议的详细内容可以参考RFC文档或者oauth官方网站的文档,以下我在研究过程中能记得的一些小TIP:


官方OAUTH文档是说所有的OAUTH实现应该可以放在HTTP HEADER或者POST FORM或者URL GET中,但是很多网站提供的AIP都只支持其中一种,比如豆瓣和新浪的api是放在http header中,而腾迅微博的API的OAUTH数据是只能附加上URL上做为GET的请求数据。这个需要仔细查看对应网站的API文档,以免走错路。


计算签名时,有些数据是必须放到basicString中做为签名的一部分来签名的,比如说新浪微博的发表新微博,需要把发表的内容转码后以status作为KEY,内容作为value成为basicString的一部分,然后再计算签名。此外签名时参数的顺序也不能错。否则会出现签名认错失败的情况。


虽然很多网站的API OAUTH认证的文档写得不详细,但是容易出错的地方还是可以到他们的网站上找到的,一旦出错了,先到文档上找找是不是有什么特别的提示,这样可能可以更快的发现错误。