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

12 KiB
Raw Blame History

УВАГА: Термінал агента не працює. Не виконуй жодних команд (dotnet build, dotnet restore, dotnet run, встановлення NuGet-пакетів тощо) самостійно. Якщо для задачі щось треба встановити, оновити чи запустити — напиши це явним окремим пунктом "Потрібно виконати вручну:" в кінці відповіді для цієї задачі, і не намагайся обійти це через bash/термінал.

Реалізуй дві задачі в FoxBrowser. Роби послідовно, кожну — окремим описом, що змінено і як перевірити вручну (агент працює в Linux sandbox без dotnet/WPF runtime — фінальний тест виконує користувач на Windows).

1. Діагностика й виправлення кнопки "Розширення"

Кнопка налаштувань розширень (ExtensionsSettingsWindow) працює неправильно. Перевір по черзі всі гіпотези нижче, знайди реальну причину в коді (не вигадуй, яка з них правильна, — прочитай файли й перевір), і виправ саме те, що підтвердиться. Якщо підтвердиться кілька — виправ усі.

1a. Recovery-fallback environment без AreBrowserExtensionsEnabled

  • Знайти в MainWindow/TabManager весь код навколо recovery-гілки з NEXT_AGENT_GUIDE/інструкції ("Startup recovery fix — 0x8007139F") — місце, де при HRESULT 0x8007139F створюється запасний CoreWebView2Environment з тимчасовою user-data folder.
  • Перевірити: чи цей запасний environment створюється через ту саму функцію/той самий CoreWebView2EnvironmentOptions з AreBrowserExtensionsEnabled = true, що й основний, чи через окремий шматок коду, де цей прапорець забули виставити.
  • Якщо прапорець не потрапляє в recovery-гілку — винести створення CoreWebView2EnvironmentOptions в один спільний метод/константу, яку використовують і основний, і recovery шлях, щоб розбіжність стала неможливою в принципі, а не просто додати прапорець ще раз у другому місці.
  • Додати явний лог/статус (напр. поле bool ExtensionsAvailable на TabManager чи MainWindow), який ExtensionsSettingsWindow може прочитати при відкритті — і якщо false (бо стартанули в recovery-режимі), показати користувачу зрозуміле повідомлення в самому вікні ("Розширення недоступні в цьому сеансі — застосунок запустився в режимі відновлення профілю, перезапусти FoxBrowser"), а не порожній список без пояснень.

1b. IsEnabled read-only і биндинг чекбокса

  • Знайти XAML розмітку списку розширень в ExtensionsSettingsWindow.xaml.
  • Перевірити: чи IsChecked чекбокса прив'язаний напряму двостороннім біндингом до Extension.IsEnabled (read-only властивість), чи через Checked/Unchecked event-обробник (або Command), що явно викликає await extension.EnableAsync(bool).
  • Якщо це прямий TwoWay-біндинг на read-only властивість — замінити на OneWay-біндинг для відображення поточного стану + окремий Click/Checked/Unchecked обробник, який викликає EnableAsync(), чекає результат, і тільки після успіху оновлює UI-стан (checkbox), а при помилці — повертає checkbox у попередній стан і показує повідомлення.

1c. FolderBrowserDialog без owner-вікна

  • Знайти виклик FolderBrowserDialog/OpenFileDialog для "Додати розширення" в ExtensionsSettingsWindow.xaml.cs.
  • Перевірити, чи передається owner-handle: new System.Windows.Interop.WindowInteropHelper(this).Handle через IWin32Window-обгортку (WinForms-діалог вимагає IWin32Window, не голий IntPtr — якщо ще нема обгортки-хелпера, додати простий NativeWindowWrapper : IWin32Window).
  • Якщо owner не передається — додати, щоб діалог відкривався поверх ExtensionsSettingsWindow, а не міг ховатись позаду.

