0

I am trying to create a chrome extension that sends the DOM body from the active tab to some backend server, which will return some response which I will do later. However, I cannot figure out how send information via event listeners from the content-script to the service-worker. Heres the code I have now: Service-Worker:

chrome.runtime.onMessage.addListener( function(request, sender, sendResponse) {
  if (request.action === "submit") {
      console.log("submit stage 1")
      const response_tabs = sendMessageToActiveTab('sendDOM')
      console.log(response_tabs)
      const response_runtime = chrome.runtime.sendMessage({message: 'sendDOM', action: 'sendDOM'})
      console.log(response_runtime)


async function sendMessageToActiveTab(message) {
  const [tab] = await chrome.tabs.query({ active: true, lastFocusedWindow: true });
  const response = await chrome.tabs.sendMessage(tab.id, {message: message, action: 'sendDOM'});
  return response
}

Content-Script:

chrome.tabs.addListener(async function(request, sender, sendResponse) {
  if (request.action === "sendDOM") {
    const article = await document.querySelector("body");
    console.log("article: ", article);
    sendResponse(article);
    return article;
  }
});
chrome.runtime.onMessage.addListener(function(message, sender) {
  if (message.action === "sendDOM") {
    const article = await document.querySelector("body");
    console.log("article: ", article);
    sendResponse(article);
    return article;
  }
});

And manifest.json:

{
  "manifest_version": 3,
  "name": "Nuntia",
  "version": "1.0",
  "permissions": ["activeTab","tabs"],  
  "action": {
    "default_popup": "popup.html"
  },
  "background": {
    "service_worker": "service-worker.js"
  },
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content-script.js"]
    }
  ],
  "externally_connectable": {
    "matches": ["*://*.google.com/*"]
  },
  "host_permissions": [
    "http://*/*",
    "https://*/*"
  ]
}

Any advice on how to go about doing this or fixing my approach would be greatly appreciated!

So far I have tried different ways to make the two js files communicate with each other such as chrome.tabs and chrome.runtime. Both are returning this same error

jbgg
  • 1
  • 1
    1) Remove the entire chrome.tabs.addListener block from the content script. 2) You can't send DOM elements via messaging. Send the element's textContent or innerHTML. 3) Remove `await` 4) You need to [re-inject content scripts explicitly](/q/10994324) after reloading/installing the extension. 5) Don't use ChatGPT. – wOxxOm Jul 02 '23 at 18:58
  • 5) Don't use ChatGPT. <- This – Thomas Mueller Jul 02 '23 at 19:02

1 Answers1

0

chrome.runtime.sendMessage accepts as the last argument a callback which is called when the other end executes sendResponse (the third parameter to the chrome.runtime.onMessage.addListener callback).

The same goes for chrome.tabs.sendMessage. Also, there is no chrome.tabs.addListener.

So, to send messages from the content script, you'll do something like this:

[the background service].

chrome.runtime.onMessage.addListener((sender, message, sendResponse) => {
  ...
});

[content script]

chrome.runtime.sendMessage({ something: 'to be sent' }, (response) => {
  ...
});

Then, the background script will process the message and call.

sendResponse({ message: 'processed' });

Which will trigger the function passed as the second argument to chrome.runtime.sendMessage in the content script and response will be { message: 'processed' }

About Error: Could not establish connection. Receiving end does not exist. That can happen in a few situations.

The most common one is if inside the callback to chrome.runtime.onMessage.addListener you perform and async task and then call sendResponse.

To prevent that, you need to return true from this callback:

chrome.runtime.onMessage.addListener((sender, message, sendResponse) => {
  setTimeout(() => sendResponse({..}), 1000);
  return true;
});

This informs the system that sendResponse will be called after the callback function returns.

Titus
  • 22,031
  • 1
  • 23
  • 33