8

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?

adorai
  • 93
  • 1
  • 4

3 Answers3

12

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);
    }
    
wOxxOm
  • 65,848
  • 11
  • 132
  • 136
  • I read the bug description and the comments: When will this bug likely be resolved? – Stephan Pillhofer Nov 09 '20 at 12:37
  • for me it crashed on "await" - Uncaught SyntaxError: Unexpected identifier. Was it because of the manifest v2? – user2809176 Jun 05 '21 at 15:51
  • after calling "chrome.action.setIcon(someAnotherIcon)" in "chrome.action.onClicked" it stops working (icon not chaged anymore, someAnotherIcon showed) why can that be? -.- – user2809176 Jun 08 '21 at 12:08
  • 1
    Sounds like a bug or an inherent limitation of the API. – wOxxOm Jun 08 '21 at 12:10
  • 1
    For Edge, the colored icon is greyed out iff there is no content.js. But add that and it is coloured even when hidden. Wasted quite a bit of time on this. – Tuntable Jun 17 '21 at 10:59
  • Tested with `manifest v3`, and works perfectly! – robe007 Oct 18 '21 at 01:58
  • @velkoon, I've just verified the code works correctly in an MV3 extension (there's also robe007's comment) so you can debug it yourself or ask a new question with a full [MCVE](/help/mcve) because comments are not for extended discussions. – wOxxOm Feb 15 '22 at 22:38
  • To Googlers: Note you must declare `"permissions": ["declarativeContent"]` in your `manifest.json`. (And for that matter, remember to declare in your `manifest.json` whatever permissions are listed at the top of the respective official doc, like on this one: https://developer.chrome.com/docs/extensions/reference/declarativeContent/ ) – velkoon Feb 15 '22 at 23:20
1

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.

Soyaine
  • 107
  • 1
  • 11
1

Chrome documents this behavior in their docs: https://developer.chrome.com/docs/extensions/reference/action/#emulating-pageactions-with-declarativecontent. The following describes how to achieve it in manifest v3.

// background.js

chrome.runtime.onInstalled.addListener(() => {
  // disable the action by default
  chrome.action.disable();

  // remove existing rules so only ours are applied
  chrome.declarativeContent.onPageChanged.removeRules(undefined, () => {
    // add a custom rule
    chrome.declarativeContent.onPageChanged.addRules([
      {
        // define the rule's conditions
        conditions: [
          new chrome.declarativeContent.PageStateMatcher({
            pageUrl: { hostSuffix: "reddit.com" },
          }),
        ],
        // show the action when conditions are met
        actions: [new chrome.declarativeContent.ShowAction()],
      },
    ]);
  });
});

This will require the declarativeContent permission in manifest.json

{
  ...
  "permissions": ["declarativeContent"]
  ...
}
TestWell
  • 734
  • 10
  • 19
  • This does not gray out the icon, it just disables the action from being fired when clicked. – Jeph Jun 16 '23 at 18:50
  • @Jeph it will gray it out for sites that do not match the pattern you define in manifest.json. If you're not seeing it work, double check the match pattern and make sure you're visiting a site that it should not match. This very approach is used for this extension and it grays out fine: https://github.com/dan-lovelace/reddit-theme-studio/blob/main/assets/manifest-v3.json – TestWell Jun 18 '23 at 12:01