/** Service worker — ouvre le panneau latéral (Chrome Side Panel ou Firefox sidebar) au clic sur l'icône. */ const extApi = (typeof browser !== 'undefined' && browser.sidebarAction) ? browser : chrome if (extApi.sidePanel?.setPanelBehavior) { // Chrome MV3 : Side Panel API extApi.sidePanel.setPanelBehavior({ openPanelOnActionClick: true }).catch(() => {}) } else if (extApi.sidebarAction?.open) { // Firefox MV3 : sidebarAction extApi.action?.onClicked?.addListener?.(() => { extApi.sidebarAction.open().catch(() => {}) }) } extApi.runtime?.onInstalled?.addListener?.(() => { if (extApi.sidePanel?.setPanelBehavior) { extApi.sidePanel.setPanelBehavior({ openPanelOnActionClick: true }).catch(() => {}) } }) extApi.runtime?.onStartup?.addListener?.(() => { if (extApi.sidePanel?.setPanelBehavior) { extApi.sidePanel.setPanelBehavior({ openPanelOnActionClick: true }).catch(() => {}) } }) // === Forwarding content script → side panel === // En Chrome MV3, chrome.runtime.sendMessage depuis un content script arrive // uniquement au background service worker (PAS au side panel directement). // On doit broadcaster manuellement vers toutes les surfaces ouvertes. extApi.runtime?.onMessage?.addListener?.((msg, sender) => { if (!msg || typeof msg !== 'object') return // Messages émis par le content script qui doivent atteindre le side panel. const FORWARD_TYPES = new Set([ 'SELECTION_CHANGED', 'PAGE_CONTEXT_CHANGED', ]) if (!FORWARD_TYPES.has(msg.type)) return // Broadcast à toutes les surfaces (side panel, popup). // runAt permet au receiver de filtrer par URL s'il veut. extApi.runtime.sendMessage({ ...msg, _fromContentScript: true, _fromTabId: sender?.tab?.id, }).catch(() => { /* no listener */ }) // Retourne true pour permettre une réponse asynchrone si besoin. return false })