Question

I'm working on a simple link sharing extension (pinboard, readability, delicious, etc), and have a question about how to properly deal with a context menu item. In my non-persistent background page I call chrome.contextMenus.create and chrome.contextMenus.onClicked.addListener to setup/respond to the context menu.

The context menu entry works as expected. But the background page is showing the following error (right after it starts and before I've used the entry) :

contextMenus.create: Cannot create item with duplicate id id_share_link at chrome-extension://.../share.js:52:30 lastError:29 set  

This made me realize that at no point do I remove the item or the listener. Knowing little about javascript and extensions, I'm left wondering if I'm doing everything correctly. I'm assuming this top-level code is going to re-execute every time the background page is invoked. So there are going to be redundant calls to create and addListener (and hence the error I see being logged).

I clearly can't do cleanup in response to suspend, as these calls need to be present to wake up the background script.

Should I be handling things differently?

Was it helpful?

Solution

You can handle it one of two ways:

  1. You can add the context menu and the listeners on install using:

    chrome.runtime.onInstalled.addListener(function() {
      /* Add context menu and listener */
    });
    
  2. You can remove the context menu and listener, and then re-add it each time the file is called.

OTHER TIPS

If you want to use an event page, ie 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“ anyways.

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 generally don't call contextMenus.onClicked.addListener from runtime.onInstalled, but from top level or other code, that is guaranteed to be executed each time the event page loads.[1]

[solution may no longer be the case, read comment]

runtime.onInstalled is not triggered if you disable/enable your extension.
My solution is to always add menu items and swallow errors:

'use strict';

{

  let seqId = 0;

  const createMenuLinkEntry = (title, tab2url) => {

    const id = (++seqId).toString();

    chrome.contextMenus.create({
      id: id,
      title: title,
      contexts: ['browser_action'],
    }, () => {

      const err = chrome.runtime.lastError;
      if(err) {
        console.warn('Context menu error ignored:', err);
      }

    });

  };

  createMenuLinkEntry('Go to Google', (tab) => 'https://google.com');
  createMenuLinkEntry('Go to GitHub', (tab) => 'https://github.com');

} // namespace
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top