Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(99)

Side by Side Diff: net/http/http_stream_factory_impl_request.cc

Issue 6591030: Add HttpStreamFactory Job orphaning semantics. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix other merge. Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/http/http_stream_factory_impl_request.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/logging.h" 7 #include "base/logging.h"
8 #include "base/stl_util-inl.h" 8 #include "base/stl_util-inl.h"
9 #include "net/http/http_stream_factory_impl_job.h" 9 #include "net/http/http_stream_factory_impl_job.h"
10 #include "net/spdy/spdy_http_stream.h"
11 #include "net/spdy/spdy_session.h"
10 12
11 namespace net { 13 namespace net {
12 14
13 HttpStreamFactoryImpl::Request::Request(const GURL& url, 15 HttpStreamFactoryImpl::Request::Request(const GURL& url,
14 HttpStreamFactoryImpl* factory, 16 HttpStreamFactoryImpl* factory,
15 HttpStreamRequest::Delegate* delegate, 17 HttpStreamRequest::Delegate* delegate,
16 const BoundNetLog& net_log) 18 const BoundNetLog& net_log)
17 : url_(url), 19 : url_(url),
18 factory_(factory), 20 factory_(factory),
19 delegate_(delegate), 21 delegate_(delegate),
20 net_log_(net_log), 22 net_log_(net_log),
21 job_(NULL),
22 completed_(false), 23 completed_(false),
23 was_alternate_protocol_available_(false), 24 was_alternate_protocol_available_(false),
24 was_npn_negotiated_(false), 25 was_npn_negotiated_(false),
25 using_spdy_(false) { 26 using_spdy_(false) {
26 DCHECK(factory_); 27 DCHECK(factory_);
27 DCHECK(delegate_); 28 DCHECK(delegate_);
28 29
29 net_log_.BeginEvent(NetLog::TYPE_HTTP_STREAM_REQUEST, NULL); 30 net_log_.BeginEvent(NetLog::TYPE_HTTP_STREAM_REQUEST, NULL);
30 } 31 }
31 32
32 HttpStreamFactoryImpl::Request::~Request() { 33 HttpStreamFactoryImpl::Request::~Request() {
34 if (bound_job_.get())
35 DCHECK(jobs_.empty());
36 else
37 DCHECK(!jobs_.empty());
38
33 net_log_.EndEvent(NetLog::TYPE_HTTP_STREAM_REQUEST, NULL); 39 net_log_.EndEvent(NetLog::TYPE_HTTP_STREAM_REQUEST, NULL);
34 40
35 factory_->request_map_.erase(job_); 41 for (std::set<Job*>::iterator it = jobs_.begin(); it != jobs_.end(); ++it)
42 factory_->request_map_.erase(*it);
36 43
37 // TODO(willchan): Remove this when we decouple requests and jobs. 44 STLDeleteElements(&jobs_);
38 delete job_;
39 45
40 RemoveRequestFromSpdySessionRequestMap(); 46 RemoveRequestFromSpdySessionRequestMap();
41 } 47 }
42 48
43 void HttpStreamFactoryImpl::Request::SetSpdySessionKey( 49 void HttpStreamFactoryImpl::Request::SetSpdySessionKey(
44 const HostPortProxyPair& spdy_session_key) { 50 const HostPortProxyPair& spdy_session_key) {
45 DCHECK(!spdy_session_key_.get()); 51 DCHECK(!spdy_session_key_.get());
46 spdy_session_key_.reset(new HostPortProxyPair(spdy_session_key)); 52 spdy_session_key_.reset(new HostPortProxyPair(spdy_session_key));
47 RequestSet& request_set = 53 RequestSet& request_set =
48 factory_->spdy_session_request_map_[spdy_session_key]; 54 factory_->spdy_session_request_map_[spdy_session_key];
49 DCHECK(!ContainsKey(request_set, this)); 55 DCHECK(!ContainsKey(request_set, this));
50 request_set.insert(this); 56 request_set.insert(this);
51 } 57 }
52 58
53 void HttpStreamFactoryImpl::Request::BindJob(HttpStreamFactoryImpl::Job* job) { 59 void HttpStreamFactoryImpl::Request::AttachJob(Job* job) {
54 DCHECK(job); 60 DCHECK(job);
55 DCHECK(!job_); 61 jobs_.insert(job);
56 job_ = job; 62 factory_->request_map_[job] = this;
57 } 63 }
58 64
59 void HttpStreamFactoryImpl::Request::Complete( 65 void HttpStreamFactoryImpl::Request::Complete(
60 bool was_alternate_protocol_available, 66 bool was_alternate_protocol_available,
61 bool was_npn_negotiated, 67 bool was_npn_negotiated,
62 bool using_spdy, 68 bool using_spdy,
63 const NetLog::Source& job_source) { 69 const NetLog::Source& job_source) {
64 DCHECK(!completed_); 70 DCHECK(!completed_);
65 completed_ = true; 71 completed_ = true;
66 was_alternate_protocol_available_ = was_alternate_protocol_available; 72 was_alternate_protocol_available_ = was_alternate_protocol_available;
67 was_npn_negotiated_ = was_npn_negotiated; 73 was_npn_negotiated_ = was_npn_negotiated;
68 using_spdy_ = using_spdy; 74 using_spdy_ = using_spdy;
69 net_log_.AddEvent( 75 net_log_.AddEvent(
70 NetLog::TYPE_HTTP_STREAM_REQUEST_BOUND_TO_JOB, 76 NetLog::TYPE_HTTP_STREAM_REQUEST_BOUND_TO_JOB,
71 make_scoped_refptr(new NetLogSourceParameter( 77 make_scoped_refptr(new NetLogSourceParameter(
72 "source_dependency", job_source))); 78 "source_dependency", job_source)));
73 } 79 }
74 80
75 void HttpStreamFactoryImpl::Request::OnStreamReady( 81 void HttpStreamFactoryImpl::Request::OnStreamReady(
82 Job* job,
76 const SSLConfig& used_ssl_config, 83 const SSLConfig& used_ssl_config,
77 const ProxyInfo& used_proxy_info, 84 const ProxyInfo& used_proxy_info,
78 HttpStream* stream) { 85 HttpStream* stream) {
79 DCHECK(stream); 86 DCHECK(stream);
80 DCHECK(completed_); 87 DCHECK(completed_);
88
89 // |job| should only be NULL if we're being serviced by a late bound
90 // SpdySession (one that was not created by a job in our |jobs_| set).
91 if (!job) {
92 DCHECK(!bound_job_.get());
93 DCHECK(!jobs_.empty());
94 // NOTE(willchan): We do *NOT* call OrphanJobs() here. The reason is because
95 // we *WANT* to cancel the unnecessary Jobs from other requests if another
96 // Job completes first.
97 // TODO(mbelshe): Revisit this when we implement ip connection pooling of
willchan no longer on Chromium 2011/03/01 00:22:42 Please chime in on this.
98 // SpdySessions. Do we want to orphan the jobs for a different hostname so
99 // they complete? Or do we want to prevent connecting a new SpdySession if
100 // we've already got one available for a different hostname where the ip
101 // address matches up?
102 } else if (!bound_job_.get()) {
103 // We may have other jobs in |jobs_|. For example, if we start multiple jobs
104 // for Alternate-Protocol.
105 OrphanJobsExcept(job);
106 } else {
107 DCHECK(jobs_.empty());
108 }
81 delegate_->OnStreamReady(used_ssl_config, used_proxy_info, stream); 109 delegate_->OnStreamReady(used_ssl_config, used_proxy_info, stream);
82 } 110 }
83 111
84 void HttpStreamFactoryImpl::Request::OnStreamFailed( 112 void HttpStreamFactoryImpl::Request::OnStreamFailed(
113 Job* job,
85 int status, 114 int status,
86 const SSLConfig& used_ssl_config) { 115 const SSLConfig& used_ssl_config) {
87 DCHECK_NE(OK, status); 116 DCHECK_NE(OK, status);
117 if (!bound_job_.get())
118 OrphanJobsExcept(job);
119 else
120 DCHECK(jobs_.empty());
88 delegate_->OnStreamFailed(status, used_ssl_config); 121 delegate_->OnStreamFailed(status, used_ssl_config);
89 } 122 }
90 123
91 void HttpStreamFactoryImpl::Request::OnCertificateError( 124 void HttpStreamFactoryImpl::Request::OnCertificateError(
125 Job* job,
92 int status, 126 int status,
93 const SSLConfig& used_ssl_config, 127 const SSLConfig& used_ssl_config,
94 const SSLInfo& ssl_info) { 128 const SSLInfo& ssl_info) {
95 DCHECK_NE(OK, status); 129 DCHECK_NE(OK, status);
130 if (!bound_job_.get())
131 OrphanJobsExcept(job);
132 else
133 DCHECK(jobs_.empty());
96 delegate_->OnCertificateError(status, used_ssl_config, ssl_info); 134 delegate_->OnCertificateError(status, used_ssl_config, ssl_info);
97 } 135 }
98 136
99 void HttpStreamFactoryImpl::Request::OnNeedsProxyAuth( 137 void HttpStreamFactoryImpl::Request::OnNeedsProxyAuth(
138 Job* job,
100 const HttpResponseInfo& proxy_response, 139 const HttpResponseInfo& proxy_response,
101 const SSLConfig& used_ssl_config, 140 const SSLConfig& used_ssl_config,
102 const ProxyInfo& used_proxy_info, 141 const ProxyInfo& used_proxy_info,
103 HttpAuthController* auth_controller) { 142 HttpAuthController* auth_controller) {
143 if (!bound_job_.get())
144 OrphanJobsExcept(job);
145 else
146 DCHECK(jobs_.empty());
104 delegate_->OnNeedsProxyAuth( 147 delegate_->OnNeedsProxyAuth(
105 proxy_response, used_ssl_config, used_proxy_info, auth_controller); 148 proxy_response, used_ssl_config, used_proxy_info, auth_controller);
106 } 149 }
107 150
108 void HttpStreamFactoryImpl::Request::OnNeedsClientAuth( 151 void HttpStreamFactoryImpl::Request::OnNeedsClientAuth(
152 Job* job,
109 const SSLConfig& used_ssl_config, 153 const SSLConfig& used_ssl_config,
110 SSLCertRequestInfo* cert_info) { 154 SSLCertRequestInfo* cert_info) {
155 if (!bound_job_.get())
156 OrphanJobsExcept(job);
157 else
158 DCHECK(jobs_.empty());
111 delegate_->OnNeedsClientAuth(used_ssl_config, cert_info); 159 delegate_->OnNeedsClientAuth(used_ssl_config, cert_info);
112 } 160 }
113 161
114 void HttpStreamFactoryImpl::Request::OnHttpsProxyTunnelResponse( 162 void HttpStreamFactoryImpl::Request::OnHttpsProxyTunnelResponse(
163 Job *job,
115 const HttpResponseInfo& response_info, 164 const HttpResponseInfo& response_info,
116 const SSLConfig& used_ssl_config, 165 const SSLConfig& used_ssl_config,
117 const ProxyInfo& used_proxy_info, 166 const ProxyInfo& used_proxy_info,
118 HttpStream* stream) { 167 HttpStream* stream) {
168 if (!bound_job_.get())
169 OrphanJobsExcept(job);
170 else
171 DCHECK(jobs_.empty());
119 delegate_->OnHttpsProxyTunnelResponse( 172 delegate_->OnHttpsProxyTunnelResponse(
120 response_info, used_ssl_config, used_proxy_info, stream); 173 response_info, used_ssl_config, used_proxy_info, stream);
121 } 174 }
122 175
123 int HttpStreamFactoryImpl::Request::RestartTunnelWithProxyAuth( 176 int HttpStreamFactoryImpl::Request::RestartTunnelWithProxyAuth(
124 const string16& username, 177 const string16& username,
125 const string16& password) { 178 const string16& password) {
126 // We're restarting the job, so ditch the old key. Note that we could actually 179 DCHECK(bound_job_.get());
127 // keep it around and eliminate the DCHECK in set_spdy_session_key() that 180 return bound_job_->RestartTunnelWithProxyAuth(username, password);
128 // |spdy_session_key_| is NULL, but I prefer to keep the assertion.
129 RemoveRequestFromSpdySessionRequestMap();
130 return job_->RestartTunnelWithProxyAuth(username, password);
131 } 181 }
132 182
133 LoadState HttpStreamFactoryImpl::Request::GetLoadState() const { 183 LoadState HttpStreamFactoryImpl::Request::GetLoadState() const {
134 return factory_->GetLoadState(*this); 184 if (bound_job_.get())
185 return bound_job_->GetLoadState();
186 DCHECK(!jobs_.empty());
187
188 // Just pick the first one.
189 return (*jobs_.begin())->GetLoadState();
135 } 190 }
136 191
137 bool HttpStreamFactoryImpl::Request::was_alternate_protocol_available() const { 192 bool HttpStreamFactoryImpl::Request::was_alternate_protocol_available() const {
138 DCHECK(completed_); 193 DCHECK(completed_);
139 return was_alternate_protocol_available_; 194 return was_alternate_protocol_available_;
140 } 195 }
141 196
142 bool HttpStreamFactoryImpl::Request::was_npn_negotiated() const { 197 bool HttpStreamFactoryImpl::Request::was_npn_negotiated() const {
143 DCHECK(completed_); 198 DCHECK(completed_);
144 return was_npn_negotiated_; 199 return was_npn_negotiated_;
(...skipping 13 matching lines...) Expand all
158 RequestSet& request_set = 213 RequestSet& request_set =
159 spdy_session_request_map[*spdy_session_key_]; 214 spdy_session_request_map[*spdy_session_key_];
160 DCHECK(ContainsKey(request_set, this)); 215 DCHECK(ContainsKey(request_set, this));
161 request_set.erase(this); 216 request_set.erase(this);
162 if (request_set.empty()) 217 if (request_set.empty())
163 spdy_session_request_map.erase(*spdy_session_key_); 218 spdy_session_request_map.erase(*spdy_session_key_);
164 spdy_session_key_.reset(); 219 spdy_session_key_.reset();
165 } 220 }
166 } 221 }
167 222
223 void HttpStreamFactoryImpl::Request::OnSpdySessionReady(
224 Job* job,
225 scoped_refptr<SpdySession> spdy_session,
226 bool direct) {
227 DCHECK(job);
228 DCHECK(job->using_spdy());
229
230 // The first case is the usual case.
231 if (!bound_job_.get()) {
232 OrphanJobsExcept(job);
233 } else { // This is the case for HTTPS proxy tunneling.
234 DCHECK_EQ(bound_job_.get(), job);
235 DCHECK(jobs_.empty());
236 }
237
238 // Cache these values in case the job gets deleted.
239 const SSLConfig used_ssl_config = job->ssl_config();
240 const ProxyInfo used_proxy_info = job->proxy_info();
241 const bool was_alternate_protocol_available =
242 job->was_alternate_protocol_available();
243 const bool was_npn_negotiated = job->was_npn_negotiated();
244 const bool using_spdy = job->using_spdy();
245 const NetLog::Source source = job->net_log().source();
246
247 Complete(was_alternate_protocol_available,
248 was_npn_negotiated,
249 using_spdy,
250 source);
251
252 // Cache this so we can still use it if the request is deleted.
253 HttpStreamFactoryImpl* factory = factory_;
254
255 bool use_relative_url = direct || url().SchemeIs("https");
256 delegate_->OnStreamReady(
257 job->ssl_config(),
258 job->proxy_info(),
259 new SpdyHttpStream(spdy_session, use_relative_url));
260 // |this| may be deleted after this point.
261 factory->OnSpdySessionReady(
262 spdy_session, direct, used_ssl_config, used_proxy_info,
263 was_alternate_protocol_available, was_npn_negotiated, using_spdy, source);
264 }
265
266 void HttpStreamFactoryImpl::Request::OrphanJobsExcept(Job* job) {
267 DCHECK(job);
268 DCHECK(!bound_job_.get());
269 DCHECK(ContainsKey(jobs_, job));
270 bound_job_.reset(job);
271 jobs_.erase(job);
272 factory_->request_map_.erase(job);
273
274 OrphanJobs();
275 }
276
277 void HttpStreamFactoryImpl::Request::OrphanJobs() {
278 RemoveRequestFromSpdySessionRequestMap();
279
280 std::set<Job*> tmp;
281 tmp.swap(jobs_);
282
283 for (std::set<Job*>::iterator it = tmp.begin(); it != tmp.end(); ++it)
284 factory_->OrphanJob(*it, this);
285 }
286
168 } // namespace net 287 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_stream_factory_impl_request.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698