Assume frame.html
inside data folder in Firefox SDK addon,
how to append an iframe and define frame.html
as its source?
Additional info:
Because of CPS, its not possible to use inline source, so I can't use data.load('frame.html')
, I need to use URL of the file:
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
It's blank because of the firefox security policy which doens't allow content scripts to load resources URLs as iframes. The solution could be to set it directly from the background script, for this you'll need to use low level 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")
so the completely working code would look like:
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")
}
})
You'll probably need a cross-process wrapper in order to make it work in future version of Firefox with electrolysis
Found a better way. You add a blank <iframe>
and attach an event listener for the load
event. Then you can easily append whatever elements you want to the iframe as usual.
Include this in your content-script:
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)
})