Reputation: 5259
I have a Firefox extension that for certain pages listens to the webRequest.onHeadersReceived
for specific URLs that it opens in order to remove the "content-disposition" header when it contains "attachment". That way some content is shown in the browser rather than downloaded as a file.
When the extension opens the URL in a new tab, it works fine; the listener is called and I can modify the headers. But, if I instead open the URL in the currently active tab, it seems the background script gets terminated and the listener is never called.
Is there a way to prevent the background script from terminating, or am I doing something wrong to cause this?
From a content script a message is sent containing a URL, e.g. for an image, to open. The background script:
// background.ts
browser.runtime.onMessage.addListener(handleMessage);
function handleMessage(message: IMessage, sender: browser.runtime.MessageSender, sendResponse: (response?: any) => void) {
const command = message.command;
switch (command) {
case "OPEN_IMAGE": {
const { url, focusTab, newTab } = message.data;
return openImage(url, focusTab, newTab);
}
// other cases...
}
}
async function openImage(url: string, shouldFocus: boolean, newTab: boolean) {
let tab: browser.tabs.Tab;
if (newTab) {
// This branch works as expected. The URL is loaded (below) and the image
// is shown rather than downloaded as a file.
tab = await browser.tabs.create({ active: shouldFocus });
}
else {
// Using this tab to load the URL into doesn't work. The image is downloaded
// as a file, rather than shown in the tab.
const activeTabs = await browser.tabs.query({ active: true, currentWindow: true });
tab = activeTabs[0];
}
requestHandler.startListening(url);
await browser.tabs.update(tab.id!, { url, loadReplace: newTab });
}
Inside requestHandler.startListening
this is what happens:
class RequestHandler {
private readonly _urlsToListenFor: string[] = [];
public startListening = (url: string) => {
console.log("added");
this._urlsToListenFor.push(url);
// I've already checked no listener is added before this
browser.webRequest.onHeadersReceived.addListener(
this.onHeadersReceived,
{
urls: ["*://*/*"],
types: ["main_frame"]
},
["responseHeaders", "blocking"]);
};
private onHeadersReceived = (details: browser.webRequest._OnHeadersReceivedDetails) => {
const listenerIndex = this._urlsToListenFor.indexOf(details.url);
if (listenerIndex === -1) return;
console.log("removed");
this._urlsToListenFor.splice(listenerIndex, 1);
return this.getBlockingResponse(details);
};
private getBlockingResponse = (details: browser.webRequest._OnHeadersReceivedDetails) => {
// Make sure the image is opened in the browser rather than downloaded
const contentDispIndex = details.responseHeaders
?.findIndex(h => h.name.toLowerCase() === "content-disposition" &&
h.value!.toLowerCase().startsWith("attachment"));
return {
responseHeaders: details.responseHeaders!
.filter((_, index) => index !== contentDispIndex)
};
};
}
console.log("new RequestHandler");
export default new RequestHandler();
Given the console.log
statements, this is what I see in the console:
// newTab === true
added
removed
// newTab === false
added
new RequestHandler
Upvotes: 1
Views: 66