Search code examples
javascriptgoogle-chromegoogle-chrome-extensionchrome-extension-manifest-v3

Getting selected text in a Chrome extension


I'm trying to create a Chrome extenstion that allows the user to get the selected text of a web page after clicking on a button and then log this text in the console.

But my code is working only if the text is selected from the HTML pop-up. If i select a text from a random webpage and then click the "Save" button, then a blank line is printed in the console.

I guess my content.js file is not able to interact with the web page when the extension popup is displayed but I don't know how to resolve that. I know there are other similar questions but nothing I tried (message passing between different .js files for example) worked.

Here are my files :

manifest.json :

{
"manifest_version": 3,
"version": "1.0",
"name": "test",
"action": {
    "default_popup": "index.html"
},
"permissions": [
    "tabs",
    "notifications"
],
"content_scripts": [
{   "matches": ["<all_urls>"],
    "js" : ["content.js"]}
],
"background":
{
"service_worker": "background.js"
}}

index.html :

<html>
<head>
    <link rel="stylesheet" href="index.css">
</head>
<body>
    <p>Just some text.</p>
    <button id="save-btn">SAVE SELECTION</button>
    <script src="content.js"></script>
</body>
</html>

content.js :

const saveBtn = document.getElementById("save-btn")

saveBtn.addEventListener("click", function(){
console.log(window.getSelection().toString())
})

Solution

    1. Remove content.js from index.html. Content scripts are for web pages, not for extension pages such as the popup.

    2. Create index.js and load it in index.html:

        <script src="index.js"></script>
      </body>
      
    3. index.js:

      document.getElementById("save-btn").onclick = async () => {
        const [tab] = await chrome.tabs.query({active: true, currentWindow: true});
        let result;
        try {
          [{result}] = await chrome.scripting.executeScript({
            target: {tabId: tab.id},
            func: () => getSelection().toString(),
          });
        } catch (e) {
          return; // ignoring an unsupported page like chrome://extensions
        }
        document.body.append('Selection: ' + result);
      };
      
    4. edit manifest.json to allow code injection in the active tab on click:

      "permissions": ["scripting", "activeTab"]
      

    Note that the popup is a separate window so it has its own separate devtools and console: right-click inside the popup and select "inspect" in the menu.