Skip to content

feat(ui): embedded explorer WebView for block-height lookup (#139)#271

Merged
RaheemJnr merged 1 commit into
mainfrom
feat/embedded-explorer-webview-139
May 21, 2026
Merged

feat(ui): embedded explorer WebView for block-height lookup (#139)#271
RaheemJnr merged 1 commit into
mainfrom
feat/embedded-explorer-webview-139

Conversation

@RaheemJnr
Copy link
Copy Markdown
Owner

Summary

Adds an in-process WebView sheet for the explorer-deeplink-lookup flow (#85, #128). Custom Tabs (#138) remains the launcher for fire-and-forget tx-detail links, but the block-height lookup is round-trip critical and an OEM memory manager killing a Custom Tab mid-read forces a full restart. An embedded WebView eliminates that failure mode.

What ships

  • ExplorerWebViewSheet — new Composable wrapping a sandboxed WebView in a ModalBottomSheet.
  • HomeScreen + SettingsScreen sync-options paths route the lookup through the WebView sheet instead of openInBrowser.
  • Tx-detail explorer links elsewhere (ActivityScreen, SendScreen, etc) unchanged — they stay on Custom Tabs.

Security posture

Baked into the Composable so the next contributor inherits the constraints:

  • Host whitelist in shouldOverrideUrlLoading — only {www.,}explorer.nervos.org, testnet.explorer.nervos.org, pudge.explorer.nervos.org. Off-host nav escapes to openInBrowser so this never serves as a general-purpose in-app browser.
  • No addJavascriptInterface — no JS-to-native bridge. Documented inline so a future PR cannot add one silently.
  • Third-party cookies refused via CookieManager.setAcceptThirdPartyCookies(view, false).
  • allowFileAccess = false, allowContentAccess = false — closes off file:// / content:// URIs.
  • mixedContentMode = MIXED_CONTENT_NEVER_ALLOW — explorer is HTTPS-only.
  • WebView.destroy() on AndroidView.onRelease — JS context doesn't pin the process past dismissal.

UX

  • Top bar shows the host text (no full URL bar by design) + close + "Open in browser" escape hatch.
  • Linear progress indicator while pages load.
  • Sheet uses skipPartiallyExpanded so the WebView lands near full-height immediately.

Out of scope (flagged in the issue acceptance criteria)

  • Settings toggle to swap WebView ↔ Custom Tabs. Issue says wait for field data before making it configurable. For now WebView is the default for the lookup flow only.
  • Manual smoke on Tecno / Infinix / stock-Android — needs real devices.
  • Memory profile under sync load — needs real devices.

Test plan

  • ./gradlew :app:compileDebugKotlin -x cargoBuild BUILD SUCCESSFUL
  • ./gradlew :app:testDebugUnitTest -x cargoBuild BUILD SUCCESSFUL
  • Manual on a debug build: Settings → Sync mode → CUSTOM → tap "Don't know your block height?" opens the explorer in the in-app sheet
  • Tap a link to another domain inside the sheet — should open in Custom Tabs, not navigate inside the WebView
  • Dismiss the sheet — verify the WebView is destroyed (no leaked process)

Refs #139, #138, #85, #128

The explorer-deeplink-lookup flow (#85, #128) opens the user's
address page on the public CKB explorer so non-technical users can
scroll to their first transaction and copy the block number for the
CUSTOM sync mode. Custom Tabs (#138) is the current launcher; on
aggressive OEM memory managers (Tecno / Infinix / MIUI) the Custom
Tab tab can be killed mid-read, forcing a full restart and reopen.
For a fire-and-forget link this is annoying. For a round-trip
critical flow like block-height lookup it is a usability cliff.

What ships

- New `ExplorerWebViewSheet` Composable wrapping a sandboxed
  `WebView` in a `ModalBottomSheet`. Stays inside Pocket Node's
  process and task, so the lookup round-trip survives backgrounding.
- HomeScreen + SettingsScreen sync-options paths now route the
  lookup through the WebView sheet instead of `openInBrowser`.
- Tx-detail explorer links elsewhere in the app (ActivityScreen,
  SendScreen, etc) remain on Custom Tabs because they are
  fire-and-forget and do not benefit from in-process containment.

Security posture

The acceptance criteria from #139 are baked into the Composable
itself, not split across the call site, so the next contributor
extending this WebView inherits the constraints automatically:

  - Host whitelist enforced in `shouldOverrideUrlLoading`. Only
    explorer.nervos.org / testnet.explorer.nervos.org /
    pudge.explorer.nervos.org (and their `www.` aliases) load
    inside the WebView. Off-host navigation escapes to
    `openInBrowser` (Custom Tabs), so this never serves as a
    general-purpose in-app browser.
  - No `addJavascriptInterface`. There is no JS-to-native bridge.
    Documented inline so a future PR cannot add one silently.
  - Third-party cookies refused via
    `CookieManager.setAcceptThirdPartyCookies(view, false)`.
  - `allowFileAccess = false`, `allowContentAccess = false` to
    close off file:// / content:// URIs.
  - `mixedContentMode = MIXED_CONTENT_NEVER_ALLOW`: the explorer is
    HTTPS-only and any downgrade is a sign of a hostile redirect.
  - `WebView.destroy()` on AndroidView.onRelease so the JS context
    does not pin the process past dismissal.

UX

  - Top bar shows the current host text (no full URL bar by design)
    plus a close button and an "Open in browser" escape hatch that
    punts the same URL to Custom Tabs.
  - Linear progress indicator while pages load.
  - Sheet uses skipPartiallyExpanded so the WebView lands near
    full-height immediately (block lookup wants real estate).

Out of scope for this PR

  - Settings toggle to swap WebView for Custom Tabs as the lookup
    primitive. The issue suggests waiting for field data before
    making the choice flip configurable; for now the WebView is
    the default for the lookup flow only and Custom Tabs remains
    the default for all other links.
  - Manual smoke on Tecno / Infinix / stock-Android — flagged in
    the issue acceptance criteria but requires real devices.
  - Memory profile of WebView under sync load — flagged similarly.

Build verified locally:
  ./gradlew :app:compileDebugKotlin -x cargoBuild       BUILD SUCCESSFUL
  ./gradlew :app:testDebugUnitTest  -x cargoBuild       BUILD SUCCESSFUL
@vercel
Copy link
Copy Markdown

vercel Bot commented May 21, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
pocket-node Ready Ready Preview, Comment May 21, 2026 8:55pm

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 21, 2026

Warning

Rate limit exceeded

@RaheemJnr has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 55 minutes and 37 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 016749e6-7fb0-4426-8c56-b2a7bb9ecd84

📥 Commits

Reviewing files that changed from the base of the PR and between 3ffdbe8 and 79f7f31.

📒 Files selected for processing (3)
  • android/app/src/main/java/com/rjnr/pocketnode/ui/components/ExplorerWebViewSheet.kt
  • android/app/src/main/java/com/rjnr/pocketnode/ui/screens/home/HomeScreen.kt
  • android/app/src/main/java/com/rjnr/pocketnode/ui/screens/settings/SettingsScreen.kt
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/embedded-explorer-webview-139

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 79f7f313ac

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +252 to +257
val host = request.url.host
if (host == null || host !in allowedHosts) {
// Off-host navigation: punt to Custom Tabs so this
// WebView never serves as a general-purpose browser.
onOffHost(request.url.toString())
return true
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restrict off-host handling to main-frame HTTP(S) requests

shouldOverrideUrlLoading can be invoked for subframes and non-HTTP(S) schemes, but this implementation sends every non-allowlisted host to onOffHost(...). In practice, an embedded frame or script-initiated non-main-frame navigation from the explorer page can unexpectedly launch Custom Tabs/external apps and interrupt the block-height lookup flow even when the user did not intentionally leave the page. Gate this branch with request.isForMainFrame (and ideally an HTTP(S) scheme check) before calling onOffHost.

Useful? React with 👍 / 👎.

@RaheemJnr RaheemJnr merged commit dc0e80b into main May 21, 2026
7 checks passed
@RaheemJnr RaheemJnr deleted the feat/embedded-explorer-webview-139 branch May 21, 2026 21:40
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