@@ -223,14 +223,50 @@ message.on(
223223 return new Promise ( ( resolve ) => {
224224 const escapePolicy = ( script ) => {
225225 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+ }
231254 }
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+ }
234270 }
235271 return script ;
236272 } ;
@@ -267,10 +303,61 @@ message.on(
267303 chrome . debugger . attach ( { tabId : target . tabId } , '1.3' , resolve ) ;
268304 } ) ;
269305
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+ }
272357
273- const jsCode = await callbackFn ( ) ;
358+ const jsCode = jsCodeResult . result . value ;
359+
360+ // 执行生成的JavaScript代码
274361 const execResult = await chrome . debugger . sendCommand (
275362 { tabId : target . tabId } ,
276363 'Runtime.evaluate' ,
@@ -279,7 +366,7 @@ message.on(
279366 userGesture : true ,
280367 awaitPromise : true ,
281368 returnByValue : true ,
282- ...( options || { } ) ,
369+ ...options ,
283370 }
284371 ) ;
285372
@@ -288,24 +375,33 @@ message.on(
288375 }
289376
290377 if ( ! execResult || ! execResult . result ) {
378+ console . error ( '无法执行代码,结果为空' ) ;
291379 throw new Error ( 'Unable execute code' ) ;
292380 }
293381
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+ ) ;
296393 }
297394
298395 return {
299396 isBlocked : true ,
300397 value : execResult . result . value || null ,
301398 } ;
302399 }
303- // todo: 这里没有实现callback的调用逻辑
304400
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 } ;
309405 }
310406 }
311407) ;
@@ -352,7 +448,7 @@ function automaFetchClient(id, { type, resource }) {
352448 return;
353449 }
354450
355- const eventName = ' __automa-fetch-response-' + id +__ ;
451+ const eventName = \` __automa-fetch-response-\${id}__\` ;
356452 const eventListener = ({ detail }) => {
357453 if (detail.id !== id) return;
358454
@@ -367,7 +463,7 @@ function automaFetchClient(id, { type, resource }) {
367463
368464 window.addEventListener(eventName, eventListener);
369465 window.dispatchEvent(
370- new CustomEvent(' __automa-fetch__' , {
466+ new CustomEvent(\` __automa-fetch__\` , {
371467 detail: {
372468 id,
373469 type,
@@ -378,9 +474,8 @@ function automaFetchClient(id, { type, resource }) {
378474 });
379475}
380476
381-
382477function automaFetch(type, resource) {
383- return automaFetchClient.toString() ('${ varName } ', { type, resource });
478+ return automaFetchClient('${ varName } ', { type, resource });
384479}
385480 ` ;
386481
@@ -548,21 +643,65 @@ message.on(
548643) ;
549644
550645message . 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+ }
566705} ) ;
567706
568707automa ( 'background' , message ) ;
0 commit comments