javascriptgoogle-chrome-extensiongetselection

selection API getSelection() not working in the context of a Chrome extension


I am creating an extension where the context menu has a new option. When I right click in text inside the webpage, and context menu is shown, and I click the new context menu option, I want to get the innerText of the html element whose text I right clicked. I was able to successfully use window.getSelection() in a simple script in an HTML page in the following way:

window.oncontextmenu = (e) => {
    s = window.getSelection();
    const wholeText = s.focusNode.data;
    ...
}

However, when I try to do it in the context of a chrome extension, window.getSelection() just returns an array with an empty object. This is the code for extension manifest and script:

{
  "manifest_version": 2,
  "name": "Test scan text",
  "version": "1.0",
  "description": "Find email address in the right clicked text",

  "icons": {
    "16": "images/icon-16.png",
    "32": "images/icon-32.png",
    "48": "images/icon-48.png",
    "128": "images/icon-128.png"
  },
  "permissions": [
    "contextMenus", "activeTab", "tabs"
  ],
  "background": {
    "scripts": ["background.js"]
  }
}

the script:

function genericOnClick(info, tab) {

        let s;
        chrome.tabs.executeScript(tab.id, { code: `window.getSelection()` }, (result) => {
            console.log(result);
            console.log(result.focusNode.data);
        });
  }

  function theCallback() {
    console.log('something went wrong');
  }

chrome.runtime.onInstalled.addListener(async () => {

        chrome.contextMenus.create(
            {
                "title": 'Check if an email',
                "contexts": ["all"],
                "id": "contextMenu123",
                "onclick": genericOnClick
            },
            theCallback
        ); 
  });

What is wrong in the context of chrome extension? This is the output obtained:

[{…}]0: {}[[Prototype]]: Objectconstructor: ƒ Object()hasOwnProperty: ƒ hasOwnProperty()isPrototypeOf: ƒ isPrototypeOf()propertyIsEnumerable: ƒ propertyIsEnumerable()toLocaleString: ƒ toLocaleString()toString: ƒ toString()valueOf: ƒ valueOf()__defineGetter__: ƒ __defineGetter__()__defineSetter__: ƒ __defineSetter__()__lookupGetter__: ƒ __lookupGetter__()__lookupSetter__: ƒ __lookupSetter__()__proto__: (...)get __proto__: ƒ __proto__()set __proto__: ƒ __proto__()length: 1[[Prototype]]: Array(0)at: ƒ at()concat: ƒ concat()constructor: ƒ Array()copyWithin: ƒ copyWithin()entries: ƒ entries()every: ƒ every()fill: ƒ fill()filter: ƒ filter()find: ƒ find()findIndex: ƒ findIndex()findLast: ƒ findLast()findLastIndex: ƒ findLastIndex()flat: ƒ flat()flatMap: ƒ flatMap()forEach: ƒ forEach()includes: ƒ includes()indexOf: ƒ indexOf()join: ƒ join()keys: ƒ keys()lastIndexOf: ƒ lastIndexOf()length: 0map: ƒ map()pop: ƒ pop()push: ƒ push()reduce: ƒ reduce()reduceRight: ƒ reduceRight()reverse: ƒ reverse()shift: ƒ shift()slice: ƒ slice()some: ƒ some()sort: ƒ sort()splice: ƒ splice()toLocaleString: ƒ toLocaleString()toString: ƒ toString()unshift: ƒ unshift()values: ƒ values()Symbol(Symbol.iterator): ƒ values()Symbol(Symbol.unscopables): {at: true, copyWithin: true, entries: true, fill: true, find: true, …}[[Prototype]]: Object
_generated_background_page.html:1

Error handling response: TypeError: Cannot read properties of undefined (reading 'data')

Solution

  • It doesn't seem to be able to return the object, so I suggest the following changes.

      chrome.tabs.executeScript(tab.id, { code: `window.getSelection().focusNode.data` }, (result) => {
          console.log(result);
          // console.log(result.focusNode.data);
      });