15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_stream_factory_impl.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <string>
8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/logging.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_network_session.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_server_properties.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_stream_factory_impl_job.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_stream_factory_impl_request.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_http_stream.h"
197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GURL UpgradeUrlToHttps(const GURL& original_url, int port) {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL::Replacements replacements;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // new_sheme and new_port need to be in scope here because GURL::Replacements
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // references the memory contained by them directly.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string new_scheme = "https";
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string new_port = base::IntToString(port);
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  replacements.SetSchemeStr(new_scheme);
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  replacements.SetPortStr(new_port);
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return original_url.ReplaceComponents(replacements);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochHttpStreamFactoryImpl::HttpStreamFactoryImpl(HttpNetworkSession* session,
39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                             bool for_websockets)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : session_(session),
41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      for_websockets_(for_websockets) {}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpStreamFactoryImpl::~HttpStreamFactoryImpl() {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(request_map_.empty());
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(spdy_session_request_map_.empty());
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<const Job*> tmp_job_set;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmp_job_set.swap(orphaned_job_set_);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteContainerPointers(tmp_job_set.begin(), tmp_job_set.end());
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(orphaned_job_set_.empty());
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmp_job_set.clear();
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tmp_job_set.swap(preconnect_job_set_);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteContainerPointers(tmp_job_set.begin(), tmp_job_set.end());
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(preconnect_job_set_.empty());
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpStreamRequest* HttpStreamFactoryImpl::RequestStream(
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HttpRequestInfo& request_info,
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RequestPriority priority,
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SSLConfig& server_ssl_config,
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SSLConfig& proxy_ssl_config,
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpStreamRequest::Delegate* delegate,
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BoundNetLog& net_log) {
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(!for_websockets_);
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return RequestStreamInternal(request_info,
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               priority,
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               server_ssl_config,
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               proxy_ssl_config,
70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               delegate,
71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               NULL,
72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               net_log);
73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)HttpStreamRequest* HttpStreamFactoryImpl::RequestWebSocketHandshakeStream(
76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const HttpRequestInfo& request_info,
77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    RequestPriority priority,
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const SSLConfig& server_ssl_config,
79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const SSLConfig& proxy_ssl_config,
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    HttpStreamRequest::Delegate* delegate,
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    WebSocketHandshakeStreamBase::CreateHelper* create_helper,
82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const BoundNetLog& net_log) {
83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(for_websockets_);
84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(create_helper);
85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return RequestStreamInternal(request_info,
86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               priority,
87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               server_ssl_config,
88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               proxy_ssl_config,
89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               delegate,
90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                               create_helper,
91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               net_log);
92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochHttpStreamRequest* HttpStreamFactoryImpl::RequestStreamInternal(
95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const HttpRequestInfo& request_info,
96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    RequestPriority priority,
97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const SSLConfig& server_ssl_config,
98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const SSLConfig& proxy_ssl_config,
99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    HttpStreamRequest::Delegate* delegate,
100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    WebSocketHandshakeStreamBase::CreateHelper*
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        websocket_handshake_stream_create_helper,
102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const BoundNetLog& net_log) {
103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  Request* request = new Request(request_info.url,
104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                 this,
105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                 delegate,
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                 websocket_handshake_stream_create_helper,
107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                 net_log);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL alternate_url;
110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  AlternateProtocolInfo alternate =
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetAlternateProtocolRequestFor(request_info.url, &alternate_url);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Job* alternate_job = NULL;
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (alternate.protocol != UNINITIALIZED_ALTERNATE_PROTOCOL) {
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Never share connection with other jobs for FTP requests.
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(!request_info.url.SchemeIs("ftp"));
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpRequestInfo alternate_request_info = request_info;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    alternate_request_info.url = alternate_url;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    alternate_job =
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        new Job(this, session_, alternate_request_info, priority,
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                server_ssl_config, proxy_ssl_config, net_log.net_log());
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request->AttachJob(alternate_job);
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    alternate_job->MarkAsAlternate(request_info.url, alternate);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Job* job = new Job(this, session_, request_info, priority,
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     server_ssl_config, proxy_ssl_config, net_log.net_log());
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request->AttachJob(job);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (alternate_job) {
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Never share connection with other jobs for FTP requests.
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(!request_info.url.SchemeIs("ftp"));
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    job->WaitFor(alternate_job);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Make sure to wait until we call WaitFor(), before starting
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // |alternate_job|, otherwise |alternate_job| will not notify |job|
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // appropriately.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    alternate_job->Start(request);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Even if |alternate_job| has already finished, it won't have notified the
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // request yet, since we defer that to the next iteration of the MessageLoop,
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so starting |job| is always safe.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  job->Start(request);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return request;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpStreamFactoryImpl::PreconnectStreams(
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int num_streams,
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HttpRequestInfo& request_info,
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RequestPriority priority,
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SSLConfig& server_ssl_config,
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SSLConfig& proxy_ssl_config) {
152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(!for_websockets_);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL alternate_url;
154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  AlternateProtocolInfo alternate =
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetAlternateProtocolRequestFor(request_info.url, &alternate_url);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Job* job = NULL;
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (alternate.protocol != UNINITIALIZED_ALTERNATE_PROTOCOL) {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpRequestInfo alternate_request_info = request_info;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    alternate_request_info.url = alternate_url;
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    job = new Job(this, session_, alternate_request_info, priority,
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  server_ssl_config, proxy_ssl_config, session_->net_log());
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    job->MarkAsAlternate(request_info.url, alternate);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    job = new Job(this, session_, request_info, priority,
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  server_ssl_config, proxy_ssl_config, session_->net_log());
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  preconnect_job_set_.insert(job);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  job->Preconnect(num_streams);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const HostMappingRules* HttpStreamFactoryImpl::GetHostMappingRules() const {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return session_->params().host_mapping_rules;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175116680a4aac90f2aa7413d9095a592090648e557Ben MurdochAlternateProtocolInfo HttpStreamFactoryImpl::GetAlternateProtocolRequestFor(
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& original_url,
177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    GURL* alternate_url) {
178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const AlternateProtocolInfo kNoAlternateProtocol =
179116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      AlternateProtocolInfo(0,  UNINITIALIZED_ALTERNATE_PROTOCOL, 0);
180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!session_->params().use_alternate_protocols)
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return kNoAlternateProtocol;
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (original_url.SchemeIs("ftp"))
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return kNoAlternateProtocol;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HostPortPair origin = HostPortPair(original_url.HostNoBrackets(),
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     original_url.EffectiveIntPort());
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  HttpServerProperties& http_server_properties =
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *session_->http_server_properties();
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!http_server_properties.HasAlternateProtocol(origin))
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return kNoAlternateProtocol;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  AlternateProtocolInfo alternate =
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      http_server_properties.GetAlternateProtocol(origin);
197a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (alternate.protocol == ALTERNATE_PROTOCOL_BROKEN) {
198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    HistogramAlternateProtocolUsage(
199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        ALTERNATE_PROTOCOL_USAGE_BROKEN,
200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        http_server_properties.GetAlternateProtocolExperiment());
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return kNoAlternateProtocol;
202a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!IsAlternateProtocolValid(alternate.protocol)) {
2054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    NOTREACHED();
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return kNoAlternateProtocol;
2074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Some shared unix systems may have user home directories (like
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://foo.com/~mike) which allow users to emit headers.  This is a bad
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // idea already, but with Alternate-Protocol, it provides the ability for a
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // single user on a multi-user system to hijack the alternate protocol.
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These systems also enforce ports <1024 as restricted ports.  So don't
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // allow protocol upgrades to user-controllable ports.
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kUnrestrictedPort = 1024;
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!session_->params().enable_user_alternate_protocol_ports &&
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (alternate.port >= kUnrestrictedPort &&
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       origin.port() < kUnrestrictedPort))
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return kNoAlternateProtocol;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  origin.set_port(alternate.port);
222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (alternate.protocol >= NPN_SPDY_MINIMUM_VERSION &&
223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      alternate.protocol <= NPN_SPDY_MAXIMUM_VERSION) {
224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!HttpStreamFactory::spdy_enabled())
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return kNoAlternateProtocol;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (session_->HasSpdyExclusion(origin))
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return kNoAlternateProtocol;
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *alternate_url = UpgradeUrlToHttps(original_url, alternate.port);
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK_EQ(QUIC, alternate.protocol);
233116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (!session_->params().enable_quic)
2347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        return kNoAlternateProtocol;
235116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // TODO(rch):  Figure out how to make QUIC iteract with PAC
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // scripts.  By not re-writing the URL, we will query the PAC script
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // for the proxy to use to reach the original URL via TCP.  But
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // the alternate request will be going via UDP to a different port.
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *alternate_url = original_url;
241eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return alternate;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpStreamFactoryImpl::OrphanJob(Job* job, const Request* request) {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(ContainsKey(request_map_, job));
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(request_map_[job], request);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!ContainsKey(orphaned_job_set_, job));
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_map_.erase(job);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  orphaned_job_set_.insert(job);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  job->Orphan(request);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid HttpStreamFactoryImpl::OnNewSpdySessionReady(
257ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const base::WeakPtr<SpdySession>& spdy_session,
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool direct,
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SSLConfig& used_ssl_config,
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ProxyInfo& used_proxy_info,
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool was_npn_negotiated,
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NextProto protocol_negotiated,
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool using_spdy,
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BoundNetLog& net_log) {
265ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  while (true) {
266ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (!spdy_session)
267ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      break;
268ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const SpdySessionKey& spdy_session_key = spdy_session->spdy_session_key();
269ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // Each iteration may empty out the RequestSet for |spdy_session_key| in
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // |spdy_session_request_map_|. So each time, check for RequestSet and use
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the first one.
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(willchan): If it's important, switch RequestSet out for a FIFO
274ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // queue (Order by priority first, then FIFO within same priority). Unclear
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // that it matters here.
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ContainsKey(spdy_session_request_map_, spdy_session_key))
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Request* request = *spdy_session_request_map_[spdy_session_key].begin();
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request->Complete(was_npn_negotiated,
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      protocol_negotiated,
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      using_spdy,
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      net_log);
283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (for_websockets_) {
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // TODO(ricea): Restore this code path when WebSocket over SPDY
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // implementation is ready.
2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      NOTREACHED();
287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    } else {
288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      bool use_relative_url = direct || request->url().SchemeIs("https");
289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      request->OnStreamReady(
290eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          NULL,
291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          used_ssl_config,
292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          used_proxy_info,
293ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          new SpdyHttpStream(spdy_session, use_relative_url));
294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(mbelshe): Alert other valid requests.
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpStreamFactoryImpl::OnOrphanedJobComplete(const Job* job) {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  orphaned_job_set_.erase(job);
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete job;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpStreamFactoryImpl::OnPreconnectsComplete(const Job* job) {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  preconnect_job_set_.erase(job);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete job;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnPreconnectsCompleteInternal();
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
311