有没有一种方法来唯一标识内容脚本运行在我的Chrome扩展的iframe?

在我的Chrome扩展中,我将内容脚本注入到页面内的所有IFRAMEs 。 这是manifest.json文件的一部分:

 "content_scripts": [ { "run_at": "document_end", "all_frames" : true, "match_about_blank": true, "matches": ["http://*/*", "https://*/*"], "js": ["content.js"] } ], 

因此,一个具有多个IFRAMEs网页将最终运行我注入content.js许多副本。

content.js的逻辑从其注入的每个IFRAME收集数据,或从主/首页收集数据,并将其发送回后台脚本 (使用chrome.runtime.sendMessage )。 后台脚本又需要存储数据在全局variables中,稍后在扩展中使用。

我面临的问题是,应用程序需要区分从多个IFRAMEs接收到的“数据”,因为我的数据收集方法可以在用户与页面交互时重复调用,因此我不能简单地“转储”收到的数据由后台脚本变成一个数组。 相反,我需要使用dictionary典型的数据存储。

我可以通过运行以下命令来判断数据是来自IFRAME还是来自顶部页面:

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

我的想法是,如果我收集每个IFRAME页面URL,那么我应该可以把它作为一个唯一的键来存储在我的字典型全局variables下的数据:

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

那么,这是行不通的,因为两个或更多的IFRAMEs可以有相同的URL。

所以,我的原始问题 – 如何分辨页面上的IFRAMEs ? Chrome是否分配给他们一些独特的ID或某些信息?

您可以识别文档在iframe层次结构中的相对位置。 根据页面的结构,这可以解决您的问题。

你的扩展能够访问window.parent及其框架。 这应该起作用,或者至less在testing用例中适用于我:

 // 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; } } 

你可以修改这个来支持嵌套iframe,但是这个原则应该工作。

我很渴望自己做,所以在这里你去:

 // 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); } } 

只是扩展@ Xan的答案 ,这里是我的IFRAME的索引的方法,考虑其可能在其他IFRAME嵌套。 我将使用forward-iframe表示法,这意味着将首先给出父IFRAME索引,然后是子索引等。另外,为了防止与浮点数混淆,我将使用下划线代替点。

所以要回答我原来的问题,一旦我在页面中有IFRAME索引,它将在该页面中唯一标识(与IFRAME的URL结合)。

以下是获取它的代码:

 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 + "?"; } 

每次内容脚本加载时,您都可以使用时间戳和随机数的组合来生成伪唯一标识,如下所示:

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

然后用这个ID将所有与数据相关的消息发送到后台。