@btraut/browser-bridge 0.4.0 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/error-sanitizer.ts", "../src/background.ts"],
4
- "sourcesContent": ["import type { DriveErrorInfo } from './protocol.js';\n\nconst TRAILING_PUNCTUATION_RE = /[.,;:!?]+$/;\n\nconst stripTrailingPunctuation = (\n value: string\n): {\n core: string;\n trailing: string;\n} => {\n const match = value.match(TRAILING_PUNCTUATION_RE);\n if (!match) {\n return { core: value, trailing: '' };\n }\n const trailing = match[0] ?? '';\n return { core: value.slice(0, -trailing.length), trailing };\n};\n\nconst sanitizeUrlToken = (token: string): string => {\n const { core, trailing } = stripTrailingPunctuation(token);\n try {\n const parsed = new URL(core);\n if (parsed.protocol === 'file:') {\n return `file://[redacted]${trailing}`;\n }\n\n if (parsed.origin && parsed.origin !== 'null') {\n return `${parsed.origin}${trailing}`;\n }\n\n // Non-standard schemes can have a \"null\" origin (chrome://, devtools://, etc).\n // Keep scheme + host and drop everything else.\n if (parsed.protocol && parsed.host) {\n return `${parsed.protocol}//${parsed.host}${trailing}`;\n }\n if (parsed.protocol) {\n return `${parsed.protocol}${trailing}`;\n }\n } catch {\n // Ignore and fall back to a simpler heuristic.\n }\n\n const fallback = core.match(/^([a-zA-Z][a-zA-Z0-9+.-]*):\\/\\/([^/\\s]+)/);\n if (fallback?.[1] && fallback?.[2]) {\n return `${fallback[1]}://${fallback[2]}${trailing}`;\n }\n return `[redacted url]${trailing}`;\n};\n\nconst URL_TOKEN_RE =\n /\\b(?:https?|wss?|chrome-extension|chrome|chrome-devtools|devtools|edge|brave|file):\\/\\/[^\\s\"'<>)}\\]]+/gi;\n\nconst VIEW_SOURCE_RE = /\\bview-source:(https?:\\/\\/[^\\s\"'<>)}\\]]+)/gi;\n\nconst sanitizeUrls = (message: string): string => {\n // Special-case view-source: since it nests another URL.\n let next = message.replace(VIEW_SOURCE_RE, (_match, inner: string) => {\n return `view-source:${sanitizeUrlToken(inner)}`;\n });\n next = next.replace(URL_TOKEN_RE, (match) => sanitizeUrlToken(match));\n return next;\n};\n\nconst extractBasename = (value: string): string => {\n const trimmed = value.trim();\n const lastSlash = Math.max(\n trimmed.lastIndexOf('/'),\n trimmed.lastIndexOf('\\\\')\n );\n if (lastSlash < 0) {\n return trimmed;\n }\n return trimmed.slice(lastSlash + 1);\n};\n\nconst sanitizeWindowsPaths = (message: string): string => {\n // Example: C:\\Users\\me\\project\\file.ts:12:34 -> file.ts:12:34\n const windowsPathRe =\n /\\b[A-Za-z]:\\\\(?:[^\\s\"')\\]}]+\\\\)+[^\\s\"')\\]}]+(?::\\d+(?::\\d+)?)?/g;\n return message.replace(windowsPathRe, (match) => extractBasename(match));\n};\n\nconst sanitizeUnixPaths = (message: string): string => {\n // Only redact paths rooted in common system locations to avoid clobbering\n // generic \"/api/v1\" style strings that might appear in error messages.\n const unixPathRe =\n /\\/(?:Users|home|var|private|tmp|opt|etc|Library|Applications|Volumes|System)(?:\\/[^\\s\"')\\]}]+)+(?::\\d+(?::\\d+)?)?/g;\n return message.replace(unixPathRe, (match) => extractBasename(match));\n};\n\nexport const sanitizeChromeErrorMessage = (message: string): string => {\n let next = message;\n next = sanitizeUrls(next);\n next = sanitizeWindowsPaths(next);\n next = sanitizeUnixPaths(next);\n return next;\n};\n\nconst sanitizeUnknown = (value: unknown): unknown => {\n if (typeof value === 'string') {\n return sanitizeChromeErrorMessage(value);\n }\n if (Array.isArray(value)) {\n return value.map((entry) => sanitizeUnknown(entry));\n }\n if (!value || typeof value !== 'object') {\n return value;\n }\n const record = value as Record<string, unknown>;\n const next: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(record)) {\n next[key] = sanitizeUnknown(entry);\n }\n return next;\n};\n\nexport const sanitizeDriveErrorInfo = (\n error: DriveErrorInfo\n): DriveErrorInfo => {\n return {\n ...error,\n message: sanitizeChromeErrorMessage(error.message),\n ...(error.details\n ? { details: sanitizeUnknown(error.details) as Record<string, unknown> }\n : {}),\n };\n};\n", "import type {\n DebuggerCommandParams,\n DebuggerEvent,\n DebuggerRequest,\n DriveRequest,\n DriveErrorInfo,\n DriveEvent,\n DriveHelloParams,\n DriveResponse,\n DriveTabInfo,\n DriveTabListResult,\n ExtensionMessage,\n ExtensionRequest,\n} from './protocol.js';\nimport { sanitizeDriveErrorInfo } from './error-sanitizer.js';\n\ntype ContentResult =\n | { ok: true; result?: unknown }\n | { ok: false; error: DriveErrorInfo };\n\ntype ContentRequest = {\n action: string;\n params?: Record<string, unknown>;\n};\n\ntype DebuggerTarget = {\n tabId?: number;\n};\n\ntype DebuggerSession = {\n attached: boolean;\n attachPromise?: Promise<void>;\n idleTimer?: number;\n lastActivityAt: string;\n initialized?: boolean;\n};\n\nconst DEFAULT_CORE_PORT = 3210;\nconst CORE_PORT_KEY = 'corePort';\nconst CORE_WS_PATH = '/drive';\n\nconst DEBUGGER_PROTOCOL_VERSION = '1.3';\nconst DEBUGGER_IDLE_TIMEOUT_KEY = 'debuggerIdleTimeoutMs';\nconst DEFAULT_DEBUGGER_IDLE_TIMEOUT_MS = 15000;\nconst DEFAULT_DEBUGGER_COMMAND_TIMEOUT_MS = 10000;\n\nconst nowIso = (): string => new Date().toISOString();\n\nconst makeEventId = (() => {\n let counter = 0;\n return () => `evt-${Date.now()}-${(counter += 1)}`;\n})();\n\nconst lastActiveAtByTab = new Map<number, string>();\n\nconst ensureLastActiveAt = (tabId: number): string => {\n const existing = lastActiveAtByTab.get(tabId);\n if (existing) {\n return existing;\n }\n const timestamp = nowIso();\n lastActiveAtByTab.set(tabId, timestamp);\n return timestamp;\n};\n\nconst markTabActive = (tabId: number): string => {\n const timestamp = nowIso();\n lastActiveAtByTab.set(tabId, timestamp);\n return timestamp;\n};\n\nconst wrapChromeCallback = <T>(\n invoker: (callback: (value: T) => void) => void\n): Promise<T> =>\n new Promise<T>((resolve, reject) => {\n invoker((value: T) => {\n const error = chrome.runtime.lastError;\n if (error) {\n reject(new Error(error.message));\n return;\n }\n resolve(value);\n });\n });\n\nconst wrapChromeVoid = (\n invoker: (callback: () => void) => void\n): Promise<void> => {\n return new Promise<void>((resolve, reject) => {\n invoker(() => {\n const error = chrome.runtime.lastError;\n if (error) {\n reject(new Error(error.message));\n return;\n }\n resolve();\n });\n });\n};\n\nconst readCorePort = async (): Promise<number> => {\n return await new Promise<number>((resolve) => {\n chrome.storage.local.get(\n [CORE_PORT_KEY],\n (result: Record<string, unknown>) => {\n const raw = result?.[CORE_PORT_KEY];\n if (typeof raw === 'number' && Number.isFinite(raw)) {\n resolve(raw);\n return;\n }\n if (typeof raw === 'string') {\n const parsed = Number(raw);\n if (Number.isFinite(parsed)) {\n resolve(parsed);\n return;\n }\n }\n resolve(DEFAULT_CORE_PORT);\n }\n );\n });\n};\n\nconst readDebuggerIdleTimeoutMs = async (): Promise<number> => {\n return await new Promise<number>((resolve) => {\n chrome.storage.local.get(\n [DEBUGGER_IDLE_TIMEOUT_KEY],\n (result: Record<string, unknown>) => {\n const raw = result?.[DEBUGGER_IDLE_TIMEOUT_KEY];\n if (typeof raw === 'number' && Number.isFinite(raw) && raw > 0) {\n resolve(raw);\n return;\n }\n if (typeof raw === 'string') {\n const parsed = Number(raw);\n if (Number.isFinite(parsed) && parsed > 0) {\n resolve(parsed);\n return;\n }\n }\n resolve(DEFAULT_DEBUGGER_IDLE_TIMEOUT_MS);\n }\n );\n });\n};\n\nconst RESTRICTED_URL_PREFIXES = [\n 'chrome://',\n 'chrome-extension://',\n 'chrome-devtools://',\n 'devtools://',\n 'edge://',\n 'brave://',\n 'view-source:',\n];\n\nconst isRestrictedUrl = (url?: string): boolean => {\n if (!url || typeof url !== 'string') {\n return false;\n }\n const lowered = url.toLowerCase();\n if (RESTRICTED_URL_PREFIXES.some((prefix) => lowered.startsWith(prefix))) {\n return true;\n }\n try {\n const parsed = new URL(url);\n if (parsed.hostname === 'chromewebstore.google.com') {\n return true;\n }\n if (parsed.hostname === 'chrome.google.com') {\n return parsed.pathname.startsWith('/webstore');\n }\n } catch (error) {\n console.debug('Ignoring invalid URL in restriction check.', error);\n }\n return false;\n};\n\nconst mapDebuggerErrorMessage = (\n message: string,\n fallbackCode = 'INSPECT_UNAVAILABLE'\n): DriveErrorInfo => {\n const normalized = message.toLowerCase();\n if (\n normalized.includes('already attached') ||\n normalized.includes('another debugger') ||\n normalized.includes('attached to this target')\n ) {\n return {\n code: 'DEBUGGER_IN_USE',\n message:\n 'Debugger already attached. Close DevTools on the target tab and retry.',\n retryable: true,\n details: {\n reason: 'debugger_in_use',\n hint: 'Close DevTools on the target tab and retry.',\n original_message: message,\n },\n };\n }\n if (\n normalized.includes('no tab') ||\n normalized.includes('no target') ||\n normalized.includes('tab id')\n ) {\n return {\n code: 'TAB_NOT_FOUND',\n message,\n retryable: false,\n };\n }\n if (\n normalized.includes('not allowed') ||\n normalized.includes('permission') ||\n normalized.includes('denied')\n ) {\n return {\n code: 'ATTACH_DENIED',\n message,\n retryable: false,\n };\n }\n if (\n normalized.includes('cannot access') ||\n normalized.includes('not supported') ||\n normalized.includes('disallowed')\n ) {\n return {\n code: 'NOT_SUPPORTED',\n message,\n retryable: false,\n };\n }\n return {\n code: fallbackCode,\n message,\n retryable: false,\n };\n};\n\nconst buildTabInfo = (tab: Record<string, unknown>): DriveTabInfo | null => {\n const tabId = tab.id;\n const windowId = tab.windowId;\n if (typeof tabId !== 'number' || typeof windowId !== 'number') {\n return null;\n }\n return {\n tab_id: tabId,\n window_id: windowId,\n url: typeof tab.url === 'string' ? tab.url : undefined,\n title: typeof tab.title === 'string' ? tab.title : undefined,\n active: typeof tab.active === 'boolean' ? tab.active : undefined,\n last_active_at: ensureLastActiveAt(tabId),\n };\n};\n\nconst queryTabs = async (): Promise<DriveTabInfo[]> => {\n const tabs = await wrapChromeCallback<Record<string, unknown>[]>((callback) =>\n chrome.tabs.query({}, callback)\n );\n const result: DriveTabInfo[] = [];\n for (const tab of tabs) {\n const info = buildTabInfo(tab);\n if (info) {\n result.push(info);\n }\n }\n return result;\n};\n\nconst getTab = async (tabId: number): Promise<Record<string, unknown>> => {\n return await wrapChromeCallback<Record<string, unknown>>((callback) =>\n chrome.tabs.get(tabId, callback)\n );\n};\n\nconst getActiveTabId = async (): Promise<number> => {\n const tabs = await wrapChromeCallback<Record<string, unknown>[]>((callback) =>\n chrome.tabs.query({ active: true, lastFocusedWindow: true }, callback)\n );\n const first = tabs[0];\n if (first && typeof first.id === 'number') {\n return first.id;\n }\n throw new Error('No active tab found.');\n};\n\nconst sendToTab = async (\n tabId: number,\n action: string,\n params?: Record<string, unknown>\n): Promise<ContentResult> => {\n return await new Promise<ContentResult>((resolve) => {\n const message: ContentRequest = { action, params };\n chrome.tabs.sendMessage(tabId, message, (response: ContentResult) => {\n const error = chrome.runtime.lastError;\n if (error) {\n resolve({\n ok: false,\n error: {\n code: 'EVALUATION_FAILED',\n message: error.message,\n retryable: false,\n },\n });\n return;\n }\n if (!response || typeof response !== 'object') {\n resolve({\n ok: false,\n error: {\n code: 'EVALUATION_FAILED',\n message: 'Empty response from content script.',\n retryable: false,\n },\n });\n return;\n }\n resolve(response);\n });\n });\n};\n\nconst waitForDomContentLoaded = async (\n tabId: number,\n timeoutMs: number\n): Promise<void> => {\n return await new Promise<void>((resolve, reject) => {\n let timeout: number | undefined;\n const cleanup = () => {\n if (timeout !== undefined) {\n clearTimeout(timeout);\n }\n chrome.webNavigation.onDOMContentLoaded.removeListener(listener);\n };\n\n const listener = (details: { tabId: number; frameId: number }) => {\n if (details.tabId !== tabId || details.frameId !== 0) {\n return;\n }\n cleanup();\n resolve();\n };\n\n chrome.webNavigation.onDOMContentLoaded.addListener(listener);\n timeout = self.setTimeout(() => {\n cleanup();\n reject(new Error('Timed out waiting for domcontentloaded.'));\n }, timeoutMs);\n });\n};\n\nconst getWsUrl = async (): Promise<string> => {\n const port = await readCorePort();\n return `ws://127.0.0.1:${port}${CORE_WS_PATH}`;\n};\n\nclass DriveSocket {\n private socket: WebSocket | null = null;\n private reconnectTimer: number | null = null;\n private reconnectDelayMs = 1000;\n private readonly maxReconnectDelayMs = 10000;\n private keepAliveTimer: number | null = null;\n private readonly keepAliveIntervalMs = 30000;\n private readonly debuggerSessions = new Map<number, DebuggerSession>();\n private debuggerIdleTimeoutMs: number | null = null;\n\n start(): void {\n void this.connect().catch((error) => {\n console.error('DriveSocket connect failed:', error);\n });\n }\n\n stop(): void {\n if (this.reconnectTimer !== null) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n this.stopKeepAlive();\n if (this.socket) {\n this.socket.close();\n this.socket = null;\n }\n }\n\n sendTabReport(): void {\n void this.emitTabReport().catch((error) => {\n console.error('DriveSocket emitTabReport failed:', error);\n });\n }\n\n private scheduleReconnect(): void {\n if (this.reconnectTimer !== null) {\n return;\n }\n const delay = this.reconnectDelayMs;\n this.reconnectTimer = self.setTimeout(() => {\n this.reconnectTimer = null;\n void this.connect().catch((error) => {\n console.error('DriveSocket reconnect failed:', error);\n });\n }, delay);\n this.reconnectDelayMs = Math.min(\n this.maxReconnectDelayMs,\n this.reconnectDelayMs * 2\n );\n }\n\n private async connect(): Promise<void> {\n const url = await getWsUrl();\n try {\n const socket = new WebSocket(url);\n this.socket = socket;\n\n socket.addEventListener('open', () => {\n this.reconnectDelayMs = 1000;\n this.startKeepAlive();\n void this.sendHello().catch((error) => {\n console.error('DriveSocket hello failed:', error);\n });\n });\n\n socket.addEventListener('message', (event) => {\n this.handleMessage(event.data);\n });\n\n socket.addEventListener('close', () => {\n this.socket = null;\n this.stopKeepAlive();\n this.scheduleReconnect();\n });\n\n socket.addEventListener('error', () => {\n this.socket = null;\n this.stopKeepAlive();\n this.scheduleReconnect();\n });\n } catch (error) {\n console.debug('DriveSocket connect failed, scheduling reconnect.', error);\n this.scheduleReconnect();\n }\n }\n\n private async sendHello(): Promise<void> {\n const manifest = chrome.runtime.getManifest();\n let tabs: DriveTabInfo[] = [];\n try {\n tabs = await queryTabs();\n } catch (error) {\n console.debug('DriveSocket sendHello failed to read tabs.', error);\n tabs = [];\n }\n const params: DriveHelloParams = {\n version: manifest.version,\n tabs,\n };\n this.sendEvent('drive.hello', params);\n }\n\n private async emitTabReport(): Promise<void> {\n try {\n const tabs = await queryTabs();\n this.sendEvent('drive.tab_report', { tabs });\n } catch (error) {\n console.debug('DriveSocket emitTabReport failed.', error);\n }\n }\n\n private sendEvent(\n action: DriveEvent['action'],\n params: DriveEvent['params']\n ): void {\n const message: DriveEvent = {\n id: makeEventId(),\n action,\n status: 'event',\n params,\n };\n this.sendMessage(message);\n }\n\n private startKeepAlive(): void {\n this.stopKeepAlive();\n this.keepAliveTimer = self.setInterval(() => {\n if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {\n return;\n }\n this.sendEvent('drive.keepalive', {});\n }, this.keepAliveIntervalMs);\n }\n\n private stopKeepAlive(): void {\n if (this.keepAliveTimer !== null) {\n clearInterval(this.keepAliveTimer);\n this.keepAliveTimer = null;\n }\n }\n\n private sendDebuggerEvent(params: DebuggerEvent['params']): void {\n const message: DebuggerEvent = {\n id: makeEventId(),\n action: 'debugger.event',\n status: 'event',\n params,\n };\n this.sendMessage(message);\n }\n\n private sendMessage(message: ExtensionMessage): void {\n if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {\n return;\n }\n this.socket.send(JSON.stringify(message));\n }\n\n private handleMessage(raw: unknown): void {\n if (typeof raw !== 'string') {\n return;\n }\n let message: ExtensionMessage | null = null;\n try {\n message = JSON.parse(raw) as ExtensionMessage;\n } catch (error) {\n console.debug('DriveSocket received invalid JSON message.', error);\n return;\n }\n if (!message || typeof message !== 'object') {\n return;\n }\n if (message.status === 'request') {\n void this.handleRequest(message as ExtensionRequest).catch((error) => {\n console.error('DriveSocket handleRequest failed:', error);\n });\n }\n }\n\n private async handleRequest(message: ExtensionRequest): Promise<void> {\n let driveMessage: DriveRequest | null = null;\n const respondOk = (result?: unknown): void => {\n if (!driveMessage) {\n return;\n }\n const response: DriveResponse = {\n id: driveMessage.id,\n action: driveMessage.action,\n status: 'ok',\n result,\n };\n this.sendMessage(response);\n };\n\n const respondError = (error: DriveErrorInfo): void => {\n if (!driveMessage) {\n return;\n }\n const response: DriveResponse = {\n id: driveMessage.id,\n action: driveMessage.action,\n status: 'error',\n error: sanitizeDriveErrorInfo(error),\n };\n this.sendMessage(response);\n };\n\n try {\n if (\n !message ||\n typeof message !== 'object' ||\n typeof message.id !== 'string' ||\n typeof message.action !== 'string'\n ) {\n return;\n }\n if (message.action.startsWith('debugger.')) {\n await this.handleDebuggerRequest(message as DebuggerRequest);\n return;\n }\n\n if (!message.action.startsWith('drive.')) {\n return;\n }\n\n driveMessage = message as DriveRequest;\n switch (message.action) {\n case 'drive.ping': {\n respondOk({ ok: true });\n return;\n }\n case 'drive.navigate': {\n const params = (message.params ?? {}) as Record<string, unknown>;\n const url = params.url;\n if (typeof url !== 'string' || url.length === 0) {\n respondError({\n code: 'INVALID_ARGUMENT',\n message: 'url must be a non-empty string.',\n retryable: false,\n });\n return;\n }\n let tabId = params.tab_id;\n if (tabId !== undefined && typeof tabId !== 'number') {\n respondError({\n code: 'INVALID_ARGUMENT',\n message: 'tab_id must be a number when provided.',\n retryable: false,\n });\n return;\n }\n if (tabId === undefined) {\n tabId = await getActiveTabId();\n }\n const waitMode =\n params.wait === 'none' || params.wait === 'domcontentloaded'\n ? params.wait\n : 'domcontentloaded';\n await wrapChromeVoid((callback) =>\n chrome.tabs.update(tabId as number, { url }, () => callback())\n );\n markTabActive(tabId as number);\n if (waitMode === 'domcontentloaded') {\n try {\n await waitForDomContentLoaded(tabId as number, 30000);\n } catch (error) {\n respondError({\n code: 'TIMEOUT',\n message:\n error instanceof Error ? error.message : 'Timed out waiting.',\n retryable: true,\n });\n return;\n }\n }\n respondOk({ ok: true });\n return;\n }\n case 'drive.go_back':\n case 'drive.back':\n case 'drive.go_forward':\n case 'drive.forward': {\n const params = (message.params ?? {}) as Record<string, unknown>;\n let tabId = params.tab_id;\n if (tabId !== undefined && typeof tabId !== 'number') {\n respondError({\n code: 'INVALID_ARGUMENT',\n message: 'tab_id must be a number when provided.',\n retryable: false,\n });\n return;\n }\n if (tabId === undefined) {\n tabId = await getActiveTabId();\n }\n try {\n const isBack =\n message.action === 'drive.go_back' ||\n message.action === 'drive.back';\n await wrapChromeVoid((callback) => {\n if (isBack) {\n chrome.tabs.goBack(tabId as number, () => callback());\n } else {\n chrome.tabs.goForward(tabId as number, () => callback());\n }\n });\n } catch (error) {\n respondError({\n code: 'FAILED_PRECONDITION',\n message:\n error instanceof Error ? error.message : 'No history entry.',\n retryable: false,\n });\n return;\n }\n markTabActive(tabId as number);\n try {\n await waitForDomContentLoaded(tabId as number, 30000);\n } catch (error) {\n respondError({\n code: 'TIMEOUT',\n message:\n error instanceof Error ? error.message : 'Timed out waiting.',\n retryable: true,\n });\n return;\n }\n respondOk({ ok: true });\n return;\n }\n case 'drive.tab_list': {\n const tabs = await queryTabs();\n const result: DriveTabListResult = { tabs };\n respondOk(result);\n return;\n }\n case 'drive.tab_activate': {\n const tabId = (message.params as Record<string, unknown> | undefined)\n ?.tab_id;\n if (typeof tabId !== 'number') {\n respondError({\n code: 'INVALID_ARGUMENT',\n message: 'tab_id must be a number.',\n retryable: false,\n });\n return;\n }\n const tab = await getTab(tabId);\n await wrapChromeVoid((callback) =>\n chrome.tabs.update(tabId, { active: true }, () => callback())\n );\n const windowId = tab.windowId;\n if (typeof windowId === 'number') {\n await wrapChromeVoid((callback) =>\n chrome.windows.update(windowId, { focused: true }, () =>\n callback()\n )\n );\n }\n markTabActive(tabId);\n respondOk({ ok: true });\n this.sendTabReport();\n return;\n }\n case 'drive.tab_close': {\n const tabId = (message.params as Record<string, unknown> | undefined)\n ?.tab_id;\n if (typeof tabId !== 'number') {\n respondError({\n code: 'INVALID_ARGUMENT',\n message: 'tab_id must be a number.',\n retryable: false,\n });\n return;\n }\n await wrapChromeVoid((callback) =>\n chrome.tabs.remove(tabId, () => callback())\n );\n lastActiveAtByTab.delete(tabId);\n respondOk({ ok: true });\n this.sendTabReport();\n return;\n }\n case 'drive.handle_dialog': {\n const params = (message.params ?? {}) as Record<string, unknown>;\n const action = params.action;\n if (action !== 'accept' && action !== 'dismiss') {\n respondError({\n code: 'INVALID_ARGUMENT',\n message: 'action must be accept or dismiss.',\n retryable: false,\n });\n return;\n }\n const promptText = params.promptText;\n if (promptText !== undefined && typeof promptText !== 'string') {\n respondError({\n code: 'INVALID_ARGUMENT',\n message: 'promptText must be a string when provided.',\n retryable: false,\n });\n return;\n }\n let tabId = params.tab_id;\n if (tabId !== undefined && typeof tabId !== 'number') {\n respondError({\n code: 'INVALID_ARGUMENT',\n message: 'tab_id must be a number when provided.',\n retryable: false,\n });\n return;\n }\n if (tabId === undefined) {\n tabId = await getActiveTabId();\n }\n\n const error = await this.ensureDebuggerAttached(tabId as number);\n if (error) {\n respondError(error);\n return;\n }\n\n try {\n await this.sendDebuggerCommand(\n tabId as number,\n 'Page.handleJavaScriptDialog',\n {\n accept: action === 'accept',\n ...(promptText ? { promptText } : {}),\n },\n DEFAULT_DEBUGGER_COMMAND_TIMEOUT_MS\n );\n this.touchDebuggerSession(tabId as number);\n respondOk({ ok: true });\n } catch (error) {\n const info = mapDebuggerErrorMessage(\n error instanceof Error ? error.message : 'Dialog handling failed.'\n );\n respondError(info);\n }\n return;\n }\n case 'drive.click':\n case 'drive.hover':\n case 'drive.select':\n case 'drive.type':\n case 'drive.fill_form':\n case 'drive.drag':\n case 'drive.key':\n case 'drive.key_press':\n case 'drive.scroll':\n case 'drive.wait_for': {\n const params = (message.params ?? {}) as Record<string, unknown>;\n let tabId = params.tab_id;\n if (tabId !== undefined && typeof tabId !== 'number') {\n respondError({\n code: 'INVALID_ARGUMENT',\n message: 'tab_id must be a number when provided.',\n retryable: false,\n });\n return;\n }\n if (tabId === undefined) {\n tabId = await getActiveTabId();\n }\n const result = await sendToTab(\n tabId as number,\n message.action,\n params\n );\n if (result.ok) {\n respondOk(result.result ?? { ok: true });\n } else {\n respondError(result.error);\n }\n return;\n }\n default:\n respondError({\n code: 'NOT_IMPLEMENTED',\n message: `${message.action} not implemented in extension yet.`,\n retryable: false,\n });\n }\n } catch (error) {\n const messageText =\n error instanceof Error ? error.message : 'Unknown error';\n respondError({\n code: 'EVALUATION_FAILED',\n message: messageText,\n retryable: false,\n });\n }\n }\n\n private async handleDebuggerRequest(message: DebuggerRequest): Promise<void> {\n const respondAck = (result?: unknown): void => {\n this.sendMessage({\n id: message.id,\n action: message.action,\n status: 'ack',\n result,\n });\n };\n\n const respondError = (error: DriveErrorInfo): void => {\n this.sendMessage({\n id: message.id,\n action: message.action,\n status: 'error',\n error: sanitizeDriveErrorInfo(error),\n });\n };\n\n try {\n switch (message.action) {\n case 'debugger.attach': {\n const params = (message.params ?? {}) as { tab_id?: unknown };\n const tabId = params.tab_id;\n if (typeof tabId !== 'number') {\n respondError({\n code: 'INVALID_ARGUMENT',\n message: 'tab_id must be a number.',\n retryable: false,\n });\n return;\n }\n\n const error = await this.ensureDebuggerAttached(tabId);\n if (error) {\n respondError(error);\n return;\n }\n respondAck({ ok: true });\n return;\n }\n case 'debugger.detach': {\n const params = (message.params ?? {}) as { tab_id?: unknown };\n const tabId = params.tab_id;\n if (typeof tabId !== 'number') {\n respondError({\n code: 'INVALID_ARGUMENT',\n message: 'tab_id must be a number.',\n retryable: false,\n });\n return;\n }\n const error = await this.detachDebugger(tabId);\n if (error) {\n respondError(error);\n return;\n }\n respondAck({ ok: true });\n return;\n }\n case 'debugger.command': {\n const params = (message.params ?? {}) as DebuggerCommandParams;\n const tabId = params.tab_id;\n if (typeof tabId !== 'number') {\n respondError({\n code: 'INVALID_ARGUMENT',\n message: 'tab_id must be a number.',\n retryable: false,\n });\n return;\n }\n if (typeof params.method !== 'string' || params.method.length === 0) {\n respondError({\n code: 'INVALID_ARGUMENT',\n message: 'method must be a non-empty string.',\n retryable: false,\n });\n return;\n }\n\n const session = this.debuggerSessions.get(tabId);\n if (session?.attachPromise) {\n try {\n await session.attachPromise;\n } catch (error) {\n const info = mapDebuggerErrorMessage(\n error instanceof Error\n ? error.message\n : 'Debugger attach failed.'\n );\n this.clearDebuggerSession(tabId);\n respondError(info);\n return;\n }\n }\n\n const attachedSession = this.debuggerSessions.get(tabId);\n if (!attachedSession?.attached) {\n respondError({\n code: 'FAILED_PRECONDITION',\n message: 'Debugger is not attached to the requested tab.',\n retryable: false,\n });\n return;\n }\n\n try {\n const result = await this.sendDebuggerCommand(\n tabId,\n params.method,\n params.params,\n DEFAULT_DEBUGGER_COMMAND_TIMEOUT_MS\n );\n this.touchDebuggerSession(tabId);\n respondAck(result);\n } catch (error) {\n if (error instanceof DebuggerTimeoutError) {\n respondError({\n code: 'TIMEOUT',\n message: error.message,\n retryable: true,\n });\n return;\n }\n const info = mapDebuggerErrorMessage(\n error instanceof Error\n ? error.message\n : 'Debugger command failed.'\n );\n respondError(info);\n }\n return;\n }\n default:\n respondError({\n code: 'NOT_IMPLEMENTED',\n message: `${message.action} not implemented in extension yet.`,\n retryable: false,\n });\n }\n } catch (error) {\n const messageText =\n error instanceof Error ? error.message : 'Unexpected debugger error.';\n respondError({\n code: 'INSPECT_UNAVAILABLE',\n message: messageText,\n retryable: false,\n });\n }\n }\n\n async handleDebuggerEvent(\n source: DebuggerTarget,\n method: string,\n params?: Record<string, unknown>\n ): Promise<void> {\n const tabId = source.tabId;\n if (typeof tabId !== 'number') {\n return;\n }\n this.touchDebuggerSession(tabId);\n this.sendDebuggerEvent({\n tab_id: tabId,\n method,\n params,\n timestamp: nowIso(),\n });\n }\n\n async handleDebuggerDetach(\n source: DebuggerTarget,\n reason?: string\n ): Promise<void> {\n const tabId = source.tabId;\n if (typeof tabId !== 'number') {\n return;\n }\n this.clearDebuggerSession(tabId);\n this.sendDebuggerEvent({\n tab_id: tabId,\n method: 'Debugger.detached',\n params: { reason: reason ?? 'unknown' },\n timestamp: nowIso(),\n });\n }\n\n private async ensureDebuggerAttached(\n tabId: number\n ): Promise<DriveErrorInfo | null> {\n const existing = this.debuggerSessions.get(tabId);\n if (existing?.attached) {\n this.touchDebuggerSession(tabId);\n return null;\n }\n\n if (existing?.attachPromise) {\n try {\n await existing.attachPromise;\n } catch (error) {\n const info = mapDebuggerErrorMessage(\n error instanceof Error ? error.message : 'Debugger attach failed.'\n );\n this.clearDebuggerSession(tabId);\n return info;\n }\n if (existing.attached) {\n this.touchDebuggerSession(tabId);\n return null;\n }\n }\n\n const preflightError = await this.checkDebuggerTarget(tabId);\n if (preflightError) {\n return preflightError;\n }\n\n const session: DebuggerSession = {\n attached: false,\n lastActivityAt: nowIso(),\n };\n this.debuggerSessions.set(tabId, session);\n\n session.attachPromise = wrapChromeVoid((callback) =>\n chrome.debugger.attach({ tabId }, DEBUGGER_PROTOCOL_VERSION, () =>\n callback()\n )\n );\n\n try {\n await session.attachPromise;\n session.attached = true;\n session.attachPromise = undefined;\n const initError = await this.initializeDebuggerDomains(tabId);\n if (initError) {\n await this.detachDebugger(tabId);\n return initError;\n }\n session.initialized = true;\n this.touchDebuggerSession(tabId);\n return null;\n } catch (error) {\n const info = mapDebuggerErrorMessage(\n error instanceof Error ? error.message : 'Debugger attach failed.'\n );\n this.clearDebuggerSession(tabId);\n return info;\n }\n }\n\n private async initializeDebuggerDomains(\n tabId: number\n ): Promise<DriveErrorInfo | null> {\n // Some CDP features (notably JS dialog handling + console/network events)\n // require domains to be enabled first. This must happen before a dialog\n // opens, otherwise Page.handleJavaScriptDialog can return \"No dialog is showing\".\n const methods: Array<[string, Record<string, unknown> | undefined]> = [\n ['Page.enable', undefined],\n ['Runtime.enable', undefined],\n ['Log.enable', undefined],\n ['Network.enable', undefined],\n ];\n\n try {\n for (const [method, params] of methods) {\n await this.sendDebuggerCommand(\n tabId,\n method,\n params,\n DEFAULT_DEBUGGER_COMMAND_TIMEOUT_MS\n );\n }\n return null;\n } catch (error) {\n return mapDebuggerErrorMessage(\n error instanceof Error\n ? error.message\n : 'Debugger initialization failed.'\n );\n }\n }\n\n private async checkDebuggerTarget(\n tabId: number\n ): Promise<DriveErrorInfo | null> {\n try {\n const tab = await getTab(tabId);\n const url = typeof tab.url === 'string' ? tab.url : undefined;\n if (isRestrictedUrl(url)) {\n return {\n code: 'NOT_SUPPORTED',\n message: 'Debugger cannot attach to restricted pages.',\n retryable: false,\n details: { url },\n };\n }\n } catch (error) {\n return mapDebuggerErrorMessage(\n error instanceof Error ? error.message : 'Failed to locate tab.',\n 'TAB_NOT_FOUND'\n );\n }\n return null;\n }\n\n private async detachDebugger(tabId: number): Promise<DriveErrorInfo | null> {\n const session = this.debuggerSessions.get(tabId);\n if (!session) {\n return null;\n }\n if (session.attachPromise) {\n try {\n await session.attachPromise;\n } catch (error) {\n console.debug('Debugger attach promise failed before detach.', error);\n this.clearDebuggerSession(tabId);\n return null;\n }\n }\n if (!session.attached) {\n this.clearDebuggerSession(tabId);\n return null;\n }\n try {\n await wrapChromeVoid((callback) =>\n chrome.debugger.detach({ tabId }, () => callback())\n );\n } catch (error) {\n return mapDebuggerErrorMessage(\n error instanceof Error ? error.message : 'Debugger detach failed.'\n );\n } finally {\n this.clearDebuggerSession(tabId);\n }\n return null;\n }\n\n private async sendDebuggerCommand(\n tabId: number,\n method: string,\n params: Record<string, unknown> | undefined,\n timeoutMs: number\n ): Promise<unknown> {\n return await new Promise((resolve, reject) => {\n let finished = false;\n const timeout = self.setTimeout(() => {\n finished = true;\n reject(new DebuggerTimeoutError(timeoutMs));\n }, timeoutMs);\n\n chrome.debugger.sendCommand(\n { tabId },\n method,\n params ?? {},\n (result: unknown) => {\n if (finished) {\n return;\n }\n finished = true;\n clearTimeout(timeout);\n const error = chrome.runtime.lastError;\n if (error) {\n reject(new Error(error.message));\n return;\n }\n resolve(result);\n }\n );\n });\n }\n\n private touchDebuggerSession(tabId: number): void {\n const session = this.debuggerSessions.get(tabId);\n if (!session) {\n return;\n }\n session.lastActivityAt = nowIso();\n void this.refreshDebuggerIdleTimer(tabId).catch((error) => {\n console.error('DriveSocket refreshDebuggerIdleTimer failed:', error);\n });\n }\n\n private async refreshDebuggerIdleTimer(tabId: number): Promise<void> {\n const session = this.debuggerSessions.get(tabId);\n if (!session) {\n return;\n }\n if (session.idleTimer) {\n clearTimeout(session.idleTimer);\n }\n const timeoutMs = await this.getDebuggerIdleTimeoutMs();\n session.idleTimer = self.setTimeout(() => {\n void this.detachDebugger(tabId).catch((error) => {\n console.error('DriveSocket detachDebugger failed:', error);\n });\n }, timeoutMs);\n }\n\n private clearDebuggerSession(tabId: number): void {\n const session = this.debuggerSessions.get(tabId);\n if (!session) {\n return;\n }\n if (session.idleTimer) {\n clearTimeout(session.idleTimer);\n }\n this.debuggerSessions.delete(tabId);\n }\n\n private async getDebuggerIdleTimeoutMs(): Promise<number> {\n if (this.debuggerIdleTimeoutMs !== null) {\n return this.debuggerIdleTimeoutMs;\n }\n const timeout = await readDebuggerIdleTimeoutMs();\n this.debuggerIdleTimeoutMs = timeout;\n return timeout;\n }\n}\n\nclass DebuggerTimeoutError extends Error {\n constructor(timeoutMs: number) {\n super(`Debugger command timed out after ${timeoutMs}ms.`);\n this.name = 'DebuggerTimeoutError';\n }\n}\n\nconst socket = new DriveSocket();\n\nchrome.tabs.onActivated.addListener((activeInfo: { tabId: number }) => {\n markTabActive(activeInfo.tabId);\n socket.sendTabReport();\n});\n\nchrome.tabs.onCreated.addListener((tab: Record<string, unknown>) => {\n if (typeof tab.id === 'number') {\n ensureLastActiveAt(tab.id);\n }\n socket.sendTabReport();\n});\n\nchrome.tabs.onUpdated.addListener(\n (\n tabId: number,\n changeInfo: Record<string, unknown>,\n tab: Record<string, unknown>\n ) => {\n const shouldReport =\n Boolean(changeInfo.url) ||\n Boolean(changeInfo.title) ||\n changeInfo.status === 'complete';\n if (!shouldReport) {\n return;\n }\n if (tab && tab.active) {\n markTabActive(tabId);\n }\n socket.sendTabReport();\n }\n);\n\nchrome.tabs.onRemoved.addListener((tabId: number) => {\n lastActiveAtByTab.delete(tabId);\n socket.sendTabReport();\n});\n\nchrome.debugger.onEvent.addListener(\n (source: DebuggerTarget, method: string, params: Record<string, unknown>) => {\n void socket.handleDebuggerEvent(source, method, params).catch((error) => {\n console.error('DriveSocket handleDebuggerEvent failed:', error);\n });\n }\n);\n\nchrome.debugger.onDetach.addListener(\n (source: DebuggerTarget, reason?: string) => {\n void socket.handleDebuggerDetach(source, reason).catch((error) => {\n console.error('DriveSocket handleDebuggerDetach failed:', error);\n });\n }\n);\n\nsocket.start();\n"],
5
- "mappings": "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",
6
- "names": ["socket", "error"]
4
+ "sourcesContent": ["import type { DriveErrorInfo } from './protocol.js';\n\nconst TRAILING_PUNCTUATION_RE = /[.,;:!?]+$/;\n\nconst stripTrailingPunctuation = (\n value: string\n): {\n core: string;\n trailing: string;\n} => {\n const match = value.match(TRAILING_PUNCTUATION_RE);\n if (!match) {\n return { core: value, trailing: '' };\n }\n const trailing = match[0] ?? '';\n return { core: value.slice(0, -trailing.length), trailing };\n};\n\nconst sanitizeUrlToken = (token: string): string => {\n const { core, trailing } = stripTrailingPunctuation(token);\n try {\n const parsed = new URL(core);\n if (parsed.protocol === 'file:') {\n return `file://[redacted]${trailing}`;\n }\n\n if (parsed.origin && parsed.origin !== 'null') {\n return `${parsed.origin}${trailing}`;\n }\n\n // Non-standard schemes can have a \"null\" origin (chrome://, devtools://, etc).\n // Keep scheme + host and drop everything else.\n if (parsed.protocol && parsed.host) {\n return `${parsed.protocol}//${parsed.host}${trailing}`;\n }\n if (parsed.protocol) {\n return `${parsed.protocol}${trailing}`;\n }\n } catch {\n // Ignore and fall back to a simpler heuristic.\n }\n\n const fallback = core.match(/^([a-zA-Z][a-zA-Z0-9+.-]*):\\/\\/([^/\\s]+)/);\n if (fallback?.[1] && fallback?.[2]) {\n return `${fallback[1]}://${fallback[2]}${trailing}`;\n }\n return `[redacted url]${trailing}`;\n};\n\nconst URL_TOKEN_RE =\n /\\b(?:https?|wss?|chrome-extension|chrome|chrome-devtools|devtools|edge|brave|file):\\/\\/[^\\s\"'<>)}\\]]+/gi;\n\nconst VIEW_SOURCE_RE = /\\bview-source:(https?:\\/\\/[^\\s\"'<>)}\\]]+)/gi;\n\nconst sanitizeUrls = (message: string): string => {\n // Special-case view-source: since it nests another URL.\n let next = message.replace(VIEW_SOURCE_RE, (_match, inner: string) => {\n return `view-source:${sanitizeUrlToken(inner)}`;\n });\n next = next.replace(URL_TOKEN_RE, (match) => sanitizeUrlToken(match));\n return next;\n};\n\nconst extractBasename = (value: string): string => {\n const trimmed = value.trim();\n const lastSlash = Math.max(\n trimmed.lastIndexOf('/'),\n trimmed.lastIndexOf('\\\\')\n );\n if (lastSlash < 0) {\n return trimmed;\n }\n return trimmed.slice(lastSlash + 1);\n};\n\nconst sanitizeWindowsPaths = (message: string): string => {\n // Example: C:\\Users\\me\\project\\file.ts:12:34 -> file.ts:12:34\n const windowsPathRe =\n /\\b[A-Za-z]:\\\\(?:[^\\s\"')\\]}]+\\\\)+[^\\s\"')\\]}]+(?::\\d+(?::\\d+)?)?/g;\n return message.replace(windowsPathRe, (match) => extractBasename(match));\n};\n\nconst sanitizeUnixPaths = (message: string): string => {\n // Only redact paths rooted in common system locations to avoid clobbering\n // generic \"/api/v1\" style strings that might appear in error messages.\n const unixPathRe =\n /\\/(?:Users|home|var|private|tmp|opt|etc|Library|Applications|Volumes|System)(?:\\/[^\\s\"')\\]}]+)+(?::\\d+(?::\\d+)?)?/g;\n return message.replace(unixPathRe, (match) => extractBasename(match));\n};\n\nexport const sanitizeChromeErrorMessage = (message: string): string => {\n let next = message;\n next = sanitizeUrls(next);\n next = sanitizeWindowsPaths(next);\n next = sanitizeUnixPaths(next);\n return next;\n};\n\nconst sanitizeUnknown = (value: unknown): unknown => {\n if (typeof value === 'string') {\n return sanitizeChromeErrorMessage(value);\n }\n if (Array.isArray(value)) {\n return value.map((entry) => sanitizeUnknown(entry));\n }\n if (!value || typeof value !== 'object') {\n return value;\n }\n const record = value as Record<string, unknown>;\n const next: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(record)) {\n next[key] = sanitizeUnknown(entry);\n }\n return next;\n};\n\nexport const sanitizeDriveErrorInfo = (\n error: DriveErrorInfo\n): DriveErrorInfo => {\n return {\n ...error,\n message: sanitizeChromeErrorMessage(error.message),\n ...(error.details\n ? { details: sanitizeUnknown(error.details) as Record<string, unknown> }\n : {}),\n };\n};\n", "import type {\n DebuggerCommandParams,\n DebuggerEvent,\n DebuggerRequest,\n DriveRequest,\n DriveErrorInfo,\n DriveEvent,\n DriveHelloParams,\n DriveResponse,\n DriveTabInfo,\n DriveTabListResult,\n ExtensionMessage,\n ExtensionRequest,\n} from './protocol.js';\nimport { sanitizeDriveErrorInfo } from './error-sanitizer.js';\n\ntype ContentResult =\n | { ok: true; result?: unknown }\n | { ok: false; error: DriveErrorInfo };\n\ntype ContentRequest = {\n action: string;\n params?: Record<string, unknown>;\n};\n\ntype DebuggerTarget = {\n tabId?: number;\n};\n\ntype DebuggerSession = {\n attached: boolean;\n attachPromise?: Promise<void>;\n idleTimer?: number;\n lastActivityAt: string;\n initialized?: boolean;\n};\n\nconst DEFAULT_CORE_PORT = 3210;\nconst CORE_PORT_KEY = 'corePort';\nconst CORE_WS_PATH = '/drive';\n\nconst DEBUGGER_PROTOCOL_VERSION = '1.3';\nconst DEBUGGER_IDLE_TIMEOUT_KEY = 'debuggerIdleTimeoutMs';\nconst DEFAULT_DEBUGGER_IDLE_TIMEOUT_MS = 15000;\nconst DEFAULT_DEBUGGER_COMMAND_TIMEOUT_MS = 10000;\n\nconst nowIso = (): string => new Date().toISOString();\n\nconst makeEventId = (() => {\n let counter = 0;\n return () => `evt-${Date.now()}-${(counter += 1)}`;\n})();\n\nconst lastActiveAtByTab = new Map<number, string>();\n\nconst ensureLastActiveAt = (tabId: number): string => {\n const existing = lastActiveAtByTab.get(tabId);\n if (existing) {\n return existing;\n }\n const timestamp = nowIso();\n lastActiveAtByTab.set(tabId, timestamp);\n return timestamp;\n};\n\nconst markTabActive = (tabId: number): string => {\n const timestamp = nowIso();\n lastActiveAtByTab.set(tabId, timestamp);\n return timestamp;\n};\n\nconst wrapChromeCallback = <T>(\n invoker: (callback: (value: T) => void) => void\n): Promise<T> =>\n new Promise<T>((resolve, reject) => {\n invoker((value: T) => {\n const error = chrome.runtime.lastError;\n if (error) {\n reject(new Error(error.message));\n return;\n }\n resolve(value);\n });\n });\n\nconst wrapChromeVoid = (\n invoker: (callback: () => void) => void\n): Promise<void> => {\n return new Promise<void>((resolve, reject) => {\n invoker(() => {\n const error = chrome.runtime.lastError;\n if (error) {\n reject(new Error(error.message));\n return;\n }\n resolve();\n });\n });\n};\n\nconst delayMs = async (ms: number): Promise<void> => {\n if (!Number.isFinite(ms) || ms <= 0) {\n return;\n }\n await new Promise<void>((resolve) => {\n self.setTimeout(resolve, ms);\n });\n};\n\nconst parseDataUrl = (\n dataUrl: string\n): { mime: string; base64: string } | null => {\n const match = /^data:([^;]+);base64,(.*)$/s.exec(dataUrl);\n if (!match) {\n return null;\n }\n return { mime: match[1] ?? 'application/octet-stream', base64: match[2] };\n};\n\nconst arrayBufferToBase64 = (buffer: ArrayBuffer): string => {\n const bytes = new Uint8Array(buffer);\n const chunkSize = 0x8000;\n let binary = '';\n for (let i = 0; i < bytes.length; i += chunkSize) {\n const chunk = bytes.subarray(i, i + chunkSize);\n binary += String.fromCharCode(...chunk);\n }\n return btoa(binary);\n};\n\nconst renderDataUrlToFormat = async (\n dataUrl: string,\n format: 'png' | 'jpeg' | 'webp',\n quality?: number\n): Promise<{\n mime: string;\n data_base64: string;\n width_px: number;\n height_px: number;\n}> => {\n const parsed = parseDataUrl(dataUrl);\n if (!parsed) {\n throw new Error('Invalid screenshot data URL.');\n }\n\n const blob = await (await fetch(dataUrl)).blob();\n const bitmap = await createImageBitmap(blob);\n try {\n const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n throw new Error('Canvas context unavailable.');\n }\n ctx.drawImage(bitmap, 0, 0);\n\n const mime =\n format === 'jpeg'\n ? 'image/jpeg'\n : format === 'webp'\n ? 'image/webp'\n : 'image/png';\n const q =\n typeof quality === 'number' && Number.isFinite(quality)\n ? Math.max(0, Math.min(1, quality / 100))\n : undefined;\n const out =\n format === 'png'\n ? await canvas.convertToBlob({ type: mime })\n : await canvas.convertToBlob({ type: mime, quality: q });\n const base64 = arrayBufferToBase64(await out.arrayBuffer());\n\n return {\n mime,\n data_base64: base64,\n width_px: bitmap.width,\n height_px: bitmap.height,\n };\n } finally {\n bitmap.close();\n }\n};\n\nconst readCorePort = async (): Promise<number> => {\n return await new Promise<number>((resolve) => {\n chrome.storage.local.get(\n [CORE_PORT_KEY],\n (result: Record<string, unknown>) => {\n const raw = result?.[CORE_PORT_KEY];\n if (typeof raw === 'number' && Number.isFinite(raw)) {\n resolve(raw);\n return;\n }\n if (typeof raw === 'string') {\n const parsed = Number(raw);\n if (Number.isFinite(parsed)) {\n resolve(parsed);\n return;\n }\n }\n resolve(DEFAULT_CORE_PORT);\n }\n );\n });\n};\n\nconst readDebuggerIdleTimeoutMs = async (): Promise<number> => {\n return await new Promise<number>((resolve) => {\n chrome.storage.local.get(\n [DEBUGGER_IDLE_TIMEOUT_KEY],\n (result: Record<string, unknown>) => {\n const raw = result?.[DEBUGGER_IDLE_TIMEOUT_KEY];\n if (typeof raw === 'number' && Number.isFinite(raw) && raw > 0) {\n resolve(raw);\n return;\n }\n if (typeof raw === 'string') {\n const parsed = Number(raw);\n if (Number.isFinite(parsed) && parsed > 0) {\n resolve(parsed);\n return;\n }\n }\n resolve(DEFAULT_DEBUGGER_IDLE_TIMEOUT_MS);\n }\n );\n });\n};\n\nconst RESTRICTED_URL_PREFIXES = [\n 'chrome://',\n 'chrome-extension://',\n 'chrome-devtools://',\n 'devtools://',\n 'edge://',\n 'brave://',\n 'view-source:',\n];\n\nconst isRestrictedUrl = (url?: string): boolean => {\n if (!url || typeof url !== 'string') {\n return false;\n }\n const lowered = url.toLowerCase();\n if (RESTRICTED_URL_PREFIXES.some((prefix) => lowered.startsWith(prefix))) {\n return true;\n }\n try {\n const parsed = new URL(url);\n if (parsed.hostname === 'chromewebstore.google.com') {\n return true;\n }\n if (parsed.hostname === 'chrome.google.com') {\n return parsed.pathname.startsWith('/webstore');\n }\n } catch (error) {\n console.debug('Ignoring invalid URL in restriction check.', error);\n }\n return false;\n};\n\nconst mapDebuggerErrorMessage = (\n message: string,\n fallbackCode = 'INSPECT_UNAVAILABLE'\n): DriveErrorInfo => {\n const normalized = message.toLowerCase();\n if (\n normalized.includes('already attached') ||\n normalized.includes('another debugger') ||\n normalized.includes('attached to this target')\n ) {\n return {\n code: 'DEBUGGER_IN_USE',\n message:\n 'Debugger already attached. Close DevTools on the target tab and retry.',\n retryable: true,\n details: {\n reason: 'debugger_in_use',\n hint: 'Close DevTools on the target tab and retry.',\n original_message: message,\n },\n };\n }\n if (\n normalized.includes('no tab') ||\n normalized.includes('no target') ||\n normalized.includes('tab id')\n ) {\n return {\n code: 'TAB_NOT_FOUND',\n message,\n retryable: false,\n };\n }\n if (\n normalized.includes('not allowed') ||\n normalized.includes('permission') ||\n normalized.includes('denied')\n ) {\n return {\n code: 'ATTACH_DENIED',\n message,\n retryable: false,\n };\n }\n if (\n normalized.includes('cannot access') ||\n normalized.includes('not supported') ||\n normalized.includes('disallowed')\n ) {\n return {\n code: 'NOT_SUPPORTED',\n message,\n retryable: false,\n };\n }\n return {\n code: fallbackCode,\n message,\n retryable: false,\n };\n};\n\nconst buildTabInfo = (tab: Record<string, unknown>): DriveTabInfo | null => {\n const tabId = tab.id;\n const windowId = tab.windowId;\n if (typeof tabId !== 'number' || typeof windowId !== 'number') {\n return null;\n }\n return {\n tab_id: tabId,\n window_id: windowId,\n url: typeof tab.url === 'string' ? tab.url : undefined,\n title: typeof tab.title === 'string' ? tab.title : undefined,\n active: typeof tab.active === 'boolean' ? tab.active : undefined,\n last_active_at: ensureLastActiveAt(tabId),\n };\n};\n\nconst queryTabs = async (): Promise<DriveTabInfo[]> => {\n const tabs = await wrapChromeCallback<Record<string, unknown>[]>((callback) =>\n chrome.tabs.query({}, callback)\n );\n const result: DriveTabInfo[] = [];\n for (const tab of tabs) {\n const info = buildTabInfo(tab);\n if (info) {\n result.push(info);\n }\n }\n return result;\n};\n\nconst getTab = async (tabId: number): Promise<Record<string, unknown>> => {\n return await wrapChromeCallback<Record<string, unknown>>((callback) =>\n chrome.tabs.get(tabId, callback)\n );\n};\n\nconst getActiveTabId = async (): Promise<number> => {\n const tabs = await wrapChromeCallback<Record<string, unknown>[]>((callback) =>\n chrome.tabs.query({ active: true, lastFocusedWindow: true }, callback)\n );\n const first = tabs[0];\n if (first && typeof first.id === 'number') {\n return first.id;\n }\n throw new Error('No active tab found.');\n};\n\nconst sendToTab = async (\n tabId: number,\n action: string,\n params?: Record<string, unknown>\n): Promise<ContentResult> => {\n return await new Promise<ContentResult>((resolve) => {\n const message: ContentRequest = { action, params };\n chrome.tabs.sendMessage(tabId, message, (response: ContentResult) => {\n const error = chrome.runtime.lastError;\n if (error) {\n resolve({\n ok: false,\n error: {\n code: 'EVALUATION_FAILED',\n message: error.message,\n retryable: false,\n },\n });\n return;\n }\n if (!response || typeof response !== 'object') {\n resolve({\n ok: false,\n error: {\n code: 'EVALUATION_FAILED',\n message: 'Empty response from content script.',\n retryable: false,\n },\n });\n return;\n }\n resolve(response);\n });\n });\n};\n\nconst waitForDomContentLoaded = async (\n tabId: number,\n timeoutMs: number\n): Promise<void> => {\n return await new Promise<void>((resolve, reject) => {\n let timeout: number | undefined;\n const cleanup = () => {\n if (timeout !== undefined) {\n clearTimeout(timeout);\n }\n chrome.webNavigation.onDOMContentLoaded.removeListener(listener);\n };\n\n const listener = (details: { tabId: number; frameId: number }) => {\n if (details.tabId !== tabId || details.frameId !== 0) {\n return;\n }\n cleanup();\n resolve();\n };\n\n chrome.webNavigation.onDOMContentLoaded.addListener(listener);\n timeout = self.setTimeout(() => {\n cleanup();\n reject(new Error('Timed out waiting for domcontentloaded.'));\n }, timeoutMs);\n });\n};\n\nconst getWsUrl = async (): Promise<string> => {\n const port = await readCorePort();\n return `ws://127.0.0.1:${port}${CORE_WS_PATH}`;\n};\n\nclass DriveSocket {\n private socket: WebSocket | null = null;\n private reconnectTimer: number | null = null;\n private reconnectDelayMs = 1000;\n private readonly maxReconnectDelayMs = 10000;\n private keepAliveTimer: number | null = null;\n private readonly keepAliveIntervalMs = 30000;\n private readonly debuggerSessions = new Map<number, DebuggerSession>();\n private debuggerIdleTimeoutMs: number | null = null;\n\n start(): void {\n void this.connect().catch((error) => {\n console.error('DriveSocket connect failed:', error);\n });\n }\n\n stop(): void {\n if (this.reconnectTimer !== null) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n this.stopKeepAlive();\n if (this.socket) {\n this.socket.close();\n this.socket = null;\n }\n }\n\n sendTabReport(): void {\n void this.emitTabReport().catch((error) => {\n console.error('DriveSocket emitTabReport failed:', error);\n });\n }\n\n private scheduleReconnect(): void {\n if (this.reconnectTimer !== null) {\n return;\n }\n const delay = this.reconnectDelayMs;\n this.reconnectTimer = self.setTimeout(() => {\n this.reconnectTimer = null;\n void this.connect().catch((error) => {\n console.error('DriveSocket reconnect failed:', error);\n });\n }, delay);\n this.reconnectDelayMs = Math.min(\n this.maxReconnectDelayMs,\n this.reconnectDelayMs * 2\n );\n }\n\n private async connect(): Promise<void> {\n const url = await getWsUrl();\n try {\n const socket = new WebSocket(url);\n this.socket = socket;\n\n socket.addEventListener('open', () => {\n this.reconnectDelayMs = 1000;\n this.startKeepAlive();\n void this.sendHello().catch((error) => {\n console.error('DriveSocket hello failed:', error);\n });\n });\n\n socket.addEventListener('message', (event) => {\n this.handleMessage(event.data);\n });\n\n socket.addEventListener('close', () => {\n this.socket = null;\n this.stopKeepAlive();\n this.scheduleReconnect();\n });\n\n socket.addEventListener('error', () => {\n this.socket = null;\n this.stopKeepAlive();\n this.scheduleReconnect();\n });\n } catch (error) {\n console.debug('DriveSocket connect failed, scheduling reconnect.', error);\n this.scheduleReconnect();\n }\n }\n\n private async sendHello(): Promise<void> {\n const manifest = chrome.runtime.getManifest();\n let tabs: DriveTabInfo[] = [];\n try {\n tabs = await queryTabs();\n } catch (error) {\n console.debug('DriveSocket sendHello failed to read tabs.', error);\n tabs = [];\n }\n const params: DriveHelloParams = {\n version: manifest.version,\n tabs,\n };\n this.sendEvent('drive.hello', params);\n }\n\n private async emitTabReport(): Promise<void> {\n try {\n const tabs = await queryTabs();\n this.sendEvent('drive.tab_report', { tabs });\n } catch (error) {\n console.debug('DriveSocket emitTabReport failed.', error);\n }\n }\n\n private sendEvent(\n action: DriveEvent['action'],\n params: DriveEvent['params']\n ): void {\n const message: DriveEvent = {\n id: makeEventId(),\n action,\n status: 'event',\n params,\n };\n this.sendMessage(message);\n }\n\n private startKeepAlive(): void {\n this.stopKeepAlive();\n this.keepAliveTimer = self.setInterval(() => {\n if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {\n return;\n }\n this.sendEvent('drive.keepalive', {});\n }, this.keepAliveIntervalMs);\n }\n\n private stopKeepAlive(): void {\n if (this.keepAliveTimer !== null) {\n clearInterval(this.keepAliveTimer);\n this.keepAliveTimer = null;\n }\n }\n\n private sendDebuggerEvent(params: DebuggerEvent['params']): void {\n const message: DebuggerEvent = {\n id: makeEventId(),\n action: 'debugger.event',\n status: 'event',\n params,\n };\n this.sendMessage(message);\n }\n\n private sendMessage(message: ExtensionMessage): void {\n if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {\n return;\n }\n this.socket.send(JSON.stringify(message));\n }\n\n private handleMessage(raw: unknown): void {\n if (typeof raw !== 'string') {\n return;\n }\n let message: ExtensionMessage | null = null;\n try {\n message = JSON.parse(raw) as ExtensionMessage;\n } catch (error) {\n console.debug('DriveSocket received invalid JSON message.', error);\n return;\n }\n if (!message || typeof message !== 'object') {\n return;\n }\n if (message.status === 'request') {\n void this.handleRequest(message as ExtensionRequest).catch((error) => {\n console.error('DriveSocket handleRequest failed:', error);\n });\n }\n }\n\n private async handleRequest(message: ExtensionRequest): Promise<void> {\n let driveMessage: DriveRequest | null = null;\n const respondOk = (result?: unknown): void => {\n if (!driveMessage) {\n return;\n }\n const response: DriveResponse = {\n id: driveMessage.id,\n action: driveMessage.action,\n status: 'ok',\n result,\n };\n this.sendMessage(response);\n };\n\n const respondError = (error: DriveErrorInfo): void => {\n if (!driveMessage) {\n return;\n }\n const response: DriveResponse = {\n id: driveMessage.id,\n action: driveMessage.action,\n status: 'error',\n error: sanitizeDriveErrorInfo(error),\n };\n this.sendMessage(response);\n };\n\n try {\n if (\n !message ||\n typeof message !== 'object' ||\n typeof message.id !== 'string' ||\n typeof message.action !== 'string'\n ) {\n return;\n }\n if (message.action.startsWith('debugger.')) {\n await this.handleDebuggerRequest(message as DebuggerRequest);\n return;\n }\n\n if (!message.action.startsWith('drive.')) {\n return;\n }\n\n driveMessage = message as DriveRequest;\n switch (message.action) {\n case 'drive.ping': {\n respondOk({ ok: true });\n return;\n }\n case 'drive.navigate': {\n const params = (message.params ?? {}) as Record<string, unknown>;\n const url = params.url;\n if (typeof url !== 'string' || url.length === 0) {\n respondError({\n code: 'INVALID_ARGUMENT',\n message: 'url must be a non-empty string.',\n retryable: false,\n });\n return;\n }\n let tabId = params.tab_id;\n if (tabId !== undefined && typeof tabId !== 'number') {\n respondError({\n code: 'INVALID_ARGUMENT',\n message: 'tab_id must be a number when provided.',\n retryable: false,\n });\n return;\n }\n if (tabId === undefined) {\n tabId = await getActiveTabId();\n }\n const waitMode =\n params.wait === 'none' || params.wait === 'domcontentloaded'\n ? params.wait\n : 'domcontentloaded';\n await wrapChromeVoid((callback) =>\n chrome.tabs.update(tabId as number, { url }, () => callback())\n );\n markTabActive(tabId as number);\n if (waitMode === 'domcontentloaded') {\n try {\n await waitForDomContentLoaded(tabId as number, 30000);\n } catch (error) {\n respondError({\n code: 'TIMEOUT',\n message:\n error instanceof Error ? error.message : 'Timed out waiting.',\n retryable: true,\n });\n return;\n }\n }\n respondOk({ ok: true });\n return;\n }\n case 'drive.go_back':\n case 'drive.back':\n case 'drive.go_forward':\n case 'drive.forward': {\n const params = (message.params ?? {}) as Record<string, unknown>;\n let tabId = params.tab_id;\n if (tabId !== undefined && typeof tabId !== 'number') {\n respondError({\n code: 'INVALID_ARGUMENT',\n message: 'tab_id must be a number when provided.',\n retryable: false,\n });\n return;\n }\n if (tabId === undefined) {\n tabId = await getActiveTabId();\n }\n try {\n const isBack =\n message.action === 'drive.go_back' ||\n message.action === 'drive.back';\n await wrapChromeVoid((callback) => {\n if (isBack) {\n chrome.tabs.goBack(tabId as number, () => callback());\n } else {\n chrome.tabs.goForward(tabId as number, () => callback());\n }\n });\n } catch (error) {\n respondError({\n code: 'FAILED_PRECONDITION',\n message:\n error instanceof Error ? error.message : 'No history entry.',\n retryable: false,\n });\n return;\n }\n markTabActive(tabId as number);\n try {\n await waitForDomContentLoaded(tabId as number, 30000);\n } catch (error) {\n respondError({\n code: 'TIMEOUT',\n message:\n error instanceof Error ? error.message : 'Timed out waiting.',\n retryable: true,\n });\n return;\n }\n respondOk({ ok: true });\n return;\n }\n case 'drive.tab_list': {\n const tabs = await queryTabs();\n const result: DriveTabListResult = { tabs };\n respondOk(result);\n return;\n }\n case 'drive.tab_activate': {\n const tabId = (message.params as Record<string, unknown> | undefined)\n ?.tab_id;\n if (typeof tabId !== 'number') {\n respondError({\n code: 'INVALID_ARGUMENT',\n message: 'tab_id must be a number.',\n retryable: false,\n });\n return;\n }\n const tab = await getTab(tabId);\n await wrapChromeVoid((callback) =>\n chrome.tabs.update(tabId, { active: true }, () => callback())\n );\n const windowId = tab.windowId;\n if (typeof windowId === 'number') {\n await wrapChromeVoid((callback) =>\n chrome.windows.update(windowId, { focused: true }, () =>\n callback()\n )\n );\n }\n markTabActive(tabId);\n respondOk({ ok: true });\n this.sendTabReport();\n return;\n }\n case 'drive.tab_close': {\n const tabId = (message.params as Record<string, unknown> | undefined)\n ?.tab_id;\n if (typeof tabId !== 'number') {\n respondError({\n code: 'INVALID_ARGUMENT',\n message: 'tab_id must be a number.',\n retryable: false,\n });\n return;\n }\n await wrapChromeVoid((callback) =>\n chrome.tabs.remove(tabId, () => callback())\n );\n lastActiveAtByTab.delete(tabId);\n respondOk({ ok: true });\n this.sendTabReport();\n return;\n }\n case 'drive.handle_dialog': {\n const params = (message.params ?? {}) as Record<string, unknown>;\n const action = params.action;\n if (action !== 'accept' && action !== 'dismiss') {\n respondError({\n code: 'INVALID_ARGUMENT',\n message: 'action must be accept or dismiss.',\n retryable: false,\n });\n return;\n }\n const promptText = params.promptText;\n if (promptText !== undefined && typeof promptText !== 'string') {\n respondError({\n code: 'INVALID_ARGUMENT',\n message: 'promptText must be a string when provided.',\n retryable: false,\n });\n return;\n }\n let tabId = params.tab_id;\n if (tabId !== undefined && typeof tabId !== 'number') {\n respondError({\n code: 'INVALID_ARGUMENT',\n message: 'tab_id must be a number when provided.',\n retryable: false,\n });\n return;\n }\n if (tabId === undefined) {\n tabId = await getActiveTabId();\n }\n\n const error = await this.ensureDebuggerAttached(tabId as number);\n if (error) {\n respondError(error);\n return;\n }\n\n try {\n await this.sendDebuggerCommand(\n tabId as number,\n 'Page.handleJavaScriptDialog',\n {\n accept: action === 'accept',\n ...(promptText ? { promptText } : {}),\n },\n DEFAULT_DEBUGGER_COMMAND_TIMEOUT_MS\n );\n this.touchDebuggerSession(tabId as number);\n respondOk({ ok: true });\n } catch (error) {\n const info = mapDebuggerErrorMessage(\n error instanceof Error ? error.message : 'Dialog handling failed.'\n );\n respondError(info);\n }\n return;\n }\n case 'drive.click':\n case 'drive.hover':\n case 'drive.select':\n case 'drive.type':\n case 'drive.fill_form':\n case 'drive.drag':\n case 'drive.key':\n case 'drive.key_press':\n case 'drive.scroll':\n case 'drive.wait_for': {\n const params = (message.params ?? {}) as Record<string, unknown>;\n let tabId = params.tab_id;\n if (tabId !== undefined && typeof tabId !== 'number') {\n respondError({\n code: 'INVALID_ARGUMENT',\n message: 'tab_id must be a number when provided.',\n retryable: false,\n });\n return;\n }\n if (tabId === undefined) {\n tabId = await getActiveTabId();\n }\n const result = await sendToTab(\n tabId as number,\n message.action,\n params\n );\n if (result.ok) {\n respondOk(result.result ?? { ok: true });\n } else {\n respondError(result.error);\n }\n return;\n }\n case 'drive.screenshot': {\n const params = (message.params ?? {}) as Record<string, unknown>;\n let tabId = params.tab_id;\n if (tabId !== undefined && typeof tabId !== 'number') {\n respondError({\n code: 'INVALID_ARGUMENT',\n message: 'tab_id must be a number when provided.',\n retryable: false,\n });\n return;\n }\n if (tabId === undefined) {\n tabId = await getActiveTabId();\n }\n\n const mode =\n params.mode === 'full_page' ||\n params.mode === 'viewport' ||\n params.mode === 'element'\n ? params.mode\n : 'viewport';\n const format =\n params.format === 'jpeg' || params.format === 'webp'\n ? params.format\n : 'png';\n const quality =\n typeof params.quality === 'number' &&\n Number.isFinite(params.quality)\n ? Math.max(0, Math.min(100, Math.floor(params.quality)))\n : undefined;\n\n const tab = await getTab(tabId as number);\n const url = tab.url;\n if (typeof url === 'string' && isRestrictedUrl(url)) {\n respondError({\n code: 'NOT_SUPPORTED',\n message: 'Screenshots are not supported for this URL.',\n retryable: false,\n details: { url },\n });\n return;\n }\n const windowId = tab.windowId;\n if (typeof windowId !== 'number') {\n respondError({\n code: 'TAB_NOT_FOUND',\n message: 'window_id missing for tab.',\n retryable: false,\n });\n return;\n }\n\n if (typeof OffscreenCanvas === 'undefined') {\n respondError({\n code: 'NOT_SUPPORTED',\n message: 'OffscreenCanvas is unavailable in this extension host.',\n retryable: false,\n });\n return;\n }\n\n const captureVisible = async (): Promise<string> => {\n return await wrapChromeCallback<string>((callback) =>\n chrome.tabs.captureVisibleTab(\n windowId,\n { format: 'png' },\n callback\n )\n );\n };\n\n const scrollTo = async (top: number, left: number): Promise<void> => {\n const result = await sendToTab(tabId as number, 'drive.scroll', {\n top,\n left,\n behavior: 'auto',\n tab_id: tabId,\n });\n if (!result.ok) {\n throw new Error(result.error.message);\n }\n };\n\n const getMetaInfo = async (): Promise<{\n viewportHeight: number;\n scrollHeight: number;\n scrollY: number;\n scrollX: number;\n devicePixelRatio: number;\n fullHeightPx: number;\n positions: number[];\n }> => {\n const meta = await sendToTab(\n tabId as number,\n 'drive.screenshot_meta'\n );\n if (!meta.ok) {\n throw new Error(meta.error.message);\n }\n const payload = meta.result;\n if (!payload || typeof payload !== 'object') {\n throw new Error('Invalid screenshot metadata response.');\n }\n\n const record = payload as Record<string, unknown>;\n const viewportHeight = record.viewportHeight;\n const scrollHeight = record.scrollHeight;\n const scrollY = record.scrollY;\n const scrollX = record.scrollX;\n const dpr = record.devicePixelRatio;\n\n if (\n typeof viewportHeight !== 'number' ||\n !Number.isFinite(viewportHeight) ||\n viewportHeight <= 0\n ) {\n throw new Error(\n 'viewportHeight missing from screenshot metadata.'\n );\n }\n if (\n typeof scrollHeight !== 'number' ||\n !Number.isFinite(scrollHeight) ||\n scrollHeight <= 0\n ) {\n throw new Error('scrollHeight missing from screenshot metadata.');\n }\n\n const devicePixelRatio =\n typeof dpr === 'number' && Number.isFinite(dpr) && dpr > 0\n ? dpr\n : 1;\n\n const fullHeightPx = Math.round(scrollHeight * devicePixelRatio);\n const maxHeightPx = 50000;\n if (fullHeightPx > maxHeightPx) {\n throw new Error(\n `Page is too tall to capture (max ${maxHeightPx}px).`\n );\n }\n\n const maxScrollY = Math.max(0, scrollHeight - viewportHeight);\n const step = viewportHeight;\n const positions: number[] = [];\n for (let y = 0; y < maxScrollY; y += step) {\n positions.push(y);\n }\n positions.push(maxScrollY);\n\n const maxTiles = 200;\n if (positions.length > maxTiles) {\n throw new Error(\n `Page requires too many tiles to capture (${positions.length}).`\n );\n }\n\n return {\n viewportHeight,\n scrollHeight,\n scrollY:\n typeof scrollY === 'number' && Number.isFinite(scrollY)\n ? scrollY\n : 0,\n scrollX:\n typeof scrollX === 'number' && Number.isFinite(scrollX)\n ? scrollX\n : 0,\n devicePixelRatio,\n fullHeightPx,\n positions,\n };\n };\n\n const canvasToResult = async (\n canvas: OffscreenCanvas\n ): Promise<{\n mime: string;\n data_base64: string;\n width_px: number;\n height_px: number;\n }> => {\n const mime =\n format === 'jpeg'\n ? 'image/jpeg'\n : format === 'webp'\n ? 'image/webp'\n : 'image/png';\n const q =\n typeof quality === 'number' && Number.isFinite(quality)\n ? Math.max(0, Math.min(1, quality / 100))\n : undefined;\n const blob =\n format === 'png'\n ? await canvas.convertToBlob({ type: mime })\n : await canvas.convertToBlob({ type: mime, quality: q });\n const base64 = arrayBufferToBase64(await blob.arrayBuffer());\n return {\n mime,\n data_base64: base64,\n width_px: canvas.width,\n height_px: canvas.height,\n };\n };\n\n const captureFullPageCanvas = async (\n metaInfo: Awaited<ReturnType<typeof getMetaInfo>>\n ): Promise<OffscreenCanvas> => {\n try {\n await scrollTo(0, 0);\n await delayMs(100);\n\n const firstDataUrl = await captureVisible();\n const firstBlob = await (await fetch(firstDataUrl)).blob();\n const firstBitmap = await createImageBitmap(firstBlob);\n\n const canvas = new OffscreenCanvas(\n firstBitmap.width,\n metaInfo.fullHeightPx\n );\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n firstBitmap.close();\n throw new Error('Canvas context unavailable.');\n }\n\n const drawTile = (bitmap: ImageBitmap, yCss: number): void => {\n const destY = Math.round(yCss * metaInfo.devicePixelRatio);\n const remaining = metaInfo.fullHeightPx - destY;\n if (remaining <= 0) {\n return;\n }\n const drawHeight = Math.min(bitmap.height, remaining);\n ctx.drawImage(\n bitmap,\n 0,\n 0,\n bitmap.width,\n drawHeight,\n 0,\n destY,\n bitmap.width,\n drawHeight\n );\n };\n\n drawTile(firstBitmap, 0);\n firstBitmap.close();\n\n for (const y of metaInfo.positions.slice(1)) {\n await scrollTo(y, 0);\n await delayMs(100);\n const dataUrl = await captureVisible();\n const blob = await (await fetch(dataUrl)).blob();\n const bitmap = await createImageBitmap(blob);\n drawTile(bitmap, y);\n bitmap.close();\n }\n\n return canvas;\n } finally {\n try {\n await scrollTo(metaInfo.scrollY, metaInfo.scrollX);\n } catch {\n // Ignore restoration errors.\n }\n }\n };\n\n if (mode === 'viewport') {\n try {\n const dataUrl = await captureVisible();\n const rendered = await renderDataUrlToFormat(\n dataUrl,\n format,\n quality\n );\n respondOk(rendered);\n } catch (error) {\n respondError({\n code: 'ARTIFACT_IO_ERROR',\n message:\n error instanceof Error\n ? error.message\n : 'Failed to capture screenshot.',\n retryable: false,\n });\n }\n return;\n }\n\n if (mode === 'element') {\n const selector = params.selector;\n if (typeof selector !== 'string' || selector.trim().length === 0) {\n respondError({\n code: 'INVALID_ARGUMENT',\n message: 'selector must be a non-empty string.',\n retryable: false,\n });\n return;\n }\n\n let metaInfo: Awaited<ReturnType<typeof getMetaInfo>>;\n try {\n metaInfo = await getMetaInfo();\n } catch (error) {\n respondError({\n code: 'EVALUATION_FAILED',\n message:\n error instanceof Error\n ? error.message\n : 'Failed to read screenshot metadata.',\n retryable: false,\n });\n return;\n }\n\n const element = await sendToTab(\n tabId as number,\n 'drive.screenshot_element',\n { selector }\n );\n if (!element.ok) {\n respondError(element.error);\n return;\n }\n\n const payload = element.result;\n if (!payload || typeof payload !== 'object') {\n respondError({\n code: 'EVALUATION_FAILED',\n message: 'Invalid element metadata response.',\n retryable: false,\n });\n return;\n }\n\n const record = payload as Record<string, unknown>;\n const viewportLeft = record.viewportLeft;\n const viewportTop = record.viewportTop;\n const viewportWidth = record.viewportWidth;\n const viewportHeight = record.viewportHeight;\n const width = record.width;\n const height = record.height;\n const pageX = record.pageX;\n const pageY = record.pageY;\n const dpr = record.devicePixelRatio;\n const devicePixelRatio =\n typeof dpr === 'number' && Number.isFinite(dpr) && dpr > 0\n ? dpr\n : metaInfo.devicePixelRatio;\n\n if (\n typeof viewportLeft !== 'number' ||\n typeof viewportTop !== 'number' ||\n typeof viewportWidth !== 'number' ||\n typeof viewportHeight !== 'number' ||\n typeof width !== 'number' ||\n typeof height !== 'number' ||\n typeof pageX !== 'number' ||\n typeof pageY !== 'number' ||\n !Number.isFinite(viewportLeft) ||\n !Number.isFinite(viewportTop) ||\n !Number.isFinite(viewportWidth) ||\n !Number.isFinite(viewportHeight) ||\n !Number.isFinite(width) ||\n !Number.isFinite(height) ||\n !Number.isFinite(pageX) ||\n !Number.isFinite(pageY)\n ) {\n respondError({\n code: 'EVALUATION_FAILED',\n message: 'Invalid element bounding box metadata.',\n retryable: false,\n });\n return;\n }\n\n const fitsInViewport =\n viewportLeft >= 0 &&\n viewportTop >= 0 &&\n viewportLeft + width <= viewportWidth &&\n viewportTop + height <= viewportHeight;\n\n const cropW = Math.max(1, Math.round(width * devicePixelRatio));\n const cropH = Math.max(1, Math.round(height * devicePixelRatio));\n\n try {\n if (fitsInViewport) {\n const dataUrl = await captureVisible();\n const blob = await (await fetch(dataUrl)).blob();\n const bitmap = await createImageBitmap(blob);\n try {\n const cropX = Math.max(\n 0,\n Math.round(viewportLeft * devicePixelRatio)\n );\n const cropY = Math.max(\n 0,\n Math.round(viewportTop * devicePixelRatio)\n );\n const srcW = Math.min(cropW, bitmap.width - cropX);\n const srcH = Math.min(cropH, bitmap.height - cropY);\n if (srcW <= 0 || srcH <= 0) {\n throw new Error('Element is outside screenshot bounds.');\n }\n const cropCanvas = new OffscreenCanvas(srcW, srcH);\n const ctx = cropCanvas.getContext('2d');\n if (!ctx) {\n throw new Error('Canvas context unavailable.');\n }\n ctx.drawImage(\n bitmap,\n cropX,\n cropY,\n srcW,\n srcH,\n 0,\n 0,\n srcW,\n srcH\n );\n respondOk(await canvasToResult(cropCanvas));\n } finally {\n bitmap.close();\n }\n return;\n }\n\n const fullCanvas = await captureFullPageCanvas(metaInfo);\n const cropX = Math.max(0, Math.round(pageX * devicePixelRatio));\n const cropY = Math.max(0, Math.round(pageY * devicePixelRatio));\n const srcW = Math.min(cropW, fullCanvas.width - cropX);\n const srcH = Math.min(cropH, fullCanvas.height - cropY);\n if (srcW <= 0 || srcH <= 0) {\n throw new Error('Element is outside screenshot bounds.');\n }\n const cropCanvas = new OffscreenCanvas(srcW, srcH);\n const ctx = cropCanvas.getContext('2d');\n if (!ctx) {\n throw new Error('Canvas context unavailable.');\n }\n ctx.drawImage(\n fullCanvas,\n cropX,\n cropY,\n srcW,\n srcH,\n 0,\n 0,\n srcW,\n srcH\n );\n respondOk(await canvasToResult(cropCanvas));\n } catch (error) {\n respondError({\n code: 'ARTIFACT_IO_ERROR',\n message:\n error instanceof Error\n ? error.message\n : 'Failed to capture element screenshot.',\n retryable: false,\n });\n } finally {\n try {\n await scrollTo(metaInfo.scrollY, metaInfo.scrollX);\n } catch {\n // Ignore.\n }\n }\n return;\n }\n\n try {\n const metaInfo = await getMetaInfo();\n const canvas = await captureFullPageCanvas(metaInfo);\n respondOk(await canvasToResult(canvas));\n } catch (error) {\n respondError({\n code: 'ARTIFACT_IO_ERROR',\n message:\n error instanceof Error\n ? error.message\n : 'Failed to capture full page screenshot.',\n retryable: false,\n });\n }\n return;\n }\n default:\n respondError({\n code: 'NOT_IMPLEMENTED',\n message: `${message.action} not implemented in extension yet.`,\n retryable: false,\n });\n }\n } catch (error) {\n const messageText =\n error instanceof Error ? error.message : 'Unknown error';\n respondError({\n code: 'EVALUATION_FAILED',\n message: messageText,\n retryable: false,\n });\n }\n }\n\n private async handleDebuggerRequest(message: DebuggerRequest): Promise<void> {\n const respondAck = (result?: unknown): void => {\n this.sendMessage({\n id: message.id,\n action: message.action,\n status: 'ack',\n result,\n });\n };\n\n const respondError = (error: DriveErrorInfo): void => {\n this.sendMessage({\n id: message.id,\n action: message.action,\n status: 'error',\n error: sanitizeDriveErrorInfo(error),\n });\n };\n\n try {\n switch (message.action) {\n case 'debugger.attach': {\n const params = (message.params ?? {}) as { tab_id?: unknown };\n const tabId = params.tab_id;\n if (typeof tabId !== 'number') {\n respondError({\n code: 'INVALID_ARGUMENT',\n message: 'tab_id must be a number.',\n retryable: false,\n });\n return;\n }\n\n const error = await this.ensureDebuggerAttached(tabId);\n if (error) {\n respondError(error);\n return;\n }\n respondAck({ ok: true });\n return;\n }\n case 'debugger.detach': {\n const params = (message.params ?? {}) as { tab_id?: unknown };\n const tabId = params.tab_id;\n if (typeof tabId !== 'number') {\n respondError({\n code: 'INVALID_ARGUMENT',\n message: 'tab_id must be a number.',\n retryable: false,\n });\n return;\n }\n const error = await this.detachDebugger(tabId);\n if (error) {\n respondError(error);\n return;\n }\n respondAck({ ok: true });\n return;\n }\n case 'debugger.command': {\n const params = (message.params ?? {}) as DebuggerCommandParams;\n const tabId = params.tab_id;\n if (typeof tabId !== 'number') {\n respondError({\n code: 'INVALID_ARGUMENT',\n message: 'tab_id must be a number.',\n retryable: false,\n });\n return;\n }\n if (typeof params.method !== 'string' || params.method.length === 0) {\n respondError({\n code: 'INVALID_ARGUMENT',\n message: 'method must be a non-empty string.',\n retryable: false,\n });\n return;\n }\n\n const session = this.debuggerSessions.get(tabId);\n if (session?.attachPromise) {\n try {\n await session.attachPromise;\n } catch (error) {\n const info = mapDebuggerErrorMessage(\n error instanceof Error\n ? error.message\n : 'Debugger attach failed.'\n );\n this.clearDebuggerSession(tabId);\n respondError(info);\n return;\n }\n }\n\n const attachedSession = this.debuggerSessions.get(tabId);\n if (!attachedSession?.attached) {\n respondError({\n code: 'FAILED_PRECONDITION',\n message: 'Debugger is not attached to the requested tab.',\n retryable: false,\n });\n return;\n }\n\n try {\n const result = await this.sendDebuggerCommand(\n tabId,\n params.method,\n params.params,\n DEFAULT_DEBUGGER_COMMAND_TIMEOUT_MS\n );\n this.touchDebuggerSession(tabId);\n respondAck(result);\n } catch (error) {\n if (error instanceof DebuggerTimeoutError) {\n respondError({\n code: 'TIMEOUT',\n message: error.message,\n retryable: true,\n });\n return;\n }\n const info = mapDebuggerErrorMessage(\n error instanceof Error\n ? error.message\n : 'Debugger command failed.'\n );\n respondError(info);\n }\n return;\n }\n default:\n respondError({\n code: 'NOT_IMPLEMENTED',\n message: `${message.action} not implemented in extension yet.`,\n retryable: false,\n });\n }\n } catch (error) {\n const messageText =\n error instanceof Error ? error.message : 'Unexpected debugger error.';\n respondError({\n code: 'INSPECT_UNAVAILABLE',\n message: messageText,\n retryable: false,\n });\n }\n }\n\n async handleDebuggerEvent(\n source: DebuggerTarget,\n method: string,\n params?: Record<string, unknown>\n ): Promise<void> {\n const tabId = source.tabId;\n if (typeof tabId !== 'number') {\n return;\n }\n this.touchDebuggerSession(tabId);\n this.sendDebuggerEvent({\n tab_id: tabId,\n method,\n params,\n timestamp: nowIso(),\n });\n }\n\n async handleDebuggerDetach(\n source: DebuggerTarget,\n reason?: string\n ): Promise<void> {\n const tabId = source.tabId;\n if (typeof tabId !== 'number') {\n return;\n }\n this.clearDebuggerSession(tabId);\n this.sendDebuggerEvent({\n tab_id: tabId,\n method: 'Debugger.detached',\n params: { reason: reason ?? 'unknown' },\n timestamp: nowIso(),\n });\n }\n\n private async ensureDebuggerAttached(\n tabId: number\n ): Promise<DriveErrorInfo | null> {\n const existing = this.debuggerSessions.get(tabId);\n if (existing?.attached) {\n this.touchDebuggerSession(tabId);\n return null;\n }\n\n if (existing?.attachPromise) {\n try {\n await existing.attachPromise;\n } catch (error) {\n const info = mapDebuggerErrorMessage(\n error instanceof Error ? error.message : 'Debugger attach failed.'\n );\n this.clearDebuggerSession(tabId);\n return info;\n }\n if (existing.attached) {\n this.touchDebuggerSession(tabId);\n return null;\n }\n }\n\n const preflightError = await this.checkDebuggerTarget(tabId);\n if (preflightError) {\n return preflightError;\n }\n\n const session: DebuggerSession = {\n attached: false,\n lastActivityAt: nowIso(),\n };\n this.debuggerSessions.set(tabId, session);\n\n session.attachPromise = wrapChromeVoid((callback) =>\n chrome.debugger.attach({ tabId }, DEBUGGER_PROTOCOL_VERSION, () =>\n callback()\n )\n );\n\n try {\n await session.attachPromise;\n session.attached = true;\n session.attachPromise = undefined;\n const initError = await this.initializeDebuggerDomains(tabId);\n if (initError) {\n await this.detachDebugger(tabId);\n return initError;\n }\n session.initialized = true;\n this.touchDebuggerSession(tabId);\n return null;\n } catch (error) {\n const info = mapDebuggerErrorMessage(\n error instanceof Error ? error.message : 'Debugger attach failed.'\n );\n this.clearDebuggerSession(tabId);\n return info;\n }\n }\n\n private async initializeDebuggerDomains(\n tabId: number\n ): Promise<DriveErrorInfo | null> {\n // Some CDP features (notably JS dialog handling + console/network events)\n // require domains to be enabled first. This must happen before a dialog\n // opens, otherwise Page.handleJavaScriptDialog can return \"No dialog is showing\".\n const methods: Array<[string, Record<string, unknown> | undefined]> = [\n ['Page.enable', undefined],\n ['Runtime.enable', undefined],\n ['Log.enable', undefined],\n ['Network.enable', undefined],\n ];\n\n try {\n for (const [method, params] of methods) {\n await this.sendDebuggerCommand(\n tabId,\n method,\n params,\n DEFAULT_DEBUGGER_COMMAND_TIMEOUT_MS\n );\n }\n return null;\n } catch (error) {\n return mapDebuggerErrorMessage(\n error instanceof Error\n ? error.message\n : 'Debugger initialization failed.'\n );\n }\n }\n\n private async checkDebuggerTarget(\n tabId: number\n ): Promise<DriveErrorInfo | null> {\n try {\n const tab = await getTab(tabId);\n const url = typeof tab.url === 'string' ? tab.url : undefined;\n if (isRestrictedUrl(url)) {\n return {\n code: 'NOT_SUPPORTED',\n message: 'Debugger cannot attach to restricted pages.',\n retryable: false,\n details: { url },\n };\n }\n } catch (error) {\n return mapDebuggerErrorMessage(\n error instanceof Error ? error.message : 'Failed to locate tab.',\n 'TAB_NOT_FOUND'\n );\n }\n return null;\n }\n\n private async detachDebugger(tabId: number): Promise<DriveErrorInfo | null> {\n const session = this.debuggerSessions.get(tabId);\n if (!session) {\n return null;\n }\n if (session.attachPromise) {\n try {\n await session.attachPromise;\n } catch (error) {\n console.debug('Debugger attach promise failed before detach.', error);\n this.clearDebuggerSession(tabId);\n return null;\n }\n }\n if (!session.attached) {\n this.clearDebuggerSession(tabId);\n return null;\n }\n try {\n await wrapChromeVoid((callback) =>\n chrome.debugger.detach({ tabId }, () => callback())\n );\n } catch (error) {\n return mapDebuggerErrorMessage(\n error instanceof Error ? error.message : 'Debugger detach failed.'\n );\n } finally {\n this.clearDebuggerSession(tabId);\n }\n return null;\n }\n\n private async sendDebuggerCommand(\n tabId: number,\n method: string,\n params: Record<string, unknown> | undefined,\n timeoutMs: number\n ): Promise<unknown> {\n return await new Promise((resolve, reject) => {\n let finished = false;\n const timeout = self.setTimeout(() => {\n finished = true;\n reject(new DebuggerTimeoutError(timeoutMs));\n }, timeoutMs);\n\n chrome.debugger.sendCommand(\n { tabId },\n method,\n params ?? {},\n (result: unknown) => {\n if (finished) {\n return;\n }\n finished = true;\n clearTimeout(timeout);\n const error = chrome.runtime.lastError;\n if (error) {\n reject(new Error(error.message));\n return;\n }\n resolve(result);\n }\n );\n });\n }\n\n private touchDebuggerSession(tabId: number): void {\n const session = this.debuggerSessions.get(tabId);\n if (!session) {\n return;\n }\n session.lastActivityAt = nowIso();\n void this.refreshDebuggerIdleTimer(tabId).catch((error) => {\n console.error('DriveSocket refreshDebuggerIdleTimer failed:', error);\n });\n }\n\n private async refreshDebuggerIdleTimer(tabId: number): Promise<void> {\n const session = this.debuggerSessions.get(tabId);\n if (!session) {\n return;\n }\n if (session.idleTimer) {\n clearTimeout(session.idleTimer);\n }\n const timeoutMs = await this.getDebuggerIdleTimeoutMs();\n session.idleTimer = self.setTimeout(() => {\n void this.detachDebugger(tabId).catch((error) => {\n console.error('DriveSocket detachDebugger failed:', error);\n });\n }, timeoutMs);\n }\n\n private clearDebuggerSession(tabId: number): void {\n const session = this.debuggerSessions.get(tabId);\n if (!session) {\n return;\n }\n if (session.idleTimer) {\n clearTimeout(session.idleTimer);\n }\n this.debuggerSessions.delete(tabId);\n }\n\n private async getDebuggerIdleTimeoutMs(): Promise<number> {\n if (this.debuggerIdleTimeoutMs !== null) {\n return this.debuggerIdleTimeoutMs;\n }\n const timeout = await readDebuggerIdleTimeoutMs();\n this.debuggerIdleTimeoutMs = timeout;\n return timeout;\n }\n}\n\nclass DebuggerTimeoutError extends Error {\n constructor(timeoutMs: number) {\n super(`Debugger command timed out after ${timeoutMs}ms.`);\n this.name = 'DebuggerTimeoutError';\n }\n}\n\nconst socket = new DriveSocket();\n\nchrome.tabs.onActivated.addListener((activeInfo: { tabId: number }) => {\n markTabActive(activeInfo.tabId);\n socket.sendTabReport();\n});\n\nchrome.tabs.onCreated.addListener((tab: Record<string, unknown>) => {\n if (typeof tab.id === 'number') {\n ensureLastActiveAt(tab.id);\n }\n socket.sendTabReport();\n});\n\nchrome.tabs.onUpdated.addListener(\n (\n tabId: number,\n changeInfo: Record<string, unknown>,\n tab: Record<string, unknown>\n ) => {\n const shouldReport =\n Boolean(changeInfo.url) ||\n Boolean(changeInfo.title) ||\n changeInfo.status === 'complete';\n if (!shouldReport) {\n return;\n }\n if (tab && tab.active) {\n markTabActive(tabId);\n }\n socket.sendTabReport();\n }\n);\n\nchrome.tabs.onRemoved.addListener((tabId: number) => {\n lastActiveAtByTab.delete(tabId);\n socket.sendTabReport();\n});\n\nchrome.debugger.onEvent.addListener(\n (source: DebuggerTarget, method: string, params: Record<string, unknown>) => {\n void socket.handleDebuggerEvent(source, method, params).catch((error) => {\n console.error('DriveSocket handleDebuggerEvent failed:', error);\n });\n }\n);\n\nchrome.debugger.onDetach.addListener(\n (source: DebuggerTarget, reason?: string) => {\n void socket.handleDebuggerDetach(source, reason).catch((error) => {\n console.error('DriveSocket handleDebuggerDetach failed:', error);\n });\n }\n);\n\nsocket.start();\n"],
5
+ "mappings": "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",
6
+ "names": ["socket", "error", "cropX", "cropY", "srcW", "srcH", "cropCanvas", "ctx"]
7
7
  }
