Search code examples
javascriptgoogle-chrome-extension

How to prevent chrome extension to run on chrome://


Absolute JS beginner here, please be gentle and pardon my ignorance.

In the background service_worker (background.js) of a Chrome extension I'm trying to build (manifest_version: 3) I use the chrome.action API to control the toolbar icon's behaviour.

chrome.action.onClicked.addListener(async function (tab) {  
    chrome.scripting.executeScript({
        target: {tabId: tab.id},
        files: ['iconClicked.js']
    });
});

Now when a user clicks the icon whilst being on chrome://extensions, this produces an error:

Uncaught (in promise) Error: Cannot access a chrome:// URL

What can I do to prevent my script to run on chrome:// URLs?

I tried wrapping it in a condition checking the current URL:

if (window.location.href.includes("urls/where/i/want/my/script/to/run") == true) {
    chrome.action.onClicked.addListener(async function (tab) {
        chrome.scripting.executeScript({
            target: {tabId: tab.id},
            files: ['iconClicked.js']
        });
    });
};

But, alas, apparently on chrome:// "window" is not defined:

ReferenceError: window is not defined

How else can I effectively prevent my extension from throwing errors on chrome:// (ideally w/out using jQuery or any other libraries)?

Any hints are greatly appreciated!


Solution

  • The background script runs as a service worker so it has no relation to location of a web page.

    Since executeScript returns a Promise by default so you can catch it to ignore the error:

    chrome.action.onClicked.addListener(async tab => {
      await chrome.scripting.executeScript({
        target: {tabId: tab.id},
        files: ['iconClicked.js'],
      }).catch(() => {});
    });
    

    Or wrap in try with await:

    chrome.action.onClicked.addListener(async tab => {
      try {
        const results = await chrome.scripting.executeScript({
          target: {tabId: tab.id},
          files: ['iconClicked.js'],
        });
        // console.log(results);
      } catch (e) {
        // ignoring the error
      }
    });
    

    And for the sake of completeness, ManifestV3 can also be used with callbacks:

    chrome.action.onClicked.addListener(tab => {
      chrome.scripting.executeScript({
        target: {tabId: tab.id},
        files: ['iconClicked.js'],
      }, () => chrome.runtime.lastError); // ignoring the error
    });