Skip to content

fix(bidi): report correct response sizes on Chrome and Firefox - #42700

Open
Ashraf Ali (ashrafiucse) wants to merge 2 commits into
microsoft:mainfrom
ashrafiucse:fix-42697
Open

Ashraf Ali (ashrafiucse) wants to merge 2 commits into
microsoft:mainfrom
ashrafiucse:fix-42697

Conversation

@ashrafiucse

Copy link
Copy Markdown
Contributor

Summary

  • network.ResponseCompleted's bodySize/headersSize carry different meanings per engine: Chrome's bodySize is the full transfer size (status line + headers + body, like CDP's encodedDataLength) and its headersSize omits the status line and the final CRLF; Firefox's bodySize is the body size and its headersSize is the full header block. The old code fed one field into both metrics, so request().sizes() over-reported responseBodySize by the header size on Chrome.
  • Map the fields per engine in bidiNetworkManager and align Chrome's responseHeadersSize with the other backends. The overhead computation matches the responseHeadersSize() fallback in network.ts, so transferSize = responseHeadersSize + encodedBodySize holds on both engines (including for HTTP/2, consistent with the existing fallback).
  • All 10 page-network-sizes entries removed from the bidi-chromium-page expectations.

Fixes #42697

network.ResponseCompleted's |bodySize| and |headersSize| carry different
meanings per engine: Chrome's |bodySize| is the full transfer size,
including the status line and headers, just like CDP's encodedDataLength,
and its |headersSize| omits the status line and the final CRLF. Firefox's
|bodySize| is the response body size and its |headersSize| is the full
header block size. Map the fields to transferSize/encodedBodySize/
responseHeadersSize per engine so request().sizes() matches the other
backends.

Fixes: microsoft#42697
@ayaangazali

Copy link
Copy Markdown

Reporter of #42697 here. Ran the original reproducer against this branch on both bidi transports, 2000 byte body with content-length set:

chrome  over bidi   responseBodySize=2000  responseHeadersSize=151   (was 2151 / 132)
firefox over bidi   responseBodySize=2000  responseHeadersSize=151   (unchanged, still correct)
chromium over CDP   responseBodySize=2000  responseHeadersSize=151   (reference)

So Chrome now agrees with CDP on both fields and Firefox is not regressed, which was the risk with the naive subtraction I had suggested on the issue. Thanks for digging into the raw ResponseCompleted params and correcting that, the per-engine semantics were not something I would have found by reading.

@ashrafiucse

Ashraf Ali (ashrafiucse) commented Sep 14, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for running it against both engines — that's exactly the check I was hoping someone would do, and matching CDP on both fields is the outcome we wanted here.

Honestly, your report made this fix a lot easier than it could've been. The two suspect lines and the transferSize = responseHeadersSize + encodedBodySize relationship you pulled out were spot on. The per-engine thing only showed up because your numbers didn't quite line up with a straight subtraction — that's what pushed me to just log what each browser actually sends. It's invisible from the code alone, and I don't think the spec spells it out either.

And genuinely — keep filing reports like this one. A repro that runs first try, plus a cause narrowed down to two lines, is better than a lot of what lands in most trackers, freshman or not.

// Chrome's |bodySize| is the transfer size (status line + headers + body),
// derive the encoded body size by subtracting the full header block size.
response.setTransferSize(bodySize);
response.setEncodedBodySize(bodySize - headersSize - this._headerBlockOverheadSize(params.response));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this works around an upstream bodySize bug but produces negative sizes for HTTP/2 and cache hits

} else {
// Firefox's |bodySize| is the encoded body size, and its |headersSize|
// already includes the status line and the final CRLF.
response.setTransferSize(headersSize + bodySize);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this sum omits chunked framing and counts cached bodies as transferred bytes

i think bytesReceived already contains the correct value

Transfer size now comes from |bytesReceived| on both engines: it is the
number of bytes actually read off the network, including the header block
and the chunked framing, and is 0 for cached responses. This also fixes
two issues with the previous change-requested approach found in review:

- Chrome's header block subtraction produced negative body sizes for
  cached responses (|bodySize| of 0) and for HTTP/2, where |headersSize|
  counts the decompressed header lines while |bodySize| is a wire size.
  The subtraction is now limited to fresh HTTP/1.x responses; everything
  else falls back to the content-length based computation in network.ts.
- Firefox's |headersSize| + |bodySize| sum counted cached bodies as
  transferred bytes and omitted the chunked framing.
@ashrafiucse

Copy link
Copy Markdown
Contributor Author

Thanks for the review — you were right on both counts, and bytesReceived was the key. Pushed 4334055:

  • transferSize now comes from bytesReceived on both engines. Verified it to be the wire count on each: h1 fixed 2151, chunked 182 (framing included — Firefox's headersSize + bodySize sum was indeed missing it), h2 72/120, and 0 for cache hits on both engines (Firefox was reporting bodySize of 500 for a cached response, so the old sum counted cached bytes as transferred).
  • The Chrome subtraction is now limited to fresh HTTP/1.x responses, where bodySize is encodedDataLength. For cached responses (bodySize of 0 with populated headersSize) and HTTP/2 (where headersSize counts decompressed header lines while bodySize is a wire size), encodedBodySize resolves to null and falls back to the content-length based computation in network.ts — no more negatives. The responseHeadersSize status-line alignment is gated to HTTP/1.x as well.

Spot-checked against CDP after the change: fixed/gzip report identical responseBodySize/responseHeadersSize (2000/151, 29/173) on bidi-chrome, bidi-firefox and CDP, cache hits report responseBodySize 500 with transfer 0, and the 10 page-network-sizes entries stay green on bidi-chromium/bidi-chrome/moz-firefox.

@dcrousso

Copy link
Copy Markdown
Contributor

FYI im working on fixing part of this upstream https://chromium-review.googlesource.com/c/chromium/src/+/8411449

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.

[Bug]: bidi reports transfer size as responseBodySize, so request().sizes() over-reports the body by the header size

3 participants