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

Chrome extension error with getSelection and chrome.tabs.create


manifest.js

{
    "manifest_version": 3,
    "version": "1.0",
    "name": "Gramotey",
    "content_scripts":[
        {
         "matches":["<all_urls>"],
         "js":["main.js"]
        }
    ],
    "background":
    {
    "service_worker": "background.js"
    },
    "commands": {
        "search_with_gramota": {
          "suggested_key": {
            "default": "Alt+Shift+5",
            "mac": "Command+Shift+5"
          },
          "description": "Общий поиск на грамоте"
        }
      },
      "permissions": ["scripting", "activeTab", "tabs"],
      "host_permissions": ["<all_urls>"]
}

background.js

chrome.commands.onCommand.addListener((command) =>
{
    if (command == "search_with_gramota")
    {
        chrome.tabs.query({ currentWindow: true, active: true }, function (tab) {
            chrome.scripting.executeScript(
                {
                target: {tabId: tab[0].id},
                function: () => {
                    function makeUrl(){
                    var sUrl = "https://gramota.ru/poisk?query="
                    var selected = getSelection().toString()
                    sUrl =  sUrl + selected
                    return sUrl
                    }
                        chrome.tabs.create({url: makeUrl()});
                },

            });   
        });
    };
});

Any time I try to execute the shortcut only the following message appears in the console enter image description here

I expect this script to open a new tab with url including currently selected text.


Solution

  • The error says chrome.tabs is undefined. This is because the function is injected by executeScript into the context of the content script in the tab, where most of chrome namespace is not exposed.

    The solution is to return the value from the injected function and use it outside as the result of executeScript:

    chrome.commands.onCommand.addListener(async command => {
      const text = await getSelectedText();
      if (text) {
        chrome.tabs.create({
          url: 'https://example.com/foo?' + new URLSearchParams({query: text}),
        });
      }
    });
    
    async function getSelectedText() {
      const [tab] = await chrome.tabs.query({ currentWindow: true, active: true });
      const [{ result }] = await chrome.scripting.executeScript({
        target: { tabId: tab.id },
        func: () => getSelection().toString(),
      }).catch(err => {
        // console.log(err);
      });
      return result;
    }