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.
5 #include "net/http/http_pipelined_host_pool.h"
7 #include "base/logging.h"
8 #include "base/stl_util.h"
9 #include "base/values.h"
10 #include "net/http/http_pipelined_host_capability.h"
11 #include "net/http/http_pipelined_host_forced.h"
12 #include "net/http/http_pipelined_host_impl.h"
13 #include "net/http/http_server_properties.h"
17 class HttpPipelinedHostImplFactory
: public HttpPipelinedHost::Factory
{
19 virtual HttpPipelinedHost
* CreateNewHost(
20 HttpPipelinedHost::Delegate
* delegate
,
21 const HttpPipelinedHost::Key
& key
,
22 HttpPipelinedConnection::Factory
* factory
,
23 HttpPipelinedHostCapability capability
,
24 bool force_pipelining
) OVERRIDE
{
25 if (force_pipelining
) {
26 return new HttpPipelinedHostForced(delegate
, key
, factory
);
28 return new HttpPipelinedHostImpl(delegate
, key
, factory
, capability
);
33 HttpPipelinedHostPool::HttpPipelinedHostPool(
35 HttpPipelinedHost::Factory
* factory
,
36 HttpServerProperties
* http_server_properties
,
37 bool force_pipelining
)
38 : delegate_(delegate
),
40 http_server_properties_(http_server_properties
),
41 force_pipelining_(force_pipelining
) {
43 factory_
.reset(new HttpPipelinedHostImplFactory
);
47 HttpPipelinedHostPool::~HttpPipelinedHostPool() {
48 CHECK(host_map_
.empty());
51 bool HttpPipelinedHostPool::IsKeyEligibleForPipelining(
52 const HttpPipelinedHost::Key
& key
) {
53 HttpPipelinedHostCapability capability
=
54 http_server_properties_
->GetPipelineCapability(key
.origin());
55 return capability
!= PIPELINE_INCAPABLE
;
58 HttpPipelinedStream
* HttpPipelinedHostPool::CreateStreamOnNewPipeline(
59 const HttpPipelinedHost::Key
& key
,
60 ClientSocketHandle
* connection
,
61 const SSLConfig
& used_ssl_config
,
62 const ProxyInfo
& used_proxy_info
,
63 const BoundNetLog
& net_log
,
64 bool was_npn_negotiated
,
65 NextProto protocol_negotiated
) {
66 HttpPipelinedHost
* host
= GetPipelinedHost(key
, true);
70 return host
->CreateStreamOnNewPipeline(connection
, used_ssl_config
,
71 used_proxy_info
, net_log
,
76 HttpPipelinedStream
* HttpPipelinedHostPool::CreateStreamOnExistingPipeline(
77 const HttpPipelinedHost::Key
& key
) {
78 HttpPipelinedHost
* host
= GetPipelinedHost(key
, false);
82 return host
->CreateStreamOnExistingPipeline();
85 bool HttpPipelinedHostPool::IsExistingPipelineAvailableForKey(
86 const HttpPipelinedHost::Key
& key
) {
87 HttpPipelinedHost
* host
= GetPipelinedHost(key
, false);
91 return host
->IsExistingPipelineAvailable();
94 HttpPipelinedHost
* HttpPipelinedHostPool::GetPipelinedHost(
95 const HttpPipelinedHost::Key
& key
, bool create_if_not_found
) {
96 HostMap::iterator host_it
= host_map_
.find(key
);
97 if (host_it
!= host_map_
.end()) {
98 CHECK(host_it
->second
);
99 return host_it
->second
;
100 } else if (!create_if_not_found
) {
104 HttpPipelinedHostCapability capability
=
105 http_server_properties_
->GetPipelineCapability(key
.origin());
106 if (capability
== PIPELINE_INCAPABLE
) {
110 HttpPipelinedHost
* host
= factory_
->CreateNewHost(
111 this, key
, NULL
, capability
, force_pipelining_
);
112 host_map_
[key
] = host
;
116 void HttpPipelinedHostPool::OnHostIdle(HttpPipelinedHost
* host
) {
117 const HttpPipelinedHost::Key
& key
= host
->GetKey();
118 CHECK(ContainsKey(host_map_
, key
));
119 host_map_
.erase(key
);
123 void HttpPipelinedHostPool::OnHostHasAdditionalCapacity(
124 HttpPipelinedHost
* host
) {
125 delegate_
->OnHttpPipelinedHostHasAdditionalCapacity(host
);
128 void HttpPipelinedHostPool::OnHostDeterminedCapability(
129 HttpPipelinedHost
* host
,
130 HttpPipelinedHostCapability capability
) {
131 http_server_properties_
->SetPipelineCapability(host
->GetKey().origin(),
135 base::Value
* HttpPipelinedHostPool::PipelineInfoToValue() const {
136 base::ListValue
* list
= new base::ListValue();
137 for (HostMap::const_iterator it
= host_map_
.begin();
138 it
!= host_map_
.end(); ++it
) {
139 base::Value
* value
= it
->second
->PipelineInfoToValue();