experiments in a post-browser web
10
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor(main): rewrite getRunning/getAllRegistered for v2 (Phase 3.9)

+26 -74
-11
backend/electron/ipc.ts
··· 94 94 95 95 import { 96 96 getExtensionHostWindow, 97 - isConsolidatedExtension, 98 97 getRunningExtensions, 99 98 getAllRegisteredExtensions, 100 99 reloadExtension, ··· 1304 1303 ipcMain.handle('extension-window-devtools', async (ev, data) => { 1305 1304 try { 1306 1305 const extId = data.id; 1307 - 1308 - // Consolidated extensions run in the extension host window 1309 - if (isConsolidatedExtension(extId)) { 1310 - const hostWin = getExtensionHostWindow(); 1311 - if (!hostWin || hostWin.isDestroyed()) { 1312 - return { success: false, error: 'Extension host is not running' }; 1313 - } 1314 - hostWin.webContents.openDevTools({ mode: 'detach' }); 1315 - return { success: true, data: { id: extId, isConsolidated: true } }; 1316 - } 1317 1306 1318 1307 // v2 tile or unknown — extensionWindows map removed in Phase 3.2 1319 1308 return { success: false, error: `Extension ${extId} is not running as a legacy window` };
+26 -63
backend/electron/main.ts
··· 87 87 88 88 // Track which lazy extensions have been loaded 89 89 const lazyExtensionLoaded = new Set<string>(); 90 - // Track which consolidated extensions have actually loaded (eager or lazy) 91 - const loadedConsolidatedExtensions = new Set<string>(); 92 90 // Pending lazy load callbacks (extId -> resolve[]) 93 91 const lazyLoadCallbacks = new Map<string, Array<() => void>>(); 94 92 ··· 740 738 if (lazyExtensionLoaded.has(extId)) return; // Already resolved normally 741 739 console.error(`[ext:lazy] Timeout waiting for ext:ready from ${extId} (${LAZY_LOAD_TIMEOUT_MS}ms)`); 742 740 lazyExtensionLoaded.add(extId); 743 - loadedConsolidatedExtensions.add(extId); 744 741 const callbacks = lazyLoadCallbacks.get(extId) || []; 745 742 lazyLoadCallbacks.delete(extId); 746 743 for (const cb of callbacks) { ··· 785 782 786 783 function handleLazyExtensionReady(extId: string, registeredTopics?: string[]): void { 787 784 lazyExtensionLoaded.add(extId); 788 - loadedConsolidatedExtensions.add(extId); 789 785 790 786 const callbacks = lazyLoadCallbacks.get(extId) || []; 791 787 lazyLoadCallbacks.delete(extId); ··· 1131 1127 const match = url.match(/^peek:\/\/([^/]+)\/background\.html/); 1132 1128 if (match) { 1133 1129 const extId = match[1]; 1134 - if (!loadedConsolidatedExtensions.has(extId)) { 1135 - loadedConsolidatedExtensions.add(extId); 1136 - DEBUG && console.log(`[ext:host] Frame loaded: ${extId} (${loadedConsolidatedExtensions.size} total)`); 1137 - 1138 - // Note: lazy extension ready callbacks are resolved via ext:ready pubsub 1139 - // (see subscribe('ext:ready', ...) below), not here — did-frame-finish-load 1140 - // fires before the extension's JS modules have executed and registered handlers. 1141 - } 1130 + DEBUG && console.log(`[ext:host] Frame loaded: ${extId}`); 1142 1131 } 1143 1132 } 1144 1133 } catch (err) { ··· 1191 1180 // grant) — no longer loaded as an iframe in the consolidated extension host. 1192 1181 await createExtensionHostWindow(); 1193 1182 await initCmd({ tilePreloadPath }); 1194 - // Keep cmd visible to getRunningExtensions(): the set is documented as 1195 - // "consolidated iframe extensions" but is the logical "core renderer is up" 1196 - // tracker used by the Features pane. Adding cmd here preserves that 1197 - // surfacing now that the renderer is a standalone BrowserWindow. 1198 - loadedConsolidatedExtensions.add('cmd'); 1199 1183 1200 1184 // Load HUD right after cmd — it's core app infrastructure like cmd, and 1201 1185 // registers the `hud` command + CmdOrCtrl+H shortcut via the portable api. 1202 1186 // HUD now runs as a standalone tile renderer (tile-preload + trustedBuiltin 1203 1187 // grant) — no longer loaded as an iframe in the consolidated extension host. 1204 1188 await initHud({ tilePreloadPath }); 1205 - // Keep hud visible to getRunningExtensions(): the set is documented as 1206 - // "consolidated iframe extensions" but is the logical "core renderer is up" 1207 - // tracker used by the Features pane. Adding hud here preserves that 1208 - // surfacing now that the renderer is a standalone BrowserWindow. 1209 - loadedConsolidatedExtensions.add('hud'); 1210 1189 1211 1190 // Load page background right after hud — registers the `open` and `modal` 1212 1191 // commands. Page is core infrastructure (the canvas architecture in ··· 1214 1193 // page now runs as a standalone tile renderer (tile-preload + trustedBuiltin 1215 1194 // grant) — no longer loaded as an iframe in the consolidated extension host. 1216 1195 await initPage({ tilePreloadPath }); 1217 - // Keep page visible to getRunningExtensions(): the set is documented as 1218 - // "consolidated iframe extensions" but is the logical "core renderer is up" 1219 - // tracker used by the Features pane. Adding page here preserves that 1220 - // surfacing now that the renderer is a standalone BrowserWindow. 1221 - loadedConsolidatedExtensions.add('page'); 1222 1196 1223 1197 // Launch the privileged test-fixture renderer when running under 1224 1198 // Playwright (E2E_TEST=true). This is the v2 replacement for the v1 ··· 1290 1264 return 0; 1291 1265 } 1292 1266 1267 + // Core renderers that are always considered "running" once the app has started. 1268 + // These are not v2 tiles (no tile manifest) and not v1 iframe extensions, but 1269 + // the Features pane should always show them as running. 1270 + const CORE_RENDERER_IDS = ['cmd', 'hud', 'page']; 1271 + 1293 1272 /** 1294 1273 * Get running extensions info 1295 - * Includes both consolidated (iframe) and separate window extensions 1274 + * Includes core renderers, declarative extensions, and v2 tiles 1296 1275 */ 1297 1276 export function getRunningExtensions(): Array<{ id: string; manifest: unknown; status: string }> { 1298 1277 const running: Array<{ id: string; manifest: unknown; status: string }> = []; 1299 1278 1300 - // Add consolidated extensions that have actually loaded (in extension host iframes). 1301 - // Iterates loadedConsolidatedExtensions (populated by did-frame-finish-load), which 1302 - // includes both CONSOLIDATED_EXTENSION_IDS features AND core pseudo-extensions like 1303 - // cmd and hud that are loaded by core glue (cmd-glue.ts, hud-glue.ts) rather than 1304 - // by the feature system. 1305 - if (extensionHostWindow && !extensionHostWindow.isDestroyed()) { 1306 - for (const extId of loadedConsolidatedExtensions) { 1307 - if (!isBuiltinExtensionEnabled(extId)) continue; 1308 - const extPath = getExtensionPath(extId); 1309 - const manifest = extPath ? loadExtensionManifest(extPath) : null; 1310 - running.push({ 1311 - id: extId, 1312 - manifest: manifest || { id: extId }, 1313 - status: 'running' 1314 - }); 1315 - } 1279 + // Add core renderers (cmd, hud, page) — always running once app is up 1280 + for (const extId of CORE_RENDERER_IDS) { 1281 + if (!isBuiltinExtensionEnabled(extId)) continue; 1282 + const extPath = getExtensionPath(extId); 1283 + const manifest = extPath ? loadExtensionManifest(extPath) : null; 1284 + running.push({ 1285 + id: extId, 1286 + manifest: manifest || { id: extId }, 1287 + status: 'running' 1288 + }); 1316 1289 } 1317 1290 1318 1291 // Add declarative-only extensions (no background page, but still active) ··· 1330 1303 } 1331 1304 1332 1305 // Add v2 tiles launched by the tile-launcher as separate BrowserWindows. 1333 - // These aren't in loadedConsolidatedExtensions (that's for iframes in the host). 1334 1306 for (const tileId of getLoadedTileIds()) { 1335 1307 if (running.some(r => r.id === tileId)) continue; 1336 1308 if (!isBuiltinExtensionEnabled(tileId)) continue; ··· 1353 1325 const registeredIds = getRegisteredExtensionIds(); 1354 1326 const result: Array<{ id: string; manifest: unknown; status: string }> = []; 1355 1327 1356 - // Build a set of running extension IDs for status info 1357 - const runningSet = new Set<string>(); 1358 - if (extensionHostWindow && !extensionHostWindow.isDestroyed()) { 1359 - for (const extId of CONSOLIDATED_EXTENSION_IDS) { 1360 - if (loadedConsolidatedExtensions.has(extId)) { 1361 - runningSet.add(extId); 1362 - } 1363 - } 1364 - } 1328 + // Build a set of running extension IDs for status info. 1329 + // Sources: core renderers (always up), declarative extensions, and loaded v2 tiles. 1330 + const runningSet = new Set<string>(CORE_RENDERER_IDS); 1365 1331 for (const extId of declarativeExtensions) { 1366 1332 runningSet.add(extId); 1333 + } 1334 + for (const tileId of getLoadedTileIds()) { 1335 + runningSet.add(tileId); 1367 1336 } 1368 1337 1369 1338 for (const extId of registeredIds) { ··· 1387 1356 return extensionHostWindow; 1388 1357 } 1389 1358 1390 - /** 1391 - * Check if an extension runs in consolidated mode (iframe in host) 1392 - */ 1393 - export function isConsolidatedExtension(extId: string): boolean { 1394 - return CONSOLIDATED_EXTENSION_IDS.includes(extId); 1395 - } 1396 1359 1397 1360 /** 1398 1361 * Check if an extension is a dev extension (loaded via CLI) ··· 1473 1436 export async function reloadExtension(extId: string): Promise<object | null> { 1474 1437 DEBUG && console.log(`[ext:reload] Reloading extension: ${extId}`); 1475 1438 1476 - // Check if it's a consolidated extension (not supported for reload) 1477 - if (isConsolidatedExtension(extId)) { 1478 - console.error(`[ext:reload] Cannot reload consolidated extension: ${extId} (reload the app instead)`); 1439 + // Check if it's a core renderer (cmd/hud/page) — not reloadable without a full app restart 1440 + if (CORE_RENDERER_IDS.includes(extId)) { 1441 + console.error(`[ext:reload] Cannot reload core renderer: ${extId} (reload the app instead)`); 1479 1442 return null; 1480 1443 } 1481 1444