google-chrome-extension content-script

google chrome extension - Opcionalmente inyectar contenido de secuencia de comandos



google-chrome-extension content-script (3)

Dado que la respuesta existente ahora tiene algunos años, la inyección opcional ahora es mucho más fácil y se describe aquí . Dice que para inyectar un nuevo archivo condicionalmente, puede usar el siguiente código:

// The lines I have commented are in the documentation, but the uncommented // lines are the important part //chrome.runtime.onMessage.addListener((message, callback) => { // if (message == “runContentScript”){ chrome.tabs.executeScript({ file: ''contentScript.js'' }); // } //});

Necesitará el permiso de pestaña activa para hacer esto.

Content Script se puede inyectar programática o permanentemente declarando en el archivo de manifiesto de Extensión. La inyección programática requiere permiso del host, que generalmente es otorgado por el navegador o la acción de la página.

En mi caso de uso, quiero inyectar el sitio web de correo gmail, outlook.com y yahoo sin la acción del usuario. Puedo hacerlo declarando que todos ellos se manifiestan, pero al hacerlo requieren todo el acceso a los datos de esas cuentas. Es posible que algunos usuarios deseen otorgar solo outlook.com, pero no gmail. La inyección programática no funciona porque necesito saber cuándo inyectar. El uso de permiso de pestañas también requiere otro permiso.

¿Hay alguna buena manera de inyectar opcionalmente el sitio web?


Lo dividiré en dos partes.

Inyección programática de guiones

Hay una nueva API contentScripts.register() que puede registrar scripts de contenido mediante programación y se cargarán exactamente como content_scripts definidos en el manifiesto:

browser.contentScripts.register({ matches: [''https://your-dynamic-domain.example.com/*''], js: [{file: ''content.js''}] });

Esta API solo está disponible en Firefox, pero hay un polyfill de Chrome que puedes usar.

Adquiriendo nuevos permisos

Al usar chrome.permissions.request puede agregar nuevos dominios en los que puede inyectar secuencias de comandos de contenido. Un ejemplo sería:

// In a content script or options page document.querySelector(''button'').addEventListener(''click'', () => { chrome.permissions.request({ origins: [''https://your-dynamic-domain.example.com/*''] }, granted => { if (granted) { /* Use contentScripts.register */ } }); });

Y tendrá que agregar optional_permissions en su manifest.json para permitir que se soliciten nuevos orígenes:

{ "optional_permissions": [ "http://*/*", "https://*/*" ] }

También escribí algunas herramientas para simplificar aún más esto para usted y para el usuario final, como webext-domain-permission-toggle y webext-dynamic-content-scripts . Registrarán automáticamente sus scripts en los próximos lanzamientos del navegador y permitirán al usuario eliminar los nuevos permisos y scripts.


No puede ejecutar código en un sitio sin los permisos adecuados. Afortunadamente, puede agregar los permisos de host a permisos_opcionales en el archivo de manifiesto para declararlos opcionales y aún permitir que la extensión los use.

En respuesta a un gesto del usuario, puede usar chrome.permission.request para solicitar permisos adicionales. Esta API solo se puede usar en páginas de extensión (página de fondo, página emergente, página de opciones, ...). A partir de Chrome 36.0.1957.0, el gesto de usuario requerido también se transfiere de los scripts de contenido, por lo que si lo desea, puede agregar un detector de eventos de clic desde un script de contenido y usar chrome.runtime.sendMessage para enviar la solicitud a la página de fondo , que a su vez llama a chrome.permissions.request .

Ejecución opcional de código en pestañas

Después de obtener los permisos de host (opcional u obligatorio), debe inyectar de alguna manera el script de contenido (o estilo CSS) en las páginas coincidentes. Hay algunas opciones, en orden de preferencia:

  1. Use la acción chrome.declarativeContent.RequestContentScript para insertar un script de contenido en la página. Lea la documentación si desea aprender a usar esta API.

  2. Use la API webNavigation (por ejemplo, chrome.webNavigation.onCommitted ) para detectar cuándo el usuario ha navegado a la página, luego use chrome.tabs.executeScript para insertar el script de contenido en la pestaña (o chrome.tabs.insertCSS para insertar estilos).

  3. Use la API de tabs ( chrome.tabs.onUpdated ) para detectar que una página podría haber cambiado e inserte un script de contenido en la página usando chrome.tabs.executeScript .

Recomiendo encarecidamente la opción 1, porque fue diseñada específicamente para este caso de uso. Nota: Esta API se agregó en Chrome 38, pero solo funcionó con permisos opcionales desde Chrome 39 . A pesar de la " chrome.declarativeContent.RequestContentScript " en la documentación, la API es realmente compatible con estable. Inicialmente, la idea era esperar una revisión antes de publicar la API en estable , pero esa revisión nunca llegó y ahora esta API ha estado funcionando bien durante casi dos años.

La segunda y tercera opciones son similares. La diferencia entre los dos es que el uso de la API webNavigation agrega una advertencia de permiso adicional ("Lea su historial de navegación"). Para esta advertencia, obtiene una API que puede filtrar eficientemente las navegaciones, por lo que la cantidad de llamadas chrome.tabs.executeScript se puede minimizar.

Si no desea incluir esta advertencia de permiso adicional en su cuadro de diálogo de permiso, puede intentar inyectar ciegamente en cada pestaña. Si su extensión tiene el permiso, la inyección tendrá éxito. De lo contrario, falla. Esto no suena muy eficiente, y no es ... ... en el lado positivo, este método no requiere ningún permiso adicional.

Al usar cualquiera de los dos últimos métodos, su secuencia de comandos de contenido debe estar diseñada de tal manera que pueda manejar múltiples inserciones (por ejemplo, con un protector ). También se admite la inserción en marcos ( allFrames:true ), pero solo si su extensión puede acceder a la URL de la pestaña (o la URL del marco si frameId está configurado).