简体   繁体   English

有没有一种方法可以唯一标识内容脚本在我的Chrome扩展程序中运行的iframe?

[英]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. 在我的Chrome扩展程序中,我将内容脚本注入到页面内的所有IFRAMEs Here's a part of the manifest.json file: 这是manifest.json文件的一部分:

"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 . 因此,具有多个IFRAMEs的单个网页最终将运行我注入的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. content.js内部的逻辑从其注入的每个IFRAME或从主页/首页收集数据,并将其发送回后台脚本 (使用chrome.runtime.sendMessage 。) 后台脚本又需要存储数据。在全局变量中,以后将在扩展本身中使用。

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. 我面临的问题是应用程序需要区分从多个IFRAMEs接收到的“数据”,因为我的数据收集方法可以在用户与页面进行交互时反复调用,因此我不能简单地“转储”接收到的数据由后台脚本分成一个数组。 Instead I need to use a dictionary -type data storage. 相反,我需要使用dictionary类型的数据存储。

I can tell if the data is coming from an IFRAME or from the top page by running the following: 通过运行以下命令,我可以判断数据是来自IFRAME还是来自首页:

//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: 我的想法是,如果我收集每个IFRAME页面URL,那么我应该能够将其用作唯一的键,以将数据存储在字典型全局变量下:

//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. 嗯,这行不通,因为两个或多个IFRAMEs可以具有相同的URL。

So thus my original question -- how to tell IFRAMEs on the page apart? 因此,这就是我最初的问题-如何区分页面上的IFRAMEs Is there some unique ID or somethign that Chrome assigns to them? Chrome是否为其分配了一些唯一的ID或其他信息?

You can identify the relative place of the document in the hierarchy of iframes. 您可以在iframe层次结构中标识文档的相对位置。 Depending on the structure of the page, this can solve your problem. 根据页面的结构,这可以解决您的问题。

Your extension is able to access window.parent and its frames. 您的扩展程序可以访问window.parent及其框架。 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. 您可以对其进行修改,以支持嵌套iframe,但是该原理应该有效。

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

Just to expand on @Xan's answer , here's my method of getting an IFRAME 's index considering its possible nesting within other IFRAMEs . 只是为了扩大对@克桑的答案 ,这是我得到一个的方法IFRAME的指数考虑其他内及其可能的嵌套IFRAMEs I'll use the forward-iframe notation, meaning that the parent IFRAME index will be given first, followed by child indexes, etc. Also to prevent a possible confusion with floating-point numbers I'll use the underscore for a separator instead of the dot. 我将使用前向iframe表示法,这意味着将首先给出父级IFRAME索引,然后是子级索引,等等。此外,为了避免与浮点数混淆,我将使用下划线代替分隔符点。

So to answer my original question, once I have IFRAME index within the page, it will uniquely identify it in that page (coupled with the IFRAME 's URL.) 因此,要回答我的原始问题,一旦我在页面中有了IFRAME索引,它就会在该页面中唯一标识它(以及IFRAME的URL)。

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

You can generate a pseudo-unique id using a combination of timestamp and a random number every time a content script loads, like this: 每次加载内容脚本时,都可以使用时间戳和随机数的组合生成伪唯一ID,如下所示:

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

And then send all your data-related messages to the background with this ID. 然后使用此ID将所有与数据相关的消息发送到后台。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM