Постоянный уникальный идентификатор для вкладок Chrome, который сохраняется между сеансами браузера

Я пытаюсь найти способ установить уникальный идентификатор для вкладок Chrome, который удовлетворяет следующим условиям:

Uniquely identifies each tab Stays the same for a given tab between browser restarts (session-restored tabs) Stays the same if a tab is closed and then reopened with Undo Closed Tab (Ctrl+Shift+T) Stays distinct if a tab is duplicated

Я провел довольно агрессивное исследование, чтобы найти исчерпывающее решение, но, похоже, ничего не получилось. Вот методы, которые я попробовал, в порядке возрастания эффективности:

Use Chrome's provided tab.id: does not persist between browser sessions or close/undo-close Put a GUID in cookies: is not unique per tab, only per domain/URL Put a GUID in localStorage: persists between browser sessions and close/undo-close, but is not unique per tab, only per domain Put a GUID in sessionStorage: unique per tab, persists across close/undo-close, unique for duplicated tabs, but is wiped out between browser sessions Use identifiable webpage document attributes as a unique key: this is the best approach I've found so far. A key can be constructed via a content script from the following values: [location.href, document.referrer, history.length].

Что касается этого последнего подхода, созданный ключ является уникальным для всех вкладок, которые имеют общий URL, реферер и длину истории. Эти значения останутся неизменными для данной вкладки между перезапусками браузера / восстановлением сессии и закрытием / отменой закрытия. Хотя этот ключ является "довольно" уникальный, есть случаи, когда это неоднозначно: например, 3 новые вкладки открытыhttp://www.google.com у всех будет один и тот же ключ (и такое часто случается на практике).

& Quot; помещать GUID в sessionStorage & quot; Метод может дополнительно использоваться для устранения неоднозначности между несколькими вкладками с одинаковым сконструированным ключом для случаев закрытия / отмены закрытия и дублирования вкладок во время текущего сеанса браузера. Но это не решает проблему неоднозначности между перезапусками браузера.

Эта последняя неоднозначность может быть частично смягчена во время восстановления сеанса путем наблюдения за тем, какие вкладки Chrome открываются вместе, в каких окнах, и экстраполяции для данного неоднозначного ключа, к какой вкладке принадлежит какое окно, на основе присутствия ожидаемого «родственного элемента». вкладки (записанные во время предыдущего сеанса браузера). Как вы можете себе представить, реализация этого решения довольно сложная и довольно хитрая. И он может различать только вкладки с одинаковыми клавишами, которые Chrome восстанавливает в разных окнах. Это оставляет вкладки с одинаковыми клавишами, которые восстанавливаются в том же окне, как неоднозначно неоднозначные.

Есть ли способ лучше? Гарантированный уникальный генерируемый браузером GUID для каждой вкладки, который сохраняется между перезапусками браузера (восстановлением сеанса) и закрытием / отменой закрытия, был бы идеальным, но до сих пор я не нашел ничего подобного.

Ответы на вопрос(3)

Этот вопрос выполняет большую часть работы по обнаружению, и принятый ответ в основном завершает его, но существует большой разрыв в реализации для людей, желающих реализовать что-то, что требует постоянных идентификаторов вкладок. Я пытался перевести это в фактическую реализацию.

Напомним: вкладки можно (почти) однозначно и последовательно идентифицировать, как того требует вопрос, путем ведения реестра вкладок, в котором в локальной постоянной памяти хранится следующая комбинация переменных:

Tab.id Tab.index A 'fingerprint' of the document open in the tab - [location.href, document.referrer, history.length]

Эти переменные могут быть отслежены и сохранены в реестре с помощью прослушивателей для комбинации следующих событий:

onUpdated onCreated onMoved onDetached onAttached onRemoved onReplaced

Есть еще способы обмануть этот метод, но на практике они, вероятно, довольно редки - в основном крайние случаи.

Поскольку, похоже, я не единственный, кому нужно было решить эту проблему, я создал свою реализацию в виде библиотеки с намерением использовать ее в любом расширении Chrome. Это MIT лицензируется идоступно на GitHub для разветвления и извлечения запросов (на самом деле, любые отзывы будут приветствоваться - безусловно, возможны улучшения).

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

Я использую массив для сохранения данных, потому что таким образом я могу сохранить порядок вкладок, что маловероятно, если данные будут сохранены в объекте. При загрузке данных после перезапуска браузера, даже если URL-адрес не является уникальным, я могу полагать, что он будет находиться под некоторым "достаточно близко". индекс. Я бы сделал это более сложным, например, обратная проверка, если вкладка не найдена, но пока это работает нормально.

Решение Вопроса

ваш 5-й метод должен сделать свое дело, но вместе с этими двумя критериями:

chrome.tabs.windowId (The ID of the window the tab is contained within) chrome.tabs.index (The zero-based index of the tab within its window)

Все эти значения должны храниться внутри вашего расширения. Кроме того, вам также придется подключить ваше расширение кchrome.tabs.onUpdated() и обновляется соответствующим образом, когда вкладки перетаскиваются, перемещаются по окнам владельца и т. д.

 16 июн. 2012 г., 05:34
@joelpt да, windowId ненадежен, но если вы подключитеchrome.window.onCreated а такжеchrome.window.onRemoved Слушатели событий вы можете легко эмулировать индекс (идентификатор заказа) на всех окнах.
 30 сент. 2012 г., 22:09
@GeneGolovchinsky test & amp; увидеть. обычно это должно
 joelpt16 июн. 2012 г., 04:58
Я добавлю, что у меня должна быть возможность соотнести «перед перезапуском»; запомнили идентификатор окна с открытым «после перезапуска» windowId, если я могу определить любойsingle вкладка, которая имеет уникальный URL-адрес + реферер + ключ длины истории. Поскольку указанная вкладка является единственной с этим конкретным ключом, я знаю, к какому окну она принадлежит; Поэтому я знаю, что любые запомненные вкладки с тем же «старым» windowId также принадлежит к тому же «новому» окно.
 30 сент. 2012 г., 05:54
Перечисляются ли окна в одном и том же порядке между перезапусками браузера?
 joelpt16 июн. 2012 г., 04:42
Отличные идеи К сожалению, windowId изменяется между сеансами браузера, но если я могу вывести изменения windowId между сеансами, запомнив и сравнив, какие вкладки находятся в каждом окне до и после перезапуска браузера, я должен иметь возможность использовать .index, поскольку вы предлагаете устранить неоднозначность в двух других идентичных вкладках в данном окне. Большое спасибо.

Ваш ответ на вопрос