记录移动壳下载阻断事件

移动壳阻断 WebView 文件下载时记录宿主诊断日志

补充移动壳下载阻断日志测试

扩展移动壳配置门禁防止下载阻断静默回退
This commit is contained in:
2026-06-20 22:29:21 +08:00
parent 03849a5879
commit 69ff4af4e6
3 changed files with 38 additions and 1 deletions
@@ -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'",
@@ -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(<ShellApp />);
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');
+7 -1
View File
@@ -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 (
<SafeAreaProvider>