1dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Use of this source code is governed by a BSD-style license that can be
3dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// found in the LICENSE file.
4dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
5dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/http/http_stream_factory_impl_request.h"
6dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
7dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/logging.h"
8dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/stl_util-inl.h"
9dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/http/http_stream_factory_impl_job.h"
10dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/spdy/spdy_http_stream.h"
11dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/spdy/spdy_session.h"
12dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
13dc0f95d653279beabeb9817299e2902918ba123eKristian Monsennamespace net {
14dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
15dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenHttpStreamFactoryImpl::Request::Request(const GURL& url,
16dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                        HttpStreamFactoryImpl* factory,
17dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                        HttpStreamRequest::Delegate* delegate,
18dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                        const BoundNetLog& net_log)
19dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    : url_(url),
20dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      factory_(factory),
21dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      delegate_(delegate),
22dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      net_log_(net_log),
23dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      completed_(false),
24dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      was_npn_negotiated_(false),
25dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      using_spdy_(false) {
26dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(factory_);
27dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(delegate_);
28dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
29dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  net_log_.BeginEvent(NetLog::TYPE_HTTP_STREAM_REQUEST, NULL);
30dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
32dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenHttpStreamFactoryImpl::Request::~Request() {
33dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (bound_job_.get())
34dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DCHECK(jobs_.empty());
35dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  else
36dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DCHECK(!jobs_.empty());
37dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
38dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  net_log_.EndEvent(NetLog::TYPE_HTTP_STREAM_REQUEST, NULL);
39dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
40dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  for (std::set<Job*>::iterator it = jobs_.begin(); it != jobs_.end(); ++it)
41dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    factory_->request_map_.erase(*it);
42dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
43dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  STLDeleteElements(&jobs_);
44dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
45dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  RemoveRequestFromSpdySessionRequestMap();
46dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
47dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
48dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpStreamFactoryImpl::Request::SetSpdySessionKey(
49dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const HostPortProxyPair& spdy_session_key) {
50dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(!spdy_session_key_.get());
51dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  spdy_session_key_.reset(new HostPortProxyPair(spdy_session_key));
52dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  RequestSet& request_set =
53dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      factory_->spdy_session_request_map_[spdy_session_key];
54dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(!ContainsKey(request_set, this));
55dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  request_set.insert(this);
56dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
57dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
58dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpStreamFactoryImpl::Request::AttachJob(Job* job) {
59dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(job);
60dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  jobs_.insert(job);
61dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  factory_->request_map_[job] = this;
62dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
63dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
64dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpStreamFactoryImpl::Request::Complete(
65dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    bool was_npn_negotiated,
66dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    bool using_spdy,
67dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const NetLog::Source& job_source) {
68dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(!completed_);
69dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  completed_ = true;
70dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  was_npn_negotiated_ = was_npn_negotiated;
71dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  using_spdy_ = using_spdy;
72dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  net_log_.AddEvent(
73dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      NetLog::TYPE_HTTP_STREAM_REQUEST_BOUND_TO_JOB,
74dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      make_scoped_refptr(new NetLogSourceParameter(
75dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          "source_dependency", job_source)));
76dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
77dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
78dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpStreamFactoryImpl::Request::OnStreamReady(
79dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    Job* job,
80dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const SSLConfig& used_ssl_config,
81dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const ProxyInfo& used_proxy_info,
82dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    HttpStream* stream) {
83dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(stream);
84dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(completed_);
85dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
86dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // |job| should only be NULL if we're being serviced by a late bound
87dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // SpdySession (one that was not created by a job in our |jobs_| set).
88dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!job) {
89dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DCHECK(!bound_job_.get());
90dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DCHECK(!jobs_.empty());
91dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // NOTE(willchan): We do *NOT* call OrphanJobs() here. The reason is because
92dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // we *WANT* to cancel the unnecessary Jobs from other requests if another
93dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // Job completes first.
94dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // TODO(mbelshe): Revisit this when we implement ip connection pooling of
95dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // SpdySessions. Do we want to orphan the jobs for a different hostname so
96dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // they complete? Or do we want to prevent connecting a new SpdySession if
97dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // we've already got one available for a different hostname where the ip
98dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // address matches up?
99dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  } else if (!bound_job_.get()) {
100dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // We may have other jobs in |jobs_|. For example, if we start multiple jobs
101dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // for Alternate-Protocol.
102dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    OrphanJobsExcept(job);
103dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  } else {
104dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DCHECK(jobs_.empty());
105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
106dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  delegate_->OnStreamReady(used_ssl_config, used_proxy_info, stream);
107dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
108dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
109dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpStreamFactoryImpl::Request::OnStreamFailed(
110dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    Job* job,
111dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    int status,
112dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const SSLConfig& used_ssl_config) {
113dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK_NE(OK, status);
114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!bound_job_.get()) {
115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // Hey, we've got other jobs! Maybe one of them will succeed, let's just
116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // ignore this failure.
117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (jobs_.size() > 1) {
118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      jobs_.erase(job);
119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      factory_->request_map_.erase(job);
120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      delete job;
121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return;
122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    } else {
123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      bound_job_.reset(job);
124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      jobs_.erase(job);
125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      DCHECK(jobs_.empty());
126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      factory_->request_map_.erase(job);
127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else {
129dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DCHECK(jobs_.empty());
130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
131dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  delegate_->OnStreamFailed(status, used_ssl_config);
132dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
133dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
134dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpStreamFactoryImpl::Request::OnCertificateError(
135dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    Job* job,
136dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    int status,
137dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const SSLConfig& used_ssl_config,
138dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const SSLInfo& ssl_info) {
139dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK_NE(OK, status);
140dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!bound_job_.get())
141dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    OrphanJobsExcept(job);
142dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  else
143dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DCHECK(jobs_.empty());
144dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  delegate_->OnCertificateError(status, used_ssl_config, ssl_info);
145dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
146dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
147dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpStreamFactoryImpl::Request::OnNeedsProxyAuth(
148dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    Job* job,
149dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const HttpResponseInfo& proxy_response,
150dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const SSLConfig& used_ssl_config,
151dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const ProxyInfo& used_proxy_info,
152dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    HttpAuthController* auth_controller) {
153dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!bound_job_.get())
154dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    OrphanJobsExcept(job);
155dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  else
156dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DCHECK(jobs_.empty());
157dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  delegate_->OnNeedsProxyAuth(
158dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      proxy_response, used_ssl_config, used_proxy_info, auth_controller);
159dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
160dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
161dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpStreamFactoryImpl::Request::OnNeedsClientAuth(
162dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    Job* job,
163dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const SSLConfig& used_ssl_config,
164dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    SSLCertRequestInfo* cert_info) {
165dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!bound_job_.get())
166dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    OrphanJobsExcept(job);
167dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  else
168dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DCHECK(jobs_.empty());
169dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  delegate_->OnNeedsClientAuth(used_ssl_config, cert_info);
170dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
171dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
172dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpStreamFactoryImpl::Request::OnHttpsProxyTunnelResponse(
173dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    Job *job,
174dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const HttpResponseInfo& response_info,
175dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const SSLConfig& used_ssl_config,
176dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const ProxyInfo& used_proxy_info,
177dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    HttpStream* stream) {
178dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!bound_job_.get())
179dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    OrphanJobsExcept(job);
180dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  else
181dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DCHECK(jobs_.empty());
182dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  delegate_->OnHttpsProxyTunnelResponse(
183dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      response_info, used_ssl_config, used_proxy_info, stream);
184dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
185dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
186dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint HttpStreamFactoryImpl::Request::RestartTunnelWithProxyAuth(
187dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const string16& username,
188dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const string16& password) {
189dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(bound_job_.get());
190dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return bound_job_->RestartTunnelWithProxyAuth(username, password);
191dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
192dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
193dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenLoadState HttpStreamFactoryImpl::Request::GetLoadState() const {
194dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (bound_job_.get())
195dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return bound_job_->GetLoadState();
196dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(!jobs_.empty());
197dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
198dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Just pick the first one.
199dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return (*jobs_.begin())->GetLoadState();
200dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
201dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
202dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool HttpStreamFactoryImpl::Request::was_npn_negotiated() const {
203dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(completed_);
204dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return was_npn_negotiated_;
205dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
206dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
207dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool HttpStreamFactoryImpl::Request::using_spdy() const {
208dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(completed_);
209dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return using_spdy_;
210dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
211dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
212dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid
213dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenHttpStreamFactoryImpl::Request::RemoveRequestFromSpdySessionRequestMap() {
214dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (spdy_session_key_.get()) {
215dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    SpdySessionRequestMap& spdy_session_request_map =
216dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        factory_->spdy_session_request_map_;
217dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DCHECK(ContainsKey(spdy_session_request_map, *spdy_session_key_));
218dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    RequestSet& request_set =
219dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        spdy_session_request_map[*spdy_session_key_];
220dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DCHECK(ContainsKey(request_set, this));
221dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    request_set.erase(this);
222dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (request_set.empty())
223dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      spdy_session_request_map.erase(*spdy_session_key_);
224dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    spdy_session_key_.reset();
225dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
226dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
227dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
228dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpStreamFactoryImpl::Request::OnSpdySessionReady(
229dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    Job* job,
230dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    scoped_refptr<SpdySession> spdy_session,
231dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    bool direct) {
232dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(job);
233dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(job->using_spdy());
234dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
235dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // The first case is the usual case.
236dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!bound_job_.get()) {
237dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    OrphanJobsExcept(job);
238dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  } else { // This is the case for HTTPS proxy tunneling.
239dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DCHECK_EQ(bound_job_.get(), job);
240dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DCHECK(jobs_.empty());
241dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
242dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
243dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Cache these values in case the job gets deleted.
244dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const SSLConfig used_ssl_config = job->ssl_config();
245dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const ProxyInfo used_proxy_info = job->proxy_info();
246dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const bool was_npn_negotiated = job->was_npn_negotiated();
247dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const bool using_spdy = job->using_spdy();
248dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const NetLog::Source source = job->net_log().source();
249dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  Complete(was_npn_negotiated,
251dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen           using_spdy,
252dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen           source);
253dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
254dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Cache this so we can still use it if the request is deleted.
255dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  HttpStreamFactoryImpl* factory = factory_;
256dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
257dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  bool use_relative_url = direct || url().SchemeIs("https");
258dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  delegate_->OnStreamReady(
259dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      job->ssl_config(),
260dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      job->proxy_info(),
261dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      new SpdyHttpStream(spdy_session, use_relative_url));
262dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // |this| may be deleted after this point.
263dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  factory->OnSpdySessionReady(
264dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      spdy_session, direct, used_ssl_config, used_proxy_info,
265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      was_npn_negotiated, using_spdy, source);
266dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
267dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
268dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpStreamFactoryImpl::Request::OrphanJobsExcept(Job* job) {
269dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(job);
270dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(!bound_job_.get());
271dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(ContainsKey(jobs_, job));
272dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  bound_job_.reset(job);
273dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  jobs_.erase(job);
274dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  factory_->request_map_.erase(job);
275dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
276dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  OrphanJobs();
277dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
278dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
279dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpStreamFactoryImpl::Request::OrphanJobs() {
280dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  RemoveRequestFromSpdySessionRequestMap();
281dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
282dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  std::set<Job*> tmp;
283dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  tmp.swap(jobs_);
284dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
285dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  for (std::set<Job*>::iterator it = tmp.begin(); it != tmp.end(); ++it)
286dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    factory_->OrphanJob(*it, this);
287dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
288dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
289dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}  // namespace net
290