Skip to content

Commit 48e9b91

Browse files
committed
feat(web/ipc): restrict penetration depth
1 parent 74e6668 commit 48e9b91

File tree

2 files changed

+43
-12
lines changed

2 files changed

+43
-12
lines changed

packages/web/src/guest/ipc.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ export interface IpcMessage {
3333
* For 'keyboard' type: Contains key mapping data {key, code, keyCode}.
3434
*/
3535
payload: any;
36+
37+
/**
38+
* The penetration depth of the event.
39+
*/
40+
depth: number;
3641
}
3742

3843
/**
@@ -51,6 +56,8 @@ export interface ReceiverOptions {
5156
let _isInitialized = false;
5257
let _allowedOrigins: string[] | '*' = [];
5358

59+
const MAX_PENETRATION_DEPTH = 3;
60+
5461
/**
5562
* Initializes the Iframe IPC receiver.
5663
* Must be executed within the context of the guest iframe.
@@ -88,6 +95,14 @@ export function initIframeReceiver(options: ReceiverOptions): void {
8895
return;
8996
}
9097

98+
// depth validation to prevent excessive iframe nesting
99+
if (!Number.isFinite(data?.depth) || data?.depth >= MAX_PENETRATION_DEPTH) {
100+
console.warn(
101+
`[OmniPad-IPC] Max penetration depth (${MAX_PENETRATION_DEPTH}) reached. Dropping signal.`,
102+
);
103+
return;
104+
}
105+
91106
// Execution: Materialize signals into events
92107
try {
93108
if (data.type === 'focus' && data.action === 'reclaim') {

packages/web/src/singletons/IFrameManager.ts

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { AbstractRect, OmniPad } from '@omnipad/core';
1+
import { AbstractRect } from '@omnipad/core';
22
import { distillRect, generateUID } from '@omnipad/core/utils';
33
import { ElementObserver } from './ElementObserver';
44
import { IpcMessage, OMNIPAD_IPC_SIGNATURE } from '../guest/ipc';
@@ -113,11 +113,11 @@ export class IframeManager {
113113
data.isVisible = visible;
114114

115115
// 如果 Iframe 突然消失,强制重置按键状态防止卡死 / If Iframe hidden, reset keys to prevent sticking
116-
if (!visible) {
117-
if (import.meta.env?.DEV)
118-
console.debug(`[OmniPad-IPC] Iframe ${uid} hidden, sending safety reset.`);
119-
this.forwardKeyboardEvent(iframe, OmniPad.ActionTypes.KEYUP, { all: true });
120-
}
116+
// if (!visible) {
117+
// if (import.meta.env?.DEV)
118+
// console.debug(`[OmniPad-IPC] Iframe ${uid} hidden, sending safety reset.`);
119+
// this.forwardKeyboardEvent(iframe, OmniPad.ActionTypes.KEYUP, { all: true });
120+
// }
121121
});
122122

123123
return data;
@@ -138,6 +138,7 @@ export class IframeManager {
138138
globalX: number,
139139
globalY: number,
140140
opts: any,
141+
currentDepth: number = 0,
141142
) {
142143
if (!iframe.contentWindow || !Number.isFinite(globalX) || !Number.isFinite(globalY)) return;
143144

@@ -155,6 +156,7 @@ export class IframeManager {
155156
type: 'pointer',
156157
action: type,
157158
payload: { x: localX, y: localY, opts },
159+
depth: currentDepth + 1,
158160
} as IpcMessage,
159161
data.origin,
160162
);
@@ -167,7 +169,12 @@ export class IframeManager {
167169
* @param type - Event type (e.g., 'keydown').
168170
* @param payload - Key mapping data.
169171
*/
170-
public forwardKeyboardEvent(iframe: HTMLIFrameElement, type: string, payload: any) {
172+
public forwardKeyboardEvent(
173+
iframe: HTMLIFrameElement,
174+
type: string,
175+
payload: any,
176+
currentDepth: number = 0,
177+
) {
171178
if (!iframe.contentWindow) return;
172179

173180
const data = this.getVerifiedIframeData(iframe);
@@ -179,6 +186,7 @@ export class IframeManager {
179186
type: 'keyboard',
180187
action: type,
181188
payload,
189+
depth: currentDepth + 1,
182190
} as IpcMessage,
183191
data.origin,
184192
);
@@ -191,7 +199,12 @@ export class IframeManager {
191199
* @param globalX - X coordinate in the host viewport.
192200
* @param globalY - Y coordinate in the host viewport.
193201
*/
194-
public forwardFocusReclaim(iframe: HTMLIFrameElement, globalX: number, globalY: number) {
202+
public forwardFocusReclaim(
203+
iframe: HTMLIFrameElement,
204+
globalX: number,
205+
globalY: number,
206+
currentDepth: number = 0,
207+
) {
195208
if (!iframe.contentWindow) return;
196209

197210
const data = this.getVerifiedIframeData(iframe);
@@ -207,6 +220,8 @@ export class IframeManager {
207220
type: 'focus',
208221
action: 'reclaim',
209222
payload: { x: localX, y: localY },
223+
224+
depth: currentDepth + 1,
210225
} as IpcMessage,
211226
data.origin,
212227
);
@@ -238,15 +253,16 @@ export class IframeManager {
238253
console.debug('[OmniPad-IPC] Refreshing all iframe rects due to environment change.');
239254

240255
this.managedIframes.forEach((data, iframe) => {
241-
// 1. 强制重置按键状态防止卡死 / reset keys to prevent sticking
242-
this.forwardKeyboardEvent(iframe, OmniPad.ActionTypes.KEYUP, { all: true });
243-
// 2. 自动执行“墓地清理” / Perform "Graveyard Cleanup" for detached elements
256+
// 强制重置按键状态防止卡死 / reset keys to prevent sticking
257+
// this.forwardKeyboardEvent(iframe, OmniPad.ActionTypes.KEYUP, { all: true });
258+
259+
// 自动执行“墓地清理” / Perform "Graveyard Cleanup" for detached elements
244260
if (!iframe.isConnected) {
245261
this.unmanageIframe(iframe, data.uid);
246262
return;
247263
}
248264

249-
// 3. 强制实时重算 Rect / Force immediate gBCR re-calibration
265+
// 强制实时重算 Rect / Force immediate gBCR re-calibration
250266
data.rect = this.captureRect(iframe);
251267
});
252268
}

0 commit comments

Comments
 (0)