{"skill":{"slug":"chrome","displayName":"Chrome","summary":"Chrome DevTools Protocol, extension Manifest V3, and debugging patterns that prevent common automation failures.","description":"---\nname: Chrome\ndescription: Chrome DevTools Protocol, extension Manifest V3, and debugging patterns that prevent common automation failures.\n---\n\n## Chrome DevTools Protocol (CDP)\n\n**Get tab WebSocket URL first**: Never connect to `ws://localhost:9222/devtools/browser` directly. Fetch `http://localhost:9222/json/list` and use `webSocketDebuggerUrl` from the active tab.\n\n**Enable domains before use**: `Runtime.enable` and `Page.enable` must be called before any `Runtime.evaluate` or `Page.navigate` commands.\n\n**CDP is async**: Wait for response before sending next command. Use Promise-based wrapper with response ID tracking.\n\n**Screenshot on high-DPI**: Include `fromSurface: true` and `scale: 2` in `Page.captureScreenshot` params for Retina displays.\n\n**Get response body separately**: `Network.responseReceived` doesn't include body. Call `Network.getResponseBody` with requestId after response completes.\n\n## Chrome Extension Manifest V3\n\n**Permissions split**: Use `permissions` for APIs, `host_permissions` for URLs. Never use `http://*/*` in permissions.\n\n**Service workers terminate**: No persistent state. Use `chrome.storage.local` instead of global variables. Use `chrome.alarms` instead of `setInterval`.\n\n**Content script isolation**: Can't access page globals. Use `chrome.scripting.executeScript` with `func` for page context. Use `window.postMessage` for content↔page communication.\n\n**Storage is async**: `chrome.storage.local.get()` returns Promise, not data. Always await. Handle `QUOTA_EXCEEDED` errors.\n\n## Context Detection\n\n**Detect actual Chrome** (not Edge/Brave): Check `window.chrome && navigator.vendor === \"Google Inc.\"` and exclude Opera/Edge.\n\n**Extension context types**:\n- `chrome.runtime.id` exists → content script\n- `chrome.runtime.getManifest` exists → popup/background/options\n- `chrome.loadTimes` exists but no runtime → regular Chrome web page\n\n**Manifest version check**: Wrap `chrome.runtime.getManifest()` in try-catch. Use `chrome.action` for V3, `chrome.browserAction` for V2.\n\n## Performance Debugging\n\n**Memory API conditional**: Check `'memory' in performance` before accessing `performance.memory.usedJSHeapSize`.\n\n**Use performance marks**: `performance.mark()` and `performance.measure()` for sub-frame timing. Clear marks to prevent memory leaks.\n\n**Layout thrash detection**: PerformanceObserver with `entryTypes: ['measure', 'paint', 'largest-contentful-paint']`. Flag entries >16.67ms.\n\n## Network Debugging\n\n**Block before navigate**: Call `Network.setBlockedURLs` before `Page.navigate`, not after.\n\n**Request interception**: Use `Network.setRequestInterception` with `requestStage: 'Request'` for granular control. Return `errorReason: 'BlockedByClient'` to block.\n\n## Security Contexts\n\n**Mixed content**: HTTPS pages can't load HTTP resources. Check `location.protocol` vs resource URL.\n\n**CORS errors**: `TypeError` on cross-origin fetch usually means CORS. Check DevTools Network tab for specific error.\n\n**Secure context required**: File System Access API, Clipboard API require `window.isSecureContext === true` and user gesture.\n","tags":{"latest":"1.0.0"},"stats":{"comments":0,"downloads":4881,"installsAllTime":46,"installsCurrent":46,"stars":14,"versions":1},"createdAt":1770667610226,"updatedAt":1778486238781},"latestVersion":{"version":"1.0.0","createdAt":1770667610226,"changelog":"Initial release","license":null},"metadata":null,"owner":{"handle":"ivangdavila","userId":"s178jdk12x4qj3gs2se3etxf3h83h7ft","displayName":"Iván","image":"https://avatars.githubusercontent.com/u/81719670?v=4"},"moderation":null}