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

In my Chrome extension, I embed the contents of the script in all the IFRAMEs inside the page. Here is 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"] } ], 

Thus, a single webpage containing multiple IFRAMEs will end up launching many copies of my embedded content.js .

The logic inside content.js collects data from each IFRAME that it enters, 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 data in a global variable , which will later be used in the extension itself.

The problem I am facing is that the application must distinguish between โ€œdataโ€ received from several IFRAMEs , since my data collection method can be called repeatedly when the user interacts with the page, and therefore I canโ€™t just โ€œdumpโ€ the data. received background script into an array. Instead, I need to use the dictionary data store.

I can tell if the data comes from IFRAME or from the top page by running the following:

 //From the `content.js` var isIframe = window != window.top; 

and I thought that if I collect the URLs of the pages of each IFRAME , then I will have to use it as a unique key to store data in my global dictionary-type variable:

 //Again from content.js var strUniqueIFrameURL = document.URL; 

Well, this will not work, because two or more IFRAMEs can have the same URLs.

So, thus, my original question is how to tell IFRAMEs on a page separately? Is there some kind of unique identifier or something like what Chrome assigns them?

+1
source share
3 answers

You can determine the relative position of the document in the iframes hierarchy. Depending on the page structure, this may solve your problem.

Your extension has access to 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 change this to support nesting frames, but the principle should work.

I had an itch 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); } } 
+4
source

Just to expand on @Xan's answer , here is my method of getting the IFRAME index, given its possible attachment to other IFRAMEs . I will use iframe formatting, which means the parent index IFRAME will be specified first, and then the child indexes, etc. Also to prevent possible confusion with floating point numbers, I use an underscore for the separator instead of a period.

So, in order to answer my initial question, as soon as I have an IFRAME index on a page, it uniquely identifies it on that page (in combination with the IFRAME URL.)

Here is the code to get it:

 function iframeIndex(wnd) { //RETURN: // = "" for top window // = IFrame zero-based index with nesting, example: "2", or "0_4" // = "?" if error return _iframeIndex(wnd || window); // Assume self by default } function _iframeIndex(wnd) { var resInd = ""; var wndTop = window.top; if(wnd == wndTop) return resInd; var wndPar = wnd.parent; if(wndPar != wndTop) { resInd = _iframeIndex(wndPar) + "_"; } var frmsPar = wndPar.frames; for(var i = 0; i < frmsPar.length; i++) { if(frmsPar[i] == wnd) return resInd + i; } return resInd + "?"; } 
+1
source

You can generate a pseudo-unique identifier using a combination of a timestamp and a random number when loading the contents of a script, for example:

 var psUid = (new Date()).getTime() + '_' + Math.random(); 

And then send all your data-related messages to the background with this identifier.

0
source

Source: https://habr.com/ru/post/1232251/


All Articles