Popup and storage
Save with extension storage
Persist page notes with chrome.storage.local instead of popup memory or page-owned localStorage.
We have a key for the page and a textarea with a note. Now we need somewhere to keep it.
Popup variables are out: they die with the popup. The page’s localStorage is out too. It belongs to the website’s origin, not to us, and a content script writing there would leave our data on someone else’s site.
The right place is chrome.storage.local. It’s owned by the extension, it’s available from every extension context, and it survives popup closes and browser restarts.
Saving a note
Storage works with objects. The property name is the key, the property value is what you store. Values must be JSON-serializable, and every operation is asynchronous.
form.addEventListener('submit', async event => {
event.preventDefault()
const value = new FormData(form).get('note').trim()
await chrome.storage.local.set({ [key]: value })
status.textContent = 'Saved'
})
Notice the await before showing “Saved”. If the write fails, the promise rejects and the success message never appears. Showing success before the write finishes is lying to the user.
Limits and visibility
storage.local keeps data until the extension is uninstalled. It currently has a 10 MB quota unless you request the unlimitedStorage permission. For short notes that’s more than enough. It’s not an invitation to hoard page data.
By default, content scripts can read storage.local too. For Page Notes I keep all storage access in the popup and the worker, and send only the one note the page needs. If you need a hard rule, chrome.storage.local.setAccessLevel() can restrict the area to trusted extension contexts.
Also, storage is not encrypted. Don’t treat it as a vault for secrets.
One key per page
It’s tempting to store one big notes object and update it. Don’t. Two popups saving at the same time would each read the object, change their own entry, and write it back, and the second write erases the first.
Independent keys avoid that. Each page writes its own property, and unrelated writes never collide. When the user clears a note, remove the key instead of storing an empty string:
await chrome.storage.local.remove(key)
If you ever have several extension pages open at once, chrome.storage.onChanged tells each one when another wrote something.
Now test it. Save notes on two different pages, close the popup, reopen it, and check that each page shows its own note. Delete one and confirm the other survives. Then make a write fail on purpose, for example by storing a huge string, and verify “Saved” never shows up.
Lesson completed