Search code examples
google-chrome-extensioncontent-security-policy

Chrome extension: Receiving error while making extension


I'm developing a chrome extension. It will make it possible to press a button, and it will capture a screenshot of your screen, then you will be able to save it to your computer.

However after attempting to load my extension at chrome://extensions/ I'm getting either of 2 messages:

  1. "Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist."

  2. "Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' blob: filesystem:". Either the 'unsafe-inline' keyword, a hash ('sha256-0xoq3Fm+45tEb3FQIwY9RYnpdCuDu/FcIzz/s1HPTAM='), or a nonce ('nonce-...') is required to enable inline execution."

I've been at this for a long time now and can't seem to find the problem. I have inserted the codes below, can anyone help me fix this?

Might be even the smallest oversight from my part, but would be super grateful for any help.

See code below:

manifest.json

{
    "manifest_version": 2,
    "name": "MySnap",
    "description": "Take a screenshot of a selected portion of the screen",
    "version": "1.0",
    "permissions": [
        "tabs",
        "activeTab"
    ],
    "browser_action": {
        "default_icon": "icon.png",
        "default_title": "MySnap",
        "default_popup": "popup.html"
    },
    "content_security_policy": "script-src 'self' 'sha256-Ws4H0eytNaM/o8NllzTlOPZFeyohSxu1N5dQ7JOcjMI='"
}

popup.html

<!DOCTYPE html>
<html>
  <head>
    <title>MySnap</title>
  </head>
  <body>
    <h1>MySnap</h1>
    <button id="screenshot-button">Take Screenshot</button>
    <div id="screenshot-container"></div>
    <script src="screenshot.js"></script>
    <script>
  document.getElementById("screenshot-button").addEventListener("click", function() {
    chrome.runtime.sendMessage({message: "take_screenshot"}, function(response) {
      // Do something with the response
    });
  });
</script>
    <script>
      function takeScreenshot() {
        chrome.runtime.sendMessage({message: "take_screenshot"}, function(response) {
          if (response && response.screenshotUrl) {
            // Create a link element and set its href to the screenshot URL
            var link = document.createElement("a");
            link.href = response.screenshotUrl;
            // Set the download attribute of the link element
            link.download = "screenshot.png";
            // Append the link element to the DOM
            document.body.appendChild(link);
            // Click the link to initiate the download
            link.click();
            // Remove the link element from the DOM
            document.body.removeChild(link);
          }
        });
      }
    </script>
  </body>
</html>

screenshot.js

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    if (request.message === "take_screenshot") {
        chrome.tabs.captureVisibleTab(null, {}, function(screenshotUrl) {
            sendResponse({screenshotUrl: screenshotUrl});
        });
    }
    return true;
});

background.js

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    if (request.message === "take_screenshot") {
        chrome.tabs.captureVisibleTab(null, {}, function(screenshotUrl) {
            sendResponse({screenshotUrl: screenshotUrl});
        });
    }
});

Solution

  • You can make the screenshot in the popup script, no need for messaging.

    1. remove content_security_policy from manifest.json
    2. remove all <script> elements from popup.html except <script src="screenshot.js">
    3. remove background.js

    // popup.html:

    <!DOCTYPE html>
    <h1>MySnap</h1>
    <button id="screenshot-button">Take Screenshot</button>
    <div id="screenshot-container"></div>
    <script src="screenshot.js"></script>
    

    // screenshot.js:

    document.getElementById('screenshot-button').onclick = () => {
      chrome.tabs.captureVisibleTab(url => {
        const el = document.createElement('a');
        el.href = url;
        el.download = 'screenshot.png';
        document.body.appendChild(el);
        el.click();
        el.remove();
      });
    };