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" |
(...skipping 21 matching lines...) Expand all Loading... |
32 using_spdy_(false) { | 32 using_spdy_(false) { |
33 DCHECK(factory_); | 33 DCHECK(factory_); |
34 DCHECK(delegate_); | 34 DCHECK(delegate_); |
35 | 35 |
36 net_log_.BeginEvent(NetLog::TYPE_HTTP_STREAM_REQUEST); | 36 net_log_.BeginEvent(NetLog::TYPE_HTTP_STREAM_REQUEST); |
37 } | 37 } |
38 | 38 |
39 HttpStreamFactoryImpl::Request::~Request() { | 39 HttpStreamFactoryImpl::Request::~Request() { |
40 if (bound_job_.get()) | 40 if (bound_job_.get()) |
41 DCHECK(jobs_.empty()); | 41 DCHECK(jobs_.empty()); |
42 else | |
43 DCHECK(!jobs_.empty()); | |
44 | 42 |
45 net_log_.EndEvent(NetLog::TYPE_HTTP_STREAM_REQUEST); | 43 net_log_.EndEvent(NetLog::TYPE_HTTP_STREAM_REQUEST); |
46 | 44 |
47 for (std::set<Job*>::iterator it = jobs_.begin(); it != jobs_.end(); ++it) | 45 CancelJobs(); |
48 factory_->request_map_.erase(*it); | |
49 | |
50 RemoveRequestFromSpdySessionRequestMap(); | |
51 | |
52 STLDeleteElements(&jobs_); | |
53 } | 46 } |
54 | 47 |
55 void HttpStreamFactoryImpl::Request::SetSpdySessionKey( | 48 void HttpStreamFactoryImpl::Request::SetSpdySessionKey( |
56 const SpdySessionKey& spdy_session_key) { | 49 const SpdySessionKey& spdy_session_key) { |
57 CHECK(!spdy_session_key_.get()); | 50 CHECK(!spdy_session_key_.get()); |
58 spdy_session_key_.reset(new SpdySessionKey(spdy_session_key)); | 51 spdy_session_key_.reset(new SpdySessionKey(spdy_session_key)); |
59 RequestSet& request_set = | 52 RequestSet& request_set = |
60 factory_->spdy_session_request_map_[spdy_session_key]; | 53 factory_->spdy_session_request_map_[spdy_session_key]; |
61 DCHECK(!ContainsKey(request_set, this)); | 54 DCHECK(!ContainsKey(request_set, this)); |
62 request_set.insert(this); | 55 request_set.insert(this); |
63 } | 56 } |
64 | 57 |
65 void HttpStreamFactoryImpl::Request::AttachJob(Job* job) { | 58 void HttpStreamFactoryImpl::Request::AttachJob(Job* job) { |
66 DCHECK(job); | 59 DCHECK(job); |
67 jobs_.insert(job); | 60 jobs_.insert(job); |
68 factory_->request_map_[job] = this; | 61 factory_->request_map_[job] = this; |
69 } | 62 } |
70 | 63 |
71 void HttpStreamFactoryImpl::Request::Complete( | 64 void HttpStreamFactoryImpl::Request::Complete(bool was_npn_negotiated, |
72 bool was_npn_negotiated, | 65 NextProto protocol_negotiated, |
73 NextProto protocol_negotiated, | 66 bool using_spdy) { |
74 bool using_spdy, | |
75 const BoundNetLog& job_net_log) { | |
76 DCHECK(!completed_); | 67 DCHECK(!completed_); |
77 completed_ = true; | 68 completed_ = true; |
78 was_npn_negotiated_ = was_npn_negotiated; | 69 was_npn_negotiated_ = was_npn_negotiated; |
79 protocol_negotiated_ = protocol_negotiated; | 70 protocol_negotiated_ = protocol_negotiated; |
80 using_spdy_ = using_spdy; | 71 using_spdy_ = using_spdy; |
81 net_log_.AddEvent( | |
82 NetLog::TYPE_HTTP_STREAM_REQUEST_BOUND_TO_JOB, | |
83 job_net_log.source().ToEventParametersCallback()); | |
84 job_net_log.AddEvent( | |
85 NetLog::TYPE_HTTP_STREAM_JOB_BOUND_TO_REQUEST, | |
86 net_log_.source().ToEventParametersCallback()); | |
87 } | 72 } |
88 | 73 |
89 void HttpStreamFactoryImpl::Request::OnStreamReady( | 74 void HttpStreamFactoryImpl::Request::OnStreamReady( |
90 Job* job, | 75 Job* job, |
91 const SSLConfig& used_ssl_config, | 76 const SSLConfig& used_ssl_config, |
92 const ProxyInfo& used_proxy_info, | 77 const ProxyInfo& used_proxy_info, |
93 HttpStream* stream) { | 78 HttpStream* stream) { |
94 DCHECK(!factory_->for_websockets_); | 79 DCHECK(!factory_->for_websockets_); |
95 DCHECK(stream); | 80 DCHECK(stream); |
96 DCHECK(completed_); | 81 DCHECK(completed_); |
(...skipping 17 matching lines...) Expand all Loading... |
114 } | 99 } |
115 | 100 |
116 void HttpStreamFactoryImpl::Request::OnStreamFailed( | 101 void HttpStreamFactoryImpl::Request::OnStreamFailed( |
117 Job* job, | 102 Job* job, |
118 int status, | 103 int status, |
119 const SSLConfig& used_ssl_config, | 104 const SSLConfig& used_ssl_config, |
120 SSLFailureState ssl_failure_state) { | 105 SSLFailureState ssl_failure_state) { |
121 DCHECK_NE(OK, status); | 106 DCHECK_NE(OK, status); |
122 DCHECK(job); | 107 DCHECK(job); |
123 if (!bound_job_.get()) { | 108 if (!bound_job_.get()) { |
124 // Hey, we've got other jobs! Maybe one of them will succeed, let's just | |
125 // ignore this failure. | |
126 if (jobs_.size() > 1) { | 109 if (jobs_.size() > 1) { |
| 110 // Hey, we've got other jobs! Maybe one of them will succeed, let's just |
| 111 // ignore this failure. |
127 jobs_.erase(job); | 112 jobs_.erase(job); |
128 factory_->request_map_.erase(job); | 113 factory_->request_map_.erase(job); |
129 // Notify all the other jobs that this one failed. | 114 // Notify all the other jobs that this one failed. |
130 for (std::set<Job*>::iterator it = jobs_.begin(); it != jobs_.end(); ++it) | 115 for (std::set<Job*>::iterator it = jobs_.begin(); it != jobs_.end(); ++it) |
131 (*it)->MarkOtherJobComplete(*job); | 116 (*it)->MarkOtherJobComplete(*job); |
132 delete job; | 117 delete job; |
133 return; | 118 return; |
134 } else { | 119 } else { |
135 bound_job_.reset(job); | 120 BindJob(job); |
136 jobs_.erase(job); | |
137 DCHECK(jobs_.empty()); | |
138 factory_->request_map_.erase(job); | |
139 } | 121 } |
140 } else { | 122 } else { |
141 DCHECK(jobs_.empty()); | 123 DCHECK(jobs_.empty()); |
142 } | 124 } |
143 delegate_->OnStreamFailed(status, used_ssl_config, ssl_failure_state); | 125 delegate_->OnStreamFailed(status, used_ssl_config, ssl_failure_state); |
144 } | 126 } |
145 | 127 |
146 void HttpStreamFactoryImpl::Request::OnCertificateError( | 128 void HttpStreamFactoryImpl::Request::OnCertificateError( |
147 Job* job, | 129 Job* job, |
148 int status, | 130 int status, |
149 const SSLConfig& used_ssl_config, | 131 const SSLConfig& used_ssl_config, |
150 const SSLInfo& ssl_info) { | 132 const SSLInfo& ssl_info) { |
151 DCHECK_NE(OK, status); | 133 DCHECK_NE(OK, status); |
152 if (!bound_job_.get()) | 134 if (!bound_job_.get()) |
153 OrphanJobsExcept(job); | 135 BindJob(job); |
154 else | 136 else |
155 DCHECK(jobs_.empty()); | 137 DCHECK(jobs_.empty()); |
156 delegate_->OnCertificateError(status, used_ssl_config, ssl_info); | 138 delegate_->OnCertificateError(status, used_ssl_config, ssl_info); |
157 } | 139 } |
158 | 140 |
159 void HttpStreamFactoryImpl::Request::OnNeedsProxyAuth( | 141 void HttpStreamFactoryImpl::Request::OnNeedsProxyAuth( |
160 Job* job, | 142 Job* job, |
161 const HttpResponseInfo& proxy_response, | 143 const HttpResponseInfo& proxy_response, |
162 const SSLConfig& used_ssl_config, | 144 const SSLConfig& used_ssl_config, |
163 const ProxyInfo& used_proxy_info, | 145 const ProxyInfo& used_proxy_info, |
164 HttpAuthController* auth_controller) { | 146 HttpAuthController* auth_controller) { |
165 if (!bound_job_.get()) | 147 if (!bound_job_.get()) |
166 OrphanJobsExcept(job); | 148 BindJob(job); |
167 else | 149 else |
168 DCHECK(jobs_.empty()); | 150 DCHECK(jobs_.empty()); |
169 delegate_->OnNeedsProxyAuth( | 151 delegate_->OnNeedsProxyAuth( |
170 proxy_response, used_ssl_config, used_proxy_info, auth_controller); | 152 proxy_response, used_ssl_config, used_proxy_info, auth_controller); |
171 } | 153 } |
172 | 154 |
173 void HttpStreamFactoryImpl::Request::OnNeedsClientAuth( | 155 void HttpStreamFactoryImpl::Request::OnNeedsClientAuth( |
174 Job* job, | 156 Job* job, |
175 const SSLConfig& used_ssl_config, | 157 const SSLConfig& used_ssl_config, |
176 SSLCertRequestInfo* cert_info) { | 158 SSLCertRequestInfo* cert_info) { |
177 if (!bound_job_.get()) | 159 if (!bound_job_.get()) |
178 OrphanJobsExcept(job); | 160 BindJob(job); |
179 else | 161 else |
180 DCHECK(jobs_.empty()); | 162 DCHECK(jobs_.empty()); |
181 delegate_->OnNeedsClientAuth(used_ssl_config, cert_info); | 163 delegate_->OnNeedsClientAuth(used_ssl_config, cert_info); |
182 } | 164 } |
183 | 165 |
184 void HttpStreamFactoryImpl::Request::OnHttpsProxyTunnelResponse( | 166 void HttpStreamFactoryImpl::Request::OnHttpsProxyTunnelResponse( |
185 Job *job, | 167 Job *job, |
186 const HttpResponseInfo& response_info, | 168 const HttpResponseInfo& response_info, |
187 const SSLConfig& used_ssl_config, | 169 const SSLConfig& used_ssl_config, |
188 const ProxyInfo& used_proxy_info, | 170 const ProxyInfo& used_proxy_info, |
189 HttpStream* stream) { | 171 HttpStream* stream) { |
190 if (!bound_job_.get()) | 172 if (!bound_job_.get()) |
191 OrphanJobsExcept(job); | 173 BindJob(job); |
192 else | 174 else |
193 DCHECK(jobs_.empty()); | 175 DCHECK(jobs_.empty()); |
194 delegate_->OnHttpsProxyTunnelResponse( | 176 delegate_->OnHttpsProxyTunnelResponse( |
195 response_info, used_ssl_config, used_proxy_info, stream); | 177 response_info, used_ssl_config, used_proxy_info, stream); |
196 } | 178 } |
197 | 179 |
198 int HttpStreamFactoryImpl::Request::RestartTunnelWithProxyAuth( | 180 int HttpStreamFactoryImpl::Request::RestartTunnelWithProxyAuth( |
199 const AuthCredentials& credentials) { | 181 const AuthCredentials& credentials) { |
200 DCHECK(bound_job_.get()); | 182 DCHECK(bound_job_.get()); |
201 return bound_job_->RestartTunnelWithProxyAuth(credentials); | 183 return bound_job_->RestartTunnelWithProxyAuth(credentials); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
274 bool direct) { | 256 bool direct) { |
275 DCHECK(job); | 257 DCHECK(job); |
276 DCHECK(job->using_spdy()); | 258 DCHECK(job->using_spdy()); |
277 | 259 |
278 // Note: |spdy_session| may be NULL. In that case, |delegate_| should still | 260 // Note: |spdy_session| may be NULL. In that case, |delegate_| should still |
279 // receive |stream| so the error propogates up correctly, however there is no | 261 // receive |stream| so the error propogates up correctly, however there is no |
280 // point in broadcasting |spdy_session| to other requests. | 262 // point in broadcasting |spdy_session| to other requests. |
281 | 263 |
282 // The first case is the usual case. | 264 // The first case is the usual case. |
283 if (!bound_job_.get()) { | 265 if (!bound_job_.get()) { |
284 OrphanJobsExcept(job); | 266 BindJob(job); |
285 } else { // This is the case for HTTPS proxy tunneling. | 267 } else { // This is the case for HTTPS proxy tunneling. |
286 DCHECK_EQ(bound_job_.get(), job); | 268 DCHECK_EQ(bound_job_.get(), job); |
287 DCHECK(jobs_.empty()); | 269 DCHECK(jobs_.empty()); |
288 } | 270 } |
289 | 271 |
290 // Cache these values in case the job gets deleted. | 272 // Cache these values in case the job gets deleted. |
291 const SSLConfig used_ssl_config = job->server_ssl_config(); | 273 const SSLConfig used_ssl_config = job->server_ssl_config(); |
292 const ProxyInfo used_proxy_info = job->proxy_info(); | 274 const ProxyInfo used_proxy_info = job->proxy_info(); |
293 const bool was_npn_negotiated = job->was_npn_negotiated(); | 275 const bool was_npn_negotiated = job->was_npn_negotiated(); |
294 const NextProto protocol_negotiated = | 276 const NextProto protocol_negotiated = |
295 job->protocol_negotiated(); | 277 job->protocol_negotiated(); |
296 const bool using_spdy = job->using_spdy(); | 278 const bool using_spdy = job->using_spdy(); |
297 const BoundNetLog net_log = job->net_log(); | 279 const BoundNetLog net_log = job->net_log(); |
298 | 280 |
299 Complete(was_npn_negotiated, protocol_negotiated, using_spdy, net_log); | 281 Complete(was_npn_negotiated, protocol_negotiated, using_spdy); |
300 | 282 |
301 // Cache this so we can still use it if the request is deleted. | 283 // Cache this so we can still use it if the request is deleted. |
302 HttpStreamFactoryImpl* factory = factory_; | 284 HttpStreamFactoryImpl* factory = factory_; |
303 if (factory->for_websockets_) { | 285 if (factory->for_websockets_) { |
304 // TODO(ricea): Re-instate this code when WebSockets over SPDY is | 286 // TODO(ricea): Re-instate this code when WebSockets over SPDY is |
305 // implemented. | 287 // implemented. |
306 NOTREACHED(); | 288 NOTREACHED(); |
307 } else { | 289 } else { |
308 delegate_->OnStreamReady(job->server_ssl_config(), job->proxy_info(), | 290 delegate_->OnStreamReady(job->server_ssl_config(), job->proxy_info(), |
309 stream.release()); | 291 stream.release()); |
(...skipping 10 matching lines...) Expand all Loading... |
320 net_log); | 302 net_log); |
321 } | 303 } |
322 } | 304 } |
323 | 305 |
324 void HttpStreamFactoryImpl::Request::AddConnectionAttempts( | 306 void HttpStreamFactoryImpl::Request::AddConnectionAttempts( |
325 const ConnectionAttempts& attempts) { | 307 const ConnectionAttempts& attempts) { |
326 for (const auto& attempt : attempts) | 308 for (const auto& attempt : attempts) |
327 connection_attempts_.push_back(attempt); | 309 connection_attempts_.push_back(attempt); |
328 } | 310 } |
329 | 311 |
330 void HttpStreamFactoryImpl::Request::OrphanJobsExcept(Job* job) { | 312 void HttpStreamFactoryImpl::Request::BindJob(Job* job) { |
331 DCHECK(job); | 313 DCHECK(job); |
332 DCHECK(!bound_job_.get()); | 314 DCHECK(!bound_job_.get()); |
333 DCHECK(ContainsKey(jobs_, job)); | 315 DCHECK(ContainsKey(jobs_, job)); |
334 bound_job_.reset(job); | 316 bound_job_.reset(job); |
335 jobs_.erase(job); | 317 jobs_.erase(job); |
336 factory_->request_map_.erase(job); | 318 factory_->request_map_.erase(job); |
337 | 319 |
| 320 net_log_.AddEvent(NetLog::TYPE_HTTP_STREAM_REQUEST_BOUND_TO_JOB, |
| 321 job->net_log().source().ToEventParametersCallback()); |
| 322 job->net_log().AddEvent(NetLog::TYPE_HTTP_STREAM_JOB_BOUND_TO_REQUEST, |
| 323 net_log_.source().ToEventParametersCallback()); |
| 324 |
338 OrphanJobs(); | 325 OrphanJobs(); |
339 } | 326 } |
340 | 327 |
341 void HttpStreamFactoryImpl::Request::OrphanJobs() { | 328 void HttpStreamFactoryImpl::Request::OrphanJobs() { |
342 RemoveRequestFromSpdySessionRequestMap(); | 329 RemoveRequestFromSpdySessionRequestMap(); |
343 | 330 |
344 std::set<Job*> tmp; | 331 std::set<Job*> tmp; |
345 tmp.swap(jobs_); | 332 tmp.swap(jobs_); |
346 | 333 |
347 for (std::set<Job*>::iterator it = tmp.begin(); it != tmp.end(); ++it) | 334 for (Job* job : tmp) |
348 factory_->OrphanJob(*it, this); | 335 factory_->OrphanJob(job, this); |
| 336 } |
| 337 |
| 338 void HttpStreamFactoryImpl::Request::CancelJobs() { |
| 339 RemoveRequestFromSpdySessionRequestMap(); |
| 340 |
| 341 std::set<Job*> tmp; |
| 342 tmp.swap(jobs_); |
| 343 |
| 344 for (Job* job : tmp) { |
| 345 factory_->request_map_.erase(job); |
| 346 delete job; |
| 347 } |
349 } | 348 } |
350 | 349 |
351 void HttpStreamFactoryImpl::Request::OnJobSucceeded(Job* job) { | 350 void HttpStreamFactoryImpl::Request::OnJobSucceeded(Job* job) { |
352 // |job| should only be NULL if we're being serviced by a late bound | 351 // |job| should only be NULL if we're being serviced by a late bound |
353 // SpdySession (one that was not created by a job in our |jobs_| set). | 352 // SpdySession (one that was not created by a job in our |jobs_| set). |
354 if (!job) { | 353 if (!job) { |
355 DCHECK(!bound_job_.get()); | 354 DCHECK(!bound_job_.get()); |
356 DCHECK(!jobs_.empty()); | 355 DCHECK(!jobs_.empty()); |
357 // NOTE(willchan): We do *NOT* call OrphanJobs() here. The reason is because | 356 // NOTE(willchan): We do *NOT* call OrphanJobs() here. The reason is because |
358 // we *WANT* to cancel the unnecessary Jobs from other requests if another | 357 // we *WANT* to cancel the unnecessary Jobs from other requests if another |
359 // Job completes first. | 358 // Job completes first. |
360 // TODO(mbelshe): Revisit this when we implement ip connection pooling of | 359 // TODO(mbelshe): Revisit this when we implement ip connection pooling of |
361 // SpdySessions. Do we want to orphan the jobs for a different hostname so | 360 // SpdySessions. Do we want to orphan the jobs for a different hostname so |
362 // they complete? Or do we want to prevent connecting a new SpdySession if | 361 // they complete? Or do we want to prevent connecting a new SpdySession if |
363 // we've already got one available for a different hostname where the ip | 362 // we've already got one available for a different hostname where the ip |
364 // address matches up? | 363 // address matches up? |
| 364 CancelJobs(); |
365 return; | 365 return; |
366 } | 366 } |
367 if (!bound_job_.get()) { | 367 if (!bound_job_.get()) { |
368 if (jobs_.size() > 1) | 368 if (jobs_.size() > 1) |
369 job->ReportJobSucceededForRequest(); | 369 job->ReportJobSucceededForRequest(); |
370 // Notify all the other jobs that this one succeeded. | 370 // Notify all the other jobs that this one succeeded. |
371 for (std::set<Job*>::iterator it = jobs_.begin(); it != jobs_.end(); ++it) { | 371 for (std::set<Job*>::iterator it = jobs_.begin(); it != jobs_.end(); ++it) { |
372 if (*it != job) { | 372 if (*it != job) { |
373 (*it)->MarkOtherJobComplete(*job); | 373 (*it)->MarkOtherJobComplete(*job); |
374 } | 374 } |
375 } | 375 } |
376 // We may have other jobs in |jobs_|. For example, if we start multiple jobs | 376 // We may have other jobs in |jobs_|. For example, if we start multiple jobs |
377 // for Alternate-Protocol. | 377 // for Alternate-Protocol. |
378 OrphanJobsExcept(job); | 378 BindJob(job); |
379 return; | 379 return; |
380 } | 380 } |
381 DCHECK(jobs_.empty()); | 381 DCHECK(jobs_.empty()); |
382 } | 382 } |
383 | 383 |
384 } // namespace net | 384 } // namespace net |
OLD | NEW |