Chrome extension mv3 - catch zip files on anchor click

Viewed 73

I put two pieces of code. The first contains the chrome extension manifest version 2 files. Here if I click on anchor with href pointed to zip file, then extension redirect to page from extension. This is a worked example.

I am trying to achieve this for chrome extension with manifest version 3. This is a second pieces of code.

First part. Extension manifest version 2

manifest.json

{
  "name": "Test app mv2",
  "version": "0.1",
  "manifest_version": 2,
  "description": "test mv2",
  "background": {
    "scripts": [
      "background.js"
    ]
  },
  "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
  "icons": {
    "128": "128.png"
  },
  "permissions": [
    "webRequest",
    "webRequestBlocking",
    "<all_urls>"
  ],  
  "web_accessible_resources": [
    "web/main.html"
  ]
}

background.js

function getHeaderFromHeaders(headers, headerName) {
  for (var i=0; i<headers.length; ++i) {
    var header = headers[i];
    if (header.name.toLowerCase() === headerName) {
      return header;
    }
  }
}

function isAllowed(details) {
  var header = getHeaderFromHeaders(details.responseHeaders, 'content-type');
  
  if (header) {
    var headerValue = header.value.toLowerCase().split(';',1)[0].trim();

    var mimeTypes = [
      'application/zip'
    ];
    
    return (mimeTypes.indexOf(headerValue) !== -1);
  }
}

chrome.webRequest.onHeadersReceived.addListener(
  function(details) {
    if (details.method !== 'GET') {
      // Don't intercept POST requests until http://crbug.com/104058 is fixed.
      return;
    }
    
    if (!isAllowed(details)) {
      return;
    }

    return { redirectUrl: chrome.runtime.getURL('web/main.html') };
  },
  {
    urls: [
      '<all_urls>'
    ],
    types: ['main_frame', 'sub_frame']
  },
  ['blocking','responseHeaders']
 );

Full source for mv2

Second part. Extension manifest version 3

manifest.json

{
  "name": "Test app mv3",
  "manifest_version": 3,
  "version": "0.1",
  "background": {
    "service_worker": "./background.js"
  },
  "action": {    
    "default_title": "SW3"
  },
  "host_permissions": [
    "<all_urls>"
  ],
  "permissions": [
    "webRequest",
    "declarativeNetRequest",
    "declarativeNetRequestFeedback",
    "declarativeNetRequestWithHostAccess"
  ],  
  "web_accessible_resources": [{
    "resources": ["web/main.html"],
    "matches": ["<all_urls>"]
  }],
  "content_security_policy": {
    "extension_pages": "script-src 'self'; object-src 'self'"
  }
}

background.js

function getHeaderFromHeaders(headers, headerName) {
  for (var i=0; i<headers.length; ++i) {
    var header = headers[i];
    if (header.name.toLowerCase() === headerName) {
      return header;
    }
  }
}

function isAllowed(details) {
  var header = getHeaderFromHeaders(details.responseHeaders, 'content-type');
  
  if (header) {
    var headerValue = header.value.toLowerCase().split(';',1)[0].trim();

    var mimeTypes = [
      'application/zip'
    ];
    
    return (mimeTypes.indexOf(headerValue) !== -1);
  }
}

chrome.webRequest.onHeadersReceived.addListener(
  function(details) {
    if (details.method !== 'GET') {
      return;
    }
    
    if (!isAllowed(details)) {
      return;
    }

    chrome.declarativeNetRequest.updateSessionRules({
      addRules: [{
        'id': 2001,
        'priority': 1,
        'action': {
          'type': 'redirect',
          'redirect': {
            url: chrome.runtime.getURL('web/main.html')
         }
        },
        'condition': {
          'urlFilter': details.url,
          'resourceTypes': ['main_frame']
        }
      }],
    removeRuleIds: [2001]
    });
  
    return { redirectUrl: chrome.runtime.getURL('web/main.html') };
  },
  {
    urls: [
      '<all_urls>'
    ],
    types: ['main_frame', 'sub_frame']
  },
  ['responseHeaders']
 );

Full source for mv3

For extension with mv3, above code achieved similar action as code for mv2. The difference is that: when I click on anchor that pointed to zip file, then on the first click the dialog "save as" is shown and if I click on same zip anchor for second time, then redirect occurs. For other zip files above actions are repeated.

How I can modify mv3 code to achieve same results as mv2?

1 Answers

This is still possible, but requires abandoning the chrome.webRequest API in favor of chrome.debugger. This allows your extension talk to the CDP protocol, where you can hook into the request/response lifecycle.

The first step is to attach the debugger the tabId in question, and send enable commands (if required) for the APIs you are using. Here you can find many examples of how to do this. For example, let's assume we want to use Fetch, so we need to send Fetch.enable.

Now, if you want to modify a request/response before it is processed, on a high level you need to:

Helpful:

I am using this approach successfully in a chrome extension project. MV3 killed the native extension request API (or at least, severely limited it) so for now this is the only option I am aware of. The downside is, an annoying bar appears under the tab, saying this browser is currently being debugged by $EXT_NAME.

Related