如何使用 Firefox SDK 插件将 iframe 附加到托管页面?

how to append iframe to hosted page using Firefox SDK addon?

假设 frame.html 在 Firefox SDK 插件的数据文件夹中, 如何附加 iframe 并将 frame.html 定义为其来源?

附加信息: 因为CPS,无法使用inline source,所以我不能使用data.load('frame.html'),我需要使用文件的URL:

lib/main.js

tabs.activeTab.attach({
  contentScriptFile: [self.data.url("js/appender.js") ],
  attachTo: 'top',
  contentScriptOptions: {
    scriptUrl: self.data.url("js/sandbox.js"),
    imageUrl: self.data.url("image.jpg")
    frameUrl: self.data.url("sandbox.html")
  }
});

data/appender.js

  var scriptTag = document.createElement("script");
  scriptTag.src = self.options.scriptUrl;
  document.body.appendChild(scriptTag); // worked fine

  var imageTag = document.createElement("image");
  imageTag.src = self.options.imageUrl;
  document.body.appendChild(imageTag); // worked fine

  var iframeTag = document.createElement("iframe");
  iframeTag.src = self.options.frameUrl;
  document.body.appendChild(iframeTag); // the html tag of iframe is empty

它是空白的,因为 firefox 安全策略不允许内容脚本将资源 URL 作为 iframe 加载。解决方案可以是直接从后台脚本设置它,为此你需要使用低级 sdk。

var { viewFor } = require("sdk/view/core");
var tab_utils = require("sdk/tabs/utils");

var iframe = viewFor(tab).linkedBrowser._contentWindow.document.querySelector('iframe[src="' + self.data.url("sandbox.html") + '"]')
iframe.contentWindow.location.href = iframe.getAttribute("src")

因此完整的工作代码如下所示:

data/appender.js

var iframeTag = document.createElement("iframe");
iframeTag.src = self.options.frameUrl;
document.body.appendChild(iframeTag); // the html tag of iframe is empty

// note that the iframe is attached after the content ready event, so you have to inform the background when it can start working with the iframe
self.port.emit("attached", true);

main.js

tabs = require("sdk/tabs")
self = require("sdk/self")

var { viewFor } = require("sdk/view/core");
tab_utils = require("sdk/tabs/utils");

tabs.on("ready", function(tab) {
  var worker = tab.attach({
    contentScriptFile: [self.data.url("js/appender.js") ],
    attachTo: 'top',
    contentScriptOptions: {
      frameUrl: self.data.url("sandbox.html")
    }
  });

  worker.port.on('attached', function() {
    reinitIframe(tab)
  });

  function reinitIframe(tab) {
    var iframe = viewFor(tab).linkedBrowser._contentWindow.document.querySelector('iframe[src="' + self.data.url("sandbox.html") + '"]')
    iframe.contentWindow.location.href = iframe.getAttribute("src")
  }
})

您可能需要 cross-process wrapper 才能在未来版本的 Firefox 中使用电解

找到更好的方法。您添加一个空白 <iframe> 并为 load 事件附加一个事件侦听器。然后您可以像往常一样轻松地将您想要的任何元素附加到 iframe。

将此包含在您的内容脚本中:

var iframe = document.createElement('iframe'),
  div = document.createElement('div');
div.textContent('Hello World');
document.body.appendChild(iframe);
iframe.addEventListener('load', function(){
  this.contentWindow.document.body.appendChild(div)
})