@@ -47,5 +47,63 @@ export const implantScript = () => {
4747 // #ENDIF
4848 // #IFDEF GECKO
4949 logger . info ( "Register Inject Scripts By Content Script Inline Code" ) ;
50+ // 使用 cross.tabs.executeScript 得到的 window 是 content window
51+ // 此时就必须要使用 Inject Script 的方式才能正常注入脚本
52+ // 然而这种方式就会受到 CSP 的限制, 因此在这里处理 CSP 问题
53+ // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/onHeadersReceived
54+ let nonceId = "" ;
55+ chrome . webRequest . onHeadersReceived . addListener (
56+ res => {
57+ if ( ! res . responseHeaders ) return void 0 ;
58+ if ( res . type !== "main_frame" && res . type !== "sub_frame" ) {
59+ return void 0 ;
60+ }
61+ for ( let i = 0 ; i < res . responseHeaders . length ; i ++ ) {
62+ const responseHeaderName = res . responseHeaders [ i ] . name . toLowerCase ( ) ;
63+ if ( responseHeaderName === "content-security-policy" ) {
64+ const value = res . responseHeaders [ i ] . value || "" ;
65+ const nonce = / ' n o n c e - ( [ - + / = \w ] + ) ' / . exec ( value ) ;
66+ if ( nonce && nonce [ 1 ] ) {
67+ nonceId = nonce [ 1 ] ;
68+ }
69+ }
70+ }
71+ return {
72+ responseHeaders : res . responseHeaders ,
73+ } ;
74+ } ,
75+ { urls : URL_MATCH } ,
76+ [ "responseHeaders" ]
77+ ) ;
78+ // https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/WebExtensions/API/tabs/executeScript
79+ cross . tabs . onUpdated . addListener ( ( _ , changeInfo , tab ) => {
80+ if ( changeInfo . status == "loading" ) {
81+ const tabId = tab && tab . id ;
82+ const tabURL = tab && tab . url ;
83+ if ( ! tabId || ! tabURL ) return void 0 ;
84+ if ( ! URL_MATCH . some ( match => new RegExp ( match ) . test ( tabURL ) ) ) {
85+ return void 0 ;
86+ }
87+ const code = `
88+ if (window["${ process . env . INJECT_FILE } "] && document instanceof XMLDocument === false) {
89+ const script = document.createElementNS("http://www.w3.org/1999/xhtml", "script");
90+ script.setAttribute("type", "text/javascript");
91+ script.innerText = \`;(\${window["${ process . env . INJECT_FILE } "].toString()})();\`;
92+ script.nonce = "${ nonceId } ";
93+ document.documentElement.appendChild(script);
94+ // script.onload = () => script.remove();
95+ // delete window["${ process . env . INJECT_FILE } "];
96+ };` ;
97+ cross . tabs
98+ . executeScript ( tabId , {
99+ allFrames : true ,
100+ code : code ,
101+ runAt : "document_start" ,
102+ } )
103+ . catch ( err => {
104+ if ( __DEV__ ) logger . warning ( "Inject Script" , err ) ;
105+ } ) ;
106+ }
107+ } ) ;
50108 // #ENDIF
51109} ;
0 commit comments