Веб-страницы внутри нативного приложения
Настольное приложение со встроенным веб-движком запускает свои страницы в отдельном изолированном процессе. Нативный механизм покрывает приложение и останавливается на этой границе — поэтому окно переходит на запрошенную вами дату, а панель внутри него нет. Это закрывает такой пробел.
Сбой, который выглядит как успех
Множество приложений Windows снаружи нативные, а внутри — веб-страница. Экран настроек, дашборд, просмотр отчёта, панель лицензии — сделанные один раз на HTML и размещённые в WebView2 или Qt WebEngine, а не написанные дважды.
Движок запускает эти страницы в собственном процессе, и этот процесс изолирован. Библиотека, внедрённая в приложение, в него не попадает. Всё, что приложение запрашивает у Windows, переходит на дату сессии, а всё, что страница запрашивает у JavaScript, — нет:
- Строка заголовка, логи и файлы говорят 2038.
- Панель в том же окне говорит сегодня.
- Ничего не падает, ничего не предупреждает, и обе половины выглядят одинаково уверенно.
Это дорогая версия такой ошибки, потому что тест как будто прошёл. Прежнее поведение сообщало о такой сессии как о чистом успехе — утверждение, которое инструмент не мог подкрепить.
Что делает сессия вместо этого
Сессия запускает оба механизма одновременно. Нативный хук входит в приложение как обычно, а до страниц добираются единственным способом, которым вообще добираются до изолированного рендерера: спрашивая сам движок.
При запуске приложение наследует две переменные среды, которые просят его движок открыть локальный порт отладки. Они добавляются к ключам, которые приложение и так передаёт, а не заменяют их. Затем сессия следит за собственными процессами, пока этот порт не появится, и когда он появляется, каждая страница и каждый worker за ним переходят на те же часы, что и приложение.
Один старт, одна скорость, одна временная шкала. Смена скорости или скачок доходят до приложения и его страниц вместе, а таймеры страниц идут в темпе приложения, а не в собственном.
Это включено по умолчанию и отключается одним переключателем, который не открывает никакого порта и оставляет страницы на настоящих часах.
# Ничего настраивать не нужно — движок находится, если он есть chrono run "C:\Program Files\YourApp\YourApp.exe" --at 2038-01-01T00:00:00 --mode x60 # Или не трогать страницы и не открывать порт chrono run "C:\Program Files\YourApp\YourApp.exe" --at 2038-01-01T00:00:00 --no-embedded
Что отчёт говорит о страницах
Страницы не вливаются в собственные числа приложения. Они считаются отдельными единицами, потому что процесс и страница — разные вещи, а их сумма изобрела бы число, которое ничего не значит:
- В заголовке считаются оба —
processes: 4, contexts: 1. - У каждой страницы свои строки, например
context 1: page Date.now (12 calls)в командной строке и page Date.now - fake clock в таблице аудита в окне. - Достигнутый движок называется вместе с портом, так что вы можете направить собственные DevTools ровно на те страницы, которыми управляет сессия.
Пробный запуск (dry run) сообщает, будут ли достигнуты страницы, до того, как что-либо запущено. Что означают вердикты →
Три ограничения, о которых стоит знать до начала
Порт отладки остаётся открытым, пока работает движок.
Он слушает только на этом компьютере, но открыт для любой программы на этом компьютере, пока работает движок, и всё, что до него доберётся, может управлять этими страницами. Сессия предупреждает об этом каждый раз, когда порт был открыт, и называет порт, а не упоминает его вообще. На общей или недоверенной машине используйте переключатель, который ничего не открывает.
Приложение, запущенное с повышенными правами, недосягаемо.
Движок, размещённый приложением с повышенными правами, игнорирует переменные, которые задаёт сессия, поэтому его страницы остаются на настоящих часах. Это собственное правило движка, а не настройка, и снаружи обойти его нельзя.
Такая сессия сообщает PARTIAL, и это честный ответ.
Вспомогательные процессы движка и собственные нативные вызовы времени рендерера остаются на настоящих часах. Страницы на часах сессии, остальная часть семьи — нет, поэтому вердикт говорит частично и называет то, что осталось за бортом, а не округляет вверх до успеха.
Ещё два, поменьше, сказанные прямо. Страницы читают часовой пояс сессии как фиксированное
смещение, поэтому Intl называет его смещением, например GMT+02:00,
а не городом. А таймер, поставленный в расписание до того, как сессия достигла
страницы, сохраняет прежний темп — так же, как в чистой сессии Chromium; сессия
предупреждает, а не позволяет сделать вывод, что ничего не произошло.
Если движок настроен политикой аргументов браузера в реестре, переменная сессии имеет приоритет на время её работы, и отчёт об этом сообщает — потому что порт отладки, настроенный там, не был бы применён.
Насколько хорошо это проверено
Экспериментально, с тем же определённым смыслом, что и в остальных местах: оно работает на тех целях, под которые создавалось, не проверялось широко, а встроенный аудит — ваш источник истины, а не эта страница. Измерено вручную на хосте WebView2 и хосте Qt WebEngine в 64-разрядной Windows, а не автоматическим набором. В этих запусках страницы читали год сессии в темпе сессии и следовали за скачком.
В 32-разрядной Windows есть нюанс, о котором лучше знать заранее, чем обнаружить: среда выполнения WebView2 64-разрядная, даже когда размещающее её приложение 32-разрядное, поэтому 32-разрядная сессия не может назвать процессы движка или их роли. Канал к страницам при этом работает. Отчёт просто менее конкретен в том, что ему не удалось определить, и говорит, какой из двух вариантов имеет место.