Home > Mobile >  Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist. With my o
Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist. With my o

Time:12-06

I'm new to extension creation and have a problem, which I've already been able to find various ways to solve, but which are all different from mine and/or fixed with manifest V2 instead of V3 which I need.

Also, some fixes found work on their end, but not on mine, so I really don't understand the problem.

Here is my problem:

  • I want to make a chrome extension to take screenshots of my browser and apps

  • I found an online tutorial that seemed correct to me (by the way, the only tutorial that uses AND the screenshots AND the V3 manifest, so perfect!)

  • Following the tutorial, I got the following error: Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist.

  • I looked for various ways, but nothing worked, I ended up downloading the git code of the tutorial, but it does not change anything, the error is still present

  • From what I understand, the error is in the following line:

chrome.action.onClicked.addListener(function (tab) {
  chrome.desktopCapture.chooseDesktopMedia(
    ["screen", "window", "tab"],
    tab,
    (streamId) => {
      if (streamId && streamId.length) {
        setTimeout(() => {
          chrome.tabs.sendMessage(
            tab.id,
            { name: "stream", streamId },
            (response) => console.log("received user data", response) // error is here, response is undefined
          );
        }, 200);
      }
    }
  );
});

I get undefined instead of the response, and I think it's from there that it's a problem, because it never goes on and therefore never activates the onMessage function, nor the content_script

Here is the full background.js code :

chrome.action.onClicked.addListener(function (tab) {
  chrome.desktopCapture.chooseDesktopMedia(
    ["screen", "window", "tab"],
    tab,
    (streamId) => {
      if (streamId && streamId.length) {
        setTimeout(() => {
          chrome.tabs.sendMessage(
            tab.id,
            { name: "stream", streamId },
            (response) => console.log("received user data", response)
          );
        }, 200);
      }
    }
  );
});

chrome.runtime.onMessage.addListener((message, sender, senderResponse) => {
  if (message.name === "download" && message.url) {
    chrome.downloads.download(
      {
        filename: "screenshot.png",
        url: message.url,
      },
      (downloadId) => {
        senderResponse({ success: true });
      }
    );

    return true;
  }
});

Content_script

chrome.runtime.onMessage.addListener((message, sender, senderResponse) => {
    if (message.name === 'stream' && message.streamId) {
        let track, canvas
        navigator.mediaDevices.getUserMedia({
            video: {
                mandatory: {
                    chromeMediaSource: 'desktop',
                    chromeMediaSourceId: message.streamId
                },
            }
        }).then((stream) => {
            track = stream.getVideoTracks()[0]
            const imageCapture = new ImageCapture(track)
            return imageCapture.grabFrame()
        }).then((bitmap) => {
            track.stop()
            canvas = document.createElement('canvas');
            canvas.width = bitmap.width; //if not set, the width will default to 200px
            canvas.height = bitmap.height;//if not set, the height will default to 200px
            let context = canvas.getContext('2d');
            context.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height)
            return canvas.toDataURL();
        }).then((url) => {
            chrome.runtime.sendMessage({name: 'download', url}, (response) => {
                if (response.success) {
                    alert("Screenshot saved");
                } else {
                    alert("Could not save screenshot")
                }
                canvas.remove()
                senderResponse({success: true})
            })
        }).catch((err) => {
            alert("Could not take screenshot")
            senderResponse({success: false, message: err})
        })
        return true;
    }
})

manifest v3

{
  "name": "Screenshots",
  "version": "0.0.1",
  "description": "Take screenshots",
  "manifest_version": 3,
  "background": {
    "service_worker": "background.js"
  },
  "permissions": ["desktopCapture", "downloads", "tabs", "nativeMessaging"],
  "action": {
    "default_title": "Take a Screenshot"
  },
  "icons": {
    "16": "/assets/icon-16.png",
    "32": "/assets/icon-32.png",
    "48": "/assets/icon-48.png",
    "128": "/assets/icon-128.png"
  },
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content_script.js"]
    }
  ]
}

I tried several things after various research like

  • Disable my extensions (which makes no sense, but you never know)

  • Add a timeout for the response, I tried up to 20 seconds delay, but without success

  • Added breakpoints everywhere to see if it crosses the line or not

CodePudding user response:

Here is an implementation without service worker and content scripts.

manifest.json

{
  "name": "desktopCapture",
  "version": "1.0",
  "manifest_version": 3,
  "permissions": [
    "desktopCapture",
    "tabs",
    "downloads"
  ],
  "action": {
    "default_popup": "popup.html"
  }
}

popup.html

<html>
<body>
  <script src="popup.js"></script>
</body>
</html>

popup.js

const createDate = {
  url: "desktopCaptuer.html",
  type: "popup",
  width: 800,
  height: 600
};
chrome.windows.create(createDate);

desktopCaptuer.html

<html>
<body>
  <input type="button" id="captuer" value="Captuer">
  <script src="desktopCaptuer.js"></script>
</body>
</html>

desktopCaptuer.js

chrome.windows.getCurrent({}, w => {
  chrome.windows.update(w.id, { focused: true }, () => {
    document.getElementById("captuer").onclick = () => {
      const sources = ["screen", "window", "tab"];
      chrome.tabs.getCurrent((tab) => {
        chrome.desktopCapture.chooseDesktopMedia(sources, tab, (streamId) => {
          let track, canvas;
          navigator.mediaDevices.getUserMedia({
            video: {
              mandatory: {
                chromeMediaSource: "desktop",
                chromeMediaSourceId: streamId
              },
            }
          }).then((stream) => {
            track = stream.getVideoTracks()[0];
            const imageCapture = new ImageCapture(track);
            return imageCapture.grabFrame();
          }).then((bitmap) => {
            track.stop();
            canvas = document.createElement("canvas");
            canvas.width = bitmap.width;
            canvas.height = bitmap.height;
            let context = canvas.getContext("2d");
            context.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height);
            return canvas.toDataURL();
          }).then((url) => {
            chrome.downloads.download({
              filename: "screenshot.png",
              url: url,
            }, () => {
              canvas.remove();
            });
          }).catch((err) => {
            console.log(err);
            alert("Could not take screenshot");
          })
        });
      });
    }
  });
});

CodePudding user response:

Works for me, using Chromium 107.0.5304.121 (Official. Build) Arch Linux (64-Bit).

  1. Go to https://stackoverflow.com/
  2. Click on the extension icon.
  3. A new window opens, with the text "Select what you want to share. Screenshots wants to share the contents of your screen with stackoverflow.com"
  4. Click on one of the tabs: Entire Screen, Window, Chromium Tab
  5. Click on a screenshot preview or tab title
  6. Click "Share"
  7. The browser displays an alert with the text "Screenshot saved", and a file named "Screenshot.png" is created in the default downloads directory.

CodePudding user response:

So, @Norio Yamamoto 's solution suits me perfectly, because I then need to make a popup to give a name and do other processing on my screen, so thanks to your help, I'm already moving on by starting to understand it HTML popups on extensions! Thanks !

For the problem itself, I was able to "fix" it in the end by reinstalling chrome, and it works as @Thomas Muller tells me... not sure why, maybe I had to break something with many tests, so the app was already working

But I noticed a problem on the version of the tutorial compared to the one with popup, the tutorial version does not work on: non-reload pages (thanks @wOxxOm for the tip by the way), nor on chrome home pages, nor on the extension page, so I really prefer the popup version, but I need to dig more to improve that

Thanks again !

  • Related