| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/http/http_stream_factory_impl.h" | 5 #include "net/http/http_stream_factory_impl.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| 11 #include "base/strings/string_number_conversions.h" | |
| 12 #include "net/base/net_util.h" | 11 #include "net/base/net_util.h" |
| 13 #include "net/http/http_network_session.h" | 12 #include "net/http/http_network_session.h" |
| 14 #include "net/http/http_server_properties.h" | 13 #include "net/http/http_server_properties.h" |
| 15 #include "net/http/http_stream_factory_impl_job.h" | 14 #include "net/http/http_stream_factory_impl_job.h" |
| 16 #include "net/http/http_stream_factory_impl_request.h" | 15 #include "net/http/http_stream_factory_impl_request.h" |
| 17 #include "net/log/net_log.h" | 16 #include "net/log/net_log.h" |
| 18 #include "net/spdy/spdy_http_stream.h" | 17 #include "net/spdy/spdy_http_stream.h" |
| 19 #include "url/gurl.h" | 18 #include "url/gurl.h" |
| 20 | 19 |
| 21 namespace net { | 20 namespace net { |
| 22 | 21 |
| 23 namespace { | |
| 24 | |
| 25 GURL UpgradeUrlToHttps(const GURL& original_url, int port) { | |
| 26 GURL::Replacements replacements; | |
| 27 // new_port needs to be in scope here because GURL::Replacements references | |
| 28 // the memory contained by it directly. | |
| 29 const std::string new_port = base::IntToString(port); | |
| 30 replacements.SetSchemeStr("https"); | |
| 31 replacements.SetPortStr(new_port); | |
| 32 return original_url.ReplaceComponents(replacements); | |
| 33 } | |
| 34 | |
| 35 } // namespace | |
| 36 | |
| 37 HttpStreamFactoryImpl::HttpStreamFactoryImpl(HttpNetworkSession* session, | 22 HttpStreamFactoryImpl::HttpStreamFactoryImpl(HttpNetworkSession* session, |
| 38 bool for_websockets) | 23 bool for_websockets) |
| 39 : session_(session), | 24 : session_(session), |
| 40 for_websockets_(for_websockets) {} | 25 for_websockets_(for_websockets) {} |
| 41 | 26 |
| 42 HttpStreamFactoryImpl::~HttpStreamFactoryImpl() { | 27 HttpStreamFactoryImpl::~HttpStreamFactoryImpl() { |
| 43 DCHECK(request_map_.empty()); | 28 DCHECK(request_map_.empty()); |
| 44 DCHECK(spdy_session_request_map_.empty()); | 29 DCHECK(spdy_session_request_map_.empty()); |
| 45 | 30 |
| 46 std::set<const Job*> tmp_job_set; | 31 std::set<const Job*> tmp_job_set; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 const SSLConfig& proxy_ssl_config, | 82 const SSLConfig& proxy_ssl_config, |
| 98 HttpStreamRequest::Delegate* delegate, | 83 HttpStreamRequest::Delegate* delegate, |
| 99 WebSocketHandshakeStreamBase::CreateHelper* | 84 WebSocketHandshakeStreamBase::CreateHelper* |
| 100 websocket_handshake_stream_create_helper, | 85 websocket_handshake_stream_create_helper, |
| 101 const BoundNetLog& net_log) { | 86 const BoundNetLog& net_log) { |
| 102 Request* request = new Request(request_info.url, | 87 Request* request = new Request(request_info.url, |
| 103 this, | 88 this, |
| 104 delegate, | 89 delegate, |
| 105 websocket_handshake_stream_create_helper, | 90 websocket_handshake_stream_create_helper, |
| 106 net_log); | 91 net_log); |
| 92 Job* job = new Job(this, session_, request_info, priority, server_ssl_config, |
| 93 proxy_ssl_config, net_log.net_log()); |
| 94 request->AttachJob(job); |
| 107 | 95 |
| 108 // TODO(bnc): Get rid of |alternate_url|. | |
| 109 GURL alternate_url; | |
| 110 AlternativeService alternative_service = | 96 AlternativeService alternative_service = |
| 111 GetAlternativeServiceRequestFor(request_info.url, &alternate_url); | 97 GetAlternativeServiceFor(request_info.url); |
| 112 Job* alternate_job = NULL; | |
| 113 if (alternative_service.protocol != UNINITIALIZED_ALTERNATE_PROTOCOL) { | 98 if (alternative_service.protocol != UNINITIALIZED_ALTERNATE_PROTOCOL) { |
| 114 // Never share connection with other jobs for FTP requests. | 99 // Never share connection with other jobs for FTP requests. |
| 115 DCHECK(!request_info.url.SchemeIs("ftp")); | 100 DCHECK(!request_info.url.SchemeIs("ftp")); |
| 116 | 101 |
| 117 HttpRequestInfo alternate_request_info = request_info; | 102 Job* alternate_job = |
| 118 alternate_request_info.url = alternate_url; | 103 new Job(this, session_, request_info, priority, server_ssl_config, |
| 119 alternate_job = | 104 proxy_ssl_config, net_log.net_log()); |
| 120 new Job(this, session_, alternate_request_info, priority, | |
| 121 server_ssl_config, proxy_ssl_config, net_log.net_log()); | |
| 122 request->AttachJob(alternate_job); | 105 request->AttachJob(alternate_job); |
| 123 alternate_job->MarkAsAlternate(request_info.url, alternative_service); | 106 alternate_job->MarkAsAlternate(alternative_service); |
| 124 } | |
| 125 | 107 |
| 126 Job* job = new Job(this, session_, request_info, priority, | |
| 127 server_ssl_config, proxy_ssl_config, net_log.net_log()); | |
| 128 request->AttachJob(job); | |
| 129 if (alternate_job) { | |
| 130 // Never share connection with other jobs for FTP requests. | 108 // Never share connection with other jobs for FTP requests. |
| 131 DCHECK(!request_info.url.SchemeIs("ftp")); | 109 DCHECK(!request_info.url.SchemeIs("ftp")); |
| 132 | 110 |
| 133 job->WaitFor(alternate_job); | 111 job->WaitFor(alternate_job); |
| 134 // Make sure to wait until we call WaitFor(), before starting | 112 // Make sure to wait until we call WaitFor(), before starting |
| 135 // |alternate_job|, otherwise |alternate_job| will not notify |job| | 113 // |alternate_job|, otherwise |alternate_job| will not notify |job| |
| 136 // appropriately. | 114 // appropriately. |
| 137 alternate_job->Start(request); | 115 alternate_job->Start(request); |
| 138 } | 116 } |
| 117 |
| 139 // Even if |alternate_job| has already finished, it won't have notified the | 118 // Even if |alternate_job| has already finished, it won't have notified the |
| 140 // request yet, since we defer that to the next iteration of the MessageLoop, | 119 // request yet, since we defer that to the next iteration of the MessageLoop, |
| 141 // so starting |job| is always safe. | 120 // so starting |job| is always safe. |
| 142 job->Start(request); | 121 job->Start(request); |
| 143 return request; | 122 return request; |
| 144 } | 123 } |
| 145 | 124 |
| 146 void HttpStreamFactoryImpl::PreconnectStreams( | 125 void HttpStreamFactoryImpl::PreconnectStreams( |
| 147 int num_streams, | 126 int num_streams, |
| 148 const HttpRequestInfo& request_info, | 127 const HttpRequestInfo& request_info, |
| 149 RequestPriority priority, | 128 RequestPriority priority, |
| 150 const SSLConfig& server_ssl_config, | 129 const SSLConfig& server_ssl_config, |
| 151 const SSLConfig& proxy_ssl_config) { | 130 const SSLConfig& proxy_ssl_config) { |
| 152 DCHECK(!for_websockets_); | 131 DCHECK(!for_websockets_); |
| 153 GURL alternate_url; | |
| 154 AlternativeService alternative_service = | 132 AlternativeService alternative_service = |
| 155 GetAlternativeServiceRequestFor(request_info.url, &alternate_url); | 133 GetAlternativeServiceFor(request_info.url); |
| 156 Job* job = NULL; | 134 Job* job = new Job(this, session_, request_info, priority, server_ssl_config, |
| 135 proxy_ssl_config, session_->net_log()); |
| 157 if (alternative_service.protocol != UNINITIALIZED_ALTERNATE_PROTOCOL) { | 136 if (alternative_service.protocol != UNINITIALIZED_ALTERNATE_PROTOCOL) { |
| 158 HttpRequestInfo alternate_request_info = request_info; | 137 job->MarkAsAlternate(alternative_service); |
| 159 alternate_request_info.url = alternate_url; | |
| 160 job = new Job(this, session_, alternate_request_info, priority, | |
| 161 server_ssl_config, proxy_ssl_config, session_->net_log()); | |
| 162 job->MarkAsAlternate(request_info.url, alternative_service); | |
| 163 } else { | |
| 164 job = new Job(this, session_, request_info, priority, | |
| 165 server_ssl_config, proxy_ssl_config, session_->net_log()); | |
| 166 } | 138 } |
| 167 preconnect_job_set_.insert(job); | 139 preconnect_job_set_.insert(job); |
| 168 job->Preconnect(num_streams); | 140 job->Preconnect(num_streams); |
| 169 } | 141 } |
| 170 | 142 |
| 171 const HostMappingRules* HttpStreamFactoryImpl::GetHostMappingRules() const { | 143 const HostMappingRules* HttpStreamFactoryImpl::GetHostMappingRules() const { |
| 172 return session_->params().host_mapping_rules; | 144 return session_->params().host_mapping_rules; |
| 173 } | 145 } |
| 174 | 146 |
| 175 AlternativeService HttpStreamFactoryImpl::GetAlternativeServiceRequestFor( | 147 AlternativeService HttpStreamFactoryImpl::GetAlternativeServiceFor( |
| 176 const GURL& original_url, | 148 const GURL& original_url) { |
| 177 GURL* alternate_url) { | |
| 178 const AlternativeService kNoAlternativeService; | 149 const AlternativeService kNoAlternativeService; |
| 179 | 150 |
| 180 if (!session_->params().use_alternate_protocols) | 151 if (!session_->params().use_alternate_protocols) |
| 181 return kNoAlternativeService; | 152 return kNoAlternativeService; |
| 182 | 153 |
| 183 if (original_url.SchemeIs("ftp")) | 154 if (original_url.SchemeIs("ftp")) |
| 184 return kNoAlternativeService; | 155 return kNoAlternativeService; |
| 185 | 156 |
| 186 HostPortPair origin = HostPortPair::FromURL(original_url); | 157 HostPortPair origin = HostPortPair::FromURL(original_url); |
| 187 HttpServerProperties& http_server_properties = | 158 HttpServerProperties& http_server_properties = |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 219 | 190 |
| 220 origin.set_port(alternative_service.port); | 191 origin.set_port(alternative_service.port); |
| 221 if (alternative_service.protocol >= NPN_SPDY_MINIMUM_VERSION && | 192 if (alternative_service.protocol >= NPN_SPDY_MINIMUM_VERSION && |
| 222 alternative_service.protocol <= NPN_SPDY_MAXIMUM_VERSION) { | 193 alternative_service.protocol <= NPN_SPDY_MAXIMUM_VERSION) { |
| 223 if (!HttpStreamFactory::spdy_enabled()) | 194 if (!HttpStreamFactory::spdy_enabled()) |
| 224 return kNoAlternativeService; | 195 return kNoAlternativeService; |
| 225 | 196 |
| 226 if (session_->HasSpdyExclusion(origin)) | 197 if (session_->HasSpdyExclusion(origin)) |
| 227 return kNoAlternativeService; | 198 return kNoAlternativeService; |
| 228 | 199 |
| 229 *alternate_url = UpgradeUrlToHttps(original_url, alternative_service.port); | 200 return alternative_service; |
| 230 } else { | 201 } |
| 231 DCHECK_EQ(QUIC, alternative_service.protocol); | |
| 232 if (!session_->params().enable_quic) | |
| 233 return kNoAlternativeService; | |
| 234 | 202 |
| 235 if (session_->quic_stream_factory()->IsQuicDisabled(origin.port())) | 203 DCHECK_EQ(QUIC, alternative_service.protocol); |
| 236 return kNoAlternativeService; | 204 if (!session_->params().enable_quic) |
| 205 return kNoAlternativeService; |
| 237 | 206 |
| 238 // TODO(rch): Figure out how to make QUIC iteract with PAC | 207 if (session_->quic_stream_factory()->IsQuicDisabled(origin.port())) |
| 239 // scripts. By not re-writing the URL, we will query the PAC script | 208 return kNoAlternativeService; |
| 240 // for the proxy to use to reach the original URL via TCP. But | 209 |
| 241 // the alternate request will be going via UDP to a different port. | |
| 242 *alternate_url = original_url; | |
| 243 } | |
| 244 return alternative_service; | 210 return alternative_service; |
| 245 } | 211 } |
| 246 | 212 |
| 247 void HttpStreamFactoryImpl::OrphanJob(Job* job, const Request* request) { | 213 void HttpStreamFactoryImpl::OrphanJob(Job* job, const Request* request) { |
| 248 DCHECK(ContainsKey(request_map_, job)); | 214 DCHECK(ContainsKey(request_map_, job)); |
| 249 DCHECK_EQ(request_map_[job], request); | 215 DCHECK_EQ(request_map_[job], request); |
| 250 DCHECK(!ContainsKey(orphaned_job_set_, job)); | 216 DCHECK(!ContainsKey(orphaned_job_set_, job)); |
| 251 | 217 |
| 252 request_map_.erase(job); | 218 request_map_.erase(job); |
| 253 | 219 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 delete job; | 269 delete job; |
| 304 } | 270 } |
| 305 | 271 |
| 306 void HttpStreamFactoryImpl::OnPreconnectsComplete(const Job* job) { | 272 void HttpStreamFactoryImpl::OnPreconnectsComplete(const Job* job) { |
| 307 preconnect_job_set_.erase(job); | 273 preconnect_job_set_.erase(job); |
| 308 delete job; | 274 delete job; |
| 309 OnPreconnectsCompleteInternal(); | 275 OnPreconnectsCompleteInternal(); |
| 310 } | 276 } |
| 311 | 277 |
| 312 } // namespace net | 278 } // namespace net |
| OLD | NEW |