Scripts and Messaging

Service Workers, Content Scripts and Messaging

The background service worker is the extension's event hub. Chrome 1 starts it for events and stops it after 30 seconds without events or API calls, so register listeners at the top level and keep state in chrome.storage, not in globals. Content scripts run inside matching pages in an isolated world: they share the page's DOM but not its JavaScript variables, and they can call only a few extension APIs such as runtime.sendMessage(). Everything else travels by message.

Link Counter's contexts and the messages between them
Link Counter's contexts and the messages between them
link-counter/content.jsJavaScript
const links = [...document.querySelectorAll('a[href]')];
const external = links.filter((a) => a.hostname && a.hostname !== location.hostname).length;
const msg = { type: 'links', title: document.title, total: links.length, external };
chrome.runtime.sendMessage(msg).then((reply) => console.log('[content] badge =', reply.badge));
link-counter/background.jsJavaScript
chrome.runtime.onInstalled.addListener(({ reason }) => console.log('[sw] onInstalled:', reason));
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
  if (msg.type !== 'links') return;
  const tabId = sender.tab.id;
  const text = String(msg.total);
  chrome.action.setBadgeText({ tabId, text });
  chrome.storage.session.set({ [`tab-${tabId}`]: msg });   // survives service worker restarts
  console.log(`[sw] tab ${tabId}: ${msg.total} links, ${msg.external} external`);
  sendResponse({ badge: text });                           // or return true to reply later
});
Output
[sw] onInstalled: install
[sw] tab 55599464: 7 links, 3 external
[content] badge = 7

This output is real: Playwright 26,280 loaded the folder into Chromium 151 4,389 with --load-extension, a flag branded Chrome ignores since version 137. The [sw] lines appear in the service worker's console (linked from chrome://extensions). From Chrome 148 a listener may return a Promise, and every API is also exposed as browser.*.