Files
FoxBrowser/ULTRALIGHT_AGENT_GUIDE.md
T
2026-10-01 01:46:18 +03:00

71 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# FoxBrowser — гайд з переходу на Ultralight (замість/поруч з WebView2)
## Контекст і чому це взагалі розглядається
Поточна архітектура (`TabManager.cs`, `NativeAudioSession.cs`) побудована на Microsoft Edge WebView2 — тобто по суті на Chromium/Blink рушії, який вже стоїть у системі. Виграш там — тільки по диску (немає власної копії Chromium в інсталяторі) і по shell-архітектурі (один спільний WebView2, suspend вкладок, audio-only CSS/JS). Базове споживання RAM на сторінку залишається "chromium-рівня", бо рушій той самий.
Диск користувача не хвилює. Хвилює тільки RAM. Тому єдиний спосіб реально зменшити базове споживання пам'яті — це взяти **інший, не Chromium-похідний рушій**. Ultralight — головний кандидат: це форк WebKit (WebCore) зі своїм легким рендерером і JavaScriptCore замість V8, зроблений спеціально для embedding в apps/games, а не для повноцінного браузингу.
**Це не заміна архітектури "один shell — багато логічних вкладок" — це заміна рушія під капотом `TabManager`.** Wrapper-рівень (metadata tabs, watchdog, resource firewall) залишається концептуально тим самим.
## ⚠️ Критичне обмеження — прочитати перед тим, як писати хоч рядок коду
Офіційний FAQ Ultralight прямо каже: **рушій не підтримує WebGL, WebRTC, а підтримка HTML5 Video/Audio — "currently experimental"**. DRM (Widevine) не підтримується взагалі — це навіть не обговорюється в їхніх матеріалах, бо Ultralight не є Chromium-похідним і не має ліцензованого DRM-модуля.
Це напряму б'є по головному сценарію проєкту — YouTube/музичні сервіси:
- Звичайний `<video>`/`<audio>` на YouTube може просто не програватись, або програватися нестабільно, бо аудіо/відео декодування в рушії — експериментальна фіча, а не production-ready шлях.
- Будь-який контент з DRM (YouTube Premium, Spotify Web Player з захищеними треками тощо) гарантовано не запрацює.
- YouTube — важкий сучасний SPA (React-подібний фронтенд, WASM-компоненти). WebCore/JavaScriptCore може мати проблеми сумісності, яких в Blink просто немає, бо весь сучасний веб тестується проти Chromium.
**Практичний висновок:** якщо є ідея "просто підмінити WebView2 на Ultralight і воно так само програє YouTube-звук" — це, ймовірно, не спрацює з коробки. Реалістичний шлях — той, що вже закладений у проєкті через `NativeAudioSession.cs`: не покладатись на рушій узагалі для аудіо-декодування, а брати **direct audio URL** і програвати його нативним `MediaPlayer`/WASAPI в обхід HTML5 `<audio>` елемента. Ultralight в такому разі відповідає тільки за легкий рендер сторінки (UI, DOM, JS-логіка сайту), а не за сам звук.
## Крок 0 — Go/No-Go тест (зробити ДО будь-якого рефакторингу коду)
Не чіпати `TabManager.cs` одразу. Спочатку окремим ізольованим експериментом перевірити, чи Ultralight взагалі відкриває YouTube прийнятно:
1. Завантажити офіційний Ultralight SDK, знайти в ньому Sample #8 ("Browser") — це вже готовий мінімальний браузер на чистому Ultralight.
2. Відкрити в ньому youtube.com, спробувати програти будь-яке відео.
3. Зафіксувати чесно: чи взагалі вантажиться сторінка, чи є звук, чи є відео, наскільки стабільно (не падає/не висне при скролі списку рекомендацій).
4. Порівняти RAM одного відкритого таба в Sample #8 з тим, що зараз показує watchdog для WebView2 на тій самій сторінці.
Якщо на кроці 3 YouTube взагалі не вантажиться або аудіо не програється — не переходити до Кроку 1. У такому разі єдиний life-виправданий сценарій — Ultralight як рушій **тільки для легких некомплексних сторінок** (власний UI, налаштування, прості сайти), а YouTube/аудіо йде повністю через `NativeAudioSession` (direct URL, без рендеру самої сторінки взагалі, або з окремим легким HTML-плеєром власної розробки). Це суттєво звужує роль Ultralight у проєкті — задокументувати це чесно, а не підганяти висновок під бажаний результат.
## Стек і бібліотеки для .NET
Офіційний API Ultralight — тільки C/C++. Готових офіційних .NET-бібліотек від самої Ultralight Inc немає — є community-підтримувані байндинги:
- **UltralightNet** / **UltralightNet.Bundle** (NuGet) — керовані байндинги до C API Ultralight + AppCore (windowing, font loader, filesystem, logger), з нативними бінарниками для `win-x64` вже в пакеті.
```
dotnet add package UltralightNet.Bundle
```
- ⚠️ На момент цього гайду `UltralightNet.Bundle` таргетить **.NET 10**, а поточний проєкт — **.NET 8**. Перед стартом перевірити актуальну версію пакета на nuget.org і чи є білд під .NET 8, або чи є сенс піднімати проєкт до .NET 10 заради цього (окреме рішення, не робити мовчки за замовчуванням).
- Пакет — тонка обгортка над нативним C API, тобто код виглядає не по-WPF-івськи (`renderer.CreateView()`, ручний update/render loop), а не як `CoreWebView2` — буде помітно більше низькорівневого коду, ніж зараз з WebView2.
## Ліцензування — важливо для будь-якого комерційного релізу
Ultralight розповсюджується за "ULTRALIGHT FREE LICENSE AGREEMENT — V1":
- Free/Limited Commercial Distribution дозволена **тільки якщо** юрособа-ліцензіат не мала обороту понад **US$100,000** за останній фінансовий рік.
- Якщо оборот перевищує цей поріг у будь-якому наступному році — усі права на комерційну дистрибуцію автоматично анулюються, і потрібна окрема платна ліцензія напряму з Ultralight Inc.
- Для приватного/некомерційного use case (як зараз, судячи з проєкту) це не проблема, але задокументувати цей поріг, щоб не зʼясувати це post-factum при спробі щось випустити комерційно.
- Заборонено reverse engineering, декомпіляція, спроби дістатись сирців пропрієтарної частини (`UltralightCore`, `Ultralight` view/compositor) — сама `WebCore` (layout engine, форк WebKit) відкрита під LGPL/BSD.
## Архітектурні відмінності від WebView2, які треба врахувати в коді
- **Single process, без IPC** — на відміну від WebView2/Chromium, де кожен renderer — окремий процес (`msedgewebview2.exe` per tab/GPU), Ultralight працює в одному процесі без міжпроцесної ізоляції. Це означає: (а) менше overhead per-tab у теорії, (б) **немає** природної sandbox-ізоляції — крашнута/зависла вкладка може завалити весь застосунок, а не тільки один child-процес. Поточний watchdog (`MemoryWatchdog.cs`) писався в припущенні окремих WebView2-процесів — цю логіку треба переосмислити під single-process модель.
- **Рендер:** GPU-текстура або CPU pixel buffer, керується вручну через `renderer.Update()` / `renderer.Render()` у власному циклі — на відміну від WebView2, де WPF-хостинг рендер-циклу ховає це від вас. Треба буде інтегрувати цей update loop у WPF `CompositionTarget.Rendering` або окремий таймер, і подавати результат як `WriteableBitmap`/текстуру у WPF `Image`-контрол.
- **`WebResourceRequested`-подібного firewall** у тому вигляді, що є зараз (перехоплення мережевих запитів по host/URL) — треба перевірити, чи є еквівалент у Ultralight API (AppCore filesystem/network hooks), задокументована частина цього не гарантована так само детально, як у WebView2.
## Рекомендований план дій для агента
1. **Крок 0 (Go/No-Go тест вище) — обов'язково перший**, і чесно задокументувати результат у цьому файлі чи окремому `ULTRALIGHT_EVAL_RESULTS.md`, включно з цифрами RAM.
2. Якщо результат прийнятний — не переписувати `TabManager.cs` одразу поверх існуючого. Зробити паралельний `Core/UltralightTabManager.cs` (або аналог) як окрему гілку/фіче-флаг, щоб WebView2-шлях лишався робочим fallback, поки Ultralight-шлях не доведено стабільним на реальних сценаріях (не тільки YouTube — плейлисти, перемикання вкладок, тривала фонова робота годинами).
3. Портувати спочатку тільки non-media сторінки (власний UI, прості сайти) на Ultralight, лишаючи медіа-плеєр окремо через `NativeAudioSession` (direct URL) незалежно від того, який рушій рендерить решту.
4. Watchdog і suspend-логіку переписати під single-process модель Ultralight — старі пороги (850 MB soft-reload) писались під конкретну поведінку WebView2/Chromium і, ймовірно, невалідні напряму.
5. Повторно виміряти реальний виграш по RAM (не по відчуттю) на тому самому сценарії, що і в NEXT_AGENT_GUIDE.md — одна довгограюча медіа-вкладка годинами — і чесно порівняти з поточними цифрами WebView2-версії.
## Головний ризик, який не можна замовчати
Якщо Крок 0 покаже, що YouTube на Ultralight банально не працює (немає звуку, ламається UI, падає рушій) — це не привід "трохи допрацювати", а сигнал, що для головного use case проєкту (легкий фоновий плеєр для YouTube/музики) Ultralight як **основний** рушій не підходить, і чесний наступний крок — залишити WebView2 для медіа-сторінок, а Ultralight розглядати хіба що для легких допоміжних вікон (налаштування, non-media UI), де сумісність з сучасним вебом не критична.