Skip to content

Isolate email from main window - #41

Merged
FixeQD merged 61 commits into
mainfrom
dev/isolated-messageview
Jun 14, 2026
Merged

FixeQD merged 61 commits into
mainfrom
dev/isolated-messageview

Conversation

@FixeQD

@FixeQD FixeQD commented Jun 14, 2026 •

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Added email webview process monitoring with automatic freeze/recovery detection to prevent rendering hangs.
    • Integrated native external link confirmation dialogs for improved security.
    • Added memory usage monitoring and visual notification when resource limits are exceeded.
  • Refactor

    • Restructured email rendering to use native webview implementation instead of iframe-based approach.
    • Moved email body preparation and caching to backend layer for improved performance and stability.

FixeQD and others added 30 commits May 2, 2026 03:14
Add Tauri commands to update and destroy the email webview and yield
briefly when recreating to let the close propagate. Replace iframe in
MessageViewBody with a placeholder div, spawn/destroy the native child
webview from React, and use ResizeObserver + requestAnimationFrame to
sync logical bounds via update_email_webview_bounds. Remove the iframe
postMessage resize/link handling and related iframe plumbing.
Change fetch_thread to return a ThreadView (with ThreadMessage entries)
constructed from MessageFull. Add ThreadMessage and ThreadView structs
to db/mod.rs. Add a defensive Array.isArray check in the React
MessageView
before accessing thread.messages.
Store raw HTML body (use unwrap_or_default) instead of running
ammonia::clean so original markup is preserved. Reorder imports for
consistency.
Use get_crypto and eml_cache::load_body to populate body_html,
body_plain and read_receipt_to. On cache miss fetch the full message
via the IMAP manager and cache the result.
…it2gtk implementation for embedded email rendering
Add allow-main-commands and allow-email-heartbeat permissions, and
create src-tauri/permissions/main-commands.toml and watchdog.toml.
Add "allow-main-commands" to default capabilities and normalize
email-webview.json formatting. Extract tpm_check helper with a 3s
timeout, simplify TPM availability mapping, and streamline security
commands handling.
Make email_heartbeat return the next nonce string and return Err on
unarmed,
token mismatch, or rate-limit. On success rotate the token and return
the new
nonce.

Inject a client-side heartbeat loop into served email HTML and
initialize
WatchdogState (token, last_heartbeat, created_at, is_frozen). Update
TODO to
mark 27.8 as done.
Implement suspend_process_windows using Toolhelp/Thread APIs to suspend
all threads of the target PID. Call SIGSTOP on Linux and suspend on
Windows via cfg branches. Restrict several EmbeddedEmailState fields to
linux-only and move SendWidget type for reuse. Update Cargo.toml deps
for required Windows and nix features and mark TODO 27.14 complete
Merge 'main' into working branch
Add read_renderer_memory(pid) for Linux (proc statm) and Windows
(GetProcessMemoryInfo), returning 0 on failure. Populate
FreezeStats.memory_bytes and set it in the watchdog loop. Add
Win32_System_ProcessStatus feature to Cargo.toml and mark TODO 27.15
as completed
Add listeners for 'email_webview_frozen' and 'email_webview_resumed'
(Tauri),
store FreezeStats in state and render EmailFreezeNotice overlay when
frozen.
Import listen and FreezeStats, make container relative to position the
overlay,
and clean up listeners on unmount.
Replace the floating draggable freeze notice with a compact inline
banner and
remove pointer-drag logic and GripHorizontal import. Wrap the notice in
the
message view layout and adjust styles for amber warning tones. Add a
scroll
listener and initial sync to keep the native webview bounds updated, and
include frozenStats in the effect deps. Clean up unused imports.
Implement platform-specific resume logic for frozen email webview.
Use SIGCONT on Unix and ResumeThread on Windows. Emit
email_webview_resumed event, register the command in Tauri, add
permission and mark related TODO items done
Add a resumed_at timestamp to WatchdogData to track when a webview
was last resumed. Use this to enforce a 10s cooldown after unfreeze
before tightening heartbeat thresholds (then a 5s grace at 3s, then
500ms). Set resumed_at when resuming the email webview.
FixeQD and others added 27 commits May 8, 2026 19:25
Replace postMessage from the webview with a fetch to /message/link.
The handler parses the url query param, rejects non-http(s) schemes
(javascript:, data:, file:, etc.), and responds with 400/403 for invalid
requests. On success it emits the email_link_clicked event so the React
frontend can show a confirmation dialog
confirmation dialog

