Upstream version 5.34.92.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 |
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 (using_quic_) {
747     DCHECK(session_->params().enable_quic);
748     if (!proxy_info_.is_direct()) {
749       NOTREACHED();
750       // TODO(rch): support QUIC proxies.
751       return ERR_NOT_IMPLEMENTED;
752     }
753     next_state_ = STATE_INIT_CONNECTION_COMPLETE;
754     const ProxyServer& proxy_server = proxy_info_.proxy_server();
755     int rv = quic_request_.Request(HostPortProxyPair(origin_, proxy_server),
756                                    using_ssl_, session_->cert_verifier(),
757                                    net_log_, io_callback_);
758     if (rv != OK) {
759       // OK, there's no available QUIC session. Let |waiting_job_| resume
760       // if it's paused.
761       if (waiting_job_) {
762         waiting_job_->Resume(this);
763         waiting_job_ = NULL;
764       }
765     }
766     return rv;
767   }
768
769   // Check first if we have a spdy session for this group.  If so, then go
770   // straight to using that.
771   SpdySessionKey spdy_session_key = GetSpdySessionKey();
772   base::WeakPtr<SpdySession> spdy_session =
773       session_->spdy_session_pool()->FindAvailableSession(
774           spdy_session_key, net_log_);
775   if (spdy_session && CanUseExistingSpdySession()) {
776     // If we're preconnecting, but we already have a SpdySession, we don't
777     // actually need to preconnect any sockets, so we're done.
778     if (IsPreconnecting())
779       return OK;
780     using_spdy_ = true;
781     next_state_ = STATE_CREATE_STREAM;
782     existing_spdy_session_ = spdy_session;
783     return OK;
784   } else if (request_ && (using_ssl_ || ShouldForceSpdyWithoutSSL())) {
785     // Update the spdy session key for the request that launched this job.
786     request_->SetSpdySessionKey(spdy_session_key);
787   } else if (IsRequestEligibleForPipelining()) {
788     // TODO(simonjam): With pipelining, we might be better off using fewer
789     // connections and thus should make fewer preconnections. Explore
790     // preconnecting fewer than the requested num_connections.
791     //
792     // Separate note: A forced pipeline is always available if one exists for
793     // this key. This is different than normal pipelines, which may be
794     // unavailable or unusable. So, there is no need to worry about a race
795     // between when a pipeline becomes available and when this job blocks.
796     existing_available_pipeline_ = stream_factory_->http_pipelined_host_pool_.
797         IsExistingPipelineAvailableForKey(*http_pipelining_key_.get());
798     if (existing_available_pipeline_) {
799       return OK;
800     } else {
801       bool was_new_key = request_->SetHttpPipeliningKey(
802           *http_pipelining_key_.get());
803       if (!was_new_key && session_->force_http_pipelining()) {
804         return ERR_IO_PENDING;
805       }
806     }
807   }
808
809   // OK, there's no available SPDY session. Let |waiting_job_| resume if it's
810   // paused.
811
812   if (waiting_job_) {
813     waiting_job_->Resume(this);
814     waiting_job_ = NULL;
815   }
816
817   if (proxy_info_.is_http() || proxy_info_.is_https())
818     establishing_tunnel_ = using_ssl_;
819
820   bool want_spdy_over_npn = original_url_ != NULL;
821
822   if (proxy_info_.is_https()) {
823     InitSSLConfig(proxy_info_.proxy_server().host_port_pair(),
824                   &proxy_ssl_config_,
825                   true /* is a proxy server */);
826     // Disable revocation checking for HTTPS proxies since the revocation
827     // requests are probably going to need to go through the proxy too.
828     proxy_ssl_config_.rev_checking_enabled = false;
829   }
830   if (using_ssl_) {
831     InitSSLConfig(origin_, &server_ssl_config_,
832                   false /* not a proxy server */);
833   }
834
835   if (IsPreconnecting()) {
836     DCHECK(!stream_factory_->for_websockets_);
837     return PreconnectSocketsForHttpRequest(
838         origin_url_,
839         request_info_.extra_headers,
840         request_info_.load_flags,
841         priority_,
842         session_,
843         proxy_info_,
844         ShouldForceSpdySSL(),
845         want_spdy_over_npn,
846         server_ssl_config_,
847         proxy_ssl_config_,
848         request_info_.privacy_mode,
849         net_log_,
850         num_streams_);
851   } else {
852     // If we can't use a SPDY session, don't both checking for one after
853     // the hostname is resolved.
854     OnHostResolutionCallback resolution_callback = CanUseExistingSpdySession() ?
855         base::Bind(&Job::OnHostResolution, session_->spdy_session_pool(),
856                    GetSpdySessionKey()) :
857         OnHostResolutionCallback();
858     if (stream_factory_->for_websockets_) {
859       // TODO(ricea): Re-enable NPN when WebSockets over SPDY is supported.
860       SSLConfig websocket_server_ssl_config = server_ssl_config_;
861       websocket_server_ssl_config.next_protos.clear();
862       return InitSocketHandleForWebSocketRequest(
863           origin_url_, request_info_.extra_headers, request_info_.load_flags,
864           priority_, session_, proxy_info_, ShouldForceSpdySSL(),
865           want_spdy_over_npn, websocket_server_ssl_config, proxy_ssl_config_,
866           request_info_.privacy_mode, net_log_,
867           connection_.get(), resolution_callback, io_callback_);
868     }
869     return InitSocketHandleForHttpRequest(
870         origin_url_, request_info_.extra_headers, request_info_.load_flags,
871         priority_, session_, proxy_info_, ShouldForceSpdySSL(),
872         want_spdy_over_npn, server_ssl_config_, proxy_ssl_config_,
873         request_info_.privacy_mode, net_log_,
874         connection_.get(), resolution_callback, io_callback_);
875   }
876 }
877
878 int HttpStreamFactoryImpl::Job::DoInitConnectionComplete(int result) {
879   if (IsPreconnecting()) {
880     if (using_quic_)
881       return result;
882     DCHECK_EQ(OK, result);
883     return OK;
884   }
885
886   if (result == ERR_SPDY_SESSION_ALREADY_EXISTS) {
887     // We found a SPDY connection after resolving the host.  This is
888     // probably an IP pooled connection.
889     SpdySessionKey spdy_session_key = GetSpdySessionKey();
890     existing_spdy_session_ =
891         session_->spdy_session_pool()->FindAvailableSession(
892             spdy_session_key, net_log_);
893     if (existing_spdy_session_) {
894       using_spdy_ = true;
895       next_state_ = STATE_CREATE_STREAM;
896     } else {
897       // It is possible that the spdy session no longer exists.
898       ReturnToStateInitConnection(true /* close connection */);
899     }
900     return OK;
901   }
902
903   // TODO(willchan): Make this a bit more exact. Maybe there are recoverable
904   // errors, such as ignoring certificate errors for Alternate-Protocol.
905   if (result < 0 && waiting_job_) {
906     waiting_job_->Resume(this);
907     waiting_job_ = NULL;
908   }
909
910   if (result < 0 && session_->force_http_pipelining()) {
911     stream_factory_->AbortPipelinedRequestsWithKey(
912         this, *http_pipelining_key_.get(), result, server_ssl_config_);
913   }
914
915   // |result| may be the result of any of the stacked pools. The following
916   // logic is used when determining how to interpret an error.
917   // If |result| < 0:
918   //   and connection_->socket() != NULL, then the SSL handshake ran and it
919   //     is a potentially recoverable error.
920   //   and connection_->socket == NULL and connection_->is_ssl_error() is true,
921   //     then the SSL handshake ran with an unrecoverable error.
922   //   otherwise, the error came from one of the other pools.
923   bool ssl_started = using_ssl_ && (result == OK || connection_->socket() ||
924                                     connection_->is_ssl_error());
925
926   if (ssl_started && (result == OK || IsCertificateError(result))) {
927     if (using_quic_ && result == OK) {
928       was_npn_negotiated_ = true;
929       NextProto protocol_negotiated =
930           SSLClientSocket::NextProtoFromString("quic/1+spdy/3");
931       protocol_negotiated_ = protocol_negotiated;
932     } else {
933       SSLClientSocket* ssl_socket =
934           static_cast<SSLClientSocket*>(connection_->socket());
935       if (ssl_socket->WasNpnNegotiated()) {
936         was_npn_negotiated_ = true;
937         std::string proto;
938         std::string server_protos;
939         SSLClientSocket::NextProtoStatus status =
940             ssl_socket->GetNextProto(&proto, &server_protos);
941         NextProto protocol_negotiated =
942             SSLClientSocket::NextProtoFromString(proto);
943         protocol_negotiated_ = protocol_negotiated;
944         net_log_.AddEvent(
945             NetLog::TYPE_HTTP_STREAM_REQUEST_PROTO,
946             base::Bind(&NetLogHttpStreamProtoCallback,
947                        status, &proto, &server_protos));
948         if (ssl_socket->was_spdy_negotiated())
949           SwitchToSpdyMode();
950       }
951       if (ShouldForceSpdySSL())
952         SwitchToSpdyMode();
953     }
954   } else if (proxy_info_.is_https() && connection_->socket() &&
955         result == OK) {
956     ProxyClientSocket* proxy_socket =
957       static_cast<ProxyClientSocket*>(connection_->socket());
958     if (proxy_socket->IsUsingSpdy()) {
959       was_npn_negotiated_ = true;
960       protocol_negotiated_ = proxy_socket->GetProtocolNegotiated();
961       SwitchToSpdyMode();
962     }
963   }
964
965   // We may be using spdy without SSL
966   if (ShouldForceSpdyWithoutSSL())
967     SwitchToSpdyMode();
968
969   if (result == ERR_PROXY_AUTH_REQUESTED ||
970       result == ERR_HTTPS_PROXY_TUNNEL_RESPONSE) {
971     DCHECK(!ssl_started);
972     // Other state (i.e. |using_ssl_|) suggests that |connection_| will have an
973     // SSL socket, but there was an error before that could happen.  This
974     // puts the in progress HttpProxy socket into |connection_| in order to
975     // complete the auth (or read the response body).  The tunnel restart code
976     // is careful to remove it before returning control to the rest of this
977     // class.
978     connection_.reset(connection_->release_pending_http_proxy_connection());
979     return result;
980   }
981
982   if (!ssl_started && result < 0 && original_url_.get()) {
983     // Mark the alternate protocol as broken and fallback.
984     session_->http_server_properties()->SetBrokenAlternateProtocol(
985         HostPortPair::FromURL(*original_url_));
986     return result;
987   }
988
989   if (using_quic_) {
990     if (result < 0)
991       return result;
992     stream_ = quic_request_.ReleaseStream();
993     next_state_ = STATE_NONE;
994     return OK;
995   }
996
997   if (result < 0 && !ssl_started)
998     return ReconsiderProxyAfterError(result);
999   establishing_tunnel_ = false;
1000
1001   if (connection_->socket()) {
1002     LogHttpConnectedMetrics(*connection_);
1003
1004     // We officially have a new connection.  Record the type.
1005     if (!connection_->is_reused()) {
1006       ConnectionType type = using_spdy_ ? CONNECTION_SPDY : CONNECTION_HTTP;
1007       UpdateConnectionTypeHistograms(type);
1008     }
1009   }
1010
1011   // Handle SSL errors below.
1012   if (using_ssl_) {
1013     DCHECK(ssl_started);
1014     if (IsCertificateError(result)) {
1015       if (using_spdy_ && original_url_.get() &&
1016           original_url_->SchemeIs("http")) {
1017         // We ignore certificate errors for http over spdy.
1018         spdy_certificate_error_ = result;
1019         result = OK;
1020       } else {
1021         result = HandleCertificateError(result);
1022         if (result == OK && !connection_->socket()->IsConnectedAndIdle()) {
1023           ReturnToStateInitConnection(true /* close connection */);
1024           return result;
1025         }
1026       }
1027     }
1028     if (result < 0)
1029       return result;
1030   }
1031
1032   next_state_ = STATE_CREATE_STREAM;
1033   return OK;
1034 }
1035
1036 int HttpStreamFactoryImpl::Job::DoWaitingUserAction(int result) {
1037   // This state indicates that the stream request is in a partially
1038   // completed state, and we've called back to the delegate for more
1039   // information.
1040
1041   // We're always waiting here for the delegate to call us back.
1042   return ERR_IO_PENDING;
1043 }
1044
1045 int HttpStreamFactoryImpl::Job::DoCreateStream() {
1046   DCHECK(connection_->socket() || existing_spdy_session_.get() ||
1047          existing_available_pipeline_ || using_quic_);
1048
1049   next_state_ = STATE_CREATE_STREAM_COMPLETE;
1050
1051   // We only set the socket motivation if we're the first to use
1052   // this socket.  Is there a race for two SPDY requests?  We really
1053   // need to plumb this through to the connect level.
1054   if (connection_->socket() && !connection_->is_reused())
1055     SetSocketMotivation();
1056
1057   if (!using_spdy_) {
1058     // We may get ftp scheme when fetching ftp resources through proxy.
1059     bool using_proxy = (proxy_info_.is_http() || proxy_info_.is_https()) &&
1060                        (request_info_.url.SchemeIs("http") ||
1061                         request_info_.url.SchemeIs("ftp"));
1062     if (stream_factory_->http_pipelined_host_pool_.
1063             IsExistingPipelineAvailableForKey(*http_pipelining_key_.get())) {
1064       DCHECK(!stream_factory_->for_websockets_);
1065       stream_.reset(stream_factory_->http_pipelined_host_pool_.
1066                     CreateStreamOnExistingPipeline(
1067                         *http_pipelining_key_.get()));
1068       CHECK(stream_.get());
1069     } else if (stream_factory_->for_websockets_) {
1070       DCHECK(request_);
1071       DCHECK(request_->websocket_handshake_stream_create_helper());
1072       websocket_stream_.reset(
1073           request_->websocket_handshake_stream_create_helper()
1074               ->CreateBasicStream(connection_.Pass(), using_proxy));
1075     } else if (!using_proxy && IsRequestEligibleForPipelining()) {
1076       // TODO(simonjam): Support proxies.
1077       stream_.reset(
1078           stream_factory_->http_pipelined_host_pool_.CreateStreamOnNewPipeline(
1079               *http_pipelining_key_.get(),
1080               connection_.release(),
1081               server_ssl_config_,
1082               proxy_info_,
1083               net_log_,
1084               was_npn_negotiated_,
1085               protocol_negotiated_));
1086       CHECK(stream_.get());
1087     } else {
1088       stream_.reset(new HttpBasicStream(connection_.release(), using_proxy));
1089     }
1090     return OK;
1091   }
1092
1093   CHECK(!stream_.get());
1094
1095   bool direct = true;
1096   const ProxyServer& proxy_server = proxy_info_.proxy_server();
1097   PrivacyMode privacy_mode = request_info_.privacy_mode;
1098   SpdySessionKey spdy_session_key(origin_, proxy_server, privacy_mode);
1099   if (IsHttpsProxyAndHttpUrl()) {
1100     // If we don't have a direct SPDY session, and we're using an HTTPS
1101     // proxy, then we might have a SPDY session to the proxy.
1102     // We never use privacy mode for connection to proxy server.
1103     spdy_session_key = SpdySessionKey(proxy_server.host_port_pair(),
1104                                       ProxyServer::Direct(),
1105                                       kPrivacyModeDisabled);
1106     direct = false;
1107   }
1108
1109   base::WeakPtr<SpdySession> spdy_session;
1110   if (existing_spdy_session_.get()) {
1111     // We picked up an existing session, so we don't need our socket.
1112     if (connection_->socket())
1113       connection_->socket()->Disconnect();
1114     connection_->Reset();
1115     std::swap(spdy_session, existing_spdy_session_);
1116   } else {
1117     SpdySessionPool* spdy_pool = session_->spdy_session_pool();
1118     spdy_session = spdy_pool->FindAvailableSession(spdy_session_key, net_log_);
1119     if (!spdy_session) {
1120       int error =
1121           spdy_pool->CreateAvailableSessionFromSocket(spdy_session_key,
1122                                                       connection_.Pass(),
1123                                                       net_log_,
1124                                                       spdy_certificate_error_,
1125                                                       &new_spdy_session_,
1126                                                       using_ssl_);
1127       if (error != OK)
1128         return error;
1129       const HostPortPair& host_port_pair = spdy_session_key.host_port_pair();
1130       base::WeakPtr<HttpServerProperties> http_server_properties =
1131           session_->http_server_properties();
1132       if (http_server_properties)
1133         http_server_properties->SetSupportsSpdy(host_port_pair, true);
1134       spdy_session_direct_ = direct;
1135       return OK;
1136     }
1137   }
1138
1139   if (!spdy_session)
1140     return ERR_CONNECTION_CLOSED;
1141
1142   // TODO(willchan): Delete this code, because eventually, the
1143   // HttpStreamFactoryImpl will be creating all the SpdyHttpStreams, since it
1144   // will know when SpdySessions become available.
1145
1146   if (stream_factory_->for_websockets_) {
1147     // TODO(ricea): Restore this code when WebSockets over SPDY is implemented.
1148     NOTREACHED();
1149   } else {
1150     bool use_relative_url = direct || request_info_.url.SchemeIs("https");
1151     stream_.reset(new SpdyHttpStream(spdy_session, use_relative_url));
1152   }
1153   return OK;
1154 }
1155
1156 int HttpStreamFactoryImpl::Job::DoCreateStreamComplete(int result) {
1157   if (result < 0)
1158     return result;
1159
1160   session_->proxy_service()->ReportSuccess(proxy_info_);
1161   next_state_ = STATE_NONE;
1162   return OK;
1163 }
1164
1165 int HttpStreamFactoryImpl::Job::DoRestartTunnelAuth() {
1166   next_state_ = STATE_RESTART_TUNNEL_AUTH_COMPLETE;
1167   ProxyClientSocket* proxy_socket =
1168       static_cast<ProxyClientSocket*>(connection_->socket());
1169   return proxy_socket->RestartWithAuth(io_callback_);
1170 }
1171
1172 int HttpStreamFactoryImpl::Job::DoRestartTunnelAuthComplete(int result) {
1173   if (result == ERR_PROXY_AUTH_REQUESTED)
1174     return result;
1175
1176   if (result == OK) {
1177     // Now that we've got the HttpProxyClientSocket connected.  We have
1178     // to release it as an idle socket into the pool and start the connection
1179     // process from the beginning.  Trying to pass it in with the
1180     // SSLSocketParams might cause a deadlock since params are dispatched
1181     // interchangeably.  This request won't necessarily get this http proxy
1182     // socket, but there will be forward progress.
1183     establishing_tunnel_ = false;
1184     ReturnToStateInitConnection(false /* do not close connection */);
1185     return OK;
1186   }
1187
1188   return ReconsiderProxyAfterError(result);
1189 }
1190
1191 void HttpStreamFactoryImpl::Job::ReturnToStateInitConnection(
1192     bool close_connection) {
1193   if (close_connection && connection_->socket())
1194     connection_->socket()->Disconnect();
1195   connection_->Reset();
1196
1197   if (request_) {
1198     request_->RemoveRequestFromSpdySessionRequestMap();
1199     request_->RemoveRequestFromHttpPipeliningRequestMap();
1200   }
1201
1202   next_state_ = STATE_INIT_CONNECTION;
1203 }
1204
1205 void HttpStreamFactoryImpl::Job::SetSocketMotivation() {
1206   if (request_info_.motivation == HttpRequestInfo::PRECONNECT_MOTIVATED)
1207     connection_->socket()->SetSubresourceSpeculation();
1208   else if (request_info_.motivation == HttpRequestInfo::OMNIBOX_MOTIVATED)
1209     connection_->socket()->SetOmniboxSpeculation();
1210   // TODO(mbelshe): Add other motivations (like EARLY_LOAD_MOTIVATED).
1211 }
1212
1213 bool HttpStreamFactoryImpl::Job::IsHttpsProxyAndHttpUrl() const {
1214   if (!proxy_info_.is_https())
1215     return false;
1216   if (original_url_.get()) {
1217     // We currently only support Alternate-Protocol where the original scheme
1218     // is http.
1219     DCHECK(original_url_->SchemeIs("http"));
1220     return original_url_->SchemeIs("http");
1221   }
1222   return request_info_.url.SchemeIs("http");
1223 }
1224
1225 // Sets several fields of ssl_config for the given origin_server based on the
1226 // proxy info and other factors.
1227 void HttpStreamFactoryImpl::Job::InitSSLConfig(
1228     const HostPortPair& origin_server,
1229     SSLConfig* ssl_config,
1230     bool is_proxy) const {
1231   if (proxy_info_.is_https() && ssl_config->send_client_cert) {
1232     // When connecting through an HTTPS proxy, disable TLS False Start so
1233     // that client authentication errors can be distinguished between those
1234     // originating from the proxy server (ERR_PROXY_CONNECTION_FAILED) and
1235     // those originating from the endpoint (ERR_SSL_PROTOCOL_ERROR /
1236     // ERR_BAD_SSL_CLIENT_AUTH_CERT).
1237     // TODO(rch): This assumes that the HTTPS proxy will only request a
1238     // client certificate during the initial handshake.
1239     // http://crbug.com/59292
1240     ssl_config->false_start_enabled = false;
1241   }
1242
1243   enum {
1244     FALLBACK_NONE = 0,    // SSL version fallback did not occur.
1245     FALLBACK_SSL3 = 1,    // Fell back to SSL 3.0.
1246     FALLBACK_TLS1 = 2,    // Fell back to TLS 1.0.
1247     FALLBACK_TLS1_1 = 3,  // Fell back to TLS 1.1.
1248     FALLBACK_MAX
1249   };
1250
1251   int fallback = FALLBACK_NONE;
1252   if (ssl_config->version_fallback) {
1253     switch (ssl_config->version_max) {
1254       case SSL_PROTOCOL_VERSION_SSL3:
1255         fallback = FALLBACK_SSL3;
1256         break;
1257       case SSL_PROTOCOL_VERSION_TLS1:
1258         fallback = FALLBACK_TLS1;
1259         break;
1260       case SSL_PROTOCOL_VERSION_TLS1_1:
1261         fallback = FALLBACK_TLS1_1;
1262         break;
1263     }
1264   }
1265   UMA_HISTOGRAM_ENUMERATION("Net.ConnectionUsedSSLVersionFallback",
1266                             fallback, FALLBACK_MAX);
1267
1268   // We also wish to measure the amount of fallback connections for a host that
1269   // we know implements TLS up to 1.2. Ideally there would be no fallback here
1270   // but high numbers of SSLv3 would suggest that SSLv3 fallback is being
1271   // caused by network middleware rather than buggy HTTPS servers.
1272   const std::string& host = origin_server.host();
1273   if (!is_proxy &&
1274       host.size() >= 10 &&
1275       host.compare(host.size() - 10, 10, "google.com") == 0 &&
1276       (host.size() == 10 || host[host.size()-11] == '.')) {
1277     UMA_HISTOGRAM_ENUMERATION("Net.GoogleConnectionUsedSSLVersionFallback",
1278                               fallback, FALLBACK_MAX);
1279   }
1280
1281   if (request_info_.load_flags & LOAD_VERIFY_EV_CERT)
1282     ssl_config->verify_ev_cert = true;
1283
1284   // Disable Channel ID if privacy mode is enabled.
1285   if (request_info_.privacy_mode == kPrivacyModeEnabled)
1286     ssl_config->channel_id_enabled = false;
1287 }
1288
1289
1290 int HttpStreamFactoryImpl::Job::ReconsiderProxyAfterError(int error) {
1291   DCHECK(!pac_request_);
1292
1293   // A failure to resolve the hostname or any error related to establishing a
1294   // TCP connection could be grounds for trying a new proxy configuration.
1295   //
1296   // Why do this when a hostname cannot be resolved?  Some URLs only make sense
1297   // to proxy servers.  The hostname in those URLs might fail to resolve if we
1298   // are still using a non-proxy config.  We need to check if a proxy config
1299   // now exists that corresponds to a proxy server that could load the URL.
1300   //
1301   switch (error) {
1302     case ERR_PROXY_CONNECTION_FAILED:
1303     case ERR_NAME_NOT_RESOLVED:
1304     case ERR_INTERNET_DISCONNECTED:
1305     case ERR_ADDRESS_UNREACHABLE:
1306     case ERR_CONNECTION_CLOSED:
1307     case ERR_CONNECTION_TIMED_OUT:
1308     case ERR_CONNECTION_RESET:
1309     case ERR_CONNECTION_REFUSED:
1310     case ERR_CONNECTION_ABORTED:
1311     case ERR_TIMED_OUT:
1312     case ERR_TUNNEL_CONNECTION_FAILED:
1313     case ERR_SOCKS_CONNECTION_FAILED:
1314     // This can happen in the case of trying to talk to a proxy using SSL, and
1315     // ending up talking to a captive portal that supports SSL instead.
1316     case ERR_PROXY_CERTIFICATE_INVALID:
1317     // This can happen when trying to talk SSL to a non-SSL server (Like a
1318     // captive portal).
1319     case ERR_SSL_PROTOCOL_ERROR:
1320       break;
1321     case ERR_SOCKS_CONNECTION_HOST_UNREACHABLE:
1322       // Remap the SOCKS-specific "host unreachable" error to a more
1323       // generic error code (this way consumers like the link doctor
1324       // know to substitute their error page).
1325       //
1326       // Note that if the host resolving was done by the SOCKS5 proxy, we can't
1327       // differentiate between a proxy-side "host not found" versus a proxy-side
1328       // "address unreachable" error, and will report both of these failures as
1329       // ERR_ADDRESS_UNREACHABLE.
1330       return ERR_ADDRESS_UNREACHABLE;
1331     default:
1332       return error;
1333   }
1334
1335   if (request_info_.load_flags & LOAD_BYPASS_PROXY) {
1336     return error;
1337   }
1338
1339   if (proxy_info_.is_https() && proxy_ssl_config_.send_client_cert) {
1340     session_->ssl_client_auth_cache()->Remove(
1341         proxy_info_.proxy_server().host_port_pair());
1342   }
1343
1344   int rv = session_->proxy_service()->ReconsiderProxyAfterError(
1345       request_info_.url, &proxy_info_, io_callback_, &pac_request_, net_log_);
1346   if (rv == OK || rv == ERR_IO_PENDING) {
1347     // If the error was during connection setup, there is no socket to
1348     // disconnect.
1349     if (connection_->socket())
1350       connection_->socket()->Disconnect();
1351     connection_->Reset();
1352     if (request_) {
1353       request_->RemoveRequestFromSpdySessionRequestMap();
1354       request_->RemoveRequestFromHttpPipeliningRequestMap();
1355     }
1356     next_state_ = STATE_RESOLVE_PROXY_COMPLETE;
1357   } else {
1358     // If ReconsiderProxyAfterError() failed synchronously, it means
1359     // there was nothing left to fall-back to, so fail the transaction
1360     // with the last connection error we got.
1361     // TODO(eroman): This is a confusing contract, make it more obvious.
1362     rv = error;
1363   }
1364
1365   return rv;
1366 }
1367
1368 int HttpStreamFactoryImpl::Job::HandleCertificateError(int error) {
1369   DCHECK(using_ssl_);
1370   DCHECK(IsCertificateError(error));
1371
1372   SSLClientSocket* ssl_socket =
1373       static_cast<SSLClientSocket*>(connection_->socket());
1374   ssl_socket->GetSSLInfo(&ssl_info_);
1375
1376   // Add the bad certificate to the set of allowed certificates in the
1377   // SSL config object. This data structure will be consulted after calling
1378   // RestartIgnoringLastError(). And the user will be asked interactively
1379   // before RestartIgnoringLastError() is ever called.
1380   SSLConfig::CertAndStatus bad_cert;
1381
1382   // |ssl_info_.cert| may be NULL if we failed to create
1383   // X509Certificate for whatever reason, but normally it shouldn't
1384   // happen, unless this code is used inside sandbox.
1385   if (ssl_info_.cert.get() == NULL ||
1386       !X509Certificate::GetDEREncoded(ssl_info_.cert->os_cert_handle(),
1387                                       &bad_cert.der_cert)) {
1388     return error;
1389   }
1390   bad_cert.cert_status = ssl_info_.cert_status;
1391   server_ssl_config_.allowed_bad_certs.push_back(bad_cert);
1392
1393   int load_flags = request_info_.load_flags;
1394   if (session_->params().ignore_certificate_errors)
1395     load_flags |= LOAD_IGNORE_ALL_CERT_ERRORS;
1396   if (ssl_socket->IgnoreCertError(error, load_flags))
1397     return OK;
1398   return error;
1399 }
1400
1401 void HttpStreamFactoryImpl::Job::SwitchToSpdyMode() {
1402   if (HttpStreamFactory::spdy_enabled())
1403     using_spdy_ = true;
1404 }
1405
1406 // static
1407 void HttpStreamFactoryImpl::Job::LogHttpConnectedMetrics(
1408     const ClientSocketHandle& handle) {
1409   UMA_HISTOGRAM_ENUMERATION("Net.HttpSocketType", handle.reuse_type(),
1410                             ClientSocketHandle::NUM_TYPES);
1411
1412   switch (handle.reuse_type()) {
1413     case ClientSocketHandle::UNUSED:
1414       UMA_HISTOGRAM_CUSTOM_TIMES("Net.HttpConnectionLatency",
1415                                  handle.setup_time(),
1416                                  base::TimeDelta::FromMilliseconds(1),
1417                                  base::TimeDelta::FromMinutes(10),
1418                                  100);
1419       break;
1420     case ClientSocketHandle::UNUSED_IDLE:
1421       UMA_HISTOGRAM_CUSTOM_TIMES("Net.SocketIdleTimeBeforeNextUse_UnusedSocket",
1422                                  handle.idle_time(),
1423                                  base::TimeDelta::FromMilliseconds(1),
1424                                  base::TimeDelta::FromMinutes(6),
1425                                  100);
1426       break;
1427     case ClientSocketHandle::REUSED_IDLE:
1428       UMA_HISTOGRAM_CUSTOM_TIMES("Net.SocketIdleTimeBeforeNextUse_ReusedSocket",
1429                                  handle.idle_time(),
1430                                  base::TimeDelta::FromMilliseconds(1),
1431                                  base::TimeDelta::FromMinutes(6),
1432                                  100);
1433       break;
1434     default:
1435       NOTREACHED();
1436       break;
1437   }
1438 }
1439
1440 bool HttpStreamFactoryImpl::Job::IsPreconnecting() const {
1441   DCHECK_GE(num_streams_, 0);
1442   return num_streams_ > 0;
1443 }
1444
1445 bool HttpStreamFactoryImpl::Job::IsOrphaned() const {
1446   return !IsPreconnecting() && !request_;
1447 }
1448
1449 bool HttpStreamFactoryImpl::Job::IsRequestEligibleForPipelining() {
1450   if (IsPreconnecting() || !request_) {
1451     return false;
1452   }
1453   if (stream_factory_->for_websockets_) {
1454     return false;
1455   }
1456   if (session_->force_http_pipelining()) {
1457     return true;
1458   }
1459   if (!session_->params().http_pipelining_enabled) {
1460     return false;
1461   }
1462   if (using_ssl_) {
1463     return false;
1464   }
1465   if (request_info_.method != "GET" && request_info_.method != "HEAD") {
1466     return false;
1467   }
1468   if (request_info_.load_flags &
1469       (net::LOAD_MAIN_FRAME | net::LOAD_SUB_FRAME | net::LOAD_PREFETCH |
1470        net::LOAD_IS_DOWNLOAD)) {
1471     // Avoid pipelining resources that may be streamed for a long time.
1472     return false;
1473   }
1474   return stream_factory_->http_pipelined_host_pool_.IsKeyEligibleForPipelining(
1475       *http_pipelining_key_.get());
1476 }
1477
1478 }  // namespace net