12 Understanding Chrome Extensions Storage

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.

  1. You can use retrieve data in you background scripts/service workers with chrome.storage as opposed to Web Storage.
  2. Content scripts running on different websites have all access to the same chrome.storage data and it not segments per domain.
  3. Unlike the Web Storage API, chrome.storage data will persists even after the clearing the browsing history. In fact chrome.storage data will persists even after cache is cleared.
  4. 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?

Photo by Steve Johnson on Unsplash

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 in chrome.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.

  1. 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.
  2. 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.
  3. 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()
  4. 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 scriptbackground 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

Link Extractor

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 herehttps://github.com/BuildChromeExtensions/googlesearchlinks

We need a manifest.json content scripts, background script, popup script and popup UI. Your project should look like this.

Project Structure

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

Chrome Extension

Leave a Reply

Your email address will not be published. Required fields are marked *

More Articles & Posts