2012-06-12 16 views
5

Sto cercando di accertare un modo per stabilire un ID univoco per schede di Chrome che soddisfi le seguenti condizioni:persistente ID univoco per schede di Chrome che dura tra le sessioni del browser

  • identifica univocamente ogni scheda
  • Soggiorni lo stesso per una data scheda tra riavvii del browser (schede ripristinate dalla sessione)
  • Restituisce lo stesso se una scheda viene chiusa e quindi riaperta con Annulla scheda chiusa (Ctrl + Shift + T)
  • Soggiorni distinti se una scheda è duplicata

Ho fatto una ricerca piuttosto aggressiva per trovare una soluzione completa, ma nulla sembra fare il trucco. Questi sono i metodi che ho provato, in ordine crescente di efficacia:

  • tab.id fornito Usa Chrome: non persistono tra le sessioni del browser o Chiudi/Annulla-vicino
  • Mettere un GUID nei cookie : non è univoco per ogni scheda, solo per dominio/URL
  • Mettere un GUID in localStorage: persiste tra le sessioni del browser e vicino/annullare-vicino, ma non è univoco per ogni scheda, solo per dominio
  • Metti un GUID in sessionStorage: univoco per ogni scheda, persiste in tutto Chiudi/Annulla-vicino, unico nel suo genere per le schede duplicate, ma viene spazzato via tra le sessioni del browser
  • Usa documento pagina web identificabile attributi come chiave univoca: questo è il approccio migliore che ho trovato finora. Una chiave può essere costruita tramite uno script di contenuto dai seguenti valori: [location.href, document.referrer, history.length].

Per quanto riguarda quest'ultimo approccio, la chiave costruita è unica in tutte le schede che condividono un URL, un referente e una cronologia comuni. Tali valori rimarranno gli stessi per una data scheda tra riavvii del browser/ripristini di sessione e chiudi/chiudi/chiudi. Sebbene questa chiave sia "carina" unica, ci sono casi in cui è ambigua: ad esempio, 3 nuove schede aperte a http://www.google.com hanno tutte la stessa chiave in comune (e questo genere di cose accade abbastanza spesso nella pratica).

Il metodo "metti GUID in sessionStorage" può anche essere usato per disambiguare tra più schede con la stessa chiave costruita per i casi chiusura/chiusura e tabulazione duplicata durante la sessione corrente del browser. Ma questo non risolve il problema di ambiguità tra i riavvii del browser.

Quest'ultima ambiguità può essere parzialmente attenuata durante il ripristino della sessione osservando quali schede Chrome si apre insieme in cui finestre e estrapolando per una determinata chiave ambigua quale scheda appartiene a quale finestra in base alla presenza delle schede "fratello" previste (registrate durante la precedente sessione del browser). Come puoi immaginare, l'implementazione di questa soluzione è abbastanza complicata e piuttosto rischiosa. E può solo disambiguare tra le schede con lo stesso codice che Chrome ripristina in finestre diverse. Ciò lascia linguette identiche che si ripristinano nella stessa finestra inconciliabilmente ambigue.

C'è un modo migliore? Un GUID univoco, generato da browser, garantito per browser, che permane tra i riavvii del browser (ripristini di sessione) e chiusura/chiusura-chiusura sarebbe l'ideale, ma finora non ho trovato nulla di simile.

risposta

1

Se ho capito bene il problema, il vostro 5 ° metodo dovrebbe fare il trucco, ma insieme a questi due criteri:

  • chrome.tabs.windowId (L'ID della finestra della scheda è contenuto all'interno)
  • chrome.tabs.index (L'indice a base zero della scheda all'interno della sua finestra)

Tutti questi valori devono essere memorizzati all'interno dell'estensione. Oltre a ciò, dovrai anche collegare la tua estensione a chrome.tabs.onUpdated() e aggiornare di conseguenza, quando le schede vengono trascinate, spostate tra le finestre del proprietario, ecc.

+0

Grandi idee. Purtroppo windowId cambia tra le sessioni del browser, ma se posso dedurre le modifiche di windowId tra le sessioni ricordando e confrontando quali schede sono presenti in ogni finestra prima e dopo il riavvio del browser, dovrei essere in grado di usare .index come suggerisci di disambiguare due altrimenti schede identiche in una data finestra. Grazie mille. – joelpt

+0

Aggiungerò che dovrei essere in grado di correlare una finestra "prima del riavvio" ricordata con un windowId "after-restart" aperto, se posso identificare qualsiasi * single * tab che abbia un url univoco + referrer + chiave historylength. Poiché detta scheda è l'unica con quella particolare chiave, so a quale finestra appartiene; Pertanto, so che tutte le schede memorizzate con la stessa finestra "vecchia" appartengono anche alla stessa "nuova" finestra. – joelpt

+1

@joelpt yes, windowId non è affidabile ma se si collegano i listener di eventi 'chrome.window.onCreated' e' chrome.window.onRemoved' è possibile emulare facilmente un indice (ID ordine) su tutte le finestre. –

3

