Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / net / http / http_stream_factory_impl_job.cc
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
3 // found in the LICENSE file.
4
5 #include "net/http/http_stream_factory_impl_job.h"
6
7 #include <algorithm>
8 #include <string>
9
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/logging.h"
13 #include "base/stl_util.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/values.h"
17 #include "build/build_config.h"
18 #include "net/base/connection_type_histograms.h"
19 #include "net/base/net_log.h"
20 #include "net/base/net_util.h"
21 #include "net/http/http_basic_stream.h"
22 #include "net/http/http_network_session.h"
23 #include "net/http/http_pipelined_connection.h"
24 #include "net/http/http_pipelined_host.h"
25 #include "net/http/http_pipelined_host_pool.h"
26 #include "net/http/http_pipelined_stream.h"
27 #include "net/http/http_proxy_client_socket.h"
28 #include "net/http/http_proxy_client_socket_pool.h"
29 #include "net/http/http_request_info.h"
30 #include "net/http/http_server_properties.h"
31 #include "net/http/http_stream_factory.h"
32 #include "net/http/http_stream_factory_impl_request.h"
33 #include "net/quic/quic_http_stream.h"
34 #include "net/socket/client_socket_handle.h"
35 #include "net/socket/client_socket_pool.h"
36 #include "net/socket/client_socket_pool_manager.h"
37 #include "net/socket/socks_client_socket_pool.h"
38 #include "net/socket/ssl_client_socket.h"
39 #include "net/socket/ssl_client_socket_pool.h"
40 #include "net/spdy/spdy_http_stream.h"
41 #include "net/spdy/spdy_session.h"
42 #include "net/spdy/spdy_session_pool.h"
43 #include "net/ssl/ssl_cert_request_info.h"
44
45 namespace net {
46
47 // Returns parameters associated with the start of a HTTP stream job.
48 base::Value* NetLogHttpStreamJobCallback(const GURL* original_url,
49                                          const GURL* url,
50                                          RequestPriority priority,
51                                          NetLog::LogLevel /* log_level */) {
52   base::DictionaryValue* dict = new base::DictionaryValue();
53   dict->SetString("original_url", original_url->GetOrigin().spec());
54   dict->SetString("url", url->GetOrigin().spec());
55   dict->SetString("priority", RequestPriorityToString(priority));
56   return dict;
57 }
58
59 // Returns parameters associated with the Proto (with NPN negotiation) of a HTTP
60 // stream.
61 base::Value* NetLogHttpStreamProtoCallback(
62     const SSLClientSocket::NextProtoStatus status,
63     const std::string* proto,
64     const std::string* server_protos,
65     NetLog::LogLevel /* log_level */) {
66   base::DictionaryValue* dict = new base::DictionaryValue();
67
68   dict->SetString("next_proto_status",
69                   SSLClientSocket::NextProtoStatusToString(status));
70   dict->SetString("proto", *proto);
71   dict->SetString("server_protos",
72                   SSLClientSocket::ServerProtosToString(*server_protos));
73   return dict;
74 }
75
76 HttpStreamFactoryImpl::Job::Job(HttpStreamFactoryImpl* stream_factory,
77                                 HttpNetworkSession* session,
78                                 const HttpRequestInfo& request_info,
79                                 RequestPriority priority,
80                                 const SSLConfig& server_ssl_config,
81                                 const SSLConfig& proxy_ssl_config,
82                                 NetLog* net_log)
83     : request_(NULL),
84       request_info_(request_info),
85       priority_(priority),
86       server_ssl_config_(server_ssl_config),
87       proxy_ssl_config_(proxy_ssl_config),
88       net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_HTTP_STREAM_JOB)),
89       io_callback_(base::Bind(&Job::OnIOComplete, base::Unretained(this))),
90       connection_(new ClientSocketHandle),
91       session_(session),
92       stream_factory_(stream_factory),
93       next_state_(STATE_NONE),
94       pac_request_(NULL),
95       blocking_job_(NULL),
96       waiting_job_(NULL),
97       using_ssl_(false),
98       using_spdy_(false),
99       using_quic_(false),
100       quic_request_(session_->quic_stream_factory()),
101       force_spdy_always_(HttpStreamFactory::force_spdy_always()),
102       force_spdy_over_ssl_(HttpStreamFactory::force_spdy_over_ssl()),
103       spdy_certificate_error_(OK),
104       establishing_tunnel_(false),
105       was_npn_negotiated_(false),
106       protocol_negotiated_(kProtoUnknown),
107       num_streams_(0),
108       spdy_session_direct_(false),
109       existing_available_pipeline_(false),
110       ptr_factory_(this) {
111   DCHECK(stream_factory);
112   DCHECK(session);
113 }
114
115 HttpStreamFactoryImpl::Job::~Job() {
116   net_log_.EndEvent(NetLog::TYPE_HTTP_STREAM_JOB);
117
118   // When we're in a partially constructed state, waiting for the user to
119   // provide certificate handling information or authentication, we can't reuse
120   // this stream at all.
121   if (next_state_ == STATE_WAITING_USER_ACTION) {
122     connection_->socket()->Disconnect();
123     connection_.reset();
124   }
125
126   if (pac_request_)
127     session_->proxy_service()->CancelPacRequest(pac_request_);
128
129   // The stream could be in a partial state.  It is not reusable.
130   if (stream_.get() && next_state_ != STATE_DONE)
131     stream_->Close(true /* not reusable */);
132 }
133
134 void HttpStreamFactoryImpl::Job::Start(Request* request) {
135   DCHECK(request);
136   request_ = request;
137   StartInternal();
138 }
139
140 int HttpStreamFactoryImpl::Job::Preconnect(int num_streams) {
141   DCHECK_GT(num_streams, 0);
142   HostPortPair origin_server =
143       HostPortPair(request_info_.url.HostNoBrackets(),
144                    request_info_.url.EffectiveIntPort());
145   base::WeakPtr<HttpServerProperties> http_server_properties =
146       session_->http_server_properties();
147   if (http_server_properties &&
148       http_server_properties->SupportsSpdy(origin_server)) {
149     num_streams_ = 1;
150   } else {
151     num_streams_ = num_streams;
152   }
153   return StartInternal();
154 }
155
156 int HttpStreamFactoryImpl::Job::RestartTunnelWithProxyAuth(
157     const AuthCredentials& credentials) {
158   DCHECK(establishing_tunnel_);
159   next_state_ = STATE_RESTART_TUNNEL_AUTH;
160   stream_.reset();
161   return RunLoop(OK);
162 }
163
164 LoadState HttpStreamFactoryImpl::Job::GetLoadState() const {
165   switch (next_state_) {
166     case STATE_RESOLVE_PROXY_COMPLETE:
167       return session_->proxy_service()->GetLoadState(pac_request_);
168     case STATE_INIT_CONNECTION_COMPLETE:
169     case STATE_CREATE_STREAM_COMPLETE:
170       return using_quic_ ? LOAD_STATE_CONNECTING : connection_->GetLoadState();
171     default:
172       return LOAD_STATE_IDLE;
173   }
174 }
175
176 void HttpStreamFactoryImpl::Job::MarkAsAlternate(
177     const GURL& original_url,
178     PortAlternateProtocolPair alternate) {
179   DCHECK(!original_url_.get());
180   original_url_.reset(new GURL(original_url));
181   if (alternate.protocol == QUIC) {
182     DCHECK(session_->params().enable_quic);
183     using_quic_ = true;
184   }
185 }
186
187 void HttpStreamFactoryImpl::Job::WaitFor(Job* job) {
188   DCHECK_EQ(STATE_NONE, next_state_);
189   DCHECK_EQ(STATE_NONE, job->next_state_);
190   DCHECK(!blocking_job_);
191   DCHECK(!job->waiting_job_);
192   blocking_job_ = job;
193   job->waiting_job_ = this;
194 }
195
196 void HttpStreamFactoryImpl::Job::Resume(Job* job) {
197   DCHECK_EQ(blocking_job_, job);
198   blocking_job_ = NULL;
199
200   // We know we're blocked if the next_state_ is STATE_WAIT_FOR_JOB_COMPLETE.
201   // Unblock |this|.
202   if (next_state_ == STATE_WAIT_FOR_JOB_COMPLETE) {
203     base::MessageLoop::current()->PostTask(
204         FROM_HERE,
205         base::Bind(&HttpStreamFactoryImpl::Job::OnIOComplete,
206                    ptr_factory_.GetWeakPtr(), OK));
207   }
208 }
209
210 void HttpStreamFactoryImpl::Job::Orphan(const Request* request) {
211   DCHECK_EQ(request_, request);
212   request_ = NULL;
213   if (blocking_job_) {
214     // We've been orphaned, but there's a job we're blocked on. Don't bother
215     // racing, just cancel ourself.
216     DCHECK(blocking_job_->waiting_job_);
217     blocking_job_->waiting_job_ = NULL;
218     blocking_job_ = NULL;
219     if (stream_factory_->for_websockets_ &&
220         connection_ && connection_->socket())
221       connection_->socket()->Disconnect();
222     stream_factory_->OnOrphanedJobComplete(this);
223   } else if (stream_factory_->for_websockets_) {
224     // We cancel this job because a WebSocketHandshakeStream can't be created
225     // without a WebSocketHandshakeStreamBase::CreateHelper which is stored in
226     // the Request class and isn't accessible from this job.
227     if (connection_ && connection_->socket())
228       connection_->socket()->Disconnect();
229     stream_factory_->OnOrphanedJobComplete(this);
230   }
231 }
232
233 void HttpStreamFactoryImpl::Job::SetPriority(RequestPriority priority) {
234   priority_ = priority;
235   // TODO(akalin): Propagate this to |connection_| and maybe the
236   // preconnect state.
237 }
238
239 bool HttpStreamFactoryImpl::Job::was_npn_negotiated() const {
240   return was_npn_negotiated_;
241 }
242
243 NextProto HttpStreamFactoryImpl::Job::protocol_negotiated() const {
244   return protocol_negotiated_;
245 }
246
247 bool HttpStreamFactoryImpl::Job::using_spdy() const {
248   return using_spdy_;
249 }
250
251 const SSLConfig& HttpStreamFactoryImpl::Job::server_ssl_config() const {
252   return server_ssl_config_;
253 }
254
255 const SSLConfig& HttpStreamFactoryImpl::Job::proxy_ssl_config() const {
256   return proxy_ssl_config_;
257 }
258
259 const ProxyInfo& HttpStreamFactoryImpl::Job::proxy_info() const {
260   return proxy_info_;
261 }
262
263 void HttpStreamFactoryImpl::Job::GetSSLInfo() {
264   DCHECK(using_ssl_);
265   DCHECK(!establishing_tunnel_);
266   DCHECK(connection_.get() && connection_->socket());
267   SSLClientSocket* ssl_socket =
268       static_cast<SSLClientSocket*>(connection_->socket());
269   ssl_socket->GetSSLInfo(&ssl_info_);
270 }
271
272 SpdySessionKey HttpStreamFactoryImpl::Job::GetSpdySessionKey() const {
273   // In the case that we're using an HTTPS proxy for an HTTP url,
274   // we look for a SPDY session *to* the proxy, instead of to the
275   // origin server.
276   PrivacyMode privacy_mode = request_info_.privacy_mode;
277   if (IsHttpsProxyAndHttpUrl()) {
278     return SpdySessionKey(proxy_info_.proxy_server().host_port_pair(),
279                           ProxyServer::Direct(),
280                           privacy_mode);
281   } else {
282     return SpdySessionKey(origin_,
283                           proxy_info_.proxy_server(),
284                           privacy_mode);
285   }
286 }
287
288 bool HttpStreamFactoryImpl::Job::CanUseExistingSpdySession() const {
289   // We need to make sure that if a spdy session was created for
290   // https://somehost/ that we don't use that session for http://somehost:443/.
291   // The only time we can use an existing session is if the request URL is
292   // https (the normal case) or if we're connection to a SPDY proxy, or
293   // if we're running with force_spdy_always_.  crbug.com/133176
294   // TODO(ricea): Add "wss" back to this list when SPDY WebSocket support is
295   // working.
296   return request_info_.url.SchemeIs("https") ||
297          proxy_info_.proxy_server().is_https() ||
298          force_spdy_always_;
299 }
300
301 void HttpStreamFactoryImpl::Job::OnStreamReadyCallback() {
302   DCHECK(stream_.get());
303   DCHECK(!IsPreconnecting());
304   DCHECK(!stream_factory_->for_websockets_);
305   if (IsOrphaned()) {
306     stream_factory_->OnOrphanedJobComplete(this);
307   } else {
308     request_->Complete(was_npn_negotiated(),
309                        protocol_negotiated(),
310                        using_spdy(),
311                        net_log_);
312     request_->OnStreamReady(this, server_ssl_config_, proxy_info_,
313                             stream_.release());
314   }
315   // |this| may be deleted after this call.
316 }
317
318 void HttpStreamFactoryImpl::Job::OnWebSocketHandshakeStreamReadyCallback() {
319   DCHECK(websocket_stream_);
320   DCHECK(!IsPreconnecting());
321   DCHECK(stream_factory_->for_websockets_);
322   // An orphaned WebSocket job will be closed immediately and
323   // never be ready.
324   DCHECK(!IsOrphaned());
325   request_->Complete(was_npn_negotiated(),
326                      protocol_negotiated(),
327                      using_spdy(),
328                      net_log_);
329   request_->OnWebSocketHandshakeStreamReady(this,
330                                             server_ssl_config_,
331                                             proxy_info_,
332                                             websocket_stream_.release());
333   // |this| may be deleted after this call.
334 }
335
336 void HttpStreamFactoryImpl::Job::OnNewSpdySessionReadyCallback() {
337   DCHECK(!stream_.get());
338   DCHECK(!IsPreconnecting());
339   DCHECK(using_spdy());
340   if (!new_spdy_session_)
341     return;
342   base::WeakPtr<SpdySession> spdy_session = new_spdy_session_;
343   new_spdy_session_.reset();
344   if (IsOrphaned()) {
345     stream_factory_->OnNewSpdySessionReady(
346         spdy_session, spdy_session_direct_, server_ssl_config_, proxy_info_,
347         was_npn_negotiated(), protocol_negotiated(), using_spdy(), net_log_);
348     stream_factory_->OnOrphanedJobComplete(this);
349   } else {
350     request_->OnNewSpdySessionReady(this, spdy_session, spdy_session_direct_);
351   }
352   // |this| may be deleted after this call.
353 }
354
355 void HttpStreamFactoryImpl::Job::OnStreamFailedCallback(int result) {
356   DCHECK(!IsPreconnecting());
357   if (IsOrphaned())
358     stream_factory_->OnOrphanedJobComplete(this);
359   else
360     request_->OnStreamFailed(this, result, server_ssl_config_);
361   // |this| may be deleted after this call.
362 }
363
364 void HttpStreamFactoryImpl::Job::OnCertificateErrorCallback(
365     int result, const SSLInfo& ssl_info) {
366   DCHECK(!IsPreconnecting());
367   if (IsOrphaned())
368     stream_factory_->OnOrphanedJobComplete(this);
369   else
370     request_->OnCertificateError(this, result, server_ssl_config_, ssl_info);
371   // |this| may be deleted after this call.
372 }
373
374 void HttpStreamFactoryImpl::Job::OnNeedsProxyAuthCallback(
375     const HttpResponseInfo& response,
376     HttpAuthController* auth_controller) {
377   DCHECK(!IsPreconnecting());
378   if (IsOrphaned())
379     stream_factory_->OnOrphanedJobComplete(this);
380   else
381     request_->OnNeedsProxyAuth(
382         this, response, server_ssl_config_, proxy_info_, auth_controller);
383   // |this| may be deleted after this call.
384 }
385
386 void HttpStreamFactoryImpl::Job::OnNeedsClientAuthCallback(
387     SSLCertRequestInfo* cert_info) {
388   DCHECK(!IsPreconnecting());
389   if (IsOrphaned())
390     stream_factory_->OnOrphanedJobComplete(this);
391   else
392     request_->OnNeedsClientAuth(this, server_ssl_config_, cert_info);
393   // |this| may be deleted after this call.
394 }
395
396 void HttpStreamFactoryImpl::Job::OnHttpsProxyTunnelResponseCallback(
397     const HttpResponseInfo& response_info,
398     HttpStream* stream) {
399   DCHECK(!IsPreconnecting());
400   if (IsOrphaned())
401     stream_factory_->OnOrphanedJobComplete(this);
402   else
403     request_->OnHttpsProxyTunnelResponse(
404         this, response_info, server_ssl_config_, proxy_info_, stream);
405   // |this| may be deleted after this call.
406 }
407
408 void HttpStreamFactoryImpl::Job::OnPreconnectsComplete() {
409   DCHECK(!request_);
410   if (new_spdy_session_.get()) {
411     stream_factory_->OnNewSpdySessionReady(new_spdy_session_,
412                                            spdy_session_direct_,
413                                            server_ssl_config_,
414                                            proxy_info_,
415                                            was_npn_negotiated(),
416                                            protocol_negotiated(),
417                                            using_spdy(),
418                                            net_log_);
419   }
420   stream_factory_->OnPreconnectsComplete(this);
421   // |this| may be deleted after this call.
422 }
423
424 // static
425 int HttpStreamFactoryImpl::Job::OnHostResolution(
426     SpdySessionPool* spdy_session_pool,
427     const SpdySessionKey& spdy_session_key,
428     const AddressList& addresses,
429     const BoundNetLog& net_log) {
430   // It is OK to dereference spdy_session_pool, because the
431   // ClientSocketPoolManager will be destroyed in the same callback that
432   // destroys the SpdySessionPool.
433   return
434       spdy_session_pool->FindAvailableSession(spdy_session_key, net_log) ?
435       ERR_SPDY_SESSION_ALREADY_EXISTS : OK;
436 }
437
438 void HttpStreamFactoryImpl::Job::OnIOComplete(int result) {
439   RunLoop(result);
440 }
441
442 int HttpStreamFactoryImpl::Job::RunLoop(int result) {
443   result = DoLoop(result);
444
445   if (result == ERR_IO_PENDING)
446     return result;
447
448   // If there was an error, we should have already resumed the |waiting_job_|,
449   // if there was one.
450   DCHECK(result == OK || waiting_job_ == NULL);
451
452   if (IsPreconnecting()) {
453     base::MessageLoop::current()->PostTask(
454         FROM_HERE,
455         base::Bind(
456             &HttpStreamFactoryImpl::Job::OnPreconnectsComplete,
457             ptr_factory_.GetWeakPtr()));
458     return ERR_IO_PENDING;
459   }
460
461   if (IsCertificateError(result)) {
462     // Retrieve SSL information from the socket.
463     GetSSLInfo();
464
465     next_state_ = STATE_WAITING_USER_ACTION;
466     base::MessageLoop::current()->PostTask(
467         FROM_HERE,
468         base::Bind(
469             &HttpStreamFactoryImpl::Job::OnCertificateErrorCallback,
470             ptr_factory_.GetWeakPtr(),
471             result, ssl_info_));
472     return ERR_IO_PENDING;
473   }
474
475   switch (result) {
476     case ERR_PROXY_AUTH_REQUESTED:
477       {
478         DCHECK(connection_.get());
479         DCHECK(connection_->socket());
480         DCHECK(establishing_tunnel_);
481
482         ProxyClientSocket* proxy_socket =
483             static_cast<ProxyClientSocket*>(connection_->socket());
484         const HttpResponseInfo* tunnel_auth_response =
485             proxy_socket->GetConnectResponseInfo();
486
487         next_state_ = STATE_WAITING_USER_ACTION;
488         base::MessageLoop::current()->PostTask(
489             FROM_HERE,
490             base::Bind(
491                 &Job::OnNeedsProxyAuthCallback,
492                 ptr_factory_.GetWeakPtr(),
493                 *tunnel_auth_response,
494                 proxy_socket->GetAuthController()));
495       }
496       return ERR_IO_PENDING;
497
498     case ERR_SSL_CLIENT_AUTH_CERT_NEEDED:
499       base::MessageLoop::current()->PostTask(
500           FROM_HERE,
501           base::Bind(
502               &Job::OnNeedsClientAuthCallback,
503               ptr_factory_.GetWeakPtr(),
504               connection_->ssl_error_response_info().cert_request_info));
505       return ERR_IO_PENDING;
506
507     case ERR_HTTPS_PROXY_TUNNEL_RESPONSE:
508       {
509         DCHECK(connection_.get());
510         DCHECK(connection_->socket());
511         DCHECK(establishing_tunnel_);
512
513         ProxyClientSocket* proxy_socket =
514             static_cast<ProxyClientSocket*>(connection_->socket());
515         base::MessageLoop::current()->PostTask(
516             FROM_HERE,
517             base::Bind(
518                 &Job::OnHttpsProxyTunnelResponseCallback,
519                 ptr_factory_.GetWeakPtr(),
520                 *proxy_socket->GetConnectResponseInfo(),
521                 proxy_socket->CreateConnectResponseStream()));
522         return ERR_IO_PENDING;
523       }
524
525     case OK:
526       next_state_ = STATE_DONE;
527       if (new_spdy_session_.get()) {
528         base::MessageLoop::current()->PostTask(
529             FROM_HERE,
530             base::Bind(&Job::OnNewSpdySessionReadyCallback,
531                        ptr_factory_.GetWeakPtr()));
532       } else if (stream_factory_->for_websockets_) {
533         DCHECK(websocket_stream_);
534         base::MessageLoop::current()->PostTask(
535             FROM_HERE,
536             base::Bind(&Job::OnWebSocketHandshakeStreamReadyCallback,
537                        ptr_factory_.GetWeakPtr()));
538       } else {
539         DCHECK(stream_.get());
540         base::MessageLoop::current()->PostTask(
541             FROM_HERE,
542             base::Bind(
543                 &Job::OnStreamReadyCallback,
544                 ptr_factory_.GetWeakPtr()));
545       }
546       return ERR_IO_PENDING;
547
548     default:
549       base::MessageLoop::current()->PostTask(
550           FROM_HERE,
551           base::Bind(
552               &Job::OnStreamFailedCallback,
553               ptr_factory_.GetWeakPtr(),
554               result));
555       return ERR_IO_PENDING;
556   }
557   return result;
558 }
559
560 int HttpStreamFactoryImpl::Job::DoLoop(int result) {
561   DCHECK_NE(next_state_, STATE_NONE);
562   int rv = result;
563   do {
564     State state = next_state_;
565     next_state_ = STATE_NONE;
566     switch (state) {
567       case STATE_START:
568         DCHECK_EQ(OK, rv);
569         rv = DoStart();
570         break;
571       case STATE_RESOLVE_PROXY:
572         DCHECK_EQ(OK, rv);
573         rv = DoResolveProxy();
574         break;
575       case STATE_RESOLVE_PROXY_COMPLETE:
576         rv = DoResolveProxyComplete(rv);
577         break;
578       case STATE_WAIT_FOR_JOB:
579         DCHECK_EQ(OK, rv);
580         rv = DoWaitForJob();
581         break;
582       case STATE_WAIT_FOR_JOB_COMPLETE:
583         rv = DoWaitForJobComplete(rv);
584         break;
585       case STATE_INIT_CONNECTION:
586         DCHECK_EQ(OK, rv);
587         rv = DoInitConnection();
588         break;
589       case STATE_INIT_CONNECTION_COMPLETE:
590         rv = DoInitConnectionComplete(rv);
591         break;
592       case STATE_WAITING_USER_ACTION:
593         rv = DoWaitingUserAction(rv);
594         break;
595       case STATE_RESTART_TUNNEL_AUTH:
596         DCHECK_EQ(OK, rv);
597         rv = DoRestartTunnelAuth();
598         break;
599       case STATE_RESTART_TUNNEL_AUTH_COMPLETE:
600         rv = DoRestartTunnelAuthComplete(rv);
601         break;
602       case STATE_CREATE_STREAM:
603         DCHECK_EQ(OK, rv);
604         rv = DoCreateStream();
605         break;
606       case STATE_CREATE_STREAM_COMPLETE:
607         rv = DoCreateStreamComplete(rv);
608         break;
609       default:
610         NOTREACHED() << "bad state";
611         rv = ERR_FAILED;
612         break;
613     }
614   } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
615   return rv;
616 }
617
618 int HttpStreamFactoryImpl::Job::StartInternal() {
619   CHECK_EQ(STATE_NONE, next_state_);
620   next_state_ = STATE_START;
621   int rv = RunLoop(OK);
622   DCHECK_EQ(ERR_IO_PENDING, rv);
623   return rv;
624 }
625
626 int HttpStreamFactoryImpl::Job::DoStart() {
627   int port = request_info_.url.EffectiveIntPort();
628   origin_ = HostPortPair(request_info_.url.HostNoBrackets(), port);
629   origin_url_ = stream_factory_->ApplyHostMappingRules(
630       request_info_.url, &origin_);
631   http_pipelining_key_.reset(new HttpPipelinedHost::Key(origin_));
632
633   net_log_.BeginEvent(NetLog::TYPE_HTTP_STREAM_JOB,
634                       base::Bind(&NetLogHttpStreamJobCallback,
635                                  &request_info_.url, &origin_url_,
636                                  priority_));
637
638   // Don't connect to restricted ports.
639   bool is_port_allowed = IsPortAllowedByDefault(port);
640   if (request_info_.url.SchemeIs("ftp")) {
641     // Never share connection with other jobs for FTP requests.
642     DCHECK(!waiting_job_);
643
644     is_port_allowed = IsPortAllowedByFtp(port);
645   }
646   if (!is_port_allowed && !IsPortAllowedByOverride(port)) {
647     if (waiting_job_) {
648       waiting_job_->Resume(this);
649       waiting_job_ = NULL;
650     }
651     return ERR_UNSAFE_PORT;
652   }
653
654   next_state_ = STATE_RESOLVE_PROXY;
655   return OK;
656 }
657
658 int HttpStreamFactoryImpl::Job::DoResolveProxy() {
659   DCHECK(!pac_request_);
660
661   next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
662
663   if (request_info_.load_flags & LOAD_BYPASS_PROXY) {
664     proxy_info_.UseDirect();
665     return OK;
666   }
667
668   return session_->proxy_service()->ResolveProxy(
669       request_info_.url, &proxy_info_, io_callback_, &pac_request_, net_log_);
670 }
671
672 int HttpStreamFactoryImpl::Job::DoResolveProxyComplete(int result) {
673   pac_request_ = NULL;
674
675   if (result == OK) {
676     // Remove unsupported proxies from the list.
677     proxy_info_.RemoveProxiesWithoutScheme(
678         ProxyServer::SCHEME_DIRECT | ProxyServer::SCHEME_QUIC |
679         ProxyServer::SCHEME_HTTP | ProxyServer::SCHEME_HTTPS |
680         ProxyServer::SCHEME_SOCKS4 | ProxyServer::SCHEME_SOCKS5);
681
682     if (proxy_info_.is_empty()) {
683       // No proxies/direct to choose from. This happens when we don't support
684       // any of the proxies in the returned list.
685       result = ERR_NO_SUPPORTED_PROXIES;
686     }
687   }
688
689   if (result != OK) {
690     if (waiting_job_) {
691       waiting_job_->Resume(this);
692       waiting_job_ = NULL;
693     }
694     return result;
695   }
696
697   if (blocking_job_)
698     next_state_ = STATE_WAIT_FOR_JOB;
699   else
700     next_state_ = STATE_INIT_CONNECTION;
701   return OK;
702 }
703
704 bool HttpStreamFactoryImpl::Job::ShouldForceSpdySSL() const {
705   bool rv = force_spdy_always_ && force_spdy_over_ssl_;
706   return rv && !HttpStreamFactory::HasSpdyExclusion(origin_);
707 }
708
709 bool HttpStreamFactoryImpl::Job::ShouldForceSpdyWithoutSSL() const {
710   bool rv = force_spdy_always_ && !force_spdy_over_ssl_;
711   return rv && !HttpStreamFactory::HasSpdyExclusion(origin_);
712 }
713
714 bool HttpStreamFactoryImpl::Job::ShouldForceQuic() const {
715   return session_->params().enable_quic &&
716     session_->params().origin_to_force_quic_on.Equals(origin_) &&
717     proxy_info_.is_direct();
718 }
719
720 int HttpStreamFactoryImpl::Job::DoWaitForJob() {
721   DCHECK(blocking_job_);
722   next_state_ = STATE_WAIT_FOR_JOB_COMPLETE;
723   return ERR_IO_PENDING;
724 }
725
726 int HttpStreamFactoryImpl::Job::DoWaitForJobComplete(int result) {
727   DCHECK(!blocking_job_);
728   DCHECK_EQ(OK, result);
729   next_state_ = STATE_INIT_CONNECTION;
730   return OK;
731 }
732
733 int HttpStreamFactoryImpl::Job::DoInitConnection() {
734   DCHECK(!blocking_job_);
735   DCHECK(!connection_->is_initialized());
736   DCHECK(proxy_info_.proxy_server().is_valid());
737   next_state_ = STATE_INIT_CONNECTION_COMPLETE;
738
739   using_ssl_ = request_info_.url.SchemeIs("https") ||
740       request_info_.url.SchemeIs("wss") || ShouldForceSpdySSL();
741   using_spdy_ = false;
742
743   if (ShouldForceQuic())
744     using_quic_ = true;
745
746   if (proxy_info_.is_quic())
747     using_quic_ = true;
748
749   if (using_quic_) {
750     DCHECK(session_->params().enable_quic);
751     if (proxy_info_.is_quic() && !request_info_.url.SchemeIs("http")) {
752       NOTREACHED();
753       // TODO(rch): support QUIC proxies for HTTPS urls.
754       return ERR_NOT_IMPLEMENTED;
755     }
756     HostPortProxyPair destination;
757     destination.first = proxy_info_.is_quic() ?
758         proxy_info_.proxy_server().host_port_pair() : origin_;
759     destination.second = ProxyServer::Direct();
760     next_state_ = STATE_INIT_CONNECTION_COMPLETE;
761     bool secure_quic = using_ssl_ || proxy_info_.is_quic();
762     int rv = quic_request_.Request(
763         destination, secure_quic, request_info_.method,
764         session_->cert_verifier(), net_log_, io_callback_);
765     if (rv != OK) {
766       // OK, there's no available QUIC session. Let |waiting_job_| resume
767       // if it's paused.
768       if (waiting_job_) {
769         waiting_job_->Resume(this);
770         waiting_job_ = NULL;
771       }
772     }
773     return rv;
774   }
775
776   // Check first if we have a spdy session for this group.  If so, then go
777   // straight to using that.
778   SpdySessionKey spdy_session_key = GetSpdySessionKey();
779   base::WeakPtr<SpdySession> spdy_session =
780       session_->spdy_session_pool()->FindAvailableSession(
781           spdy_session_key, net_log_);
782   if (spdy_session && CanUseExistingSpdySession()) {
783     // If we're preconnecting, but we already have a SpdySession, we don't
784     // actually need to preconnect any sockets, so we're done.
785     if (IsPreconnecting())
786       return OK;
787     using_spdy_ = true;
788     next_state_ = STATE_CREATE_STREAM;
789     existing_spdy_session_ = spdy_session;
790     return OK;
791   } else if (request_ && (using_ssl_ || ShouldForceSpdyWithoutSSL())) {
792     // Update the spdy session key for the request that launched this job.
793     request_->SetSpdySessionKey(spdy_session_key);
794   } else if (IsRequestEligibleForPipelining()) {
795     // TODO(simonjam): With pipelining, we might be better off using fewer
796     // connections and thus should make fewer preconnections. Explore
797     // preconnecting fewer than the requested num_connections.
798     //
799     // Separate note: A forced pipeline is always available if one exists for
800     // this key. This is different than normal pipelines, which may be
801     // unavailable or unusable. So, there is no need to worry about a race
802     // between when a pipeline becomes available and when this job blocks.
803     existing_available_pipeline_ = stream_factory_->http_pipelined_host_pool_.
804         IsExistingPipelineAvailableForKey(*http_pipelining_key_.get());
805     if (existing_available_pipeline_) {
806       return OK;
807     } else {
808       bool was_new_key = request_->SetHttpPipeliningKey(
809           *http_pipelining_key_.get());
810       if (!was_new_key && session_->force_http_pipelining()) {
811         return ERR_IO_PENDING;
812       }
813     }
814   }
815
816   // OK, there's no available SPDY session. Let |waiting_job_| resume if it's
817   // paused.
818
819   if (waiting_job_) {
820     waiting_job_->Resume(this);
821     waiting_job_ = NULL;
822   }
823
824   if (proxy_info_.is_http() || proxy_info_.is_https())
825     establishing_tunnel_ = using_ssl_;
826
827   bool want_spdy_over_npn = original_url_ != NULL;
828
829   if (proxy_info_.is_https()) {
830     InitSSLConfig(proxy_info_.proxy_server().host_port_pair(),
831                   &proxy_ssl_config_,
832                   true /* is a proxy server */);
833     // Disable revocation checking for HTTPS proxies since the revocation
834     // requests are probably going to need to go through the proxy too.
835     proxy_ssl_config_.rev_checking_enabled = false;
836   }
837   if (using_ssl_) {
838     InitSSLConfig(origin_, &server_ssl_config_,
839                   false /* not a proxy server */);
840   }
841
842   if (IsPreconnecting()) {
843     DCHECK(!stream_factory_->for_websockets_);
844     return PreconnectSocketsForHttpRequest(
845         origin_url_,
846         request_info_.extra_headers,
847         request_info_.load_flags,
848         priority_,
849         session_,
850         proxy_info_,
851         ShouldForceSpdySSL(),
852         want_spdy_over_npn,
853         server_ssl_config_,
854         proxy_ssl_config_,
855         request_info_.privacy_mode,
856         net_log_,
857         num_streams_);
858   } else {
859     // If we can't use a SPDY session, don't both checking for one after
860     // the hostname is resolved.
861     OnHostResolutionCallback resolution_callback = CanUseExistingSpdySession() ?
862         base::Bind(&Job::OnHostResolution, session_->spdy_session_pool(),
863                    GetSpdySessionKey()) :
864         OnHostResolutionCallback();
865     if (stream_factory_->for_websockets_) {
866       // TODO(ricea): Re-enable NPN when WebSockets over SPDY is supported.
867       SSLConfig websocket_server_ssl_config = server_ssl_config_;
868       websocket_server_ssl_config.next_protos.clear();
869       return InitSocketHandleForWebSocketRequest(
870           origin_url_, request_info_.extra_headers, request_info_.load_flags,
871           priority_, session_, proxy_info_, ShouldForceSpdySSL(),
872           want_spdy_over_npn, websocket_server_ssl_config, proxy_ssl_config_,
873           request_info_.privacy_mode, net_log_,
874           connection_.get(), resolution_callback, io_callback_);
875     }
876     return InitSocketHandleForHttpRequest(
877         origin_url_, request_info_.extra_headers, request_info_.load_flags,
878         priority_, session_, proxy_info_, ShouldForceSpdySSL(),
879         want_spdy_over_npn, server_ssl_config_, proxy_ssl_config_,
880         request_info_.privacy_mode, net_log_,
881         connection_.get(), resolution_callback, io_callback_);
882   }
883 }
884
885 int HttpStreamFactoryImpl::Job::DoInitConnectionComplete(int result) {
886   if (IsPreconnecting()) {
887     if (using_quic_)
888       return result;
889     DCHECK_EQ(OK, result);
890     return OK;
891   }
892
893   if (result == ERR_SPDY_SESSION_ALREADY_EXISTS) {
894     // We found a SPDY connection after resolving the host.  This is
895     // probably an IP pooled connection.
896     SpdySessionKey spdy_session_key = GetSpdySessionKey();
897     existing_spdy_session_ =
898         session_->spdy_session_pool()->FindAvailableSession(
899             spdy_session_key, net_log_);
900     if (existing_spdy_session_) {
901       using_spdy_ = true;
902       next_state_ = STATE_CREATE_STREAM;
903     } else {
904       // It is possible that the spdy session no longer exists.
905       ReturnToStateInitConnection(true /* close connection */);
906     }
907     return OK;
908   }
909
910   // TODO(willchan): Make this a bit more exact. Maybe there are recoverable
911   // errors, such as ignoring certificate errors for Alternate-Protocol.
912   if (result < 0 && waiting_job_) {
913     waiting_job_->Resume(this);
914     waiting_job_ = NULL;
915   }
916
917   if (result < 0 && session_->force_http_pipelining()) {
918     stream_factory_->AbortPipelinedRequestsWithKey(
919         this, *http_pipelining_key_.get(), result, server_ssl_config_);
920   }
921
922   // |result| may be the result of any of the stacked pools. The following
923   // logic is used when determining how to interpret an error.
924   // If |result| < 0:
925   //   and connection_->socket() != NULL, then the SSL handshake ran and it
926   //     is a potentially recoverable error.
927   //   and connection_->socket == NULL and connection_->is_ssl_error() is true,
928   //     then the SSL handshake ran with an unrecoverable error.
929   //   otherwise, the error came from one of the other pools.
930   bool ssl_started = using_ssl_ && (result == OK || connection_->socket() ||
931                                     connection_->is_ssl_error());
932
933   if (ssl_started && (result == OK || IsCertificateError(result))) {
934     if (using_quic_ && result == OK) {
935       was_npn_negotiated_ = true;
936       NextProto protocol_negotiated =
937           SSLClientSocket::NextProtoFromString("quic/1+spdy/3");
938       protocol_negotiated_ = protocol_negotiated;
939     } else {
940       SSLClientSocket* ssl_socket =
941           static_cast<SSLClientSocket*>(connection_->socket());
942       if (ssl_socket->WasNpnNegotiated()) {
943         was_npn_negotiated_ = true;
944         std::string proto;
945         std::string server_protos;
946         SSLClientSocket::NextProtoStatus status =
947             ssl_socket->GetNextProto(&proto, &server_protos);
948         NextProto protocol_negotiated =
949             SSLClientSocket::NextProtoFromString(proto);
950         protocol_negotiated_ = protocol_negotiated;
951         net_log_.AddEvent(
952             NetLog::TYPE_HTTP_STREAM_REQUEST_PROTO,
953             base::Bind(&NetLogHttpStreamProtoCallback,
954                        status, &proto, &server_protos));
955         if (ssl_socket->was_spdy_negotiated())
956           SwitchToSpdyMode();
957       }
958       if (ShouldForceSpdySSL())
959         SwitchToSpdyMode();
960     }
961   } else if (proxy_info_.is_https() && connection_->socket() &&
962         result == OK) {
963     ProxyClientSocket* proxy_socket =
964       static_cast<ProxyClientSocket*>(connection_->socket());
965     if (proxy_socket->IsUsingSpdy()) {
966       was_npn_negotiated_ = true;
967       protocol_negotiated_ = proxy_socket->GetProtocolNegotiated();
968       SwitchToSpdyMode();
969     }
970   }
971
972   // We may be using spdy without SSL
973   if (ShouldForceSpdyWithoutSSL())
974     SwitchToSpdyMode();
975
976   if (result == ERR_PROXY_AUTH_REQUESTED ||
977       result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) {
978     DCHECK(!ssl_started);
979     // Other state (i.e. |using_ssl_|) suggests that |connection_| will have an
980     // SSL socket, but there was an error before that could happen.  This
981     // puts the in progress HttpProxy socket into |connection_| in order to
982     // complete the auth (or read the response body).  The tunnel restart code
983     // is careful to remove it before returning control to the rest of this
984     // class.
985     connection_.reset(connection_->release_pending_http_proxy_connection());
986     return result;
987   }
988
989   if (!ssl_started && result < 0 && original_url_.get()) {
990     // Mark the alternate protocol as broken and fallback.
991     session_->http_server_properties()->SetBrokenAlternateProtocol(
992         HostPortPair::FromURL(*original_url_));
993     return result;
994   }
995
996   if (using_quic_) {
997     if (result < 0)
998       return result;
999     stream_ = quic_request_.ReleaseStream();
1000     next_state_ = STATE_NONE;
1001     return OK;
1002   }
1003
1004   if (result < 0 && !ssl_started)
1005     return ReconsiderProxyAfterError(result);
1006   establishing_tunnel_ = false;
1007
1008   if (connection_->socket()) {
1009     LogHttpConnectedMetrics(*connection_);
1010
1011     // We officially have a new connection.  Record the type.
1012     if (!connection_->is_reused()) {
1013       ConnectionType type = using_spdy_ ? CONNECTION_SPDY : CONNECTION_HTTP;
1014       UpdateConnectionTypeHistograms(type);
1015     }
1016   }
1017
1018   // Handle SSL errors below.
1019   if (using_ssl_) {
1020     DCHECK(ssl_started);
1021     if (IsCertificateError(result)) {
1022       if (using_spdy_ && original_url_.get() &&
1023           original_url_->SchemeIs("http")) {
1024         // We ignore certificate errors for http over spdy.
1025         spdy_certificate_error_ = result;
1026         result = OK;
1027       } else {
1028         result = HandleCertificateError(result);
1029         if (result == OK && !connection_->socket()->IsConnectedAndIdle()) {
1030           ReturnToStateInitConnection(true /* close connection */);
1031           return result;
1032         }
1033       }
1034     }
1035     if (result < 0)
1036       return result;
1037   }
1038
1039   next_state_ = STATE_CREATE_STREAM;
1040   return OK;
1041 }
1042
1043 int HttpStreamFactoryImpl::Job::DoWaitingUserAction(int result) {
1044   // This state indicates that the stream request is in a partially
1045   // completed state, and we've called back to the delegate for more
1046   // information.
1047
1048   // We're always waiting here for the delegate to call us back.
1049   return ERR_IO_PENDING;
1050 }
1051
1052 int HttpStreamFactoryImpl::Job::DoCreateStream() {
1053   DCHECK(connection_->socket() || existing_spdy_session_.get() ||
1054          existing_available_pipeline_ || using_quic_);
1055
1056   next_state_ = STATE_CREATE_STREAM_COMPLETE;
1057
1058   // We only set the socket motivation if we're the first to use
1059   // this socket.  Is there a race for two SPDY requests?  We really
1060   // need to plumb this through to the connect level.
1061   if (connection_->socket() && !connection_->is_reused())
1062     SetSocketMotivation();
1063
1064   if (!using_spdy_) {
1065     // We may get ftp scheme when fetching ftp resources through proxy.
1066     bool using_proxy = (proxy_info_.is_http() || proxy_info_.is_https()) &&
1067                        (request_info_.url.SchemeIs("http") ||
1068                         request_info_.url.SchemeIs("ftp"));
1069     if (stream_factory_->http_pipelined_host_pool_.
1070             IsExistingPipelineAvailableForKey(*http_pipelining_key_.get())) {
1071       DCHECK(!stream_factory_->for_websockets_);
1072       stream_.reset(stream_factory_->http_pipelined_host_pool_.
1073                     CreateStreamOnExistingPipeline(
1074                         *http_pipelining_key_.get()));
1075       CHECK(stream_.get());
1076     } else if (stream_factory_->for_websockets_) {
1077       DCHECK(request_);
1078       DCHECK(request_->websocket_handshake_stream_create_helper());
1079       websocket_stream_.reset(
1080           request_->websocket_handshake_stream_create_helper()
1081               ->CreateBasicStream(connection_.Pass(), using_proxy));
1082     } else if (!using_proxy && IsRequestEligibleForPipelining()) {
1083       // TODO(simonjam): Support proxies.
1084       stream_.reset(
1085           stream_factory_->http_pipelined_host_pool_.CreateStreamOnNewPipeline(
1086               *http_pipelining_key_.get(),
1087               connection_.release(),
1088               server_ssl_config_,
1089               proxy_info_,
1090               net_log_,
1091               was_npn_negotiated_,
1092               protocol_negotiated_));
1093       CHECK(stream_.get());
1094     } else {
1095       stream_.reset(new HttpBasicStream(connection_.release(), using_proxy));
1096     }
1097     return OK;
1098   }
1099
1100   CHECK(!stream_.get());
1101
1102   bool direct = true;
1103   const ProxyServer& proxy_server = proxy_info_.proxy_server();
1104   PrivacyMode privacy_mode = request_info_.privacy_mode;
1105   SpdySessionKey spdy_session_key(origin_, proxy_server, privacy_mode);
1106   if (IsHttpsProxyAndHttpUrl()) {
1107     // If we don't have a direct SPDY session, and we're using an HTTPS
1108     // proxy, then we might have a SPDY session to the proxy.
1109     // We never use privacy mode for connection to proxy server.
1110     spdy_session_key = SpdySessionKey(proxy_server.host_port_pair(),
1111                                       ProxyServer::Direct(),
1112                                       kPrivacyModeDisabled);
1113     direct = false;
1114   }
1115
1116   base::WeakPtr<SpdySession> spdy_session;
1117   if (existing_spdy_session_.get()) {
1118     // We picked up an existing session, so we don't need our socket.
1119     if (connection_->socket())
1120       connection_->socket()->Disconnect();
1121     connection_->Reset();
1122     std::swap(spdy_session, existing_spdy_session_);
1123   } else {
1124     SpdySessionPool* spdy_pool = session_->spdy_session_pool();
1125     spdy_session = spdy_pool->FindAvailableSession(spdy_session_key, net_log_);
1126     if (!spdy_session) {
1127       int error =
1128           spdy_pool->CreateAvailableSessionFromSocket(spdy_session_key,
1129                                                       connection_.Pass(),
1130                                                       net_log_,
1131                                                       spdy_certificate_error_,
1132                                                       &new_spdy_session_,
1133                                                       using_ssl_);
1134       if (error != OK)
1135         return error;
1136       const HostPortPair& host_port_pair = spdy_session_key.host_port_pair();
1137       base::WeakPtr<HttpServerProperties> http_server_properties =
1138           session_->http_server_properties();
1139       if (http_server_properties)
1140         http_server_properties->SetSupportsSpdy(host_port_pair, true);
1141       spdy_session_direct_ = direct;
1142       return OK;
1143     }
1144   }
1145
1146   if (!spdy_session)
1147     return ERR_CONNECTION_CLOSED;
1148
1149   // TODO(willchan): Delete this code, because eventually, the
1150   // HttpStreamFactoryImpl will be creating all the SpdyHttpStreams, since it
1151   // will know when SpdySessions become available.
1152
1153   if (stream_factory_->for_websockets_) {
1154     // TODO(ricea): Restore this code when WebSockets over SPDY is implemented.
1155     NOTREACHED();
1156   } else {
1157     bool use_relative_url = direct || request_info_.url.SchemeIs("https");
1158     stream_.reset(new SpdyHttpStream(spdy_session, use_relative_url));
1159   }
1160   return OK;
1161 }
1162
1163 int HttpStreamFactoryImpl::Job::DoCreateStreamComplete(int result) {
1164   if (result < 0)
1165     return result;
1166
1167   session_->proxy_service()->ReportSuccess(proxy_info_);
1168   next_state_ = STATE_NONE;
1169   return OK;
1170 }
1171
1172 int HttpStreamFactoryImpl::Job::DoRestartTunnelAuth() {
1173   next_state_ = STATE_RESTART_TUNNEL_AUTH_COMPLETE;
1174   ProxyClientSocket* proxy_socket =
1175       static_cast<ProxyClientSocket*>(connection_->socket());
1176   return proxy_socket->RestartWithAuth(io_callback_);
1177 }
1178
1179 int HttpStreamFactoryImpl::Job::DoRestartTunnelAuthComplete(int result) {
1180   if (result == ERR_PROXY_AUTH_REQUESTED)
1181     return result;
1182
1183   if (result == OK) {
1184     // Now that we've got the HttpProxyClientSocket connected.  We have
1185     // to release it as an idle socket into the pool and start the connection
1186     // process from the beginning.  Trying to pass it in with the
1187     // SSLSocketParams might cause a deadlock since params are dispatched
1188     // interchangeably.  This request won't necessarily get this http proxy
1189     // socket, but there will be forward progress.
1190     establishing_tunnel_ = false;
1191     ReturnToStateInitConnection(false /* do not close connection */);
1192     return OK;
1193   }
1194
1195   return ReconsiderProxyAfterError(result);
1196 }
1197
1198 void HttpStreamFactoryImpl::Job::ReturnToStateInitConnection(
1199     bool close_connection) {
1200   if (close_connection && connection_->socket())
1201     connection_->socket()->Disconnect();
1202   connection_->Reset();
1203
1204   if (request_) {
1205     request_->RemoveRequestFromSpdySessionRequestMap();
1206     request_->RemoveRequestFromHttpPipeliningRequestMap();
1207   }
1208
1209   next_state_ = STATE_INIT_CONNECTION;
1210 }
1211
1212 void HttpStreamFactoryImpl::Job::SetSocketMotivation() {
1213   if (request_info_.motivation == HttpRequestInfo::PRECONNECT_MOTIVATED)
1214     connection_->socket()->SetSubresourceSpeculation();
1215   else if (request_info_.motivation == HttpRequestInfo::OMNIBOX_MOTIVATED)
1216     connection_->socket()->SetOmniboxSpeculation();
1217   // TODO(mbelshe): Add other motivations (like EARLY_LOAD_MOTIVATED).
1218 }
1219
1220 bool HttpStreamFactoryImpl::Job::IsHttpsProxyAndHttpUrl() const {
1221   if (!proxy_info_.is_https())
1222     return false;
1223   if (original_url_.get()) {
1224     // We currently only support Alternate-Protocol where the original scheme
1225     // is http.
1226     DCHECK(original_url_->SchemeIs("http"));
1227     return original_url_->SchemeIs("http");
1228   }
1229   return request_info_.url.SchemeIs("http");
1230 }
1231
1232 // Sets several fields of ssl_config for the given origin_server based on the
1233 // proxy info and other factors.
1234 void HttpStreamFactoryImpl::Job::InitSSLConfig(
1235     const HostPortPair& origin_server,
1236     SSLConfig* ssl_config,
1237     bool is_proxy) const {
1238   if (proxy_info_.is_https() && ssl_config->send_client_cert) {
1239     // When connecting through an HTTPS proxy, disable TLS False Start so
1240     // that client authentication errors can be distinguished between those
1241     // originating from the proxy server (ERR_PROXY_CONNECTION_FAILED) and
1242     // those originating from the endpoint (ERR_SSL_PROTOCOL_ERROR /
1243     // ERR_BAD_SSL_CLIENT_AUTH_CERT).
1244     // TODO(rch): This assumes that the HTTPS proxy will only request a
1245     // client certificate during the initial handshake.
1246     // http://crbug.com/59292
1247     ssl_config->false_start_enabled = false;
1248   }
1249
1250   enum {
1251     FALLBACK_NONE = 0,    // SSL version fallback did not occur.
1252     FALLBACK_SSL3 = 1,    // Fell back to SSL 3.0.
1253     FALLBACK_TLS1 = 2,    // Fell back to TLS 1.0.
1254     FALLBACK_TLS1_1 = 3,  // Fell back to TLS 1.1.
1255     FALLBACK_MAX
1256   };
1257
1258   int fallback = FALLBACK_NONE;
1259   if (ssl_config->version_fallback) {
1260     switch (ssl_config->version_max) {
1261       case SSL_PROTOCOL_VERSION_SSL3:
1262         fallback = FALLBACK_SSL3;
1263         break;
1264       case SSL_PROTOCOL_VERSION_TLS1:
1265         fallback = FALLBACK_TLS1;
1266         break;
1267       case SSL_PROTOCOL_VERSION_TLS1_1:
1268         fallback = FALLBACK_TLS1_1;
1269         break;
1270     }
1271   }
1272   UMA_HISTOGRAM_ENUMERATION("Net.ConnectionUsedSSLVersionFallback",
1273                             fallback, FALLBACK_MAX);
1274
1275   // We also wish to measure the amount of fallback connections for a host that
1276   // we know implements TLS up to 1.2. Ideally there would be no fallback here
1277   // but high numbers of SSLv3 would suggest that SSLv3 fallback is being
1278   // caused by network middleware rather than buggy HTTPS servers.
1279   const std::string& host = origin_server.host();
1280   if (!is_proxy &&
1281       host.size() >= 10 &&
1282       host.compare(host.size() - 10, 10, "google.com") == 0 &&
1283       (host.size() == 10 || host[host.size()-11] == '.')) {
1284     UMA_HISTOGRAM_ENUMERATION("Net.GoogleConnectionUsedSSLVersionFallback",
1285                               fallback, FALLBACK_MAX);
1286   }
1287
1288   if (request_info_.load_flags & LOAD_VERIFY_EV_CERT)
1289     ssl_config->verify_ev_cert = true;
1290
1291   // Disable Channel ID if privacy mode is enabled.
1292   if (request_info_.privacy_mode == kPrivacyModeEnabled)
1293     ssl_config->channel_id_enabled = false;
1294 }
1295
1296
1297 int HttpStreamFactoryImpl::Job::ReconsiderProxyAfterError(int error) {
1298   DCHECK(!pac_request_);
1299
1300   // A failure to resolve the hostname or any error related to establishing a
1301   // TCP connection could be grounds for trying a new proxy configuration.
1302   //
1303   // Why do this when a hostname cannot be resolved?  Some URLs only make sense
1304   // to proxy servers.  The hostname in those URLs might fail to resolve if we
1305   // are still using a non-proxy config.  We need to check if a proxy config
1306   // now exists that corresponds to a proxy server that could load the URL.
1307   //
1308   switch (error) {
1309     case ERR_PROXY_CONNECTION_FAILED:
1310     case ERR_NAME_NOT_RESOLVED:
1311     case ERR_INTERNET_DISCONNECTED:
1312     case ERR_ADDRESS_UNREACHABLE:
1313     case ERR_CONNECTION_CLOSED:
1314     case ERR_CONNECTION_TIMED_OUT:
1315     case ERR_CONNECTION_RESET:
1316     case ERR_CONNECTION_REFUSED:
1317     case ERR_CONNECTION_ABORTED:
1318     case ERR_TIMED_OUT:
1319     case ERR_TUNNEL_CONNECTION_FAILED:
1320     case ERR_SOCKS_CONNECTION_FAILED:
1321     // This can happen in the case of trying to talk to a proxy using SSL, and
1322     // ending up talking to a captive portal that supports SSL instead.
1323     case ERR_PROXY_CERTIFICATE_INVALID:
1324     // This can happen when trying to talk SSL to a non-SSL server (Like a
1325     // captive portal).
1326     case ERR_SSL_PROTOCOL_ERROR:
1327       break;
1328     case ERR_SOCKS_CONNECTION_HOST_UNREACHABLE:
1329       // Remap the SOCKS-specific "host unreachable" error to a more
1330       // generic error code (this way consumers like the link doctor
1331       // know to substitute their error page).
1332       //
1333       // Note that if the host resolving was done by the SOCKS5 proxy, we can't
1334       // differentiate between a proxy-side "host not found" versus a proxy-side
1335       // "address unreachable" error, and will report both of these failures as
1336       // ERR_ADDRESS_UNREACHABLE.
1337       return ERR_ADDRESS_UNREACHABLE;
1338     default:
1339       return error;
1340   }
1341
1342   if (request_info_.load_flags & LOAD_BYPASS_PROXY) {
1343     return error;
1344   }
1345
1346   if (proxy_info_.is_https() && proxy_ssl_config_.send_client_cert) {
1347     session_->ssl_client_auth_cache()->Remove(
1348         proxy_info_.proxy_server().host_port_pair());
1349   }
1350
1351   int rv = session_->proxy_service()->ReconsiderProxyAfterError(
1352       request_info_.url, &proxy_info_, io_callback_, &pac_request_, net_log_);
1353   if (rv == OK || rv == ERR_IO_PENDING) {
1354     // If the error was during connection setup, there is no socket to
1355     // disconnect.
1356     if (connection_->socket())
1357       connection_->socket()->Disconnect();
1358     connection_->Reset();
1359     if (request_) {
1360       request_->RemoveRequestFromSpdySessionRequestMap();
1361       request_->RemoveRequestFromHttpPipeliningRequestMap();
1362     }
1363     next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
1364   } else {
1365     // If ReconsiderProxyAfterError() failed synchronously, it means
1366     // there was nothing left to fall-back to, so fail the transaction
1367     // with the last connection error we got.
1368     // TODO(eroman): This is a confusing contract, make it more obvious.
1369     rv = error;
1370   }
1371
1372   return rv;
1373 }
1374
1375 int HttpStreamFactoryImpl::Job::HandleCertificateError(int error) {
1376   DCHECK(using_ssl_);
1377   DCHECK(IsCertificateError(error));
1378
1379   SSLClientSocket* ssl_socket =
1380       static_cast<SSLClientSocket*>(connection_->socket());
1381   ssl_socket->GetSSLInfo(&ssl_info_);
1382
1383   // Add the bad certificate to the set of allowed certificates in the
1384   // SSL config object. This data structure will be consulted after calling
1385   // RestartIgnoringLastError(). And the user will be asked interactively
1386   // before RestartIgnoringLastError() is ever called.
1387   SSLConfig::CertAndStatus bad_cert;
1388
1389   // |ssl_info_.cert| may be NULL if we failed to create
1390   // X509Certificate for whatever reason, but normally it shouldn't
1391   // happen, unless this code is used inside sandbox.
1392   if (ssl_info_.cert.get() == NULL ||
1393       !X509Certificate::GetDEREncoded(ssl_info_.cert->os_cert_handle(),
1394                                       &bad_cert.der_cert)) {
1395     return error;
1396   }
1397   bad_cert.cert_status = ssl_info_.cert_status;
1398   server_ssl_config_.allowed_bad_certs.push_back(bad_cert);
1399
1400   int load_flags = request_info_.load_flags;
1401   if (session_->params().ignore_certificate_errors)
1402     load_flags |= LOAD_IGNORE_ALL_CERT_ERRORS;
1403   if (ssl_socket->IgnoreCertError(error, load_flags))
1404     return OK;
1405   return error;
1406 }
1407
1408 void HttpStreamFactoryImpl::Job::SwitchToSpdyMode() {
1409   if (HttpStreamFactory::spdy_enabled())
1410     using_spdy_ = true;
1411 }
1412
1413 // static
1414 void HttpStreamFactoryImpl::Job::LogHttpConnectedMetrics(
1415     const ClientSocketHandle& handle) {
1416   UMA_HISTOGRAM_ENUMERATION("Net.HttpSocketType", handle.reuse_type(),
1417                             ClientSocketHandle::NUM_TYPES);
1418
1419   switch (handle.reuse_type()) {
1420     case ClientSocketHandle::UNUSED:
1421       UMA_HISTOGRAM_CUSTOM_TIMES("Net.HttpConnectionLatency",
1422                                  handle.setup_time(),
1423                                  base::TimeDelta::FromMilliseconds(1),
1424                                  base::TimeDelta::FromMinutes(10),
1425                                  100);
1426       break;
1427     case ClientSocketHandle::UNUSED_IDLE:
1428       UMA_HISTOGRAM_CUSTOM_TIMES("Net.SocketIdleTimeBeforeNextUse_UnusedSocket",
1429                                  handle.idle_time(),
1430                                  base::TimeDelta::FromMilliseconds(1),
1431                                  base::TimeDelta::FromMinutes(6),
1432                                  100);
1433       break;
1434     case ClientSocketHandle::REUSED_IDLE:
1435       UMA_HISTOGRAM_CUSTOM_TIMES("Net.SocketIdleTimeBeforeNextUse_ReusedSocket",
1436                                  handle.idle_time(),
1437                                  base::TimeDelta::FromMilliseconds(1),
1438                                  base::TimeDelta::FromMinutes(6),
1439                                  100);
1440       break;
1441     default:
1442       NOTREACHED();
1443       break;
1444   }
1445 }
1446
1447 bool HttpStreamFactoryImpl::Job::IsPreconnecting() const {
1448   DCHECK_GE(num_streams_, 0);
1449   return num_streams_ > 0;
1450 }
1451
1452 bool HttpStreamFactoryImpl::Job::IsOrphaned() const {
1453   return !IsPreconnecting() && !request_;
1454 }
1455
1456 bool HttpStreamFactoryImpl::Job::IsRequestEligibleForPipelining() {
1457   if (IsPreconnecting() || !request_) {
1458     return false;
1459   }
1460   if (stream_factory_->for_websockets_) {
1461     return false;
1462   }
1463   if (session_->force_http_pipelining()) {
1464     return true;
1465   }
1466   if (!session_->params().http_pipelining_enabled) {
1467     return false;
1468   }
1469   if (using_ssl_) {
1470     return false;
1471   }
1472   if (request_info_.method != "GET" && request_info_.method != "HEAD") {
1473     return false;
1474   }
1475   if (request_info_.load_flags &
1476       (net::LOAD_MAIN_FRAME | net::LOAD_SUB_FRAME | net::LOAD_PREFETCH |
1477        net::LOAD_IS_DOWNLOAD)) {
1478     // Avoid pipelining resources that may be streamed for a long time.
1479     return false;
1480   }
1481   return stream_factory_->http_pipelined_host_pool_.IsKeyEligibleForPipelining(
1482       *http_pipelining_key_.get());
1483 }
1484
1485 }  // namespace net