I am making chrome extension but I am getting error of "Cannot read properties of undefined (reading 'sendMessage')"
My content.js file is
document.addEventListener("visibilitychange", event => {
if (document.visibilityState === "visible") {
chrome.runtime.sendMessage({ mycontent: "from content script" })
console.log("tab is active")
} else {
chrome.runtime.sendMessage({ mycontent: "from content script" })
console.log("tab is inactive")
}
})
And my background.js file is
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
if (message.mycontent) {
}
})
and my manifest.json file is
{
"name": "Ju Close Chrome",
"description": "Build an Extension!",
"version": "1.0",
"manifest_version": 3,
"background": {
"service_worker": "background.js"
},
"content_security_policy": {
"extension_pages": "script-src 'self'; object-src 'self'"
},
"permissions": ["notifications", "storage", "alarms", "activeTab"],
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"js": ["jquery.js", "content.js"]
}
],
"action": {
"default_popup": "popup.html"
}
}
Related
Error when Migrating Manifest V2 to Manifest V3
with the error message: Could not establish connection. Receiving end does not exist.
It occurred between sendMessage and onMessage
manifest.js
{
"update_url": "https://clients2.google.com/service/update2/crx",
"manifest_version": 3,
"name": "AAANAME2.7",
"version": "2.7",
"description": "AAA NAME",
"action": {
"default_icon": "logo_19.png",
"default_popup": "popup.html"
},
"default_locale": "ko",
"icons": {
"16": "logo_16.png",
"19": "logo_19.png",
"48": "logo_48.png",
"128": "logo_128.png"
},
"background": {
"service_worker": "bg.js"
},
"options_page": "options.html",
"content_security_policy": {
"extension_pages": "script-src 'self'; object-src 'self'"
},
"content_scripts": [
{
"all_frames": false,
"css": [
"achecker.css"
],
"js": [
"lib/rainbowColor.js",
"lib/colorInspector.js",
"lib/KWAX.js",
"i18n.js",
"lib/jquery-3.6.0.min.js"
],
"matches": [
"http://*/*",
"https://*/*"
]
}
],
"permissions": [
"activeTab",
"tabs",
"contextMenus", // extension right click popup menu
"downloads",
"storage",
"tts"
],
"web_accessible_resources": [
{
"resources": [
"images/*.png",
"popup-attach-tagname.html",
"achecker.css"
],
"matches": [
"http://*/*",
"https://*/*"
]
}
]
}
content.js
const captureRequest = new Promise(function(resolve, reject) {
console.log("appId=" + appId);
chrome.runtime.sendMessage(appId, {
capture: "yes"
}, function(response) {
console.log('return from bg...')
if (!chrome.runtime.lastError) {
if (!response) {
console.log('Fail Capture')
reject(new Error('Fail Capture'));
} else {
console.log('succ Capture')
resolve(response)
}
} else {
console.log(chrome.runtime.lastError)
// returned : Could not establish connection. Receiving end does not exist."
}
});
});
bg.js
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.capture == "yes") {
chrome.tabs.captureVisibleTab(
null, {
format: "png",
quality: 100
},
function(dataUrl) {
sendResponse({
src: dataUrl
});
}
);
return true;
} else if (request.ignoreCommon) {
// some else
}
});
i'm trying to send a message from my content script to my popup script because i need to use popup DOM when a page is loaded, here's what i tried :
contentScript.js
window.addEventListener("load", function() {
chrome.runtime.sendMessage({
"action": "init"
});
})
popup.js
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
if (request.action == "init") {
alert('Initialisation demandée...')
} else {
alert('Je n\'ai pas compris')
}
})
manifest.json
{
"manifest_version": 2,
"name": "Youtube color modifier",
"description": "Change youtube colors",
"version": "1.0",
"page_action": {
"default_icon": "icon.png",
"default_title": "Youtube color modifier",
"default_popup": "popup.html"
},
"permissions": [
"activeTab"
],
"content_scripts": [{
"matches": ["<all_urls>"],
"js": ["contentScript.js"]
}]
}
Thank you for helping a noob :))
If you have a content script, it will be run everytime you (re)load the page, assuming that the page you are visiting is registered in the manifest.json.
So instead of this:
window.addEventListener("load", function() {
chrome.runtime.sendMessage({
"action": "init"
});
})
simply try this:
chrome.runtime.sendMessage({
"action": "init"
});
Here is my manifest.json file:
{
"manifest_version": 2,
"permissions": ["tabs", "storage", "webRequest", "<all_urls>"],
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["assets/js/jquery-3.3.1.min.js", "blocker.js"]
}
],
"background": {
"scripts": ["background.js"]
},
"options_ui": {
"page": "background-page.html",
"browser_style": true
}
}
and my blocker.js file:
function cleanPage(tabId, changeInfo, tabInfo) {
console.log("I am in cleanPage");
}
try {
console.log("browser : ");
console.log(browser);
console.log("browser.tabs : " + browser.tabs);
browser.tabs.onUpdated.addListener(cleanPage);
} catch(err) {
console.log("err : ", err);
}
And I get this error:
browser.tabs : undefined blocker.js:114:3
err : TypeError: "browser.tabs is undefined"
My setup:
- Mozilla Firefox 65.0.1
- Ubuntu 18.04
I don't really understand this error, since I'm doing exactly what is written in the Mozilla Tutorial. Does anyone know why this error does appear?
My blocker.js file was in the content_scripts. I moved it to the background_scripts and it worked.
Only the files from the background_scripts can access the browser.tabs API.
My new manifest.json file:
{
"manifest_version": 2,
"permissions": ["tabs", "storage", "webRequest", "<all_urls>"],
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": []
}
],
"background": {
"scripts": ["assets/js/jquery-3.3.1.min.js", "background.js", "blocker.js"]
},
"options_ui": {
"page": "background-page.html",
"browser_style": true
}
}
I'm working on an extension and I want the icon to change when the active tab or url changes. Here's what i have so far:
manifest.json
{
"manifest_version": 2,
"name": "Link2QR",
"description": "chrome_extension",
"version": "1.0",
"browser_action": {
"default_icon":"icon.png",
"default_popup": "popup.html"
},
"permissions": [
"activeTab",
"https://ajax.googleapis.com/",
"tabs"
],
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"]
}
]
}
content.js
if(onSupportedPageNeedChangeIcon) {
chrome.runtime.sendMessage({ "newIconPath" : "testimage.png" });
}
popup.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
chrome.browserAction.setIcon({
path: request.newIconPath,
tabId: sender.tab.id
});
});
You are handling the message in popup.js, which I suppose is running in the browser_action popup page.
popup.js thus only runs when the extension button is clicked.
You should instead handle it in background.js:
manifest.json
{
"manifest_version": 2,
"name": "test",
"version": "0.0.1",
"background": {
"scripts": ["background.js"]
},
"browser_action": {
"default_icon": {
"24": "icon.png",
"25": "icon.png"
}
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"]
}
]
}
background.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
chrome.browserAction.setIcon({
path: request.newIconPath,
tabId: sender.tab.id
});
});
I got result but it returns two alerts "Content: This is a test" but in scripts I send only 1 post.
It works perfect but two answers is too annoying. Help pls.
Manifest:
{
"name": "Test",
"version": "1.0",
"manifest_version": 2,
"description": "Test",
"background": {
"scripts": ["event.js"],
"persistent": true
},
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
"permissions": [ "tabs", "http://*/*", "https://*/*" ],
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"js": ["content.js"],
"run_at": "document_end",
"all_frames": true
}
],
"browser_action": {
"name": "Do Action",
"default_icon": "icon.png",
"default_popup": "popup.html"
}}
Popup script.js:
$("#myButton").click(function(){
chrome.tabs.getSelected(null, function(tab)
{
chrome.tabs.executeScript(tab.id, { file: "content.js" }, function()
{
var port = chrome.tabs.connect(tab.id, { name: "port-conn" });
port.postMessage({ data: "This is a test" });
port.onMessage.addListener(function (msg)
{
alert("Content: " + msg.answer);
});
});
});
}...
content.js:
chrome.extension.onConnect.addListener(function(port) {
port.onMessage.addListener(function(msg) {
port.postMessage({answer: msg.data});
});
});
Content.js is specified first in manifest so it is now loading when your extension is loaded. Then you are using it via executeScript so it runs the second time.
do these changes.
Popup script.js:
chrome.tabs.getSelected(null, function(tab){
var port = chrome.tabs.connect(tab.id, { name: "port-conn" });
port.onMessage.addListener(function (msg)
{
alert("Content: " + msg.answer);
});
$("#myButton").click(function(){
port.postMessage({ data: "This is a test" });
});
});
That is the point of messaging. if it did not work then you HAVE TO USE BACKGROUND SCRIPT AS WELL that just forwards message between content and popup
Problem solved.
In manifest
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"js": ["content.js"],
"run_at": "document_end",
"all_frames": true
}
],
it runs content.js on every page and
{ file: "content.js" }
Run it again in active tab. So thats why one tab run content twice.