37 lines
1.7 KiB
TypeScript
37 lines
1.7 KiB
TypeScript
// MAIN world 桥 —— 跑在页面主世界,读取页面 JS 变量(isolated world 读不到)。
|
|
// 协议(对齐竞品 inject.js 模式):
|
|
// isolated → MAIN: {type:'sc-bridge-req', requestId, keys: [...]} keys 含 '*' 时返回诊断键列表
|
|
// MAIN → isolated: {type:'sc-bridge-res', requestId, payload: {key: value}}
|
|
// MAIN 侧零业务逻辑:只读白名单键、JSON 序列化过滤后回传,不注入任何页面行为。
|
|
export default defineContentScript({
|
|
matches: [
|
|
'https://*.ozon.ru/*', 'https://*.ozon.kz/*', 'https://*.ozon.by/*',
|
|
'https://detail.1688.com/*',
|
|
'https://item.taobao.com/*', 'https://detail.tmall.com/*',
|
|
],
|
|
world: 'MAIN',
|
|
main() {
|
|
window.addEventListener('message', (ev: MessageEvent) => {
|
|
if (ev.source !== window) return;
|
|
const d = ev.data as { type?: string; requestId?: string; keys?: string[] } | null;
|
|
if (!d || d.type !== 'sc-bridge-req' || !d.requestId || !Array.isArray(d.keys)) return;
|
|
|
|
const payload: Record<string, unknown> = {};
|
|
if (d.keys.includes('*')) {
|
|
// 诊断模式:列出页面上可能有数据的全局键
|
|
payload['__sc_window_keys__'] = Object.keys(window).filter(k =>
|
|
/^(__|_)?[A-Za-z]/.test(k) && /(context|rawData|ICE|sku|item|g_config|DATA|state)/i.test(k)
|
|
);
|
|
}
|
|
for (const k of d.keys) {
|
|
if (k === '*') continue;
|
|
try {
|
|
const v = (window as unknown as Record<string, unknown>)[k];
|
|
if (v !== undefined) payload[k] = JSON.parse(JSON.stringify(v)); // 过滤函数/循环引用
|
|
} catch { /* 不可序列化的跳过 */ }
|
|
}
|
|
window.postMessage({ type: 'sc-bridge-res', requestId: d.requestId, payload }, '*');
|
|
});
|
|
},
|
|
});
|