Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to uniquely identify an iframe that the content script runs in for my Chrome extension?

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?

like image 287
c00000fd Avatar asked Feb 12 '23 23:02

c00000fd


1 Answers

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);
   }
}
like image 92
Xan Avatar answered Feb 14 '23 18:02

Xan