2012年(272)
分类: Python/Ruby
2012-06-26 11:14:10
这两天学习了一下Firefox扩展的开发,根据官方文档一步步做了下来,记一点笔记备忘:
按照下面写的步骤可以很轻松的为Firefox
创建一个扩展。
要打包一个可供安装的扩展很简单,把整个目录打包为zip,然后改后缀为 xpi 就可以了。
实际上Firefox的扩展可以理解为 XUL + JS
XPCOM是非常重要的东西,功能极其强大,提供了很多API,可以操作文件、网络、数据流等等。Firefox实际上可以看作是XPCOM的实现组合。由于XPCOM是跨平台和语言的,所以还可以用C++, Python
等来开发扩展。
要写一个HelloWorld其实非常简单,在下面的第5步就能做到,但是我们应该学会怎么用XPCOM来写一个复杂的HelloWorld.
笔记写的比较乱,直接看估计会没什么感觉,但是对照着官方文档动手做一遍,就很快上手了。
参考:
https://developer.mozilla.org/en/Building_an_Extension
1. 创建目录结构
exampleExt.xpi:
/install.rdf
/components/*
/components/cmdline.js
/defaults/
/defaults/preferences/*.js
/plugins/*
/chrome.manifest
/chrome/icons/default/*
/chrome/
/chrome/content/
2. 创建
install.rdf ,用于注册该扩展
3. 在
chrome/content/ 目录中创建
xul 文件(overlay), 用于展示和描述扩展
https://developer.mozilla.org/en/XUL_Overlays
https://developer.mozilla.org/en/XUL
sample.xul:
4. 创建
chrome.manifest
写入内容 Don't
forget the trailing slash, "/"!
content sample chrome/content/
overlay chrome://browser/content/browser.xul chrome://sample/content/sample.xul
5. javascript和xul进行交互
直接在xul中引入javascript文件sample.js
====>
6. XPCOM -- 非常强大!
https://developer.mozilla.org/en/How_to_Build_an_XPCOM_Component_in_Javascript
6.1 创建idl文件
HelloWorld.idl
#include "nsISupports.idl"
[scriptable, uuid(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)]
interface nsIHelloWorld : nsISupports
{
string hello();
};
创建GUID:
https://developer.mozilla.org/en/Generating_GUIDs
6.2 编译idl文件为 xpt文件 (需要安装Gecko SDK
https://developer.mozilla.org/en/Gecko_SDK)
静态编译的xpidl.exe 下载:
https://developer.mozilla.org/User:Andywang/xpidl
{sdk_dir}/bin/xpidl -m typelib -w -v -I {sdk_dir}/idl -e HelloWorld.xpt
HelloWorld.idl
6.3 创建一个组件 (使用XPCOMUtils)
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
function HelloWorld() { }
HelloWorld.prototype = {
classDescription: "My Hello World Javascript XPCOM Component",
classID:
Components.ID("{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"),
contractID:
"@dietrich.ganx4.com/helloworld;1",
QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIHelloWorld]),
hello: function() { return "Hello World!"; }
};
var components = [HelloWorld];
function NSGetModule(compMgr, fileSpec) {
return XPCOMUtils.generateModule(components);
}
如果只需要JS访问, 使用wrappedJSObject:
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
function HelloWorld() {
this.wrappedJSObject = this;
}
HelloWorld.prototype = {
classDescription: "My Hello World Javascript XPCOM Component",
classID: Components.ID("{98630970-F28B-11DD-B67F-A37256D89593}"),
contractID:
"@example.net/helloworld;1",
QueryInterface: XPCOMUtils.generateQI(),
hello: function() { return "Hello World!"; }
};
var components = [HelloWorld];
function NSGetModule(compMgr, fileSpec) {
return XPCOMUtils.generateModule(components);
}
6.4 在自己写的js里调用 chrome/content/sample.js
try {
// this is needed to generally allow
usage of components in javascript
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var myComponent =
Components.classes['@example.net/helloworld;1'].createInstance(Components.interfaces.nsIHelloWorld);
alert(myComponent.hello());
} catch (anError) {
dump("ERROR: " + anError);
}
使用
wrappedJSObject 的情况:
try {
// this is needed to generally allow
usage of components in javascript
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var myComponent =
Components.classes['@example.net/helloworld;1'].getService().wrappedJSObject;
alert(myComponent.hello());
} catch (anError) {
dump("ERROR: " + anError);
}
注意不能直接在web页面上的js进行这么调用,会遇到拒绝访问
如果WEB页面的js要和扩展交互,需要定义一个DOM事件
https://developer.mozilla.org/En/Code_snippets/Interaction_between_privileged_and_non-privileged_pages