Постоянный уникальный идентификатор для вкладок Chrome, который сохраняется между сеансами браузера
Я пытаюсь найти способ установить уникальный идентификатор для вкладок Chrome, который удовлетворяет следующим условиям:
- однозначно идентифицирует каждую вкладку
- остается неизменным для данной вкладки между перезапусками браузера (вкладки с восстановленным сеансом)
- остается неизменным, если вкладка закрыта, а затем снова открыта с помощью функции отменить закрытую вкладку (Ctrl + Shift+T)
- остается отличным, если вкладка дублируется
Я провел несколько довольно агрессивных исследований, чтобы найти всеобъемлющее решение, но кажется, ничего не помогает. Вот методы, которые я пробовал, в порядке возрастания эффективности:
использовать хром, предоставленной вкладке.идентификатор: не сохраняется между сеансами браузера или закрыть/отменить-закрыть
поместите GUID в cookies: не является уникальным для каждой вкладки, только для домена / URL
поместите GUID в localStorage: сохраняется между сеансами браузера и close / undo-close, но не является уникальным для каждой вкладки, только для домена
введите GUID sessionStorage: уникальный для каждой вкладки, сохраняется при закрытии / отмене закрытия, уникален для дублированных вкладок, но стирается между сеансами браузера
используйте идентифицируемые атрибуты документа веб-страницы в качестве уникального ключа: Это лучший подход, который я нашел до сих пор. Ключ может быть сконструирован с помощью скрипта содержимого из следующих значений:[location.href, document.referrer, history.length].
Что касается последнего подхода, сконструированный ключ уникален для всех вкладок, которые имеют общий URL, реферер и историю длина. Эти значения останутся неизменными для данной вкладки между перезапуском браузера/восстановлением сеанса и закрытием/отменой закрытия. Хотя этот ключ" довольно " уникален, есть случаи, когда он неоднозначен: например, 3 новые вкладки, открытые в http://www.google.com у всех был бы один и тот же общий ключ (и на практике такое случается довольно часто).
Метод "put GUID in sessionStorage" можно дополнительно использовать для устранения неоднозначности между несколькими вкладками с одним и тем же именем. сконструированный ключ для случаев закрытия / отмены-закрытия и дублированной-вкладки во время текущего сеанса браузера. Но это не решает проблему неоднозначности между перезапусками браузера.
Эта последняя неопределенность может быть частично смягчена во время восстановления сеанса, наблюдая, какие вкладки Chrome открываются вместе в каких окнах, и экстраполируя для данного неоднозначного ключа, какая вкладка принадлежит какому окну, основываясь на наличии ожидаемых "родственных" вкладок (записанных во время предыдущей сессии браузера). Как вы можете себе представить, что реализация этого решения довольно запутанная и довольно изворотливая. И он может только устранить неоднозначность между вкладками с одинаковыми ключами, которые Chrome восстанавливает в разных окнах. Это оставляет одинаковые вкладки, которые восстанавливаются в одном окне, как непримиримо неоднозначные.
Есть ли лучший способ? Гарантированный уникальный, созданный браузером GUID для каждой вкладки, который сохраняется между перезапуском браузера (восстановление сеанса) и закрытием / отменой закрытия, был бы идеальным, но до сих пор я не нашел ничего подобного этот.
3 ответов:
Если я правильно понимаю вашу проблему, ваш 5-й метод должен сделать трюк, но вместе с этими двумя критериями:
chrome.tabs.windowId(идентификатор окна, в котором находится вкладка)chrome.tabs.index(нулевой индекс вкладки в ее окне)Все эти значения должны храниться внутри вашего расширения. Кроме того, вам также придется подключить ваше расширение к
chrome.tabs.onUpdated()и соответственно обновляться, когда вкладки перетаскиваются, перемещаются по окнам владельца, и т.д.
Вопрос здесь выполняет большую часть работы по обнаружению, и принятый ответ в основном завершает ее, но все еще существует большой пробел в реализации для людей, желающих реализовать что-то, что требует постоянных идентификаторов вкладок. Я попытался перегнать это в реальную реализацию.
Чтобы резюмировать: вкладки могут быть (почти) однозначно и последовательно идентифицированы в соответствии с требованиями вопроса, поддерживая регистр вкладок, который хранит следующую комбинацию переменных в локальном постоянное хранение:
Эти переменные могут быть отслежены и сохранены в реестре с помощью прослушивателей в комбинации следующих событий:
Tab.idTab.index- отпечаток пальца документа, открытого на вкладке -
[location.href, document.referrer, history.length]
onUpdatedonCreatedonMovedonDetachedonAttachedonRemovedonReplacedЕсть еще способы обмануть этот метод, но на практике они, вероятно, довольно редко - в основном крайние случаи.
Поскольку похоже, что я не единственный, кому нужно было решить эту проблему, я построил свою реализацию как библиотеку с намерением, что она может быть использована в любом расширении Chrome. Он лицензирован MIT идоступен на GitHub для запросов на раздвоение и вытягивание (на самом деле, любая обратная связь будет приветствоваться - определенно возможны улучшения).
Поместите это как постоянный фоновый сценарий в манифест.json:
"background": { "scripts": [ "background.js" ], "persistent": true },Вот предыстория.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 не является уникальным, я могу быть уверен, что он будет находиться под каким-то "достаточно близким" индексом. Я бы сделал это более сложным, например обратный чек, если бы tab не было найдено, но это работает нормально до сих пор.
Comments