New issue
Advanced search Search tips

Issue 896475 link

Starred by 3 users

Issue metadata

Status: Assigned
Owner:
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: ----
Pri: 3
Type: Bug



Sign in to add a comment

Security Panel in DevTools protocol is very chatty

Project Member Reported by davidben@chromium.org, Oct 17

Issue description

(pfeldman: Please correct me if I summarized our chat incorrectly anywhere!)

During a review of https://chromium-review.googlesource.com/c/chromium/src/+/1249912, it came up that the DevTools security panel is expensive. Specifically, it attaches this SecurityDetails struct to every request.
https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/inspector/browser_protocol.pdl?rcl=2a7f55bd4c7fe63030b4315e89c5b29e909ea981&l=3689

As we've grown more things we wish to report in DevTools, that struct has gotten larger. However, this corner of DevTools is used in many contexts, from folks trying to debug non-TLS things to various telemetry or tracing type use cases, where the information isn't used at all.

This introduces friction between adding to the security panel and other DevTools use cases.

pfeldman and I chatted a bit. Some things that came up:


1) Fundamentally, the security panel's usage, while meaningful, is dwarfed in comparison to the rest of DevTools. At least with the current protocol (though maybe the changes elsewhere could help?), this isn't a great tradeoff.

Possible fix: pfeldman suggested some kind of opt-in checkbox plus reload to capture the request information. This, however, is a user-visible change.


2) The DevTools protocol is basically straight-up JSON. We thus pay not only for values but also field names! For most TLS bits, the name is far far more expensive than the value!

Possible fix: could we design a more efficient transport for this? On the one hand, JSON is nice for hackability, especially for a customer-facing protocol. On the other hand, given we are clearly concerned about bandwidth, efficiency improvements may be warranted.


3) TLS settings are 16-bit integers, allocated in some registry here, such as the ones here.
https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml
(Note: although some of these registries are giant, namely the cipher suite one, we only actually use a tiny fraction of them. Our largest one in BoringSSL is 25 entries, of which only 16 are reachable from Chrome.)

However, the DevTools protocol and structs leading up to it in memory use human-readable strings:
https://cs.chromium.org/chromium/src/third_party/blink/public/platform/web_url_response.h?type=cs&q=WebSecurityDetails&sq=package:chromium&g=0&l=94

This is much less efficient. Going through that struct:

- protocol is *almost* a 16-bit number, but we also jam QUIC in there. Either way, it's really just an enum:
https://cs.chromium.org/chromium/src/net/ssl/ssl_connection_status_flags.h?rcl=90a499f67f5f97dfd6f11845f9101dd6e605528e&l=38

- key_exchange, cipher, and mac are an exploded form of a single 16-bit integer.

- key_exchange_group is a single 16-bit integer.

- I was hoping to add the server signature... which also is a single 16-bit integer but, following the current pattern, would be *two more strings*.

- subject_name, san_list, issuer, valid_from, and valid_to are all encoded in the certificate. We have a parser readily callable in //net these days.

Possible fix: Transit those more efficiently. To start with, we can defer the string conversion to just before entering DevTools, basically pushing the content/renderer/loader/web_url_loader_impl.cc logic further down into Blink.

But the real benefit would be compressing the DevTools protocol bits. Unfortunately, being JSON, the DevTools protocol still cannot efficiently encode that right now. We'd be paying for the JSON keys and the integer would be encoded in decimal. Additionally, DevTools cannot easily call into C++ code to decode the integers, so we'd need to replicate and maintain a few tables in the DevTools frontend code. (The tables are pretty small, but they do get occasional additions over time.)


pfeldman wants to tackle (1). I feel the inefficient encoding is worth tackling. It sounds like there is a *TON* of low-hanging fruit to improve the efficiency here, at which point it's not clear to me SecurityDetails will still be as controversially expensive. (At the end of the day, the problematic CL is trying to add a whole two bytes of information. I feel like if we can't add a few two-byte or one-bit fields without trouble, we're not in a good place.)
 
> To start with, we can defer the string conversion to just before entering DevTools, basically pushing the content/renderer/loader/web_url_loader_impl.cc logic further down into Blink.

This was quite straightforward. I'll upload a CL for it tomorrow.
Incidentally, it should be pretty straightforward to make the protocol more efficient without changing the schema (so you can easily support both old and new protocols for compatibility). Here's a strawman:

1. Replace JSON with canonical CBOR (so no indefinite-length nonsense). Chromium already has encoders and decoders.

2. First message is a list of strings. This is every field name in the IDL file in some order (sorted?). First one is zero, second is one, etc. This is so you don't pay for keys. Otherwise there's pressure to use short rather than readable field names, which is silly.

