Skip to content

[Android] BlazorWebView: Simplify Blazor startup scripts - #35053

Merged
kubaflo merged 5 commits into
inflight/currentfrom
mattleibow/remove-run-blazor-startup-scripts
Aug 9, 2026
Merged

kubaflo merged 5 commits into
inflight/currentfrom
mattleibow/remove-run-blazor-startup-scripts

Conversation

@mattleibow

@mattleibow mattleibow commented Apr 20, 2026 •

Copy link
Copy Markdown
Member

Note

Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

Description

Refactors the Android RunBlazorStartupScripts method in WebKitWebViewClient.cs from a three-level nested EvaluateJavascript callback chain into one BlazorInitScript constant with one callback.

What changed

Before: Three nested EvaluateJavascript calls with three JavaScriptValueCallback instances:

  1. Check window.__BlazorStarted.
  2. Inject JavaScript that creates a MessageChannel, sets up window.external, and configures port listeners.
  3. After native SetUpMessageChannel() posts the port, inject Blazor.start() and set __BlazorStarted.

After: One BlazorInitScript constant and one EvaluateJavascript callback:

  • Eliminates the JavaScript-side relay MessageChannel.
  • Uses window.__nativePort for JavaScript-to-native messaging.
  • Dispatches native-to-JavaScript messages from the window message event to window.external.__callback.
  • Calls Blazor.start() from the capturePort handler so the native port is captured first.

Startup flags

Introduces two flags:

  • window.__BlazorStarting is set when the initialization script runs and guards duplicate OnPageFinished calls.
  • window.__BlazorStarted is set after the Blazor.start() promise resolves and is used by WaitForWebViewReady.

Message-source filtering

The message listener processes only events for which event.source === null; events from JavaScript contexts with a non-null source are skipped.

Preserved behavior

  • Native WebMessageChannel setup through SetUpMessageChannel().
  • Native-to-JavaScript PostWebMessage calls through SendMessage().
  • BlazorWebMessageCallback for JavaScript messages received on the native port.
  • autostart="false" in templates; no template changes.

New device tests

Adds BlazorWebViewTests.Startup.cs with six tests:

Test Scope Verifies
BlazorStartupSetsUpWindowExternal All platforms sendMessage and receiveMessage are functions
BlazorStartupSetsStartingAndStartedFlags Android Both startup flags become true
BlazorStartupCapturesNativePort Android window.__nativePort is set after handoff
BlazorStartupScriptIsIdempotent Android Duplicate startup does not replace the port or submit another channel
BlazorStartupRejectionPreservesLiveBridge Android A post-start promise rejection does not destroy the active bridge
BlazorMessageDispatchOnlyProcessesNativeSourceMessages Android A same-window JavaScript message is not dispatched to the bridge callback

Also adds WebViewHelpers.WaitForCondition(), which polls a JavaScript boolean expression through the existing retry infrastructure.

Files changed

File Change
src/BlazorWebView/src/Maui/Android/WebKitWebViewClient.cs Refactors startup and bridge initialization
src/BlazorWebView/src/SharedSource/Log.cs Adds the BlazorStartupScriptsSubmitted log event
src/BlazorWebView/tests/DeviceTests/Elements/BlazorWebViewTests.Startup.cs Adds six startup tests
src/BlazorWebView/tests/DeviceTests/WebViewHelpers.Shared.cs Adds WaitForCondition

Validation status

The trusted Android BlazorWebView Gate currently fails: 24 of 29 tests time out waiting for window.Blazor and window.__BlazorStarted. The implementation requires correction before merge; no passing test result is claimed.

Copilot AI lite review requested due to automatic review settings April 20, 2026 22:46
@github-actions

github-actions Bot commented Apr 20, 2026 •

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 35053

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 35053"

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Refactors Android BlazorWebView startup initialization to reduce nested EvaluateJavascript callback chains, and adds device tests/helpers to validate startup invariants and messaging behavior.

Changes:

  • Replaces the nested Android startup script sequence with a single BlazorInitScript executed via one EvaluateJavascript call.
  • Adds new BlazorWebView device tests focused on startup flags/port capture/idempotency and message dispatch filtering.
  • Introduces WebViewHelpers.WaitForCondition() to poll arbitrary JS conditions using existing retry infrastructure.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
src/BlazorWebView/src/Maui/Android/WebKitWebViewClient.cs Consolidates Android Blazor startup JS into a single init script and simplifies native callback flow.
src/BlazorWebView/tests/DeviceTests/Elements/BlazorWebViewTests.Startup.cs Adds startup-focused device tests for Android/all platforms.
src/BlazorWebView/tests/DeviceTests/WebViewHelpers.Shared.cs Adds a generic “wait for JS condition” helper used by the new tests.

Comment thread src/BlazorWebView/src/Maui/Android/WebKitWebViewClient.cs Outdated
Comment thread src/BlazorWebView/src/Maui/Android/WebKitWebViewClient.cs
Comment thread src/BlazorWebView/tests/DeviceTests/WebViewHelpers.Shared.cs Outdated
Comment thread src/BlazorWebView/tests/DeviceTests/Elements/BlazorWebViewTests.Startup.cs Outdated
@mattleibow
mattleibow force-pushed the mattleibow/remove-run-blazor-startup-scripts branch 2 times, most recently from ea7944d to 5ed2bbf Compare April 20, 2026 23:10
@mattleibow
mattleibow requested a review from Copilot April 20, 2026 23:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

