I'm making a chrome extension to gather data from a webpage. When I try to use document.querySelectorAll() it gets the DOM from the popup, not the current webpage. I tried using chrome's messaging system to request and send back the HTML but it doesn't work and gives me errors.
Here's the important files:
manifest.json
{
"name": "Name",
"description": "Description",
"version": "1.0",
"manifest_version": 3,
"permissions": ["storage", "activeTab", "scripting", "tabs"],
"host_permissions": [
"*://*.website.com/*"
],
"content_scripts": [
{
"matches": ["*://*.website.com/*"],
"js": ["content_script.js"]
}
],
"action": {
"default_popup": "popup.html",
"default_icon": {
"32": "/images/icon.png"
}
},
"icons": {
"32": "/images/icon.png"
}
}
popup.js (runs inside popup.html)
function fetchData() {
chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "fetchData"}, (response) => {
console.log(response);
});
});
}
content_script.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.greeting === "fetchData") {
sendResponse(document.querySelectorAll(".class"));
}
}
);
The error I get from the message sending is "Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist."
When I turn the NodeList to an array, there are no console errors, but it returns a list of "[object Object]".
Please let me know if there's a way to do this. I'm just using vanilla js.
The problem is that NodeList can not by default be serialized into JSON in Chrome.
from mdn web docs
sendResponseA function to call, at most once, to send a response to the message. The function takes a single argument, which may be any serializable object (see Data cloning algorithm). This argument is passed back to the message sender.
You should refer to this stackoverflow answer to json serialize a NodeList before sending it back to popup.js