- add sources.
[platform/framework/web/crosswalk.git] / src / net / http / http_stream_factory.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_stream_factory.h"
6
7 #include "base/logging.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/string_split.h"
10 #include "net/base/host_mapping_rules.h"
11 #include "net/base/host_port_pair.h"
12 #include "url/gurl.h"
13
14 namespace net {
15
16 // WARNING: If you modify or add any static flags, you must keep them in sync
17 // with |ResetStaticSettingsToInit|. This is critical for unit test isolation.
18
19 // static
20 std::vector<std::string>* HttpStreamFactory::next_protos_ = NULL;
21 // static
22 bool HttpStreamFactory::enabled_protocols_[NUM_VALID_ALTERNATE_PROTOCOLS];
23 // static
24 bool HttpStreamFactory::spdy_enabled_ = true;
25 // static
26 bool HttpStreamFactory::use_alternate_protocols_ = false;
27 // static
28 bool HttpStreamFactory::force_spdy_over_ssl_ = true;
29 // static
30 bool HttpStreamFactory::force_spdy_always_ = false;
31 // static
32 std::list<HostPortPair>* HttpStreamFactory::forced_spdy_exclusions_ = NULL;
33
34 HttpStreamFactory::~HttpStreamFactory() {}
35
36 // static
37 bool HttpStreamFactory::IsProtocolEnabled(AlternateProtocol protocol) {
38   DCHECK(IsAlternateProtocolValid(protocol));
39   return enabled_protocols_[
40       protocol - ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION];
41 }
42
43 // static
44 void HttpStreamFactory::SetProtocolEnabled(AlternateProtocol protocol) {
45   DCHECK(IsAlternateProtocolValid(protocol));
46   enabled_protocols_[
47       protocol - ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION] = true;
48 }
49
50 // static
51 void HttpStreamFactory::ResetEnabledProtocols() {
52   for (int i = ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION;
53        i <= ALTERNATE_PROTOCOL_MAXIMUM_VALID_VERSION; ++i) {
54     enabled_protocols_[i - ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION] = false;
55   }
56 }
57
58 // static
59 void HttpStreamFactory::ResetStaticSettingsToInit() {
60   // WARNING: These must match the initializers above.
61   delete next_protos_;
62   delete forced_spdy_exclusions_;
63   next_protos_ = NULL;
64   spdy_enabled_ = true;
65   use_alternate_protocols_ = false;
66   force_spdy_over_ssl_ = true;
67   force_spdy_always_ = false;
68   forced_spdy_exclusions_ = NULL;
69   ResetEnabledProtocols();
70 }
71
72 void HttpStreamFactory::ProcessAlternateProtocol(
73     const base::WeakPtr<HttpServerProperties>& http_server_properties,
74     const std::string& alternate_protocol_str,
75     const HostPortPair& http_host_port_pair) {
76   std::vector<std::string> port_protocol_vector;
77   base::SplitString(alternate_protocol_str, ':', &port_protocol_vector);
78   if (port_protocol_vector.size() != 2) {
79     DLOG(WARNING) << kAlternateProtocolHeader
80                   << " header has too many tokens: "
81                   << alternate_protocol_str;
82     return;
83   }
84
85   int port;
86   if (!base::StringToInt(port_protocol_vector[0], &port) ||
87       port <= 0 || port >= 1 << 16) {
88     DLOG(WARNING) << kAlternateProtocolHeader
89                   << " header has unrecognizable port: "
90                   << port_protocol_vector[0];
91     return;
92   }
93
94   AlternateProtocol protocol =
95       AlternateProtocolFromString(port_protocol_vector[1]);
96   if (IsAlternateProtocolValid(protocol) && !IsProtocolEnabled(protocol)) {
97     protocol = ALTERNATE_PROTOCOL_BROKEN;
98   }
99
100   if (protocol == ALTERNATE_PROTOCOL_BROKEN) {
101     DLOG(WARNING) << kAlternateProtocolHeader
102                   << " header has unrecognized protocol: "
103                   << port_protocol_vector[1];
104     return;
105   }
106
107   HostPortPair host_port(http_host_port_pair);
108   const HostMappingRules* mapping_rules = GetHostMappingRules();
109   if (mapping_rules)
110     mapping_rules->RewriteHost(&host_port);
111
112   if (http_server_properties->HasAlternateProtocol(host_port)) {
113     const PortAlternateProtocolPair existing_alternate =
114         http_server_properties->GetAlternateProtocol(host_port);
115     // If we think the alternate protocol is broken, don't change it.
116     if (existing_alternate.protocol == ALTERNATE_PROTOCOL_BROKEN)
117       return;
118   }
119
120   http_server_properties->SetAlternateProtocol(host_port, port, protocol);
121 }
122
123 GURL HttpStreamFactory::ApplyHostMappingRules(const GURL& url,
124                                               HostPortPair* endpoint) {
125   const HostMappingRules* mapping_rules = GetHostMappingRules();
126   if (mapping_rules && mapping_rules->RewriteHost(endpoint)) {
127     url_canon::Replacements<char> replacements;
128     const std::string port_str = base::IntToString(endpoint->port());
129     replacements.SetPort(port_str.c_str(),
130                          url_parse::Component(0, port_str.size()));
131     replacements.SetHost(endpoint->host().c_str(),
132                          url_parse::Component(0, endpoint->host().size()));
133     return url.ReplaceComponents(replacements);
134   }
135   return url;
136 }
137
138 // static
139 void HttpStreamFactory::add_forced_spdy_exclusion(const std::string& value) {
140   HostPortPair pair = HostPortPair::FromURL(GURL(value));
141   if (!forced_spdy_exclusions_)
142     forced_spdy_exclusions_ = new std::list<HostPortPair>();
143   forced_spdy_exclusions_->push_back(pair);
144 }
145
146 // static
147 bool HttpStreamFactory::HasSpdyExclusion(const HostPortPair& endpoint) {
148   std::list<HostPortPair>* exclusions = forced_spdy_exclusions_;
149   if (!exclusions)
150     return false;
151
152   std::list<HostPortPair>::const_iterator it;
153   for (it = exclusions->begin(); it != exclusions->end(); ++it)
154     if (it->Equals(endpoint))
155       return true;
156   return false;
157 }
158
159 // static
160 void HttpStreamFactory::EnableNpnHttpOnly() {
161   // Avoid alternate protocol in this case. Otherwise, browser will try SSL
162   // and then fallback to http. This introduces extra load.
163   set_use_alternate_protocols(false);
164   std::vector<NextProto> next_protos;
165   next_protos.push_back(kProtoHTTP11);
166   SetNextProtos(next_protos);
167 }
168
169 // static
170 void HttpStreamFactory::EnableNpnSpdy3() {
171   set_use_alternate_protocols(true);
172   std::vector<NextProto> next_protos;
173   next_protos.push_back(kProtoHTTP11);
174   next_protos.push_back(kProtoQUIC1SPDY3);
175   next_protos.push_back(kProtoSPDY3);
176   SetNextProtos(next_protos);
177 }
178
179 // static
180 void HttpStreamFactory::EnableNpnSpdy31() {
181   set_use_alternate_protocols(true);
182   std::vector<NextProto> next_protos;
183   next_protos.push_back(kProtoHTTP11);
184   next_protos.push_back(kProtoQUIC1SPDY3);
185   next_protos.push_back(kProtoSPDY3);
186   next_protos.push_back(kProtoSPDY31);
187   SetNextProtos(next_protos);
188 }
189
190 // static
191 void HttpStreamFactory::EnableNpnSpdy31WithSpdy2() {
192   set_use_alternate_protocols(true);
193   std::vector<NextProto> next_protos;
194   next_protos.push_back(kProtoHTTP11);
195   next_protos.push_back(kProtoQUIC1SPDY3);
196   next_protos.push_back(kProtoDeprecatedSPDY2);
197   next_protos.push_back(kProtoSPDY3);
198   next_protos.push_back(kProtoSPDY31);
199   SetNextProtos(next_protos);
200 }
201
202 // static
203 void HttpStreamFactory::EnableNpnSpdy4a2() {
204   set_use_alternate_protocols(true);
205   std::vector<NextProto> next_protos;
206   next_protos.push_back(kProtoHTTP11);
207   next_protos.push_back(kProtoQUIC1SPDY3);
208   next_protos.push_back(kProtoSPDY3);
209   next_protos.push_back(kProtoSPDY31);
210   next_protos.push_back(kProtoSPDY4a2);
211   SetNextProtos(next_protos);
212 }
213
214 // static
215 void HttpStreamFactory::EnableNpnHttp2Draft04() {
216   set_use_alternate_protocols(true);
217   std::vector<NextProto> next_protos;
218   next_protos.push_back(kProtoHTTP11);
219   next_protos.push_back(kProtoQUIC1SPDY3);
220   next_protos.push_back(kProtoSPDY3);
221   next_protos.push_back(kProtoSPDY31);
222   next_protos.push_back(kProtoSPDY4a2);
223   next_protos.push_back(kProtoHTTP2Draft04);
224   SetNextProtos(next_protos);
225 }
226
227 // static
228 void HttpStreamFactory::SetNextProtos(const std::vector<NextProto>& value) {
229   if (!next_protos_)
230     next_protos_ = new std::vector<std::string>;
231
232   next_protos_->clear();
233
234   ResetEnabledProtocols();
235
236   // TODO(rtenneti): bug 116575 - consider combining the NextProto and
237   // AlternateProtocol.
238   for (uint32 i = 0; i < value.size(); ++i) {
239     NextProto proto = value[i];
240     // Add the protocol to the TLS next protocol list, except for QUIC
241     // since it uses UDP.
242     if (proto != kProtoQUIC1SPDY3) {
243       next_protos_->push_back(SSLClientSocket::NextProtoToString(proto));
244     }
245
246     // Enable the corresponding alternate protocol, except for HTTP
247     // which has not corresponding alternative.
248     if (proto != kProtoHTTP11) {
249       AlternateProtocol alternate = AlternateProtocolFromNextProto(proto);
250       if (!IsAlternateProtocolValid(alternate)) {
251         NOTREACHED() << "Invalid next proto: " << proto;
252         continue;
253       }
254       SetProtocolEnabled(alternate);
255     }
256   }
257 }
258
259 HttpStreamFactory::HttpStreamFactory() {}
260
261 }  // namespace net