Skip to content

Latest commit

 

History

History
113 lines (87 loc) · 4.23 KB

ep_005.md

File metadata and controls

113 lines (87 loc) · 4.23 KB

Episode Five: Context Menus

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.)

V2 Baseline

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.

V3 Test

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"
      });
    });
  });
};

Things to Do and Notice

Install and Inspect:

  • Install by dragging and dropping ep_005/v2/ and ep_005/v3/ into chrome://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.

Current Status

Seems good! Keeping an eye out for other instances where I might have been adding inline listeners, which will fail on service workers.