Home > Mobile >  Chrome Extension: Fetching the value of a DOM element
Chrome Extension: Fetching the value of a DOM element

Time:02-02

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;
  });
});
  • Related