Skip to content

fix(ai): avoid native WebView2 crash in book_content_search on Windows - #978

Open
bazzdug-arch wants to merge 1 commit into
Anxcye:developfrom
bazzdug-arch:fix/ai-book-content-search-crash
Open

fix(ai): avoid native WebView2 crash in book_content_search on Windows#978
bazzdug-arch wants to merge 1 commit into
Anxcye:developfrom
bazzdug-arch:fix/ai-book-content-search-crash

Conversation

@bazzdug-arch

Copy link
Copy Markdown

Problem

On Windows, invoking the AI book_content_search tool crashes the app hard
(native access violation, no Dart exception, the process just dies). It is
reproducible whenever the AI searches the currently-open book. Related:
#844 (P1, open), #888 (closed stale).

Root cause

BookContentSearchRepository serves the search by spinning up a second
HeadlessInAppWebView that re-loads the book and runs foliate-js search().
On Windows (WebView2), creating a 2nd headless WebView while the reader
WebView is alive triggers a native crash in flutter_inappwebview
(upstream issue #2840). The crash is deterministic on affected machines and
is not mitigated by giving the 2nd WebView its own
WebViewEnvironment/userDataFolder — I tested that first (still crashed;
the log showed the dedicated environment being created, then the process
died mid-search with no completed event).

Fix (Option A: reuse the live reader controller)

On Windows, do not create a 2nd WebView. Run the search on the existing
reader WebView and collect the results.

  • EpubPlayerState.runAiBookSearch(keyword) — resets tocSearchProvider
    and runs the book-scoped search() on the live reader WebView, reusing
    the reader's existing onSearch handler (results flow to
    tocSearchProvider). Uses jsonEncode for safe keyword escaping.
  • BookContentSearchRepository.search():
    • On Windows, if the target book is the currently-open one, drive
      runAiBookSearch() and collect results from tocSearchProvider (poll
      until progress >= 1.0), then clearSearch() to clean up.
    • On Windows for a non-current book, return a graceful
      StateError in the tool result instead of crashing. The AI gets a
      clear message to ask the user to open the book.
    • On non-Windows, the existing headless session path is unchanged
      (the native crash is Windows/WebView2-specific).

Why not fix the plugin / keep the dedicated environment

A separate WebViewEnvironment (separate userDataFolder) was the first
attempt and does not help — the crash happens at 2nd-WebView creation
itself, independent of environment separation. The real fix belongs in the
flutter_inappwebview native Windows plugin (#2840); this PR is an
app-level workaround that avoids the 2nd WebView entirely on Windows so the
AI feature works today, with zero behavior change on other platforms.

Verification

Built and tested on Windows (Flutter 3.35.3, dev build 1.15.0):

  • Before: book_content_search crashed the app on the first call (log cut
    off mid-search, no completed event, process restarted).
  • After: ~12 consecutive book_content_search calls on the open book,
    all completed:true (~1-1.9 s each), real results (CFI + snippets), app
    stayed alive throughout. A search with zero matches returned
    completed:true with empty results (graceful, no crash).

flutter analyze on the changed files: no issues.

Files

  • lib/page/book_player/epub_player.dart — add runAiBookSearch().
  • lib/service/ai/tools/repository/book_content_search_repository.dart
    Windows live-reader path + graceful fallback; non-Windows unchanged.
  • lib/service/ai/tools/ai_tool_registry.dart — pass WidgetRef to the
    repository (needed to read tocSearchProvider / currentReadingProvider).

Notes / limitations

  • On Windows, searching a non-current book is unavailable (graceful
    error) until the native plugin issue is fixed. Acceptable trade-off vs. a
    hard crash; the common case (AI asked about the book the user is reading)
    works.
  • Minor UX side effect: while the AI search runs, the reader's TOC search
    drawer briefly reflects the AI's search (results are cleared on
    completion). Concurrent manual TOC search + AI search on the same book
    could conflict; AI tool calls are normally sequential.

Creating a second headless WebView (for AI book_content_search) while the
reader WebView is alive crashes the app natively on Windows
(flutter_inappwebview #2840): a hard access violation with no Dart
exception, regardless of WebViewEnvironment/userDataFolder separation.

On Windows, run the search on the live reader controller instead of
spawning a 2nd headless WebView:

- EpubPlayerState.runAiBookSearch(): resets tocSearchProvider and runs the
  book-scoped search() on the existing reader WebView (with jsonEncode
  keyword escaping), reusing the reader's onSearch handler.
- BookContentSearchRepository.search(): on Windows, if the target book is
  the currently-open one, drive runAiBookSearch() and collect results from
  tocSearchProvider (poll until progress >= 1.0); for a non-current book,
  return a graceful StateError instead of crashing.
- Non-Windows keeps the existing headless session path (unchanged).

Verified: ~12 consecutive book_content_search calls on the open book,
all completed:true, no crash (previously crashed on the first call).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants