Comunique los datos del popup al script de contenido inyectado mediante popup con executeScript ()

Tengo un área de texto y un botón en mi ventana emergente de extensión de Chrome. Quiero que los usuarios ingresen el texto deseado en el área de texto. Luego, una vez que hagan clic en el botón, inyectará un script de contenido para cambiar el texto de los campos en la página actual que tienen

popup.js :

 function injectTheScript3() { chrome.tabs.query({active: true, currentWindow: true}, function(tabs) { // query the active tab, which will be only one tab //and inject the script in it chrome.tabs.executeScript(tabs[0].id, {file: "content_script3.js"}); }); } document.getElementById('clickactivity3').addEventListener('click', injectTheScript3); 

content_script3 :

 //returns a node list which is good var objSelectComments = document.querySelectorAll('.comments'); //desired user input how? function setCommentsValue(objSelectComments,){ //This will be for loop to iterate among all the text fields on the page, and apply // the text to each instance. for (var i=0; i<objSelectComments.length; i++) { objSelectComments[i]= //user's desired text } 

Hay tres formas generales de hacer esto:

  1. Use chrome.storage.local ( MDN ) para pasar los datos (configurados antes de inyectar su script).
  2. Inyecte el código antes de su secuencia de comandos que establece una variable con los datos (consulte el análisis detallado de posibles problemas de seguridad).
  3. Use el paso de mensajes ( MDN ) para pasar los datos después de que se haya inyectado su script.

Use chrome.storage.local (establecido antes de ejecutar su script)

El uso de este método mantiene el paradigma de ejecución que está utilizando para inyectar un script que realiza una función y luego sale. Tampoco tiene el problema de seguridad potencial de utilizar un valor dynamic para comstackr el código de ejecución, que se realiza en la segunda opción a continuación.

De su secuencia de comandos emergente:

  1. Almacene los datos usando chrome.storage.local.set() ( MDN )
  2. En la callback para chrome.storage.local.set() , llame a tabs.executeScript() ( MDN )
 var updateTextTo = document.getElementById('comments').value; chrome.storage.local.set({ updateTextTo: updateTextTo }, function () { chrome.tabs.executeScript({ file: "content_script3.js" }); }); 

De tu script de contenido:

  1. Lea los datos de chrome.storage.local.get() ( MDN )
  2. Haz los cambios en el DOM
  3. Invalidar los datos en storage.local (por ejemplo, eliminar la clave: chrome.storage.local.remove() ( MDN )).
 chrome.storage.local.get('updateTextTo', function (items) { assignTextToTextareas(items.updateTextTo); chrome.storage.local.remove('updateTextTo'); }); function assignTextToTextareas(newText){ if (typeof newText === 'string') { Array.from(document.querySelectorAll('textarea.comments')).forEach(el => { el.value = newText; }); } } 

Ver: Notas 1 y 2.

Inyectar código antes de su secuencia de comandos para establecer una variable

Antes de ejecutar su secuencia de comandos, puede insertar un código que establezca una variable en el contexto del script de contenido que su secuencia de comandos primaria pueda usar:

Problema de seguridad:
Los siguientes usos "'" + JSON.stringify().replace(/\\/g,'\\\\').replace(/'/g,"\\'") + "'" para codificar los datos en texto que será JSON apropiado cuando se interpreta como código, antes de ponerlo en la cadena de code . Los métodos .replace() son necesarios para A) hacer que el texto se interprete correctamente como una cadena cuando se usa como código, y B) citar cualquier ' que exista en los datos. A continuación, utiliza JSON.parse() para devolver los datos a una cadena en su secuencia de comandos de contenido. Si bien esta encoding no es estrictamente necesaria, es una buena idea ya que no conoce el contenido del valor que va a enviar al script de contenido. Este valor podría ser fácilmente algo que corrompería el código que está inyectando (es decir, el usuario puede estar usando ' y / o " en el texto que ingresaron). Si no logra, de alguna manera, escapar del valor, existe una seguridad agujero que podría dar lugar a la ejecución de código arbitrario.

De su secuencia de comandos emergente:

  1. Inyecte un código simple que establece una variable para contener los datos.
  2. En la callback para chrome.tabs.executeScript() ( MDN ), llame a tabs.executeScript() para inyectar su secuencia de comandos (Nota: tabs.executeScript() ejecutará las secuencias de comandos en el orden en que llame tabs.executeScript() , como siempre que tengan el mismo valor para runAt . Por lo tanto, no es estrictamente necesario esperar la devolución de la llamada del code pequeño).
 var updateTextTo = document.getElementById('comments').value; chrome.tabs.executeScript({ code: "var newText = JSON.parse('" + JSON.stringify(updateTextTo).replace(/\\/g,'\\\\').replace(/'/g,"\\'") + "';" }, function () { chrome.tabs.executeScript({ file: "content_script3.js" }); }); 

De tu script de contenido:

  1. Realice los cambios en el DOM utilizando los datos almacenados en la variable
 if (typeof newText === 'string') { Array.from(document.querySelectorAll('textarea.comments')).forEach(el => { el.value = newText; }); } 

Ver: Notas 1, 2 y 3.

Usar el paso de mensajes ( MDN ) (enviar datos después de inyectar el script de contenido)

Esto requiere que el código de secuencia de comandos de contenido instale un agente de escucha para un mensaje enviado por el elemento emergente, o quizás el script de fondo (si la interacción con la interfaz de usuario hace que se cierre la ventana emergente). Es un poco más complejo.

De su secuencia de comandos emergente:

  1. Determine la pestaña activa usando tabs.query() ( MDN ).
  2. Llamar a tabs.executeScript() ( MDN )
  3. En la callback para tabs.executeScript() , use tabs.sendMessage() ( MDN ) (que requiere conocer la tabId ), para enviar los datos como un mensaje.
 var updateTextTo = document.getElementById('comments').value; chrome.tabs.query({active: true, currentWindow: true}, function(tabs) { chrome.tabs.executeScript(tabs[0].id, { file: "content_script3.js" }, function(){ chrome.tabs.sendMessage(tabs[0].id,{ updateTextTo: updateTextTo }); }); }); 

De tu script de contenido:

  1. Agregue un oyente usando chrome.runtime.onMessage.addListener() ( MDN )
  2. Salga de su código principal, dejando al oyente activo. Podría devolver un indicador de éxito, si lo desea.
  3. Al recibir un mensaje con los datos:
    1. Haz los cambios en el DOM
    2. Elimine su escucha de runtime.onMessage

# 3.2 es opcional. Podrías mantener tu código activo esperando otro mensaje, pero eso cambiaría el paradigma que estás usando a uno donde cargues tu código y permanece residente esperando mensajes para iniciar acciones.

 chrome.runtime.onMessage.addListener(assignTextToTextareas); function assignTextToTextareas(message){ newText = message.updateTextTo; if (typeof newText === 'string') { Array.from(document.querySelectorAll('textarea.comments')).forEach(el => { el.value = newText; }); } chrome.runtime.onMessage.removeListener(assignTextToTextareas); //optional } 

Ver: Notas 1 y 2.


Nota 1: Usar Array.from() está bien si no lo hace muchas veces y está usando una versión de navegador que lo tiene (Chrome> = versión 45, Firefox> = 32). En Chrome y Firefox, Array.from() es lento en comparación con otros métodos para obtener una matriz de una NodeList . Para una conversión más rápida y más compatible a una matriz, puede usar el código asArray() en esta respuesta . La segunda versión de asArray() provista en esa respuesta también es más robusta.

Nota 2: Si está dispuesto a limitar su código a la versión de Chrome> = 51 o a la versión de Firefox> = 50 , Chrome tiene un método forEach() para NodeLists desde v51. Por lo tanto, no es necesario convertir a una matriz. Obviamente, no necesita convertir a una matriz si utiliza un tipo diferente de bucle.

Nota 3: Si bien anteriormente he utilizado este método (inyectando un script con el valor de la variable) en mi propio código, se me recordó que debería haberlo incluido aquí al leer esta respuesta .

    Intereting Posts