| 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_request.h" | 5 #include "net/http/http_stream_factory_impl_request.h" |
| 6 | 6 |
| 7 #include "base/callback.h" | 7 #include "base/callback.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
| 10 #include "net/http/http_stream_factory_impl_job.h" | 10 #include "net/http/http_stream_factory_impl_job.h" |
| 11 #include "net/spdy/spdy_http_stream.h" | 11 #include "net/spdy/spdy_http_stream.h" |
| 12 #include "net/spdy/spdy_session.h" | 12 #include "net/spdy/spdy_session.h" |
| 13 | 13 |
| 14 namespace net { | 14 namespace net { |
| 15 | 15 |
| 16 HttpStreamFactoryImpl::Request::Request(const GURL& url, | 16 HttpStreamFactoryImpl::Request::Request( |
| 17 HttpStreamFactoryImpl* factory, | 17 const GURL& url, |
| 18 HttpStreamRequest::Delegate* delegate, | 18 HttpStreamFactoryImpl* factory, |
| 19 const BoundNetLog& net_log) | 19 HttpStreamRequest::Delegate* delegate, |
| 20 WebSocketStreamBase::Factory* websocket_stream_factory, |
| 21 const BoundNetLog& net_log) |
| 20 : url_(url), | 22 : url_(url), |
| 21 factory_(factory), | 23 factory_(factory), |
| 24 websocket_stream_factory_(websocket_stream_factory), |
| 22 delegate_(delegate), | 25 delegate_(delegate), |
| 23 net_log_(net_log), | 26 net_log_(net_log), |
| 24 completed_(false), | 27 completed_(false), |
| 25 was_npn_negotiated_(false), | 28 was_npn_negotiated_(false), |
| 26 protocol_negotiated_(kProtoUnknown), | 29 protocol_negotiated_(kProtoUnknown), |
| 27 using_spdy_(false) { | 30 using_spdy_(false) { |
| 28 DCHECK(factory_); | 31 DCHECK(factory_); |
| 29 DCHECK(delegate_); | 32 DCHECK(delegate_); |
| 30 | 33 |
| 31 net_log_.BeginEvent(NetLog::TYPE_HTTP_STREAM_REQUEST); | 34 net_log_.BeginEvent(NetLog::TYPE_HTTP_STREAM_REQUEST); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 87 protocol_negotiated_ = protocol_negotiated; | 90 protocol_negotiated_ = protocol_negotiated; |
| 88 using_spdy_ = using_spdy; | 91 using_spdy_ = using_spdy; |
| 89 net_log_.AddEvent( | 92 net_log_.AddEvent( |
| 90 NetLog::TYPE_HTTP_STREAM_REQUEST_BOUND_TO_JOB, | 93 NetLog::TYPE_HTTP_STREAM_REQUEST_BOUND_TO_JOB, |
| 91 job_net_log.source().ToEventParametersCallback()); | 94 job_net_log.source().ToEventParametersCallback()); |
| 92 job_net_log.AddEvent( | 95 job_net_log.AddEvent( |
| 93 NetLog::TYPE_HTTP_STREAM_JOB_BOUND_TO_REQUEST, | 96 NetLog::TYPE_HTTP_STREAM_JOB_BOUND_TO_REQUEST, |
| 94 net_log_.source().ToEventParametersCallback()); | 97 net_log_.source().ToEventParametersCallback()); |
| 95 } | 98 } |
| 96 | 99 |
| 97 void HttpStreamFactoryImpl::Request::OnStreamReady( | 100 void HttpStreamFactoryImpl::Request::Orphan(Job* job) { |
| 98 Job* job, | |
| 99 const SSLConfig& used_ssl_config, | |
| 100 const ProxyInfo& used_proxy_info, | |
| 101 HttpStreamBase* stream) { | |
| 102 DCHECK(stream); | |
| 103 DCHECK(completed_); | |
| 104 | |
| 105 // |job| should only be NULL if we're being serviced by a late bound | 101 // |job| should only be NULL if we're being serviced by a late bound |
| 106 // SpdySession or HttpPipelinedConnection (one that was not created by a job | 102 // SpdySession or HttpPipelinedConnection (one that was not created by a job |
| 107 // in our |jobs_| set). | 103 // in our |jobs_| set). |
| 108 if (!job) { | 104 if (!job) { |
| 109 DCHECK(!bound_job_.get()); | 105 DCHECK(!bound_job_.get()); |
| 110 DCHECK(!jobs_.empty()); | 106 DCHECK(!jobs_.empty()); |
| 111 // NOTE(willchan): We do *NOT* call OrphanJobs() here. The reason is because | 107 // NOTE(willchan): We do *NOT* call OrphanJobs() here. The reason is because |
| 112 // we *WANT* to cancel the unnecessary Jobs from other requests if another | 108 // we *WANT* to cancel the unnecessary Jobs from other requests if another |
| 113 // Job completes first. | 109 // Job completes first. |
| 114 // TODO(mbelshe): Revisit this when we implement ip connection pooling of | 110 // TODO(mbelshe): Revisit this when we implement ip connection pooling of |
| 115 // SpdySessions. Do we want to orphan the jobs for a different hostname so | 111 // SpdySessions. Do we want to orphan the jobs for a different hostname so |
| 116 // they complete? Or do we want to prevent connecting a new SpdySession if | 112 // they complete? Or do we want to prevent connecting a new SpdySession if |
| 117 // we've already got one available for a different hostname where the ip | 113 // we've already got one available for a different hostname where the ip |
| 118 // address matches up? | 114 // address matches up? |
| 119 } else if (!bound_job_.get()) { | 115 } else if (!bound_job_.get()) { |
| 120 // We may have other jobs in |jobs_|. For example, if we start multiple jobs | 116 // We may have other jobs in |jobs_|. For example, if we start multiple jobs |
| 121 // for Alternate-Protocol. | 117 // for Alternate-Protocol. |
| 122 OrphanJobsExcept(job); | 118 OrphanJobsExcept(job); |
| 123 } else { | 119 } else { |
| 124 DCHECK(jobs_.empty()); | 120 DCHECK(jobs_.empty()); |
| 125 } | 121 } |
| 122 } |
| 123 |
| 124 void HttpStreamFactoryImpl::Request::OnStreamReady( |
| 125 Job* job, |
| 126 const SSLConfig& used_ssl_config, |
| 127 const ProxyInfo& used_proxy_info, |
| 128 HttpStreamBase* stream) { |
| 129 DCHECK(!factory_->for_websockets_); |
| 130 DCHECK(stream); |
| 131 DCHECK(completed_); |
| 132 |
| 133 Orphan(job); |
| 126 delegate_->OnStreamReady(used_ssl_config, used_proxy_info, stream); | 134 delegate_->OnStreamReady(used_ssl_config, used_proxy_info, stream); |
| 127 } | 135 } |
| 128 | 136 |
| 137 void HttpStreamFactoryImpl::Request::OnWebSocketStreamReady( |
| 138 Job* job, |
| 139 const SSLConfig& used_ssl_config, |
| 140 const ProxyInfo& used_proxy_info, |
| 141 WebSocketStreamBase* stream) { |
| 142 DCHECK(factory_->for_websockets_); |
| 143 DCHECK(stream); |
| 144 DCHECK(completed_); |
| 145 |
| 146 Orphan(job); |
| 147 delegate_->OnWebSocketStreamReady(used_ssl_config, used_proxy_info, stream); |
| 148 } |
| 149 |
| 129 void HttpStreamFactoryImpl::Request::OnStreamFailed( | 150 void HttpStreamFactoryImpl::Request::OnStreamFailed( |
| 130 Job* job, | 151 Job* job, |
| 131 int status, | 152 int status, |
| 132 const SSLConfig& used_ssl_config) { | 153 const SSLConfig& used_ssl_config) { |
| 133 DCHECK_NE(OK, status); | 154 DCHECK_NE(OK, status); |
| 134 // |job| should only be NULL if we're being canceled by a late bound | 155 // |job| should only be NULL if we're being canceled by a late bound |
| 135 // HttpPipelinedConnection (one that was not created by a job in our |jobs_| | 156 // HttpPipelinedConnection (one that was not created by a job in our |jobs_| |
| 136 // set). | 157 // set). |
| 137 if (!job) { | 158 if (!job) { |
| 138 DCHECK(!bound_job_.get()); | 159 DCHECK(!bound_job_.get()); |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 request_vector.erase(it); | 294 request_vector.erase(it); |
| 274 break; | 295 break; |
| 275 } | 296 } |
| 276 } | 297 } |
| 277 if (request_vector.empty()) | 298 if (request_vector.empty()) |
| 278 http_pipelining_request_map.erase(*http_pipelining_key_); | 299 http_pipelining_request_map.erase(*http_pipelining_key_); |
| 279 http_pipelining_key_.reset(); | 300 http_pipelining_key_.reset(); |
| 280 } | 301 } |
| 281 } | 302 } |
| 282 | 303 |
| 283 void HttpStreamFactoryImpl::Request::OnSpdySessionReady( | 304 void HttpStreamFactoryImpl::Request::OnNewSpdySessionReady( |
| 284 Job* job, | 305 Job* job, |
| 285 scoped_refptr<SpdySession> spdy_session, | 306 scoped_refptr<SpdySession> spdy_session, |
| 286 bool direct) { | 307 bool direct) { |
| 287 DCHECK(job); | 308 DCHECK(job); |
| 288 DCHECK(job->using_spdy()); | 309 DCHECK(job->using_spdy()); |
| 289 | 310 |
| 290 // The first case is the usual case. | 311 // The first case is the usual case. |
| 291 if (!bound_job_.get()) { | 312 if (!bound_job_.get()) { |
| 292 OrphanJobsExcept(job); | 313 OrphanJobsExcept(job); |
| 293 } else { // This is the case for HTTPS proxy tunneling. | 314 } else { // This is the case for HTTPS proxy tunneling. |
| 294 DCHECK_EQ(bound_job_.get(), job); | 315 DCHECK_EQ(bound_job_.get(), job); |
| 295 DCHECK(jobs_.empty()); | 316 DCHECK(jobs_.empty()); |
| 296 } | 317 } |
| 297 | 318 |
| 298 // Cache these values in case the job gets deleted. | 319 // Cache these values in case the job gets deleted. |
| 299 const SSLConfig used_ssl_config = job->server_ssl_config(); | 320 const SSLConfig used_ssl_config = job->server_ssl_config(); |
| 300 const ProxyInfo used_proxy_info = job->proxy_info(); | 321 const ProxyInfo used_proxy_info = job->proxy_info(); |
| 301 const bool was_npn_negotiated = job->was_npn_negotiated(); | 322 const bool was_npn_negotiated = job->was_npn_negotiated(); |
| 302 const NextProto protocol_negotiated = | 323 const NextProto protocol_negotiated = |
| 303 job->protocol_negotiated(); | 324 job->protocol_negotiated(); |
| 304 const bool using_spdy = job->using_spdy(); | 325 const bool using_spdy = job->using_spdy(); |
| 305 const BoundNetLog net_log = job->net_log(); | 326 const BoundNetLog net_log = job->net_log(); |
| 306 | 327 |
| 307 Complete(was_npn_negotiated, protocol_negotiated, using_spdy, net_log); | 328 Complete(was_npn_negotiated, protocol_negotiated, using_spdy, net_log); |
| 308 | 329 |
| 309 // Cache this so we can still use it if the request is deleted. | 330 // Cache this so we can still use it if the request is deleted. |
| 310 HttpStreamFactoryImpl* factory = factory_; | 331 HttpStreamFactoryImpl* factory = factory_; |
| 311 | 332 WebSocketStreamBase::Factory* websocket_stream_factory = |
| 312 bool use_relative_url = direct || url().SchemeIs("https"); | 333 websocket_stream_factory_; |
| 313 delegate_->OnStreamReady( | 334 if (factory->for_websockets_) { |
| 314 job->server_ssl_config(), | 335 DCHECK(websocket_stream_factory); |
| 315 job->proxy_info(), | 336 bool use_relative_url = direct || url().SchemeIs("wss"); |
| 316 new SpdyHttpStream(spdy_session, use_relative_url)); | 337 delegate_->OnWebSocketStreamReady( |
| 338 job->server_ssl_config(), |
| 339 job->proxy_info(), |
| 340 websocket_stream_factory->CreateSpdyStream( |
| 341 spdy_session, use_relative_url)); |
| 342 } else { |
| 343 bool use_relative_url = direct || url().SchemeIs("https"); |
| 344 delegate_->OnStreamReady( |
| 345 job->server_ssl_config(), |
| 346 job->proxy_info(), |
| 347 new SpdyHttpStream(spdy_session, use_relative_url)); |
| 348 } |
| 317 // |this| may be deleted after this point. | 349 // |this| may be deleted after this point. |
| 318 factory->OnSpdySessionReady( | 350 factory->OnNewSpdySessionReady( |
| 319 spdy_session, direct, used_ssl_config, used_proxy_info, | 351 spdy_session, direct, used_ssl_config, used_proxy_info, |
| 320 was_npn_negotiated, protocol_negotiated, using_spdy, net_log); | 352 was_npn_negotiated, protocol_negotiated, using_spdy, net_log); |
| 321 } | 353 } |
| 322 | 354 |
| 323 void HttpStreamFactoryImpl::Request::OrphanJobsExcept(Job* job) { | 355 void HttpStreamFactoryImpl::Request::OrphanJobsExcept(Job* job) { |
| 324 DCHECK(job); | 356 DCHECK(job); |
| 325 DCHECK(!bound_job_.get()); | 357 DCHECK(!bound_job_.get()); |
| 326 DCHECK(ContainsKey(jobs_, job)); | 358 DCHECK(ContainsKey(jobs_, job)); |
| 327 bound_job_.reset(job); | 359 bound_job_.reset(job); |
| 328 jobs_.erase(job); | 360 jobs_.erase(job); |
| 329 factory_->request_map_.erase(job); | 361 factory_->request_map_.erase(job); |
| 330 | 362 |
| 331 OrphanJobs(); | 363 OrphanJobs(); |
| 332 } | 364 } |
| 333 | 365 |
| 334 void HttpStreamFactoryImpl::Request::OrphanJobs() { | 366 void HttpStreamFactoryImpl::Request::OrphanJobs() { |
| 335 RemoveRequestFromSpdySessionRequestMap(); | 367 RemoveRequestFromSpdySessionRequestMap(); |
| 336 RemoveRequestFromHttpPipeliningRequestMap(); | 368 RemoveRequestFromHttpPipeliningRequestMap(); |
| 337 | 369 |
| 338 std::set<Job*> tmp; | 370 std::set<Job*> tmp; |
| 339 tmp.swap(jobs_); | 371 tmp.swap(jobs_); |
| 340 | 372 |
| 341 for (std::set<Job*>::iterator it = tmp.begin(); it != tmp.end(); ++it) | 373 for (std::set<Job*>::iterator it = tmp.begin(); it != tmp.end(); ++it) |
| 342 factory_->OrphanJob(*it, this); | 374 factory_->OrphanJob(*it, this); |
| 343 } | 375 } |
| 344 | 376 |
| 345 } // namespace net | 377 } // namespace net |
| OLD | NEW |