Extensión de Chrome: acceso a localStorage en script de contenido

157

Tengo una página de opciones donde el usuario puede definir ciertas opciones y la guarda en localStorage: options.html

Ahora, también tengo un script de contenido que necesita obtener las opciones que se definieron en la options.htmlpágina, pero cuando trato de acceder a localStorage desde el script de contenido, no devuelve el valor de la página de opciones.

¿Cómo hago que mi script de contenido obtenga valores de localStorage, de la página de opciones o incluso de la página de fondo?

usuario476214
fuente

Respuestas:

233

Actualización 2016:

Google Chrome lanzó la API de almacenamiento: http://developer.chrome.com/extensions/storage.html

Es bastante fácil de usar como las otras API de Chrome y puede usarlo desde cualquier contexto de página dentro de Chrome.

    // Save it using the Chrome extension storage API.
    chrome.storage.sync.set({'foo': 'hello', 'bar': 'hi'}, function() {
      console.log('Settings saved');
    });

    // Read it using the storage API
    chrome.storage.sync.get(['foo', 'bar'], function(items) {
      message('Settings retrieved', items);
    });

Para usarlo, asegúrese de definirlo en el manifiesto:

    "permissions": [
      "storage"
    ],

Hay métodos para "eliminar", "borrar", "getBytesInUse" y un detector de eventos para escuchar el almacenamiento modificado "onChanged"

Uso de localStorage nativo ( antigua respuesta de 2011 )

Los scripts de contenido se ejecutan en el contexto de páginas web, no páginas de extensión. Por lo tanto, si está accediendo a localStorage desde su script de contenido, será el almacenamiento de esa página web, no el almacenamiento de la página de extensión.

Ahora, para permitir que su secuencia de comandos de contenido lea el almacenamiento de su extensión (donde los configura desde su página de opciones), debe usar la transmisión de mensajes de extensión .

Lo primero que debe hacer es indicarle a su script de contenido que envíe una solicitud a su extensión para obtener algunos datos, y esos datos pueden ser su extensión localStorage:

contentscript.js

chrome.runtime.sendMessage({method: "getStatus"}, function(response) {
  console.log(response.status);
});

background.js

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    if (request.method == "getStatus")
      sendResponse({status: localStorage['status']});
    else
      sendResponse({}); // snub them.
});

Puede hacer una API para obtener datos genéricos de localStorage en su secuencia de comandos de contenido, o tal vez, obtener toda la matriz localStorage.

Espero que eso haya ayudado a resolver tu problema.

Ser elegante y genérico ...

contentscript.js

chrome.runtime.sendMessage({method: "getLocalStorage", key: "status"}, function(response) {
  console.log(response.data);
});

background.js

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    if (request.method == "getLocalStorage")
      sendResponse({data: localStorage[request.key]});
    else
      sendResponse({}); // snub them.
});
Mohamed Mansour
fuente
1
Obviamente, la solicitud también podría ser {método: 'getStorage', clave: 'estado'}, y el oyente respondería con los datos correspondientes.
JC Inacio
¿Qué sucede si deseo que todo desde localStorage se transfiera a la extensión? ¿Puedo escribir sendResponse({data: localStorage});?
Bibhas Debnath
Estoy un poco confundido. Quiero que los datos de mi página de opciones estén disponibles en la página background.html. ¿Entonces solicito desde la página de fondo al contenido? y contentcript puede enviar los datos de localStorage? Vea esto -> pastebin.com/xtFexFtc .. ¿Lo estoy haciendo bien?
Bibhas Debnath
77
La página de fondo y la página de opciones pertenecen al mismo contexto de extensión, por lo que no necesita scripts de contenido o mensajes. Puede llamar localStoragedirectamente desde la página de opciones o usar chrome.extension.getBackgroundPagedesde la página de opciones.
Mohamed Mansour
1
Eso es extraño. Estoy configurando algunas opciones en la página de opciones y creando menús contextuales basados ​​en ellas en la página de fondo. La cuestión es que si configuro una variable en localStorage desde la página de opciones, no se refleja en la página de fondo inmediatamente (es decir, no hay un nuevo menú contextual), a menos que desactive y vuelva a habilitar la extensión. ¿Alguna razón que se te ocurra?
Bibhas Debnath
47

A veces puede ser mejor usar la API chrome.storage . Es mejor que localStorage porque puedes:

  • almacenar información de su secuencia de comandos de contenido sin la necesidad de que el mensaje pase entre la secuencia de comandos de contenido y la extensión;
  • almacenar sus datos como objetos JavaScript sin serializarlos a JSON ( localStorage solo almacena cadenas ).

Aquí hay un código simple que demuestra el uso de chrome.storage. El script de contenido obtiene la url de la página visitada y la marca de tiempo y la almacena, popup.js la obtiene del área de almacenamiento.

content_script.js

(function () {
    var visited = window.location.href;
    var time = +new Date();
    chrome.storage.sync.set({'visitedPages':{pageUrl:visited,time:time}}, function () {
        console.log("Just visited",visited)
    });
})();

popup.js

(function () {
    chrome.storage.onChanged.addListener(function (changes,areaName) {
        console.log("New item in storage",changes.visitedPages.newValue);
    })
})();

"Cambios" aquí es un objeto que contiene valores antiguos y nuevos para una clave determinada. El argumento "AreaName" se refiere al nombre del área de almacenamiento, 'local', 'sincronización' o 'administrado'.

Recuerde declarar el permiso de almacenamiento en manifest.json.

manifest.json

...
"permissions": [
    "storage"
 ],
...
Pawel Miech
fuente
El onChangedevento ya proporciona los datos en el changesobjeto. Además, prestar especial atención a la namespacedel onChangedevento. Si almacena algo usando chrome.storage.local.set, entonces el onChangedevento se dispara, pero leer usando chrome.storage.sync.gettiene poco sentido.
Rob W
Sí, tienes razón, editó mi respuesta. Obviamente, puede usar chrome.storage.sync.get en otros escenarios, pero aquí sí es redundante.
Pawel Miech
En respuesta a la revisión 5 de su respuesta: changes.visitedPagesserá indefinido si visitedPagesno se ha cambiado. Envuelva la línea if (changes.visitedPages) { ... }para resolver este problema.
Rob W
7

Otra opción sería utilizar la API de chromestorage. Esto permite el almacenamiento de datos del usuario con sincronización opcional entre sesiones.

Un inconveniente es que es asíncrono.

https://developer.chrome.com/extensions/storage.html

Jason
fuente
@ Jason, ¿qué pasa con las transacciones de todo o nada ?
Pacerier