Rozszerzenie Chrome: dostęp do localStorage w skrypcie zawartości

157

Mam stronę opcji, na której użytkownik może definiować pewne opcje i zapisuje ją w localStorage: options.html

Teraz mam także skrypt zawartości, który musi pobrać opcje zdefiniowane na options.htmlstronie, ale kiedy próbuję uzyskać dostęp do localStorage ze skryptu zawartości, nie zwraca wartości ze strony opcji.

Jak sprawić, by mój skrypt zawartości pobierał wartości z localStorage, ze strony opcji, a nawet strony w tle?

user476214
źródło

Odpowiedzi:

233

Aktualizacja 2016:

Google Chrome udostępnił interfejs API do przechowywania danych: http://developer.chrome.com/extensions/storage.html

Jest dość łatwy w użyciu, podobnie jak inne interfejsy API Chrome i możesz go używać z dowolnego kontekstu strony w 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);
    });

Aby z niego skorzystać, upewnij się, że zdefiniowałeś go w manifeście:

    "permissions": [
      "storage"
    ],

Istnieją metody „usuwania”, „czyszczenia”, „getBytesInUse” i nasłuchiwania zdarzeń do nasłuchiwania zmienionej pamięci „onChanged”

Korzystanie z natywnego localStorage ( stara odpowiedź z 2011 r. )

Skrypty zawartości działają w kontekście stron internetowych, a nie stron rozszerzeń. Dlatego jeśli uzyskujesz dostęp do localStorage ze swojego skryptu contentcript, będzie to pamięć z tej strony internetowej, a nie pamięć strony rozszerzenia.

Teraz, aby pozwolić skryptowi zawartości na odczytanie pamięci rozszerzeń (gdzie ustawiasz je na stronie opcji), musisz użyć przekazywania wiadomości rozszerzenia .

Pierwszą rzeczą, którą musisz zrobić, jest poinformowanie skryptu zawartości, aby wysłał żądanie do twojego rozszerzenia w celu pobrania niektórych danych, a te dane mogą być twoim rozszerzeniem localStorage:

contentcript.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.
});

Możesz zastosować interfejs API, aby uzyskać ogólne dane localStorage do skryptu zawartości lub być może pobrać całą tablicę localStorage.

Mam nadzieję, że pomogło to rozwiązać Twój problem.

Aby być fantazyjnym i ogólnym ...

contentcript.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
źródło
1
Oczywiście żądanie mogłoby również mieć postać {metoda: 'getStorage', klucz: 'status'}, a słuchacz odpowiedziałby odpowiednimi danymi.
JC Inacio
A jeśli chcę, aby wszystko, od localStorage, zostało przeniesione do rozszerzenia? Mogę napisać sendResponse({data: localStorage});?
Bibhas Debnath,
Jestem nieco zdezorientowany. Chcę, aby dane z mojej strony opcji były dostępne na stronie background.html. Więc wysyłam żądanie ze strony w tle do skryptu zawartości? i contentcript może odesłać dane localStorage? Zobacz to -> pastebin.com/xtFexFtc .. Czy robię to dobrze?
Bibhas Debnath
7
Strona w tle i strona opcji należą do tego samego kontekstu rozszerzenia, więc nie potrzebujesz skryptów zawartości ani wiadomości. Możesz zadzwonić localStoragebezpośrednio ze strony opcji lub użyć chrome.extension.getBackgroundPageze strony opcji.
Mohamed Mansour
1
To jest dziwne. Ustawiam kilka opcji na stronie opcji i na ich podstawie tworzę menu kontekstowe na stronie w tle. Chodzi o to, że jeśli ustawię zmienną w localStorage ze strony opcji, nie zostanie ona natychmiast odzwierciedlona na stronie w tle (tj. Brak nowego menu kontekstowego), chyba że wyłączę i ponownie włączę rozszerzenie. Masz jakiś powód?
Bibhas Debnath
47

Czasami lepiej jest użyć interfejsu API chrome.storage . Lepiej niż localStorage, ponieważ możesz:

  • przechowywać informacje z twojego skryptu treści bez potrzeby przekazywania wiadomości między skryptem treści a rozszerzeniem;
  • przechowuj dane jako obiekty JavaScript bez serializacji ich do formatu JSON ( localStorage przechowuje tylko ciągi ).

Oto prosty kod demonstrujący użycie chrome.storage. Skrypt treści pobiera adres URL odwiedzanej strony i sygnaturę czasową i przechowuje je, a popup.js pobiera z magazynu.

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

„Zmiany” to obiekt zawierający starą i nową wartość dla danego klucza. Argument „AreaName” odnosi się do nazwy obszaru pamięci, „lokalny”, „synchronizacja” lub „zarządzany”.

Pamiętaj, aby zadeklarować zezwolenie na przechowywanie w pliku manifest.json.

manifest.json

...
"permissions": [
    "storage"
 ],
...
Paweł Miech
źródło
onChangedWydarzenie już dostarcza danych w changesobiekcie. Ponadto zwróć szczególną uwagę namespacena onChangedwydarzenie. Jeśli przechowujesz coś przy użyciu chrome.storage.local.set, onChangedzdarzenie jest wyzwalane, ale czytanie za pomocą chrome.storage.sync.getnie ma sensu.
Rob W
Tak, masz rację, zredagowałeś moją odpowiedź. Oczywiście możesz użyć chrome.storage.sync.get w innych scenariuszach, ale tutaj jest to rzeczywiście zbędne.
Paweł Miech
W odpowiedzi na poprawkę 5 Twojej odpowiedzi: changes.visitedPagesbędzie niezdefiniowana, jeśli visitedPagesnie została zmieniona. Zawiń linię, if (changes.visitedPages) { ... }aby rozwiązać ten problem.
Rob W
7

Inną opcją byłoby użycie interfejsu API chromestorage. Pozwala to na przechowywanie danych użytkownika z opcjonalną synchronizacją między sesjami.

Jedną wadą jest to, że jest asynchroniczny.

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

Jason
źródło
@Jason, A co z transakcjami typu wszystko albo nic ?
Pacerier,