The chrome.storage
API is an API that store persistent data, get and modify the data. In our opinion it is one of the most important API used in chrome extensions projects. See the Chrome Storage API documentation for more info
Unlike a lot of the other APIs we’ve looked at in previous articles chrome.storage
works in all parts of the extensions; content scripts, background scripts and popup/extensions pages.
How is Chrome Storage API different from Web Storage API?
For those familiar with web dev, you might be wondering why use chrome.storage
API when can store data using Web Storage API (window.localStorage
)? Good question.
- You can use retrieve data in you background scripts/service workers with
chrome.storage
as opposed to Web Storage. - Content scripts running on different websites have all access to the same
chrome.storage
data and it not segments per domain. - Unlike the Web Storage API,
chrome.storage
data will persists even after the clearing the browsing history. In factchrome.storage
data will persists even after cache is cleared. - If the chrome extensions is running in an incognito window. The extension can access to the
chrome.storage
data.
What Kind of Data can we storage in Chrome Storage API?
Similar to the data sent via chrome.runtime.sendMessage
function the data stored in chrome.storage
API is a JSON with serializable values. In others words primitive types such as Numbers, Strings and Booleans and Arrays and Objects consists of primitive types. For instance
chrome.storage.local.set({myValue : 2 });
chrome.storage.local.set({myValue : "2" });
chrome.storage.local.set({myValue : true });
// array
chrome.storage.local.set({myValue: [true, 2, false, "2", {value:2 } ] });
// complex objects
chrome.storage.local.set({
myValue: {
text:"text",
number: 2,
list: [23, 24, 5, 25 ],
okay:false,
otherdata:{
areTheyStillReading : false
}
}
});
You can make the json object as complex as you want as long as it contains primitive type or collection or object of primitive types. So NO
Date
,Set
,Map
or custom classes in your code can be saved inchrome.storage
API.
Storage Areas
There are four types of storage areas local
, sync
, session
, and managed
. More often than not, local
will be used in chrome extensions projects.
- Local: In this area data is stored locally on the browser the extension is installed on. The limit of data that be stored in 5MB but that can be increased to an indefinite amount. We will show you how later in this article.
- Sync: The sync area stores data locally at first but syncs the data with all the chrome browsers the users is logged into and synced with. The storage limit is significantly much less than local.
- Sessions: In this area data persists for the duration of the browser sessions. Usually used to hold sensitive data. It denials content scripts access to the data by default. But can be changes by running this function
chrome.storage.session.setAccessLevel()
- Managed: “Managed storage is read-only storage for policy installed extensions and managed by system administrators using a developer-defined schema and enterprise policies.” See Documentation for Administrators.
NOTE: Storing data often comes with performance costs, be careful with how much data your storing and how fast your storing it.
How to declare in Manifest.json
{
...
"permissions":[
"storage"
],
...
}
If you want to go beyond the 5MB local
limit
{
...
"permissions":[
"storage",
"unlimitedStorage"
],
...
}
How to save data to Chrome Storage API?
To save data using the Chrome Stoage API we’ll use the chrome.storage.local.set
function. As mention, in the beginning section of the this article, we can only store primitive types or a collection of primitive types. In addition the function runs asynchronously.
// use the then function
chrome.storage.local.set({valueA : "2" }).then(() => console.log("Done") );
// or use await/async
await chrome.storage.local.set({valueB: true });
In this particular example valueA
and valueB
are the keys in which the data is stored. The same would apply to the other storage areas as well.
await chrome.storage.sync.set({valueB: true });
await chrome.storage.session.set({valueB: true });
How to retrieve data from Chrome Storage API?
To retrieve data use the chrome.storage.get
function. This function also runs asynchronously. Moreover, there are multiple ways for retrieve data.
Get One JSON object
// use the then function
chrome.storage.local.get('valueA').then((data) => {
// data.valueA == undefined if the data was never stored
console.log(data.valueA)
});
// or use await/async
const data = await chrome.storage.local.get('valueB');
console.log(data.valueB)
Get Multiple JSON object
// use the then function
chrome.storage.local.get(['valueA', 'valueB']).then((data) => {
console.log(data.valueA)
console.log(data.valueB)
});
// or use await/async
const data = await chrome.storage.local.get(['valueA', 'valueB']);
console.log(data.valueA)
console.log(data.valueB)
The same would apply to the other storage areas as well.
const syncedData = await chrome.storage.sync.get('valueA');
const sessionData = await chrome.storage.session.get('valueB');
A React JS code snippet example
function App(){
const [valueA, setValueA] = useState("");
const [valueB, setValueB] = useState("");
// Retrive chrome data
useEffect(() => {
chrome.storage.local.get(['valueA', 'valueB']).then((data) => {
setValueA(data.valueA)
setValueB(data.valueB)
});
}, [])
return <div>{valueA} and {valueB}</div>
}
How to listen of storage changes
Sometimes you want run code even data can just been added or modified. Chrome Storage API provides a listener for such as purpose. You can run this listener in any part of the extension, content script, background script and extension pages (pop up UI).
chrome.storage.onChanged.addListener((changes, area) => {
// the area is == local, sync, session or managed
// changes have the data of what was changed.
// for example if valueA was changed
if(changes.valueA){
console.log(changes.valueA.oldValue) // old json
console.log(changes.valueA.newValue) // new json
}
})
A React JS code snippet example
function App(){
const [valueA, setValueA] = useState("");
// Retrive chrome data
useEffect(() => {
const listener = (changes, area) => {
// the area is == local, sync, session or managed
// changes have the data of what was changed.
// for example if valueA was changed
if(changes.valueA){
console.log(changes.valueA.oldValue) // old json
console.log(changes.valueA.newValue) // new json
setValueA(changes.valueA.newValue);
}
}
chrome.storage.onChanged.addListener(listener)
// because react re-renders, each re-render will add a listener
// so when the useffect is dismounting we'll remove the listener
return () => chrome.storage.removeListener(listener);
}, [])
return <div>Value just changed to {valueA}</div>
}
Sample Project
In this extension we will be scraping the links from Google Search page and storing them in the local area. For the source code you can clone this repository here: https://github.com/BuildChromeExtensions/googlesearchlinks
We need a manifest.json content scripts, background script, popup script and popup UI. Your project should look like this.
manifest.json
{
"name": "Search Links",
"manifest_version": 3,
"version": "1.0.0.0",
"action": {
"default_popup": "popup.html"
},
"permissions": [
"storage"
],
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"matches": [
"https://www.google.com/search*"
],
"js": [
"content.js"
]
}
]
}
popup.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style type="text/css">
body {
width: 400px;
height: 400px;
display: flex;
flex-direction: column;
margin: 0 auth;
padding:10px;
}
</style>
</head>
<body>
<h1>Google Searched Links</h1>
<!-- Where the link will show -->
<ol>
</ol>
<script type="text/javascript" src="./popup.js"></script>
</body>
</html>
popup.js
// Add Google Search to UI
chrome.storage.local.get('links').then(data => {
if (data.links) {
const ol = document.querySelector('ol');
for (const link of data.links) {
const name = link.name;
const url = link.url;
const a = document.createElement('a');
a.textContent = name;
a.href = url;
const li = document.createElement('li');
li.appendChild(a);
ol.appendChild(li);
}
}
})
content.js
// get all h3 under an a tag
const h3s = document.querySelectorAll('a h3');
// store {name, url}
const list = [];
// loop through elements
for(const h3 of h3s){
const a = h3.parentElement;
const url = a.href;
const name = h3.textContent;
list.push({
name: name,
url: url
});
}
// save to chrome storage
chrome.storage.local.set({ links : list }).then(() => {
console.log('Saved Successfully');
});
background.js
chrome.storage.onChanged.addListener((changes, area) => {
// the area is == local, sync, session or managed
// changes have the data of what was changed.
// for example if links was changed
console.log('Area', area);
if (changes.links) {
console.log('Old Links', changes.links.oldValue) // old json
console.log('New Links', changes.links.newValue) // new json
}
})
Leave a Reply