While we're waiting for browser action buttons to catch up with Canary, let's try out context menus.
To further explore message passing through business logic, let's rebuild our context menus for each page load. (Why? We might want to make them behave differently or hide them entirely on certain domains or sets of domains that cannot or should not be expressed via the site_permissions
property.)
In our manifest we'll add contextMenus
to the permissions
property.
We'll build and activate menus inside our background script, like this:
// clear, add, and listen to new context menu
const handleContextMenus = () => {
// remove existing menu items
chrome.contextMenus.removeAll();
// create a menu
chrome.contextMenus.create({
id: "BaselineV2",
title: "V2 Baseline",
// show the menu over everything
contexts: ["all"],
// handle interactions
onclick: () => {
chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {
msg: "Greetings from your Baseline V2 context menu"
});
});
}
});
};
For each time handleContextMenus
is called, we're going to:
- clear any existing menus
- make a new menu
- send a message back to the page whenever it's clicked
In our business logic, we'll send a request to our background script to add the context menu:
chrome.runtime.sendMessage({
cmd: "addMenu"
});
Our business logic already had a function that logs any messages received to console.
Changes to manifest and business logic are identical; changes to our background script are not. The old-school inline onclick
handler won't do, because our service worker is not a persistent background script. Instead, we'll add a proper event listener:
const handleContextMenus = () => {
// remove existing menu items
chrome.contextMenus.removeAll();
// create a menu
chrome.contextMenus.create({
title: "V3 Test",
id: "TestV3",
// show the menu over everything
contexts: ["all"]
// IMPORTANT: because we are no longer using a
// persistent background script we will need to
// add an event listener outside contextMenus.create.
});
// handle interactions
chrome.contextMenus.onClicked.addListener(menu => {
chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {
msg: "Greetings from your Test V3 context menu"
});
});
});
};
Install and Inspect:
- Install by dragging and dropping
ep_005/v2/
andep_005/v3/
intochrome://extensions
- The v2 card should have no errors; the v3 card may show a warning about Manifest V3.
- Inspect the v2 version by clicking the background page link in the v2 card
- Inspect the v3 version by opening
chrome://serviceworker-internals
in a new tab and then clicking the Inspect button
Open a new page in a new tab and inspect. You ought to see something like this in console:
Content script has loaded via Manifest V2.
Content script has loaded via Manifest V3.
A script has run from chrome.tabs.executeScript via Manifest V2.
A script has run from chrome.tabs.executeScript via Manifest V3.
Right-click anywhere on the page. You ought to see both the V2 Baseline and V3 Test context menu items.
Click V2 Baseline and V3 Test and note messages like this in page console:
{msg: "Greetings from your Baseline V2 context menu"}
{msg: "Greetings from your Test V3 context menu"}
Check in your background script inspector consoles; you ought to see notes from your background in each. This will get noisy quickly as you open new tabs.
Seems good! Keeping an eye out for other instances where I might have been adding inline listeners, which will fail on service workers.