收口H5原生分享目标同步边界

H5 原生 App 分享目标同步前复用共享分享 payload 边界

H5 HostBridge 测试覆盖无效分享目标不发送原生请求

原生壳门禁反查 share.setTarget 发送前校验
This commit is contained in:
2026-06-20 04:30:03 +08:00
parent ed05b410c9
commit de77f59387
3 changed files with 56 additions and 0 deletions
+11
View File
@@ -1093,6 +1093,17 @@ function assertH5HostBridgePayloadBoundaries() {
'H5 HostBridge facade must normalize share.open payloads with the shared share boundary',
);
}
if (
!h5HostBridgeSource.includes(
'const normalizedPayload = normalizeHostBridgeShareOpenPayload(message);',
) ||
!h5HostBridgeSource.includes("normalizedPayload.status !== 'valid'") ||
!h5HostBridgeSource.includes("'share.setTarget', {\n target: message,")
) {
throw new Error(
'H5 HostBridge facade must validate native share.setTarget payloads before sending them to native shells',
);
}
if (
!h5HostBridgeSource.includes(
'const normalizedPayload = normalizeHostBridgeExportTextPayload(params);',
@@ -878,6 +878,47 @@ describe('hostBridge', () => {
expect(setHostShareTarget({ type: 'test' })).toBe(false);
});
test('原生 App 宿主分享目标同步前先拒绝无效目标', () => {
const invoke = vi.fn();
window.history.replaceState(
null,
'',
nativeAppPath(['share.setTarget']),
);
window.__TAURI__ = {
core: {
invoke: asTauriInvoke(invoke),
},
};
expect(setHostShareTarget({})).toBe(false);
expect(
setHostShareTarget({
title: '危险作品',
url: 'https://example.com/works/detail?work=PZ-1',
}),
).toBe(false);
expect(invoke).not.toHaveBeenCalled();
expect(
setHostShareTarget({
title: '暖灯猫街',
work: 'PZ-00000001',
}),
).toBe(true);
expect(invoke).toHaveBeenCalledWith('host_bridge_request', {
request: expect.objectContaining({
method: 'share.setTarget',
payload: {
target: {
title: '暖灯猫街',
work: 'PZ-00000001',
},
},
}),
});
});
test('原生 App 宿主通过 HostBridge 处理导航、登录和支付', async () => {
const invoke = vi.fn(async (_command: string, args?: Record<string, unknown>) => {
const request = (args as { request: { id: string; method: string } })
+4
View File
@@ -699,6 +699,10 @@ export function setHostShareTarget(message: unknown) {
if (!canUseNativeHostCapability('share.setTarget')) {
return false;
}
const normalizedPayload = normalizeHostBridgeShareOpenPayload(message);
if (normalizedPayload.status !== 'valid') {
return false;
}
void requestNativeAppHostBridge('share.setTarget', {
target: message,
}).catch(() => {