OLD | NEW |
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_job.h" | 5 #include "net/http/http_stream_factory_impl_job.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 "base/string_number_conversions.h" | |
10 #include "base/string_util.h" | 9 #include "base/string_util.h" |
11 #include "base/stringprintf.h" | 10 #include "base/stringprintf.h" |
12 #include "base/values.h" | 11 #include "base/values.h" |
13 #include "net/base/connection_type_histograms.h" | 12 #include "net/base/connection_type_histograms.h" |
14 #include "net/base/net_log.h" | 13 #include "net/base/net_log.h" |
15 #include "net/base/net_util.h" | 14 #include "net/base/net_util.h" |
16 #include "net/base/ssl_cert_request_info.h" | 15 #include "net/base/ssl_cert_request_info.h" |
17 #include "net/http/http_basic_stream.h" | 16 #include "net/http/http_basic_stream.h" |
18 #include "net/http/http_network_session.h" | 17 #include "net/http/http_network_session.h" |
19 #include "net/http/http_proxy_client_socket.h" | 18 #include "net/http/http_proxy_client_socket.h" |
20 #include "net/http/http_proxy_client_socket_pool.h" | 19 #include "net/http/http_proxy_client_socket_pool.h" |
21 #include "net/http/http_request_info.h" | 20 #include "net/http/http_request_info.h" |
22 #include "net/http/http_stream_factory_impl_request.h" | 21 #include "net/http/http_stream_factory_impl_request.h" |
23 #include "net/socket/client_socket_handle.h" | 22 #include "net/socket/client_socket_handle.h" |
24 #include "net/socket/client_socket_pool.h" | 23 #include "net/socket/client_socket_pool.h" |
25 #include "net/socket/socks_client_socket_pool.h" | 24 #include "net/socket/socks_client_socket_pool.h" |
26 #include "net/socket/ssl_client_socket.h" | 25 #include "net/socket/ssl_client_socket.h" |
27 #include "net/socket/ssl_client_socket_pool.h" | 26 #include "net/socket/ssl_client_socket_pool.h" |
28 #include "net/socket/tcp_client_socket_pool.h" | 27 #include "net/socket/tcp_client_socket_pool.h" |
29 #include "net/spdy/spdy_http_stream.h" | 28 #include "net/spdy/spdy_http_stream.h" |
30 #include "net/spdy/spdy_session.h" | 29 #include "net/spdy/spdy_session.h" |
31 #include "net/spdy/spdy_session_pool.h" | 30 #include "net/spdy/spdy_session_pool.h" |
32 | 31 |
33 namespace net { | 32 namespace net { |
34 | 33 |
35 namespace { | 34 namespace { |
36 | 35 |
37 GURL UpgradeUrlToHttps(const GURL& original_url) { | |
38 GURL::Replacements replacements; | |
39 // new_sheme and new_port need to be in scope here because GURL::Replacements | |
40 // references the memory contained by them directly. | |
41 const std::string new_scheme = "https"; | |
42 const std::string new_port = base::IntToString(443); | |
43 replacements.SetSchemeStr(new_scheme); | |
44 replacements.SetPortStr(new_port); | |
45 return original_url.ReplaceComponents(replacements); | |
46 } | |
47 | |
48 } // namespace | 36 } // namespace |
49 | 37 |
50 HttpStreamFactoryImpl::Job::Job(HttpStreamFactoryImpl* stream_factory, | 38 HttpStreamFactoryImpl::Job::Job(HttpStreamFactoryImpl* stream_factory, |
51 HttpNetworkSession* session) | 39 HttpNetworkSession* session, |
| 40 const HttpRequestInfo& request_info, |
| 41 const SSLConfig& ssl_config, |
| 42 const BoundNetLog& net_log) |
52 : request_(NULL), | 43 : request_(NULL), |
| 44 request_info_(request_info), |
| 45 ssl_config_(ssl_config), |
| 46 net_log_(BoundNetLog::Make(net_log.net_log(), |
| 47 NetLog::SOURCE_HTTP_STREAM_JOB)), |
53 ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_(this, &Job::OnIOComplete)), | 48 ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_(this, &Job::OnIOComplete)), |
54 connection_(new ClientSocketHandle), | 49 connection_(new ClientSocketHandle), |
55 session_(session), | 50 session_(session), |
56 stream_factory_(stream_factory), | 51 stream_factory_(stream_factory), |
57 next_state_(STATE_NONE), | 52 next_state_(STATE_NONE), |
58 pac_request_(NULL), | 53 pac_request_(NULL), |
| 54 blocking_job_(NULL), |
| 55 dependent_job_(NULL), |
59 using_ssl_(false), | 56 using_ssl_(false), |
60 using_spdy_(false), | 57 using_spdy_(false), |
61 force_spdy_always_(HttpStreamFactory::force_spdy_always()), | 58 force_spdy_always_(HttpStreamFactory::force_spdy_always()), |
62 force_spdy_over_ssl_(HttpStreamFactory::force_spdy_over_ssl()), | 59 force_spdy_over_ssl_(HttpStreamFactory::force_spdy_over_ssl()), |
63 spdy_certificate_error_(OK), | 60 spdy_certificate_error_(OK), |
64 alternate_protocol_(HttpAlternateProtocols::UNINITIALIZED), | |
65 establishing_tunnel_(false), | 61 establishing_tunnel_(false), |
66 was_alternate_protocol_available_(false), | |
67 was_npn_negotiated_(false), | 62 was_npn_negotiated_(false), |
68 num_streams_(0), | 63 num_streams_(0), |
69 spdy_session_direct_(false), | 64 spdy_session_direct_(false), |
70 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { | 65 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { |
71 DCHECK(stream_factory); | 66 DCHECK(stream_factory); |
72 DCHECK(session); | 67 DCHECK(session); |
73 if (HttpStreamFactory::use_alternate_protocols()) | |
74 alternate_protocol_mode_ = kUnspecified; | |
75 else | |
76 alternate_protocol_mode_ = kDoNotUseAlternateProtocol; | |
77 } | 68 } |
78 | 69 |
79 HttpStreamFactoryImpl::Job::~Job() { | 70 HttpStreamFactoryImpl::Job::~Job() { |
80 net_log_.EndEvent(NetLog::TYPE_HTTP_STREAM_JOB, NULL); | 71 net_log_.EndEvent(NetLog::TYPE_HTTP_STREAM_JOB, NULL); |
81 | 72 |
82 // When we're in a partially constructed state, waiting for the user to | 73 // When we're in a partially constructed state, waiting for the user to |
83 // provide certificate handling information or authentication, we can't reuse | 74 // provide certificate handling information or authentication, we can't reuse |
84 // this stream at all. | 75 // this stream at all. |
85 if (next_state_ == STATE_WAITING_USER_ACTION) { | 76 if (next_state_ == STATE_WAITING_USER_ACTION) { |
86 connection_->socket()->Disconnect(); | 77 connection_->socket()->Disconnect(); |
87 connection_.reset(); | 78 connection_.reset(); |
88 } | 79 } |
89 | 80 |
90 if (pac_request_) | 81 if (pac_request_) |
91 session_->proxy_service()->CancelPacRequest(pac_request_); | 82 session_->proxy_service()->CancelPacRequest(pac_request_); |
92 | 83 |
93 // The stream could be in a partial state. It is not reusable. | 84 // The stream could be in a partial state. It is not reusable. |
94 if (stream_.get() && next_state_ != STATE_DONE) | 85 if (stream_.get() && next_state_ != STATE_DONE) |
95 stream_->Close(true /* not reusable */); | 86 stream_->Close(true /* not reusable */); |
96 } | 87 } |
97 | 88 |
98 void HttpStreamFactoryImpl::Job::Start(Request* request, | 89 void HttpStreamFactoryImpl::Job::Start(Request* request) { |
99 const HttpRequestInfo& request_info, | |
100 const SSLConfig& ssl_config, | |
101 const BoundNetLog& net_log) { | |
102 DCHECK(request); | 90 DCHECK(request); |
103 request_ = request; | 91 request_ = request; |
104 StartInternal(request_info, ssl_config, net_log); | 92 StartInternal(); |
105 } | 93 } |
106 | 94 |
107 int HttpStreamFactoryImpl::Job::Preconnect(int num_streams, | 95 int HttpStreamFactoryImpl::Job::Preconnect(int num_streams) { |
108 const HttpRequestInfo& request_info, | |
109 const SSLConfig& ssl_config, | |
110 const BoundNetLog& net_log) { | |
111 DCHECK_GT(num_streams, 0); | 96 DCHECK_GT(num_streams, 0); |
112 num_streams_ = num_streams; | 97 num_streams_ = num_streams; |
113 return StartInternal(request_info, ssl_config, net_log); | 98 return StartInternal(); |
114 } | 99 } |
115 | 100 |
116 int HttpStreamFactoryImpl::Job::RestartTunnelWithProxyAuth( | 101 int HttpStreamFactoryImpl::Job::RestartTunnelWithProxyAuth( |
117 const string16& username, const string16& password) { | 102 const string16& username, const string16& password) { |
118 DCHECK(establishing_tunnel_); | 103 DCHECK(establishing_tunnel_); |
119 next_state_ = STATE_RESTART_TUNNEL_AUTH; | 104 next_state_ = STATE_RESTART_TUNNEL_AUTH; |
120 stream_.reset(); | 105 stream_.reset(); |
121 return RunLoop(OK); | 106 return RunLoop(OK); |
122 } | 107 } |
123 | 108 |
124 LoadState HttpStreamFactoryImpl::Job::GetLoadState() const { | 109 LoadState HttpStreamFactoryImpl::Job::GetLoadState() const { |
125 switch (next_state_) { | 110 switch (next_state_) { |
126 case STATE_RESOLVE_PROXY_COMPLETE: | 111 case STATE_RESOLVE_PROXY_COMPLETE: |
127 return LOAD_STATE_RESOLVING_PROXY_FOR_URL; | 112 return LOAD_STATE_RESOLVING_PROXY_FOR_URL; |
128 case STATE_CREATE_STREAM_COMPLETE: | 113 case STATE_CREATE_STREAM_COMPLETE: |
129 return connection_->GetLoadState(); | 114 return connection_->GetLoadState(); |
130 case STATE_INIT_CONNECTION_COMPLETE: | 115 case STATE_INIT_CONNECTION_COMPLETE: |
131 return LOAD_STATE_SENDING_REQUEST; | 116 return LOAD_STATE_SENDING_REQUEST; |
132 default: | 117 default: |
133 return LOAD_STATE_IDLE; | 118 return LOAD_STATE_IDLE; |
134 } | 119 } |
135 } | 120 } |
136 | 121 |
| 122 void HttpStreamFactoryImpl::Job::MarkAsAlternate(const GURL& original_url) { |
| 123 DCHECK(!original_url_.get()); |
| 124 original_url_.reset(new GURL(original_url)); |
| 125 } |
| 126 |
| 127 void HttpStreamFactoryImpl::Job::WaitFor(Job* job) { |
| 128 DCHECK_EQ(STATE_NONE, next_state_); |
| 129 DCHECK_EQ(STATE_NONE, job->next_state_); |
| 130 DCHECK(!blocking_job_); |
| 131 DCHECK(!job->dependent_job_); |
| 132 blocking_job_ = job; |
| 133 job->dependent_job_ = this; |
| 134 } |
| 135 |
| 136 void HttpStreamFactoryImpl::Job::Resume(Job* job) { |
| 137 DCHECK_EQ(blocking_job_, job); |
| 138 blocking_job_ = NULL; |
| 139 |
| 140 // We know we're blocked if the next_state_ is STATE_WAIT_FOR_JOB_COMPLETE. |
| 141 // Unblock |this|. |
| 142 if (next_state_ == STATE_WAIT_FOR_JOB_COMPLETE) { |
| 143 MessageLoop::current()->PostTask( |
| 144 FROM_HERE, |
| 145 method_factory_.NewRunnableMethod( |
| 146 &HttpStreamFactoryImpl::Job::OnIOComplete, OK)); |
| 147 } |
| 148 } |
| 149 |
137 void HttpStreamFactoryImpl::Job::Orphan(const Request* request) { | 150 void HttpStreamFactoryImpl::Job::Orphan(const Request* request) { |
138 DCHECK_EQ(request_, request); | 151 DCHECK_EQ(request_, request); |
139 request_ = NULL; | 152 request_ = NULL; |
140 } | 153 // We've been orphaned, but there's a job we're blocked on. Don't bother |
141 | 154 // racing, just cancel ourself. |
142 bool HttpStreamFactoryImpl::Job::was_alternate_protocol_available() const { | 155 if (blocking_job_) { |
143 return was_alternate_protocol_available_; | 156 DCHECK(blocking_job_->dependent_job_); |
| 157 blocking_job_->dependent_job_ = NULL; |
| 158 blocking_job_ = NULL; |
| 159 stream_factory_->OnOrphanedJobComplete(this); |
| 160 } |
144 } | 161 } |
145 | 162 |
146 bool HttpStreamFactoryImpl::Job::was_npn_negotiated() const { | 163 bool HttpStreamFactoryImpl::Job::was_npn_negotiated() const { |
147 return was_npn_negotiated_; | 164 return was_npn_negotiated_; |
148 } | 165 } |
149 | 166 |
150 bool HttpStreamFactoryImpl::Job::using_spdy() const { | 167 bool HttpStreamFactoryImpl::Job::using_spdy() const { |
151 return using_spdy_; | 168 return using_spdy_; |
152 } | 169 } |
153 | 170 |
(...skipping 13 matching lines...) Expand all Loading... |
167 static_cast<SSLClientSocket*>(connection_->socket()); | 184 static_cast<SSLClientSocket*>(connection_->socket()); |
168 ssl_socket->GetSSLInfo(&ssl_info_); | 185 ssl_socket->GetSSLInfo(&ssl_info_); |
169 } | 186 } |
170 | 187 |
171 void HttpStreamFactoryImpl::Job::OnStreamReadyCallback() { | 188 void HttpStreamFactoryImpl::Job::OnStreamReadyCallback() { |
172 DCHECK(stream_.get()); | 189 DCHECK(stream_.get()); |
173 DCHECK(!IsPreconnecting()); | 190 DCHECK(!IsPreconnecting()); |
174 if (IsOrphaned()) { | 191 if (IsOrphaned()) { |
175 stream_factory_->OnOrphanedJobComplete(this); | 192 stream_factory_->OnOrphanedJobComplete(this); |
176 } else { | 193 } else { |
177 request_->Complete(was_alternate_protocol_available(), | 194 request_->Complete(was_npn_negotiated(), |
178 was_npn_negotiated(), | |
179 using_spdy(), | 195 using_spdy(), |
180 net_log_.source()); | 196 net_log_.source()); |
181 request_->OnStreamReady(this, ssl_config_, proxy_info_, stream_.release()); | 197 request_->OnStreamReady(this, ssl_config_, proxy_info_, stream_.release()); |
182 } | 198 } |
183 // |this| may be deleted after this call. | 199 // |this| may be deleted after this call. |
184 } | 200 } |
185 | 201 |
186 void HttpStreamFactoryImpl::Job::OnSpdySessionReadyCallback() { | 202 void HttpStreamFactoryImpl::Job::OnSpdySessionReadyCallback() { |
187 DCHECK(!stream_.get()); | 203 DCHECK(!stream_.get()); |
188 DCHECK(!IsPreconnecting()); | 204 DCHECK(!IsPreconnecting()); |
189 DCHECK(using_spdy()); | 205 DCHECK(using_spdy()); |
190 DCHECK(new_spdy_session_); | 206 DCHECK(new_spdy_session_); |
191 scoped_refptr<SpdySession> spdy_session = new_spdy_session_; | 207 scoped_refptr<SpdySession> spdy_session = new_spdy_session_; |
192 new_spdy_session_ = NULL; | 208 new_spdy_session_ = NULL; |
193 if (IsOrphaned()) { | 209 if (IsOrphaned()) { |
194 stream_factory_->OnSpdySessionReady( | 210 stream_factory_->OnSpdySessionReady( |
195 spdy_session, spdy_session_direct_, ssl_config_, proxy_info_, | 211 spdy_session, spdy_session_direct_, ssl_config_, proxy_info_, |
196 was_alternate_protocol_available(), was_npn_negotiated(), | 212 was_npn_negotiated(), using_spdy(), net_log_.source()); |
197 using_spdy(), net_log_.source()); | |
198 stream_factory_->OnOrphanedJobComplete(this); | 213 stream_factory_->OnOrphanedJobComplete(this); |
199 } else { | 214 } else { |
200 request_->OnSpdySessionReady(this, spdy_session, spdy_session_direct_); | 215 request_->OnSpdySessionReady(this, spdy_session, spdy_session_direct_); |
201 } | 216 } |
202 // |this| may be deleted after this call. | 217 // |this| may be deleted after this call. |
203 } | 218 } |
204 | 219 |
205 void HttpStreamFactoryImpl::Job::OnStreamFailedCallback(int result) { | 220 void HttpStreamFactoryImpl::Job::OnStreamFailedCallback(int result) { |
206 DCHECK(!IsPreconnecting()); | 221 DCHECK(!IsPreconnecting()); |
207 if (IsOrphaned()) | 222 if (IsOrphaned()) |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 request_->OnHttpsProxyTunnelResponse( | 268 request_->OnHttpsProxyTunnelResponse( |
254 this, response_info, ssl_config_, proxy_info_, stream); | 269 this, response_info, ssl_config_, proxy_info_, stream); |
255 // |this| may be deleted after this call. | 270 // |this| may be deleted after this call. |
256 } | 271 } |
257 | 272 |
258 void HttpStreamFactoryImpl::Job::OnPreconnectsComplete() { | 273 void HttpStreamFactoryImpl::Job::OnPreconnectsComplete() { |
259 DCHECK(!request_); | 274 DCHECK(!request_); |
260 if (new_spdy_session_) { | 275 if (new_spdy_session_) { |
261 stream_factory_->OnSpdySessionReady( | 276 stream_factory_->OnSpdySessionReady( |
262 new_spdy_session_, spdy_session_direct_, ssl_config_, | 277 new_spdy_session_, spdy_session_direct_, ssl_config_, |
263 proxy_info_, was_alternate_protocol_available(), | 278 proxy_info_, was_npn_negotiated(), using_spdy(), net_log_.source()); |
264 was_npn_negotiated(), using_spdy(), net_log_.source()); | |
265 } | 279 } |
266 stream_factory_->OnPreconnectsComplete(this); | 280 stream_factory_->OnPreconnectsComplete(this); |
267 // |this| may be deleted after this call. | 281 // |this| may be deleted after this call. |
268 } | 282 } |
269 | 283 |
270 void HttpStreamFactoryImpl::Job::OnIOComplete(int result) { | 284 void HttpStreamFactoryImpl::Job::OnIOComplete(int result) { |
271 RunLoop(result); | 285 RunLoop(result); |
272 } | 286 } |
273 | 287 |
274 int HttpStreamFactoryImpl::Job::RunLoop(int result) { | 288 int HttpStreamFactoryImpl::Job::RunLoop(int result) { |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
378 State state = next_state_; | 392 State state = next_state_; |
379 next_state_ = STATE_NONE; | 393 next_state_ = STATE_NONE; |
380 switch (state) { | 394 switch (state) { |
381 case STATE_RESOLVE_PROXY: | 395 case STATE_RESOLVE_PROXY: |
382 DCHECK_EQ(OK, rv); | 396 DCHECK_EQ(OK, rv); |
383 rv = DoResolveProxy(); | 397 rv = DoResolveProxy(); |
384 break; | 398 break; |
385 case STATE_RESOLVE_PROXY_COMPLETE: | 399 case STATE_RESOLVE_PROXY_COMPLETE: |
386 rv = DoResolveProxyComplete(rv); | 400 rv = DoResolveProxyComplete(rv); |
387 break; | 401 break; |
| 402 case STATE_WAIT_FOR_JOB: |
| 403 DCHECK_EQ(OK, rv); |
| 404 rv = DoWaitForJob(); |
| 405 break; |
| 406 case STATE_WAIT_FOR_JOB_COMPLETE: |
| 407 rv = DoWaitForJobComplete(rv); |
| 408 break; |
388 case STATE_INIT_CONNECTION: | 409 case STATE_INIT_CONNECTION: |
389 DCHECK_EQ(OK, rv); | 410 DCHECK_EQ(OK, rv); |
390 rv = DoInitConnection(); | 411 rv = DoInitConnection(); |
391 break; | 412 break; |
392 case STATE_INIT_CONNECTION_COMPLETE: | 413 case STATE_INIT_CONNECTION_COMPLETE: |
393 rv = DoInitConnectionComplete(rv); | 414 rv = DoInitConnectionComplete(rv); |
394 break; | 415 break; |
395 case STATE_WAITING_USER_ACTION: | 416 case STATE_WAITING_USER_ACTION: |
396 rv = DoWaitingUserAction(rv); | 417 rv = DoWaitingUserAction(rv); |
397 break; | 418 break; |
(...skipping 13 matching lines...) Expand all Loading... |
411 break; | 432 break; |
412 default: | 433 default: |
413 NOTREACHED() << "bad state"; | 434 NOTREACHED() << "bad state"; |
414 rv = ERR_FAILED; | 435 rv = ERR_FAILED; |
415 break; | 436 break; |
416 } | 437 } |
417 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); | 438 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); |
418 return rv; | 439 return rv; |
419 } | 440 } |
420 | 441 |
421 int HttpStreamFactoryImpl::Job::StartInternal( | 442 int HttpStreamFactoryImpl::Job::StartInternal() { |
422 const HttpRequestInfo& request_info, | |
423 const SSLConfig& ssl_config, | |
424 const BoundNetLog& net_log) { | |
425 CHECK_EQ(STATE_NONE, next_state_); | 443 CHECK_EQ(STATE_NONE, next_state_); |
426 request_info_ = request_info; | |
427 ssl_config_ = ssl_config; | |
428 net_log_ = BoundNetLog::Make(net_log.net_log(), | |
429 NetLog::SOURCE_HTTP_STREAM_JOB); | |
430 net_log_.BeginEvent(NetLog::TYPE_HTTP_STREAM_JOB, | 444 net_log_.BeginEvent(NetLog::TYPE_HTTP_STREAM_JOB, |
431 make_scoped_refptr(new NetLogStringParameter( | 445 make_scoped_refptr(new NetLogStringParameter( |
432 "url", request_info.url.GetOrigin().spec()))); | 446 "url", request_info_.url.GetOrigin().spec()))); |
433 next_state_ = STATE_RESOLVE_PROXY; | 447 next_state_ = STATE_RESOLVE_PROXY; |
434 int rv = RunLoop(OK); | 448 int rv = RunLoop(OK); |
435 DCHECK_EQ(ERR_IO_PENDING, rv); | 449 DCHECK_EQ(ERR_IO_PENDING, rv); |
436 return rv; | 450 return rv; |
437 } | 451 } |
438 | 452 |
439 int HttpStreamFactoryImpl::Job::DoResolveProxy() { | 453 int HttpStreamFactoryImpl::Job::DoResolveProxy() { |
440 DCHECK(!pac_request_); | 454 DCHECK(!pac_request_); |
441 | 455 |
442 next_state_ = STATE_RESOLVE_PROXY_COMPLETE; | 456 next_state_ = STATE_RESOLVE_PROXY_COMPLETE; |
443 | 457 |
444 // |endpoint_| indicates the final destination endpoint. | 458 origin_ = HostPortPair(request_info_.url.HostNoBrackets(), |
445 endpoint_ = HostPortPair(request_info_.url.HostNoBrackets(), | 459 request_info_.url.EffectiveIntPort()); |
446 request_info_.url.EffectiveIntPort()); | |
447 | |
448 // Extra URL we might be attempting to resolve to. | |
449 GURL alternate_endpoint_url = request_info_.url; | |
450 | |
451 // Tracks whether we are using |request_.url| or |alternate_endpoint_url|. | |
452 const GURL *curr_endpoint_url = &request_info_.url; | |
453 | |
454 alternate_endpoint_url = | |
455 HttpStreamFactory::ApplyHostMappingRules( | |
456 alternate_endpoint_url, &endpoint_); | |
457 | |
458 const HttpAlternateProtocols& alternate_protocols = | |
459 session_->alternate_protocols(); | |
460 if (HttpStreamFactory::spdy_enabled() && | |
461 alternate_protocols.HasAlternateProtocolFor(endpoint_)) { | |
462 was_alternate_protocol_available_ = true; | |
463 if (alternate_protocol_mode_ == kUnspecified) { | |
464 HttpAlternateProtocols::PortProtocolPair alternate = | |
465 alternate_protocols.GetAlternateProtocolFor(endpoint_); | |
466 if (alternate.protocol != HttpAlternateProtocols::BROKEN) { | |
467 DCHECK_LE(HttpAlternateProtocols::NPN_SPDY_1, alternate.protocol); | |
468 DCHECK_GT(HttpAlternateProtocols::NUM_ALTERNATE_PROTOCOLS, | |
469 alternate.protocol); | |
470 endpoint_.set_port(alternate.port); | |
471 alternate_protocol_ = alternate.protocol; | |
472 alternate_protocol_mode_ = kUsingAlternateProtocol; | |
473 alternate_endpoint_url = UpgradeUrlToHttps(*curr_endpoint_url); | |
474 curr_endpoint_url = &alternate_endpoint_url; | |
475 } | |
476 } | |
477 } | |
478 | 460 |
479 if (request_info_.load_flags & LOAD_BYPASS_PROXY) { | 461 if (request_info_.load_flags & LOAD_BYPASS_PROXY) { |
480 proxy_info_.UseDirect(); | 462 proxy_info_.UseDirect(); |
481 return OK; | 463 return OK; |
482 } | 464 } |
483 | 465 |
484 return session_->proxy_service()->ResolveProxy( | 466 return session_->proxy_service()->ResolveProxy( |
485 *curr_endpoint_url, &proxy_info_, &io_callback_, &pac_request_, | 467 request_info_.url, &proxy_info_, &io_callback_, &pac_request_, |
486 net_log_); | 468 net_log_); |
487 } | 469 } |
488 | 470 |
489 int HttpStreamFactoryImpl::Job::DoResolveProxyComplete(int result) { | 471 int HttpStreamFactoryImpl::Job::DoResolveProxyComplete(int result) { |
490 pac_request_ = NULL; | 472 pac_request_ = NULL; |
491 | 473 |
492 if (result != OK) | 474 if (result == OK) { |
493 return result; | 475 // Remove unsupported proxies from the list. |
| 476 proxy_info_.RemoveProxiesWithoutScheme( |
| 477 ProxyServer::SCHEME_DIRECT | |
| 478 ProxyServer::SCHEME_HTTP | ProxyServer::SCHEME_HTTPS | |
| 479 ProxyServer::SCHEME_SOCKS4 | ProxyServer::SCHEME_SOCKS5); |
494 | 480 |
495 // TODO(mbelshe): consider retrying ResolveProxy if we came here via use of | 481 if (proxy_info_.is_empty()) { |
496 // AlternateProtocol. | 482 // No proxies/direct to choose from. This happens when we don't support |
497 | 483 // any of the proxies in the returned list. |
498 // Remove unsupported proxies from the list. | 484 result = ERR_NO_SUPPORTED_PROXIES; |
499 proxy_info_.RemoveProxiesWithoutScheme( | 485 } |
500 ProxyServer::SCHEME_DIRECT | | |
501 ProxyServer::SCHEME_HTTP | ProxyServer::SCHEME_HTTPS | | |
502 ProxyServer::SCHEME_SOCKS4 | ProxyServer::SCHEME_SOCKS5); | |
503 | |
504 if (proxy_info_.is_empty()) { | |
505 // No proxies/direct to choose from. This happens when we don't support any | |
506 // of the proxies in the returned list. | |
507 return ERR_NO_SUPPORTED_PROXIES; | |
508 } | 486 } |
509 | 487 |
| 488 if (result != OK) { |
| 489 if (dependent_job_) |
| 490 dependent_job_->Resume(this); |
| 491 return result; |
| 492 } |
| 493 |
| 494 if (blocking_job_) |
| 495 next_state_ = STATE_WAIT_FOR_JOB; |
| 496 else |
| 497 next_state_ = STATE_INIT_CONNECTION; |
| 498 return OK; |
| 499 } |
| 500 |
| 501 bool HttpStreamFactoryImpl::Job::ShouldForceSpdySSL() const { |
| 502 return force_spdy_always_ && force_spdy_over_ssl_; |
| 503 } |
| 504 |
| 505 bool HttpStreamFactoryImpl::Job::ShouldForceSpdyWithoutSSL() const { |
| 506 return force_spdy_always_ && !force_spdy_over_ssl_; |
| 507 } |
| 508 |
| 509 int HttpStreamFactoryImpl::Job::DoWaitForJob() { |
| 510 DCHECK(blocking_job_); |
| 511 next_state_ = STATE_WAIT_FOR_JOB_COMPLETE; |
| 512 return ERR_IO_PENDING; |
| 513 } |
| 514 |
| 515 int HttpStreamFactoryImpl::Job::DoWaitForJobComplete(int result) { |
| 516 DCHECK(!blocking_job_); |
| 517 DCHECK_EQ(OK, result); |
510 next_state_ = STATE_INIT_CONNECTION; | 518 next_state_ = STATE_INIT_CONNECTION; |
511 return OK; | 519 return OK; |
512 } | 520 } |
513 | 521 |
514 static bool HasSpdyExclusion(const HostPortPair& endpoint) { | |
515 std::list<HostPortPair>* exclusions = | |
516 HttpStreamFactory::forced_spdy_exclusions(); | |
517 if (!exclusions) | |
518 return false; | |
519 | |
520 std::list<HostPortPair>::const_iterator it; | |
521 for (it = exclusions->begin(); it != exclusions->end(); it++) | |
522 if (it->Equals(endpoint)) | |
523 return true; | |
524 return false; | |
525 } | |
526 | |
527 bool HttpStreamFactoryImpl::Job::ShouldForceSpdySSL() { | |
528 bool rv = force_spdy_always_ && force_spdy_over_ssl_; | |
529 return rv && !HasSpdyExclusion(endpoint_); | |
530 } | |
531 | |
532 bool HttpStreamFactoryImpl::Job::ShouldForceSpdyWithoutSSL() { | |
533 bool rv = force_spdy_always_ && !force_spdy_over_ssl_; | |
534 return rv && !HasSpdyExclusion(endpoint_); | |
535 } | |
536 | |
537 int HttpStreamFactoryImpl::Job::DoInitConnection() { | 522 int HttpStreamFactoryImpl::Job::DoInitConnection() { |
| 523 DCHECK(!blocking_job_); |
538 DCHECK(!connection_->is_initialized()); | 524 DCHECK(!connection_->is_initialized()); |
539 DCHECK(proxy_info_.proxy_server().is_valid()); | 525 DCHECK(proxy_info_.proxy_server().is_valid()); |
540 next_state_ = STATE_INIT_CONNECTION_COMPLETE; | 526 next_state_ = STATE_INIT_CONNECTION_COMPLETE; |
541 | 527 |
542 bool want_spdy_over_npn = | 528 using_ssl_ = request_info_.url.SchemeIs("https") || ShouldForceSpdySSL(); |
543 alternate_protocol_mode_ == kUsingAlternateProtocol && | |
544 alternate_protocol_ == HttpAlternateProtocols::NPN_SPDY_2; | |
545 using_ssl_ = request_info_.url.SchemeIs("https") || | |
546 ShouldForceSpdySSL() || want_spdy_over_npn; | |
547 using_spdy_ = false; | 529 using_spdy_ = false; |
548 | 530 |
549 // If spdy has been turned off on-the-fly, then there may be SpdySessions | 531 // Check first if we have a spdy session for this group. If so, then go |
550 // still active. But don't use them unless spdy is currently on. | 532 // straight to using that. |
551 if (HttpStreamFactory::spdy_enabled() && !HasSpdyExclusion(endpoint_)) { | 533 HostPortProxyPair spdy_session_key; |
552 // Check first if we have a spdy session for this group. If so, then go | 534 if (IsHttpsProxyAndHttpUrl()) { |
553 // straight to using that. | 535 spdy_session_key = |
554 HostPortProxyPair spdy_session_key; | 536 HostPortProxyPair(proxy_info_.proxy_server().host_port_pair(), |
555 if (IsHttpsProxyAndHttpUrl()) { | 537 ProxyServer::Direct()); |
556 spdy_session_key = | 538 } else { |
557 HostPortProxyPair(proxy_info_.proxy_server().host_port_pair(), | 539 spdy_session_key = HostPortProxyPair(origin_, proxy_info_.proxy_server()); |
558 ProxyServer::Direct()); | 540 } |
559 } else { | 541 if (session_->spdy_session_pool()->HasSession(spdy_session_key)) { |
560 spdy_session_key = | 542 // If we're preconnecting, but we already have a SpdySession, we don't |
561 HostPortProxyPair(endpoint_, proxy_info_.proxy_server()); | 543 // actually need to preconnect any sockets, so we're done. |
562 } | 544 if (IsPreconnecting()) |
563 if (session_->spdy_session_pool()->HasSession(spdy_session_key)) { | |
564 // If we're preconnecting, but we already have a SpdySession, we don't | |
565 // actually need to preconnect any sockets, so we're done. | |
566 if (IsPreconnecting()) | |
567 return OK; | |
568 using_spdy_ = true; | |
569 next_state_ = STATE_CREATE_STREAM; | |
570 return OK; | 545 return OK; |
571 } else if (request_) { | 546 using_spdy_ = true; |
572 // Update the spdy session key for the request that launched this job. | 547 next_state_ = STATE_CREATE_STREAM; |
573 request_->SetSpdySessionKey(spdy_session_key); | 548 return OK; |
574 } | 549 } else if (request_ && (using_ssl_ || ShouldForceSpdyWithoutSSL())) { |
| 550 // Update the spdy session key for the request that launched this job. |
| 551 request_->SetSpdySessionKey(spdy_session_key); |
| 552 } |
| 553 |
| 554 // OK, there's no available SPDY session. Let |dependent_job_| resume if it's |
| 555 // paused. |
| 556 |
| 557 if (dependent_job_) { |
| 558 dependent_job_->Resume(this); |
| 559 dependent_job_ = NULL; |
575 } | 560 } |
576 | 561 |
577 // Build the string used to uniquely identify connections of this type. | 562 // Build the string used to uniquely identify connections of this type. |
578 // Determine the host and port to connect to. | 563 // Determine the host and port to connect to. |
579 std::string connection_group = endpoint_.ToString(); | 564 std::string connection_group = origin_.ToString(); |
580 DCHECK(!connection_group.empty()); | 565 DCHECK(!connection_group.empty()); |
581 | 566 |
582 if (using_ssl_) | 567 if (using_ssl_) |
583 connection_group = base::StringPrintf("ssl/%s", connection_group.c_str()); | 568 connection_group = base::StringPrintf("ssl/%s", connection_group.c_str()); |
584 | 569 |
585 // If the user is refreshing the page, bypass the host cache. | 570 // If the user is refreshing the page, bypass the host cache. |
586 bool disable_resolver_cache = | 571 bool disable_resolver_cache = |
587 request_info_.load_flags & LOAD_BYPASS_CACHE || | 572 request_info_.load_flags & LOAD_BYPASS_CACHE || |
588 request_info_.load_flags & LOAD_VALIDATE_CACHE || | 573 request_info_.load_flags & LOAD_VALIDATE_CACHE || |
589 request_info_.load_flags & LOAD_DISABLE_CACHE; | 574 request_info_.load_flags & LOAD_DISABLE_CACHE; |
590 | 575 |
591 // Build up the connection parameters. | 576 // Build up the connection parameters. |
592 scoped_refptr<TCPSocketParams> tcp_params; | 577 scoped_refptr<TCPSocketParams> tcp_params; |
593 scoped_refptr<HttpProxySocketParams> http_proxy_params; | 578 scoped_refptr<HttpProxySocketParams> http_proxy_params; |
594 scoped_refptr<SOCKSSocketParams> socks_params; | 579 scoped_refptr<SOCKSSocketParams> socks_params; |
595 scoped_ptr<HostPortPair> proxy_host_port; | 580 scoped_ptr<HostPortPair> proxy_host_port; |
596 | 581 |
597 if (proxy_info_.is_direct()) { | 582 if (proxy_info_.is_direct()) { |
598 tcp_params = new TCPSocketParams(endpoint_, request_info_.priority, | 583 tcp_params = new TCPSocketParams(origin_, request_info_.priority, |
599 request_info_.referrer, | 584 request_info_.referrer, |
600 disable_resolver_cache); | 585 disable_resolver_cache); |
601 } else { | 586 } else { |
602 ProxyServer proxy_server = proxy_info_.proxy_server(); | 587 ProxyServer proxy_server = proxy_info_.proxy_server(); |
603 proxy_host_port.reset(new HostPortPair(proxy_server.host_port_pair())); | 588 proxy_host_port.reset(new HostPortPair(proxy_server.host_port_pair())); |
604 scoped_refptr<TCPSocketParams> proxy_tcp_params( | 589 scoped_refptr<TCPSocketParams> proxy_tcp_params( |
605 new TCPSocketParams(*proxy_host_port, request_info_.priority, | 590 new TCPSocketParams(*proxy_host_port, request_info_.priority, |
606 request_info_.referrer, disable_resolver_cache)); | 591 request_info_.referrer, disable_resolver_cache)); |
607 | 592 |
608 if (proxy_info_.is_http() || proxy_info_.is_https()) { | 593 if (proxy_info_.is_http() || proxy_info_.is_https()) { |
609 GURL authentication_url = request_info_.url; | |
610 if (using_ssl_ && !authentication_url.SchemeIs("https")) { | |
611 // If a proxy tunnel connection needs to be established due to | |
612 // an Alternate-Protocol, the URL needs to be changed to indicate | |
613 // https or digest authentication attempts will fail. | |
614 // For example, suppose the initial request was for | |
615 // "http://www.example.com/index.html". If this is an SSL | |
616 // upgrade due to alternate protocol, the digest authorization | |
617 // should have a uri="www.example.com:443" field rather than a | |
618 // "/index.html" entry, even though the original request URL has not | |
619 // changed. | |
620 authentication_url = UpgradeUrlToHttps(authentication_url); | |
621 } | |
622 establishing_tunnel_ = using_ssl_; | 594 establishing_tunnel_ = using_ssl_; |
623 std::string user_agent; | 595 std::string user_agent; |
624 request_info_.extra_headers.GetHeader(HttpRequestHeaders::kUserAgent, | 596 request_info_.extra_headers.GetHeader(HttpRequestHeaders::kUserAgent, |
625 &user_agent); | 597 &user_agent); |
626 scoped_refptr<SSLSocketParams> ssl_params; | 598 scoped_refptr<SSLSocketParams> ssl_params; |
627 if (proxy_info_.is_https()) { | 599 if (proxy_info_.is_https()) { |
628 // Set ssl_params, and unset proxy_tcp_params | 600 // Set ssl_params, and unset proxy_tcp_params |
629 ssl_params = GenerateSSLParams(proxy_tcp_params, NULL, NULL, | 601 ssl_params = GenerateSSLParams(proxy_tcp_params, NULL, NULL, |
630 ProxyServer::SCHEME_DIRECT, | 602 ProxyServer::SCHEME_DIRECT, |
631 *proxy_host_port.get(), | 603 *proxy_host_port.get(), |
632 want_spdy_over_npn); | 604 original_url_.get() ? true : false); |
633 proxy_tcp_params = NULL; | 605 proxy_tcp_params = NULL; |
634 } | 606 } |
635 | 607 |
636 http_proxy_params = | 608 http_proxy_params = |
637 new HttpProxySocketParams(proxy_tcp_params, | 609 new HttpProxySocketParams(proxy_tcp_params, |
638 ssl_params, | 610 ssl_params, |
639 authentication_url, | 611 request_info_.url, |
640 user_agent, | 612 user_agent, |
641 endpoint_, | 613 origin_, |
642 session_->http_auth_cache(), | 614 session_->http_auth_cache(), |
643 session_->http_auth_handler_factory(), | 615 session_->http_auth_handler_factory(), |
644 session_->spdy_session_pool(), | 616 session_->spdy_session_pool(), |
645 using_ssl_); | 617 using_ssl_); |
646 } else { | 618 } else { |
647 DCHECK(proxy_info_.is_socks()); | 619 DCHECK(proxy_info_.is_socks()); |
648 char socks_version; | 620 char socks_version; |
649 if (proxy_server.scheme() == ProxyServer::SCHEME_SOCKS5) | 621 if (proxy_server.scheme() == ProxyServer::SCHEME_SOCKS5) |
650 socks_version = '5'; | 622 socks_version = '5'; |
651 else | 623 else |
652 socks_version = '4'; | 624 socks_version = '4'; |
653 connection_group = base::StringPrintf( | 625 connection_group = base::StringPrintf( |
654 "socks%c/%s", socks_version, connection_group.c_str()); | 626 "socks%c/%s", socks_version, connection_group.c_str()); |
655 | 627 |
656 socks_params = new SOCKSSocketParams(proxy_tcp_params, | 628 socks_params = new SOCKSSocketParams(proxy_tcp_params, |
657 socks_version == '5', | 629 socks_version == '5', |
658 endpoint_, | 630 origin_, |
659 request_info_.priority, | 631 request_info_.priority, |
660 request_info_.referrer); | 632 request_info_.referrer); |
661 } | 633 } |
662 } | 634 } |
663 | 635 |
664 // Deal with SSL - which layers on top of any given proxy. | 636 // Deal with SSL - which layers on top of any given proxy. |
665 if (using_ssl_) { | 637 if (using_ssl_) { |
666 scoped_refptr<SSLSocketParams> ssl_params = | 638 scoped_refptr<SSLSocketParams> ssl_params = |
667 GenerateSSLParams(tcp_params, http_proxy_params, socks_params, | 639 GenerateSSLParams(tcp_params, http_proxy_params, socks_params, |
668 proxy_info_.proxy_server().scheme(), | 640 proxy_info_.proxy_server().scheme(), |
669 HostPortPair::FromURL(request_info_.url), | 641 origin_, original_url_.get() ? true : false); |
670 want_spdy_over_npn); | |
671 SSLClientSocketPool* ssl_pool = NULL; | 642 SSLClientSocketPool* ssl_pool = NULL; |
672 if (proxy_info_.is_direct()) | 643 if (proxy_info_.is_direct()) |
673 ssl_pool = session_->ssl_socket_pool(); | 644 ssl_pool = session_->ssl_socket_pool(); |
674 else | 645 else |
675 ssl_pool = session_->GetSocketPoolForSSLWithProxy(*proxy_host_port); | 646 ssl_pool = session_->GetSocketPoolForSSLWithProxy(*proxy_host_port); |
676 | 647 |
677 if (IsPreconnecting()) { | 648 if (IsPreconnecting()) { |
678 RequestSocketsForPool(ssl_pool, connection_group, ssl_params, | 649 RequestSocketsForPool(ssl_pool, connection_group, ssl_params, |
679 num_streams_, net_log_); | 650 num_streams_, net_log_); |
680 return OK; | 651 return OK; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
727 request_info_.priority, &io_callback_, | 698 request_info_.priority, &io_callback_, |
728 pool, net_log_); | 699 pool, net_log_); |
729 } | 700 } |
730 | 701 |
731 int HttpStreamFactoryImpl::Job::DoInitConnectionComplete(int result) { | 702 int HttpStreamFactoryImpl::Job::DoInitConnectionComplete(int result) { |
732 if (IsPreconnecting()) { | 703 if (IsPreconnecting()) { |
733 DCHECK_EQ(OK, result); | 704 DCHECK_EQ(OK, result); |
734 return OK; | 705 return OK; |
735 } | 706 } |
736 | 707 |
| 708 // TODO(willchan): Make this a bit more exact. Maybe there are recoverable |
| 709 // errors, such as ignoring certificate errors for Alternate-Protocol. |
| 710 if (result < 0 && dependent_job_) { |
| 711 dependent_job_->Resume(this); |
| 712 dependent_job_ = NULL; |
| 713 } |
| 714 |
737 // |result| may be the result of any of the stacked pools. The following | 715 // |result| may be the result of any of the stacked pools. The following |
738 // logic is used when determining how to interpret an error. | 716 // logic is used when determining how to interpret an error. |
739 // If |result| < 0: | 717 // If |result| < 0: |
740 // and connection_->socket() != NULL, then the SSL handshake ran and it | 718 // and connection_->socket() != NULL, then the SSL handshake ran and it |
741 // is a potentially recoverable error. | 719 // is a potentially recoverable error. |
742 // and connection_->socket == NULL and connection_->is_ssl_error() is true, | 720 // and connection_->socket == NULL and connection_->is_ssl_error() is true, |
743 // then the SSL handshake ran with an unrecoverable error. | 721 // then the SSL handshake ran with an unrecoverable error. |
744 // otherwise, the error came from one of the other pools. | 722 // otherwise, the error came from one of the other pools. |
745 bool ssl_started = using_ssl_ && (result == OK || connection_->socket() || | 723 bool ssl_started = using_ssl_ && (result == OK || connection_->socket() || |
746 connection_->is_ssl_error()); | 724 connection_->is_ssl_error()); |
(...skipping 28 matching lines...) Expand all Loading... |
775 // Other state (i.e. |using_ssl_|) suggests that |connection_| will have an | 753 // Other state (i.e. |using_ssl_|) suggests that |connection_| will have an |
776 // SSL socket, but there was an error before that could happen. This | 754 // SSL socket, but there was an error before that could happen. This |
777 // puts the in progress HttpProxy socket into |connection_| in order to | 755 // puts the in progress HttpProxy socket into |connection_| in order to |
778 // complete the auth (or read the response body). The tunnel restart code | 756 // complete the auth (or read the response body). The tunnel restart code |
779 // is careful to remove it before returning control to the rest of this | 757 // is careful to remove it before returning control to the rest of this |
780 // class. | 758 // class. |
781 connection_.reset(connection_->release_pending_http_proxy_connection()); | 759 connection_.reset(connection_->release_pending_http_proxy_connection()); |
782 return result; | 760 return result; |
783 } | 761 } |
784 | 762 |
785 if ((!ssl_started && result < 0 && | 763 if (!ssl_started && result < 0 && original_url_.get()) { |
786 alternate_protocol_mode_ == kUsingAlternateProtocol) || | |
787 result == ERR_NPN_NEGOTIATION_FAILED) { | |
788 // Mark the alternate protocol as broken and fallback. | 764 // Mark the alternate protocol as broken and fallback. |
789 MarkBrokenAlternateProtocolAndFallback(); | 765 session_->mutable_alternate_protocols()->MarkBrokenAlternateProtocolFor( |
790 return OK; | 766 HostPortPair::FromURL(*original_url_)); |
| 767 return result; |
791 } | 768 } |
792 | 769 |
793 if (result < 0 && !ssl_started) | 770 if (result < 0 && !ssl_started) |
794 return ReconsiderProxyAfterError(result); | 771 return ReconsiderProxyAfterError(result); |
795 establishing_tunnel_ = false; | 772 establishing_tunnel_ = false; |
796 | 773 |
797 if (connection_->socket()) { | 774 if (connection_->socket()) { |
798 LogHttpConnectedMetrics(*connection_); | 775 LogHttpConnectedMetrics(*connection_); |
799 | 776 |
800 // We officially have a new connection. Record the type. | 777 // We officially have a new connection. Record the type. |
801 if (!connection_->is_reused()) { | 778 if (!connection_->is_reused()) { |
802 ConnectionType type = using_spdy_ ? CONNECTION_SPDY : CONNECTION_HTTP; | 779 ConnectionType type = using_spdy_ ? CONNECTION_SPDY : CONNECTION_HTTP; |
803 UpdateConnectionTypeHistograms(type); | 780 UpdateConnectionTypeHistograms(type); |
804 } | 781 } |
805 } | 782 } |
806 | 783 |
807 // Handle SSL errors below. | 784 // Handle SSL errors below. |
808 if (using_ssl_) { | 785 if (using_ssl_) { |
809 DCHECK(ssl_started); | 786 DCHECK(ssl_started); |
810 if (IsCertificateError(result)) { | 787 if (IsCertificateError(result)) { |
811 if (using_spdy_ && request_info_.url.SchemeIs("http")) { | 788 if (using_spdy_ && original_url_.get() && |
| 789 original_url_->SchemeIs("http")) { |
812 // We ignore certificate errors for http over spdy. | 790 // We ignore certificate errors for http over spdy. |
813 spdy_certificate_error_ = result; | 791 spdy_certificate_error_ = result; |
814 result = OK; | 792 result = OK; |
815 } else { | 793 } else { |
816 result = HandleCertificateError(result); | 794 result = HandleCertificateError(result); |
817 if (result == OK && !connection_->socket()->IsConnectedAndIdle()) { | 795 if (result == OK && !connection_->socket()->IsConnectedAndIdle()) { |
818 ReturnToStateInitConnection(true /* close connection */); | 796 ReturnToStateInitConnection(true /* close connection */); |
819 return result; | 797 return result; |
820 } | 798 } |
821 } | 799 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
855 using_proxy)); | 833 using_proxy)); |
856 return OK; | 834 return OK; |
857 } | 835 } |
858 | 836 |
859 CHECK(!stream_.get()); | 837 CHECK(!stream_.get()); |
860 | 838 |
861 bool direct = true; | 839 bool direct = true; |
862 SpdySessionPool* spdy_pool = session_->spdy_session_pool(); | 840 SpdySessionPool* spdy_pool = session_->spdy_session_pool(); |
863 scoped_refptr<SpdySession> spdy_session; | 841 scoped_refptr<SpdySession> spdy_session; |
864 | 842 |
865 HostPortProxyPair pair(endpoint_, proxy_server); | 843 HostPortProxyPair pair(origin_, proxy_server); |
866 if (spdy_pool->HasSession(pair)) { | 844 if (spdy_pool->HasSession(pair)) { |
867 // We have a SPDY session to the origin server. This might be a direct | 845 // We have a SPDY session to the origin server. This might be a direct |
868 // connection, or it might be a SPDY session through an HTTP or HTTPS proxy. | 846 // connection, or it might be a SPDY session through an HTTP or HTTPS proxy. |
869 spdy_session = spdy_pool->Get(pair, net_log_); | 847 spdy_session = spdy_pool->Get(pair, net_log_); |
870 } else if (IsHttpsProxyAndHttpUrl()) { | 848 } else if (IsHttpsProxyAndHttpUrl()) { |
871 // If we don't have a direct SPDY session, and we're using an HTTPS | 849 // If we don't have a direct SPDY session, and we're using an HTTPS |
872 // proxy, then we might have a SPDY session to the proxy. | 850 // proxy, then we might have a SPDY session to the proxy. |
873 pair = HostPortProxyPair(proxy_server.host_port_pair(), | 851 pair = HostPortProxyPair(proxy_server.host_port_pair(), |
874 ProxyServer::Direct()); | 852 ProxyServer::Direct()); |
875 if (spdy_pool->HasSession(pair)) { | 853 if (spdy_pool->HasSession(pair)) { |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
959 | 937 |
960 void HttpStreamFactoryImpl::Job::SetSocketMotivation() { | 938 void HttpStreamFactoryImpl::Job::SetSocketMotivation() { |
961 if (request_info_.motivation == HttpRequestInfo::PRECONNECT_MOTIVATED) | 939 if (request_info_.motivation == HttpRequestInfo::PRECONNECT_MOTIVATED) |
962 connection_->socket()->SetSubresourceSpeculation(); | 940 connection_->socket()->SetSubresourceSpeculation(); |
963 else if (request_info_.motivation == HttpRequestInfo::OMNIBOX_MOTIVATED) | 941 else if (request_info_.motivation == HttpRequestInfo::OMNIBOX_MOTIVATED) |
964 connection_->socket()->SetOmniboxSpeculation(); | 942 connection_->socket()->SetOmniboxSpeculation(); |
965 // TODO(mbelshe): Add other motivations (like EARLY_LOAD_MOTIVATED). | 943 // TODO(mbelshe): Add other motivations (like EARLY_LOAD_MOTIVATED). |
966 } | 944 } |
967 | 945 |
968 bool HttpStreamFactoryImpl::Job::IsHttpsProxyAndHttpUrl() { | 946 bool HttpStreamFactoryImpl::Job::IsHttpsProxyAndHttpUrl() { |
969 return proxy_info_.is_https() && request_info_.url.SchemeIs("http"); | 947 if (!proxy_info_.is_https()) |
| 948 return false; |
| 949 if (original_url_.get()) { |
| 950 // We currently only support Alternate-Protocol where the original scheme |
| 951 // is http. |
| 952 DCHECK(original_url_->SchemeIs("http")); |
| 953 return original_url_->SchemeIs("http"); |
| 954 } |
| 955 return request_info_.url.SchemeIs("http"); |
970 } | 956 } |
971 | 957 |
972 // Returns a newly create SSLSocketParams, and sets several | 958 // Returns a newly create SSLSocketParams, and sets several |
973 // fields of ssl_config_. | 959 // fields of ssl_config_. |
974 scoped_refptr<SSLSocketParams> HttpStreamFactoryImpl::Job::GenerateSSLParams( | 960 scoped_refptr<SSLSocketParams> HttpStreamFactoryImpl::Job::GenerateSSLParams( |
975 scoped_refptr<TCPSocketParams> tcp_params, | 961 scoped_refptr<TCPSocketParams> tcp_params, |
976 scoped_refptr<HttpProxySocketParams> http_proxy_params, | 962 scoped_refptr<HttpProxySocketParams> http_proxy_params, |
977 scoped_refptr<SOCKSSocketParams> socks_params, | 963 scoped_refptr<SOCKSSocketParams> socks_params, |
978 ProxyServer::Scheme proxy_scheme, | 964 ProxyServer::Scheme proxy_scheme, |
979 const HostPortPair& host_and_port, | 965 const HostPortPair& origin_server, |
980 bool want_spdy_over_npn) { | 966 bool want_spdy_over_npn) { |
981 | 967 |
982 if (stream_factory_->IsTLSIntolerantServer(request_info_.url)) { | 968 if (stream_factory_->IsTLSIntolerantServer(origin_server)) { |
983 LOG(WARNING) << "Falling back to SSLv3 because host is TLS intolerant: " | 969 LOG(WARNING) << "Falling back to SSLv3 because host is TLS intolerant: " |
984 << GetHostAndPort(request_info_.url); | 970 << origin_server.ToString(); |
985 ssl_config_.ssl3_fallback = true; | 971 ssl_config_.ssl3_fallback = true; |
986 ssl_config_.tls1_enabled = false; | 972 ssl_config_.tls1_enabled = false; |
987 } | 973 } |
988 | 974 |
989 if (proxy_info_.is_https() && ssl_config_.send_client_cert) { | 975 if (proxy_info_.is_https() && ssl_config_.send_client_cert) { |
990 // When connecting through an HTTPS proxy, disable TLS False Start so | 976 // When connecting through an HTTPS proxy, disable TLS False Start so |
991 // that client authentication errors can be distinguished between those | 977 // that client authentication errors can be distinguished between those |
992 // originating from the proxy server (ERR_PROXY_CONNECTION_FAILED) and | 978 // originating from the proxy server (ERR_PROXY_CONNECTION_FAILED) and |
993 // those originating from the endpoint (ERR_SSL_PROTOCOL_ERROR / | 979 // those originating from the endpoint (ERR_SSL_PROTOCOL_ERROR / |
994 // ERR_BAD_SSL_CLIENT_AUTH_CERT). | 980 // ERR_BAD_SSL_CLIENT_AUTH_CERT). |
(...skipping 12 matching lines...) Expand all Loading... |
1007 if (request_info_.load_flags & LOAD_VERIFY_EV_CERT) | 993 if (request_info_.load_flags & LOAD_VERIFY_EV_CERT) |
1008 ssl_config_.verify_ev_cert = true; | 994 ssl_config_.verify_ev_cert = true; |
1009 | 995 |
1010 if (proxy_info_.proxy_server().scheme() == ProxyServer::SCHEME_HTTP || | 996 if (proxy_info_.proxy_server().scheme() == ProxyServer::SCHEME_HTTP || |
1011 proxy_info_.proxy_server().scheme() == ProxyServer::SCHEME_HTTPS) { | 997 proxy_info_.proxy_server().scheme() == ProxyServer::SCHEME_HTTPS) { |
1012 ssl_config_.mitm_proxies_allowed = true; | 998 ssl_config_.mitm_proxies_allowed = true; |
1013 } | 999 } |
1014 | 1000 |
1015 scoped_refptr<SSLSocketParams> ssl_params( | 1001 scoped_refptr<SSLSocketParams> ssl_params( |
1016 new SSLSocketParams(tcp_params, socks_params, http_proxy_params, | 1002 new SSLSocketParams(tcp_params, socks_params, http_proxy_params, |
1017 proxy_scheme, host_and_port, | 1003 proxy_scheme, origin_server, |
1018 ssl_config_, load_flags, | 1004 ssl_config_, load_flags, |
1019 ShouldForceSpdySSL(), | 1005 ShouldForceSpdySSL(), |
1020 want_spdy_over_npn)); | 1006 want_spdy_over_npn)); |
1021 | 1007 |
1022 return ssl_params; | 1008 return ssl_params; |
1023 } | 1009 } |
1024 | 1010 |
1025 | 1011 |
1026 void HttpStreamFactoryImpl::Job::MarkBrokenAlternateProtocolAndFallback() { | |
1027 // We have to: | |
1028 // * Reset the endpoint to be the unmodified URL specified destination. | |
1029 // * Mark the endpoint as broken so we don't try again. | |
1030 // * Set the alternate protocol mode to kDoNotUseAlternateProtocol so we | |
1031 // ignore future Alternate-Protocol headers from the HostPortPair. | |
1032 // * Reset the connection and go back to STATE_INIT_CONNECTION. | |
1033 | |
1034 endpoint_ = HostPortPair(request_info_.url.HostNoBrackets(), | |
1035 request_info_.url.EffectiveIntPort()); | |
1036 | |
1037 session_->mutable_alternate_protocols()->MarkBrokenAlternateProtocolFor( | |
1038 endpoint_); | |
1039 | |
1040 alternate_protocol_mode_ = kDoNotUseAlternateProtocol; | |
1041 ReturnToStateInitConnection(false /* close connection */); | |
1042 } | |
1043 | |
1044 int HttpStreamFactoryImpl::Job::ReconsiderProxyAfterError(int error) { | 1012 int HttpStreamFactoryImpl::Job::ReconsiderProxyAfterError(int error) { |
1045 DCHECK(!pac_request_); | 1013 DCHECK(!pac_request_); |
1046 | 1014 |
1047 // A failure to resolve the hostname or any error related to establishing a | 1015 // A failure to resolve the hostname or any error related to establishing a |
1048 // TCP connection could be grounds for trying a new proxy configuration. | 1016 // TCP connection could be grounds for trying a new proxy configuration. |
1049 // | 1017 // |
1050 // Why do this when a hostname cannot be resolved? Some URLs only make sense | 1018 // Why do this when a hostname cannot be resolved? Some URLs only make sense |
1051 // to proxy servers. The hostname in those URLs might fail to resolve if we | 1019 // to proxy servers. The hostname in those URLs might fail to resolve if we |
1052 // are still using a non-proxy config. We need to check if a proxy config | 1020 // are still using a non-proxy config. We need to check if a proxy config |
1053 // now exists that corresponds to a proxy server that could load the URL. | 1021 // now exists that corresponds to a proxy server that could load the URL. |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1178 bool HttpStreamFactoryImpl::Job::IsPreconnecting() const { | 1146 bool HttpStreamFactoryImpl::Job::IsPreconnecting() const { |
1179 DCHECK_GE(num_streams_, 0); | 1147 DCHECK_GE(num_streams_, 0); |
1180 return num_streams_ > 0; | 1148 return num_streams_ > 0; |
1181 } | 1149 } |
1182 | 1150 |
1183 bool HttpStreamFactoryImpl::Job::IsOrphaned() const { | 1151 bool HttpStreamFactoryImpl::Job::IsOrphaned() const { |
1184 return !IsPreconnecting() && !request_; | 1152 return !IsPreconnecting() && !request_; |
1185 } | 1153 } |
1186 | 1154 |
1187 } // namespace net | 1155 } // namespace net |
OLD | NEW |