【问题标题】:Access Firefox extension XPCOM object from Javascript inside an HTML page从 HTML 页面中的 Javascript 访问 Firefox 扩展 XPCOM 对象
【发布时间】:2013-01-10 14:46:42
【问题描述】:

我正在尝试让我加载到我的网页中的 javascript 可以访问最基本的 XPCOM javascript 对象。我正在使用本教程中的示例代码: https://developer.mozilla.org/en-US/docs/How_to_Build_an_XPCOM_Component_in_Javascript

这是我的设置:


安装.rdf:

<?xml version="1.0"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
     xmlns:em="http://www.mozilla.org/2004/em-rdf#">

    <Description about="urn:mozilla:install-manifest">
        <em:id>helloworld@thellamatesting.com</em:id>
        <em:name>Hello World</em:name>
        <em:version>1.0</em:version>
        <em:type>2</em:type>
        <em:creator>The Llama</em:creator>
        <em:description>Testing</em:description>

        <em:targetApplication>
            <Description>
                <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
                <em:minVersion>2.0</em:minVersion>
                <em:maxVersion>20.0</em:maxVersion>
            </Description>
        </em:targetApplication>
    </Description>      
</RDF>



chrome.manifest

content     helloworld    chrome/content/
content     helloworld    chrome/content/ contentaccessible=yes
overlay chrome://browser/content/browser.xul chrome://helloworld/content/browser.xul

component {4762b5c0-5b32-11e2-bcfd-0800200c9a66} components/HelloWorld.js
contract @thellamatesting.com/helloworld;1 {4762b5c0-5b32-11e2-bcfd-0800200c9a66}

locale  helloworld  en-US   locale/en-US/



components/HelloWorld.js

Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");

function HelloWorld() {
    // If you only need to access your component from Javascript, uncomment the following line:
    this.wrappedJSObject = this;
}

HelloWorld.prototype = {
    classDescription: "My Hello World Javascript XPCOM Component",
    classID:          Components.ID("{4762b5c0-5b32-11e2-bcfd-0800200c9a66}"),
    //Also tried
    //classID:          Components.ID("4762b5c0-5b32-11e2-bcfd-0800200c9a66"),
    contractID:       "@thellamatesting.com/helloworld;1",
    QueryInterface: XPCOMUtils.generateQI(),
    // Also tried
    //QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIHelloWorld]),
    hello: function() { 
        return "Hello World!"; 
    }
};

var components = [HelloWorld];
if ("generateNSGetFactory" in XPCOMUtils)
  var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);  // Firefox 4.0 and higher
else
  var NSGetModule = XPCOMUtils.generateNSGetModule(components);    // Firefox 3.x



测试 HTML:

<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title></title>
        <script type="application/javascript">

            function go() {
                try {
                    var coms = Components;
                    alert(Components.classes);
                    var myComponent = Components.classes['@thellamatesting.com/helloworld;1'].getService().wrappedJSObject;
                    alert(myComponent.hello());
                } catch (anError) {
                        dump("ERROR: " + anError);
                }
            };

        </script>
    </head>
    <body>

        <button onclick="javascript:go()">Click to go</button>

    </body>
</html>

在这一切之后,我最终得到“Components.classes 未定义”。有谁知道我在这里做错了什么?

非常感谢!

【问题讨论】:

  • 尝试将其中的一些代码以 JSFiddle 的形式放入。
  • 您好 Jules,我不确定这会有所帮助。 Components.classes 未定义,因此问题不在于我的 HTML javascript,而在于我的扩展。但是,为了确定,我试过了,结果一样。
  • 我看不出 JSFiddle 会有什么帮助,因为 Components 是 Mozilla 独有的特权对象。

标签: javascript firefox-addon xpcom


【解决方案1】:

为了从 javascript 上下文中访问 Components 对象,您需要具有扩展功能,即从 chrome:// URL 运行。 过去曾有一种方法让常规网页(从 http:// 提供服务)请求扩展功能(称为 UniversalXPConnect),但出于安全考虑已将其删除。

我认为你应该告诉我们更多关于你想要实现的目标。如果您尝试将数据从插件导出到网页中,AddonSDK(请参阅https://addons.mozilla.org/en-US/developers/docs/sdk/latest/dev-guide/)有一个非常好的协议,称为 page-mod;它允许您将数据注入网页。

【讨论】:

  • 您好乔纳森,感谢您的回复。我的最终目标是创建一个允许我的 Web 应用程序与剪贴板通信的插件。由于 Firefox 更改了他们的安全策略,我们的软件不能再复制/粘贴,这是一个大问题。不幸的是,我无法将人们引导至 chrome:// URL。我还有其他选择吗?
  • 我建议使用 SDK 创建一个插件; page-mod 允许您将脚本附加到给定的网页:。你可以做的是: * 只在你的 webapp 的域上附加一个 page-mod; * 内容脚本将在窗口对象上公开全局函数,例如window.foo = function () { ... }。 * 你的 webapp 会调用 foo 函数 * foo 函数的作用是使用port 与插件通信;然后插件将完成使用剪贴板的工作。
  • 请参阅addons.mozilla.org/en-US/developers/docs/sdk/1.12/modules/sdk/… 以获得更多见解,希望您阅读本文后会更有意义。
  • 谢谢乔纳森!这非常有效。我仍然无法将函数直接附加到窗口,但使用 CustomEvents 我能够完成同样的事情。我将在下面发布我的代码,以防其他人将来需要它。
【解决方案2】:

感谢 Jonathan 的建议,我能够想出一个很好的解决方案来解决这个问题。这是我正在使用的代码:

main.js:

var data = require("self").data;
var pageMod = require("page-mod");
const {Cc,Ci} = require("chrome");

pageMod.PageMod({
    include: "*",
    contentScriptFile: data.url("copy-helper.js"),
    onAttach: function(worker) {
        worker.port.on("handleCopy", function(copyInfo) {

            var gClipboardHelper = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
            gClipboardHelper.copyString(copyInfo.dataToCopy);
        });
    }
});

copy-helper.js:

window.addEventListener("copyEvent", function (event) {

    self.port.emit('handleCopy', event.detail.copyInfo);

}, false);

在我的应用程序中 javascript

var event = new CustomEvent("copyEvent", {
    detail:{
        copyInfo: {dataToCopy:"my string"}
    }
});
window.dispatchEvent(event);

希望这对遇到此问题的其他人有所帮助!

【讨论】:

  • 这是一个很好的解决方案,谢谢分享。如果您要将插件提交给 AMO,我建议您使用名为“剪贴板”的内置插件模块,因为它提供了一个很好的包装器,不依赖于 require("chrome")(请参阅 addons.mozilla.org/en-US/developers/docs/sdk/latest/modules/sdk/…)但因为这是仅适用于您的内部网站...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-12
  • 1970-01-01
  • 2010-09-08
相关资源
最近更新 更多