I’m developing a Chrome extension that listens for requests to a particular url and sends a message to the tab that initiated the request. Here’s the relevant part of my background.ts:
chrome.webRequest.onBeforeRequest.addListener(
(request) => {
logger.infoDev('Received request', request);
if (request.tabId === -1) {
// we are hitting here with requests that are being intercepted by service workers
return;
}
chrome.tabs.get(request.tabId, (tab) => {
chrome.tabs.sendMessage<InnerMessage>(request.tabId, {
type: MessageType.Loaded,
payload: request,
location: getLocation(tab.url),
});
});
},
{
urls: ['https://some-request-url.com/*'],
},
);
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
switch (message.type) {
case 'UpdateBadgeCount':
if (!sender.tab || sender.tab.id === undefined) {
console.error('Unexpected source of UpdateBadgeCount message');
return;
}
updateBadgeCount(sender.tab.id, message.payload.count); // just updates the count that shows on the extension
sendResponse();
break;
default:
console.error('Unexpected message type in background script');
}
});
function getLocation(url: string | undefined) {
return url ? url.replace(/https?://(?:www.)?/, '') : '';
}
I’m encountering a problem where request.tabId becomes -1 for some requests to our url. Specifically, on certain websites, it looks like they have some sort of service worker intercepting all requests.
My Questions:
- How can I reliably associate requests with tabId === -1 to the correct tab in the onBeforeRequest listener?
- Is there a way to handle these fetch requests (with tabId === -1) so that the extension can correctly update the page visit count or badge count?
- Are there best practices for dealing with requests initiated by service workers or via the Fetch API that result in tabId === -1?
I attempted to handle the tabId === -1 case by using chrome.tabs.query with the initiator URL to find the tab:
if (request.tabId === -1) {
if (request.initiator) {
chrome.tabs.query({ url: request.initiator + '/*' }, (tabs) => {
if (tabs.length > 0) {
const tab = tabs[0];
chrome.tabs.sendMessage(tab.id, {
type: 'RequestDetected',
payload: request,
location: getLocation(tab.url),
});
} else {
console.warn(`Could not find tab for initiator ${request.initiator}`);
}
});
} else {
console.warn(`No tabId or initiator for request ${request.requestId}`);
}
} else {
// Original code handling valid tabId
}
When multiple tabs have the same initiator URL (e.g., several tabs open to the same site), this method incorrectly updates the badge count or performs actions on the wrong tabs. It doesn’t reliably associate the request with the correct tab, leading to unintended behavior.
Ignoring requests with tabId === -1 is not ideal because we would miss handling legitimate requests that are important for the extension’s functionality.