3. Subsequent messages are CBOR messages, with only the subset corresponding to JSON allowed. Except that map keys may be either strings or integer. If it's an integer key, replace it with the corresponding index into the strings table.

4. Later probably add the bytes type so you're not base64-encoding things.
These are all good ideas.

- Binary protocol is on its way, but it takes time. We are currently migrating base64 bits to explicit binary markup. CBOR is a fine candidate for the serialization itself though.

- Indexing keys makes protocol a bit involved - keys are latin1, so the CPU cost of serializing those is minimal.

- We are working on (4) already. It is not JSON serialization that is expensive, transcoding text and base64-ing blobs is what shows up in profiles.

In either case, I think it is somewhat beside the point - we should opt out from doing unnecessary work first and only then think about mitigating the overhead by means of transport optimization.
I guess my claim would be that, under any sensible serialization, the SecurityDetails cost should be negligible enough that I can't imagine it mattering. If we can solve the performance issues without making what is already not a great UX even worse, that seems preferable, no? (But I also work on Networking, not Enamel. Hopefully Enamel folks can chime in on that one.)

The indexing keys suggestion was because you were concerned that adding two bytes isn't just adding two bytes because of the key name. I could go name my new field "sig" instead of "signatureAlgorithm", but this starts getting silly in the long run.

Additionally, the blocked CL has been out for a month now and is really just trying to add one field. It is frustrating to have one's small addition get caught up in broader architectural concerns between two completely different teams. I agree the original implementation (two strings with two long keys) is costly. I was following the existing design, but it sounds like the existing design was bad.

Let's try to keep progress possible by tackling the low-hanging fruit first. You mentioned it's text and base64 that shows up in profiles. Let's do (3) then, at least for the new stuff. We can easily turn the TLS bits into numbers.

If I add "sig":u16, that'll cost 12 characters. I can free up that amount easily by going back and compressing "keyExchangeGroup":string to "group":u16. That should also be more efficient in-memory as integers are, one hopes, not boxed in V8. They also avoid a UTF-8 decode. I could compress keyExchange/cipher/mac too, but keyExchange/cipher were, sadly, not marked optional, so this may not be worth it.

And then when you all make a binary protocol, those numbers will get even smaller by avoiding decimal.

(To be clear, using numbers for TLS here is neither some ad-hoc compression scheme nor serializing Chrome-internal values. TLS parameters are natively represented uint16_t on the wire, with standardized values. The string representation is the ad-hoc Chrome-specific one.)
I see the point about the Security Panel not being used very often (it's opened something like 0.34% of the time according to UMA). However, making it so that it's even harder to get security details by requiring additional user input doesn't seem great--the panel is already somewhat hidden and requires reload to see subresources.

I tend to agree that it shouldn't be difficult to add additional fields, and that it would be preferable to make optimizations in the transport to provide a better UX.
Owner: pfeldman@chromium.org
Status: Assigned (was: Untriaged)
Owner: davidben@chromium.org
>> However, making it so that it's even harder to get security details by requiring additional user input doesn't seem great--the panel is already somewhat hidden and requires reload to see subresources.

Maybe we can use this fact and reload with the security aspects enabled when reloading from the security panel? That way we don't add overhead and preserve existing UX.
To be clear, I do not work on the security panel or anything related to UI. I am happy to do (3) from above, but I'm not the right person to do the other things here.

I do, however, continue to believe that the chattiness should not require UX changes or preclude fixing the reload problem. The amount of data that needs to be transmitted is naturally very small. The problem is the way we are transmitting it does not meet the apparent requirements.
I'm triaging the DevTools bugs and am trying to figure out what we should do with this one. It is filed by you and assigned to you, but I don't think there is a plan to do something here. So I wonder what should happen to this bug. We try to close those with no clear plan to be able to keep the product in a healthy state...
I like the suggestion by pfeldman@ in comment 7, but I think we may still need some pieces from SecurityDetails to get the Connection information for the Security overview. Would it be okay to split out the connection details from the certificate and CT details, and then only send SecurityDetails on reload from the security panel with no UX changes as suggested?

As far as triaging, I can probably work on this optimization as a separate bug. But I agree with comment 8 that it doesn't preclude work on some of the other proposals above.
Cc: binghamj@chromium.org est...@chromium.org
Hi everyone... I'm back from leave and catching up on this bug. I suggest that as a path forwards, Livvie and I implement davidben's proposal #3 initially, while simultaneously fleshing out the UX details of #1 (perhaps with binghamj's help?). I think pfeldman's suggestion in #7 is workable but proposal #3 is probably worth doing regardless.

Sign in to add a comment