I am trying to get into chrome extension development and want to make an extension which highlights a specific word on every page from a background script.
If I give my extension the activeTab permission, it is listed as "Access requested" and I need to invoke it by opening the popup, then after reloading the page it will highlight the word.
The documentation says "essentially, activeTab grants the tabs permission temporarily", so I switched to giving the tabs permission because I don't want to open the popup every time I visit a new website. However, now the extension is listed as "no access needed" and the highlighting does not work regardless of whether I invoke the popup or not.
Here is my service-worker background.js:
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab){
if (changeInfo.status == 'complete') {
chrome.scripting.executeScript({
target: { tabId: tabId },
function: highlightwords,
});
}
})
function highlightwords(){
var list = document.getElementsByTagName("p")
var search_words = ["the", "it", "you"]
var words = []
for(var i = 0; i < list.length; i++){
var words = list[i].textContent.split(' ')
for (var j = 0; j < words.length; j++) {
if (search_words.includes(words[j])) {
console.log(words[j]);
var elem = document.createElement("span")
elem.textContent = words[j]
elem.style.color = "red"
words[j]=elem.outerHTML
}
}
list[i].innerHTML = words.join(' ')
}
}
manifest.json:
{
"name": "Getting Started Example",
"description": "Build an Extension!",
"version": "1.0",
"manifest_version": 3,
"background": {
"service_worker": "background.js"
},
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "/images/get_started16.png",
"32": "/images/get_started32.png",
"48": "/images/get_started48.png",
"128": "/images/get_started128.png"
}
},
"icons": {
"16": "/images/get_started16.png",
"32": "/images/get_started32.png",
"48": "/images/get_started48.png",
"128": "/images/get_started128.png"
},
"options_page": "options.html",
"permissions": ["storage", "scripting", "tabs"]
}
I'd be very grateful for any hint on what's going wrong here or which alternatives there are (apart from using manifest v2, which probably doesn't have much of a future, at least in Chrome).
The only purpose of the tabs
permission is to show url
in changeInfo
and tab
objects e.g. in chrome.tabs.onUpdated event. You don't use it and you don't need it for this task.
Remove tabs
and scripting
permissions, remove the background worker.
Declare a content script in manifest.json
"content_scripts": [{
"matches": ["*://*/*"],
"js": ["content.js"]
}]
content.js will run in all http/https sites (this is what the first *
in *://*/*
means) and highlight the text.
P.S. Note that your current code destroys event listeners added by the page to any nested elements inside p
because you assign to innerHTML
. This is bad. A much better approach is to replace the matching parts of text inline by using DOM methods createTreeWalker and splitText, example, or just use mark.js.