tab script matches make info how extensions extension example content chrome javascript google-chrome google-chrome-extension content-script

javascript - matches - Inyectando múltiples scripts a través de executeScript en Google Chrome



make chrome extensions (3)

Dada su respuesta, esperaba que la inyección sincrónica de los scripts causara problemas (es decir, pensé que los scripts podrían cargarse en el orden incorrecto), pero funciona bien para mí.

var scripts = [ ''first.js'', ''middle.js'', ''last.js'' ]; scripts.forEach(function(script) { chrome.tabs.executeScript(null, { file: script }, function(resp) { if (script!==''last.js'') return; // Your callback code here }); });

Esto supone que solo desea una devolución de llamada al final y no necesita los resultados de cada script ejecutado.

Necesito inyectar mediante programación varios archivos de script (seguidos de un fragmento de código) en la página actual desde mi extensión de Google Chrome. El método chrome.tabs.executeScript permite que un solo objeto InjectDetails (que representa un archivo de script o un fragmento de código), así como una función de devolución de llamada, se ejecute después del script. Las respuestas actuales proponen el anidamiento de executeScript llamadas executeScript :

chrome.browserAction.onClicked.addListener(function(tab) { chrome.tabs.executeScript(null, { file: "jquery.js" }, function() { chrome.tabs.executeScript(null, { file: "master.js" }, function() { chrome.tabs.executeScript(null, { file: "helper.js" }, function() { chrome.tabs.executeScript(null, { code: "transformPage();" }) }) }) }) });

Sin embargo, la anidación de devolución de llamada se vuelve difícil de manejar. ¿Hay alguna forma de abstraer esto?


Desde Chrome v32, soporta Promise . Debemos usarlo para hacer el código limpio.

Aquí hay un ejemplo:

new ScriptExecution(tab.id) .executeScripts("js/jquery.js", "js/script.js") .then(s => s.executeCodes(''console.log("executes code...")'')) .then(s => s.injectCss("css/style.css")) .then(s => console.log(''done''));

Fuente ScriptExecution :

(function() { function ScriptExecution(tabId) { this.tabId = tabId; } ScriptExecution.prototype.executeScripts = function(fileArray) { fileArray = Array.prototype.slice.call(arguments); // ES6: Array.from(arguments) return Promise.all(fileArray.map(file => exeScript(this.tabId, file))).then(() => this); // ''this'' will be use at next chain }; ScriptExecution.prototype.executeCodes = function(fileArray) { fileArray = Array.prototype.slice.call(arguments); return Promise.all(fileArray.map(code => exeCodes(this.tabId, code))).then(() => this); }; ScriptExecution.prototype.injectCss = function(fileArray) { fileArray = Array.prototype.slice.call(arguments); return Promise.all(fileArray.map(file => exeCss(this.tabId, file))).then(() => this); }; function promiseTo(fn, tabId, info) { return new Promise(resolve => { fn.call(chrome.tabs, tabId, info, x => resolve()); }); } function exeScript(tabId, path) { let info = { file : path, runAt: ''document_end'' }; return promiseTo(chrome.tabs.executeScript, tabId, info); } function exeCodes(tabId, code) { let info = { code : code, runAt: ''document_end'' }; return promiseTo(chrome.tabs.executeScript, tabId, info); } function exeCss(tabId, path) { let info = { file : path, runAt: ''document_end'' }; return promiseTo(chrome.tabs.insertCSS, tabId, info); } window.ScriptExecution = ScriptExecution; })()

Si desea usar ES5, puede usar el compilador en línea para compilar los códigos anteriores a ES5.

Me bifurcas en GitHub: chrome-script-execution


Esta es mi solución propuesta:

function executeScripts(tabId, injectDetailsArray) { function createCallback(tabId, injectDetails, innerCallback) { return function () { chrome.tabs.executeScript(tabId, injectDetails, innerCallback); }; } var callback = null; for (var i = injectDetailsArray.length - 1; i >= 0; --i) callback = createCallback(tabId, injectDetailsArray[i], callback); if (callback !== null) callback(); // execute outermost function }

Posteriormente, la secuencia de los scripts de InjectDetails se puede especificar como una matriz:

chrome.browserAction.onClicked.addListener(function (tab) { executeScripts(null, [ { file: "jquery.js" }, { file: "master.js" }, { file: "helper.js" }, { code: "transformPage();" } ]) });