I've been trying to migrate one of my Chrome extensions to manifest v3, and I'm having trouble with the page_action
. In manifest v3, the page_action
and browser_action
are merged into action
, which is all good, but it's not clear to me how I can get the behavior I had previously with the new APIs.
A bit of background; the extension in question is only supposed to run on one host (let's say https://example.com). As such, I want to grey out the icon on pages with a different host. It has a popup with some settings but the main functionality is inserted via a content script (this works).
The old extension using manifest v2 used
{
"manifest_version": 2,
"name": "...",
"description": "...",
"version": "...",
"permissions": ["declarativeContent", "storage", "https://example.com/", "tabs"],
"page_action": {
"default_icon": { ... },
"default_popup": "popup.html"
},
"background": {
"scripts": ["background.js"],
"persistent": false
},
"icons": { ... },
"content_scripts": [{
"js": ["content.js"],
"matches": ["https://example.com/*", "https://www.example.com/*"]
}]
}
and in background.js
I used
chrome.runtime.onInstalled.addListener(function(){
const pageUrl = {hostEquals: 'www.example.com'};
const {
onPageChanged,
PageStateMatcher,
ShowPageAction
} = chrome.declarativeContent;
onPageChanged.removeRules(undefined, function(){
onPageChanged.addRules([{
conditions: [new PageStateMatcher({pageUrl})],
actions: [new ShowPageAction()]
}]);
});
});
this works fine and the icon gets greyed out except on https://example.com. When migrating, the manifest looks like
{
"manifest_version": 3,
"name": ...,
"description": ...,
"version": ...,
"permissions": ["storage", "tabs", "declarativeContent", "activeTab"],
"background": {"service_worker": "service-worker.js"},
"action": {
"default_icon": { ... },
"default_popup": "popup/index.html"
},
"icons": { ... },
"content_scripts": [{
"matches": ["*://*.example.com/*"],
"js": ["content/detect-theme.js"]
}]
}
I cannot seem to get this to work properly. I've tried adding host_permissions
, removing the declarativeContent
-related code (as it doesn't seem to affect the icon whatsoever) but the extension stays available on all hosts. I know I can use the chrome.action.enable
and chrome.action.disable
methods to simulate this behavior but it seems overkill for such a simple use-case.
Actually, the action being available even on other pages is not breaking by any means, but I would like to make it more clear to my users that the extension only does things on https://example.com and nowhere else. Perhaps this is not even the right approach; if it isn't, I accept that as an answer as well.
TLDR; how do I only enable the (page-)action on a specific host with manifest v3?
Had the same issue myself, and I just solved it!
I fixed it by disabling the extension in the handler before adding the activation rule. I've removed the actual handler for brevity.
chrome.runtime.onInstalled.addListener(() => {
chrome.action.disable(); // The important line!
// actual handler...
});
I would guess that ShowPageAction
doesn't disable the extension by default anymore.