Chrome Extension Manifest v3: Load content script only on click on extension icon (minimize permissions)
Asked Answered
E

3

6

I am migrating a functioning browser extension to manifest v3. The problem: I want the content script to be loaded only upon clicking on the browser extension icon. However, the script is always loaded. When I try to upload to the chrome store, I get the following message, which is what I want to avoid:

Because of the host permission, your extension may require an in-depth review that will delay publishing.

I suspect it has something to do with the "action", but I could not figure out on how to fix this. Here is the manifest:

{
    "manifest_version": 3,
    "name": "__MSG_extName__",
    "description": "__MSG_extDescription__",
    "key": "...",
    "version": "1.0.0",
    "icons": { ... },
    "background": {
        "service_worker": "/background.js"
    },
    "permissions": [
        "storage"
    ],
    "content_scripts": [
        {
            "matches": [
                "<all_urls>"
            ],
            "js": [
                "/content.js"
            ]
        }
    ],
    "web_accessible_resources": [
        {
            "resources": [
                "/assets/*",
                "/options.html"
            ],
            "matches": [
                "<all_urls>"
            ]
        }
    ],
    "options_page": "options.html",
    "action": {}
}

One last note: I assume that I need activeTab permission. But again, my problem is that I want to minimize the required permissions.

Thanks in advance!

Epiboly answered 18/5, 2022 at 20:10 Comment(1)
See programmatic injection in the documentation.Lunna
E
9

I eventually figured it out. Basically, I had to remove the "content_scripts" section. Instead, I need to inject the content script explicitly with the action handler. I was under the wrong assumption that I could constraint the content_scripts section with the right permissions.

For this to work, I had to set activeTab and scripting permissions, here the new permissions:

"permissions": [
    "storage",
    "activeTab",
    "scripting"
],

I already had an action handler in my service worker (background.js), which now looks like this:

chrome.action.onClicked.addListener(async (tab) => {
  await chrome.scripting.executeScript({
    target: { tabId: tab.id, allFrames: true },
    files: ["content.js"],
  });
  // Do other stuff...
});

I hope this answer will help someone, somewhere!

Epiboly answered 19/5, 2022 at 7:40 Comment(1)
Note that this means upon clicking the browser extension button, it will re-inject that content script, this can cause problems.Monoclinous
S
1

From my experience still you can use content_scripts but you should add the permission scripting.

See my manifest json below.

  {
  "manifest_version": 3,
  "name": "*********",
  "description": "This extension will repeat the media you are playing",
  "version": "1.0",
  "background": {
    "service_worker": "background.js"
  },
  "content_scripts":[
    {
      "matches": ["https://www.google.com/*"],
      "js": ["bot.js"]
    }
  ],
  "action": {
   "default_icon": "icon.png",
   "default_popup": "popup/popup.html"
  },
  "permissions": [
   "activeTab",
   "storage",
   "tabs",
   "scripting"
   ]
}
Sweeten answered 14/12, 2022 at 16:25 Comment(0)
P
1

These are the steps to to load content.js on click on the extension icon

  1. remove content_scripts from manifest.json

  2. in manifest.json add action with default_icon

    "action": {
      "default_icon": {
        "16": "images/icon-32.png",
      }
    },
    
  3. in background.js listen to the onClick action

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

above update code will be:

{
    "manifest_version": 3,
    "name": "__MSG_extName__",
    "description": "__MSG_extDescription__",
    "key": "...",
    "version": "1.0.0",
    "icons": { ... },
    "background": {
        "service_worker": "/background.js"
    },
    "permissions": [
        "storage"
    ],
    "web_accessible_resources": [
        {
            "resources": [
                "/assets/*",
                "/options.html"
            ],
            "matches": [
                "<all_urls>"
            ]
        }
    ],
    "options_page": "options.html",
    "action": {
        "default_icon": {
          "16": "images/icon-32.png",
        }
      },
}
Profanatory answered 27/6, 2023 at 18:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.