From 69ff4af4e67d579d57b73980e4966bf6b82669ab Mon Sep 17 00:00:00 2001 From: kdletters Date: Sat, 20 Jun 2026 22:29:21 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AE=B0=E5=BD=95=E7=A7=BB=E5=8A=A8=E5=A3=B3?= =?UTF-8?q?=E4=B8=8B=E8=BD=BD=E9=98=BB=E6=96=AD=E4=BA=8B=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 移动壳阻断 WebView 文件下载时记录宿主诊断日志 补充移动壳下载阻断日志测试 扩展移动壳配置门禁防止下载阻断静默回退 --- apps/mobile-shell/scripts/check-config.mjs | 7 ++++++ apps/mobile-shell/src/shell/ShellApp.test.tsx | 24 +++++++++++++++++++ apps/mobile-shell/src/shell/ShellApp.tsx | 8 ++++++- 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/apps/mobile-shell/scripts/check-config.mjs b/apps/mobile-shell/scripts/check-config.mjs index 302338f2a..4bca38ea6 100644 --- a/apps/mobile-shell/scripts/check-config.mjs +++ b/apps/mobile-shell/scripts/check-config.mjs @@ -1497,6 +1497,8 @@ for (const snippet of [ 'source: window', 'MOBILE_WEBVIEW_BEFORE_CONTENT_SCRIPT', 'shouldBlockMobileWebViewNavigationRequest', + 'logMobileShellDownloadBlocked', + "console.warn('mobile shell blocked WebView file download', event)", 'SafeAreaProvider', 'SafeAreaView', 'MOBILE_SHELL_SAFE_AREA_EDGES', @@ -1515,6 +1517,7 @@ for (const snippet of [ 'webviewDebuggingEnabled={false}', 'injectedJavaScriptBeforeContentLoaded={MOBILE_WEBVIEW_BEFORE_CONTENT_SCRIPT}', 'handleBlockedFileDownload', + 'logMobileShellDownloadBlocked(event)', 'onFileDownload={handleBlockedFileDownload}', 'setSupportMultipleWindows={false}', 'logMobileShellNavigationFailure', @@ -1530,6 +1533,10 @@ if (shellAppSource.includes('catch(() => undefined)')) { throw new Error('mobile shell ShellApp must not hide async navigation failures'); } +if (!shellAppTestSource.includes('blocked WebView file downloads are logged for host diagnostics')) { + throw new Error('mobile shell tests must cover blocked WebView file download diagnostics'); +} + for (const snippet of [ "describe('mobile shell safe area'", "test('protects the WebView from every device edge'", diff --git a/apps/mobile-shell/src/shell/ShellApp.test.tsx b/apps/mobile-shell/src/shell/ShellApp.test.tsx index 0b88f00a1..5596908d4 100644 --- a/apps/mobile-shell/src/shell/ShellApp.test.tsx +++ b/apps/mobile-shell/src/shell/ShellApp.test.tsx @@ -630,6 +630,30 @@ describe('ShellApp HostBridge event injection', () => { warnSpy.mockRestore(); }); + test('blocked WebView file downloads are logged for host diagnostics', async () => { + const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => undefined); + const ShellApp = await importShellApp(); + render(); + + const webViewProps = shellHarness.webViewProps.current as { + onFileDownload?: (event: unknown) => void; + }; + const downloadEvent = { + nativeEvent: { + downloadUrl: 'blob:https://app.genarrative.world/download-id', + }, + }; + + webViewProps.onFileDownload?.(downloadEvent); + + expect(warnSpy).toHaveBeenCalledWith( + 'mobile shell blocked WebView file download', + downloadEvent, + ); + + warnSpy.mockRestore(); + }); + test('initial deep link read failures are logged without replacing the current WebView URL', async () => { const { Linking } = await import('react-native'); const initialUrlError = new Error('initial URL unavailable'); diff --git a/apps/mobile-shell/src/shell/ShellApp.tsx b/apps/mobile-shell/src/shell/ShellApp.tsx index 563cf0cc3..5e0c9fb09 100644 --- a/apps/mobile-shell/src/shell/ShellApp.tsx +++ b/apps/mobile-shell/src/shell/ShellApp.tsx @@ -71,6 +71,10 @@ function logMobileShellNavigationFailure(label: string, error: unknown) { console.warn(`mobile shell navigation failed for ${label}`, error); } +function logMobileShellDownloadBlocked(event: unknown) { + console.warn('mobile shell blocked WebView file download', event); +} + function logMobileShellDeepLinkFailure(label: string, error: unknown) { console.warn(`mobile shell deep link failed for ${label}`, error); } @@ -445,7 +449,9 @@ export default function ShellApp() { ), ); }; - const handleBlockedFileDownload = () => undefined; + const handleBlockedFileDownload = (event: unknown) => { + logMobileShellDownloadBlocked(event); + }; return (