La domanda qui fa la maggior parte del lavoro di scoperta e la risposta accettata sostanzialmente lo completa, ma c'è ancora un grande gap di implementazione per le persone che cercano di implementare qualcosa che richiede ID di tabulazione persistenti. Ho tentato di distillare questo in un'implementazione reale.

Per ricapitolare: schede può essere (quasi) univoco e coerente identificato come richiesto dalla domande per mantenere un registro delle linguette che memorizza la seguente combinazione di variabili in memoria permanente locale:

  • Tab.id
  • Tab.index
  • Un 'impronta digitale' del documento aperto nella scheda - [location.href, document.referrer, history.length]

Queste variabili possono essere monitorati e memorizzati nel Registro di sistema utilizzando gli ascoltatori su una combinazione dei seguenti eventi:

  • onUpdated
  • onCreated
  • onMoved
  • onDetached
  • onAttached
  • onRemoved
  • onReplaced

Ci sono ancora modi per ingannare questo metodo, ma in pratica sono probabilmente piuttosto rari, per lo più casi limite.

Poiché sembra che non sia l'unico che ha avuto bisogno di risolvere questo problema, ho costruito la mia implementazione come libreria con l'intenzione che potesse essere utilizzata in qualsiasi estensione di Chrome. È autorizzato dal MIT e available on GitHub per le richieste di forking e pull (in effetti, qualsiasi commento sarebbe gradito - ci sono sicuramente miglioramenti possibili).

1

Mettete questo come uno script sfondo persistente manifest.json:

"background": { 
     "scripts": [ "background.js" ], 
     "persistent": true 
}, 

Ecco background.js. Speriamo che il codice sia auto esplicativo.

var tabs_hashes = {}; 
var tabs_hashes_save_queued = false; 

function Start(){ 
    chrome.tabs.query({windowType: "normal"}, function(querytabs){ 
     querytabs.forEach(function(tab){ 
      tabs_hashes[tab.id] = GetHash(tab.url); 
     }); 

     if (localStorage.getItem("tabs_hashes") !== null){ 

      var ref_load = JSON.parse(localStorage["tabs_hashes"]); 
      var ref_tabId = {}; 


      querytabs.forEach(function(tab){ 
       for (var t = 0; t < ref_load.length; t++){ 
        if (ref_load[t][1] === tabs_hashes[tab.id]){ 
         ref_tabId[ref_load[t][0]] = tab.id; 
         ref_load.splice(t, 1); 
         break; 
        } 
       } 
      }); 

      // do what you have to do to convert previous tabId to the new one 
      // just use ref_tabId[your_previous_tabId] to get the current corresponding new tabId 
      console.log(ref_tabId); 

     } 
    }); 
} 


function SaveHashes(){ 
    if (!tabs_hashes_save_queued && Object.keys(tabs_hashes).length > 0){ 
     tabs_hashes_save_queued = true; 
     chrome.tabs.query({windowType: "normal"}, function(querytabs){ 
      var data = []; 
      querytabs.forEach(function(tab){ 
       if (tabs_hashes[tab.id]){ 
        data.push([tab.id, tabs_hashes[tab.id]]); 
       } else { 
        data.push([tab.id, GetHash(tab.url)]); 
       } 
      }); 
      localStorage["tabs_hashes"] = JSON.stringify(data); 
      setTimeout(function(){ tabs_hashes_save_queued = false; }, 1000); 
     }); 
    } 
} 

function GetHash(s){ 
    var hash = 0; 
    if (s.length === 0){ 
     return 0; 
    } 
    for (var i = 0; i < s.length; i++){ 
     hash = (hash << 5)-hash; 
     hash = hash+s.charCodeAt(i); 
     hash |= 0; 
    } 
    return Math.abs(hash); 
} 


chrome.tabs.onCreated.addListener(function(tab){ 
    SaveHashes(); 
}); 
chrome.tabs.onAttached.addListener(function(tabId){ 
    SaveHashes(); 
}); 
chrome.tabs.onRemoved.addListener(function(tabId){ 
    delete tabs_hashes[tabId]; 
    SaveHashes(); 
}); 
chrome.tabs.onDetached.addListener(function(tabId){ 
    SaveHashes(); 
}); 
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo){ 
    if (changeInfo.pinned != undefined || changeInfo.url != undefined){ 
     delete tabs_hashes[tabId]; 
     SaveHashes(); 
    } 
}); 
chrome.tabs.onMoved.addListener(function(tabId){ 
    SaveHashes(); 
}); 
chrome.tabs.onReplaced.addListener(function(addedTabId, removedTabId){ 
    delete tabs_hashes[removedTabId]; 
    SaveHashes(); 
}); 


Start(); 

che uso matrice per salvare i dati, perché in questo modo posso mantenere l'ordine linguette, che è improbabile se i dati saranno memorizzati nell'oggetto. Quando carico i dati dopo il riavvio del browser, anche se url non è univoco, posso fidarmi che sarà sotto un indice "abbastanza vicino". Lo farei più complesso, ad esempio, controllo inverso se la scheda non è stata trovata, ma questo funziona ok finora.

Problemi correlati