# WebExtensions dynamic context menu

**URL:** <https://discourse.mozilla.org/t/webextensions-dynamic-context-menu/18051>\
**Category:** Add-on Support\
**Created:** [August 14, 2017, 5:45am UTC](https://discourse.mozilla.org/t/webextensions-dynamic-context-menu/18051 "2017-08-14T05:45:51Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![kiboke](https://sea1.discourse-cdn.com/flex001/user_avatar/discourse.mozilla.org/kiboke/32/3248_2.png) [@kiboke](https://discourse.mozilla.org/u/kiboke)\
**Post date:** [August 14, 2017, 5:45am UTC](https://discourse.mozilla.org/t/webextensions-dynamic-context-menu/18051/1 "2017-08-14T05:45:51Z")

</div>

Hi,

I plan to switch my addon to WebExtensions but I have an issue with context menu: I can’t change the context menu real-time. The way I try to do it is:

I listen to the right click event and send a message with chrome.runtime.sendMessage which triggers context menu update. Everything is async so this update happens a bit after the context menu is opened so, to see it updated, I need to close the context menu and open it again.

The same thing happens in chrome and opera, of course. Can someone tell me how to make it work properly?

---

<div class="post-metadata">

**Author:** ![erosman](https://sea1.discourse-cdn.com/flex001/user_avatar/discourse.mozilla.org/erosman/32/15447_2.png) [@erosman](https://discourse.mozilla.org/u/erosman)\
**Post date:** [August 14, 2017, 6:12pm UTC](https://discourse.mozilla.org/t/webextensions-dynamic-context-menu/18051/2 "2017-08-14T18:12:14Z")

</div>

There is a talk about an onBeforeShow event, which would have been good for this circumstance, but it is P5 and it is not gong to be available soon.

[https://bugzilla.mozilla.org/show\_bug.cgi?id=1215376](https://bugzilla.mozilla.org/show_bug.cgi?id=1215376)

---

<div class="post-metadata">

**Author:** ![asamuzaK](https://sea1.discourse-cdn.com/flex001/user_avatar/discourse.mozilla.org/asamuzak/32/18266_2.png) [@asamuzaK](https://discourse.mozilla.org/u/asamuzaK)\
**Post date:** [August 15, 2017, 12:43am UTC](https://discourse.mozilla.org/t/webextensions-dynamic-context-menu/18051/3 "2017-08-15T00:43:29Z")

</div>

For the workaround, see also [Change label in the contextmenu before the opening](https://discourse.mozilla.org/t/change-label-in-the-contextmenu-before-the-opening/16620/2)

---

<div class="post-metadata">

**Author:** ![kiboke](https://sea1.discourse-cdn.com/flex001/user_avatar/discourse.mozilla.org/kiboke/32/3248_2.png) [@kiboke](https://discourse.mozilla.org/u/kiboke)\
**Post date:** [August 23, 2017, 4:29am UTC](https://discourse.mozilla.org/t/webextensions-dynamic-context-menu/18051/4 "2017-08-23T04:29:02Z")

</div>

This solution doesn’t work.

Context menu update is triggered separately from menu opening and runs too late. I have to close the context menu and reopen it to see the effect of the previous context menu update.

To make the problem worse, thanks to this delay, I see the result of the context menu update of one tab in ALL tabs, until I reopen the context menu.

---

<div class="post-metadata">

**Author:** ![asamuzaK](https://sea1.discourse-cdn.com/flex001/user_avatar/discourse.mozilla.org/asamuzak/32/18266_2.png) [@asamuzaK](https://discourse.mozilla.org/u/asamuzaK)\
**Post date:** [August 23, 2017, 4:47am UTC](https://discourse.mozilla.org/t/webextensions-dynamic-context-menu/18051/5 "2017-08-23T04:47:05Z")

</div>

If possible, could you show me the link to your code?

---

<div class="post-metadata">

**Author:** ![kiboke](https://sea1.discourse-cdn.com/flex001/user_avatar/discourse.mozilla.org/kiboke/32/3248_2.png) [@kiboke](https://discourse.mozilla.org/u/kiboke)\
**Post date:** [August 23, 2017, 5:13am UTC](https://discourse.mozilla.org/t/webextensions-dynamic-context-menu/18051/6 "2017-08-23T05:13:30Z")

</div>

Can you download my extension from chrome web store, unpack it and add to firefox? I’d be happy to guide you to this issue, which persists in all browsers.

> **[I don't care about cookies](https://chrome.google.com/webstore/detail/i-dont-care-about-cookies/fihnjjcciajhdojfnbdddfaoknhalnja)**
>
> Remove annoying cookie warnings from almost all 'infected' websites!
> 
> The EU regulations require that any website using cookies…

---

<div class="post-metadata">

**Author:** ![asamuzaK](https://sea1.discourse-cdn.com/flex001/user_avatar/discourse.mozilla.org/asamuzak/32/18266_2.png) [@asamuzaK](https://discourse.mozilla.org/u/asamuzaK)\
**Post date:** [August 23, 2017, 9:21am UTC](https://discourse.mozilla.org/t/webextensions-dynamic-context-menu/18051/7 "2017-08-23T09:21:01Z")

</div>

```auto
document.addEventListener('mousedown', function(e) {
	if (e.button != 2)
		return;
	
	var a = document.createElement('a');
	a.href = document.location.href;
	const time = window.performance.now();
	console.log(time);
	chrome.runtime.sendMessage({
	  request:'updateToggleMenu',
	  hostname:`${a.hostname.replace(/^w{2,3}\d*\./i, '')} (${time})`,
	});
});

```

I’ve added `time` to your script for checking.  
Seems working.

 ![capture](https://sea1.discourse-cdn.com/flex001/uploads/mozilla/original/3X/b/a/ba2e42074179d5ef3a7418a0c8494090de41ec76.png)

Add listener to `window` instead of `document`, and set 3rd argument (useCapture) to `true` will be better, I suppose.

```auto
window.addEventListener("mousedown", evt => {
}, true);

```

You should also listen to `keydown` event.

---

<div class="post-metadata">

**Author:** ![asamuzaK](https://sea1.discourse-cdn.com/flex001/user_avatar/discourse.mozilla.org/asamuzak/32/18266_2.png) [@asamuzaK](https://discourse.mozilla.org/u/asamuzaK)\
**Post date:** [August 23, 2017, 9:55am UTC](https://discourse.mozilla.org/t/webextensions-dynamic-context-menu/18051/8 "2017-08-23T09:55:57Z")

</div>

Off topic.  
You don’t have to create anchor element just for getting hostname.

```auto
  const {hostname} = new URL(window.location.href);
  console.log(hostname);

```

will do.

---

<div class="post-metadata">

**Author:** ![kiboke](https://sea1.discourse-cdn.com/flex001/user_avatar/discourse.mozilla.org/kiboke/32/3248_2.png) [@kiboke](https://discourse.mozilla.org/u/kiboke)\
**Post date:** [August 25, 2017, 4:57am UTC](https://discourse.mozilla.org/t/webextensions-dynamic-context-menu/18051/9 "2017-08-25T04:57:51Z")

</div>

Thans for the anchor element tip! This is my code, the problem persists (first content menu opening, nothing happens, the default text is being displayed “Extension doesn’t work on this domain”, the second opening, everything ok. If I don’t open the second time and go to other tab and then open the context menu, it will display the previously set text from the other tab):

```
function updateMessage()
{
	const {hostname} = new URL(window.location.href);
	chrome.runtime.sendMessage({request:'updateToggleMenu', hostname:hostname.replace(/^w{2,3}\d*\./i, '')});
}

window.addEventListener("mousedown", evt => {
	if (evt.button === 2)
		updateMessage();
}, true);

window.addEventListener("keydown", evt => {
	if (evt.shiftKey && evt.key === "F10" || evt.key === "ContextMenu")
		updateMessage();
}, true);
```

---

<div class="post-metadata">

**Author:** ![asamuzaK](https://sea1.discourse-cdn.com/flex001/user_avatar/discourse.mozilla.org/asamuzak/32/18266_2.png) [@asamuzaK](https://discourse.mozilla.org/u/asamuzaK)\
**Post date:** [August 25, 2017, 6:53pm UTC](https://discourse.mozilla.org/t/webextensions-dynamic-context-menu/18051/10 "2017-08-25T18:53:40Z")

</div>

Maybe iframe used?

If so, add below in `manifest.json`, and see if something gets better (or worse).

```auto
"content_scripts": [
  {
    "all_frames": true
  }
]

```

---

<div class="post-metadata">

**Author:** ![kiboke](https://sea1.discourse-cdn.com/flex001/user_avatar/discourse.mozilla.org/kiboke/32/3248_2.png) [@kiboke](https://discourse.mozilla.org/u/kiboke)\
**Post date:** [August 31, 2017, 4:03am UTC](https://discourse.mozilla.org/t/webextensions-dynamic-context-menu/18051/11 "2017-08-31T04:03:56Z")

</div>

Nothing has changed. The context menu with an old value is being displayed before the value gets updated.

P.S. in chrome it works fine now so i guess it’s a performance issue. I have FF 55.0.2. I have aslo tried ff with addons disabled in safe mode, hoping that it will run faster but it doesn’t help.

---

<div class="post-metadata">

**Author:** ![asamuzaK](https://sea1.discourse-cdn.com/flex001/user_avatar/discourse.mozilla.org/asamuzak/32/18266_2.png) [@asamuzaK](https://discourse.mozilla.org/u/asamuzaK)\
**Post date:** [September 1, 2017, 12:41am UTC](https://discourse.mozilla.org/t/webextensions-dynamic-context-menu/18051/12 "2017-09-01T00:41:59Z")

</div>

If the hostname is the only matter, how about updating the menu item when the active tab changes?  
You don’t need to listen in content script then.

background.js:

```auto
tabs.onActivated.addListener(async info => {
  const {tabId, windowId} = info;
  const tab = await tabs.getCurrent();
  const {id, windowId: currentWindowId, url} = tab;
  if (tabId === id && windowId === currentWindowId && url) {
    const {hostname} = new URL(url);
    contextMenus.update(...);
  } else {
    // default menu item
    contextMenus.update(...);
  }
});

```

ref [tabs.onActivated - Mozilla | MDN](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/tabs/onActivated "tabs.onActivated - Mozilla | MDN")  
ref [tabs.getCurrent() - Mozilla | MDN](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/tabs/getCurrent "tabs.getCurrent() - Mozilla | MDN")

---

<div class="post-metadata">

**Author:** ![kiboke](https://sea1.discourse-cdn.com/flex001/user_avatar/discourse.mozilla.org/kiboke/32/3248_2.png) [@kiboke](https://discourse.mozilla.org/u/kiboke)\
**Post date:** [September 5, 2017, 9:20am UTC](https://discourse.mozilla.org/t/webextensions-dynamic-context-menu/18051/13 "2017-09-05T09:20:16Z")

</div>

This doesn’t help because the hostname may change many times after onActivated is triggered. I can’t believe nobody run into this issue before 🙂

---

<div class="post-metadata">

**Author:** ![asamuzaK](https://sea1.discourse-cdn.com/flex001/user_avatar/discourse.mozilla.org/asamuzak/32/18266_2.png) [@asamuzaK](https://discourse.mozilla.org/u/asamuzaK)\
**Post date:** [September 5, 2017, 9:38am UTC](https://discourse.mozilla.org/t/webextensions-dynamic-context-menu/18051/14 "2017-09-05T09:38:06Z")

</div>

Then add listener to tabs.onUpdated too?

```auto
tabs.onUpdated.addListener(async (tabId, info, tab) => {
  const {active, status, windowId, url} = tab;
  if (active && status === "complete") {
    const {id: currentWindowId} = await windows.getCurrent();
    if (windowId === currentWindowId) {
      const {hostname} = ...
    }
  }
});

```

---

<div class="post-metadata">

**Author:** ![kiboke](https://sea1.discourse-cdn.com/flex001/user_avatar/discourse.mozilla.org/kiboke/32/3248_2.png) [@kiboke](https://discourse.mozilla.org/u/kiboke)\
**Post date:** [September 11, 2017, 11:38am UTC](https://discourse.mozilla.org/t/webextensions-dynamic-context-menu/18051/15 "2017-09-11T11:38:44Z")

</div>

It worked, although not with async/await, I had to do it the old way, and I’ve also optimized the code so it doesn’t have to run anything and slow down the affected events.

Thank you very much for your time and help, asamuzaK!
