C’è un modo per identificare in modo univoco un iframe in cui viene eseguito lo script di contenuto per la mia estensione di Chrome?

Nell’estensione di Chrome sto inserendo lo script di contenuto in tutti gli IFRAMEs all’interno di una pagina. Ecco una parte del file manifest.json :

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

Quindi una singola pagina web con più IFRAMEs finirà con l’esecuzione di molte copie del mio content.js .

La logica all’interno di content.js raccoglie i dati da ciascun IFRAME cui è stato iniettato, o dalla pagina principale / principale, e li rimanda allo script di sfondo (utilizzando chrome.runtime.sendMessage .) Lo script di background a sua volta deve memorizzare i dati nella variabile globale, che viene successivamente utilizzata nell’estensione stessa.

Il problema che sto affrontando è che l’app deve distinguere tra i “dati” ricevuti da più IFRAMEs , dal momento che il mio metodo di raccolta dei dati può essere chiamato ripetutamente in base all’interazione dell’utente con la pagina, e quindi non posso semplicemente “scaricare” i dati ricevuti dallo script di sfondo in un array. Invece ho bisogno di usare un immagazzinamento di dati di tipo dictionary .

Posso sapere se i dati provengono da un IFRAME o dalla pagina principale eseguendo quanto segue:

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

e il mio pensiero è che se raccolgo gli URL delle pagine di ogni IFRAME dovrei essere in grado di usarlo come chiave univoca per memorizzare i dati nella mia variabile globale del tipo di dizionario:

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

Bene, non funzionerà, perché due o più IFRAMEs possono avere gli stessi URL.

Quindi, quindi, la mia domanda iniziale: come distinguere gli IFRAMEs dalla pagina? C’è qualche ID univoco o qualcosa che Chrome assegna loro?

È ansible identificare la posizione relativa del documento nella gerarchia degli iframe. A seconda della struttura della pagina, questo può risolvere il tuo problema.

La tua estensione è in grado di accedere a window.parent e ai suoi frame. Questo dovrebbe funzionare, o almeno funziona per me in un caso di test:

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

È ansible modificare questo per supportare gli iframe di nidificazione, ma il principio dovrebbe funzionare.

Avevo voglia di farlo da solo, quindi ecco qua:

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

Solo per espandere la risposta di @ Xan, ecco il mio metodo per ottenere un indice di IFRAME considerando il ansible nidificazione all’interno di altri IFRAMEs . Userò la notazione forward-iframe, il che significa che l’indice IFRAME genitore sarà dato per primo, seguito da indici figlio, ecc. Inoltre, per evitare una ansible confusione con numeri in virgola mobile, userò il carattere di sottolineatura per un separatore invece di il punto.

Quindi, per rispondere alla mia domanda iniziale, una volta che ho indice IFRAME all’interno della pagina, lo identificherà in modo univoco in quella pagina (abbinato all’URL IFRAME ).

Ecco il codice per ottenerlo:

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

Puoi generare un ID pseudo-unico usando una combinazione di data / ora e un numero casuale ogni volta che viene caricato uno script di contenuto, come questo:

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

E quindi invia tutti i tuoi messaggi relativi ai dati in background con questo ID.