In my Chrome extension I am injecting the content script into all IFRAMEs
inside a page. Here's a part of the manifest.json
file:
"content_scripts": [
{
"run_at": "document_end",
"all_frames" : true,
"match_about_blank": true,
"matches": ["http://*/*", "https://*/*"],
"js": ["content.js"]
}
],
So a single web page having multiple IFRAMEs
will end up running that many copies of my injected content.js
.
The logic inside content.js
collects data from each IFRAME
it's injected into, or from the main/top page, and sends it back to the background script (using chrome.runtime.sendMessage
.) The background script in turn needs to store the data in the global variable, that is later used in the extension itself.
The issue I'm facing is that the app needs to distinguish between the "data" received from multiple IFRAMEs
, since my data collection method can be called repeatedly upon user's interaction with the page, and thus I cannot simply "dump" the data received by the background script into an array. Instead I need to use a dictionary
-type data storage.
I can tell if the data is coming from an IFRAME
or from the top page by running the following:
//From the `content.js`
var isIframe = window != window.top;
and my thinking was that if I collect page URLs of each IFRAME
then I should be able to use it as a unique key to store the data under in my dictionary-type global variable:
//Again from content.js
var strUniqueIFrameURL = document.URL;
Well, that is not going to work, because two or more IFRAMEs
can have the same URLs.
So thus my original question -- how to tell IFRAMEs
on the page apart? Is there some unique ID or somethign that Chrome assigns to them?
You can identify the relative place of the document in the hierarchy of iframes. Depending on the structure of the page, this can solve your problem.
Your extension is able to access window.parent
and its frames. This should work, or at least works for me in a test case:
// Returns the index of the iframe in the parent document,
// or -1 if we are the topmost document
function iframeIndex(win) {
win = win || window; // Assume self by default
if (win.parent != win) {
for (var i = 0; i < win.parent.frames.length; i++) {
if (win.parent.frames[i] == win) { return i; }
}
throw Error("In a frame, but could not find myself");
} else {
return -1;
}
}
You can modify this to support nesting iframes, but the principle should work.
I was itching to do it myself, so here you go:
// Returns a unique index in iframe hierarchy, or empty string if topmost
function iframeFullIndex(win) {
win = win || window; // Assume self by default
if (iframeIndex(win) < 0) {
return "";
} else {
return iframeFullIndex(win.parent) + "." + iframeIndex(win);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With