2

我正在开发一个 firefox 插件,我需要的功能之一是在用户正在导航的页面内注入一个弹出元素。

我尝试在正文中注入一个 DIV,但是我的 DIV 继承了页面 CSS 并且每个页面中的弹出窗口显示都不同,所以我决定将它添加到 iframe 中。

这是插件代码:main.js

    exports.main = function() {};

var page_mod            = require("page-mod");  
var data                = require("self").data;
var self                = require("self"); 

function initPageMod()
{
      myPageMod = page_mod.PageMod({
          include: ['*'],
          contentScriptWhen: "start",
          contentScriptFile: [data.url("jquery.js"), data.url("modPage.js")],
           onAttach: function(worker) {
            worker.port.emit("inject", data.load("iframecontent.html"));
           }
        });
}

initPageMod();

我在这里所做的是在每个页面上安装一个 page-mod,注入 jquery 和我的 modPage.js 并在连接时调用“注入”端口。iframecontent.html:

<html>
    <head>
    <title>title</title>
    <script type="text/javascript">
        window.showPopup = function() {
        }
    </script>
    </head>
    <body>
        body
    </body>
</html>

这是一个非常简单的 HTML 文件,带有一个脚本标记,它定义了我想从父文档调用的 showPopup 函数。

modPage.js:

self.port.on("inject", function(iframeContent) {
    $(function(){
        if(window.frameElement == null) {
            $('body').append(
                '<div id="myExternalDiv" style="position:fixed;width:2560;height:auto;float:left;left:0px;top:0px;z-index:2147483647;overflow-x:hidden;overflow-y:hidden;background: transparent;margin: 0px;padding: 0px;">' +
                '<iframe id="myMagicIframe" width="100%" height="100%" frameborder="0" style="width:100%; overflow-y: hidden;background-color:transparent;" scrolling="no" marginheight="0" frameborder="0" allowtransparency="true" onload="alert(1)"></iframe>' +
                '</div>'
            );

            try {
                var oIframe = document.getElementById("myMagicIframe");
                var iframeDoc = (oIframe.contentWindow.document || oIframe.contentDocument);

                iframeDoc.open();
                iframeDoc.write(iframeContent);
                iframeDoc.close();
            } catch (err) {
                alert(err);
            }

            setTimeout(function(){func()}, 5000);          
        }
    });
});

function func() {
    if (document.getElementById("myMagicIframe") != null) {
        try {
            document.getElementById("myMagicIframe").contentWindow.showPopup();
        }catch(err) {
            alert(err);
            setTimeout(function(){func()}, 1000);
        }
    }
}

“注入”在 div 中创建一个 iframe,将 iframe 内容写入其中,并在 5 秒后调用 func 函数。发生的事情是我收到以下异常:“showPopup 不是函数”。document.getElementById("myMagicIframe").contentWindow.showPopup 未定义。

如果我在 HTML 中添加上面的代码并在 firefox 中运行它,它可以工作并调用 showPopup 函数,但在插件内部它不起作用。

我正在使用插件生成器: https ://builder.addons.mozilla.org/package/159673/latest/

谢谢

4

2 回答 2

2

首先感谢 canuckistani 让我知道代理概念。当您添加页面模块时,您的脚本将在沙箱上运行,并且您使用的变量是代理。

更改以下文件:

document.getElementById("myMagicIframe").contentWindow.showPopup();

document.getElementById("myMagicIframe").contentWindow.wrappedJSObject.showPopup();

解决了这个问题。

我的 iframe 被添加到页面中,因此 showPopup 函数被添加到真实的窗口对象中。currentWindow 对象是一个代理,没有添加的功能。使用 WrappedJSObject 对象,我能够获取真正的窗口对象并调用该函数。

于 2012-11-05T21:30:36.067 回答
1

发生这种情况是因为,与从不同服务器(或者在这种情况下,通过资源 uri)加载 iframe 的任何页面一样,您无法跨框架边界访问其他文档。

我最好的建议是让附加到 iframe 的内容脚本将消息发送回 main.js,然后它可以将消息路由到附加到父文档的内容脚本。这是间接的,但它会起作用。

欲了解更多信息:

类似的例子,但使用面板:

https://builder.addons.mozilla.org/package/159682/latest/

关于使用内容脚本的文档:

https://addons.mozilla.org/en-US/developers/docs/sdk/latest/dev-guide/guides/content-scripts/index.html

于 2012-11-01T21:14:41.497 回答