- Remove redundant UI dialog and simplify external link confirmation
  flow
- Use native OS dialogs for external link confirmation
- Improve security by removing custom dialog implementation
- Switch to `add_child` API for child webview management
- Update webview bounds using `tauri::Rect` and `tauri::Size` types
- Fix module path for Windows webview2 renderer detection
The change replaces `get_webview_window` with `get_window` to correctly
retrieve the main window instance, resolving an incorrect API usage that
was causing lookup failures.
The FALSE constant needs to be explicitly converted to a boolean type
for the Windows API calls to work correctly. This change ensures proper
thread suspension and resumption functionality.
- Use correct TimeSpan struct for appointment duration
- Request appropriate calendar access rights
- Handle cases where no calendars exist by creating a default one
- Ensure events are saved to a valid calendar instance
- Add Windows-specific webview state handling with COM objects
- Introduce WinViewInner struct for Windows Composition API
- Wrap non-Send handles with SendWidget for cross-platform compatibility
- Update Linux process detection logic
- Switch from windows::create/update/destroy/reload to win:: equivalents
- Remove redundant info message on webview reload
- Disable "tpm" feature by default in favor of empty default features
  list
Added pending_bounds to manage window dimensions before initialization

Signed-off-by: Paweł <134298056+FixeQD@users.noreply.github.com>
Refactor protocol routing to expose handle_message_route taking an
AppHandle
so the WebView2 handler can call it. Wire the handler into webview init
and add
required Windows COM and StructuredStorage features to Cargo.toml.
@coderabbitai

coderabbitai Bot commented Jun 14, 2026 •

Copy link
Copy Markdown

Review Change Stack

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Free

Run ID: a8e3419a-ff24-4f7c-8d57-caefed59e614

📥 Commits

Reviewing files that changed from the base of the PR and between 73f9d54 and a15cd4a.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (47)
  • .cargo/config.toml
  • .gitignore
  • Cargo.toml
  • TODO.md
  • crates/email_network/Cargo.toml
  • crates/email_network/src/error.rs
  • crates/email_network/src/lib.rs
  • crates/email_network/src/network/cache.rs
  • crates/email_network/src/network/fetcher.rs
  • crates/email_network/src/network/mod.rs
  • crates/email_network/src/network/null_proxy.rs
  • crates/email_network/src/network/rewriter.rs
  • crates/email_webview/Cargo.toml
  • crates/email_webview/src/commands.rs
  • crates/email_webview/src/lib.rs
  • crates/email_webview/src/policy.rs
  • crates/email_webview/src/state.rs
  • crates/email_webview/src/watchdog.rs
  • crates/email_webview/src/webview/linux.rs
  • crates/email_webview/src/webview/mod.rs
  • crates/email_webview/src/webview/windows.rs
  • src-tauri/Cargo.toml
  • src-tauri/src/calendar/mod.rs
  • src-tauri/src/cmd/mail/listing/fetching.rs
  • src-tauri/src/cmd/network.rs
  • src-tauri/src/cmd/security/mod.rs
  • src-tauri/src/cmd/security/options.rs
  • src-tauri/src/cmd/utils.rs
  • src-tauri/src/db/mail/message_bodies.rs
  • src-tauri/src/db/mod.rs
  • src-tauri/src/email_view.rs
  • src-tauri/src/error.rs
  • src-tauri/src/lib.rs
  • src-tauri/src/main.rs
  • src-tauri/src/protocol.rs
  • src-tauri/src/security/tpm/store/linux.rs
  • src-tauri/src/security/tpm/store/mod.rs
  • src-tauri/src/security/tpm/store/windows.rs
  • src-tauri/src/webview_policy.rs
  • src-tauri/tests/db.rs
  • src/components/Inbox/MessageView/EmailFreezeNotice.tsx
  • src/components/Inbox/MessageView/MessageViewBody.tsx
  • src/components/Inbox/MessageView/ThreadView.tsx
  • src/components/Inbox/MessageView/index.tsx
  • src/i18n/resources/en/inbox.json
  • src/types/components/shared.ts
  • src/types/mail.ts
