I\'m writing my first Chrome Extension. I\'ve used permission, but I\'m seeing my button everywhere.
How can I only show the button on the addresses I\'m writing th
Although the answer from @Sorter works, it is not the best way to solve the problem.
First and foremost, it does not always work. If the page used history.pushState
, the page action will disappear and not come back until you trigger the onUpdated
or onHighlighted
event again Chromium issue 231075.
Secondly, the method is inefficient, because it's triggered for every update of tab state on all pages.
The most efficient and reliable way to get a page action to appear on certain domains is to use the declarativeContent API. This is only available since Chrome 33. Before that, the webNavigation API was the most suitable API. The advantage of these API over the method using the tabs
API is that you can safely use event pages, because you can declare URL filters. With these URL filters, the events will only be triggered if you navigate to a page that matches the URL filters. Consequently, your extension/event page will not be activated until really needed (= no wasted RAM or CPU).
Here's a minimal example (background.js
) using the webNavigation
API:
function onWebNav(details) {
if (details.frameId === 0) {
// Top-level frame
chrome.pageAction.show(details.tabId);
}
}
var filter = {
url: [{
hostEquals: 'example.com'
}]
};
chrome.webNavigation.onCommitted.addListener(onWebNav, filter);
chrome.webNavigation.onHistoryStateUpdated.addListener(onWebNav, filter);
manifest.json
:
{
"name": "Name ",
"version": "1",
"manifest_version": 2,
"background": {
"scripts": ["background.js"],
"persistent": false
},
"page_action": {
"default_title": "Only visible on stackoverflow.com"
},
"permissions": [
"webNavigation"
]
}
If you target Chrome 33 and higher, then you can also use the declarativeContent API instead. Simply replace the "webNavigation" permission with "declarativeContent", and use the following background script (background.js):
chrome.runtime.onInstalled.addListener(function() {
chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
chrome.declarativeContent.onPageChanged.addRules([{
conditions: [
new chrome.declarativeContent.PageStateMatcher({
pageUrl: {
hostEquals: 'example.com'
}
})
],
actions: [new chrome.declarativeContent.ShowPageAction()]
}]);
});
});
In both examples, I used a UrlFilter that matches the example.com
domain.
Create background.js which checks for updated and highlighted tab.
function checkForValidUrl(tabId, changeInfo, tab) {
// If 'example.com' is the hostname for the tabs url.
var a = document.createElement ('a');
a.href = tab.url;
if (a.hostname == "example.com") {
// ... show the page action.
chrome.pageAction.show(tabId);
}
};
// Listen for any changes to the URL of any tab.
chrome.tabs.onUpdated.addListener(checkForValidUrl);
//For highlighted tab as well
chrome.tabs.onHighlighted.addListener(checkForValidUrl);
Create popup.html and popup.js in the similar manner.
You can use the variables defined in background.js in content scripts (popup.js) with
chrome.extension.getBackgroundPage().variableName
Here's the example extention download link.
For your reference and ease, here's the sample manifest.json file
{
"manifest_version": 2,
"name": "Example Extension",
"version": "1.0",
"background": {
"scripts": ["background.js"]
},
"page_action":{
"default_icon": "images/icon_16.png",
"default_popup": "popup.html",
"default_title": "Title for the extension"
},
"permissions": [
"tabs"
]
}
An Updated Way:
I use the following with great success:
chrome.tabs.onUpdated.addListener(function(tabId, info, tab) {
var url = info.url || tab.url;
if(url && url.indexOf('example.com') > -1)
chrome.pageAction.show(tabId);
else
chrome.pageAction.hide(tabId);
});