javascriptgoogle-chrome-extensionmanifest.json

"Cannot access contents of url" - Manifest v3 Chrome Extension


I got error in background.js Unchecked runtime.lastError: Cannot access contents of url. Extension manifest must request permission to access this host. and Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist.

in google chrome manifest 3.

Listener from content script

chrome.runtime.onMessage.addListener(
function(req, sender, sendResponse) {
    if(req.msg === "analysis background") {
        let obj = parse();
        sendResponse(obj);
    }
        
    return true;
}
); 
); 

Part of code from manifest.json

{
    "manifest_version": 3,
    "name": "extensionParser",
    "version": "1.0.0",
    "action": { 
        "default_popup": "popups/popup.html"
      },
    "background": {
        "service_worker": "background.js"
    },
    "permissions": ["tabs", "scripting",
        "http://localhost/site_for_parsing"]
}

Part of code from background.js file

const siteUrl = "http://localhost/site_for_parsing";

chrome.runtime.onConnect.addListener(port => {
    port.onMessage.addListener(msg => {
        if(msg.message === 'analysis') {
            chrome.tabs.create({active: false, url: siteUrl}, tab => {
                chrome.scripting.executeScript({
                    target: {tabId:tab.id},
                    files: ['dist/parser.js']
                }, (results) => {
                    chrome.tabs.sendMessage(tab.id, {msg: "analysis background"}, res => {
                        port.postMessage(res)
                        chrome.tabs.remove(tab.id)
                    })
                })
            });
        }

    });
});

I am waiting for your responses


Solution

    1. Site permissions should be added to host_permissions, not permissions, more info.
    2. create + executeScript in ManifestV3 is bugged in Chrome older than 100 so either a) go back to ManifestV2 until Chrome 100 is stable or b) use the workaround below.

    Wait for the URL to be set:

    (async () => {
      const tab = await chrome.tabs.create({url: 'https://www.example.com'});
      const tabId = tab.id;
      if (!tab.url) await onTabUrlUpdated(tabId);
      const results = await chrome.scripting.executeScript({
        target: {tabId},
        files: ['content.js'],
      });
      chrome.tabs.sendMessage(tabId, {msg: 'analysis background'}, res => {
        port.postMessage(res);
        chrome.tabs.remove(tabId);
      });
    })();
    
    function onTabUrlUpdated(tabId) {
      return new Promise((resolve, reject) => {
        const onUpdated = (id, info) => id === tabId && info.url && done(true);
        const onRemoved = id => id === tabId && done(false);
        chrome.tabs.onUpdated.addListener(onUpdated);
        chrome.tabs.onRemoved.addListener(onRemoved);
        function done(ok) {
          chrome.tabs.onUpdated.removeListener(onUpdated);
          chrome.tabs.onRemoved.removeListener(onRemoved);
          (ok ? resolve : reject)();
        }
      });
    }