💤 Files with no reviewable changes (4)
  • crates/email_network/src/network/null_proxy.rs
  • src-tauri/src/webview_policy.rs
  • crates/email_network/src/network/rewriter.rs
  • src/types/mail.ts

📝 Walkthrough

Walkthrough

Two new Rust workspace crates (email_network, email_webview) are introduced. email_network extracts error types and refactors ResourceCache to accept injected encrypt/decrypt closures. email_webview implements a cross-platform isolated email renderer: a heartbeat watchdog that detects silence and freeze/resumes the renderer process, Linux GTK overlay and Windows DirectComposition WebView2 backends, Tauri IPC commands, and protocol routing for heartbeat and link-click events. The frontend MessageViewBody is rewritten to manage this native webview, and TPM feature-flag gating is tightened across the security module.

Changes

Isolated Email Webview with Watchdog

Layer / File(s) Summary
Workspace & crate scaffolding
Cargo.toml, .cargo/config.toml, .gitignore, crates/email_network/Cargo.toml, crates/email_webview/Cargo.toml, src-tauri/Cargo.toml, TODO.md
Registers email_network and email_webview as workspace members, adds a release profile, configures the Windows GNU linker, expands platform dependency sets, removes tpm from default features, and marks TODO section 27 items as complete.
email_network: error types and cache closure injection
crates/email_network/src/error.rs, crates/email_network/src/lib.rs, crates/email_network/src/network/cache.rs, src-tauri/src/error.rs
Defines NetworkError/CacheError in email_network, refactors ResourceCache::new to accept caller-provided encrypt/decrypt closures replacing the global SECURITY lock, and re-exports the error types from src-tauri/src/error.rs.
email_webview: watchdog state, heartbeat, and freeze/resume
crates/email_webview/src/watchdog.rs, crates/email_webview/src/lib.rs
Introduces WatchdogData/WatchdogState, a token-rotating email_heartbeat with rate limiting, an async run_watchdog_loop that suspends the renderer (SIGSTOP/SuspendThread) when heartbeats cease, FreezeStats telemetry, and OS-specific process suspend/resume/memory helpers.
email_webview: shared state and network/resource policy
crates/email_webview/src/state.rs, crates/email_webview/src/policy.rs
Defines EmbeddedEmailState (Linux overlay/webview handles, Windows WinViewInner) and SendWidget; implements install_network_block (Linux WebKitGTK proxy) and Windows set_route_handler/register_webview2_resource_handler COM interop.
email_webview: Linux GTK and Windows DirectComposition backends
crates/email_webview/src/webview/mod.rs, crates/email_webview/src/webview/linux.rs, crates/email_webview/src/webview/windows.rs
Linux backend embeds WebKit2GTK in a GTK overlay and detects renderer PID via sysinfo diff. Windows backend initializes WebView2 via DirectComposition/D3D11 with deferred bounds and Toolhelp PID capture. Both expose create/update_bounds/destroy/reload.
email_webview: Tauri IPC commands
crates/email_webview/src/commands.rs
Exposes create/update_bounds/destroy/reload/resume as Tauri commands, dispatching to the correct platform backend; resume_email_webview handles the full async unfreeze flow with watchdog state updates and event emission.
src-tauri: data models, email HTML preparation, and protocol routing
src-tauri/src/db/mod.rs, src-tauri/src/db/mail/message_bodies.rs, src-tauri/src/cmd/mail/listing/fetching.rs, src-tauri/src/email_view.rs, src-tauri/src/protocol.rs, src-tauri/src/cmd/utils.rs
Adds MessageMeta/ThreadViewMeta DB structs; updates fetch_message_full/fetch_thread to return them; implements prepare_email_view (encrypted body load, cid: inline image embedding, external resource rewriting); refactors protocol::handler to route /message/heartbeat and /message/link; injects a heartbeat polling script into served HTML; removes ammonia::clean; adds confirm_external_link.
src-tauri: app initialization wiring and TPM feature cleanup
src-tauri/src/lib.rs, src-tauri/src/webview_policy.rs, src-tauri/src/main.rs, src-tauri/src/security/tpm/store/..., src-tauri/src/calendar/mod.rs, src-tauri/src/cmd/security/options.rs, src-tauri/src/cmd/security/mod.rs, src-tauri/tests/db.rs
Wires EmbeddedEmailState/WatchdogState, constructs ResourceCache with SECURITY closures, spawns run_watchdog_loop, migrates network policy to new crates, removes webview_policy.rs. TPM stores on Linux/Windows become unconditionally compiled; get_tpm_store gains tpm feature gate; tpm_check() helper deduplicates security options logic; calendar Windows helpers offloaded to spawn_blocking.
Frontend: native webview MessageViewBody rewrite and freeze notice
src/types/..., src/components/Inbox/MessageView/MessageViewBody.tsx, src/components/Inbox/MessageView/EmailFreezeNotice.tsx, src/components/Inbox/MessageView/ThreadView.tsx, src/components/Inbox/MessageView/index.tsx, src/i18n/resources/en/inbox.json
MessageViewBodyProps switches from rendered content fields to message identity fields; MessageViewBody manages native webview lifecycle via Tauri commands, syncs bounds via ResizeObserver, and listens for freeze/link-click events. EmailFreezeNotice provides resume/dismiss UI. ThreadView and MessageView call sites are updated accordingly.

