Chrome extension: accessing localStorage in content script
Asked Answered
D

4

191

I have an options page where the user can define certain options and it saves it in localStorage: options.html

Now, I also have a content script that needs to get the options that were defined in the options.html page, but when I try to access localStorage from the content script, it doesn't return the value from the options page.

How do I make my content script get values from localStorage, from the options page or even the background page?

Disuse answered 14/10, 2010 at 19:55 Comment(3)
Related: #3034329Pozzuoli
Related: #4224539Beberg
Related: #39768505Ut
N
275

Update 2016:

Google Chrome released the storage API: https://developer.chrome.com/docs/extensions/reference/storage/

It is pretty easy to use like the other Chrome APIs and you can use it from any page context within 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);
    });

To use it, make sure you define it in the manifest:

    "permissions": [
      "storage"
    ],

There are methods to "remove", "clear", "getBytesInUse", and an event listener to listen for changed storage "onChanged"

Using native localStorage (old reply from 2011)

Content scripts run in the context of webpages, not extension pages. Therefore, if you're accessing localStorage from your contentscript, it will be the storage from that webpage, not the extension page storage.

Now, to let your content script to read your extension storage (where you set them from your options page), you need to use extension message passing.

The first thing you do is tell your content script to send a request to your extension to fetch some data, and that data can be your extension 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.
});

You can do an API around that to get generic localStorage data to your content script, or perhaps, get the whole localStorage array.

I hope that helped solve your problem.

To be fancy and generic ...

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.
});
Nanci answered 14/10, 2010 at 22:11 Comment(12)
Obviously, request could also be {method:'getStorage', key: 'status'}, and the listener would respond with the corresponding data.Sorehead
What if I want everything from the localStorage to be transferred to the extension? Can I write sendResponse({data: localStorage}); ?Oberhausen
I'm a bit confused. I want data from my options page to be available at background.html page.. So I make a request from Background page to the contentscript? and contentscript can send back the localStorage data? See this -> pastebin.com/xtFexFtc .. Am I doing it right?Oberhausen
The background page and options page belong to the same extension context, so you don't need content scripts or messaging. You can call localStorage directly from the options page or use chrome.extension.getBackgroundPage from the options page.Nanci
Thats strange. I'm setting few options in options page and creating context menus based on them in background page. The thing is, if I set a variable in localStorage from options page, it doesnt get reflected to the background page immediately(i.e. No new contextmenu), unless I disable and re-enable the extension. Any reason you can think of?Oberhausen
@MohamedMansour I'm not sure if this is still valid 2 years later, but should background.html be options.html instead? I'm still having trouble with this.Azevedo
I believe Chrome changed the extension design so it should be background.js, not options because options page only lives when you activate it and disposes once you close it.Nanci
Thanks @OrangeTux, woah, it has been two years since I wrote this answer :) I just updated it to the new API, thanksNanci
@MohamedMansour : do you have any recommendation for this question #39768505Ut
Use your method ContentScript can read localStorage of background page now !Pastiche
@MohamedMansour, What about all-or-nothing transactions?Stieglitz
For some reason, I still had to use the old answer from 2011. But I am getting localStorage is not defined . Anyone facing the same issue ?Rico
T
54

Sometimes it may be better to use chrome.storage API. It's better then localStorage because you can:

  • store information from your content script without the need for message passing between content script and extension;
  • store your data as JavaScript objects without serializing them to JSON (localStorage only stores strings).

Here's a simple code demonstrating the use of chrome.storage. Content script gets the url of visited page and timestamp and stores it, popup.js gets it from storage area.

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

"Changes" here is an object that contains old and new value for a given key. "AreaName" argument refers to name of storage area, either 'local', 'sync' or 'managed'.

Remember to declare storage permission in manifest.json.

manifest.json

...
"permissions": [
    "storage"
 ],
...
Theola answered 11/1, 2014 at 18:38 Comment(4)
The onChanged event already provides the data in the changes object. Further, pay special attention to the namespace of the onChanged event. If you store something using chrome.storage.local.set, then the onChanged event is triggered, but reading using chrome.storage.sync.get makes little sense.Lubricous
Yes you're right, edited my answer. Obviously you can use chrome.storage.sync.get in other scenarios, but here it is indeed redundant.Theola
In response to revision 5 of your answer: changes.visitedPages will be undefined if visitedPages has not been changed. Wrap the line in if (changes.visitedPages) { ... } to solve this problem.Lubricous
If I have set Google Auth in some auth.js and content_script should run If I get user details, how should I manage the message passing for both files?Foretooth
B
8

Another option would be to use the chromestorage API. This allows storage of user data with optional syncing across sessions.

One downside is that it is asynchronous.

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

Beberg answered 19/7, 2012 at 5:30 Comment(1)
@Jason, What about all-or-nothing transactions?Stieglitz
I
8

[For manifest v3]

You can execute a script that returns localstorage items from the webpage. This script can be executed from popup or background service worker.

Add this line in manifest.json:

"permissions": ["scripting"]


 let [tab] = await chrome.tabs.query({ active: true, currentWindow: true })

 // Execute script in the current tab
  const fromPageLocalStore = await chrome.scripting.executeScript({
    target: { tabId: tabId },
    func: () => {
      return JSON.stringify(localStorage)
    }
  })

  const localStorageItems = JSON.parse(fromPageLocalStore[0].result)
Iiette answered 15/11, 2022 at 20:50 Comment(1)
was looking for hours for this solution, so simple, thank youFricative

© 2022 - 2024 — McMap. All rights reserved.