Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / net / http / http_response_info.cc
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.
4
5 #include "net/http/http_response_info.h"
6
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/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
18 using base::Time;
19
20 namespace net {
21
22 namespace {
23
24 X509Certificate::PickleType GetPickleTypeForVersion(int version) {
25   switch (version) {
26     case 1:
27       return X509Certificate::PICKLETYPE_SINGLE_CERTIFICATE;
28     case 2:
29       return X509Certificate::PICKLETYPE_CERTIFICATE_CHAIN_V2;
30     case 3:
31     default:
32       return X509Certificate::PICKLETYPE_CERTIFICATE_CHAIN_V3;
33   }
34 }
35
36 }  // namespace
37
38 // These values can be bit-wise combined to form the flags field of the
39 // serialized HttpResponseInfo.
40 enum {
41   // The version of the response info used when persisting response info.
42   RESPONSE_INFO_VERSION = 3,
43
44   // The minimum version supported for deserializing response info.
45   RESPONSE_INFO_MINIMUM_VERSION = 1,
46
47   // We reserve up to 8 bits for the version number.
48   RESPONSE_INFO_VERSION_MASK = 0xFF,
49
50   // This bit is set if the response info has a cert at the end.
51   // Version 1 serialized only the end-entity certificate, while subsequent
52   // versions include the available certificate chain.
53   RESPONSE_INFO_HAS_CERT = 1 << 8,
54
55   // This bit is set if the response info has a security-bits field (security
56   // strength, in bits, of the SSL connection) at the end.
57   RESPONSE_INFO_HAS_SECURITY_BITS = 1 << 9,
58
59   // This bit is set if the response info has a cert status at the end.
60   RESPONSE_INFO_HAS_CERT_STATUS = 1 << 10,
61
62   // This bit is set if the response info has vary header data.
63   RESPONSE_INFO_HAS_VARY_DATA = 1 << 11,
64
65   // This bit is set if the request was cancelled before completion.
66   RESPONSE_INFO_TRUNCATED = 1 << 12,
67
68   // This bit is set if the response was received via SPDY.
69   RESPONSE_INFO_WAS_SPDY = 1 << 13,
70
71   // This bit is set if the request has NPN negotiated.
72   RESPONSE_INFO_WAS_NPN = 1 << 14,
73
74   // This bit is set if the request was fetched via an explicit proxy.
75   RESPONSE_INFO_WAS_PROXY = 1 << 15,
76
77   // This bit is set if the response info has an SSL connection status field.
78   // This contains the ciphersuite used to fetch the resource as well as the
79   // protocol version, compression method and whether SSLv3 fallback was used.
80   RESPONSE_INFO_HAS_SSL_CONNECTION_STATUS = 1 << 16,
81
82   // This bit is set if the response info has protocol version.
83   RESPONSE_INFO_HAS_NPN_NEGOTIATED_PROTOCOL = 1 << 17,
84
85   // This bit is set if the response info has connection info.
86   RESPONSE_INFO_HAS_CONNECTION_INFO = 1 << 18,
87
88   // This bit is set if the request has http authentication.
89   RESPONSE_INFO_USE_HTTP_AUTHENTICATION = 1 << 19,
90
91   // This bit is set if ssl_info has SCTs.
92   RESPONSE_INFO_HAS_SIGNED_CERTIFICATE_TIMESTAMPS = 1 << 20,
93
94   // TODO(darin): Add other bits to indicate alternate request methods.
95   // For now, we don't support storing those.
96 };
97
98 HttpResponseInfo::HttpResponseInfo()
99     : was_cached(false),
100       server_data_unavailable(false),
101       network_accessed(false),
102       was_fetched_via_spdy(false),
103       was_npn_negotiated(false),
104       was_fetched_via_proxy(false),
105       did_use_http_auth(false),
106       connection_info(CONNECTION_INFO_UNKNOWN) {
107 }
108
109 HttpResponseInfo::HttpResponseInfo(const HttpResponseInfo& rhs)
110     : was_cached(rhs.was_cached),
111       server_data_unavailable(rhs.server_data_unavailable),
112       network_accessed(rhs.network_accessed),
113       was_fetched_via_spdy(rhs.was_fetched_via_spdy),
114       was_npn_negotiated(rhs.was_npn_negotiated),
115       was_fetched_via_proxy(rhs.was_fetched_via_proxy),
116       proxy_server(rhs.proxy_server),
117       did_use_http_auth(rhs.did_use_http_auth),
118       socket_address(rhs.socket_address),
119       npn_negotiated_protocol(rhs.npn_negotiated_protocol),
120       connection_info(rhs.connection_info),
121       request_time(rhs.request_time),
122       response_time(rhs.response_time),
123       auth_challenge(rhs.auth_challenge),
124       cert_request_info(rhs.cert_request_info),
125       ssl_info(rhs.ssl_info),
126       headers(rhs.headers),
127       vary_data(rhs.vary_data),
128       metadata(rhs.metadata) {
129 }
130
131 HttpResponseInfo::~HttpResponseInfo() {
132 }
133
134 HttpResponseInfo& HttpResponseInfo::operator=(const HttpResponseInfo& rhs) {
135   was_cached = rhs.was_cached;
136   server_data_unavailable = rhs.server_data_unavailable;
137   network_accessed = rhs.network_accessed;
138   was_fetched_via_spdy = rhs.was_fetched_via_spdy;
139   proxy_server = rhs.proxy_server;
140   was_npn_negotiated = rhs.was_npn_negotiated;
141   was_fetched_via_proxy = rhs.was_fetched_via_proxy;
142   did_use_http_auth = rhs.did_use_http_auth;
143   socket_address = rhs.socket_address;
144   npn_negotiated_protocol = rhs.npn_negotiated_protocol;
145   connection_info = rhs.connection_info;
146   request_time = rhs.request_time;
147   response_time = rhs.response_time;
148   auth_challenge = rhs.auth_challenge;
149   cert_request_info = rhs.cert_request_info;
150   ssl_info = rhs.ssl_info;
151   headers = rhs.headers;
152   vary_data = rhs.vary_data;
153   metadata = rhs.metadata;
154   return *this;
155 }
156
157 bool HttpResponseInfo::InitFromPickle(const Pickle& pickle,
158                                       bool* response_truncated) {
159   PickleIterator iter(pickle);
160
161   // Read flags and verify version
162   int flags;
163   if (!pickle.ReadInt(&iter, &flags))
164     return false;
165   int version = flags & RESPONSE_INFO_VERSION_MASK;
166   if (version < RESPONSE_INFO_MINIMUM_VERSION ||
167       version > RESPONSE_INFO_VERSION) {
168     DLOG(ERROR) << "unexpected response info version: " << version;
169     return false;
170   }
171
172   // Read request-time
173   int64 time_val;
174   if (!pickle.ReadInt64(&iter, &time_val))
175     return false;
176   request_time = Time::FromInternalValue(time_val);
177   was_cached = true;  // Set status to show cache resurrection.
178
179   // Read response-time
180   if (!pickle.ReadInt64(&iter, &time_val))
181     return false;
182   response_time = Time::FromInternalValue(time_val);
183
184   // Read response-headers
185   headers = new HttpResponseHeaders(pickle, &iter);
186   if (headers->response_code() == -1)
187     return false;
188
189   // Read ssl-info
190   if (flags & RESPONSE_INFO_HAS_CERT) {
191     X509Certificate::PickleType type = GetPickleTypeForVersion(version);
192     ssl_info.cert = X509Certificate::CreateFromPickle(pickle, &iter, type);
193     if (!ssl_info.cert.get())
194       return false;
195   }
196   if (flags & RESPONSE_INFO_HAS_CERT_STATUS) {
197     CertStatus cert_status;
198     if (!pickle.ReadUInt32(&iter, &cert_status))
199       return false;
200     ssl_info.cert_status = cert_status;
201   }
202   if (flags & RESPONSE_INFO_HAS_SECURITY_BITS) {
203     int security_bits;
204     if (!pickle.ReadInt(&iter, &security_bits))
205       return false;
206     ssl_info.security_bits = security_bits;
207   }
208
209   if (flags & RESPONSE_INFO_HAS_SSL_CONNECTION_STATUS) {
210     int connection_status;
211     if (!pickle.ReadInt(&iter, &connection_status))
212       return false;
213     ssl_info.connection_status = connection_status;
214   }
215
216   if (flags & RESPONSE_INFO_HAS_SIGNED_CERTIFICATE_TIMESTAMPS) {
217     int num_scts;
218     if (!pickle.ReadInt(&iter, &num_scts))
219       return false;
220     for (int i = 0; i < num_scts; ++i) {
221       scoped_refptr<ct::SignedCertificateTimestamp> sct(
222           ct::SignedCertificateTimestamp::CreateFromPickle(&iter));
223       uint16 status;
224       if (!sct.get() || !pickle.ReadUInt16(&iter, &status))
225         return false;
226       ssl_info.signed_certificate_timestamps.push_back(
227           SignedCertificateTimestampAndStatus(
228               sct, static_cast<ct::SCTVerifyStatus>(status)));
229     }
230   }
231
232   // Read vary-data
233   if (flags & RESPONSE_INFO_HAS_VARY_DATA) {
234     if (!vary_data.InitFromPickle(pickle, &iter))
235       return false;
236   }
237
238   // Read socket_address.
239   std::string socket_address_host;
240   if (pickle.ReadString(&iter, &socket_address_host)) {
241     // If the host was written, we always expect the port to follow.
242     uint16 socket_address_port;
243     if (!pickle.ReadUInt16(&iter, &socket_address_port))
244       return false;
245     socket_address = HostPortPair(socket_address_host, socket_address_port);
246   } else if (version > 1) {
247     // socket_address was not always present in version 1 of the response
248     // info, so we don't fail if it can't be read.
249     return false;
250   }
251
252   // Read protocol-version.
253   if (flags & RESPONSE_INFO_HAS_NPN_NEGOTIATED_PROTOCOL) {
254     if (!pickle.ReadString(&iter, &npn_negotiated_protocol))
255       return false;
256   }
257
258   // Read connection info.
259   if (flags & RESPONSE_INFO_HAS_CONNECTION_INFO) {
260     int value;
261     if (!pickle.ReadInt(&iter, &value))
262       return false;
263
264     if (value > static_cast<int>(CONNECTION_INFO_UNKNOWN) &&
265         value < static_cast<int>(NUM_OF_CONNECTION_INFOS)) {
266       connection_info = static_cast<ConnectionInfo>(value);
267     }
268   }
269
270   was_fetched_via_spdy = (flags & RESPONSE_INFO_WAS_SPDY) != 0;
271
272   was_npn_negotiated = (flags & RESPONSE_INFO_WAS_NPN) != 0;
273
274   was_fetched_via_proxy = (flags & RESPONSE_INFO_WAS_PROXY) != 0;
275
276   *response_truncated = (flags & RESPONSE_INFO_TRUNCATED) != 0;
277
278   did_use_http_auth = (flags & RESPONSE_INFO_USE_HTTP_AUTHENTICATION) != 0;
279
280   return true;
281 }
282
283 void HttpResponseInfo::Persist(Pickle* pickle,
284                                bool skip_transient_headers,
285                                bool response_truncated) const {
286   int flags = RESPONSE_INFO_VERSION;
287   if (ssl_info.is_valid()) {
288     flags |= RESPONSE_INFO_HAS_CERT;
289     flags |= RESPONSE_INFO_HAS_CERT_STATUS;
290     if (ssl_info.security_bits != -1)
291       flags |= RESPONSE_INFO_HAS_SECURITY_BITS;
292     if (ssl_info.connection_status != 0)
293       flags |= RESPONSE_INFO_HAS_SSL_CONNECTION_STATUS;
294   }
295   if (vary_data.is_valid())
296     flags |= RESPONSE_INFO_HAS_VARY_DATA;
297   if (response_truncated)
298     flags |= RESPONSE_INFO_TRUNCATED;
299   if (was_fetched_via_spdy)
300     flags |= RESPONSE_INFO_WAS_SPDY;
301   if (was_npn_negotiated) {
302     flags |= RESPONSE_INFO_WAS_NPN;
303     flags |= RESPONSE_INFO_HAS_NPN_NEGOTIATED_PROTOCOL;
304   }
305   if (was_fetched_via_proxy)
306     flags |= RESPONSE_INFO_WAS_PROXY;
307   if (connection_info != CONNECTION_INFO_UNKNOWN)
308     flags |= RESPONSE_INFO_HAS_CONNECTION_INFO;
309   if (did_use_http_auth)
310     flags |= RESPONSE_INFO_USE_HTTP_AUTHENTICATION;
311   if (!ssl_info.signed_certificate_timestamps.empty())
312     flags |= RESPONSE_INFO_HAS_SIGNED_CERTIFICATE_TIMESTAMPS;
313
314   pickle->WriteInt(flags);
315   pickle->WriteInt64(request_time.ToInternalValue());
316   pickle->WriteInt64(response_time.ToInternalValue());
317
318   net::HttpResponseHeaders::PersistOptions persist_options =
319       net::HttpResponseHeaders::PERSIST_RAW;
320
321   if (skip_transient_headers) {
322     persist_options =
323         net::HttpResponseHeaders::PERSIST_SANS_COOKIES |
324         net::HttpResponseHeaders::PERSIST_SANS_CHALLENGES |
325         net::HttpResponseHeaders::PERSIST_SANS_HOP_BY_HOP |
326         net::HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE |
327         net::HttpResponseHeaders::PERSIST_SANS_RANGES |
328         net::HttpResponseHeaders::PERSIST_SANS_SECURITY_STATE;
329   }
330
331   headers->Persist(pickle, persist_options);
332
333   if (ssl_info.is_valid()) {
334     ssl_info.cert->Persist(pickle);
335     pickle->WriteUInt32(ssl_info.cert_status);
336     if (ssl_info.security_bits != -1)
337       pickle->WriteInt(ssl_info.security_bits);
338     if (ssl_info.connection_status != 0)
339       pickle->WriteInt(ssl_info.connection_status);
340     if (!ssl_info.signed_certificate_timestamps.empty()) {
341       pickle->WriteInt(ssl_info.signed_certificate_timestamps.size());
342       for (SignedCertificateTimestampAndStatusList::const_iterator it =
343            ssl_info.signed_certificate_timestamps.begin(); it !=
344            ssl_info.signed_certificate_timestamps.end(); ++it) {
345         it->sct->Persist(pickle);
346         pickle->WriteUInt16(it->status);
347       }
348     }
349   }
350
351   if (vary_data.is_valid())
352     vary_data.Persist(pickle);
353
354   pickle->WriteString(socket_address.host());
355   pickle->WriteUInt16(socket_address.port());
356
357   if (was_npn_negotiated)
358     pickle->WriteString(npn_negotiated_protocol);
359
360   if (connection_info != CONNECTION_INFO_UNKNOWN)
361     pickle->WriteInt(static_cast<int>(connection_info));
362 }
363
364 HttpResponseInfo::ConnectionInfo HttpResponseInfo::ConnectionInfoFromNextProto(
365     NextProto next_proto) {
366   switch (next_proto) {
367     case kProtoDeprecatedSPDY2:
368       return CONNECTION_INFO_DEPRECATED_SPDY2;
369     case kProtoSPDY3:
370     case kProtoSPDY31:
371       return CONNECTION_INFO_SPDY3;
372     case kProtoSPDY4:
373       return CONNECTION_INFO_SPDY4;
374     case kProtoQUIC1SPDY3:
375       return CONNECTION_INFO_QUIC1_SPDY3;
376
377     case kProtoUnknown:
378     case kProtoHTTP11:
379       break;
380   }
381
382   NOTREACHED();
383   return CONNECTION_INFO_UNKNOWN;
384 }
385
386 // static
387 std::string HttpResponseInfo::ConnectionInfoToString(
388     ConnectionInfo connection_info) {
389   switch (connection_info) {
390     case CONNECTION_INFO_UNKNOWN:
391       return "unknown";
392     case CONNECTION_INFO_HTTP1:
393       return "http/1";
394     case CONNECTION_INFO_DEPRECATED_SPDY2:
395       return "spdy/2";
396     case CONNECTION_INFO_SPDY3:
397       return "spdy/3";
398     case CONNECTION_INFO_SPDY4:
399       // This is the HTTP/2 draft 13 identifier. For internal
400       // consistency, HTTP/2 is named SPDY4 within Chromium.
401       return "h2-13";
402     case CONNECTION_INFO_QUIC1_SPDY3:
403       return "quic/1+spdy/3";
404     case NUM_OF_CONNECTION_INFOS:
405       break;
406   }
407   NOTREACHED();
408   return "";
409 }
410
411 }  // namespace net