Skip to content

feat(devtools): add optional Elements / Console / Network tools (Chrome DevTools Protocol) - #115

Closed
graydovee wants to merge 2 commits into
omdsh-dev:mainfrom
graydovee:feat/devtools-group
Closed

graydovee wants to merge 2 commits into
omdsh-dev:mainfrom
graydovee:feat/devtools-group

Conversation

@graydovee

@graydovee graydovee commented Oct 9, 2026 •

Copy link
Copy Markdown

概述 / Summary

Adds an optional developer-tools group: inspect and edit element styles, run JS in the page, and capture network requests. Off by default; requires separate authorization. Closes #114.

  • 81eb4cd implementation (20 files)
  • 9d4d2e4 tests and docs (21 files)

动机 / Motivation

See #114. The existing tools cannot read computed styles or layout information, so style-related questions dead-end.

改动内容 / Changes

Host side (bridge-browser):

  • hello gains a devTools capability negotiation: the group is registered only after the extension advertises it, and retracted on reconnect if the capability disappears
  • 9 new tools: browser_devtools_elements (inspect elements), browser_devtools_set_element_style / browser_devtools_set_element_attribute (edit styles and attributes), browser_console_eval / browser_console_logs (run JS, read the console), browser_devtools_network / browser_devtools_list_requests / browser_devtools_get_request / browser_devtools_request_body (network capture); output remains { text }

Extension side (dsh-browser):

  • chrome.debugger session management: attach, domain enable, timeouts, and a clear error on conflicts asking to close DevTools
  • Elements: locate by selector or snapshot index; return computed styles, box model, and matched rules; edit inline styles or matched style rules
  • Console: Runtime.evaluate runs JS and returns the result; console output and exceptions are recorded
  • Network: requests recorded from CDP network events, with headers, status, timing, and response bodies
  • Authorization: a dedicated approval dialog; a new "allow developer tools" setting; toggling it off detaches the debugger immediately
  • The Chrome manifest gains the debugger permission; the Firefox manifest does not

Two implementation notes:

  1. Network capture cannot listen to Network.requestWillBeSent alone: on some pages Chrome emits only requestWillBeSentExtraInfo and never the main event, leaving the capture empty. Both events now create entries, and entries missing the main event are annotated "request method may be incomplete".
  2. In element reports, when a rule carries both a shorthand and its longhands, only the shorthand is kept; editing one longhand (e.g. margin-top) replaces the whole margin family, otherwise the shorthand would override the edit.

测试 / Testing

  • pnpm run check:runtime
  • pnpm run typecheck
  • pnpm run test: bridge 160/160, extension 494/494
  • pnpm run build
  • pnpm run test:smoke

New tests cover: debugger session lifecycle, network-capture event handling (including the ExtraInfo case), element location and style edits, authorization policy ("full browser control" and the origin allowlist never cover this group), and the manifest platform differences.

Verified in Chrome: inspecting an element's computed styles and matched rules; adding an outline and re-reading it to confirm the style attribute was written; running JS in the console and reading back JSON plus an uncaught exception with its stack; capturing a fetch with status, headers, timing, and a formatted JSON body.

影响范围 / Impact

  • The group is Chrome-only; it is not registered on Firefox
  • Off by default: without the setting or a per-call approval there is no behavior change
  • While the debugger is attached, the browser's own DevTools cannot open on the same tab
  • No new dependencies; wire protocol unchanged

Checklist

  • 已在相关平台实测通过 / Tested on the relevant platforms
  • 已通过 pnpm run build / bash -n scripts/install.sh 等基础检查 / Passed basic checks
  • 文档已同步更新(如需要)/ Docs updated if needed
  • 不包含无关改动 / No unrelated changes included

…Chrome DevTools Protocol

Adds a high-privilege developer-tools group on top of the existing browser
bridge: element/CSS inspection and live edits, page-context JavaScript plus
console output, and network capture with request detail and bodies.

## Capability negotiation

The group is registered only while the connected extension advertises
`devTools` in its `hello` (version 1). `BridgeServer` now records the caps of
the authenticated connection and reports changes through `onCapsChange`, so a
reconnect that drops the capability retracts the tools instead of offering
tools the extension cannot serve. Firefox builds do not declare the API and
therefore never advertise it.

## Consent model

Approval in this repository is rooted in the extension, and the host-level
approval seam is refused outright under a `never` session policy, so the
consent boundary lives where the user actually is: the side panel.

- Every devtools call raises its own dialog unless the user turned on the new
  **Allow developer tools** setting.
- `trustedActionOrigins` and `unrestrictedBrowserAccess` deliberately do NOT
  cover this group: `resolveApprovalGate` keeps those shortcuts to ordinary
  actions, so enabling either can never silently hand over the debugger.
