Гобелен - кликните для возврата на главную
Не прошло и месяца а Фурмановская ЦРБ в очередной раз попала в историю. На этот раз сотрудница клеветала на пациентов, а именно огласку получил случай когда сотрудница назвала пациента алкашём.
После того как в некоторых случаях перестала работать программа goodbydpi появились сложности с просмотром сайта YouTube. В конце мая 2025 года стало доступно расширение позволяющее разблокировать сайт YouTube в браузере Firefox на территории России.
Ровно 3 года назад произошло событие, которое подарило жителям планеты Змеля новый чистый праздник 6 апреля - в этот замечательный день земля забрала гнить негодяя и СПАМера Владимира Вольфовича Жириновского.
Как бы не обстояли дела в области культуры и IT-технологий, Самосвал писал статьи на связанные темы и планирует ещё написать.
На очередном конкурсе танцев, школьница отлично выступила.
Вот та самая информация: программа для продвижения канала YouTube, эта информация выложена уже несколько лет, при этом просмотров не много, а метод который описан в данном видео действительно помогает продвигать видео в YouTube.
Начал разбираться с информацией которая находится в HTTPS клиентском запросе рукопожатия.
Обратите внимание! Объект изображённый на гобилене может отличаться от общепринятого вида описанного объекта. Тут дело в том что художник видит именно так!
Доброго времени суток. Вопрос про расширение для Firefox. Ситуация следующая, так как расширение которое я в частности сейчас делаю обменивается данными с сервером(расширения), мне необходимо как то отличать экземпляры которые присылают данные. Подскажите пожалуйста есть ли при установке приложения какой то идентификатор который не меняется про последующих загрузках браузера. И если ли сессионный идентификатор который меняется при перезагрузке браузера. Приведите пример расширения которое в окне(которое появляется при клике на расширение на панели) будет отображать первый и второй вариант идентификатора. Если системно таковых идентификаторов не существует, реализуйте методы их генерации и хранения.
Для вашего Firefox расширения, которое обменивается данными с сервером, я предлагаю следующие подходы для идентификации экземпляров:
1. Постоянный идентификатор (не меняется после перезагрузки)
Firefox предоставляет API browser.runtime.id, но это ID самого расширения, а не его экземпляра. Для уникального идентификатора экземпляра можно использовать storage.local с генерируемым UUID.
2. Сессионный идентификатор (меняется после перезагрузки)
Для сессионного ID можно генерировать новый UUID при каждом запуске браузера.
Пример реализации
Вот полный код расширения, которое отображает оба идентификатора:
Файл manifest.json
{
"manifest_version": 2,
"name": "Instance ID Viewer",
"version": "1.0",
"description": "Displays persistent and session instance IDs",
"icons": {
"48": "icon.png"
},
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": [
"storage"
]
}
Файл popup.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ID Viewer</title>
<style>
body {
width: 200px;
padding: 10px;
font-family: Arial, sans-serif;
}
.id-container {
margin-bottom: 10px;
}
.id-label {
font-weight: bold;
display: block;
margin-bottom: 5px;
}
.id-value {
font-family: monospace;
font-size: 12px;
word-break: break-all;
}
</style>
</head>
<body>
<div class="id-container">
<span class="id-label">Persistent ID:</span>
<span id="persistent-id" class="id-value"></span>
</div>
<div class="id-container">
<span class="id-label">Session ID:</span>
<span id="session-id" class="id-value"></span>
</div>
<script src="popup.js"></script>
</body>
</html>
Файл popup.js
// Генерация UUID
function generateUUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
// Инициализация идентификаторов
async function initIds() {
// Получаем или создаем постоянный ID
let { persistentId } = await browser.storage.local.get('persistentId');
if (!persistentId) {
persistentId = generateUUID();
await browser.storage.local.set({ persistentId });
}
// Получаем или создаем сессионный ID
let { sessionId } = await browser.storage.session.get('sessionId');
if (!sessionId) {
sessionId = generateUUID();
await browser.storage.session.set({ sessionId });
}
// Отображаем ID
document.getElementById('persistent-id').textContent = persistentId;
document.getElementById('session-id').textContent = sessionId;
}
// Запускаем при загрузке
document.addEventListener('DOMContentLoaded', initIds);
Постоянный идентификатор:
Сессионный идентификатор:
Генерируется при каждом запуске браузера Сохраняется в browser.storage.session (доступно в Firefox) Сбрасывается при закрытии браузера Альтернативный подход Если browser.storage.session недоступен в вашей версии Firefox, можно использовать обычный browser.storage.local с флагом сессии: javascript // Альтернативная реализация сессионного ID async function getSessionId() { // Проверяем, есть ли сохраненный ID сессии let { sessionId, sessionActive } = await browser.storage.local.get(['sessionId', 'sessionActive']); // Если нет ID или сессия неактивна (браузер был перезапущен) if (!sessionId || !sessionActive) { sessionId = generateUUID(); await browser.storage.local.set({ sessionId, sessionActive: true }); } return sessionId; } // При загрузке расширения помечаем сессию как активную browser.runtime.onStartup.addListener(() => { browser.storage.local.set({ sessionActive: true }); }); // При выгрузке расширения помечаем сессию как неактивную browser.runtime.onSuspend.addListener(() => { browser.storage.local.set({ sessionActive: false }); }); Это расширение будет показывать два идентификатора в popup-окне, что позволит вам различать экземпляры как на сервере, так и в аналитике. Есть предположение что Вы меняете сессионный идентификатор при загрузке конкретной страницы. Я имел ввиду загрузку браузера а не страницы. Вы совершенно правы! Давайте переработаем решение, чтобы сессионный идентификатор менялся только при запуске браузера, а не при загрузке каждой страницы или открытии popup. Исправленная реализация Основные изменения: Сессионный ID будет генерироваться при старте браузера Используем background script для управления сессией Popup будет только отображать заранее сгенерированные ID Обновленный manifest.json: json { "manifest_version": 2, "name": "Instance ID Viewer", "version": "1.0", "description": "Displays persistent and session instance IDs", "icons": { "48": "icon.png" }, "browser_action": { "default_icon": "icon.png", "default_popup": "popup.html" }, "background": { "scripts": ["background.js"], "persistent": false }, "permissions": [ "storage" ] } Новый файл background.js:
// Генерация UUID
function generateUUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
// Инициализация идентификаторов при запуске браузера
browser.runtime.onStartup.addListener(async () => {
// Постоянный ID (если нет - создаем)
let { persistentId } = await browser.storage.local.get('persistentId');
if (!persistentId) {
persistentId = generateUUID();
await browser.storage.local.set({ persistentId });
}
// Генерируем новый сессионный ID при старте браузера
const sessionId = generateUUID();
await browser.storage.local.set({ sessionId });
});
// Также инициализируем при установке расширения
browser.runtime.onInstalled.addListener(async () => {
const persistentId = generateUUID();
const sessionId = generateUUID();
await browser.storage.local.set({ persistentId, sessionId });
});
Обновленный popup.js:
javascript
// Просто отображаем сохраненные ID
async function displayIds() {
const { persistentId, sessionId } = await browser.storage.local.get(['persistentId', 'sessionId']);
document.getElementById('persistent-id').textContent = persistentId || 'Not set';
document.getElementById('session-id').textContent = sessionId || 'Not set';
}
document.addEventListener('DOMContentLoaded', displayIds);
При запуске браузера:
Срабатывает onStartup в background script Генерируется новый сессионный ID Постоянный ID остается неизменным (или создается при первом запуске) При открытии popup: Скрипт просто получает сохраненные значения из storage Не генерирует новые ID При установке расширения: Создаются оба идентификатора Преимущества этого подхода Сессионный ID меняется только при перезапуске браузера Нет лишних генераций ID при каждом открытии popup Background script работает только когда нужно (thanks to non-persistent) Все данные хранятся в storage.local, что гарантирует сохранность Альтернатива с sessionStorage Если вы хотите использовать sessionStorage (который очищается при закрытии браузера), можно модифицировать background script: javascript // В background.js browser.runtime.onStartup.addListener(async () => { const sessionId = generateUUID(); await browser.storage.session.set({ sessionId }); }); // В popup.js async function displayIds() { const persistentId = (await browser.storage.local.get('persistentId')).persistentId; const sessionId = (await browser.storage.session.get('sessionId')).sessionId; // ... отображение } Однако browser.storage.session доступен не во всех версиях Firefox, поэтому первый вариант более универсален. Смотрите какая ситуация. Сейчас действительно один идентификатор создаётся 1 раз и существует далее не зависимо от рестартов браузера и выключения плагина. Второй обновляется при перезагрузке браузера, при этом если выключить расширение затем перезапустить браузер и снова включить расширение, то второй идентификатор не изменится. Если не существует возможности каким то образом проверять был ли перезагружен браузер в время когда плагин был выключен(например может быть есть возможность получать время старта браузера и сравнивать его), то предлагаю добавить обновление второго идентификатора так же на запуск расширения. Вы подняли важный момент. Давайте реализуем гибридный подход, который будет учитывать оба сценария: Первый идентификатор - постоянный (как и раньше) Второй идентификатор - обновляется: При старте браузера (если расширение активно) При включении расширения (если браузер был перезапущен) Для этого добавим проверку времени последнего запуска браузера. Обновленная реализация manifest.json (добавляем разрешение на runtime): json { "manifest_version": 2, "name": "Instance ID Viewer", "version": "1.0", "description": "Displays persistent and session instance IDs", "icons": { "48": "icon.png" }, "browser_action": { "default_icon": "icon.png", "default_popup": "popup.html" }, "background": { "scripts": ["background.js"], "persistent": false }, "permissions": [ "storage", "runtime" ] } background.js: javascript function generateUUID() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { const r = Math.random() * 16 | 0; const v = c === 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); } // Проверяем, был ли браузер перезапущен с момента последнего запуска расширения async function wasBrowserRestarted() { const { lastBrowserStartTime } = await browser.storage.local.get('lastBrowserStartTime'); const currentStartTime = await browser.runtime.getBrowserInfo().then(info => info.startTime); if (!lastBrowserStartTime || lastBrowserStartTime !== currentStartTime) { await browser.storage.local.set({ lastBrowserStartTime: currentStartTime }); return true; } return false; } // Основная логика инициализации async function initializeIds() { // Постоянный ID let { persistentId } = await browser.storage.local.get('persistentId'); if (!persistentId) { persistentId = generateUUID(); await browser.storage.local.set({ persistentId }); } // Проверяем рестарт браузера const browserRestarted = await wasBrowserRestarted(); // Сессионный ID - обновляем если: // 1. Браузер только что запущен // 2. Или это первая инициализация let { sessionId } = await browser.storage.local.get('sessionId'); if (!sessionId || browserRestarted) { sessionId = generateUUID(); await browser.storage.local.set({ sessionId }); } } // Обработчики событий browser.runtime.onStartup.addListener(initializeIds); browser.runtime.onInstalled.addListener(initializeIds); // Также вызываем при каждом включении расширения initializeIds(); popup.js (остается без изменений): javascript async function displayIds() { const { persistentId, sessionId } = await browser.storage.local.get(['persistentId', 'sessionId']); document.getElementById('persistent-id').textContent = persistentId || 'Not set'; document.getElementById('session-id').textContent = sessionId || 'Not set'; } document.addEventListener('DOMContentLoaded', displayIds); Как это теперь работает При старте браузера: onStartup вызывает инициализацию Фиксируется время старта браузера Генерируется новый сессионный ID При включении расширения: Проверяется время последнего старта браузера Если браузер был перезапущен - генерируется новый сессионный ID Если нет - используется существующий При установке: Создаются оба идентификатора Особенности реализации Используем browser.runtime.getBrowserInfo() для получения времени старта браузера Храним время последнего известного старта в storage.local При каждом вызове initializeIds() проверяем, изменилось ли время старта Сессионный ID обновляется в двух случаях: При первом запуске Если обнаружен рестарт браузера Это решение гарантирует, что сессионный ID будет обновляться: При перезапуске браузера (даже если расширение было выключено) При первом включении расширения после установки При ручном вызове инициализацииВы так же можете прочитать следующие статьи: