• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/http/http_response_info.h"
6 
7 #include "base/logging.h"
8 #include "base/numerics/safe_conversions.h"
9 #include "base/pickle.h"
10 #include "base/time/time.h"
11 #include "net/base/net_errors.h"
12 #include "net/cert/sct_status_flags.h"
13 #include "net/cert/signed_certificate_timestamp.h"
14 #include "net/cert/x509_certificate.h"
15 #include "net/http/http_response_headers.h"
16 #include "net/ssl/ssl_cert_request_info.h"
17 #include "net/ssl/ssl_connection_status_flags.h"
18 #include "net/third_party/quiche/src/quiche/quic/core/quic_versions.h"
19 #include "third_party/abseil-cpp/absl/types/optional.h"
20 #include "third_party/boringssl/src/include/openssl/ssl.h"
21 
22 using base::Time;
23 
24 namespace net {
25 
26 namespace {
27 
KeyExchangeGroupIsValid(int ssl_connection_status)28 bool KeyExchangeGroupIsValid(int ssl_connection_status) {
29   // TLS 1.3 and later always treat the field correctly.
30   if (SSLConnectionStatusToVersion(ssl_connection_status) >=
31       SSL_CONNECTION_VERSION_TLS1_3) {
32     return true;
33   }
34 
35   // Prior to TLS 1.3, only ECDHE ciphers have groups.
36   const SSL_CIPHER* cipher = SSL_get_cipher_by_value(
37       SSLConnectionStatusToCipherSuite(ssl_connection_status));
38   return cipher && SSL_CIPHER_get_kx_nid(cipher) == NID_kx_ecdhe;
39 }
40 
41 }  // namespace
42 
43 // These values can be bit-wise combined to form the flags field of the
44 // serialized HttpResponseInfo.
45 enum {
46   // The version of the response info used when persisting response info.
47   RESPONSE_INFO_VERSION = 3,
48 
49   // The minimum version supported for deserializing response info.
50   RESPONSE_INFO_MINIMUM_VERSION = 3,
51 
52   // We reserve up to 8 bits for the version number.
53   RESPONSE_INFO_VERSION_MASK = 0xFF,
54 
55   // This bit is set if the response info has a cert at the end.
56   // Version 1 serialized only the end-entity certificate, while subsequent
57   // versions include the available certificate chain.
58   RESPONSE_INFO_HAS_CERT = 1 << 8,
59 
60   // This bit was historically set if the response info had a security-bits
61   // field (security strength, in bits, of the SSL connection) at the end.
62   RESPONSE_INFO_HAS_SECURITY_BITS = 1 << 9,
63 
64   // This bit is set if the response info has a cert status at the end.
65   RESPONSE_INFO_HAS_CERT_STATUS = 1 << 10,
66 
67   // This bit is set if the response info has vary header data.
68   RESPONSE_INFO_HAS_VARY_DATA = 1 << 11,
69 
70   // This bit is set if the request was cancelled before completion.
71   RESPONSE_INFO_TRUNCATED = 1 << 12,
72 
73   // This bit is set if the response was received via SPDY.
74   RESPONSE_INFO_WAS_SPDY = 1 << 13,
75 
76   // This bit is set if the request has ALPN negotiated.
77   RESPONSE_INFO_WAS_ALPN = 1 << 14,
78 
79   // This bit is set if the request was fetched via an explicit proxy.
80   RESPONSE_INFO_WAS_PROXY = 1 << 15,
81 
82   // This bit is set if the response info has an SSL connection status field.
83   // This contains the ciphersuite used to fetch the resource as well as the
84   // protocol version, compression method and whether SSLv3 fallback was used.
85   RESPONSE_INFO_HAS_SSL_CONNECTION_STATUS = 1 << 16,
86 
87   // This bit is set if the response info has protocol version.
88   RESPONSE_INFO_HAS_ALPN_NEGOTIATED_PROTOCOL = 1 << 17,
89 
90   // This bit is set if the response info has connection info.
91   RESPONSE_INFO_HAS_CONNECTION_INFO = 1 << 18,
92 
93   // This bit is set if the request has http authentication.
94   RESPONSE_INFO_USE_HTTP_AUTHENTICATION = 1 << 19,
95 
96   // This bit is set if ssl_info has SCTs.
97   RESPONSE_INFO_HAS_SIGNED_CERTIFICATE_TIMESTAMPS = 1 << 20,
98 
99   RESPONSE_INFO_UNUSED_SINCE_PREFETCH = 1 << 21,
100 
101   // This bit is set if the response has a key exchange group.
102   RESPONSE_INFO_HAS_KEY_EXCHANGE_GROUP = 1 << 22,
103 
104   // This bit is set if ssl_info recorded that PKP was bypassed due to a local
105   // trust anchor.
106   RESPONSE_INFO_PKP_BYPASSED = 1 << 23,
107 
108   // This bit is set if stale_revalidate_time is stored.
109   RESPONSE_INFO_HAS_STALENESS = 1 << 24,
110 
111   // This bit is set if the response has a peer signature algorithm.
112   RESPONSE_INFO_HAS_PEER_SIGNATURE_ALGORITHM = 1 << 25,
113 
114   // This bit is set if the response is a prefetch whose reuse should be
115   // restricted in some way.
116   RESPONSE_INFO_RESTRICTED_PREFETCH = 1 << 26,
117 
118   // This bit is set if the response has a nonempty `dns_aliases` entry.
119   RESPONSE_INFO_HAS_DNS_ALIASES = 1 << 27,
120 
121   // This bit is set for an entry in the single-keyed cache that has been marked
122   // unusable due to the checksum not matching.
123   RESPONSE_INFO_SINGLE_KEYED_CACHE_ENTRY_UNUSABLE = 1 << 28,
124 
125   // This bit is set if the response has `encrypted_client_hello` set.
126   RESPONSE_INFO_ENCRYPTED_CLIENT_HELLO = 1 << 29,
127 
128   // This bit is set if the response has `browser_run_id` set.
129   RESPONSE_INFO_BROWSER_RUN_ID = 1 << 30,
130 
131   // This enum only has a few bits (`1 << 31` is the limit). If allocating the
132   // last flag, instead allocate it as `RESPONSE_INFO_HAS_EXTRA_FLAGS` to
133   // signal another flags word.
134 };
135 
ConnectionInfoToCoarse(ConnectionInfo info)136 HttpResponseInfo::ConnectionInfoCoarse HttpResponseInfo::ConnectionInfoToCoarse(
137     ConnectionInfo info) {
138   switch (info) {
139     case CONNECTION_INFO_HTTP0_9:
140     case CONNECTION_INFO_HTTP1_0:
141     case CONNECTION_INFO_HTTP1_1:
142       return CONNECTION_INFO_COARSE_HTTP1;
143 
144     case CONNECTION_INFO_HTTP2:
145     case CONNECTION_INFO_DEPRECATED_SPDY2:
146     case CONNECTION_INFO_DEPRECATED_SPDY3:
147     case CONNECTION_INFO_DEPRECATED_HTTP2_14:
148     case CONNECTION_INFO_DEPRECATED_HTTP2_15:
149       return CONNECTION_INFO_COARSE_HTTP2;
150 
151     case CONNECTION_INFO_QUIC_UNKNOWN_VERSION:
152     case CONNECTION_INFO_QUIC_32:
153     case CONNECTION_INFO_QUIC_33:
154     case CONNECTION_INFO_QUIC_34:
155     case CONNECTION_INFO_QUIC_35:
156     case CONNECTION_INFO_QUIC_36:
157     case CONNECTION_INFO_QUIC_37:
158     case CONNECTION_INFO_QUIC_38:
159     case CONNECTION_INFO_QUIC_39:
160     case CONNECTION_INFO_QUIC_40:
161     case CONNECTION_INFO_QUIC_41:
162     case CONNECTION_INFO_QUIC_42:
163     case CONNECTION_INFO_QUIC_43:
164     case CONNECTION_INFO_QUIC_44:
165     case CONNECTION_INFO_QUIC_45:
166     case CONNECTION_INFO_QUIC_46:
167     case CONNECTION_INFO_QUIC_47:
168     case CONNECTION_INFO_QUIC_Q048:
169     case CONNECTION_INFO_QUIC_T048:
170     case CONNECTION_INFO_QUIC_Q049:
171     case CONNECTION_INFO_QUIC_T049:
172     case CONNECTION_INFO_QUIC_Q050:
173     case CONNECTION_INFO_QUIC_T050:
174     case CONNECTION_INFO_QUIC_Q099:
175     case CONNECTION_INFO_QUIC_T099:
176     case CONNECTION_INFO_QUIC_999:
177     case CONNECTION_INFO_QUIC_DRAFT_25:
178     case CONNECTION_INFO_QUIC_DRAFT_27:
179     case CONNECTION_INFO_QUIC_DRAFT_28:
180     case CONNECTION_INFO_QUIC_DRAFT_29:
181     case CONNECTION_INFO_QUIC_T051:
182     case CONNECTION_INFO_QUIC_RFC_V1:
183     case CONNECTION_INFO_DEPRECATED_QUIC_2_DRAFT_1:
184     case CONNECTION_INFO_QUIC_2_DRAFT_8:
185       return CONNECTION_INFO_COARSE_QUIC;
186 
187     case CONNECTION_INFO_UNKNOWN:
188       return CONNECTION_INFO_COARSE_OTHER;
189 
190     case NUM_OF_CONNECTION_INFOS:
191       NOTREACHED();
192       return CONNECTION_INFO_COARSE_OTHER;
193   }
194 
195   NOTREACHED();
196   return CONNECTION_INFO_COARSE_OTHER;
197 }
198 
199 HttpResponseInfo::HttpResponseInfo() = default;
200 
201 HttpResponseInfo::HttpResponseInfo(const HttpResponseInfo& rhs) = default;
202 
203 HttpResponseInfo::~HttpResponseInfo() = default;
204 
205 HttpResponseInfo& HttpResponseInfo::operator=(const HttpResponseInfo& rhs) =
206     default;
207 
InitFromPickle(const base::Pickle & pickle,bool * response_truncated)208 bool HttpResponseInfo::InitFromPickle(const base::Pickle& pickle,
209                                       bool* response_truncated) {
210   base::PickleIterator iter(pickle);
211 
212   // Read flags and verify version
213   int flags;
214   if (!iter.ReadInt(&flags))
215     return false;
216   int version = flags & RESPONSE_INFO_VERSION_MASK;
217   if (version < RESPONSE_INFO_MINIMUM_VERSION ||
218       version > RESPONSE_INFO_VERSION) {
219     DLOG(ERROR) << "unexpected response info version: " << version;
220     return false;
221   }
222 
223   // Read request-time
224   int64_t time_val;
225   if (!iter.ReadInt64(&time_val))
226     return false;
227   request_time = Time::FromInternalValue(time_val);
228   was_cached = true;  // Set status to show cache resurrection.
229 
230   // Read response-time
231   if (!iter.ReadInt64(&time_val))
232     return false;
233   response_time = Time::FromInternalValue(time_val);
234 
235   // Read response-headers
236   headers = base::MakeRefCounted<HttpResponseHeaders>(&iter);
237   if (headers->response_code() == -1)
238     return false;
239 
240   // Read ssl-info
241   if (flags & RESPONSE_INFO_HAS_CERT) {
242     ssl_info.cert = X509Certificate::CreateFromPickle(&iter);
243     if (!ssl_info.cert.get())
244       return false;
245   }
246   if (flags & RESPONSE_INFO_HAS_CERT_STATUS) {
247     CertStatus cert_status;
248     if (!iter.ReadUInt32(&cert_status))
249       return false;
250     ssl_info.cert_status = cert_status;
251   }
252   if (flags & RESPONSE_INFO_HAS_SECURITY_BITS) {
253     // The security_bits field has been removed from ssl_info. For backwards
254     // compatibility, we should still read the value out of iter.
255     int security_bits;
256     if (!iter.ReadInt(&security_bits))
257       return false;
258   }
259 
260   if (flags & RESPONSE_INFO_HAS_SSL_CONNECTION_STATUS) {
261     int connection_status;
262     if (!iter.ReadInt(&connection_status))
263       return false;
264 
265     // SSLv3 is gone, so drop cached entries that were loaded over SSLv3.
266     if (SSLConnectionStatusToVersion(connection_status) ==
267         SSL_CONNECTION_VERSION_SSL3) {
268       return false;
269     }
270     ssl_info.connection_status = connection_status;
271   }
272 
273   // Signed Certificate Timestamps are no longer persisted to the cache, so
274   // ignore them when reading them out.
275   if (flags & RESPONSE_INFO_HAS_SIGNED_CERTIFICATE_TIMESTAMPS) {
276     int num_scts;
277     if (!iter.ReadInt(&num_scts))
278       return false;
279     for (int i = 0; i < num_scts; ++i) {
280       scoped_refptr<ct::SignedCertificateTimestamp> sct(
281           ct::SignedCertificateTimestamp::CreateFromPickle(&iter));
282       uint16_t status;
283       if (!sct.get() || !iter.ReadUInt16(&status))
284         return false;
285     }
286   }
287 
288   // Read vary-data
289   if (flags & RESPONSE_INFO_HAS_VARY_DATA) {
290     if (!vary_data.InitFromPickle(&iter))
291       return false;
292   }
293 
294   // Read socket_address.
295   std::string socket_address_host;
296   if (!iter.ReadString(&socket_address_host))
297     return false;
298   // If the host was written, we always expect the port to follow.
299   uint16_t socket_address_port;
300   if (!iter.ReadUInt16(&socket_address_port))
301     return false;
302 
303   IPAddress ip_address;
304   if (ip_address.AssignFromIPLiteral(socket_address_host)) {
305     remote_endpoint = IPEndPoint(ip_address, socket_address_port);
306   } else if (ParseURLHostnameToAddress(socket_address_host, &ip_address)) {
307     remote_endpoint = IPEndPoint(ip_address, socket_address_port);
308   }
309 
310   // Read protocol-version.
311   if (flags & RESPONSE_INFO_HAS_ALPN_NEGOTIATED_PROTOCOL) {
312     if (!iter.ReadString(&alpn_negotiated_protocol))
313       return false;
314   }
315 
316   // Read connection info.
317   if (flags & RESPONSE_INFO_HAS_CONNECTION_INFO) {
318     int value;
319     if (!iter.ReadInt(&value))
320       return false;
321 
322     if (value > static_cast<int>(CONNECTION_INFO_UNKNOWN) &&
323         value < static_cast<int>(NUM_OF_CONNECTION_INFOS)) {
324       connection_info = static_cast<ConnectionInfo>(value);
325     }
326   }
327 
328   // Read key_exchange_group
329   if (flags & RESPONSE_INFO_HAS_KEY_EXCHANGE_GROUP) {
330     int key_exchange_group;
331     if (!iter.ReadInt(&key_exchange_group))
332       return false;
333 
334     // Historically, the key_exchange_group field was key_exchange_info which
335     // conflated a number of different values based on the cipher suite, so some
336     // values must be discarded. See https://crbug.com/639421.
337     if (KeyExchangeGroupIsValid(ssl_info.connection_status))
338       ssl_info.key_exchange_group = key_exchange_group;
339   }
340 
341   // Read staleness time.
342   if (flags & RESPONSE_INFO_HAS_STALENESS) {
343     if (!iter.ReadInt64(&time_val))
344       return false;
345     stale_revalidate_timeout = base::Time() + base::Microseconds(time_val);
346   }
347 
348   was_fetched_via_spdy = (flags & RESPONSE_INFO_WAS_SPDY) != 0;
349 
350   was_alpn_negotiated = (flags & RESPONSE_INFO_WAS_ALPN) != 0;
351 
352   was_fetched_via_proxy = (flags & RESPONSE_INFO_WAS_PROXY) != 0;
353 
354   *response_truncated = (flags & RESPONSE_INFO_TRUNCATED) != 0;
355 
356   did_use_http_auth = (flags & RESPONSE_INFO_USE_HTTP_AUTHENTICATION) != 0;
357 
358   unused_since_prefetch = (flags & RESPONSE_INFO_UNUSED_SINCE_PREFETCH) != 0;
359 
360   restricted_prefetch = (flags & RESPONSE_INFO_RESTRICTED_PREFETCH) != 0;
361 
362   single_keyed_cache_entry_unusable =
363       (flags & RESPONSE_INFO_SINGLE_KEYED_CACHE_ENTRY_UNUSABLE) != 0;
364 
365   ssl_info.pkp_bypassed = (flags & RESPONSE_INFO_PKP_BYPASSED) != 0;
366 
367   // Read peer_signature_algorithm.
368   if (flags & RESPONSE_INFO_HAS_PEER_SIGNATURE_ALGORITHM) {
369     int peer_signature_algorithm;
370     if (!iter.ReadInt(&peer_signature_algorithm) ||
371         !base::IsValueInRangeForNumericType<uint16_t>(
372             peer_signature_algorithm)) {
373       return false;
374     }
375     ssl_info.peer_signature_algorithm =
376         base::checked_cast<uint16_t>(peer_signature_algorithm);
377   }
378 
379   // Read DNS aliases.
380   if (flags & RESPONSE_INFO_HAS_DNS_ALIASES) {
381     int num_aliases;
382     if (!iter.ReadInt(&num_aliases))
383       return false;
384 
385     std::string alias;
386     for (int i = 0; i < num_aliases; i++) {
387       if (!iter.ReadString(&alias))
388         return false;
389       dns_aliases.insert(alias);
390     }
391   }
392 
393   ssl_info.encrypted_client_hello =
394       (flags & RESPONSE_INFO_ENCRYPTED_CLIENT_HELLO) != 0;
395 
396   // Read browser_run_id.
397   if (flags & RESPONSE_INFO_BROWSER_RUN_ID) {
398     int64_t id;
399     if (!iter.ReadInt64(&id))
400       return false;
401     browser_run_id = absl::make_optional(id);
402   }
403 
404   return true;
405 }
406 
Persist(base::Pickle * pickle,bool skip_transient_headers,bool response_truncated) const407 void HttpResponseInfo::Persist(base::Pickle* pickle,
408                                bool skip_transient_headers,
409                                bool response_truncated) const {
410   int flags = RESPONSE_INFO_VERSION;
411   if (ssl_info.is_valid()) {
412     flags |= RESPONSE_INFO_HAS_CERT;
413     flags |= RESPONSE_INFO_HAS_CERT_STATUS;
414     if (ssl_info.key_exchange_group != 0)
415       flags |= RESPONSE_INFO_HAS_KEY_EXCHANGE_GROUP;
416     if (ssl_info.connection_status != 0)
417       flags |= RESPONSE_INFO_HAS_SSL_CONNECTION_STATUS;
418     if (ssl_info.peer_signature_algorithm != 0)
419       flags |= RESPONSE_INFO_HAS_PEER_SIGNATURE_ALGORITHM;
420   }
421   if (vary_data.is_valid())
422     flags |= RESPONSE_INFO_HAS_VARY_DATA;
423   if (response_truncated)
424     flags |= RESPONSE_INFO_TRUNCATED;
425   if (was_fetched_via_spdy)
426     flags |= RESPONSE_INFO_WAS_SPDY;
427   if (was_alpn_negotiated) {
428     flags |= RESPONSE_INFO_WAS_ALPN;
429     flags |= RESPONSE_INFO_HAS_ALPN_NEGOTIATED_PROTOCOL;
430   }
431   if (was_fetched_via_proxy)
432     flags |= RESPONSE_INFO_WAS_PROXY;
433   if (connection_info != CONNECTION_INFO_UNKNOWN)
434     flags |= RESPONSE_INFO_HAS_CONNECTION_INFO;
435   if (did_use_http_auth)
436     flags |= RESPONSE_INFO_USE_HTTP_AUTHENTICATION;
437   if (unused_since_prefetch)
438     flags |= RESPONSE_INFO_UNUSED_SINCE_PREFETCH;
439   if (restricted_prefetch)
440     flags |= RESPONSE_INFO_RESTRICTED_PREFETCH;
441   if (single_keyed_cache_entry_unusable)
442     flags |= RESPONSE_INFO_SINGLE_KEYED_CACHE_ENTRY_UNUSABLE;
443   if (ssl_info.pkp_bypassed)
444     flags |= RESPONSE_INFO_PKP_BYPASSED;
445   if (!stale_revalidate_timeout.is_null())
446     flags |= RESPONSE_INFO_HAS_STALENESS;
447   if (!dns_aliases.empty())
448     flags |= RESPONSE_INFO_HAS_DNS_ALIASES;
449   if (ssl_info.encrypted_client_hello)
450     flags |= RESPONSE_INFO_ENCRYPTED_CLIENT_HELLO;
451   if (browser_run_id.has_value())
452     flags |= RESPONSE_INFO_BROWSER_RUN_ID;
453 
454   pickle->WriteInt(flags);
455   pickle->WriteInt64(request_time.ToInternalValue());
456   pickle->WriteInt64(response_time.ToInternalValue());
457 
458   HttpResponseHeaders::PersistOptions persist_options =
459       HttpResponseHeaders::PERSIST_RAW;
460 
461   if (skip_transient_headers) {
462     persist_options = HttpResponseHeaders::PERSIST_SANS_COOKIES |
463                       HttpResponseHeaders::PERSIST_SANS_CHALLENGES |
464                       HttpResponseHeaders::PERSIST_SANS_HOP_BY_HOP |
465                       HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE |
466                       HttpResponseHeaders::PERSIST_SANS_RANGES |
467                       HttpResponseHeaders::PERSIST_SANS_SECURITY_STATE;
468   }
469 
470   headers->Persist(pickle, persist_options);
471 
472   if (ssl_info.is_valid()) {
473     ssl_info.cert->Persist(pickle);
474     pickle->WriteUInt32(ssl_info.cert_status);
475     if (ssl_info.connection_status != 0)
476       pickle->WriteInt(ssl_info.connection_status);
477   }
478 
479   if (vary_data.is_valid())
480     vary_data.Persist(pickle);
481 
482   pickle->WriteString(remote_endpoint.ToStringWithoutPort());
483   pickle->WriteUInt16(remote_endpoint.port());
484 
485   if (was_alpn_negotiated)
486     pickle->WriteString(alpn_negotiated_protocol);
487 
488   if (connection_info != CONNECTION_INFO_UNKNOWN)
489     pickle->WriteInt(static_cast<int>(connection_info));
490 
491   if (ssl_info.is_valid() && ssl_info.key_exchange_group != 0)
492     pickle->WriteInt(ssl_info.key_exchange_group);
493 
494   if (flags & RESPONSE_INFO_HAS_STALENESS) {
495     pickle->WriteInt64(
496         (stale_revalidate_timeout - base::Time()).InMicroseconds());
497   }
498 
499   if (ssl_info.is_valid() && ssl_info.peer_signature_algorithm != 0)
500     pickle->WriteInt(ssl_info.peer_signature_algorithm);
501 
502   if (!dns_aliases.empty()) {
503     pickle->WriteInt(dns_aliases.size());
504     for (const auto& alias : dns_aliases)
505       pickle->WriteString(alias);
506   }
507 
508   if (browser_run_id.has_value()) {
509     pickle->WriteInt64(browser_run_id.value());
510   }
511 }
512 
DidUseQuic() const513 bool HttpResponseInfo::DidUseQuic() const {
514   switch (connection_info) {
515     case CONNECTION_INFO_UNKNOWN:
516     case CONNECTION_INFO_HTTP1_1:
517     case CONNECTION_INFO_DEPRECATED_SPDY2:
518     case CONNECTION_INFO_DEPRECATED_SPDY3:
519     case CONNECTION_INFO_HTTP2:
520     case CONNECTION_INFO_DEPRECATED_HTTP2_14:
521     case CONNECTION_INFO_DEPRECATED_HTTP2_15:
522     case CONNECTION_INFO_HTTP0_9:
523     case CONNECTION_INFO_HTTP1_0:
524       return false;
525     case CONNECTION_INFO_QUIC_UNKNOWN_VERSION:
526     case CONNECTION_INFO_QUIC_32:
527     case CONNECTION_INFO_QUIC_33:
528     case CONNECTION_INFO_QUIC_34:
529     case CONNECTION_INFO_QUIC_35:
530     case CONNECTION_INFO_QUIC_36:
531     case CONNECTION_INFO_QUIC_37:
532     case CONNECTION_INFO_QUIC_38:
533     case CONNECTION_INFO_QUIC_39:
534     case CONNECTION_INFO_QUIC_40:
535     case CONNECTION_INFO_QUIC_41:
536     case CONNECTION_INFO_QUIC_42:
537     case CONNECTION_INFO_QUIC_43:
538     case CONNECTION_INFO_QUIC_44:
539     case CONNECTION_INFO_QUIC_45:
540     case CONNECTION_INFO_QUIC_46:
541     case CONNECTION_INFO_QUIC_47:
542     case CONNECTION_INFO_QUIC_Q048:
543     case CONNECTION_INFO_QUIC_T048:
544     case CONNECTION_INFO_QUIC_Q049:
545     case CONNECTION_INFO_QUIC_T049:
546     case CONNECTION_INFO_QUIC_Q050:
547     case CONNECTION_INFO_QUIC_T050:
548     case CONNECTION_INFO_QUIC_Q099:
549     case CONNECTION_INFO_QUIC_T099:
550     case CONNECTION_INFO_QUIC_999:
551     case CONNECTION_INFO_QUIC_DRAFT_25:
552     case CONNECTION_INFO_QUIC_DRAFT_27:
553     case CONNECTION_INFO_QUIC_DRAFT_28:
554     case CONNECTION_INFO_QUIC_DRAFT_29:
555     case CONNECTION_INFO_QUIC_T051:
556     case CONNECTION_INFO_QUIC_RFC_V1:
557     case CONNECTION_INFO_DEPRECATED_QUIC_2_DRAFT_1:
558     case CONNECTION_INFO_QUIC_2_DRAFT_8:
559       return true;
560     case NUM_OF_CONNECTION_INFOS:
561       NOTREACHED();
562       return false;
563   }
564   NOTREACHED();
565   return false;
566 }
567 
568 // static
ConnectionInfoToString(ConnectionInfo connection_info)569 std::string HttpResponseInfo::ConnectionInfoToString(
570     ConnectionInfo connection_info) {
571   switch (connection_info) {
572     case CONNECTION_INFO_UNKNOWN:
573       return "unknown";
574     case CONNECTION_INFO_HTTP1_1:
575       return "http/1.1";
576     case CONNECTION_INFO_DEPRECATED_SPDY2:
577       NOTREACHED();
578       return "";
579     case CONNECTION_INFO_DEPRECATED_SPDY3:
580       return "spdy/3";
581     // Since ConnectionInfo is persisted to disk, deprecated values have to be
582     // handled. Note that h2-14 and h2-15 are essentially wire compatible with
583     // h2.
584     // Intentional fallthrough.
585     case CONNECTION_INFO_DEPRECATED_HTTP2_14:
586     case CONNECTION_INFO_DEPRECATED_HTTP2_15:
587     case CONNECTION_INFO_HTTP2:
588       return "h2";
589     case CONNECTION_INFO_QUIC_UNKNOWN_VERSION:
590       return "http/2+quic";
591     case CONNECTION_INFO_QUIC_32:
592       return "http/2+quic/32";
593     case CONNECTION_INFO_QUIC_33:
594       return "http/2+quic/33";
595     case CONNECTION_INFO_QUIC_34:
596       return "http/2+quic/34";
597     case CONNECTION_INFO_QUIC_35:
598       return "http/2+quic/35";
599     case CONNECTION_INFO_QUIC_36:
600       return "http/2+quic/36";
601     case CONNECTION_INFO_QUIC_37:
602       return "http/2+quic/37";
603     case CONNECTION_INFO_QUIC_38:
604       return "http/2+quic/38";
605     case CONNECTION_INFO_QUIC_39:
606       return "http/2+quic/39";
607     case CONNECTION_INFO_QUIC_40:
608       return "http/2+quic/40";
609     case CONNECTION_INFO_QUIC_41:
610       return "http/2+quic/41";
611     case CONNECTION_INFO_QUIC_42:
612       return "http/2+quic/42";
613     case CONNECTION_INFO_QUIC_43:
614       return "http/2+quic/43";
615     case CONNECTION_INFO_QUIC_44:
616       return "http/2+quic/44";
617     case CONNECTION_INFO_QUIC_45:
618       return "http/2+quic/45";
619     case CONNECTION_INFO_QUIC_46:
620       return "http/2+quic/46";
621     case CONNECTION_INFO_QUIC_47:
622       return "http/2+quic/47";
623     case CONNECTION_INFO_QUIC_Q048:
624       return "h3-Q048";
625     case CONNECTION_INFO_QUIC_T048:
626       return "h3-T048";
627     case CONNECTION_INFO_QUIC_Q049:
628       return "h3-Q049";
629     case CONNECTION_INFO_QUIC_T049:
630       return "h3-T049";
631     case CONNECTION_INFO_QUIC_Q050:
632       return "h3-Q050";
633     case CONNECTION_INFO_QUIC_T050:
634       return "h3-T050";
635     case CONNECTION_INFO_QUIC_Q099:
636       return "h3-Q099";
637     case CONNECTION_INFO_QUIC_DRAFT_25:
638       return "h3-25";
639     case CONNECTION_INFO_QUIC_DRAFT_27:
640       return "h3-27";
641     case CONNECTION_INFO_QUIC_DRAFT_28:
642       return "h3-28";
643     case CONNECTION_INFO_QUIC_DRAFT_29:
644       return "h3-29";
645     case CONNECTION_INFO_QUIC_T099:
646       return "h3-T099";
647     case CONNECTION_INFO_HTTP0_9:
648       return "http/0.9";
649     case CONNECTION_INFO_HTTP1_0:
650       return "http/1.0";
651     case CONNECTION_INFO_QUIC_999:
652       return "http2+quic/999";
653     case CONNECTION_INFO_QUIC_T051:
654       return "h3-T051";
655     case CONNECTION_INFO_QUIC_RFC_V1:
656       return "h3";
657     case CONNECTION_INFO_DEPRECATED_QUIC_2_DRAFT_1:
658       return "h3/quic2draft01";
659     case CONNECTION_INFO_QUIC_2_DRAFT_8:
660       return "h3/quic2draft08";
661     case NUM_OF_CONNECTION_INFOS:
662       break;
663   }
664   NOTREACHED();
665   return "";
666 }
667 
668 }  // namespace net
669