Search code examples
google-chrome-extensiongoogle-chrome-devtoolsmanifest.json

I was trying to make a chrome extension and Getting localStorage undefined error while using manifest v3


With manifest v2 it is working fine. But with manifest v3 I'm getting error "ReferenceError: localStorage is not defined"

manifest.json

{
  "name": "Getting Started Example",
  "description": "Build an Extension!",
  "version": "1.0",
  "manifest_version": 3,
  "background": {
    "service_worker": "background.js"
  },
  "permissions": ["storage", "activeTab", "contextMenus"],
  "action": {
    "default_popup": "popup.html"
  }
}

background.js

var contextMenuItems = {
  "title": 'Add to notepad"',
  "contexts": ["selection"],
  "id": "myContextMenuId"
};
chrome.contextMenus.create(contextMenuItems);
chrome.contextMenus.onClicked.addListener(function(clickData){
  if(clickData.menuItemId == "myContextMenuId" && clickData.selectionText){
   localStorage.setItem("text", "clickData.selectionText");
  }
});

Solution

  • The background script in ManifestV3 is a service worker now so it can't access stuff exposed only on window like HTML5 localStorage or DOM. By the way, service workers don't have window, their global context is self or globalThis.

    The solution is to switch to chrome.storage.local. It's an entirely different storage available in all extension contexts including content scripts. Note that a) it's asynchronous so the usage is different and b) it doesn't currently return a Promise due to a bug in Chrome so you can't await it. Until it's fixed, use the callback version shown in the documentation.

    Storing:

    chrome.contextMenus.onClicked.addListener(info => {
      if (info.menuItemId == 'myContextMenuId' && info.selectionText) {
        chrome.storage.local.set({text: info.selectionText});
      }
    });
    

    Reading in popup:

    chrome.storage.local.get('text', ({text}) => {
      // the callback runs asynchronously so you should use the value here
      document.body.prepend(text);
    });