Browse Source

解决content-script的问题

[email protected] 3 năm trước cách đây
mục cha
commit
8b3737ecd3

+ 86 - 56
apps/background/index.js → apps/background/background.js

@@ -65,29 +65,81 @@ let BgPageInstance = (function () {
     let injectScriptIfTabExists = function (tabId, codeConfig, callback) {
         chrome.tabs.query({currentWindow: true}, (tabs) => {
             tabs.some(tab => {
-                if (tab.id === tabId) {
-                    Settings.getOptions((opts) => {
+                if (tab.id !== tabId) return false;
+                Settings.getOptions((opts) => {
 
-                        codeConfig.code = 'try{' + codeConfig.code + '}catch(e){};';
-                        if (!codeConfig.hasOwnProperty('allFrames')) {
-                            codeConfig.allFrames = String(opts['CONTENT_SCRIPT_ALLOW_ALL_FRAMES']) === 'true';
-                        }
+                    if (!codeConfig.hasOwnProperty('allFrames')) {
+                        codeConfig.allFrames = String(opts['CONTENT_SCRIPT_ALLOW_ALL_FRAMES']) === 'true';
+                    }
 
+                    codeConfig.code = 'try{' + codeConfig.code + ';}catch(e){};';
+                    // 有文件就注入文件
+                    if(codeConfig.files && codeConfig.files.length){
+                        // 注入样式
+                        if(codeConfig.files.join(',').indexOf('.css') > -1) {
+                            chrome.scripting.insertCSS({
+                                target: {tabId, allFrames: codeConfig.allFrames},
+                                files: codeConfig.files
+                            }, function () {
+                                callback && callback.apply(this, arguments);
+                            });
+                        }
+                        // 注入js
+                        else {
+                            chrome.scripting.executeScript({
+                                target: {tabId, allFrames: codeConfig.allFrames},
+                                files: codeConfig.files
+                            }, function () {
+                                chrome.scripting.executeScript({
+                                    target: {tabId, allFrames: codeConfig.allFrames},
+                                    func: function(code){evalCore.getEvalInstance(window)(code)},
+                                    args: [codeConfig.code]
+                                }, function () {
+                                    callback && callback.apply(this, arguments);
+                                });
+                            });
+                        }
+                    }else{
+                        // 没有文件就只注入脚本
                         chrome.scripting.executeScript({
                             target: {tabId, allFrames: codeConfig.allFrames},
-                            func: new Function(`evalCore.getEvalInstance(window)(\`${codeConfig.code}\`)`)
+                            func: function(code){evalCore.getEvalInstance(window)(code)},
+                            args: [codeConfig.code]
                         }, function () {
                             callback && callback.apply(this, arguments);
                         });
-                    });
+                    }
 
-                    return true;
-                }
-                return false;
+                });
+
+                return true;
             });
         });
     };
 
+    // 往当前页面直接注入脚本,不再使用content-script的配置了
+    let _injectContentScripts = function (tabId) {
+
+        // 其他工具注入
+        Awesome.getInstalledTools().then(tools => {
+
+            // 注入样式
+            let cssFiles = Object.keys(tools).filter(tool => tools[tool].contentScriptCss)
+                            .map(tool => `${tool}/content-script.css`);
+            injectScriptIfTabExists(tabId, {files: cssFiles});
+
+            // 注入js
+            let jsTools = Object.keys(tools).filter(tool => tools[tool].contentScriptJs);
+            let jsCodes = [];
+            jsTools.forEach((t, i) => {
+                let func = `window['${t.replace(/-/g, '')}ContentScript']`;
+                jsCodes.push(`(()=>{let func=${func};func&&func();})()`);
+            });
+            let jsFiles = jsTools.map(tool => `${tool}/content-script.js`);
+            injectScriptIfTabExists(tabId, {files: jsFiles,code: jsCodes.join(';')});
+        });
+    };
+
     /**
      * 动态运行工具
      * @param configs
@@ -102,6 +154,7 @@ let BgPageInstance = (function () {
         let tool = configs.tool || configs.page;
         let withContent = configs.withContent;
         let activeTab = null;
+        let query = configs.query;
 
         // 如果是noPage模式,则表名只完成content-script的工作,直接发送命令即可
         if (configs.noPage) {
@@ -162,7 +215,7 @@ let BgPageInstance = (function () {
 
                 if (!isOpened) {
                     chrome.tabs.create({
-                        url: `/${tool}/index.html`,
+                        url: `/${tool}/index.html` + (query ? "?" + query : ''),
                         active: true
                     }, _tabUpdatedCallback(tool, withContent));
                 } else {
@@ -239,46 +292,6 @@ let BgPageInstance = (function () {
         });
     };
 
-    // 往当前页面直接注入脚本,不再使用content-script的配置了
-    let _injectContentScripts = function (tabId) {
-
-        // 创建一个css内容的注入方法
-        // 在内容脚本中,这样调用方法即可,比如:window.${toolName}ContentScriptCssInject();
-        let _createCssInjecter = (tool, cssText) => {
-            return `window['${tool.replace(/-/g, '')}ContentScriptCssInject']=()=>{let style=document.createElement('style');
-                    style.textContent=unescape('${escape(cssText)}');document.head.appendChild(style);}`;
-        };
-
-        // 其他工具注入
-        Awesome.getInstalledTools().then(tools => {
-            let list = Object.keys(tools).filter(tool => tool !== 'json-format' && tools[tool].contentScript);
-
-            // 注入样式
-            let promiseStyles = list.map(tool => Awesome.getContentScript(tool, true));
-            Promise.all(promiseStyles).then(values => {
-                let cssCodes = [];
-                values.forEach((css, i) => {
-                    if (css && css.length) {
-                        cssCodes.push(_createCssInjecter(list[i], css));
-                    }
-                });
-                injectScriptIfTabExists(tabId, {code: cssCodes.join(';')});
-            });
-
-            // 注入脚本
-            let promiseScripts = list.map(tool => Awesome.getContentScript(tool));
-            Promise.all(promiseScripts).then(values => {
-                let jsCodes = [];
-                values.forEach((js, i) => {
-                    let func = `window['${list[i].replace(/-/g, '')}ContentScript']`;
-                    jsCodes.push(`(()=>{ ${js} ; let func=${func};func&&func();})()`);
-                });
-
-                injectScriptIfTabExists(tabId, {code: jsCodes.join(';')});
-            });
-        });
-    };
-
     /**
      * 接收来自content_scripts发来的消息
      */
@@ -314,7 +327,6 @@ let BgPageInstance = (function () {
             }
             // 任何事件,都可以通过这个钩子来完成
             else if (request.type === MSG_TYPE.DYNAMIC_ANY_THING) {
-                request.func && request.func(request.params, callback);
                 switch(request.thing){
                     case 'save-options':
                         //管理右键菜单
@@ -324,6 +336,26 @@ let BgPageInstance = (function () {
                             autoClose: 2000
                         });
                         break;
+                    case 'code-beautify':
+                        if (['javascript', 'css'].includes(request.params.fileType)) {
+                            Awesome.StorageMgr.get('JS_CSS_PAGE_BEAUTIFY').then(val => {
+                                if(val !== '0') {
+                                    let code = `window._codebutifydetect_('${request.params.fileType}')`;
+                                    injectScriptIfTabExists(request.params.tabId, { code });
+                                }
+                            });
+                        }
+                        break;
+                    case 'close-beautify':
+                        Awesome.StorageMgr.set('JS_CSS_PAGE_BEAUTIFY',0);
+                        break;
+                    case 'qr-decode':
+                        chrome.DynamicToolRunner({
+                            withContent: request.params.uri,
+                            tool: MSG_TYPE.QR_CODE,
+                            query: `mode=decode`
+                        });
+                        break;
                 }
                 callback && callback(request.params);
             } else {
@@ -341,9 +373,7 @@ let BgPageInstance = (function () {
                 && /^(http(s)?|file):\/\//.test(tab.url)
                 && blacklist.every(reg => !reg.test(tab.url))) {
 
-                injectScriptIfTabExists(tabId, {
-                    code: `window.__FH_TAB_ID__=${tabId};`
-                });
+                injectScriptIfTabExists(tabId, { code: `window.__FH_TAB_ID__=${tabId};` });
 
                 _injectContentScripts(tabId);
             }

+ 10 - 2
apps/background/tools.js

@@ -2,7 +2,7 @@ let toolMap = {
     'json-format': {
         name: 'JSON美化工具',
         tips: '页面自动检测并格式化、手动格式化、乱码解码、排序、BigInt、编辑、下载、皮肤定制等',
-        contentScript: true,
+        contentScriptJs: true,
         contentScriptCss: true,
         offloadForbid: true,
         menuConfig: [{
@@ -22,7 +22,7 @@ let toolMap = {
     'qr-code': {
         name: '二维码/解码',
         tips: '支持自定义颜色和icon的二维码生成器,并且支持多种模式的二维码解码,包括截图后粘贴解码',
-        contentScript: true,
+        contentScriptJs: true,
         menuConfig: [{
             icon: '▣',
             text: '二维码生成器',
@@ -62,6 +62,8 @@ let toolMap = {
     'code-beautify': {
         name: '代码美化工具',
         tips: '支持多语言的代码美化,包括 Javascript、CSS、HTML、XML、SQL,且会陆续支持更多格式',
+        contentScriptJs: true,
+        contentScriptCss: true,
         menuConfig: [{
             icon: '✡',
             text: '代码美化工具',
@@ -151,6 +153,7 @@ let toolMap = {
     'page-monkey': {
         name: '网页油猴工具',
         tips: '自行配置页面匹配规则、编写Hack脚本,实现网页Hack,如页面自动刷新、自动抢票等',
+        contentScriptJs: true,
         menuConfig: [{
             icon: '♀',
             text: 'FH开发者工具'
@@ -159,6 +162,7 @@ let toolMap = {
     'screenshot': {
         name: '网页截屏工具',
         tips: '可对任意网页进行截屏,支持可视区域截屏、全网页滚动截屏,最终结果可预览后再保存',
+        contentScriptJs: true,
         menuConfig: [{
             icon: '✂',
             text: 'FH开发者工具'
@@ -167,6 +171,7 @@ let toolMap = {
     'color-picker': {
         name: '页面取色工具',
         tips: '可直接在网页上针对任意元素进行色值采集,将光标移动到需要取色的位置,单击确定即可',
+        contentScriptJs: true,
         menuConfig: [{
             icon: '✑',
             text: 'FH开发者工具'
@@ -183,6 +188,8 @@ let toolMap = {
     'grid-ruler': {
         name: '网页栅格标尺',
         tips: 'Web开发用,横竖两把尺子,以10px为单位,用以检测&校准当前网页的栅格对齐率',
+        contentScriptJs: true,
+        contentScriptCss: true,
         menuConfig: [{
             icon: 'Ⅲ',
             text: 'FH开发者工具'
@@ -191,6 +198,7 @@ let toolMap = {
     'page-timing': {
         name: '网页性能检测',
         tips: '检测网页加载性能,包括握手、响应、渲染等各阶段耗时,同时提供Response Headers以便分析',
+        contentScriptJs: true,
         menuConfig: [{
             icon: 'Σ',
             text: 'FH开发者工具'

+ 54 - 74
apps/code-beautify/content-script.js

@@ -1,17 +1,23 @@
-let __importScript = (filename) => {
-    fetch(filename).then(resp => resp.text()).then(jsText => {
-        if(window.evalCore && window.evalCore.getEvalInstance){
-            return window.evalCore.getEvalInstance(window)(jsText);
-        }
-    });
-};
-
-__importScript('beautify.js');
-__importScript('beautify-css.js');
 
 let highlightWebWorker = () => {
+    let __importScript = (filename) => {
+        let url = filename;
+
+        if (location.protocol === 'chrome-extension:' || typeof chrome !='undefined' && chrome.runtime && chrome.runtime.getURL) {
+            url = chrome.runtime.getURL('code-beautify/' + filename);
+        }
+        fetch(url).then(resp => resp.text()).then(jsText => {
+            if(window.evalCore && window.evalCore.getEvalInstance){
+                return window.evalCore.getEvalInstance(window)(jsText);
+            }
+            let el = document.createElement('script');
+            el.textContent = jsText;
+            document.head.appendChild(el);
+        });
+    };
 
-    __importScript('../static/vendor/highlight/highlight.js');
+    let site = 'chrome-extension://mnaedlmagdcfmejjndjhffalddfofeim';
+    __importScript(site + '/static/vendor/highlight/highlight.js');
 
     self.onmessage = (event) => {
         const result = self.hljs.highlightAuto(event.data);
@@ -20,9 +26,29 @@ let highlightWebWorker = () => {
 };
 
 window.codebeautifyContentScript = (() => {
+    let __importScript = (filename) => {
+        let url = filename;
+
+        if (location.protocol === 'chrome-extension:' || chrome.runtime && chrome.runtime.getURL) {
+            url = chrome.runtime.getURL('code-beautify/' + filename);
+        }
+        fetch(url).then(resp => resp.text()).then(jsText => {
+            if(window.evalCore && window.evalCore.getEvalInstance){
+                return window.evalCore.getEvalInstance(window)(jsText);
+            }
+            let el = document.createElement('script');
+            el.textContent = jsText;
+            document.head.appendChild(el);
+        });
+    };
+
+    __importScript('beautify.js');
+    __importScript('beautify-css.js');
 
     let formattedCodes = '';
 
+    // **************************************************************
+
     /**
      * 代码美化
      */
@@ -79,33 +105,6 @@ window.codebeautifyContentScript = (() => {
         }
         let source = document.getElementsByTagName('pre')[0].textContent;
 
-        if (window.codebeautifyContentScriptCssInject) {
-            window.codebeautifyContentScriptCssInject();
-        } else {
-            // 注入css and html fragment
-            chrome.runtime.sendMessage({
-                type: 'fh-dynamic-any-thing',
-                func: ((params, callback) => {
-
-                    let injectFn = (cssText) => {
-                        chrome.tabs.insertCSS({
-                            code: cssText,
-                            runAt: 'document_end'
-                        });
-                    };
-
-                    let cssText = Awesome.getContentScript('code-beautify', true);
-                    if (typeof cssText === 'string') {
-                        injectFn(cssText);
-                    } else if (cssText instanceof Promise) {
-                        cssText.then(css => injectFn(css));
-                    }
-                    callback && callback();
-                    return true;
-                }).toString()
-            });
-        }
-
         $(document.body).addClass('show-tipsbar');
 
         let tipsBar = $('<div id="fehelper_tips">' +
@@ -132,9 +131,7 @@ window.codebeautifyContentScript = (() => {
             if (confirm('一旦彻底关闭,不可恢复,请确认?')) {
                 chrome.runtime.sendMessage({
                     type: 'fh-dynamic-any-thing',
-                    func: ((params, callback) => {
-                        localStorage.setItem('JS_CSS_PAGE_BEAUTIFY', 0);
-                    }).toString()
+                    thing: 'close-beautify'
                 }, () => {
                     alert('已关闭,如果要恢复,请在FeHelper「设置页」重新安装「代码美化工具」!');
                 });
@@ -182,41 +179,24 @@ window.codebeautifyContentScript = (() => {
     };
 
     return function () {
+        let ext = location.pathname.substring(location.pathname.lastIndexOf(".") + 1).toLowerCase();
+        let fileType = ({'js': 'javascript', 'css': 'css'})[ext];
+        let contentType = document.contentType.toLowerCase();
+
+        if (!fileType) {
+            if (/\/javascript$/.test(contentType)) {
+                fileType = 'javascript';
+            } else if (/\/css$/.test(contentType)) {
+                fileType = 'css';
+            }
+        } else if (contentType === 'text/html') {
+            fileType = undefined;
+        }
+
         chrome.runtime.sendMessage({
             type: 'fh-dynamic-any-thing',
-            params: {
-                tabId: window.__FH_TAB_ID__ || null
-            },
-            func: ((params, callback) => {
-                chrome.tabs.executeScript(params.tabId, {
-                    code: '(' + (() => {
-                        let ext = location.pathname.substring(location.pathname.lastIndexOf(".") + 1).toLowerCase();
-                        let fileType = ({'js': 'javascript', 'css': 'css'})[ext];
-                        let contentType = document.contentType.toLowerCase();
-
-                        if (!fileType) {
-                            if (/\/javascript$/.test(contentType)) {
-                                fileType = 'javascript';
-                            } else if (/\/css$/.test(contentType)) {
-                                fileType = 'css';
-                            }
-                        } else if (contentType === 'text/html') {
-                            fileType = undefined;
-                        }
-                        return fileType;
-                    }).toString() + ')()'
-                }, function (fileType) {
-                    if (['javascript', 'css'].includes(fileType[0])) {
-                        if (localStorage.getItem('JS_CSS_PAGE_BEAUTIFY') !== '0') {
-                            chrome.tabs.executeScript(params.tabId, {
-                                code: `window._codebutifydetect_('${fileType[0]}')`
-                            });
-                        }
-                    }
-                });
-                callback && callback();
-                return true;
-            }).toString()
+            thing: 'code-beautify',
+            params: { fileType, tabId: window.__FH_TAB_ID__ || null }
         });
     };
 

+ 23 - 24
apps/json-format/content-script.js

@@ -2,34 +2,33 @@
  * Json Page Automatic Format Via FeHelper
  * @author zhaoxianlie
  */
+window.JsonAutoFormat = (() => {
 
-// 留100ms时间给静态文件加载,当然,这个代码只是留给未开发过程中用的
-let pleaseLetJsLoaded = 0;
-let __importScript = (filename) => {
-    pleaseLetJsLoaded = 100;
-    let url = filename;
-
-    if (location.protocol === 'chrome-extension:' || chrome.runtime && chrome.runtime.getURL) {
-        url = chrome.runtime.getURL(filename);
-    }
-    fetch(url).then(resp => resp.text()).then(jsText => {
-        if(window.evalCore && window.evalCore.getEvalInstance){
-            return window.evalCore.getEvalInstance(window)(jsText);
-        }
-        let el = document.createElement('script');
-        el.textContent = jsText;
-        document.head.appendChild(el);
-    });
-};
+    // 留100ms时间给静态文件加载,当然,这个代码只是留给未开发过程中用的
+    let pleaseLetJsLoaded = 0;
+    let __importScript = (filename) => {
+        pleaseLetJsLoaded = 100;
+        let url = filename;
 
-__importScript('json-bigint.js');
-__importScript('format-lib.js');
-__importScript('json-abc.js');
-__importScript('json-decode.js');
+        if (location.protocol === 'chrome-extension:' || chrome.runtime && chrome.runtime.getURL) {
+            url = chrome.runtime.getURL('json-format/' + filename);
+        }
+        fetch(url).then(resp => resp.text()).then(jsText => {
+            if(window.evalCore && window.evalCore.getEvalInstance){
+                return window.evalCore.getEvalInstance(window)(jsText);
+            }
+            let el = document.createElement('script');
+            el.textContent = jsText;
+            document.head.appendChild(el);
+        });
+    };
 
-window.JsonAutoFormat = (() => {
+    __importScript('json-bigint.js');
+    __importScript('format-lib.js');
+    __importScript('json-abc.js');
+    __importScript('json-decode.js');
 
-    "use strict";
+    // **************************************************************
 
     const JSON_SORT_TYPE_KEY = 'json_sort_type_key';
     const JSON_AUTO_DECODE = 'json_auto_decode';

+ 6 - 18
apps/manifest.json

@@ -15,7 +15,7 @@
     "default_popup": "popup/index.html"
   },
   "background": {
-    "service_worker": "background/index.js",
+    "service_worker": "background/background.js",
     "type": "module"
   },
   "options_ui": {
@@ -57,7 +57,10 @@
             "json-format/json-bigint.js",
             "json-format/json-decode.js",
             "static/vendor/jquery/jquery-3.3.1.min.js",
-            "static/vendor/evalCore.min.js"
+            "static/vendor/evalCore.min.js",
+
+            "code-beautify/beautify.js",
+            "code-beautify/beautify-css.js"
         ],
         "matches": ["<all_urls>"]
       }
@@ -74,22 +77,7 @@
       ],
       "js": [
         "static/vendor/jquery/jquery-3.3.1.min.js",
-        "static/vendor/evalCore.min.js",
-
-        "json-format/content-script.js",
-        "screenshot/content-script.js",
-        "grid-ruler/content-script.js",
-        "code-beautify/content-script.js",
-        "hello-world/content-script.js",
-        "qr-code/content-script.js",
-        "page-timing/content-script.js",
-        "color-picker/content-script.js",
-        "page-monkey/content-script.js"
-      ],
-      "css": [
-        "json-format/content-script.css",
-        "grid-ruler/content-script.css",
-        "code-beautify/content-script.css"
+        "static/vendor/evalCore.min.js"
       ],
       "run_at": "document_start",
       "all_frames": true

+ 3 - 10
apps/qr-code/content-script.js

@@ -31,20 +31,13 @@ window.qrcodeContentScript = function () {
 
             chrome.runtime.sendMessage({
                 type: 'fh-dynamic-any-thing',
+                thing: 'qr-decode',
                 params: {
                     uri: dataUrl || imgUrl
-                },
-                func: ((params, csCallback) => {
-                    chrome.DynamicToolRunner({
-                        withContent: params.uri,
-                        query: `tool=qr-code&mode=decode`
-                    });
-                    csCallback && csCallback();
-                    return true;
-                }).toString()
+                }
             });
         });
     };
 
     return {decode}
-};
+};