I'm trying to build an extension, and I'm having trouble injecting a function.
This is the link that I'm trying to work on, I suspect that the blob at the start is the problem.
blob:https://web.whatsapp.com/29d92fb3-d8e1-4c84-89af-b51668f5d2b3
This is my manifest.json file:
{
"name": "Image rotator",
"version": "1.0",
"manifest_version": 3,
"description": "An extension to rotate images in web page.",
"background": {
"service_worker": "src/background.js"
},
"permissions": ["contextMenus","scripting","storage", "declarativeContent", "activeTab","<all_urls>"],
"host_permissions": [
"*://web.whatsapp.com/*"
]
}
This is my background.js file:
chrome.runtime.onInstalled.addListener(() => {
chrome.contextMenus.create({
"id": "rotateImage",
"title": "Rotate Image",
"contexts": ["image"]
})
});
function injectedFunc() {
document.getElementsByTagName("img").style.transform = "rotate(90deg)";
};
try {
chrome.contextMenus.onClicked.addListener((tab) => {
chrome.scripting.executeScript({
target: {
tabId: tab.id
},
function: injectedFunc
});
});
} catch (e) {
console.error(e);
}
In this version, I get this error:
Error in event handler: TypeError: Error in invocation of scripting.executeScript(scripting.ScriptInjection injection, optional function callback): Error at parameter 'injection': Error at property 'target': Missing required property 'tabId'.
If I change the onClicked method to this version:
try{
chrome.contextMenus.onClicked.addListener((info, tab) => {
if(info.menuItemId === "rotateImage"){
chrome.scripting.executeScript({
target: {tabId: tab.id},
function: injectedFunc
});}
});
} catch (e) {
console.error(e);
}
I get this error:
Uncaught (in promise) Error: Cannot access contents of the page. Extension manifest must request permission to access the respective host.
The second variant was the correct one, according to this I needed to add "match_origin_as_fallback": true,
to the manifest.json file inside "content_script" to make the browser be able to read the blob URL.
But it still didn't work, I needed to add the injected code to a different file than the background.js.
With some help from Reddit (Thanks Ibrahim_AA), the sendMessage and onMessage API did the work. Here is the full solution:
manifest.json:
{
"name": "Image rotator",
"version": "1.0",
"manifest_version": 3,
"description": "An extension to rotate images in web page.",
"background": {
"service_worker": "src/background.js"
},
"permissions": ["contextMenus","scripting"],
"host_permissions": [
"*://web.whatsapp.com/*"
],
"content_scripts": [
{
"matches": ["*://web.whatsapp.com/*"],
"match_origin_as_fallback": true,
"js": ["contentScript.js"]
}
]
}
background.js:
chrome.runtime.onInstalled.addListener(() => {
chrome.contextMenus.create({
"id": "rotateImage",
"title": "Rotate Image",
"contexts": ["image"]
})
});
try{
chrome.contextMenus.onClicked.addListener((info, tab) => {
if(info.menuItemId === "rotateImage"){
chrome.tabs.query({active: true, currentWindow: true}, function (tabs) {
chrome.tabs.sendMessage(tabs[0].id, {
type: "rotateImage",
});
});
}
});
} catch (e) {
console.error(e);
}
contentScript.js
function rotateImage() {
document.getElementsByTagName("img")[0].style.transform = "rotate(90deg)";
};
chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
if (msg.type === 'rotateImage') {
rotateImage();
}
});
Hope it helps anyone that comes across this problem.