Accediendo a `ventana`/DOM/HTML de la página web desde la extensión

Resuelto Steven asked hace 13 años • 2 respuestas

Estoy escribiendo una extensión de Chrome e intentando superponerla <div>a la página web actual tan pronto como se hace clic en un botón en el archivo popup.html.

Cuando accedo al document.body.insertBeforemétodo desde popup.html, se superpone <div>en la ventana emergente, en lugar de en la página web actual.

¿Tengo que utilizar mensajes entre background.html y popup.html para poder acceder al DOM de la página web? Me gustaría hacer todo en popup.html y usar jQuery también, si es posible.

Steven avatar Dec 26 '10 07:12 Steven
Aceptado

Problema: las páginas de extensión (ventana emergente, opciones, página de fondo en MV2, etc.) están separadas de la página web y tienen su propio DOM, document, windowy una chrome-extension://URL.

  • Tenga en cuenta que el trabajador del servicio no tiene ningún DOM/documento/ventana.
  • Para inspeccionar cada contexto de la extensión, utilice sus propias herramientas de desarrollo .

Solución: utilizar un script de contenido para acceder a la página web o interactuar con su contenido.

  • Los scripts de contenido se ejecutan en la página web, no en la extensión.
  • Los scripts de contenido están aislados de forma predeterminada; consulte cómo ejecutar código en el contexto de la página (también conocido como mundo PRINCIPAL).
  • No cargue sus scripts de contenido en la página de extensión.

Método 1. Declarativo

manifiesto.json:

"content_scripts": [{
  "matches": ["*://*.example.com/*"],
  "js": ["contentScript.js"]
}],

Se ejecutará una vez cuando se cargue la página. Después de que eso suceda, utilice la mensajería .

¡Advertencia! No puede enviar elementos DOM, Map, Set, ArrayBuffer, clases, funciones, etc. Solo puede enviar objetos y tipos simples compatibles con JSON, por lo que deberá extraer manualmente los datos requeridos y pasarlos como una matriz u objeto simple.

Método 2. Programático

  • Manifiesto V3 :

    Utilice chrome.scripting.executeScript en el script de extensión (como la ventana emergente) para inyectar un script/función de contenido en una pestaña a pedido.

    El resultado de este método es la última expresión del script de contenido, por lo que puede usarse para extraer datos. Los datos deben ser compatibles con JSON; consulte la advertencia anterior.

    Requerido permissionsen manifest.json:

    • "scripting"- obligatorio;
    • "activeTab"- escenario ideal, adecuado para una respuesta a una acción del usuario (normalmente un clic en el icono de extensión en la barra de herramientas). No muestra ninguna advertencia de permiso al instalar la extensión.

    Si el escenario ideal es imposible, agregue los sitios permitidos host_permissionsen manifest.json:

    • "*://*.example.com/"además de cualquier otro sitio que desee.

    • "<all_urls>"o "*://*/"estos colocarán su extensión en una cola de revisión súper lenta en Chrome Web Store debido a los amplios permisos de host.

  • Diferencias de ManifestV2 con lo anterior:

    • Utilice chrome.tabs.executeScript .
    • Especifique sitios en permissions.
Mohamed Mansour avatar Dec 26 '2010 02:12 Mohamed Mansour

Algunos ejemplos del script emergente de extensión que utilizan inyección programática para agregar ese div.

ManifiestoV3

No olvide agregar los permisos en manifest.json; consulte la otra respuesta para obtener más información.

  • llamada sencilla:

    (async () => {
      const [tab] = await chrome.tabs.query({active: true, currentWindow: true});
      const [{result}] = await chrome.scripting.executeScript({
        target: {tabId: tab.id},
        func: () => document.querySelector('foo')?.textContent,
      });
      document.body.textContent = result;
    })();
    
  • Llamada sencilla 2:

    (async () => {
      const [tab] = await chrome.tabs.query({active: true, currentWindow: true});
      await chrome.scripting.executeScript({
        target: {tabId: tab.id},
        func: inContent1,
      });
    })();
    
    // executeScript runs this code inside the tab
    function inContent1() {
      const el = document.createElement('div');
      el.style.cssText = 'position:fixed; top:0; left:0; right:0; background:red';
      el.textContent = 'DIV';
      document.body.appendChild(el);
    }
    

    Nota: en Chrome 91 o versiones anteriores func:debería ser function:.

  • Llamar con parámetros y recibir un resultado.

    Requiere Chrome 92 tal como se implementó args.

    Ejemplo 1:

    res = await chrome.scripting.executeScript({
      target: {tabId: tab.id},
      func: (a, b) => { return [window[a], window[b]]; },
      args: ['foo', 'bar'],
    });
    

    Ejemplo 2:

    (async () => {
      const [tab] = await chrome.tabs.query({active: true, currentWindow: true});
      let res;
      try {
        res = await chrome.scripting.executeScript({
          target: {tabId: tab.id},
          func: inContent2,
          args: [{ foo: 'bar' }], // arguments must be JSON-serializable
        });
      } catch (e) {
        console.warn(e.message || e);
        return;
      }
      // res[0] contains results for the main page of the tab 
      document.body.textContent = JSON.stringify(res[0].result);
    })();
    
    // executeScript runs this code inside the tab
    function inContent2(params) {
      const el = document.createElement('div');
      el.style.cssText = 'position:fixed; top:0; left:0; right:0; background:red';
      el.textContent = params.foo;
      document.body.appendChild(el);
      return {
        success: true,
        html: document.body.innerHTML,
      };
    }
    

ManifiestoV2

  • llamada sencilla:

    // uses inContent1 from ManifestV3 example above
    chrome.tabs.executeScript({ code: `(${ inContent1 })()` });
    
  • Llamar con parámetros y recibir un resultado:

    // uses inContent2 from ManifestV3 example above
    chrome.tabs.executeScript({
      code: `(${ inContent2 })(${ JSON.stringify({ foo: 'bar' }) })`
    }, ([result] = []) => {
      if (!chrome.runtime.lastError) {
        console.log(result); // shown in devtools of the popup window
      }
    });
    

    Este ejemplo utiliza la conversión automática del inContentcódigo de la función a cadena; el beneficio aquí es que el IDE puede aplicar resaltado de sintaxis y linting. El inconveniente obvio es que el navegador pierde tiempo analizando el código, pero normalmente tarda menos de 1 milisegundo, por lo que es insignificante.

wOxxOm avatar Apr 23 '2021 09:04 wOxxOm