cc: Added inline to Tile::IsReadyToDraw
[chromium-blink-merge.git] / net / http / http_response_info.cc
blob0b57a4e774bb76555a6e6080ee0255cc4b289bbe
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/http/http_response_info.h"
7 #include "base/logging.h"
8 #include "base/pickle.h"
9 #include "base/time/time.h"
10 #include "net/base/auth.h"
11 #include "net/base/io_buffer.h"
12 #include "net/base/net_errors.h"
13 #include "net/cert/x509_certificate.h"
14 #include "net/http/http_response_headers.h"
15 #include "net/ssl/ssl_cert_request_info.h"
17 using base::Time;
19 namespace net {
21 namespace {
23 X509Certificate::PickleType GetPickleTypeForVersion(int version) {
24 switch (version) {
25 case 1:
26 return X509Certificate::PICKLETYPE_SINGLE_CERTIFICATE;
27 case 2:
28 return X509Certificate::PICKLETYPE_CERTIFICATE_CHAIN_V2;
29 case 3:
30 default:
31 return X509Certificate::PICKLETYPE_CERTIFICATE_CHAIN_V3;
35 } // namespace
37 // These values can be bit-wise combined to form the flags field of the
38 // serialized HttpResponseInfo.
39 enum {
40 // The version of the response info used when persisting response info.
41 RESPONSE_INFO_VERSION = 3,
43 // The minimum version supported for deserializing response info.
44 RESPONSE_INFO_MINIMUM_VERSION = 1,
46 // We reserve up to 8 bits for the version number.
47 RESPONSE_INFO_VERSION_MASK = 0xFF,
49 // This bit is set if the response info has a cert at the end.
50 // Version 1 serialized only the end-entity certificate, while subsequent
51 // versions include the available certificate chain.
52 RESPONSE_INFO_HAS_CERT = 1 << 8,
54 // This bit is set if the response info has a security-bits field (security
55 // strength, in bits, of the SSL connection) at the end.
56 RESPONSE_INFO_HAS_SECURITY_BITS = 1 << 9,
58 // This bit is set if the response info has a cert status at the end.
59 RESPONSE_INFO_HAS_CERT_STATUS = 1 << 10,
61 // This bit is set if the response info has vary header data.
62 RESPONSE_INFO_HAS_VARY_DATA = 1 << 11,
64 // This bit is set if the request was cancelled before completion.
65 RESPONSE_INFO_TRUNCATED = 1 << 12,
67 // This bit is set if the response was received via SPDY.
68 RESPONSE_INFO_WAS_SPDY = 1 << 13,
70 // This bit is set if the request has NPN negotiated.
71 RESPONSE_INFO_WAS_NPN = 1 << 14,
73 // This bit is set if the request was fetched via an explicit proxy.
74 RESPONSE_INFO_WAS_PROXY = 1 << 15,
76 // This bit is set if the response info has an SSL connection status field.
77 // This contains the ciphersuite used to fetch the resource as well as the
78 // protocol version, compression method and whether SSLv3 fallback was used.
79 RESPONSE_INFO_HAS_SSL_CONNECTION_STATUS = 1 << 16,
81 // This bit is set if the response info has protocol version.
82 RESPONSE_INFO_HAS_NPN_NEGOTIATED_PROTOCOL = 1 << 17,
84 // This bit is set if the response info has connection info.
85 RESPONSE_INFO_HAS_CONNECTION_INFO = 1 << 18,
87 // This bit is set if the request has http authentication.
88 RESPONSE_INFO_USE_HTTP_AUTHENTICATION = 1 << 19,
90 // TODO(darin): Add other bits to indicate alternate request methods.
91 // For now, we don't support storing those.
94 HttpResponseInfo::HttpResponseInfo()
95 : was_cached(false),
96 server_data_unavailable(false),
97 network_accessed(false),
98 was_fetched_via_spdy(false),
99 was_npn_negotiated(false),
100 was_fetched_via_proxy(false),
101 did_use_http_auth(false),
102 connection_info(CONNECTION_INFO_UNKNOWN) {
105 HttpResponseInfo::HttpResponseInfo(const HttpResponseInfo& rhs)
106 : was_cached(rhs.was_cached),
107 server_data_unavailable(rhs.server_data_unavailable),
108 network_accessed(rhs.network_accessed),
109 was_fetched_via_spdy(rhs.was_fetched_via_spdy),
110 was_npn_negotiated(rhs.was_npn_negotiated),
111 was_fetched_via_proxy(rhs.was_fetched_via_proxy),
112 did_use_http_auth(rhs.did_use_http_auth),
113 socket_address(rhs.socket_address),
114 npn_negotiated_protocol(rhs.npn_negotiated_protocol),
115 connection_info(rhs.connection_info),
116 request_time(rhs.request_time),
117 response_time(rhs.response_time),
118 auth_challenge(rhs.auth_challenge),
119 cert_request_info(rhs.cert_request_info),
120 ssl_info(rhs.ssl_info),
121 headers(rhs.headers),
122 vary_data(rhs.vary_data),
123 metadata(rhs.metadata) {
126 HttpResponseInfo::~HttpResponseInfo() {
129 HttpResponseInfo& HttpResponseInfo::operator=(const HttpResponseInfo& rhs) {
130 was_cached = rhs.was_cached;
131 server_data_unavailable = rhs.server_data_unavailable;
132 network_accessed = rhs.network_accessed;
133 was_fetched_via_spdy = rhs.was_fetched_via_spdy;
134 was_npn_negotiated = rhs.was_npn_negotiated;
135 was_fetched_via_proxy = rhs.was_fetched_via_proxy;
136 did_use_http_auth = rhs.did_use_http_auth;
137 socket_address = rhs.socket_address;
138 npn_negotiated_protocol = rhs.npn_negotiated_protocol;
139 connection_info = rhs.connection_info;
140 request_time = rhs.request_time;
141 response_time = rhs.response_time;
142 auth_challenge = rhs.auth_challenge;
143 cert_request_info = rhs.cert_request_info;
144 ssl_info = rhs.ssl_info;
145 headers = rhs.headers;
146 vary_data = rhs.vary_data;
147 metadata = rhs.metadata;
148 return *this;
151 bool HttpResponseInfo::InitFromPickle(const Pickle& pickle,
152 bool* response_truncated) {
153 PickleIterator iter(pickle);
155 // Read flags and verify version
156 int flags;
157 if (!pickle.ReadInt(&iter, &flags))
158 return false;
159 int version = flags & RESPONSE_INFO_VERSION_MASK;
160 if (version < RESPONSE_INFO_MINIMUM_VERSION ||
161 version > RESPONSE_INFO_VERSION) {
162 DLOG(ERROR) << "unexpected response info version: " << version;
163 return false;
166 // Read request-time
167 int64 time_val;
168 if (!pickle.ReadInt64(&iter, &time_val))
169 return false;
170 request_time = Time::FromInternalValue(time_val);
171 was_cached = true; // Set status to show cache resurrection.
173 // Read response-time
174 if (!pickle.ReadInt64(&iter, &time_val))
175 return false;
176 response_time = Time::FromInternalValue(time_val);
178 // Read response-headers
179 headers = new HttpResponseHeaders(pickle, &iter);
180 if (headers->response_code() == -1)
181 return false;
183 // Read ssl-info
184 if (flags & RESPONSE_INFO_HAS_CERT) {
185 X509Certificate::PickleType type = GetPickleTypeForVersion(version);
186 ssl_info.cert = X509Certificate::CreateFromPickle(pickle, &iter, type);
187 if (!ssl_info.cert.get())
188 return false;
190 if (flags & RESPONSE_INFO_HAS_CERT_STATUS) {
191 CertStatus cert_status;
192 if (!pickle.ReadUInt32(&iter, &cert_status))
193 return false;
194 ssl_info.cert_status = cert_status;
196 if (flags & RESPONSE_INFO_HAS_SECURITY_BITS) {
197 int security_bits;
198 if (!pickle.ReadInt(&iter, &security_bits))
199 return false;
200 ssl_info.security_bits = security_bits;
203 if (flags & RESPONSE_INFO_HAS_SSL_CONNECTION_STATUS) {
204 int connection_status;
205 if (!pickle.ReadInt(&iter, &connection_status))
206 return false;
207 ssl_info.connection_status = connection_status;
210 // Read vary-data
211 if (flags & RESPONSE_INFO_HAS_VARY_DATA) {
212 if (!vary_data.InitFromPickle(pickle, &iter))
213 return false;
216 // Read socket_address.
217 std::string socket_address_host;
218 if (pickle.ReadString(&iter, &socket_address_host)) {
219 // If the host was written, we always expect the port to follow.
220 uint16 socket_address_port;
221 if (!pickle.ReadUInt16(&iter, &socket_address_port))
222 return false;
223 socket_address = HostPortPair(socket_address_host, socket_address_port);
224 } else if (version > 1) {
225 // socket_address was not always present in version 1 of the response
226 // info, so we don't fail if it can't be read.
227 return false;
230 // Read protocol-version.
231 if (flags & RESPONSE_INFO_HAS_NPN_NEGOTIATED_PROTOCOL) {
232 if (!pickle.ReadString(&iter, &npn_negotiated_protocol))
233 return false;
236 // Read connection info.
237 if (flags & RESPONSE_INFO_HAS_CONNECTION_INFO) {
238 int value;
239 if (!pickle.ReadInt(&iter, &value))
240 return false;
242 if (value > static_cast<int>(CONNECTION_INFO_UNKNOWN) &&
243 value < static_cast<int>(NUM_OF_CONNECTION_INFOS)) {
244 connection_info = static_cast<ConnectionInfo>(value);
248 was_fetched_via_spdy = (flags & RESPONSE_INFO_WAS_SPDY) != 0;
250 was_npn_negotiated = (flags & RESPONSE_INFO_WAS_NPN) != 0;
252 was_fetched_via_proxy = (flags & RESPONSE_INFO_WAS_PROXY) != 0;
254 *response_truncated = (flags & RESPONSE_INFO_TRUNCATED) != 0;
256 did_use_http_auth = (flags & RESPONSE_INFO_USE_HTTP_AUTHENTICATION) != 0;
258 return true;
261 void HttpResponseInfo::Persist(Pickle* pickle,
262 bool skip_transient_headers,
263 bool response_truncated) const {
264 int flags = RESPONSE_INFO_VERSION;
265 if (ssl_info.is_valid()) {
266 flags |= RESPONSE_INFO_HAS_CERT;
267 flags |= RESPONSE_INFO_HAS_CERT_STATUS;
268 if (ssl_info.security_bits != -1)
269 flags |= RESPONSE_INFO_HAS_SECURITY_BITS;
270 if (ssl_info.connection_status != 0)
271 flags |= RESPONSE_INFO_HAS_SSL_CONNECTION_STATUS;
273 if (vary_data.is_valid())
274 flags |= RESPONSE_INFO_HAS_VARY_DATA;
275 if (response_truncated)
276 flags |= RESPONSE_INFO_TRUNCATED;
277 if (was_fetched_via_spdy)
278 flags |= RESPONSE_INFO_WAS_SPDY;
279 if (was_npn_negotiated) {
280 flags |= RESPONSE_INFO_WAS_NPN;
281 flags |= RESPONSE_INFO_HAS_NPN_NEGOTIATED_PROTOCOL;
283 if (was_fetched_via_proxy)
284 flags |= RESPONSE_INFO_WAS_PROXY;
285 if (connection_info != CONNECTION_INFO_UNKNOWN)
286 flags |= RESPONSE_INFO_HAS_CONNECTION_INFO;
287 if (did_use_http_auth)
288 flags |= RESPONSE_INFO_USE_HTTP_AUTHENTICATION;
290 pickle->WriteInt(flags);
291 pickle->WriteInt64(request_time.ToInternalValue());
292 pickle->WriteInt64(response_time.ToInternalValue());
294 net::HttpResponseHeaders::PersistOptions persist_options =
295 net::HttpResponseHeaders::PERSIST_RAW;
297 if (skip_transient_headers) {
298 persist_options =
299 net::HttpResponseHeaders::PERSIST_SANS_COOKIES |
300 net::HttpResponseHeaders::PERSIST_SANS_CHALLENGES |
301 net::HttpResponseHeaders::PERSIST_SANS_HOP_BY_HOP |
302 net::HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE |
303 net::HttpResponseHeaders::PERSIST_SANS_RANGES |
304 net::HttpResponseHeaders::PERSIST_SANS_SECURITY_STATE;
307 headers->Persist(pickle, persist_options);
309 if (ssl_info.is_valid()) {
310 ssl_info.cert->Persist(pickle);
311 pickle->WriteUInt32(ssl_info.cert_status);
312 if (ssl_info.security_bits != -1)
313 pickle->WriteInt(ssl_info.security_bits);
314 if (ssl_info.connection_status != 0)
315 pickle->WriteInt(ssl_info.connection_status);
318 if (vary_data.is_valid())
319 vary_data.Persist(pickle);
321 pickle->WriteString(socket_address.host());
322 pickle->WriteUInt16(socket_address.port());
324 if (was_npn_negotiated)
325 pickle->WriteString(npn_negotiated_protocol);
327 if (connection_info != CONNECTION_INFO_UNKNOWN)
328 pickle->WriteInt(static_cast<int>(connection_info));
331 HttpResponseInfo::ConnectionInfo HttpResponseInfo::ConnectionInfoFromNextProto(
332 NextProto next_proto) {
333 switch (next_proto) {
334 case kProtoSPDY2:
335 return CONNECTION_INFO_SPDY2;
336 case kProtoSPDY3:
337 case kProtoSPDY31:
338 return CONNECTION_INFO_SPDY3;
339 case kProtoSPDY4a2:
340 return CONNECTION_INFO_SPDY4A2;
341 case kProtoHTTP2Draft04:
342 return CONNECTION_INFO_HTTP2_DRAFT_04;
343 case kProtoQUIC1SPDY3:
344 return CONNECTION_INFO_QUIC1_SPDY3;
346 case kProtoUnknown:
347 case kProtoHTTP11:
348 case kProtoSPDY1:
349 case kProtoSPDY21:
350 break;
353 NOTREACHED();
354 return CONNECTION_INFO_UNKNOWN;
357 // static
358 std::string HttpResponseInfo::ConnectionInfoToString(
359 ConnectionInfo connection_info) {
360 switch (connection_info) {
361 case CONNECTION_INFO_UNKNOWN:
362 return "unknown";
363 case CONNECTION_INFO_HTTP1:
364 return "http/1";
365 case CONNECTION_INFO_SPDY2:
366 return "spdy/2";
367 case CONNECTION_INFO_SPDY3:
368 return "spdy/3";
369 case CONNECTION_INFO_SPDY4A2:
370 return "spdy/4a2";
371 case CONNECTION_INFO_HTTP2_DRAFT_04:
372 return "HTTP-draft-04/2.0";
373 case CONNECTION_INFO_QUIC1_SPDY3:
374 return "quic/1+spdy/3";
375 case NUM_OF_CONNECTION_INFOS:
376 break;
378 NOTREACHED();
379 return "";
382 } // namespace net