Access Add-On SDK 'main' from XUL
Access Add-On SDK 'main' from XUL
在我的附加组件中,我使用XUL来显示对话框窗口,因为我可以自定义它们的外观以适应附加组件的一般样式(如自定义titlebar
)。
使用迁移指南,我可以很容易地做到这一点。问题是,我想从XUL对话框中调用附加组件的main
模块中的某些函数。
经过一番搜索,我发现了loader
模块,这似乎能够做到我想要的。但是,我在使用它访问main
模块时遇到了麻烦。
首先,我尝试了文档中提到的显而易见的方法;
xul_dialog.js :
let {Loader} = Components.utils.import('resource://gre/modules/commonjs/toolkit/loader.js');
let loader = Loader.Loader({
paths: {
'toolkit/': 'resource://gre/modules/commonjs/toolkit/',
'': 'resource:///modules/',
'./': 'resource://<my-addon-name>/root/'
}
});
let main = Loader.main(loader, './main');
我得到一个错误,'./main'
没有找到resource://<my-addon-name>/root/
。考虑到我使用了不正确的路径,我做了一些实验,直到我可以删除所有与路径相关的错误。
xul_dialog.js :
let {Loader} = Components.utils.import('resource://gre/modules/commonjs/toolkit/loader.js');
let loader = Loader.Loader({
paths: {
'toolkit/': 'resource://gre/modules/commonjs/toolkit/',
'': 'resource://gre/modules/commonjs/',
'./': 'resource://<my-addon-id>-at-jetpack/<my-addon-name>/lib/'
}
});
let main = Loader.main(loader, './main');
这次我在loader.js, line 279
得到了一个相当令人困惑的错误。
Components is not available in this context.
Functionality provided by Components may be available in an SDK
module: https://jetpack.mozillalabs.com/sdk/latest/docs/
However, if you still need to import Components, you may use the
`chrome` module's properties for shortcuts to Component properties:
Shortcuts:
Cc = Components.classes
Ci = Components.interfaces
Cu = Components.utils
CC = Components.Constructor
Example:
let { Cc, Ci } = require('chrome');
当我使用Loader.Require(loader, {id: './main'})
而不是Loader.main
时,我得到同样的错误。在实例化加载器时,我甚至尝试将Components
作为globals
传递,但没有太多运气。
我相当肯定我做错了很多事情。我不明白为什么我得到的错误,即使花了相当多的时间在loader.js
。另外,我还认为有一个更好的选择,而不是必须使用附加id的路径main.js
;像那样硬编码似乎是不对的。
你要做的是找到一个特定的Loader
实例,而不是创建一个新的。
const { id, name, prefixURI } = require("@loader/options");
//pass these to the XUL dialog
在xul.js(或任何xul对话框脚本的名称)
Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm");
var extensionscope = XPIProvider.bootstrapScopes[id];
var mainjssandbox = extensionscope.loader.sandboxes[prefixURI + name + "/lib/main.js"];
假设在main.js中有一个foo
函数,你可以像
mainjssandbox.foo();
当然,不要指望事情会像XUL和Add-on SDK实际上融合在一起一样工作。
如果它是你的 XUL对话框应该与你的插件交互,那么请不要使用Loader
的东西,特别是不要去XPIProvider.bootstrapScopes
@paa建议。虽然这可能是可行的(目前),但应该注意的是,它依赖于大量的实现细节,这些细节在任何时候都可能发生变化,这使得这个解决方案非常脆弱。
相反,有几个其他的选项(不是一个详尽的列表):
- 如果SDK部分打开了窗口,您可以使用
.openDialog
,它支持向创建的窗口传递参数,这些参数甚至可以是对象和函数。此外,您可以拥有窗口调度(自定义)事件,并且您的SDK部分可以通过在.openDialog
调用返回的window
上调用addEventListener
来侦听。 - 如果窗口是从其他地方创建的(例如从
AddonManager
因为em:optionsURL
),那么nsIObserverService
是另一种通信方式。例如,.notifyObservers
上的DOMContentLoaded
包含对自身的引用。SDK部分只需要观察addObserver
的此类通知。 - 另一种方法,有点hacky,但工作,是SDK部分监听新窗口通过
nsIWindowWatcher.registerNotification
,然后注入一些API到browser.xul
窗口通过XPCNativeWrapper.unwrap(subject.QueryInterface(Ci.nsIDOMWindow)).myAddonAPI = something
。
一定要处理好卸载或你的附加组件-它仍然是不可重启的-即逆转你所做的任何更改并删除任何观察者,等等。
如果您想与不是由您创建的SDK插件进行交互,那么XPIProvider
路由可能是唯一可行的。但是,也许值得先联系插件作者,要求添加一些公共API,而不是深入到AddonManager和SDK加载器内部。
考虑将require
或全局作用域通过openDialog
传递给你的窗口,如果你想的话。通过将其放入main.js
:
const globalScope = this;
- Validate JSON from Mongo?
- Get JSON from an url
- creating objects from variables ES6
- getting id from jsp
- jquery使用name from变量按类选择元素
- Using jQuery with classes from ES6
- 如何计算与php中的CRC32函数兼容的arrayBuffer(javascript中的From FileReader)
- 无法在XUL Firefox扩展中获取TinyMCE的实例
- 如何删除'被按压'state from复选框
- 当我的所有 Ng-from 都有效时启用一个按钮
- getDocument by id/get input text from button dons'不起作用
- Calling VB.Net from Javascript
- Blob from DataURL?
- PDF Generation from DOM?
- AWSELB Cookie access from Javascript
- 转换类似数组的对象Array.prototype.slice或Array.from
- fetch data from db using javascript & php
- 在Stripe Checkout from表单中预先填充电子邮件
- 参考Firefox插件's install.rdf em:xul文件中的版本
- Access Add-On SDK 'main' from XUL