31

Después de instalar o actualizar la extensión de Chrome en la que estoy trabajando, las secuencias de comandos de contenido (especificadas en el manifiesto) no se vuelven a inyectar, por lo que es necesario actualizar la página. hacer que la extensión funcione ¿Hay alguna manera de obligar a los scripts a ser inyectados nuevamente?Reintentar script de contenido de extensión de Chrome después de la actualización o instalar

Creo que podría inyectarlos de nuevo programáticamente quitándolos del manifiesto y luego manejando qué páginas inyectar en la página de fondo, pero esta no es una buena solución.

No quiero actualizar automáticamente las pestañas del usuario porque eso podría perder parte de sus datos. Safari actualiza automáticamente todas las páginas cuando instala o actualiza una extensión.

+0

Parece que Safari 7 (al menos) ya no se actualiza automáticamente la página cuando una extensión está instalada – baseten

Respuesta

20

Hay una manera de permitir una extensión pesada de la escritura de contenido para continuar funcionando después de una actualización, ya hacer que funcione inmediatamente después de la instalación.

Instalar

El método de instalación es para repetir simplemente a través de todas las pestañas en todas las ventanas, e inyectar algunas secuencias de comandos mediante programación en pestañas con URLs que coincidan.

Obviamente, tiene que hacerlo en una secuencia de comandos o background pageevent page declarada en manifest.json:

"background": { 
    "scripts": ["background.js"] 
}, 

background.js:

// Add a `manifest` property to the `chrome` object. 
chrome.manifest = chrome.app.getDetails(); 

var injectIntoTab = function (tab) { 
    // You could iterate through the content scripts here 
    var scripts = chrome.manifest.content_scripts[0].js; 
    var i = 0, s = scripts.length; 
    for(; i < s; i++) { 
     chrome.tabs.executeScript(tab.id, { 
      file: scripts[i] 
     }); 
    } 
} 

// Get all windows 
chrome.windows.getAll({ 
    populate: true 
}, function (windows) { 
    var i = 0, w = windows.length, currentWindow; 
    for(; i < w; i++) { 
     currentWindow = windows[i]; 
     var j = 0, t = currentWindow.tabs.length, currentTab; 
     for(; j < t; j++) { 
      currentTab = currentWindow.tabs[j]; 
      // Skip chrome:// and https:// pages 
      if(! currentTab.url.match(/(chrome|https):\/\//gi)) { 
       injectIntoTab(currentTab); 
      } 
     } 
    } 
}); 

de actualización

método

La actualización se basa sobre el hecho de que los scripts de contenido se dejan inyectar después de que una extensión se deshabilita, desinstala o actualiza.

Cuando se realiza la conexión de puerto, se agrega un controlador onDisconnect. Esto espera un segundo después del evento de desconexión, luego intenta reconectarse. Si falla, se activa otro onDisconnect para que el proceso vuelva a suceder, hasta que se establezca una conexión. No es perfecto, pero funciona.

El script contenido:

var port; 

// Attempt to reconnect 
var reconnectToExtension = function() { 
    // Reset port 
    port = null; 
    // Attempt to reconnect after 1 second 
    setTimeout(connectToExtension, 1000 * 1); 
}; 

// Attempt to connect 
var connectToExtension = function() { 

    // Make the connection 
    port = chrome.runtime.connect({name: "my-port"}); 

    // When extension is upgraded or disabled and renabled, the content scripts 
    // will still be injected, so we have to reconnect them. 
    // We listen for an onDisconnect event, and then wait for a second before 
    // trying to connect again. Becuase chrome.runtime.connect fires an onDisconnect 
    // event if it does not connect, an unsuccessful connection should trigger 
    // another attempt, 1 second later. 
    port.onDisconnect.addListener(reconnectToExtension); 

}; 

// Connect for the first time 
connectToExtension(); 
+6

No estoy seguro de que esto funcione más debido a http://crbug.com/168263 ('No permita que las secuencias de comandos de contenido huérfano se comuniquen con su extensión.). 'chrome.runtime.sendMessage' no. Podría estar equivocado, pero si la gente tiene problemas con ese cambio, probablemente sea por eso. – vaughan

+1

en Chrome 46 necesita usar 'chrome.runtime.getManifest()' en lugar de 'chrome.manifest'. – Lee

+0

Para ejecutar chrome.tabs.executeScript, debe agregar permisos "pestañas", "http: // */*", "https: // */*" a su manifest.json – cnmuc

15

La única forma de forzar la inserción de un script de contenido sin actualizar la página es a través de la inyección de programatic.

Puede obtener todas las pestañas e insertar código en ellas con la API de pestañas de cromo. Por ejemplo, puede almacenar una versión de manifiesto en el almacenamiento local y comprobar siempre si la versión de manifiesto es anterior (en la página de fondo), de ser así, puede obtener todas las pestañas activas e inyectar su código mediante programación, o cualquier otra solución que haga estás seguro de que la extensión está actualizada.

Obtener todas las pestañas usando:
chrome.tabs.query

e inyectar el código en todas las páginas
chrome.tabs.executeScript(tabId, {file: "content_script.js"});

+0

Gracias, pero no quiero utilizar este método - la inyección programática requiere mucho más código y aumenta la complejidad. –

+3

Estoy bastante seguro de que esa es la única forma de hacerlo. Implementé una cosa similar, utilizando tanto la inyección de manifiesto como la inyección de programa para que se inyectaran todas las pestañas que estén abiertas cuando se cargue la secuencia de comandos de fondo, y todas las pestañas nuevas se manejarán mediante la inyección de manifiesto normal. Lo que debe tener cuidado, sin embargo, es cualquier cosa que deje en el DOM o en el contexto de la página, por ej. recarga o actualización, por lo que debe tener una función que deshace todo lo que ha hecho, pero también necesita obtener el nuevo contexto para hablar con el anterior. –

+0

Gracias @ AdamM-W - He estado pensando cosas similares. Idealmente, habría un evento que podría desencadenar un script de 'salida' que desharía todos los cambios DOM. –

-5

no se puede añadir ?ver=2.10 al final de css o js ha realizado una actualización?

"content_scripts": [ { 
     "css": [ "css/cs.css?ver=2.10" ], 
     "js": [ "js/contentScript.js?ver=2.10" ], 
     "matches": [ "http://*/*", "https://*/*" ], 
     "run_at": "document_end" 
    } ], 
Cuestiones relacionadas