15 KiB
Промт для агента: FoxBrowser — легкий фоновий браузер
Задум і чесна оцінка реалістичності
Три цілі проєкту:
- Низьке споживання CPU/RAM порівняно зі звичайними браузерами.
- Вікно завжди позаду всіх інших вікон (як "приліплений" віджет, а не звичайне вікно застосунку).
- Не "роздувається" з часом, коли грає фонова музика/відео (напр. плейлист на YouTube з однією вкладкою).
- (Другий етап) Вбудований VPN через WireGuard-тунель, без потреби в окремому клієнті.
Важлива чесна засторога перед стартом: писати власний рушій рендерингу HTML/CSS/JS (як Blink чи Gecko) — це багаторічна робота команд у сотні людей, нереалістично для одного проєкту. Правильний шлях — не змагатися з Chromium рушієм, а взяти вже готовий системний рушій (Microsoft Edge WebView2 на Windows) і виграти на рівні: відсутності власної копії Chromium в кожному інсталяторі (Electron тягне ~150+ МБ свого Chromium, WebView2 використовує вже встановлений у системі Edge Runtime), мінімалістичного "chrome" браузера без важкої екосистеми розширень, агресивного керування вкладками/пам'яттю, і унікальних UX-фіч (always-on-bottom, audio-only режим). Це дає реальний, чесний виграш у легкості — але базове споживання пам'яті на сторінку не буде на порядок меншим за сам Edge, бо рушій той самий.
Рекомендований стек
- Windows-first, C#/.NET 8 (WPF) + Microsoft.Web.WebView2 — обрано для консистентності з попереднім OCR-проєктом (той самий стек, ті самі патерни Win32-інтеропу для системних фіч), і тому що WebView2 — найлегший шлях отримати сучасний рушій без бандлингу власного Chromium.
- Альтернатива, якщо потрібна кросплатформність з нуля: Rust + Tauri v2 (теж використовує системний WebView, а не власний Chromium) — складніше по стеку, але менший бінарник і нативна швидкість shell-коду.
Функціональні вимоги
1. Базовий shell браузера
- Мультивкладковість: кожна вкладка — окремий
CoreWebView2контролер (WebView2 підтримує кількаCoreWebView2Environment/профілів у одному процесі-хості). - Мінімалістичний UI: рядок вкладок, адресний рядок, кнопки назад/вперед/оновити — без важкої панелі закладок/історії з великою кількістю віджетів (легкість — і візуальна, і по ресурсах).
- Системний трей: згортання в трей замість закриття, іконка з контекстним меню (Show/Hide, Play/Pause якщо є активна медіа-вкладка, Exit).
2. Always-on-bottom (вікно завжди позаду)
- Реалізується через Win32 API, а не WPF-властивості:
SetWindowPos(hwnd, HWND_BOTTOM, ...)замість звичногоHWND_TOPMOST. - Ключова складність: Windows постійно "підіймає" активне вікно наверх при фокусі/кліку, тому просто одноразовий
HWND_BOTTOMне втримає вікно ззаду. Потрібен або: (а) хук наWM_WINDOWPOSCHANGING/WM_ACTIVATEдля повторного примусовогоSetWindowPos(HWND_BOTTOM)щоразу, коли ОС намагається підняти вікно, або (б)SetWinEventHookнаEVENT_SYSTEM_FOREGROUND, який відстежує зміну активного вікна і одразу опускає FoxBrowser назад вниз z-order. Задокументуй обраний підхід і протестуй, що вікно не "мигає" і не краде фокус у користувача під час гри музики. - Клік по вкладці/елементу керування в самому FoxBrowser (напр. пауза музики) має працювати без переведення вікна на передній план — тобто вікно позаду, але клікабельне (
WS_EX_NOACTIVATEдля сценаріїв, де фокус не потрібен, або контрольоване тимчасове підняття тільки коли користувач свідомо клікає в вікно). - Гаряча клавіша для "тимчасово підняти на передній план" (напр. коли треба щось вибрати в плеєрі), потім вікно саме повертається вниз.
3. Захист від "роздування" пам'яті з часом
- Моніторинг: фоновий таймер кожні N хвилин читає RAM/CPU процесу WebView2 (через
Process.WorkingSet64для дочірніх процесів WebView2 — у них окреміmsedgewebview2.exeпроцеси на renderer/GPU). - Watchdog для довгограючих вкладок: якщо пам'ять конкретної вкладки перевищує поріг (наприклад, зросла вдвічі відносно початкового рівня після завантаження) — виконати "м'який" reload сторінки, попередньо зберігши стан програвання через JS injection (
ExecuteScriptAsync): зчитати зdocumentпоточний час відео/треку, назву плейлиста/позицію, після reload — виконати JS, який перемотує на збережену позицію і продовжує відтворення. Користувач в ідеалі навіть не помітить короткого "заїкання" звуку. - Suspend неактивних вкладок: вкладки, які не видно і не грають аудіо, вивантажувати (закривати
CoreWebView2Controller, лишаючи тільки URL+заголовок+favicon у пам'яті), і відновлювати повний рендер лише при переключенні на них — аналогічно "sleeping tabs" в Edge/Chrome, тільки агресивніше за замовчуванням. - "Music Mode" (аудіо-only режим) — головна фіча проти роздування на музичних плейлистах: для розпізнаних медіа-сайтів (YouTube, SoundCloud тощо) пропонувати режим, де відеодоріжка не рендериться взагалі (сторінка завантажується, але відеоелемент приховується/призупиняється у видимості, звук іде далі через Web Audio) — це прибирає найважчу частину навантаження (декодування й рендер відеокадрів), лишаючи тільки аудіодекодування, яке на порядки дешевше по CPU/GPU. Технічно: CSS/JS ін'єкція, яка ховає
<video>елемент і зупиняє його рендер-цикл, не займаючи паузою сам плеєр (display: noneна відео не завжди зупиняє декодування в Chromium — треба перевірити практично й, якщо потрібно, додатковоvideo.pause()рендер-кадрів черезrequestVideoFrameCallbackтрюки або обмеження частоти кадрів).
4. Вбудований WireGuard VPN (другий етап)
- Не вимагати від користувача встановлювати окремий клієнт WireGuard. Варіанти реалізації, від простішого до "повністю вбудованого":
- Найпростіше: якщо офіційний WireGuard for Windows встановлений, керувати тунелем через його CLI (
wireguard.exe /installtunnelservice config.conf) з коду застосунку — швидко зробити, але вимагає зовнішньої залежності. - Повністю вбудоване (рекомендовано для фінальної версії): використати
wintun.dll(офіційний легкий TUN-драйвер від творців WireGuard, розповсюджується вільно, не вимагає окремої інсталяції — просто кладеш dll поруч з .exe) у парі з boringtun (userspace-реалізація WireGuard-протоколу від Cloudflare на Rust, є FFI-бібліотека) або нативним P/Invoke доwireguard-go. Це дає тумблер "VPN: Увімкнено/Вимкнено" прямо в налаштуваннях FoxBrowser без жодних зовнішніх застосунків.
- Найпростіше: якщо офіційний WireGuard for Windows встановлений, керувати тунелем через його CLI (
- UI: імпорт
.conf-файлу конфігурації тунелю (стандартний формат WireGuard, який видають VPN-провайдери), список збережених профілів, індикатор стану підключення в тулбарі.
Архітектура (орієнтовна структура)
/FoxBrowser
/Core
TabManager.cs // CoreWebView2 контролери, lifecycle вкладок
WindowStackManager.cs // Win32 always-on-bottom логіка
MemoryWatchdog.cs // моніторинг RAM/CPU, soft-reload довгограючих вкладок
TabSuspender.cs // вивантаження неактивних вкладок
MusicModeInjector.cs // CSS/JS ін'єкція для audio-only режиму
VpnManager.cs // обгортка над wintun/boringtun або wireguard.exe CLI
/UI
MainWindow.xaml(.cs)
TabBar.xaml(.cs)
TrayIconManager.cs
VpnSettingsWindow.xaml(.cs)
/Native
Win32Interop.cs // SetWindowPos, SetWinEventHook, P/Invoke сигнатури
App.xaml(.cs)
Кроки реалізації для агента (фазами — не намагайся зробити все одразу)
Фаза 1 — робочий shell:
- Ініціалізувати WPF-проєкт, додати
Microsoft.Web.WebView2NuGet. - Реалізувати одну вкладку з WebView2, адресний рядок, навігацію.
- Додати мультивкладковість (
TabManager, кілька контролерів). - Системний трей + згортання замість закриття.
Фаза 2 — always-on-bottom:
5. Реалізувати WindowStackManager з SetWinEventHook на EVENT_SYSTEM_FOREGROUND, тестувати на різних сценаріях (Alt+Tab, клік по інших вікнах, повноекранні застосунки).
6. Гаряча клавіша для тимчасового підняття вікна.
Фаза 3 — керування пам'яттю:
7. MemoryWatchdog — логування споживання по вкладках, поки без автодій, просто щоб бачити цифри.
8. TabSuspender для неактивних вкладок.
9. Soft-reload з відновленням позиції відтворення для довгограючих вкладок.
Фаза 4 — Music Mode:
10. Детекція медіа-сайтів, UI-перемикач "Audio only", MusicModeInjector.
11. Виміряти реальний виграш по CPU/GPU до/після (профайлер Windows Performance Monitor або вбудований Task Manager по процесу msedgewebview2.exe) — це треба підтвердити цифрами, а не тільки відчуттями.
Фаза 5 — VPN:
12. Почати з найпростішого варіанту (керування зовнішнім wireguard.exe), переконатись, що весь флоу працює.
13. Якщо треба повна автономність без зовнішніх застосунків — інтегрувати wintun + boringtun.
Нефункціональні вимоги
- Кожна фаза має бути окремим працюючим релізом, який можна потестувати — не розтягувати "великий бенг" на весь проєкт одразу.
- Вимірювати реальне споживання пам'яті/CPU до і після кожної оптимізації (Фаза 3-4) — легко обманути себе відчуттям "стало легше", коли насправді змінилось не так уже й багато.
- Задокументувати, які Windows-версії підтримуються (WebView2 Runtime вимагає Windows 10 1809+ або треба бандлити Evergreen-інсталятор для дуже старих систем).
Почни з Фази 1 (робочий shell з кількома вкладками і треєм) — саме на цьому етапі одразу стане видно, наскільки WebView2 справді легший за Chrome/Electron у твоєму конкретному сценарії використання, і чи варто взагалі рухатись далі за цим планом.