Skip to content

feat(extension): advanced recording settings for Network Interceptor#66

Merged
nafees87n merged 2 commits into
masterfrom
feat/network-recording-advanced-settings
Jun 10, 2026
Merged

feat(extension): advanced recording settings for Network Interceptor#66
nafees87n merged 2 commits into
masterfrom
feat/network-recording-advanced-settings

Conversation

@nafees87n

Copy link
Copy Markdown
Contributor

What

Adds four advanced recording settings to the LTS Network Interceptor, mirroring the classic LTS recorder's "Advanced Options". All ride the existing startNetworkRecording config object (no new message types, no listener change). Chrome + Edge only — Firefox/Safari are unaffected (feature-guarded; no manifest change there).

Story: RQ-3330 (epic RQ-2894)
Contract doc: Confluence — Requestly <> LT network interceptor integration (v34)

Options

Config key Default Behavior
disableCache false Wipe the HTTP cache for the recorded origin at record start (DevTools "Disable cache" equivalent) — cold first load, no 304/from-cache skeletons. No Cache-Control header injection (would distort recorded traffic).
wipeServiceWorkers false Unregister the origin's service workers + clear the Cache API (cacheStorage) they serve from, at record start.
recordAjax true true → XHR/Fetch recorded with full bodies+headers (web-sdk, v2). false → XHR/Fetch not recorded at all (suppressed from both the SDK page script and the webRequest path). A yes/no on recording ajax, not a bodies toggle.
requestScope "all" "all" → every frame. "top-level" → only main-frame requests (frameId === 0), dropping iframe-originated requests.

The two cache/SW wipes coalesce into one chrome.browsingData.remove call.

Key implementation notes

  • Gesture-safe: the wipe is fire-and-forget (never awaited), issued inside the chrome.tabs.create callback, so chrome.sidePanel.open() keeps its user gesture. Verified the panel still opens with both wipes on.
  • Feature-guarded: all browsingData access via (chrome as any).browsingData?.remove with a typeof check → clean no-op on Firefox/Safari.
  • New permission: browsingData added to manifest.chrome.json + manifest.edge.json only. ⚠️ This re-prompts existing Chrome/Edge users to accept on update. Store-review justification: "browsingData is used solely to clear the recorded site's HTTP/Cache-API cache and service workers at the moment a user starts a network recording, so captured traffic reflects a clean, uncached load."
  • requestScope is a string-valued RequestScope enum (wire value stays "all"/"top-level").
  • Config fields stay optional in the contract type (defensive defaults), but LTS is expected to send all four explicitly per the user's selection (documented in the Confluence contract).

Caveats (documented)

  • disableCache clears the whole-browser HTTP cache (Chrome ignores origins for the cache data type; only cacheStorage is origin-scoped) — a momentary record-start action.
  • wipeServiceWorkers + origins may be silently ignored on some Chrome versions (degrades gracefully, best-effort).

Testing

