Chromium Code Reviews| 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" |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 113 RequestPriority priority, | 113 RequestPriority priority, |
| 114 const SSLConfig& server_ssl_config, | 114 const SSLConfig& server_ssl_config, |
| 115 const SSLConfig& proxy_ssl_config, | 115 const SSLConfig& proxy_ssl_config, |
| 116 HttpStreamRequest::Delegate* delegate, | 116 HttpStreamRequest::Delegate* delegate, |
| 117 WebSocketHandshakeStreamBase::CreateHelper* | 117 WebSocketHandshakeStreamBase::CreateHelper* |
| 118 websocket_handshake_stream_create_helper, | 118 websocket_handshake_stream_create_helper, |
| 119 const BoundNetLog& net_log) { | 119 const BoundNetLog& net_log) { |
| 120 Request* request = new Request(request_info.url, this, delegate, | 120 Request* request = new Request(request_info.url, this, delegate, |
| 121 websocket_handshake_stream_create_helper, | 121 websocket_handshake_stream_create_helper, |
| 122 net_log, Request::HTTP_STREAM); | 122 net_log, Request::HTTP_STREAM); |
| 123 HostPortPair server = HostPortPair::FromURL(request_info.url); | |
| 124 GURL origin_url = ApplyHostMappingRules(request_info.url, &server); | |
| 125 | |
| 123 Job* job = new Job(this, session_, request_info, priority, server_ssl_config, | 126 Job* job = new Job(this, session_, request_info, priority, server_ssl_config, |
| 124 proxy_ssl_config, net_log.net_log()); | 127 proxy_ssl_config, server, origin_url, net_log.net_log()); |
| 125 request->AttachJob(job); | 128 request->AttachJob(job); |
| 126 | 129 |
| 127 const AlternativeServiceVector alternative_service_vector = | 130 const AlternativeService alternative_service = |
| 128 GetAlternativeServicesFor(request_info.url, delegate); | 131 GetAlternativeServiceFor(request_info, delegate); |
| 129 | 132 |
| 130 if (!alternative_service_vector.empty()) { | 133 if (alternative_service.protocol != UNINITIALIZED_ALTERNATE_PROTOCOL) { |
|
mef
2016/01/08 16:03:10
Should this code be also applied to HttpStreamFact
| |
| 131 // TODO(bnc): Pass on multiple alternative services to Job. | |
| 132 const AlternativeService& alternative_service = | |
| 133 alternative_service_vector[0]; | |
| 134 // Never share connection with other jobs for FTP requests. | 134 // Never share connection with other jobs for FTP requests. |
| 135 DVLOG(1) << "Selected alternative service (host: " | |
| 136 << alternative_service.host_port_pair().host() | |
| 137 << " port: " << alternative_service.host_port_pair().port() << ")"; | |
| 138 | |
| 135 DCHECK(!request_info.url.SchemeIs("ftp")); | 139 DCHECK(!request_info.url.SchemeIs("ftp")); |
| 140 HostPortPair server = alternative_service.host_port_pair(); | |
| 141 GURL origin_url = ApplyHostMappingRules(request_info.url, &server); | |
| 136 | 142 |
| 137 Job* alternative_job = | 143 Job* alternative_job = |
| 138 new Job(this, session_, request_info, priority, server_ssl_config, | 144 new Job(this, session_, request_info, priority, server_ssl_config, |
| 139 proxy_ssl_config, alternative_service, net_log.net_log()); | 145 proxy_ssl_config, server, origin_url, alternative_service, |
| 146 net_log.net_log()); | |
| 140 request->AttachJob(alternative_job); | 147 request->AttachJob(alternative_job); |
| 141 | 148 |
| 142 job->WaitFor(alternative_job); | 149 job->WaitFor(alternative_job); |
| 143 // Make sure to wait until we call WaitFor(), before starting | 150 // Make sure to wait until we call WaitFor(), before starting |
| 144 // |alternative_job|, otherwise |alternative_job| will not notify |job| | 151 // |alternative_job|, otherwise |alternative_job| will not notify |job| |
| 145 // appropriately. | 152 // appropriately. |
| 146 alternative_job->Start(request); | 153 alternative_job->Start(request); |
| 147 } | 154 } |
| 148 | 155 |
| 149 // Even if |alternative_job| has already finished, it will not have notified | 156 // Even if |alternative_job| has already finished, it will not have notified |
| 150 // the request yet, since we defer that to the next iteration of the | 157 // the request yet, since we defer that to the next iteration of the |
| 151 // MessageLoop, so starting |job| is always safe. | 158 // MessageLoop, so starting |job| is always safe. |
| 152 job->Start(request); | 159 job->Start(request); |
| 153 return request; | 160 return request; |
| 154 } | 161 } |
| 155 | 162 |
| 156 void HttpStreamFactoryImpl::PreconnectStreams( | 163 void HttpStreamFactoryImpl::PreconnectStreams( |
| 157 int num_streams, | 164 int num_streams, |
| 158 const HttpRequestInfo& request_info, | 165 const HttpRequestInfo& request_info, |
| 159 const SSLConfig& server_ssl_config, | 166 const SSLConfig& server_ssl_config, |
| 160 const SSLConfig& proxy_ssl_config) { | 167 const SSLConfig& proxy_ssl_config) { |
| 161 DCHECK(!for_websockets_); | 168 DCHECK(!for_websockets_); |
| 162 AlternativeService alternative_service; | 169 AlternativeService alternative_service = |
| 163 AlternativeServiceVector alternative_service_vector = | 170 GetAlternativeServiceFor(request_info, nullptr); |
| 164 GetAlternativeServicesFor(request_info.url, nullptr); | 171 HostPortPair server; |
| 165 if (!alternative_service_vector.empty()) { | 172 if (alternative_service.protocol != UNINITIALIZED_ALTERNATE_PROTOCOL) { |
| 166 // TODO(bnc): Pass on multiple alternative services to Job. | 173 server = alternative_service.host_port_pair(); |
| 167 alternative_service = alternative_service_vector[0]; | |
| 168 if (session_->params().quic_disable_preconnect_if_0rtt && | 174 if (session_->params().quic_disable_preconnect_if_0rtt && |
| 169 alternative_service.protocol == QUIC && | 175 alternative_service.protocol == QUIC && |
| 170 session_->quic_stream_factory()->ZeroRTTEnabledFor(QuicServerId( | 176 session_->quic_stream_factory()->ZeroRTTEnabledFor(QuicServerId( |
| 171 alternative_service.host_port_pair(), request_info.privacy_mode))) { | 177 alternative_service.host_port_pair(), request_info.privacy_mode))) { |
| 172 return; | 178 return; |
| 173 } | 179 } |
| 180 } else { | |
| 181 server = HostPortPair::FromURL(request_info.url); | |
| 174 } | 182 } |
| 175 | 183 GURL origin_url = ApplyHostMappingRules(request_info.url, &server); |
| 176 // Due to how the socket pools handle priorities and idle sockets, only IDLE | 184 // Due to how the socket pools handle priorities and idle sockets, only IDLE |
| 177 // priority currently makes sense for preconnects. The priority for | 185 // priority currently makes sense for preconnects. The priority for |
| 178 // preconnects is currently ignored (see RequestSocketsForPool()), but could | 186 // preconnects is currently ignored (see RequestSocketsForPool()), but could |
| 179 // be used at some point for proxy resolution or something. | 187 // be used at some point for proxy resolution or something. |
| 180 Job* job = | 188 Job* job = new Job(this, session_, request_info, IDLE, server_ssl_config, |
| 181 new Job(this, session_, request_info, IDLE, server_ssl_config, | 189 proxy_ssl_config, server, origin_url, alternative_service, |
| 182 proxy_ssl_config, alternative_service, session_->net_log()); | 190 session_->net_log()); |
| 183 preconnect_job_set_.insert(job); | 191 preconnect_job_set_.insert(job); |
| 184 job->Preconnect(num_streams); | 192 job->Preconnect(num_streams); |
| 185 } | 193 } |
| 186 | 194 |
| 187 const HostMappingRules* HttpStreamFactoryImpl::GetHostMappingRules() const { | 195 const HostMappingRules* HttpStreamFactoryImpl::GetHostMappingRules() const { |
| 188 return session_->params().host_mapping_rules; | 196 return session_->params().host_mapping_rules; |
| 189 } | 197 } |
| 190 | 198 |
| 191 AlternativeServiceVector HttpStreamFactoryImpl::GetAlternativeServicesFor( | 199 AlternativeService HttpStreamFactoryImpl::GetAlternativeServiceFor( |
| 192 const GURL& original_url, | 200 const HttpRequestInfo& request_info, |
| 193 HttpStreamRequest::Delegate* delegate) { | 201 HttpStreamRequest::Delegate* delegate) { |
| 202 GURL original_url = request_info.url; | |
| 203 | |
| 194 if (original_url.SchemeIs("ftp")) | 204 if (original_url.SchemeIs("ftp")) |
| 195 return AlternativeServiceVector(); | 205 return AlternativeService(); |
| 196 | 206 |
| 197 HostPortPair origin = HostPortPair::FromURL(original_url); | 207 HostPortPair origin = HostPortPair::FromURL(original_url); |
| 198 HttpServerProperties& http_server_properties = | 208 HttpServerProperties& http_server_properties = |
| 199 *session_->http_server_properties(); | 209 *session_->http_server_properties(); |
| 200 const AlternativeServiceVector alternative_service_vector = | 210 const AlternativeServiceVector alternative_service_vector = |
| 201 http_server_properties.GetAlternativeServices(origin); | 211 http_server_properties.GetAlternativeServices(origin); |
| 202 if (alternative_service_vector.empty()) | 212 if (alternative_service_vector.empty()) |
| 203 return AlternativeServiceVector(); | 213 return AlternativeService(); |
| 204 | 214 |
| 205 bool quic_advertised = false; | 215 bool quic_advertised = false; |
| 206 bool quic_all_broken = true; | 216 bool quic_all_broken = true; |
| 207 | 217 |
| 208 const bool enable_different_host = | 218 const bool enable_different_host = |
| 209 session_->params().use_alternative_services; | 219 session_->params().use_alternative_services; |
| 210 | 220 |
| 211 AlternativeServiceVector enabled_alternative_service_vector; | 221 // First Alt-Svc that is not marked as broken. |
| 222 AlternativeService first_alternative_service; | |
| 223 | |
| 212 for (const AlternativeService& alternative_service : | 224 for (const AlternativeService& alternative_service : |
| 213 alternative_service_vector) { | 225 alternative_service_vector) { |
| 214 DCHECK(IsAlternateProtocolValid(alternative_service.protocol)); | 226 DCHECK(IsAlternateProtocolValid(alternative_service.protocol)); |
| 215 if (!quic_advertised && alternative_service.protocol == QUIC) | 227 if (!quic_advertised && alternative_service.protocol == QUIC) |
| 216 quic_advertised = true; | 228 quic_advertised = true; |
| 217 if (http_server_properties.IsAlternativeServiceBroken( | 229 if (http_server_properties.IsAlternativeServiceBroken( |
| 218 alternative_service)) { | 230 alternative_service)) { |
| 219 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_BROKEN); | 231 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_BROKEN); |
| 220 continue; | 232 continue; |
| 221 } | 233 } |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 237 | 249 |
| 238 origin.set_port(alternative_service.port); | 250 origin.set_port(alternative_service.port); |
| 239 if (alternative_service.protocol >= NPN_SPDY_MINIMUM_VERSION && | 251 if (alternative_service.protocol >= NPN_SPDY_MINIMUM_VERSION && |
| 240 alternative_service.protocol <= NPN_SPDY_MAXIMUM_VERSION) { | 252 alternative_service.protocol <= NPN_SPDY_MAXIMUM_VERSION) { |
| 241 if (!HttpStreamFactory::spdy_enabled()) | 253 if (!HttpStreamFactory::spdy_enabled()) |
| 242 continue; | 254 continue; |
| 243 | 255 |
| 244 if (session_->HasSpdyExclusion(origin)) | 256 if (session_->HasSpdyExclusion(origin)) |
| 245 continue; | 257 continue; |
| 246 | 258 |
| 247 enabled_alternative_service_vector.push_back(alternative_service); | 259 // Cache this entry if we don't have a non-broken Alt-Svc yet. |
| 260 if (first_alternative_service.protocol == | |
| 261 UNINITIALIZED_ALTERNATE_PROTOCOL) | |
| 262 first_alternative_service = alternative_service; | |
| 248 continue; | 263 continue; |
| 249 } | 264 } |
| 250 | 265 |
| 251 DCHECK_EQ(QUIC, alternative_service.protocol); | 266 DCHECK_EQ(QUIC, alternative_service.protocol); |
| 252 quic_all_broken = false; | 267 quic_all_broken = false; |
| 253 if (!session_->params().enable_quic) | 268 if (!session_->params().enable_quic) |
| 254 continue; | 269 continue; |
| 255 | 270 |
| 256 if (session_->quic_stream_factory()->IsQuicDisabled(origin.port())) | 271 if (session_->quic_stream_factory()->IsQuicDisabled(origin.port())) |
| 257 continue; | 272 continue; |
| 258 | 273 |
| 259 if (!original_url.SchemeIs("https")) | 274 if (!original_url.SchemeIs("https")) |
| 260 continue; | 275 continue; |
| 261 | 276 |
| 262 enabled_alternative_service_vector.push_back(alternative_service); | 277 // Check whether there's an existing session to use for this QUIC Alt-Svc. |
| 278 HostPortPair destination = alternative_service.host_port_pair(); | |
| 279 std::string origin_host = | |
| 280 ApplyHostMappingRules(request_info.url, &destination).host(); | |
| 281 QuicServerId server_id(destination, request_info.privacy_mode); | |
| 282 if (session_->quic_stream_factory()->CanUseExistingSession( | |
| 283 server_id, request_info.privacy_mode, origin_host)) | |
| 284 return alternative_service; | |
| 285 | |
| 286 // Cache this entry if we don't have a non-broken Alt-Svc yet. | |
| 287 if (first_alternative_service.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL) | |
| 288 first_alternative_service = alternative_service; | |
| 263 } | 289 } |
| 290 | |
| 291 // Ask delegate to mark QUIC as broken for the origin. | |
| 264 if (quic_advertised && quic_all_broken && delegate != nullptr) | 292 if (quic_advertised && quic_all_broken && delegate != nullptr) |
| 265 delegate->OnQuicBroken(); | 293 delegate->OnQuicBroken(); |
| 266 return enabled_alternative_service_vector; | 294 |
| 295 return first_alternative_service; | |
| 267 } | 296 } |
| 268 | 297 |
| 269 void HttpStreamFactoryImpl::OrphanJob(Job* job, const Request* request) { | 298 void HttpStreamFactoryImpl::OrphanJob(Job* job, const Request* request) { |
| 270 DCHECK(ContainsKey(request_map_, job)); | 299 DCHECK(ContainsKey(request_map_, job)); |
| 271 DCHECK_EQ(request_map_[job], request); | 300 DCHECK_EQ(request_map_[job], request); |
| 272 DCHECK(!ContainsKey(orphaned_job_set_, job)); | 301 DCHECK(!ContainsKey(orphaned_job_set_, job)); |
| 273 | 302 |
| 274 request_map_.erase(job); | 303 request_map_.erase(job); |
| 275 | 304 |
| 276 orphaned_job_set_.insert(job); | 305 orphaned_job_set_.insert(job); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 328 delete job; | 357 delete job; |
| 329 } | 358 } |
| 330 | 359 |
| 331 void HttpStreamFactoryImpl::OnPreconnectsComplete(const Job* job) { | 360 void HttpStreamFactoryImpl::OnPreconnectsComplete(const Job* job) { |
| 332 preconnect_job_set_.erase(job); | 361 preconnect_job_set_.erase(job); |
| 333 delete job; | 362 delete job; |
| 334 OnPreconnectsCompleteInternal(); | 363 OnPreconnectsCompleteInternal(); |
| 335 } | 364 } |
| 336 | 365 |
| 337 } // namespace net | 366 } // namespace net |
| OLD | NEW |