有没有一种方法来唯一标识内容脚本运行在我的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将所有与数据相关的消息发送到后台。