I'm building my first Chrome extension and my goal is to fetch the value of a DOM element from the extension popup by the click of a button. I'm basically following the exact documentation on how to send a message but keep getting:
'Error: Could not establish connection. Receiving end does not exist.'
For now, I'm not even trying to return DOM data; just trying to console.log a message triggered by the extension and returned by the content script. Any idea what the issue might be?
Here's my setup:
manifest.jst
{
"name": "Fetch Test",
"description": "Fetch data from DOM",
"version": "1.0",
"manifest_version": 3,
"action": {
"default_popup": "popup.html"
},
"permissions": ["activeTab", "tabs", "scripting"],
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content_script.js"]
}
]
}
popup.html
<html>
<body>
<div >
<button id="fetch-button">Fetch</button>
</div>
</body>
</html>
<script src="popup.js"></script>
popup.js
document.getElementById("fetch-button").addEventListener("click", function () {
(async () => {
const [tab] = await chrome.tabs.query({
active: true,
lastFocusedWindow: true,
});
const response = await chrome.tabs.sendMessage(tab.id, {
greeting: "hello",
});
console.log(response);
})();
});
content_script.js
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
console.log(
sender.tab
? "from a content script:" sender.tab.url
: "from the extension"
);
if (request.greeting === "hello") sendResponse({ farewell: "goodbye" });
});
CodePudding user response:
You need to include the javascript files in your popup.html file like so. Does that help?
<html>
<head>
<script src="popup.js"></script>
<script src="content_script.js"></script>
</head>
<body>
<div >
<button id="fetch-button">Fetch</button>
</div>
</body>
</html>
CodePudding user response:
You can try to do a long-lived message passing.
popup.js
const extensionContentScriptPort = () => {
return (async function () {
const currentTabQuery = {
active: true,
currentWindow: true,
};
const currentTabId = (await chrome?.tabs?.query(currentTabQuery))?.[0].id;
return chrome?.tabs?.connect(currentTabId, {
name: 'EXTENSION_CONTENTSCRIPT',
});
})();
};
// Add Event Listener for receiving messages
extensionContentScriptPort.then(port =>
port.onMessage.addListener((extensionContentScriptMsg) => {
console.log(extensionContentScriptMsg);
});
);
// Post message to content script
document.getElementById("fetch-button").addEventListener("click", function () {
extensionContentScriptPort?.then(port => {
port.postMessage({
greeting: "hello"
})
});
});
content_script.js
chrome?.runtime?.onConnect?.addListener(function (extensionContentScriptPort) {
console.assert(extensionContentScriptPort?.name === 'EXTENSION_CONTENTSCRIPT');
extensionContentScriptPort?.onMessage?.addListener(function (
extensionContentScriptMsg,
) {
if (extensionContentScriptMsg?.greetings === "hello") {
return extensionContentScriptPort?.postMessage({
greetings_reply: "Hey, there!"
})
}
}
}
CodePudding user response:
This sample uses executeScript
to get document.title.
manifest.json
{
"name": "Get document.title",
"version": "1.0",
"manifest_version": 3,
"permissions": [
"scripting"
],
"host_permissions": [
"<all_urls>"
],
"action": {
"default_popup": "popup.html"
}
}
popup.html
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
* {
font-size: x-large;
}
</style>
</head>
<body style="min-width:300px">
<div id="title"></div><br>
<script src="popup.js"></script>
</body>
</html>
popup.js
const getTitle = () => {
console.log("getTitle() = " document.title);
return document.title;
}
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
console.log("Execute Script");
chrome.scripting.executeScript({
target: { tabId: tabs[0].id },
func: getTitle
}, (result) => {
console.log("Recv result = " result[0].result);
document.getElementById("title").innerText = result[0].result;
});
});