Исполнение
Где и как работает плагин: изолированная среда, жизненный цикл, сторожевой таймер, перезапуск и лимиты.
Каждый плагин получает отдельную изолированную среду:
- iframe с
sandbox="allow-scripts"и собственным непрозрачным origin; - политика безопасности
default-src 'none',script-src 'unsafe-inline' blob: 'wasm-unsafe-eval',worker-src blob:иconnect-srcтолько для разрешённых адресов изnetwork; - выделенный воркер, в котором исполняется код плагина.
Встроенный скрипт в политике нужен только загрузчику самой среды. Код плагина загружается в воркер из blob: и не имеет DOM, поэтому вставить свой скрипт на страницу он не может.
Из воркера недоступны: окно и DOM приложения, eval и new Function, importScripts и import() по сети, IndexedDB, Cache Storage, cookies, localStorage, сеть вне объявленных адресов. Доступны: таймеры, TextEncoder, TextDecoder, URL, structuredClone, WebAssembly и прочее стандартное окружение воркера.
Жизненный цикл
- Приложение создаёт среду, загружает код и отправляет
init. - Для каждого действия на видимой странице приходит
appear, при уходе со страницыdisappear. - Нажатия, сообщения из настроек, ответы брокеров и таймеры приходят событиями.
- При остановке плагина среда уничтожается целиком: воркер, таймеры, соединения брокеров.
Сторожевой таймер и перезапуск
Хост раз в 5 секунд проверяет, отвечает ли воркер. Если ответа нет 10 секунд, воркер считается зависшим и уничтожается. Экземпляр также останавливают ошибка при загрузке кода и трап WASM, в том числе паника в Rust.
После сбоя хост перезапускает плагин с паузами 1, 2, 5, 10 и 30 секунд. Если экземпляр проработал дольше минуты, счётчик сбрасывается. Шестой сбой подряд переводит плагин в состояние crashed, дальше его перезапускает только пользователь.
Ошибка в обработчике (Err в Rust, исключение или отклонённый Promise в JavaScript) записывается в журнал и не останавливает плагин.
Лимиты
Плагин, который превысил лимит команд, получает предупреждение в журнал. Лишние команды отбрасываются.