The main problem is that my extension is loading into every iframes on a target webpage. It puts buttons that appear inside the iframes as well. I want them to disappear. The window and document objects are shown as the parent's window and document objects. So it's impossible to check the document location for example because it shows the parent's location instead of the iframe's location.
-
Are you using the page-mod or tabs module to attach your content scripts to the page? It is not currently possible to target only the top frame using page-mod, the content script will get loaded into any matching document. – therealjeffg Sep 07 '11 at 19:05
-
I want to use a WYSIWYG editor as well, I picked one called CLEditor. The only problem is that if I use page-mod than the extension is loading into it's iframe. If I use the tab module instead of that, i get a security error, the extension doesn't have the rights to access the editor iframe's window object. – Gera János Sep 07 '11 at 20:00
-
How precise can you make your url filter for the page-mod? Are you trying to page-mod *all* pages, or a very specific one? – therealjeffg Sep 07 '11 at 22:06
-
1Why not add a check to your content script and stop doing anything if `window.top != window`? – Wladimir Palant Sep 08 '11 at 06:01
-
Wladimir: I tried this at first but it didn't worked. The two objects are the same, the window object of the iframe inherited from the top window. Canuckistani: A specific one. I figured it out that i can check elements that are present in the top window but not in the iframes. Not the best solution but it worked. – Gera János Sep 08 '11 at 13:18
-
2I've seen people use if(unsafeWindow.self == unsafeWindow.top) {} , see this forum discussion: https://forums.mozilla.org/addons/viewtopic.php?t=3841 – therealjeffg Sep 08 '11 at 17:26
-
Yes, that worked! Send this comment as an answer and i will accept it. – Gera János Sep 08 '11 at 20:13
3 Answers
You could write a user script which uses the @noframes
metadata header key and include the user script in to your Jetpack with this user script package for the addon sdk.
Writing user scripts is much easier than writing Page Mods too.

- 15,988
- 11
- 54
- 98
-
3Interesting work-around! We really need to address this in page-mod directly though if only for the performance considerations when injecting content scripts into an iframe-rich page. – therealjeffg Sep 09 '11 at 17:51
Edit: now (Add-on SDK version 1.11 released) pagemod
supports what you are looking for. See the docs and the new attachTo
option.
The following information is outdated (can be used if you build against Add-on SDK 1.10 or previous:
Unfortunately pagemod
injects your script in all the frames of the page, and not just once per page on the top frame as what you achieve with Chrome's content scripts. Of course, there are workarounds for stopping the execution of the script (see the other answers).
But if you really want to inject your script only once per page, on the top frame, you have to use tabs
. With this solution you script only gets injected when it has to.
Bellow I provide and example for porting from pagemod
to tabs
, keeping all the message reception system with port
working. It can easily be modified if you need to not just receive, but also send messages using that same port
object. The script gets injected when we are in the domain youtube.com:
Old pagemod way:
var self = require("self");
var pagemod = require("page-mod");
pagemod.PageMod(
{
include: "*.youtube.com",
contentScriptFile: self.data.url("myContentScript.js"),
onAttach: function(worker)
{
worker.port.on("myMessageId", function(payload)
{
console.log("Message received: " + payload);
});
}
});
New tabs way:
var self = require("self");
var tabs = require("tabs");
tabs.on("ready", function(tab)
{
if (tab != undefined && tab.url != undefined && tab.url.split("/")[2] != undefined)
{
var domain = "youtube.com";
var host = tab.url.split("/")[2];
if (host == domain || host.substr(host.length - domain.length - 1) == "." + domain)
{
var worker = tab.attach({ contentScriptFile: self.data.url("myContentScript.js") });
worker.port.on("myMessageId", function(payload)
{
console.log("Message received: " + payload);
});
}
}
});

- 17,118
- 7
- 88
- 91
One workaround is to put something like this in your content script:
if (window.frameElement === null){
// I'm in the topmost window
// Add buttons and things to the page.
}else{
// I'm in an iFrame... do nothing!
}
The content script will still be added to every page, but it's a relatively simple and lightweight check for iFrames.

- 11,670
- 12
- 42
- 58