@@ -223,14 +223,50 @@ message.on(
223
223
return new Promise ( ( resolve ) => {
224
224
const escapePolicy = ( script ) => {
225
225
if ( window ?. trustedTypes ?. createPolicy ) {
226
- const escapeElPolicy = window . trustedTypes . createPolicy (
227
- 'forceInner' ,
228
- {
229
- createHTML : ( to_escape ) => to_escape ,
230
- createScript : ( to_escape ) => to_escape ,
226
+ try {
227
+ // 尝试使用可能在CSP白名单中的名称
228
+ const policyNames = [
229
+ 'default' ,
230
+ 'dompurify' ,
231
+ 'jSecure' ,
232
+ 'forceInner' ,
233
+ ] ;
234
+ let escapeElPolicy = null ;
235
+
236
+ // 尝试创建策略,如果一个名称失败,尝试下一个
237
+ for ( const policyName of policyNames ) {
238
+ try {
239
+ escapeElPolicy = window . trustedTypes . createPolicy (
240
+ policyName ,
241
+ {
242
+ createHTML : ( to_escape ) => to_escape ,
243
+ createScript : ( to_escape ) => to_escape ,
244
+ }
245
+ ) ;
246
+ // 如果成功创建,跳出循环
247
+ break ;
248
+ } catch ( e ) {
249
+ // 该名称失败,继续尝试下一个
250
+ console . debug (
251
+ `Policy name ${ policyName } failed, trying next one`
252
+ ) ;
253
+ }
231
254
}
232
- ) ;
233
- return escapeElPolicy . createScript ( script ) ;
255
+
256
+ // 如果成功创建了策略,使用它
257
+ if ( escapeElPolicy ) {
258
+ return escapeElPolicy . createScript ( script ) ;
259
+ }
260
+ // 如果所有策略名称都失败,返回原始脚本
261
+ console . debug (
262
+ 'All trusted policy creation attempts failed, falling back to raw script'
263
+ ) ;
264
+ return script ;
265
+ } catch ( e ) {
266
+ // 捕获任何其他错误并降级
267
+ console . debug ( 'Error creating trusted policy:' , e ) ;
268
+ return script ;
269
+ }
234
270
}
235
271
return script ;
236
272
} ;
@@ -267,10 +303,61 @@ message.on(
267
303
chrome . debugger . attach ( { tabId : target . tabId } , '1.3' , resolve ) ;
268
304
} ) ;
269
305
270
- // eslint-disable-next-line no-new-func
271
- const callbackFn = new Function ( `return ${ callback } ` ) ( ) ;
306
+ // 直接执行回调函数字符串
307
+ // 避免使用new Function构造函数,因为它会被CSP阻止
308
+ const callbackFn = callback ;
309
+
310
+ // 检查回调函数字符串是否有效
311
+ if ( ! callbackFn ) {
312
+ throw new Error ( 'Callback function is missing or invalid' ) ;
313
+ }
314
+
315
+ // 创建一个包装函数,直接执行回调函数
316
+ const wrappedCallback = `
317
+ (function() {
318
+ return (${ callbackFn } )();
319
+ })()
320
+ ` ;
321
+
322
+ // 执行回调函数以获取JavaScript代码
323
+ const jsCodeResult = await chrome . debugger . sendCommand (
324
+ { tabId : target . tabId } ,
325
+ 'Runtime.evaluate' ,
326
+ {
327
+ expression : wrappedCallback ,
328
+ userGesture : true ,
329
+ returnByValue : true ,
330
+ ...options ,
331
+ }
332
+ ) ;
333
+
334
+ if ( ! jsCodeResult || ! jsCodeResult . result ) {
335
+ console . error ( '无法获取JavaScript代码,结果为空' ) ;
336
+ throw new Error ( 'Unable to get JavaScript code' ) ;
337
+ }
338
+
339
+ if (
340
+ jsCodeResult . result . subtype === 'error' ||
341
+ jsCodeResult . exceptionDetails
342
+ ) {
343
+ console . error (
344
+ '执行回调函数时出错:' ,
345
+ jsCodeResult . result . description || jsCodeResult . exceptionDetails
346
+ ) ;
347
+ throw new Error (
348
+ jsCodeResult . result . description || 'Error executing callback'
349
+ ) ;
350
+ }
351
+
352
+ // 确保我们获取到的是字符串类型的JavaScript代码
353
+ if ( typeof jsCodeResult . result . value !== 'string' ) {
354
+ console . error ( '回调函数返回的不是JavaScript代码字符串' ) ;
355
+ throw new Error ( 'Callback did not return JavaScript code string' ) ;
356
+ }
272
357
273
- const jsCode = await callbackFn ( ) ;
358
+ const jsCode = jsCodeResult . result . value ;
359
+
360
+ // 执行生成的JavaScript代码
274
361
const execResult = await chrome . debugger . sendCommand (
275
362
{ tabId : target . tabId } ,
276
363
'Runtime.evaluate' ,
@@ -279,7 +366,7 @@ message.on(
279
366
userGesture : true ,
280
367
awaitPromise : true ,
281
368
returnByValue : true ,
282
- ...( options || { } ) ,
369
+ ...options ,
283
370
}
284
371
) ;
285
372
@@ -288,24 +375,33 @@ message.on(
288
375
}
289
376
290
377
if ( ! execResult || ! execResult . result ) {
378
+ console . error ( '无法执行代码,结果为空' ) ;
291
379
throw new Error ( 'Unable execute code' ) ;
292
380
}
293
381
294
- if ( execResult . result . subtype === 'error' ) {
295
- throw new Error ( execResult . result . description ) ;
382
+ if (
383
+ execResult . result . subtype === 'error' ||
384
+ execResult . exceptionDetails
385
+ ) {
386
+ console . error (
387
+ '执行JavaScript代码时出错:' ,
388
+ execResult . result . description || execResult . exceptionDetails
389
+ ) ;
390
+ throw new Error (
391
+ execResult . result . description || 'Error executing JavaScript code'
392
+ ) ;
296
393
}
297
394
298
395
return {
299
396
isBlocked : true ,
300
397
value : execResult . result . value || null ,
301
398
} ;
302
399
}
303
- // todo: 这里没有实现callback的调用逻辑
304
400
305
- return { isBlocked : false , value : null } ;
306
- } catch ( err ) {
307
- console . error ( 'CSP check error:' , err ) ;
308
- return { isBlocked : false , value : null } ;
401
+ return { isBlocked : false } ;
402
+ } catch ( error ) {
403
+ console . error ( error ) ;
404
+ return { isBlocked : false , error : error . message } ;
309
405
}
310
406
}
311
407
) ;
@@ -352,7 +448,7 @@ function automaFetchClient(id, { type, resource }) {
352
448
return;
353
449
}
354
450
355
- const eventName = ' __automa-fetch-response-' + id +__ ;
451
+ const eventName = \` __automa-fetch-response-\${id}__\` ;
356
452
const eventListener = ({ detail }) => {
357
453
if (detail.id !== id) return;
358
454
@@ -367,7 +463,7 @@ function automaFetchClient(id, { type, resource }) {
367
463
368
464
window.addEventListener(eventName, eventListener);
369
465
window.dispatchEvent(
370
- new CustomEvent(' __automa-fetch__' , {
466
+ new CustomEvent(\` __automa-fetch__\` , {
371
467
detail: {
372
468
id,
373
469
type,
@@ -378,9 +474,8 @@ function automaFetchClient(id, { type, resource }) {
378
474
});
379
475
}
380
476
381
-
382
477
function automaFetch(type, resource) {
383
- return automaFetchClient.toString() ('${ varName } ', { type, resource });
478
+ return automaFetchClient('${ varName } ', { type, resource });
384
479
}
385
480
` ;
386
481
@@ -548,21 +643,65 @@ message.on(
548
643
) ;
549
644
550
645
message . on ( 'script:execute-callback' , async ( { target, callback } ) => {
551
- await browser . scripting . executeScript ( {
552
- target,
553
- func : ( $callbackFn ) => {
554
- const script = document . createElement ( 'script' ) ;
555
- script . textContent = `
556
- (() => {
557
- ${ $callbackFn }
558
- })()
559
- ` ;
560
- document . body . appendChild ( script ) ;
561
- } ,
562
- world : 'MAIN' ,
563
- args : [ callback ] ,
564
- } ) ;
565
- return true ;
646
+ try {
647
+ // 首先尝试使用scripting API执行脚本
648
+ const result = await browser . scripting . executeScript ( {
649
+ target,
650
+ func : ( $callbackFn ) => {
651
+ try {
652
+ const script = document . createElement ( 'script' ) ;
653
+ script . textContent = `
654
+ (() => {
655
+ ${ $callbackFn }
656
+ })()
657
+ ` ;
658
+ document . body . appendChild ( script ) ;
659
+ return { success : true } ;
660
+ } catch ( error ) {
661
+ console . error ( '执行脚本时出错:' , error ) ;
662
+ return { success : false , error : error . message } ;
663
+ }
664
+ } ,
665
+ world : 'MAIN' ,
666
+ args : [ callback ] ,
667
+ } ) ;
668
+
669
+ // 检查执行结果
670
+ const executionResult = result [ 0 ] ?. result ;
671
+ if ( executionResult && executionResult . success ) {
672
+ return true ;
673
+ }
674
+
675
+ // 如果常规方法失败,尝试使用debugger API
676
+ await new Promise ( ( resolve ) => {
677
+ chrome . debugger . attach ( { tabId : target . tabId } , '1.3' , resolve ) ;
678
+ } ) ;
679
+
680
+ // 使用debugger API执行脚本
681
+ const execResult = await chrome . debugger . sendCommand (
682
+ { tabId : target . tabId } ,
683
+ 'Runtime.evaluate' ,
684
+ {
685
+ expression : `(() => { ${ callback } })()` ,
686
+ userGesture : true ,
687
+ awaitPromise : false ,
688
+ returnByValue : true ,
689
+ }
690
+ ) ;
691
+
692
+ // 执行完成后分离debugger
693
+ await chrome . debugger . detach ( { tabId : target . tabId } ) ;
694
+
695
+ if ( ! execResult || ! execResult . result ) {
696
+ console . error ( '使用debugger API执行脚本失败' ) ;
697
+ return false ;
698
+ }
699
+
700
+ return true ;
701
+ } catch ( error ) {
702
+ console . error ( '执行script:execute-callback时出错:' , error ) ;
703
+ return false ;
704
+ }
566
705
} ) ;
567
706
568
707
automa ( 'background' , message ) ;
0 commit comments