How to disable (gray out) page action for Chrome extension?

Viewed 1715

I want the Chrome extension icon to be disabled (grayed out) on all pages except for pages on docs.google.com. This is my code in background.js.

'use strict';

chrome.runtime.onInstalled.addListener(function() {
  chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
    chrome.declarativeContent.onPageChanged.addRules([{
      conditions: [new chrome.declarativeContent.PageStateMatcher({
        pageUrl: { urlContains: 'docs.google' },
      })
      ],
          actions: [new chrome.declarativeContent.ShowPageAction()]
    }]);
  });
});

From the documentation for pageActions this should result in my extension icon being gray on all pages except for ones that have docs.google in the URL. But the icon is active (NOT grayed out) on all pages. Tapping it on non docs.google pages results in it not doing anything, but I want it to be grayed out in the first place.

Any ideas on this?

2 Answers

This is a bug in Chrome and so far it's unclear if it's even fixable.

Meanwhile, you can maintain the icon yourself:

  1. make a grayscale version of the icon(s) in any image editor and save them separately.

  2. specify the gray icon in manifest.json:

    • ManifestV2:

      "page_action": {
        "default_icon": { "16": "icons/16-gray.png", "32": "icons/32-gray.png" }
      }
      
    • ManifestV3 uses action instead of page_action

      "action": {
        "default_icon": { "16": "icons/16-gray.png", "32": "icons/32-gray.png" }
      }
      
  3. set the normal icon using SetIcon action:

    chrome.declarativeContent.onPageChanged.removeRules(async () => {
      chrome.declarativeContent.onPageChanged.addRules([{
        conditions: [
          new chrome.declarativeContent.PageStateMatcher({
            pageUrl: { hostPrefix: 'docs.google.' },
          }),
        ],
        actions: [
          new chrome.declarativeContent.SetIcon({
            imageData: {
              16: await loadImageData('icons/16.png'),
              32: await loadImageData('icons/32.png'),
            },
          }),
          chrome.declarativeContent.ShowAction
            ? new chrome.declarativeContent.ShowAction()
            : new chrome.declarativeContent.ShowPageAction(),
        ],
      }]);
    });
    
    // SVG icons aren't supported yet
    async function loadImageData(url) {
      const img = await createImageBitmap(await (await fetch(url)).blob());
      const {width: w, height: h} = img;
      const canvas = new OffscreenCanvas(w, h);
      const ctx = canvas.getContext('2d');
      ctx.drawImage(img, 0, 0, w, h);
      return ctx.getImageData(0, 0, w, h);
    }
    

If you use manifest version 2, just need to declare the colored icon in page_action, rather than the gray one.

// manifest.json
 "manifest_version": 2
 "page_action": {
   "default_icon": "icon-color.png"
 },

And then the icon will be gray in the URL out of permissions and matches. You can see the description at pageAction/#manifest.

But in manifest v3, it seems the configures above no works longer.

Related