Sequence Diagram(s)

sequenceDiagram
  participant React as MessageViewBody
  participant TauriIPC as Tauri IPC
  participant RustProtocol as protocol.rs
  participant Watchdog as run_watchdog_loop
  participant NativeWV as Native Webview Process

  React->>TauriIPC: create_email_webview
  TauriIPC->>NativeWV: spawn GTK overlay / WebView2 DComp
  React->>TauriIPC: prepare_email_view(account, mailbox, uid)
  TauriIPC->>RustProtocol: store HTML in EmailViewState
  React->>TauriIPC: reload_email_webview
  RustProtocol-->>NativeWV: serve HTML + heartbeat script + CSP
  loop every ~5s
    NativeWV->>RustProtocol: GET /message/heartbeat?token=T
    RustProtocol->>Watchdog: email_heartbeat(token)
    Watchdog-->>RustProtocol: next_token
    RustProtocol-->>NativeWV: {"token": "next_token"}
  end
  Note over Watchdog: silence > threshold
  Watchdog->>NativeWV: SIGSTOP / SuspendThread
  Watchdog->>React: emit email_webview_frozen(FreezeStats)
  React->>React: show EmailFreezeNotice
  React->>TauriIPC: resume_email_webview
  TauriIPC->>NativeWV: SIGCONT / ResumeThread
  TauriIPC->>React: emit email_webview_resumed
  React->>React: hide EmailFreezeNotice
  React->>TauriIPC: destroy_email_webview (unmount)
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Poem

🐇 A bunny built two crates with care,
To watch the webview — freeze it there!
A heartbeat ticks, a token spins,
GTK and DComp — the browser wins.
If silence grows, it hits SIGSTOP,
Then hops right back — it'll never drop! 🎉


Note

🎁 Summarized by CodeRabbit Free

Your organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/login.

Comment @coderabbitai help to get the list of available commands and usage tips.

@FixeQD
FixeQD merged commit 46cd0d5 into main Jun 14, 2026
2 of 3 checks passed
@FixeQD
FixeQD deleted the dev/isolated-messageview branch June 14, 2026 16:08
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.

1 participant