Chrono Mock
МоваУкраїнська

Вебсторінки всередині нативного застосунку

Настільний застосунок із вбудованим вебрушієм запускає свої сторінки в окремому ізольованому процесі. Нативний механізм покриває застосунок і зупиняється на цій межі — тож вікно переходить на запитану вами дату, а панель усередині нього ні. Це закриває таку прогалину.

Збій, що виглядає як успіх

Безліч застосунків 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-розрядна сесія не може назвати процеси рушія чи їхні ролі. Канал до сторінок усе одно працює. Звіт просто менш конкретний щодо того, що йому не вдалося визначити, і каже, який із двох варіантів має місце.

Спробуйте