Manually verified all four on a loaded build:

  • disableCache → static assets fetched from network, not disk cache
  • wipeServiceWorkers → SW unregistered (confirmed via chrome://serviceworker-internals + the browsingData.remove call firing with the right payload in the SW console)
  • recordAjax: false → zero xhr/fetch entries; non-ajax resources still captured
  • requestScope: "top-level" → iframe requests dropped
  • Gesture regression → side panel opens with both wipes enabled

Build is clean (only pre-existing TS7030/circular-dep warnings on listener.ts, unrelated to this change). Harness (test/network-recording-test.html) updated with the four toggles.

🤖 Generated with Claude Code

nafees87n and others added 2 commits June 9, 2026 18:46
Add four config options to startNetworkRecording (Chrome/Edge only):
- disableCache: wipe HTTP cache for the origin at record start
- wipeServiceWorkers: unregister SWs + clear Cache API at start
- recordAjax (default true): when false, xhr/fetch not recorded at all
- requestScope (default all): "top-level" records only frameId 0

Cache/SW wipes coalesce into one fire-and-forget chrome.browsingData.remove
inside the tabs.create callback (preserves the sidePanel.open gesture);
browsingData permission added to chrome+edge manifests only, feature-guarded
so Firefox/Safari no-op. Harness updated with the four toggles.

Refs RQ-3330

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- disableCache: document that it clears the ENTIRE browser HTTP cache (all
  sites), not just the recorded origin — Chrome ignores the origins filter for
  the `cache` data type.
- injectBodyRecorder: fix stale comment — when recordAjax=false, xhr/fetch are
  dropped by the webRequest path too (isAjaxRequest), so ajax is not recorded at
  all (not "falls to the webRequest skeleton path").

Comment-only; no functional change. Addresses the two confirmed (doc-only)
findings from the multi-agent PR review.

Refs RQ-3330

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@nafees87n nafees87n merged commit ac5632b into master Jun 10, 2026
4 checks passed
@nafees87n nafees87n deleted the feat/network-recording-advanced-settings branch June 10, 2026 10:33
nafees87n added a commit that referenced this pull request Jun 10, 2026
…-timing race) (#67)

* feat(extension): add advanced recording settings to Network Interceptor

Add four config options to startNetworkRecording (Chrome/Edge only):
- disableCache: wipe HTTP cache for the origin at record start
- wipeServiceWorkers: unregister SWs + clear Cache API at start
- recordAjax (default true): when false, xhr/fetch not recorded at all
- requestScope (default all): "top-level" records only frameId 0

Cache/SW wipes coalesce into one fire-and-forget chrome.browsingData.remove
inside the tabs.create callback (preserves the sidePanel.open gesture);
browsingData permission added to chrome+edge manifests only, feature-guarded
so Firefox/Safari no-op. Harness updated with the four toggles.

Refs RQ-3330

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(extension): clarify advanced-settings comments per PR review

- disableCache: document that it clears the ENTIRE browser HTTP cache (all
  sites), not just the recorded origin — Chrome ignores the origins filter for
  the `cache` data type.
- injectBodyRecorder: fix stale comment — when recordAjax=false, xhr/fetch are
  dropped by the webRequest path too (isAjaxRequest), so ajax is not recorded at
  all (not "falls to the webRequest skeleton path").

Comment-only; no functional change. Addresses the two confirmed (doc-only)
findings from the multi-agent PR review.

Refs RQ-3330

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(extension): capture initial-page-load XHR/fetch bodies (injection-timing race)

v2 body capture missed an SPA's bootstrap XHR/fetch responses because the web-sdk
interceptor was injected via executeScript from webNavigation.onCommitted and only
armed on the START round-trip — landing after the page's first requests fired.
Those responses carry the IDs/slugs LTS auto-correlation needs, so correlation
chained 0 rows.

Fix — register before the recorded navigation, buffer from t=0:
- Create the recorded tab at about:blank, open the side panel synchronously
  (gesture intact), THEN register the web-sdk UMD + body recorder as one ordered
  document_start MAIN-world content script (registerContentScripts), THEN navigate
  to the URL. The interceptor is guaranteed armed before request #1. The URL loads
  only once, so nothing is double-captured.
- Page script arms the interceptor at injection and BUFFERS captures until START,
  then flushes — so even an early request is retained.
- Pull-based READY->START handshake with retry: the page re-posts READY until START
  arrives (the one-shot version raced the content-script relay on fast loads and
  silently dropped, leaving the buffer un-flushed / 0 entries).
- Guard clientHandler + tabService onCommitted/DOMContentLoaded handlers against
  non-http(s) URLs so the about:blank step doesn't log access errors.
- Unregister the body-recorder scripts when the last recording stops; clean up
  orphaned registrations on SW init.

Also raise DEFAULT_MAX_PAYLOAD_SIZE 200KB -> 10MB (safe maximum: covers realistic
API/JSON bodies, stays well under Chrome's ~32MB sendMessage ceiling so oversized
bodies truncate gracefully instead of throwing).

Validated on realworld.show and practicesoftwaretesting.com: bootstrap XHRs now
captured with request+response bodies; panel counts them; no double-send.

Stacked on the advanced-settings branch (PR #66).
Refs RQ-2894

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(extension): bound pre-START body-capture buffer + focus recorded tab

Buffer leak: the body recorder is registered into every http(s) tab while a
recording is active, but only the recorded tab gets START. On every other tab
the interceptor sat in "buffering" forever, accumulating raw request/response
bodies for the page's lifetime. Now:
- the READY handshake, on giving up (no START after ~6s), transitions to
  "stopped" and frees the buffer — so non-recorded tabs stop capturing;
- the pre-START buffer is hard-capped (MAX_BUFFERED_ENTRIES, drop-oldest) so it
  can't grow unbounded even before give-up / on a slow-to-START recorded tab.
Late START (>6s, effectively never for a recorded tab) is ignored — the
recorded-tab live path is unaffected (START arrives in ms).

Focus: navigate the recorded tab with { active: true } so Chrome moves focus to
the page instead of leaving it in the omnibox (the about:blank tab held no
focus). Best-effort nudge.

Addresses the buffer-leak finding from the PR review.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

2 participants