统一移动外链打开 helper
让 HostBridge 外链打开复用移动壳外链 helper 用配置检查防止两条外链路径漂移 同步移动壳外链 helper 共用决策记录
This commit is contained in:
@@ -1596,12 +1596,10 @@ if (
|
||||
!hostBridgeSource.includes(
|
||||
'const externalUrlPayload = normalizeHostBridgeExternalUrlPayload(',
|
||||
) ||
|
||||
!hostBridgeSource.includes('const { url } = externalUrlPayload;') ||
|
||||
!hostBridgeSource.includes('Linking.canOpenURL(url)') ||
|
||||
!hostBridgeSource.includes('Linking.openURL(url)')
|
||||
!hostBridgeSource.includes('openMobileShellExternalNavigation(Linking, externalUrlPayload.url)')
|
||||
) {
|
||||
throw new Error(
|
||||
'mobile shell app.openExternalUrl must normalize payloads with the shared HostBridge external URL boundary',
|
||||
'mobile shell app.openExternalUrl must normalize payloads and use the shared external navigation helper',
|
||||
);
|
||||
}
|
||||
if (
|
||||
@@ -1762,8 +1760,10 @@ if (!dispatchSource.includes('Appearance.getColorScheme()')) {
|
||||
throw new Error('mobile shell HostBridge must read the native color scheme');
|
||||
}
|
||||
|
||||
if (!dispatchSource.includes('Linking.canOpenURL(url)')) {
|
||||
throw new Error('mobile shell HostBridge external URL flow must check Linking.canOpenURL');
|
||||
if (!dispatchSource.includes('openMobileShellExternalNavigation(Linking, externalUrlPayload.url)')) {
|
||||
throw new Error(
|
||||
'mobile shell HostBridge external URL flow must use the shared external navigation helper',
|
||||
);
|
||||
}
|
||||
|
||||
if (!shellAppSource.includes('openMobileShellExternalNavigation(Linking, request.url)')) {
|
||||
|
||||
@@ -27,7 +27,10 @@ import {
|
||||
type OpenExternalUrlPayload,
|
||||
type SetBadgeCountPayload,
|
||||
} from '../../../../packages/shared/src/contracts/hostBridge';
|
||||
import { resolveMobileShellWebViewUrl } from '../shell/navigation';
|
||||
import {
|
||||
openMobileShellExternalNavigation,
|
||||
resolveMobileShellWebViewUrl,
|
||||
} from '../shell/navigation';
|
||||
import { getMobileNetworkStatus } from '../shell/network';
|
||||
import { MOBILE_SHELL_HOST_VERSION } from '../shell/runtime';
|
||||
import { resolveMobileHostCapabilities } from './capabilities';
|
||||
@@ -78,15 +81,13 @@ async function openExternalUrl(payload: unknown) {
|
||||
throw invalidRequest('url must use an allowed external protocol');
|
||||
}
|
||||
|
||||
const { url } = externalUrlPayload;
|
||||
if (!(await Linking.canOpenURL(url))) {
|
||||
if (!(await openMobileShellExternalNavigation(Linking, externalUrlPayload.url))) {
|
||||
throw {
|
||||
code: 'host_error',
|
||||
message: 'external URL cannot be opened',
|
||||
} satisfies HostBridgeError;
|
||||
}
|
||||
|
||||
await Linking.openURL(url);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
- 2026-06-18 移动壳 WebView 导航收紧:Expo WebView 自身拦截外域导航时复用 HostBridge 外链协议白名单,只把 `http:`、`https:`、`mailto:`、`tel:` 交给 `Linking.openURL`,`javascript:`、`file:`、相对异常路径等危险目标直接阻断,避免离开同源主站后仍保留完整 HostBridge。
|
||||
- 2026-06-19 移动壳 WebView 外链协议共源:`apps/mobile-shell/src/shell/navigation.ts` 的 WebView 外链离壳判断必须调用共享 `normalizeHostBridgeExternalUrl`,不得在 shell 层另写协议判断;`apps/mobile-shell/scripts/check-config.mjs` 会拒绝重新硬编码 `mailto:` / `tel:` / `javascript:` 等协议分支,`navigation.test.ts` 用 `HOST_BRIDGE_EXTERNAL_URL_PROTOCOLS` 反查当前允许协议。
|
||||
- 2026-06-19 移动壳 WebView 外链打开收口:Expo WebView 外链拦截统一调用 `openMobileShellExternalNavigation(Linking, request.url)`,该 helper 先复用共享外链协议 normalizer,再调用 `canOpenURL` 确认系统可处理,最后才 `openURL`;系统不能打开或 URL 被拒绝时只阻断留壳,不伪造成功也不把危险协议交给系统。`ShellApp` 不再内联 `Linking.canOpenURL` / `Linking.openURL` Promise 链,移动壳配置检查和 `navigation.test.ts` 会覆盖该顺序。
|
||||
- 2026-06-19 移动壳外链打开 helper 共用:Expo WebView 外域拦截和 HostBridge `app.openExternalUrl` 都必须复用 `openMobileShellExternalNavigation` 执行系统外链打开动作;HostBridge 分支仍先调用 `normalizeHostBridgeExternalUrlPayload` 保留 payload 错误语义,但不再单独维护 `Linking.canOpenURL` / `Linking.openURL` 顺序。移动壳配置检查会拒绝 `app.openExternalUrl` 绕开该 helper,避免两条离壳路径漂移。
|
||||
- 2026-06-19 移动壳系统分享 URL 边界:Expo `share.open` 调用 React Native 系统分享面板前,只允许把 `url`、`href`、`path`、`targetPath` 和 `work` 归一为 `https://app.genarrative.world` 同源公开 URL;外域、协议相对 URL、`javascript:` 等危险目标必须返回 `invalid_request`,且显式非法 payload 不得回退到之前缓存的 `share.setTarget` 目标。分享实现复用移动壳入口 URL 的生产主站 origin,配置检查会拒绝重新声明同值 origin 或移除协议相对 URL 拦截。
|
||||
- 2026-06-19 桌面壳系统分享 URL 边界:Tauri `share.open` 写入系统剪贴板前同样只允许把 `url`、`href`、`path`、`targetPath` 和 `work` 归一为 `https://app.genarrative.world` 同源公开 URL;外域、协议相对 URL、`javascript:` 等危险目标必须返回 `invalid_request`,且显式非法 payload 不得回退到之前缓存的 `share.setTarget` 目标。桌面壳配置检查会拒绝移除同源分享 URL 归一和协议相对 URL 拦截。
|
||||
- 2026-06-18 能力声明收紧:`packages/shared/src/contracts/hostBridge.ts` 提供 HostBridge method / capability 白名单,H5 的 `getHostRuntime()` 会解析并过滤 `hostCapabilities`;`openHostShare`、`writeHostClipboardText`、`requestHostHapticsImpact`、`setHostAppTitle`、`exportHostTextFile` 等 native 能力只在宿主声明对应 capability 后调用。发布分享弹窗只有声明 `share.open` 时才显示“系统分享”,避免旧壳或裁剪壳露出不可用入口。
|
||||
|
||||
Reference in New Issue
Block a user