锁定移动图片权限请求失败边界

移动文件桥接把相册权限请求失败转为结构化 host_error

移动文件桥接把相机权限请求失败转为结构化 host_error

移动文件单测覆盖权限请求失败不启动原生选择器

移动壳配置检查反查权限请求失败边界
This commit is contained in:
2026-06-20 11:58:28 +08:00
parent 306df618bd
commit d8ef351c59
3 changed files with 43 additions and 2 deletions
@@ -303,6 +303,26 @@ describe('mobile HostBridge file actions', () => {
expect(imageLibraryMock).not.toHaveBeenCalled();
});
test('rejects image import before picker launch when library permission request fails', async () => {
libraryPermissionMock.mockRejectedValueOnce(new Error('native permission failed'));
await expect(importImageFile()).rejects.toMatchObject({
code: 'host_error',
message: 'photo library permission unavailable',
});
expect(imageLibraryMock).not.toHaveBeenCalled();
});
test('rejects image capture before camera launch when camera permission request fails', async () => {
cameraPermissionMock.mockRejectedValueOnce(new Error('native permission failed'));
await expect(captureImageFile()).rejects.toMatchObject({
code: 'host_error',
message: 'camera permission unavailable',
});
expect(cameraMock).not.toHaveBeenCalled();
});
test('imports audio and exports binary files through controlled payloads', async () => {
fileBase64Data.set('file:///picked/voice.mp3', MP3_BASE64);
fileSizes.set('file:///picked/voice.mp3', Buffer.byteLength('ID3\x04\x00\x00\x00\x00\x00\x10'));
+18 -2
View File
@@ -270,7 +270,15 @@ export async function exportMobileHostBridgeImageFile(
}
export async function importImageFile(): Promise<FileImportImageResult> {
const permission = await ImagePicker.requestMediaLibraryPermissionsAsync();
let permission: ImagePicker.MediaLibraryPermissionResponse;
try {
permission = await ImagePicker.requestMediaLibraryPermissionsAsync();
} catch {
throw {
code: 'host_error',
message: 'photo library permission unavailable',
} satisfies HostBridgeError;
}
if (permission.status !== ImagePicker.PermissionStatus.GRANTED) {
throw {
code: 'host_error',
@@ -301,7 +309,15 @@ export async function importMobileHostBridgeImageFile(
}
export async function captureImageFile(): Promise<FileImportImageResult> {
const permission = await ImagePicker.requestCameraPermissionsAsync();
let permission: ImagePicker.CameraPermissionResponse;
try {
permission = await ImagePicker.requestCameraPermissionsAsync();
} catch {
throw {
code: 'host_error',
message: 'camera permission unavailable',
} satisfies HostBridgeError;
}
if (permission.status !== ImagePicker.PermissionStatus.GRANTED) {
throw {
code: 'host_error',