1d. Options-сторінка розширення через спільний WebView2

  • Знайти обробник кнопки "Налаштування" (per-extension), що відкриває chrome-extension://<id>/options.html.
  • Перевірити: чи ця навігація йде через ТОЙ САМИЙ спільний CoreWebView2, яким керує TabManager для звичайних вкладок, чи через окремий CoreWebView2Controller, створений безпосередньо в ExtensionsSettingsWindow.
  • Якщо використовується спільний контрол — це помилка архітектури: клік по "Налаштування" в діалозі може непомітно перекидати активну вкладку користувача в головному вікні. Виправити: створити в ExtensionsSettingsWindow власний ізольований CoreWebView2Controller (з того самого CoreWebView2Environment, щоб профіль/розширення збігались) — тільки для options-сторінок, ніколи не займаючи головний спільний WebView2.

Після кожного виправленого пункту (1a-1d) — короткий підсумок і ручний тест-сценарій для Windows.

2. Звук WebView2 у Volume Mixer як "FoxBrowser"

Додати Core/AudioSessionLabeler.cs, який перейменовує WASAPI audio-сесії власних дочірніх WebView2-процесів на "FoxBrowser" з іконкою застосунку, БЕЗ ризику торкнутись чужих WebView2-сесій (Teams, Outlook, системний Edge).

  • Додати NuGet-пакет NAudio (зазнач це явно в "Потрібно виконати вручну" — сам пакет не встановлюй, тільки допиши <PackageReference> в .csproj вручну і попроси користувача зробити dotnet restore).
  • Клас має:
    1. Відстежувати список PID усіх дочірніх msedgewebview2.exe-процесів, які належать саме FoxBrowser (ті самі, що вже прив'язані через Job Object з попередньої задачі про дерево процесів — переюзати ту логіку, не дублювати).
    2. Через NAudio.CoreAudioApi.MMDeviceEnumerator отримати default render endpoint (eRender, eMultimedia), і його AudioSessionManager.
    3. Підписатись на подію нової сесії (AudioSessionManager.SessionCreated в NAudio, або еквівалент IAudioSessionNotification.OnSessionCreated якщо в NAudio такого немає в потрібній версії — перевір API конкретної версії пакету, яку додаси).
    4. У обробнику нової сесії: якщо session.GetProcessID входить у список PID FoxBrowser — викликати session.DisplayName = "FoxBrowser" і session.IconPath = Path.Combine(AppContext.BaseDirectory, "foxbrowser.ico") (або еквівалентні NAudio-методи SetDisplayNameAsync/властивості — перевір актуальний API пакету).
    5. Критично: ці властивості НЕ переживають життя об'єкта сесії (задокументована поведінка WASAPI) — тому одноразового виклику при старті недостатньо. Логіка з пункту 3-4 має спрацьовувати на КОЖНУ нову сесію протягом усього часу роботи FoxBrowser, не тільки на старті.
    6. НІКОЛИ не застосовувати DisplayName/IconPath до сесії, чий PID не входить у явно відстежуваний список власних дочірніх процесів — це і є захист від зачіпання чужих msedgewebview2.exe на машині користувача.
  • Покласти файл foxbrowser.ico в корінь проєкту поруч з іншими іконками (якщо такого файлу ще нема в репозиторії — створи заглушку-примітивну іконку і явно напиши користувачу в "Потрібно виконати вручну", що варто замінити на нормальну).
  • Викликати ініціалізацію AudioSessionLabeler один раз при старті застосунку (напр. в MainWindow після успішної ініціалізації TabManager, коли вже відомий перший дочірній PID).

Ручний тест Windows:

  1. Запустити FoxBrowser, відкрити вкладку з YouTube, почати відтворення.
  2. Відкрити Volume Mixer (правий клік на іконку гучності в треї Windows → Open Volume mixer, або через Settings → System → Sound → Volume mixer).
  3. Перевірити, що застосунок у списку показаний як "FoxBrowser" з іконкою застосунку, а не як "Microsoft Edge WebView2"/msedgewebview2.exe.
  4. Переключитись на іншу вкладку, знову увімкнути звук на новій — перевірити, що лейбл лишається "FoxBrowser" і для нової audio-сесії (не тільки для першої).
  5. Паралельно запустити щось інше з WebView2 на цій же машині (напр. Microsoft Teams, якщо є), перевірити, що ЙОГО лейбл у Volume Mixer НЕ змінився і лишився своїм — це підтверджує, що фільтр по PID працює правильно й не займає чужі процеси.