- A session-scoped grant is cleared when the setting changes, the panel
  closes, or the worker restarts. Revoking detaches the debugger and aborts
  in-flight devtools calls.

The controller itself only owns capability and target policy (platform
support, undebuggable schemes, attachment); it must not add a second hard gate
on the setting, or the dialog above becomes unreachable.

## Elements and CSS

Resolves a target by CSS selector or by the `data-dsh-el` inventory index
written by the content script, then reports box model, filtered computed
styles, inline style, and matched rules. Writes apply to the inline style
(through `CSS.setStyleTexts` when Chrome exposes an editable range, otherwise
through the `style` attribute) or to the first matching author rule, spliced
into its stylesheet by token range so unrelated rules survive.

Reports are canonicalized: CSS custom properties are dropped (theme plumbing,
hundreds of lines on one `body`) and a longhand is folded away only when the
same block carries the shorthand covering it. An edit resolves its whole
shorthand family, otherwise the shorthand would win the cascade and the edit
would silently do nothing. Script-capable attributes are refused.

## Console

`browser_console_eval` runs in the page's own context with `returnByValue` so
JSON-compatible results come back as data instead of an opaque "object
Object"; classes, functions, and DOM nodes fall back to description plus an
optional preview. Exceptions are reported with their stack.

## Network capture

`Network.enable` is not sufficient on its own: on live pages Chrome may emit
`Network.requestWillBeSentExtraInfo` without ever sending the main
`requestWillBeSent`, and a store that only listens for the main event records
nothing while its event counters show traffic. Entries are therefore created
from either event, a response adopts itself when no request event arrived, and
both header shapes (the array the main event uses, the map the extra-info
events use) are normalized. An entry whose request event never arrived is
flagged rather than presenting a guessed method as fact.

Capture is in memory, bounded (200 requests, 500 console entries), and resets
on attach and on every top-level navigation; credential headers are redacted
unless a call opts in, and bodies of authentication-shaped URLs are redacted
by default. A status answer carries the enabled domains and observed network
event kinds, so a thin capture is explainable without a rebuild.

Wire format is unchanged: results remain single text payloads.
Adds 8 suites (extension + bridge) and extends the existing ones, on top of
the implementation in the previous commit.

## Coverage

- `debugger-session`: attach once and enable the four domains, conflict ->
  `devtools-conflict` with an actionable message, half-attachment cleanup,
  command timeout, pending commands settling on detach, absent platform API.
- `devtools-network`: the observed live sequence (`requestWillBeSentExtraInfo`
  -> `responseReceivedExtraInfo` -> `responseReceived` -> `loadingFinished`,
  with the main request event withheld), response adoption, both header
  shapes, the incomplete-request flag clearing when the main event arrives,
  ring-buffer cap, reset on navigation, console levels and cap.
- `devtools-elements`: selector and inventory-index resolution, computed-style
  filtering, shorthand canonicalization (including single-value `margin: 0`,
  which an earlier revision missed), family-aware edits, rule splicing,
  attribute risk classification, and both inline-edit paths.
- `devtools-controller`: allowance no longer blocks a call (the dialog must
  stay reachable), internal pages refused before attach, stale failures
  cleared, pipeline evidence, and the `sinceIndex` window.
- `devtools-authorization`: prompt shape for all nine tools, read vs action
  classification, and `resolveApprovalGate` proving neither unrestricted
  access nor the origin allowlist covers the group.
- Plus the `hello` capability contract, the config key, and the manifest
  asymmetry asserted against both manifests.

## Docs

Both READMEs (EN/ZH) gain a developer-tools section: the tool table, the
opt-out setting, the one-debugger-per-tab constraint, and the data handling
(redaction, bounded in-memory capture). The manifest and known-limitations
sections record that the group is Chrome-only and needs a debuggable tab.

## Verification

- `pnpm run check:runtime`, `pnpm run typecheck`, `pnpm run build`,
  `pnpm run test:smoke` (all five CI gates) pass locally.
- `pnpm run test`: bridge 160/160, extension 493/493.
- Exercised end to end on a real page: element inspection and CSS edit
  (written to the `style` attribute and re-read back), object evaluation
  returning JSON, console logs including uncaught exceptions, and a captured
  `fetch` with status, headers, timing, and pretty-printed response body.
@graydovee graydovee changed the title feat(devtools): 增加可选的 Elements / Console / Network 工具(基于 Chrome DevTools Protocol) feat(devtools): add optional Elements / Console / Network tools (Chrome DevTools Protocol) Oct 10, 2026
@graydovee graydovee closed this Oct 16, 2026
@graydovee
graydovee deleted the feat/devtools-group branch October 16, 2026 17:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: 为浏览器助手增加可选的开发者工具(Elements / Console / Network)

1 participant