Skip to content

Instantly share code, notes, and snippets.

@kltdwrds
Created Nov 8, 2021
Embed
What would you like to do?
background.js
/* eslint-disable no-console */
import * as Sentry from "@sentry/browser";
import { openIA, openTab, queryTabs } from "../../utils/popup";
// See https://github.com/getsentry/sentry-javascript/blob/master/packages/browser/src/sdk.ts#L77
const initSentry = (): void => {
if (
process.env.APP_ENV &&
!["production", "beta"].includes(process.env.APP_ENV)
) {
return;
}
Sentry.init({
dsn:
"https://xxxxxx@xxxxx.ingest.sentry.io/xxxxxx",
environment: process.env.SENTRY_ENV,
beforeSend(event, hint) {
if (event.exception != null) {
event.exception?.values?.[0].stacktrace?.frames?.forEach((frame) => {
// eslint-disable-next-line no-param-reassign
frame.filename = frame.filename?.substring(
frame.filename?.lastIndexOf("/")
);
});
}
return event;
},
});
};
initSentry();
const messageListener = (
message: Message,
sender,
sendResponse: (response?: MessageResponse) => void
): boolean => {
// see https://github.com/getsentry/sentry-javascript/blob/8ca6da819ff3b96c04307fe4493fb4c88c7fd9b3/packages/browser/src/helpers.ts#L34
Sentry.wrap(() => {
const response = handleMessage(message, sender);
sendResponse(response);
});
return false;
};
const handleMessage = (
message: Message,
sender: chrome.runtime.MessageSender
): undefined | MessageResponse => {
switch (message.action) {
case "getVersion": {
const manifest = chrome.runtime.getManifest() as Manifest;
return { version: manifest.version };
}
case "getTabId": {
if (sender.tab?.id == null) {
Sentry.captureMessage(`Missing sender tabId`, {
extra: { message, sender },
});
}
return { tabId: sender.tab?.id };
}
case "openUrl": {
if (!message.payload?.url) {
Sentry.captureMessage(`Missing url`, {
extra: { message, sender },
});
break;
}
console.info(`Opening url ${message.payload.url}`);
openTab(message.payload.url);
break;
}
case "openIA": {
console.info(
`Opening with url ${message.payload?.url}`
);
openIA(message.payload?.url);
break;
}
case "toggleDrawer": {
if (message.payload?.tabId == null) {
Sentry.captureMessage(`Missing tabId`, {
extra: { message, sender },
});
break;
}
chrome.tabs.sendMessage(message.payload.tabId, {
action: "toggleDrawer",
});
break;
}
case "openDrawerToast": {
if (message.payload?.tabId == null) {
Sentry.captureMessage(`Missing tabId`, {
extra: { message, sender },
});
break;
}
chrome.tabs.sendMessage(message.payload.tabId, {
action: "openDrawerToast",
});
break;
}
case "closeDrawerToast": {
if (message.payload?.tabId == null) {
Sentry.captureMessage(`Missing tabId`, {
extra: { message, sender },
});
break;
}
chrome.tabs.sendMessage(message.payload.tabId, {
action: "closeDrawerToast",
});
break;
}
case "disableDrawerToast": {
if (message.payload?.tabId == null) {
Sentry.captureMessage(`Missing tabId`, {
extra: { message, sender },
});
break;
}
chrome.tabs.sendMessage(message.payload.tabId, {
action: "disableDrawerToast",
payload: message.payload,
});
break;
}
case "enableDrawerToast": {
if (message.payload?.tabId == null) {
Sentry.captureMessage(`Missing tabId`, {
extra: { message, sender },
});
break;
}
chrome.tabs.sendMessage(message.payload.tabId, {
action: "enableDrawerToast",
});
break;
}
case "setToastText": {
if (message.payload?.tabId == null) {
Sentry.captureMessage(`Missing tabId`, {
extra: { message, sender },
});
break;
}
chrome.tabs.sendMessage(message.payload.tabId, {
action: "setToastText",
payload: message.payload,
});
break;
}
case "loadingComplete":
if (message.payload?.tabId == null) {
Sentry.captureMessage(`Missing tabId`, {
extra: { message, sender },
});
break;
}
chrome.tabs.sendMessage(message.payload.tabId, {
action: "loadingComplete",
});
break;
default: {
// support depricated properties
if (message.openUrl) {
openTab(message.openUrl);
return;
}
if (message.iaUrl) {
openIA(message.iaUrl);
return;
}
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
Sentry.captureMessage(`Unsupported message action: ${message.action}`, {
extra: { message },
});
}
}
};
chrome.runtime.onMessage.addListener(messageListener);
chrome.runtime.onMessageExternal.addListener(messageListener);
chrome.action.onClicked.addListener(() =>
Sentry.wrap(() => openIA())
);
chrome.runtime.onInstalled.addListener((details) => {
// reload all content script tabs on install (excludes <all_urls> pattern)
const manifest = chrome.runtime.getManifest() as Manifest;
Sentry.captureMessage("User install", {
extra: { ...details, currentVersion: manifest.version },
});
const patterns: string[] = manifest.content_scripts.reduce((prev, next) => {
return [...prev, ...next.matches];
}, [] as string[]);
const tabIdsPromises = patterns
.filter((url) => url !== "<all_urls>")
.map((url) => queryTabs({ url, discarded: false }));
Promise.all(tabIdsPromises).then((tabsArray) => {
const tabIds = tabsArray
.flat()
.map((tab) => tab?.id)
.filter((id) => id !== undefined && id !== chrome.tabs.TAB_ID_NONE);
const distinctTabIds = [...new Set(tabIds)];
distinctTabIds.forEach((tabId) =>
chrome.tabs.reload(tabId, { bypassCache: true })
);
});
});
// Force updates to be installed when available
// https://developer.chrome.com/docs/extensions/reference/runtime/#event-onUpdateAvailable
chrome.runtime.onUpdateAvailable.addListener((details) =>
chrome.runtime.reload()
);
chrome.tabs.onUpdated.addListener((tabId, changeInfo) => {
if (changeInfo.url) {
chrome.tabs.sendMessage(tabId, {
action: "handleTabUpdate",
payload: {
url: changeInfo.url,
},
});
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment