devtools.js

 1/**
 2 * Impeccable DevTools Extension - DevTools Page
 3 *
 4 * Creates the Impeccable panel and triggers an auto-scan when DevTools opens.
 5 * This page lives for the entire DevTools session -- its port disconnect
 6 * is the canonical signal that DevTools has closed.
 7 */
 8
 9chrome.devtools.panels.create(
10  'Impeccable',
11  'icons/icon-32.png',
12  'devtools/panel.html'
13);
14
15// Sidebar pane in the Elements panel: shows findings for the currently selected element
16chrome.devtools.panels.elements.createSidebarPane('Impeccable', (sidebar) => {
17  sidebar.setPage('devtools/sidebar.html');
18  sidebar.setHeight('200px');
19});
20
21// Lifecycle port to the service worker. Auto-reconnects if the SW gets terminated
22// (which can happen in MV3 after ~30s of inactivity, especially when the browser is unfocused).
23const portName = `impeccable-devtools-${chrome.devtools.inspectedWindow.tabId}`;
24let lifecyclePort = null;
25let firstConnect = true;
26function connectLifecycle() {
27  lifecyclePort = chrome.runtime.connect({ name: portName });
28  // On the very first connection, decide whether to auto-scan based on the user's setting.
29  // Default ('panel'): wait until the user opens the Impeccable panel or sidebar.
30  // Opt-in ('devtools'): scan immediately when DevTools opens.
31  if (firstConnect) {
32    firstConnect = false;
33    chrome.storage.sync.get({ autoScan: 'panel' }, (settings) => {
34      if (settings.autoScan === 'devtools') {
35        try { lifecyclePort?.postMessage({ action: 'scan' }); } catch {}
36      }
37    });
38  }
39  lifecyclePort.onDisconnect.addListener(() => {
40    lifecyclePort = null;
41    // Reconnect on the next tick so the SW sees a fresh connection
42    setTimeout(connectLifecycle, 100);
43  });
44}
45connectLifecycle();
46
47// Heartbeat to keep the SW alive
48setInterval(() => {
49  try { lifecyclePort?.postMessage({ action: 'ping' }); } catch {}
50}, 20000);