A persistent unique identifier for Chrome tabs that lasts between browser sessions

I'm trying to figure out how to set a unique identifier for Chrome tabs that satisfies the following conditions:

  • Uniquely identifies each tab
  • Remains unchanged for this tab between browser restarts (tabs restored by the session)
  • Remains unchanged if the tab is closed and then reopened using the Undo Closed tab (Ctrl + Shift + T)
  • Saved if duplication is duplicated.

I did some pretty aggressive research to find a complete solution, but it doesn't seem to do anything like that. Here are the methods I tried, in order of increasing efficiency:

  • Use Chrome provided that tab.id: is not saved between browser sessions or closing / unsealing
  • Put GUID in cookies: not unique for each tab, only for domain / URL
  • Put the GUID in localStorage: saved between browser sessions and closed / canceled, but not unique for each tab, only for the domain
  • Put the GUID in sessionStorage: unique to each tab, retained by closing / undoing, unique to duplicate tabs, but destroyed between browser sessions.
  • Using identifiable attributes of a web page document as a unique key: this is the best approach I've found so far. The key can be created using the content of the following script: [location.href, document.referrer, history.length].

, , URL-, . /- / . "" , , : , , http://www.google.com, ( ).

"put GUID in sessionStorage" / . .

, , Chrome , , , , "sibling" ( ). , . , Chrome . , , .

? , GUID GUID, ( ) close/undo-close, , .

+5
3

, 5- , :

  • chrome.tabs.windowId ( , )
  • chrome.tabs.index ( )

. , chrome.tabs.onUpdated() , , ..

+1

, , , -, . .

: () , , :

  • Tab.id
  • Tab.index
  • "" - [location.href, document.referrer, history.length]

:

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

, , , - .

, , , , Chrome. MIT GitHub forking pull ( , - ).

+3

script manifest.json:

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

background.js. , .

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

I use an array to save data, because in this way I can save the order of the tabs, which is unlikely if the data will be stored in the object. When loading data after restarting the browser, even if the URL is not unique, I can trust that it will be under some index “close enough”. I would make it more complicated, for example, checking back if the tab is not found, but for now it works fine.

+1
source

All Articles