Adding context menu item on a non-persistent background script?

Ammending what Marco Bonelli wrote:

If you want to use an event page or a non-persistent background page, as you call it, you should register a context menu via contextMenus.create in the event handler of runtime.onInstalled, as these context menu registrations ”persist“ anyway.

You have to add the listener-function for the contextMenus.onClicked event every time the event page gets reloaded, though, as the registration of your wish to listen on that event persists, while the handler callback itself does not.

So to do it right™, register your context-menu-to-be from runtime.onInstalled, but set the event handler callback itself using contextMenus.onClicked.addListener from top level or other code, that is guaranteed to be executed each time the event page loads.[1]


You are saying you've got a non-persistent background page, so you should have a manifest.json file that looks like this:

{
    "manifest_version": 2,

    "name": "My extension",
    "description": "My description",
    "version": "1",
    
    "permissions": ["contextMenus"],
    "background": {
        "persistent": false,
        "scripts": [
            "/background.js"
        ] 
    }
}

Now, since you've got a non-persistent background page, you have to use the right listeners to "wake it up" when you need to use the context menu.

Quoting from the official documentation (NOTE: this link points to an archived copy of the documentation from 2014 and is outdated):

Best practices when using event pages:

[...]

  1. If you're using the context menus API, pass a string id parameter to contextMenus.create, and use the contextMenus.onClicked callback instead of an onclick parameter to contextMenus.create.

So, simply, your error is using the onclick parameter instead of the contextMenus.onClicked.addListener() method in your background.js.

Solution

I already said that you should use the onClicked event, but I would like to add that, referring to x a's answer:

You should register a context menu via contextMenus.create in the event handler of runtime.onInstalled, as these context menu registrations persist anyway.

So simply, given that once created the context menus persist in your extension, it's best practice to only define them a single time: when your extension is installed (or updated), and add the listener each time the background page is loaded.

chrome.runtime.onInstalled.addListener(function() {
    chrome.contextMenus.create({
        title: 'My menu',
        id: 'menu1', // you'll use this in the handler function to identify this context menu item
        contexts: ['all'],
    });
});

chrome.contextMenus.onClicked.addListener(function(info, tab) {
    if (info.menuItemId === "menu1") { // here's where you'll need the ID
        // do something
    }
});

That's what you need to create a context menu in an event page, as shown in the documentation page of the chrome.contextMenus API.