Расширение Chrome: доступ к localStorage в скрипте содержимого

157

У меня есть страница параметров, где пользователь может определить определенные параметры и сохраняет их в localStorage: options.html

Теперь у меня также есть скрипт контента, который должен получить параметры, которые были определены на options.htmlстранице, но когда я пытаюсь получить доступ к localStorage из скрипта контента, он не возвращает значение со страницы настроек.

Как сделать так, чтобы мой скрипт содержимого получал значения из localStorage, страницы параметров или даже фоновой страницы?

user476214
источник
1
Связанный: stackoverflow.com/questions/3033829/…
Шей Эрличмен
Связанный: stackoverflow.com/questions/4224039/…
Джейсон
Связанный: stackoverflow.com/questions/39768005/…
super1ha1

Ответы:

233

Обновление 2016:

Google Chrome выпустил API хранилища: http://developer.chrome.com/extensions/storage.html

Его довольно легко использовать, как и другие API Chrome, и вы можете использовать его из любого контекста страницы в 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);
    });

Чтобы использовать его, убедитесь, что вы определили его в манифесте:

    "permissions": [
      "storage"
    ],

Существуют методы для «удаления», «очистки», «getBytesInUse» и прослушивателя событий для прослушивания измененного хранилища «onChanged»

Использование родного localStorage ( старый ответ от 2011 года )

Сценарии содержимого выполняются в контексте веб-страниц, а не страниц расширения. Поэтому, если вы обращаетесь к localStorage из вашего содержимого, это будет хранилище с этой веб-страницы, а не хранилище страниц расширения.

Теперь, чтобы ваш контент-скрипт мог читать ваше хранилище расширений (где вы установили их со страницы настроек), вам нужно использовать передачу сообщений расширений .

Первое, что вы должны сделать - это попросить ваш контент-скрипт отправить запрос вашему расширению для получения некоторых данных, и эти данные могут быть вашим расширением 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.
});

Вы можете использовать API для этого, чтобы получить общие данные localStorage для вашего скрипта контента или, возможно, получить весь массив localStorage.

Я надеюсь, что это помогло решить вашу проблему.

Быть модным и родовым ...

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.
});
Мохамед Мансур
источник
1
Очевидно, что запрос также может быть {method: 'getStorage', key: 'status'}, и слушатель будет отвечать соответствующими данными.
JC Inacio
Что если я хочу, чтобы все из localStorage было перенесено в расширение? Я могу написать sendResponse({data: localStorage});?
Бибхас Дебнатх
Я немного смущен. Я хочу, чтобы данные из моей страницы параметров были доступны на странице background.html. Итак, я делаю запрос с фоновой страницы к содержимому? а contentcript может отправлять обратно данные localStorage? Смотрите это -> pastebin.com/xtFexFtc .. Я делаю это правильно?
Бибхас Дебнат
7
Фоновая страница и страница параметров принадлежат одному и тому же контексту расширения, поэтому вам не нужны скрипты содержимого или обмен сообщениями. Вы можете позвонить localStorageпрямо со страницы параметров или использовать chrome.extension.getBackgroundPageсо страницы параметров.
Мохамед Мансур
1
Это странно. Я устанавливаю несколько параметров на странице параметров и создаю контекстные меню на их основе на странице фона. Дело в том, что если я устанавливаю переменную в localStorage со страницы параметров, она не отражается сразу на фоновой странице (т.е. без нового контекстного меню), если только я не отключаю и не включаю расширение. Любая причина, по которой вы можете думать?
Бибхас Дебнатх
47

Иногда может быть лучше использовать chrome.storage API. Это лучше, чем localStorage, потому что вы можете:

  • хранить информацию из вашего скрипта контента без необходимости передачи сообщений между скриптом контента и расширением;
  • хранить ваши данные как объекты JavaScript без их сериализации в JSON ( localStorage хранит только строки ).

Вот простой код, демонстрирующий использование chrome.storage. Сценарий содержимого получает URL посещенной страницы и отметку времени и сохраняет ее, popup.js получает ее из области хранения.

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

«Изменения» - это объект, который содержит старое и новое значение для данного ключа. Аргумент «AreaName» относится к имени области хранения: «локальный», «синхронный» или «управляемый».

Не забудьте объявить разрешение на хранение в manifest.json.

manifest.json

...
"permissions": [
    "storage"
 ],
...
Павел Мех
источник
onChangedСобытие уже предоставляет данные в changesобъекте. Кроме того, обратите особое внимание на namespaceчасть onChangedмероприятия. Если вы что-то храните с помощью chrome.storage.local.set, то onChangedсобытие инициируется, но чтение с использованием chrome.storage.sync.getимеет мало смысла.
Роб Вт
Да ты прав, отредактировал мой ответ. Очевидно, что вы можете использовать chrome.storage.sync.get в других сценариях, но здесь это действительно избыточно.
Павел Мех
В ответ на 5-ю редакцию вашего ответа: changes.visitedPagesбудет неопределенным, если visitedPagesне был изменен. Заверните строку, if (changes.visitedPages) { ... }чтобы решить эту проблему.
Роб W
7

Другим вариантом будет использование API-интерфейса chromestorage. Это позволяет хранить пользовательские данные с возможностью синхронизации между сеансами.

Недостатком является то, что он асинхронный.

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

Джейсон
источник
@Jason, а как насчет транзакций " все или ничего" ?
Pacerier