feat(native-ui): locked-down webview element#7
Merged
Conversation
Adds a <native:webview> leaf element for embedding web content, with a paranoid-by-default posture: JS off, no DOM storage, no file access, no JS bridge to the host, no new windows (target=_blank / window.open denied), mixed content blocked, non-persistent cookies/data store, and media playback requiring a user gesture. Hosts opt back into individual capabilities via `javascript` / `dom-storage` attributes. Content comes from `src` (https/http/data/about schemes only) or inline `html` (loaded with a null base URL, so it gets an opaque origin). Top-frame navigations fire `@navigated` with the resolved URL once committed; external schemes (mailto, tel, intent, ...) are dropped. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Package renamed nativephp/native-ui -> nativephp/mobile-ui and the PHP
namespace Nativephp\NativeUi -> Native\Mobile\UI, matching the repo's
new home and bringing the plugin under the framework's Native\Mobile
namespace root (alongside Native\Mobile\Edge from nativephp/mobile).
Touches every class in src/, the PSR-4 mapping + provider FQCN in
composer.json, element/blade FQCNs and the plugin name in nativephp.json,
tests, docs, and namespace mentions in native-side comments. Platform
identifiers are intentionally unchanged: the Kotlin package
(com.nativephp.plugins.native_ui), Swift NativeUI* renderer names, the
manifest bridge namespace ("NativeUI"), and the native-ui config
key/publish tags.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The framework's PluginDiscovery and PluginValidateCommand both require type "nativephp-plugin" exactly; the old "nativephp-ui-plugin" value this test asserted would never be discovered. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
refactor(mobile-ui)!: rename package to nativephp/mobile-ui
`<x-webview php />` swaps the locked-down sandbox for the app's own enriched Laravel webview — pages served by the embedded PHP runtime with the full window.Native bridge, shared session store, and asset pipeline. `src` becomes an app route path; empty/relative falls back to the app's configured start URL. iOS builds an independent WKWebView wired like the shell's classic one (PHPSchemeHandler on php://, shared WebView.dataStore, addNativeHelper user scripts borrowed from the shell). Android runs the full WebViewManager.setup() wiring on a renderer-owned WebView, restoring the process-wide `shared` slot afterwards and wrapping the stock client so its "page load = web mode" isActive flip can't unmount the native tree this webview lives inside. `<x-webview fullscreen />` gives the v3 default-webview presentation: fill layout from the PHP side plus ignoresSafeArea on iOS. Also fixes `@navigated` never firing: `_navigated` isn't in the collector's callback allowlist, so the element now wires it in applyAttributes itself. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Device testing surfaced the real blocker for php mode: the persistent runtime's single PHP executor is parked in the native screen's event loop while a Route::native screen is live, so it can never answer the embedded webview's requests. Each php-mode webview now gets a dedicated WebviewPHPRuntime (its own PHP thread/context), wired through PHPSchemeHandler.dedicatedRuntime on iOS and PHPBridge.dedicatedWebviewRuntime on Android, and released the moment the webview leaves the view hierarchy. Also: reload once when WebKit's content process dies (transient kills self-heal), and diagnostic logging across the php-mode load/navigation path. Requires the nativephp/mobile counterpart that ships WebviewPHPRuntime (not in 4.0.0-rc.1). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Android side of the per-webview PHP runtime (mobile-air feat/webview-php-runtimes), plus the rendering fixes that made the embedded webview livable inside a native screen: - PhpWebView creates a WebviewPHPRuntime per instance, hands its PHPBridge to WebViewManager with embedded = true (no app-level mode flips or chrome clearing from an embedded page), and releases the runtime in onRelease so its PHP thread dies with the webview. - setBackgroundColor(TRANSPARENT) on the php webview — a fresh WebView surface otherwise paints opaque black over the window until Chromium's first paint (the sandbox factory already had this). - clipToBounds() on both AndroidView sites + a requestLayout() nudge on page commit: a WebView created mid-composition can transiently paint its layer at a stale offset covering sibling composables (tree and view bounds verified correct while it happened); clipping makes the race invisible and the nudge snaps the surface home. Verified with 514 recorded frames across 8 create/destroy cycles — zero artifacts. - K2 compile fixes: labeled return in the AndroidView factory restructured to an explicit branch; isLoadableScheme(String) renamed isLoadableUrl (JVM signature clash with the String? overload). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
feat(mobile-ui): webview php + fullscreen modes
The main merge brought in files predating the mobile-ui rename and the branch's Pint pass: ThemeFontsTest and README still referenced Nativephp\NativeUi, and six PHP files carried style drift. Renames applied, Pint run; suite green (98 passed). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds a
<native:webview>leaf element (self-closing,<x-webview />in Blade) for embedding web content on both platforms —WKWebViewon iOS,android.webkit.WebViewon Android.Security posture
Defaults are paranoid by design; hosts opt back into individual capabilities via Blade attributes:
javascriptattribute to enable)dom-storageattribute to enable)target=_blank/window.open()silently denied on both platformsMIXED_CONTENT_NEVER_ALLOW)https/http/data/about; external schemes (mailto,tel,intent, …) are dropped rather than dispatched to the systemAPI
src— URL to load (loadable schemes only)html— inline HTML, loaded with a null base URL so it gets an opaque origin and can't make same-origin requests against the host app@navigated— fires once per committed top-frame navigation with the resolved URL (didCommiton iOS,onPageCommitVisibleon Android)Content reloads only when
src/htmlactually change (signature check), so recompositions/re-renders don't reset scroll position or flicker.Notes
self_closing: true— the renderers intentionally ignore children.applyA11yAttributes()wired in like the other elements.nativephp/mobile(pre-existing:mainalready targets unreleased Edge classes likeNative\Mobile\Edge\Element), so this was validated by manifest/class cross-check rather than pest.🤖 Generated with Claude Code