@@ -682,6 +682,77 @@
682
682
  "scroll requires delta_x/delta_y or top/left."
683
683
  );
684
684
  }
685
+ case "drive.screenshot_meta": {
686
+ const root = document.documentElement;
687
+ const body = document.body;
688
+ const scrollWidth = Math.max(
689
+ root?.scrollWidth ?? 0,
690
+ root?.clientWidth ?? 0,
691
+ body?.scrollWidth ?? 0,
692
+ body?.clientWidth ?? 0
693
+ );
694
+ const scrollHeight = Math.max(
695
+ root?.scrollHeight ?? 0,
696
+ root?.clientHeight ?? 0,
697
+ body?.scrollHeight ?? 0,
698
+ body?.clientHeight ?? 0
699
+ );
700
+ return ok({
701
+ scrollX: window.scrollX,
702
+ scrollY: window.scrollY,
703
+ viewportWidth: window.innerWidth,
704
+ viewportHeight: window.innerHeight,
705
+ scrollWidth,
706
+ scrollHeight,
707
+ devicePixelRatio: typeof window.devicePixelRatio === "number" && Number.isFinite(window.devicePixelRatio) && window.devicePixelRatio > 0 ? window.devicePixelRatio : 1
708
+ });
709
+ }
710
+ case "drive.screenshot_element": {
711
+ const { selector } = parseParams();
712
+ if (typeof selector !== "string" || selector.trim().length === 0) {
713
+ return buildError(
714
+ "INVALID_ARGUMENT",
715
+ "selector must be a non-empty string."
716
+ );
717
+ }
718
+ let element = null;
719
+ try {
720
+ element = document.querySelector(selector);
721
+ } catch {
722
+ return buildError(
723
+ "INVALID_ARGUMENT",
724
+ "selector must be a valid CSS selector."
725
+ );
726
+ }
727
+ if (!element) {
728
+ return buildError("INVALID_ARGUMENT", "No element matched selector.");
729
+ }
730
+ try {
731
+ element.scrollIntoView?.({
732
+ block: "center",
733
+ inline: "center"
734
+ });
735
+ } catch {
736
+ }
737
+ const rect = element.getBoundingClientRect();
738
+ const scrollX = window.scrollX;
739
+ const scrollY = window.scrollY;
740
+ const dpr = typeof window.devicePixelRatio === "number" && Number.isFinite(window.devicePixelRatio) && window.devicePixelRatio > 0 ? window.devicePixelRatio : 1;
741
+ return ok({
742
+ selector,
743
+ pageX: rect.left + scrollX,
744
+ pageY: rect.top + scrollY,
745
+ width: rect.width,
746
+ height: rect.height,
747
+ viewportLeft: rect.left,
748
+ viewportTop: rect.top,
749
+ viewportWidth: window.innerWidth,
750
+ viewportHeight: window.innerHeight,
751
+ scrollX,
752
+ scrollY,
753
+ devicePixelRatio: dpr
754
+ });
755
+ }
685
756
  case "drive.wait_for": {
686
757
  const { condition, timeout_ms } = parseParams();
687
758
  if (!condition || typeof condition !== "object") {