Extensão do Chrome: acessando localStorage no script de conteúdo

157

Eu tenho uma página de opções em que o usuário pode definir determinadas opções e salvá-lo em localStorage: options.html

Agora, eu também tenho um script de conteúdo que precisa obter as opções definidas no options.html página, mas quando tento acessar localStorage a partir do script de conteúdo, ele não retorna o valor da página de opções.

Como faço para que meu script de conteúdo obtenha valores do localStorage, da página de opções ou até da página de segundo plano?

user476214
fonte
1
Veja também: stackoverflow.com/questions/3033829/…
Shay Erlichmen:

Respostas:

233

Atualização 2016:

O Google Chrome lançou a API de armazenamento: http://developer.chrome.com/extensions/storage.html

É muito fácil de usar, como as outras APIs do Chrome, e você pode usá-lo em qualquer contexto de página no 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 usá-lo, defina-o no manifesto:

    "permissions": [
      "storage"
    ],

Existem métodos para "remover", "limpar", "getBytesInUse" e um ouvinte de eventos para escutar o armazenamento alterado "onChanged"

Usando localStorage nativo ( resposta antiga de 2011 )

Os scripts de conteúdo são executados no contexto de páginas da Web, não em páginas de extensão. Portanto, se você estiver acessando o localStorage a partir do seu conteúdo, ele será o armazenamento dessa página da Web, não o armazenamento da página de extensão.

Agora, para permitir que seu script de conteúdo leia seu armazenamento de extensões (onde você os define na página de opções), é necessário usar a passagem de mensagens de extensão .

A primeira coisa que você faz é dizer ao script de conteúdo para enviar uma solicitação à sua extensão para buscar alguns dados, e esses dados podem ser sua extensão 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.
});

Você pode fazer uma API em torno disso para obter dados genéricos do localStorage no script de conteúdo ou, talvez, obter toda a matriz localStorage.

Espero que tenha ajudado a resolver seu problema.

Para ser chique e 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
fonte
1
Obviamente, a solicitação também poderia ser {method: 'getStorage', key: 'status'}, e o ouvinte responderia com os dados correspondentes.
JC Inacio
E se eu quiser que tudo, desde o localStorage, seja transferido para a extensão? Posso escrever sendResponse({data: localStorage});?
Bibhas Debnath
Estou um pouco confuso. Quero que os dados da minha página de opções estejam disponíveis na página background.html. Então, solicito da página Background para o conteúdo do documento? e o contentcript pode enviar de volta os dados do localStorage? Veja isto -> pastebin.com/xtFexFtc .. Estou fazendo certo?
Bibhas Debnath
7
A página de segundo plano e a página de opções pertencem ao mesmo contexto de extensão, portanto, você não precisa de scripts ou mensagens de conteúdo. Você pode ligar localStoragediretamente da página de opções ou usá chrome.extension.getBackgroundPage-la na página de opções.
Mohamed Mansour
1
Isso é estranho. Estou definindo poucas opções na página de opções e criando menus de contexto com base nelas na página de plano de fundo. O problema é que, se eu definir uma variável no localStorage na página de opções, ela não será refletida na página de segundo plano imediatamente (por exemplo, nenhum novo menu de contexto), a menos que eu desative e reative a extensão. Algum motivo para pensar?
Bibhas Debnath
47

Às vezes, pode ser melhor usar a API chrome.storage . É melhor que localStorage porque você pode:

  • armazene informações do seu script de conteúdo sem a necessidade de passar mensagens entre o script e a extensão do conteúdo;
  • armazene seus dados como objetos JavaScript sem serializá-los para JSON ( localStorage armazena apenas cadeias ).

Aqui está um código simples que demonstra o uso do chrome.storage. O script de conteúdo obtém o URL da página visitada e o carimbo de data e hora e o armazena, o popup.js o obtém da área de armazenamento.

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);
    })
})();

"Alterações" aqui é um objeto que contém um valor antigo e novo para uma determinada chave. O argumento "AreaName" refere-se ao nome da área de armazenamento, 'local', 'sync' ou 'managed'.

Lembre-se de declarar a permissão de armazenamento no manifest.json.

manifest.json

...
"permissions": [
    "storage"
 ],
...
Pawel Miech
fonte
O onChangedevento já fornece os dados no changesobjeto. Além disso, preste atenção especial ao namespacedo onChangedevento. Se você armazenar algo usando chrome.storage.local.set, o onChangedevento será acionado, mas a leitura usando chrome.storage.sync.getfaz pouco sentido.
Rob W
Sim, você está certo, editei minha resposta. Obviamente, você pode usar chrome.storage.sync.get em outros cenários, mas aqui é realmente redundante.
Pawel Miech
Em resposta à revisão 5 da sua resposta: changes.visitedPagesserá indefinida se visitedPagesnão tiver sido alterada. Enrole a linha if (changes.visitedPages) { ... }para resolver esse problema.
Rob W
7

Outra opção seria usar a API do chromestorage. Isso permite o armazenamento de dados do usuário com sincronização opcional entre as sessões.

Uma desvantagem é que é assíncrono.

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

Jason
fonte
@ Jason, e as transações de tudo ou nada ?
Pacerier