"Half of Chrome's most-installed extensions never get the all-websites warning, because they use activeTab and a handful of narrow permissions that solve the same problems. Lesson 4 is the shortcut list — what to reach for instead of <all_urls>."
activeTab — The Workhorse
"activeTab" is a special API permission that grants temporary host access to the currently-active tab, starting when the user invokes the extension via:
- Toolbar icon click (
chrome.action.onClickedor popup open). - Keyboard command (
chrome.commands.onCommand). - Context menu (
chrome.contextMenus.onClicked).
The grant covers: chrome.scripting.executeScript on that tab, chrome.tabs.captureVisibleTab on that tab, and reading tab.url / tab.title. It lasts until the user navigates the tab to a new URL or closes the tab.
Crucially: no install warning. activeTab by itself adds nothing to the prompt. Combined with the user-gesture trigger pattern, you get "works on demand, only when asked" semantics without the all-sites alarm.
activeTab vs Programmatic Injection
Confusion point: activeTab grants host access; scripting grants the API. You usually want both:
"permissions": ["activeTab", "scripting"]
With those two declared, your SW can call chrome.scripting.executeScript on the user-active tab inside a gesture handler. No host_permissions needed. No content-script declaration needed unless you also want always-on injection.
Other Narrow Permissions Worth Knowing
tabGroups— read and modify Chrome's tab grouping. No install warning of its own.notifications— show desktop notifications viachrome.notifications.create. Mild install warning ("Show notifications"); benign for most users.alarms— schedule one-shot or recurring SW wake-ups. No install warning. Replaces setInterval/setTimeout (which die with the SW).identity— OAuth flows for Google sign-in. Install warning summarizes the scopes you'll later request, not host access.webNavigation— fine-grained navigation events. Comes with a "Read your browsing history" warning;tabscovers most of the same ground less scarily.contextMenus— already in your manifest. No warning.storage,commands,sidePanel,omnibox,action— all silent.
The Permissions to Treat With Care
These each add their own loud warning. Use only when you truly need them, and consider gating behind optional_permissions:
history— "Read and modify your browsing history." Rarely needed;tabsplus a per-tab cache usually covers the use case.cookies— "Read and modify cookies on all sites." Almost never needed for a clip-saving extension.geolocation— "Detect your physical location." Surprises users; ask runtime.nativeMessaging— "Communicate with cooperating native applications." Lets you talk to a desktop binary; opens an attack surface.debugger— "Use the developer tools on any tab." Power-user only; install warning is loud and justified.webRequest— "Block or modify network requests." MV3 restricted this heavily compared to MV2; even narrow use produces a warning.
The Substitution Game
Before declaring a host permission or a scary API permission, ask: "is there a narrower way?" Often yes:
- Need a periodic background job?
alarms, notsetInterval+ persistent worker. - Need to remember per-site preferences?
storage, notcookies. - Need to read the current page?
activeTab+scripting, not host_permissions. - Need to know which sites the user just visited?
tabswith onUpdated, nothistoryorwebNavigation. - Need to act when the user types something?
commandsfor a hotkey, oromniboxfor an address-bar keyword. Nodebugger.
content_scripts manifest entry is always-on for matching URLs and is governed by content_scripts.matches, separately from activeTab.