skip to Main Content

I’m trying to implement a function that user can take screenshot using browser.tabs.captureVisibleTab .

But browser.runtime.sendMessage immediately returns undefined.

In console.log("dataUrl ::: ", dataUrl) of browser.runtime.onMessage.addListener it logged data url, so it’s working. But somehow, it’s undefined in screenshot.addEventListener
My current code is as below. It works fine in chrome(I changed browser with chrome of course).

I appreciate any advice.

// manifest.json

"permissions": ["activeTab", "tabs", "storage", "webRequest", "<all_urls>"],
  "host_permissions": ["<all_urls>"]

// popup.js

screenshot.addEventListener("click", async () => {
  try {
    const response = await browser.runtime.sendMessage({
      type: "takeScreenshot",
    });
    console.log("response is ", response); // undefined
    if (response.dataUrl) {
      const img = document.createElement("img");
      img.src = response.dataUrl;
      document.body.appendChild(img);
    }
  } catch (error) {
    console.error("Error sending message:", error);
  }
});

// background.js

browser.runtime.onMessage.addListener(async (message, sender, sendResponse) => {
  
  if (message.type === "takeScreenshot") {
    const option = { active: true, currentWindow: true }; 
    await browser.tabs.query(option, async (tabs) => {
      const activeTab = tabs[0];
      if (!activeTab) {
        await sendResponse({ error: "No active tab." });
        return;
      }
      await browser.tabs.captureVisibleTab(
        activeTab.windowId,
        { format: "png" },
       
        async (dataUrl) => {
          if (browser.runtime.lastError) {
            await sendResponse({ error: browser.runtime.lastError.message });

            return;
          }
          console.log("dataUrl ::: ", dataUrl); //it logs correct dataUrl

          await sendResponse({ dataUrl: dataUrl }); 
        }
       
      );
    });
    return true;
  }
});

I enabled the “<all_urls>” permission in the Add-ons Manager according to this .
But it still returns same result.

2

Answers


  1. You’ve incorrectly used Chrome’s atavistic return true in a Firefox’s async onMessage.

    In Firefox you simply return the value just like you do in any async code:

    browser.runtime.onMessage.addListener(async (message, sender) => {
      if (message.type === 'takeScreenshot') {
        const [{windowId}] = await browser.tabs.query({active: true, currentWindow: true});
        const dataUrl = await browser.tabs.captureVisibleTab(windowId, {format: 'png'});
        return {dataUrl};
      }
    });
    

    The exceptions are automatically sent to your calling code’s catch, no need to catch them here.

    Login or Signup to reply.
  2. Observation #1:

    It seems to be in fashion lately for people to add “await” outside of functions; probably thinking that it’ll make them run asynchronously, but it doesn’t work like that… a function has to be async by design (ie: promise) to be compatible with await.

    Observation #2:

    Your “return true” under browser.runtime.onMessage, is illegal and utterly useless and may well be making your function terminate prematurely.

    Comment out “return true;” as well as all those “await”s and try again.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search