StayActive — фокус под вашим контролем.
Скрывайте стандартные сигналы потери видимости и фокуса
на сайтах, которые вы выбираете сами.
Установка · Настройки · Ограничения · Техническое руководство
FocusLock — расширение Google Chrome с минималистичным popup StayActive. Для включённых доменов оно подменяет Page Visibility и focus API в контексте самой страницы, чтобы обычное переключение вкладки не передавалось через эти стандартные сигналы.
Каждый сайт включается вручную. По умолчанию расширение выключено везде.
Important
FocusLock скрывает определённые API и события, но не гарантирует невыявляемость переключения вкладок всеми возможными способами. Подмена видимости также не отменяет фоновый throttling Chrome. Совместимость с конкретными сайтами и браузерное тестирование текущей версии не подтверждены.
| Что делает расширение | |
|---|---|
| Видимость | Подменяет document.hidden → false и document.visibilityState → "visible"; фильтрует стандартные события видимости. |
| Фокус | Подменяет document.hasFocus() → true; фильтрует blur / focus окна и связанные сигналы ухода со страницы. |
| Раннее внедрение | Устанавливает MAIN-скрипт на document_start через постоянную регистрацию для разрешённого домена. |
| Настройки по сайтам | Сохраняет отдельную конфигурацию для каждого hostname. |
| Таймеры | Опционально восстанавливает часть пропущенных функциональных setInterval callbacks при пробуждении JS. |
| Диагностика | Показывает регистрацию обработчиков, подавленные события и счётчики восстановления в DevTools. |
При обычном переходе между полями ввода их focus-события сохраняются. Навигация, BFCache и события pagehide, pageshow, freeze, resume не блокируются.
-
Скачайте проект ZIP-архивом и распакуйте его. Или клонируйте репозиторий:
git clone https://github.com/moii-dev/FocusLock.git
-
Откройте
chrome://extensionsи включите Developer mode / Режим разработчика. -
Нажмите Load unpacked / Загрузить распакованное расширение.
-
Выберите распакованную папку, в которой лежит
manifest.json. -
Откройте нужный сайт и нажмите значок FocusLock.
-
Включите Stay active on this site и разрешите доступ к этому домену.
-
Нажмите Reload tab — перезагрузка необходима для внедрения до скриптов сайта.
Требуется Chrome 119+. Сборка и npm install для загрузки расширения не нужны. Node.js понадобится только для запуска локального тестового сервера или повторной генерации ресурсов.
Как обновить установленное расширение
Замените файлы свежей версией, нажмите кнопку обновления на карточке FocusLock в chrome://extensions, затем перезагрузите вкладки защищаемых сайтов.
Обновление расширения не заменяет MAIN-код, который уже исполнился в открытом документе. Popup версии 1.1.0 проверяет наличие контроллера текущей версии, фактические getters и совпадение настроек; при необходимости он сообщает о перезагрузке.
| Переключатель | По умолчанию | Назначение |
|---|---|---|
| Stay active on this site | Выкл. | Включает защиту для текущего домена. |
| Hide tab visibility | Вкл.* | Скрывает стандартные сигналы смены видимости. |
| Prevent blur detection | Вкл.* | Скрывает стандартные сигналы потери фокуса окна. |
| Keep timers accurate | Выкл. | Включает ограниченное восстановление interval callbacks. |
| Developer diagnostics | Выкл. | Выводит технические логи в консоль страницы. |
* Эти опции работают только при включённом главном переключателе.
Настройки хранятся локально. example.com и www.example.com — разные домены; HTTP, HTTPS и разные порты одного hostname используют одну настройку.
Расширение запрашивает три обязательных разрешения:
| Разрешение | Зачем |
|---|---|
activeTab |
Определить текущий сайт при открытии popup. |
scripting |
Зарегистрировать и внедрить MAIN-скрипты. |
storage |
Сохранить настройки доменов. |
Доступ к хосту запрашивается отдельно при включении сайта. Широкие HTTP/HTTPS-паттерны объявлены только как optional host permissions: они не выдают доступ ко всем сайтам при установке. Обязательного <all_urls> нет.
После выключения домена его регистрация удаляется, а ранее выданное разрешение сохраняется для восстановления открытых страниц. Отозвать его можно в Chrome → Extensions → FocusLock → Details → Site access. После отзыва доступа или удаления расширения перезагрузите открытые страницы.
Код расширения не содержит аналитики, внешних библиотек, удалённых скриптов или отправки содержимого страниц. Значки badges в этом README загружаются GitHub отдельно и не используются расширением.
- Chrome управляет исполнением в фоне. JS-подмена видимости не предотвращает throttling, freeze, discard или сон системы.
- Keep timers accurate — best effort. Восстанавливаются только новые функциональные
setIntervalс периодом от 250 мс, максимум 10 вызовов за одно пробуждение. Остальные пропуски учитываются, но не воспроизводятся. - Повторные callbacks могут иметь побочные эффекты. Режим таймеров по умолчанию выключен; он не является универсальным исправлением для любого сайта.
setTimeoutи рекурсивные timeout-цепочки не восстанавливаются. - Чужие фреймы имеют собственные разрешения. Включение домена не распространяется автоматически на встроенные страницы другого origin.
- Защита охватывает стандартные сигналы. Сайт может применять другие механизмы, оригинальные API из другого контекста или серверную логику.
- Служебные страницы Chrome не поддерживаются. На
chrome://, Chrome Web Store, страницах расширений,file://и IPv6 URL включить FocusLock нельзя.
Для таймера на сайте, код которого можно изменить, надёжнее считать время по deadline, а не по количеству callbacks. Пример: deadline-clock.js. Подробности — в техническом руководстве.
Из папки проекта запустите:
node tools/serve.mjsОткройте http://127.0.0.1:8765. Сервер слушает только локальный адрес, установка зависимостей не нужна. Остановить его можно Ctrl+C.
На стенде есть:
- текущие
hidden,visibilityStateиhasFocus(); - счётчики событий окна, документа и полей ввода;
- секундный callback-счётчик и отсчёт по времени начала;
- пятиминутный таймер, который останавливается через
window.blur; - первый синхронный скрипт страницы для проверки раннего внедрения;
- журнал жизненного цикла и снимок диагностики.
Сравните поведение до и после включения домена, переключаясь между вкладками и окнами. Полный порядок ручной проверки находится в руководстве.
Включите Developer diagnostics, перезагрузите сайт и откройте DevTools → Console. Разрешите уровень Verbose и установите фильтр StayActive.
Состояние перехватов можно получить в консоли страницы:
window[Symbol.for('focuslock.controller.v1')]?.snapshot()Для сообщения об ошибке укажите версию Chrome, домен, настройки, шаги воспроизведения и текст статуса popup. Перед публикацией логов удалите личные данные и ссылки с токенами.
FocusLock/
├── manifest.json # Manifest V3
├── background.js # Service worker
├── shared/ # Схема и адресация настроек
├── scripts/
│ ├── main.js # MAIN-перехваты и диагностика
│ └── config/ # 16 синхронных bootstrap-конфигураций
├── popup/ # Интерфейс StayActive
├── icons/ # PNG 16 / 32 / 48 / 128
├── test/ # Локальный стенд и пример deadline-таймера
├── tools/ # Сервер и генератор ресурсов
└── docs/
└── ARCHITECTURE.md # Устройство, ограничения и ручная проверка
Сгенерированные иконки и конфигурации включены в репозиторий. Для повторной генерации: npm run generate:assets.