javascriptfirefox-addonfirefox-addon-webextensions

I'm building addon for firefox user can take screenshot, but browser.runtime.sendMessage returns undefined


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.


Solution

  • You don't need the background script and messaging in this case - just use captureVisibleTab in the popup! But, assuming you want to use the background script, the problem is that 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.

    There may be other causes for not receving a response: