({getConnectionMessage, onColorSchemeChange, getTabMessage}: TabManagerOptions)
| 67 | private static readonly LOCAL_STORAGE_KEY = 'TabManager-state'; |
| 68 | |
| 69 | static init({getConnectionMessage, onColorSchemeChange, getTabMessage}: TabManagerOptions): void { |
| 70 | TabManager.stateManager = new StateManager<TabManagerState>(TabManager.LOCAL_STORAGE_KEY, this, {tabs: {}, timestamp: 0}, logWarn); |
| 71 | TabManager.tabs = {}; |
| 72 | TabManager.onColorSchemeChange = onColorSchemeChange; |
| 73 | TabManager.getTabMessage = getTabMessage; |
| 74 | |
| 75 | chrome.runtime.onMessage.addListener((message: MessageCStoBG | MessageUItoBG, sender, sendResponse): boolean => { |
| 76 | if (isFirefox && makeFirefoxHappy(message, sender, sendResponse)) { |
| 77 | return false; |
| 78 | } |
| 79 | switch (message.type) { |
| 80 | case MessageTypeCStoBG.DOCUMENT_CONNECT: { |
| 81 | if (__CHROMIUM_MV3__ && isPanel(sender)) { |
| 82 | sendResponse({ |
| 83 | type: MessageTypeBGtoCS.UNSUPPORTED_SENDER, |
| 84 | }); |
| 85 | return false; |
| 86 | } |
| 87 | TabManager.onColorSchemeMessage(message, sender); |
| 88 | |
| 89 | const reply = (tabURL: string, url: string, isTopFrame: boolean, topFrameHasDarkTheme?: boolean) => { |
| 90 | getConnectionMessage(tabURL, url, isTopFrame, topFrameHasDarkTheme).then((response) => { |
| 91 | if (!response) { |
| 92 | return; |
| 93 | } |
| 94 | response.scriptId = message.scriptId!; |
| 95 | TabManager.sendDocumentMessage(sender.tab!.id!, sender.documentId!, response, sender.frameId!); |
| 96 | }); |
| 97 | }; |
| 98 | |
| 99 | if (isPanel(sender)) { |
| 100 | // NOTE: Vivaldi and Opera can show a page in a side panel, |
| 101 | // but it is not possible to handle messaging correctly (no tab ID, frame ID). |
| 102 | if (isFirefox) { |
| 103 | if (sender && sender.tab && typeof sender.tab.id === 'number') { |
| 104 | chrome.tabs.sendMessage<MessageBGtoCS>(sender.tab.id, |
| 105 | { |
| 106 | type: MessageTypeBGtoCS.UNSUPPORTED_SENDER, |
| 107 | scriptId: message.scriptId!, |
| 108 | }, |
| 109 | { |
| 110 | frameId: sender && typeof sender.frameId === 'number' ? sender.frameId : undefined, |
| 111 | }); |
| 112 | } |
| 113 | } else { |
| 114 | sendResponse('unsupportedSender'); |
| 115 | } |
| 116 | return false; |
| 117 | } |
| 118 | |
| 119 | const {frameId} = sender; |
| 120 | const isTopFrame: boolean = (__CHROMIUM_MV2__ || __CHROMIUM_MV3__) ? (frameId === 0 || message.data.isTopFrame) : frameId === 0; |
| 121 | const url = sender.url!; |
| 122 | const tabId = sender.tab!.id!; |
| 123 | const scriptId = message.scriptId!; |
| 124 | // Chromium 106+ may prerender frames resulting in top-level frames with chrome.runtime.MessageSender.tab.url |
| 125 | // set to chrome://newtab/ and positive chrome.runtime.MessageSender.frameId |
| 126 | const tabURL = ((__CHROMIUM_MV2__ || __CHROMIUM_MV3__) && isTopFrame) ? url : sender.tab!.url!; |
nothing calls this directly
no test coverage detected