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
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:
The exceptions are automatically sent to your calling code’s
catch
, no need to catch them here.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.