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

Why does my chrome extenstion only react to webRequests after I opened the extensions popup (Manifest V3)?


I am building a chrome extenstion using manifest V3. It should listen for webRequests against certain urls and react on these.

In the service-worker.js:

  1. rules are set for supported domains (in this example -> example.com) to block a webrequest (replacing manifests V2 webRequestBlocking).
  2. a listener configured to listen to these requests and should then react and log the url.

When I install the extension and open the popup, it reacts to a request in the currently opened tab. When I dont open the extension popup first, it doesnt recognize the request at all. Also, everytime I open a new tab, I need to click on the extension icon first, before it reacts to a request.

Why is that and can I somehow make sure that it also works out of the box, if i just install the extension?

I also tried what was recommended here without any success: Persistent Service Worker in Chrome Extension (There was a "persistent": true parameter in Manifest V2 keeping the background script alive, but it seems that there is no equivalent in V3)

The service-worker.js:

let rules = [];

const supportedDomainPatterns = ['*://*example.com/*'];

supportedDomainPatterns.forEach((domainPattern, index) => {
  rules.push({
    id: index + 1001,
    priority: 1,
    action: {
      type: 'block',
    },
    condition: {
      urlFilter: domainPattern,
    },
  });
});
// Collect all the rule IDs to remove.
const ruleIdsToRemove = rules.map((rule) => rule.id);

chrome.runtime.onInstalled.addListener(() => {
  chrome.declarativeNetRequest.updateDynamicRules({
    removeRuleIds: ruleIdsToRemove,
    addRules: rules,
  });
});

chrome.webRequest.onBeforeRequest.addListener(
    (details) => {
      const url = new URL(details.url);

      console.log('caught request' + url);
    },
    {
      urls: supportedDomainPatterns,
      types: ['main_frame'],
    }
);

My manifest.json:

{
  "manifest_version": 3,
  "name": "example extension",
  "description": "example",
  "version": "1.0",
  "background": {
    "service_worker": "service-worker.js"
  },
  "action": {
    "default_popup": "popup.html",
    "default_icon": "icon-34.png"
  },
  "icons": {
    "128": "icon-128.png"
  },
  "web_accessible_resources": [
    {
      "resources": ["content.styles.css", "icon-128.png", "icon-34.png"],
      "matches": []
    }
  ],
  "host_permissions": ["*://*example.com/*"],
  "permissions": [
    "declarativeNetRequest",
    "activeTab",
    "webRequest",
  ]
}

Solution

  • My description was actually missing something: In the service-worker.js I actually added 2 listeners like e.g. this:

    // first listener
    chrome.webRequest.onBeforeRequest.addListener(
        (details) => {
          const url = new URL(details.url);
    
          console.log('caught request for supported domain patterns' + url);
        },
        {
          urls: supportedDomainPatterns,
          types: ['main_frame'],
        }
    );
    
    // second listener
    chrome.webRequest.onBeforeRequest.addListener(
        (details) => {
          const url = new URL(details.url);
    
          console.log('caught request for some other patterns' + url);
        },
        {
          urls: someOtherPatterns,
          types: ['main_frame'],
        }
    );
    

    This seemed not to work at first and the outcome of this manifested in the behaviour I described above.

    edit: then I also found out that I accidentally removed a host permission that was needed from the manifest.json:

    "host_permissions": [
      "someOtherPatternPermission0"
    ]
    

    After adding the permission, everything worked as I wanted it to work, even with multiple listeners of the same type...

    Hope this helps anyone having the same or similar issues!