Comment thread src/BlazorWebView/src/Maui/Android/WebKitWebViewClient.cs Outdated
@mattleibow
mattleibow force-pushed the mattleibow/remove-run-blazor-startup-scripts branch from 5ed2bbf to 551c803 Compare April 20, 2026 23:36
@mattleibow
mattleibow requested a review from Copilot April 20, 2026 23:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

Comment thread src/BlazorWebView/tests/DeviceTests/WebViewHelpers.Shared.cs Outdated
Comment thread src/BlazorWebView/tests/DeviceTests/Elements/BlazorWebViewTests.Startup.cs Outdated
Comment thread src/BlazorWebView/src/Maui/Android/WebKitWebViewClient.cs
Comment thread src/BlazorWebView/src/Maui/Android/WebKitWebViewClient.cs Outdated
@mattleibow
mattleibow force-pushed the mattleibow/remove-run-blazor-startup-scripts branch from 551c803 to ca96b1d Compare April 20, 2026 23:52
@MauiBot MauiBot added s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Apr 21, 2026
@dotnet dotnet deleted a comment from MauiBot Apr 23, 2026
@dotnet dotnet deleted a comment from MauiBot Apr 24, 2026
@dotnet dotnet deleted a comment from MauiBot Apr 26, 2026
@kubaflo

kubaflo commented Apr 28, 2026

Copy link
Copy Markdown
Contributor

/review

@github-actions

github-actions Bot commented Apr 28, 2026 •

Copy link
Copy Markdown
Contributor

✅ Expert Code Review completed successfully!

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Expert Code Review — PR #35053

Methodology: 3 independent reviewers with adversarial consensus (initial review + targeted follow-ups for disputed findings).


Summary

This is a well-executed simplification that collapses a 3-level nested EvaluateJavascript callback chain into a single self-contained init script. The elimination of the JS-side MessageChannel relay is a genuine architectural improvement, and the new capturePort-gated Blazor.start() fixes a latent ordering issue. The 5 new device tests provide thorough coverage of the key behaviors (bridge setup, startup flags, port capture, idempotency, message source filtering).


Findings

# Severity Finding Consensus File
1 🟡 MODERATE Missing .catch() on Promise.resolve(Blazor.start()) — unhandled rejection leaves startup permanently blocked 3/3 reviewers WebKitWebViewClient.cs:57
2 🟡 MODERATE BlazorStartupScriptsFinished log semantics changed — fires unconditionally and before actual Blazor.start() completion 3/3 reviewers WebKitWebViewClient.cs:214
3 🟢 MINOR Test setup boilerplate (~15 lines) repeated across all 5 test methods 2/3 reviewers BlazorWebViewTests.Startup.cs
4 🟢 MINOR receiveMessage single-callback overwrites (Android) vs multi-callback array (iOS) — pre-existing cross-platform inconsistency 2/3 reviewers WebKitWebViewClient.cs:44
5 🟢 MINOR event.source === null assumption for native PostWebMessage could use documentation note 2/3 reviewers WebKitWebViewClient.cs:52

Discarded Findings (single reviewer, not corroborated)

  • sendMessage silently drops messages before port capture — both follow-up reviewers independently concluded this is pre-existing behavior (not a regression) and the internal bridge is not a public API
  • Idempotency test validates JS guard pattern rather than re-injecting the actual init script
  • startedValue assertion in BlazorStartupSetsStartingAndStartedFlags is tautological after WaitForWebViewReady

Test Coverage Assessment

✅ Good coverage: 5 new device tests covering startup bridge, flags, port capture, idempotency, and message source filtering. The WaitForCondition helper is a useful reusable addition. The cross-platform BlazorStartupSetsUpWindowExternal test validates the bridge on all platforms, while the Android-specific #if ANDROID tests appropriately scope platform-specific behavior.

⚠️ Gap: No test for Blazor.start() rejection path (aligns with Finding #1). If .catch() is added, a corresponding test would strengthen confidence.


Verdict

LGTM with suggestions. The two 🟡 MODERATE findings (missing .catch() and log semantics) are non-blocking but worth addressing — especially the Promise rejection path, which would make startup failures much harder to diagnose without it. The 🟢 MINOR findings are all non-blocking improvements or pre-existing observations.

Generated by Expert Code Review for issue #35053 · ● 16.1M

Comment thread src/BlazorWebView/src/Maui/Android/WebKitWebViewClient.cs Outdated
Comment thread src/BlazorWebView/src/Maui/Android/WebKitWebViewClient.cs
Comment thread src/BlazorWebView/src/Maui/Android/WebKitWebViewClient.cs
Comment thread src/BlazorWebView/src/Maui/Android/WebKitWebViewClient.cs Outdated
@sheiksyedm sheiksyedm modified the milestones: .NET 10 SR10, .NET 10 SR11 Aug 26, 2026
This was referenced Sep 22, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates s/agent-gate-failed AI could not verify tests catch the bug s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants