Chrono Mock

Strony internetowe wewnątrz natywnej aplikacji

Aplikacja desktopowa z wbudowanym silnikiem web trzyma swoje strony w osobnym, piaskowanym procesie. Mechanizm natywny obejmuje aplikację i zatrzymuje się na tej granicy - więc okno przesuwa się na wskazaną datę, a panel w jego środku nie. To domyka tę lukę.

Awaria, która wygląda jak sukces

Sporo aplikacji Windows jest natywnych na zewnątrz i webowych w środku. Ekran ustawień, pulpit z danymi, widok raportu, panel licencji - zbudowane raz jako HTML i osadzone w WebView2 albo Qt WebEngine, zamiast pisane dwa razy.

Silnik uruchamia te strony we własnym procesie, a ten proces jest piaskowany. Biblioteka wstrzyknięta do aplikacji do niego nie wchodzi. Wszystko, o co aplikacja pyta Windows, przesuwa się na datę sesji, a wszystko, o co strona pyta JavaScript, nie:

  • Pasek tytułu, dzienniki i pliki mówią 2038.
  • Panel w tym samym oknie mówi dzisiaj.
  • Nic nie zgłasza błędu, nic nie ostrzega, a obie połowy wyglądają równie pewnie.

To jest kosztowna odmiana tego błędu, bo test sprawia wrażenie wykonanego. Wcześniejsze zachowanie raportowało taką sesję jako czyste przejście, czyli twierdziło coś, czego narzędzie nie miało czym poprzeć.

Co robi sesja zamiast tego

Sesja uruchamia oba mechanizmy naraz. Hook natywny wchodzi do aplikacji jak zawsze, a strony osiąga się jedyną drogą, jaką cokolwiek sięga do piaskowanego renderera: pytając sam silnik.

Przy starcie aplikacja dziedziczy dwie zmienne środowiskowe, które proszą jej silnik o otwarcie lokalnego portu diagnostycznego. Są dokładane do przełączników, które aplikacja i tak przekazuje, a nie stawiane w ich miejsce. Potem sesja pilnuje własnych procesów, aż ten port się pojawi, a gdy się pojawi, każda strona i każdy worker za nim trafiają na ten sam zegar co aplikacja.

Jeden start, jedno tempo, jedna oś czasu. Zmiana tempa albo skok sięgają aplikacji i jej stron razem, a liczniki stron biegną w tempie aplikacji, a nie własnym.

Działa domyślnie i wyłącza się jednym przełącznikiem, który nie otwiera żadnego portu i zostawia strony na prawdziwym zegarze.

# Nic do konfigurowania - silnik zostanie znaleziony, jeśli tam jest
chrono run "C:\Program Files\YourApp\YourApp.exe" --at 2038-01-01T00:00:00 --mode x60

# Albo zostaw strony w spokoju i nie otwieraj portu
chrono run "C:\Program Files\YourApp\YourApp.exe" --at 2038-01-01T00:00:00 --no-embedded

Co raport mówi o stronach

Strony nie są wliczane do liczb samej aplikacji. Liczą się jako osobne jednostki, bo proces i strona to różne rzeczy, a zsumowanie ich dałoby liczbę, która nic nie znaczy:

  • Nagłówek liczy jedno i drugie - processes: 4, contexts: 1.
  • Każda strona dostaje własne wiersze, na przykład context 1: page Date.now (12 calls) w wierszu poleceń i page Date.now - fake clock w tabeli audytu w oknie.
  • Osiągnięty silnik jest nazwany razem z portem, więc możesz wycelować własne DevTools dokładnie w te strony, którymi steruje sesja.

Przebieg na sucho mówi, czy strony zostałyby osiągnięte, zanim cokolwiek wystartuje. Co znaczą werdykty →

Trzy ograniczenia, które warto znać przed startem

Port diagnostyczny stoi otwarty, dopóki silnik działa.

Nasłuchuje wyłącznie na tym komputerze, ale jest otwarty dla każdego programu na tym komputerze przez cały czas pracy silnika, a cokolwiek do niego sięgnie, może tymi stronami sterować. Sesja ostrzega o tym za każdym razem, gdy port został otwarty, i podaje jego numer, zamiast wspominać o nim ogólnikowo. Na maszynie współdzielonej albo niezaufanej użyj przełącznika, który nie otwiera niczego.

Aplikacja z podniesionymi uprawnieniami jest poza zasięgiem.

Silnik osadzony w aplikacji z podniesionymi uprawnieniami ignoruje zmienne, które ustawia sesja, więc jego strony zostają na prawdziwym zegarze. To jest reguła samego silnika, a nie ustawienie, i nie da się jej obejść z zewnątrz.

Taka sesja raportuje PARTIAL i to jest uczciwa odpowiedź.

Procesy pomocnicze silnika oraz natywne odczyty czasu samego renderera zostają na prawdziwym zegarze. Strony są na zegarze sesji, a reszta tej rodziny nie, więc werdykt mówi partial i nazywa to, co zostało pominięte, zamiast zaokrąglać w górę do sukcesu.

Dwa mniejsze, powiedziane wprost. Strony zachowują strefę czasową tej maszyny, więc niezależna strefa sesji jest funkcją wyłącznie trybu natywnego. A licznik zaplanowany zanim sesja sięgnęła do strony zachowuje stare tempo, tak samo jak w czystej sesji Chromium - sesja ostrzega, zamiast pozwolić ci wyciągnąć wniosek, że nic się nie stało.

Jeśli silnik jest konfigurowany polityką argumentów przeglądarki w rejestrze, zmienna sesji ma pierwszeństwo na czas jej trwania, a raport to mówi - bo port diagnostyczny ustawiony tam nie zostałby zastosowany.

Jak dobrze to jest przetestowane

Eksperymentalnie, w tym samym zdefiniowanym znaczeniu co wszędzie tutaj: działa na celach, na których było budowane, nie było testowane szeroko, a źródłem prawdy jest wbudowany audyt, a nie ta strona. Zmierzone ręcznie na hoście WebView2 i hoście Qt WebEngine pod 64-bitowym Windows, a nie przez zestaw automatyczny. W tych przebiegach strony czytały rok sesji w tempie sesji i poszły za skokiem.

Pod 32-bitowym Windows jest zmarszczka, o której lepiej wiedzieć, niż ją odkryć: runtime WebView2 jest 64-bitowy nawet wtedy, gdy aplikacja go osadzająca jest 32-bitowa, więc sesja 32-bitowa nie potrafi nazwać procesów silnika ani ich ról. Kanał do stron działa mimo to. Raport jest po prostu mniej konkretny co do tego, czego nie rozpoznał, i mówi, który z dwóch przypadków to jest.

Wypróbuj