blob: c777169d91e60896390d5f20f0e8c555258bb243 [file] [log] [blame]
[email protected]39c48fc2012-03-12 18:42:121// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]17291a022011-10-10 07:32:532// 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_server_properties.h"
6
Matt Menke609160742019-08-02 18:47:267#include "base/bind.h"
Matt Menke1be93d22019-08-20 16:57:588#include "base/feature_list.h"
Matt Menke609160742019-08-02 18:47:269#include "base/location.h"
10#include "base/logging.h"
11#include "base/metrics/histogram_macros.h"
12#include "base/single_thread_task_runner.h"
13#include "base/stl_util.h"
14#include "base/strings/string_util.h"
15#include "base/strings/stringprintf.h"
16#include "base/threading/thread_task_runner_handle.h"
17#include "base/time/default_clock.h"
18#include "base/time/default_tick_clock.h"
19#include "base/values.h"
Matt Menke1be93d22019-08-20 16:57:5820#include "net/base/features.h"
Matt Menke609160742019-08-02 18:47:2621#include "net/http/http_network_session.h"
22#include "net/http/http_server_properties_manager.h"
bncfacdd852015-01-09 19:22:5423#include "net/socket/ssl_client_socket.h"
24#include "net/ssl/ssl_config.h"
[email protected]17291a022011-10-10 07:32:5325
26namespace net {
27
Matt Menke609160742019-08-02 18:47:2628namespace {
29
30// Time to wait before starting an update the preferences from the
31// http_server_properties_impl_ cache. Scheduling another update during this
32// period will be a no-op.
33constexpr base::TimeDelta kUpdatePrefsDelay = base::TimeDelta::FromSeconds(60);
34
Matt Menked9b24f02019-09-26 17:07:1735url::SchemeHostPort NormalizeSchemeHostPort(
36 const url::SchemeHostPort& scheme_host_port) {
37 if (scheme_host_port.scheme() == url::kWssScheme) {
38 return url::SchemeHostPort(url::kHttpsScheme, scheme_host_port.host(),
39 scheme_host_port.port());
40 }
41 if (scheme_host_port.scheme() == url::kWsScheme) {
42 return url::SchemeHostPort(url::kHttpScheme, scheme_host_port.host(),
43 scheme_host_port.port());
44 }
45 return scheme_host_port;
46}
47
Matt Menke609160742019-08-02 18:47:2648} // namespace
49
50HttpServerProperties::PrefDelegate::~PrefDelegate() = default;
51
Matt Menke5e7dcd32019-08-09 22:25:2152HttpServerProperties::ServerInfo::ServerInfo() = default;
53HttpServerProperties::ServerInfo::ServerInfo(const ServerInfo& server_info) =
54 default;
55HttpServerProperties::ServerInfo::ServerInfo(ServerInfo&& server_info) =
56 default;
57HttpServerProperties::ServerInfo::~ServerInfo() = default;
58
Matt Menkefe9b5962019-08-14 20:56:1459bool HttpServerProperties::ServerInfo::empty() const {
Matt Menke86878a62019-08-14 21:01:1160 return !supports_spdy.has_value() && !alternative_services.has_value() &&
61 !server_network_stats.has_value();
Matt Menkefe9b5962019-08-14 20:56:1462}
63
Matt Menke1be93d22019-08-20 16:57:5864bool HttpServerProperties::ServerInfo::operator==(
65 const ServerInfo& other) const {
66 return supports_spdy == other.supports_spdy &&
67 alternative_services == other.alternative_services &&
68 server_network_stats == other.server_network_stats;
69}
70
71HttpServerProperties::ServerInfoMapKey::ServerInfoMapKey(
Matt Menked9b24f02019-09-26 17:07:1772 url::SchemeHostPort server,
Matt Menke1be93d22019-08-20 16:57:5873 const NetworkIsolationKey& network_isolation_key,
74 bool use_network_isolation_key)
Matt Menked9b24f02019-09-26 17:07:1775 : server(std::move(server)),
Matt Menke1be93d22019-08-20 16:57:5876 network_isolation_key(use_network_isolation_key ? network_isolation_key
77 : NetworkIsolationKey()) {
Matt Menked9b24f02019-09-26 17:07:1778 // Scheme should have been normalized before this method was called.
79 DCHECK_NE(this->server.scheme(), url::kWsScheme);
80 DCHECK_NE(this->server.scheme(), url::kWssScheme);
Matt Menke1be93d22019-08-20 16:57:5881}
82
83HttpServerProperties::ServerInfoMapKey::~ServerInfoMapKey() = default;
84
85bool HttpServerProperties::ServerInfoMapKey::operator<(
86 const ServerInfoMapKey& other) const {
87 return std::tie(server, network_isolation_key) <
88 std::tie(other.server, other.network_isolation_key);
89}
90
Matt Menke0142bc02019-09-13 20:17:4591HttpServerProperties::QuicServerInfoMapKey::QuicServerInfoMapKey(
92 const quic::QuicServerId& server_id,
93 const NetworkIsolationKey& network_isolation_key,
94 bool use_network_isolation_key)
95 : server_id(server_id),
96 network_isolation_key(use_network_isolation_key ? network_isolation_key
97 : NetworkIsolationKey()) {
98}
99
100HttpServerProperties::QuicServerInfoMapKey::~QuicServerInfoMapKey() = default;
101
102bool HttpServerProperties::QuicServerInfoMapKey::operator<(
103 const QuicServerInfoMapKey& other) const {
104 return std::tie(server_id, network_isolation_key) <
105 std::tie(other.server_id, other.network_isolation_key);
106}
107
108// Used in tests.
109bool HttpServerProperties::QuicServerInfoMapKey::operator==(
110 const QuicServerInfoMapKey& other) const {
111 return std::tie(server_id, network_isolation_key) ==
112 std::tie(other.server_id, other.network_isolation_key);
113}
114
Matt Menke5e7dcd32019-08-09 22:25:21115HttpServerProperties::ServerInfoMap::ServerInfoMap()
Matt Menke1be93d22019-08-20 16:57:58116 : base::MRUCache<ServerInfoMapKey, ServerInfo>(kMaxServerInfoEntries) {}
Matt Menke5e7dcd32019-08-09 22:25:21117
118HttpServerProperties::ServerInfoMap::iterator
Matt Menke1be93d22019-08-20 16:57:58119HttpServerProperties::ServerInfoMap::GetOrPut(const ServerInfoMapKey& key) {
Matt Menke5e7dcd32019-08-09 22:25:21120 auto it = Get(key);
121 if (it != end())
122 return it;
123 return Put(key, ServerInfo());
124}
125
Matt Menkefe9b5962019-08-14 20:56:14126HttpServerProperties::ServerInfoMap::iterator
127HttpServerProperties::ServerInfoMap::EraseIfEmpty(iterator server_info_it) {
128 if (server_info_it->second.empty())
129 return Erase(server_info_it);
130 return ++server_info_it;
131}
132
Matt Menke609160742019-08-02 18:47:26133HttpServerProperties::HttpServerProperties(
134 std::unique_ptr<PrefDelegate> pref_delegate,
135 NetLog* net_log,
136 const base::TickClock* tick_clock,
137 base::Clock* clock)
138 : tick_clock_(tick_clock ? tick_clock
139 : base::DefaultTickClock::GetInstance()),
140 clock_(clock ? clock : base::DefaultClock::GetInstance()),
Matt Menke1be93d22019-08-20 16:57:58141 use_network_isolation_key_(base::FeatureList::IsEnabled(
142 features::kPartitionHttpServerPropertiesByNetworkIsolationKey)),
Matt Menke609160742019-08-02 18:47:26143 is_initialized_(pref_delegate.get() == nullptr),
Matt Menke723f10292019-08-02 21:13:10144 queue_write_on_load_(false),
Matt Menke609160742019-08-02 18:47:26145 properties_manager_(
146 pref_delegate
147 ? std::make_unique<HttpServerPropertiesManager>(
148 std::move(pref_delegate),
149 base::BindOnce(&HttpServerProperties::OnPrefsLoaded,
150 base::Unretained(this)),
151 kDefaultMaxQuicServerEntries,
152 net_log,
153 tick_clock_)
154 : nullptr),
155 broken_alternative_services_(kMaxRecentlyBrokenAlternativeServiceEntries,
156 this,
157 tick_clock_),
158 canonical_suffixes_({".ggpht.com", ".c.youtube.com", ".googlevideo.com",
159 ".googleusercontent.com"}),
160 quic_server_info_map_(kDefaultMaxQuicServerEntries),
161 max_server_configs_stored_in_properties_(kDefaultMaxQuicServerEntries) {}
162
163HttpServerProperties::~HttpServerProperties() {
164 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
165
166 if (properties_manager_) {
167 // Stop waiting for initial settings.
168 is_initialized_ = true;
169
170 // Stop the timer if it's running, since this will write to the properties
171 // file immediately.
172 prefs_update_timer_.Stop();
173
174 WriteProperties(base::OnceClosure());
175 }
176}
177
178void HttpServerProperties::Clear(base::OnceClosure callback) {
179 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
Matt Menke5e7dcd32019-08-09 22:25:21180 server_info_map_.Clear();
Matt Menke609160742019-08-02 18:47:26181 broken_alternative_services_.Clear();
182 canonical_alt_svc_map_.clear();
Matt Menkeb566c392019-09-11 23:22:43183 last_local_address_when_quic_worked_ = IPAddress();
Matt Menke609160742019-08-02 18:47:26184 quic_server_info_map_.Clear();
185 canonical_server_info_map_.clear();
186
187 if (properties_manager_) {
188 // Stop waiting for initial settings.
189 is_initialized_ = true;
Matt Menke723f10292019-08-02 21:13:10190 // Leaving this as-is doesn't actually have any effect, if it's true, but
191 // seems best to be safe.
192 queue_write_on_load_ = false;
Matt Menke609160742019-08-02 18:47:26193
194 // Stop the timer if it's running, since this will write to the properties
195 // file immediately.
196 prefs_update_timer_.Stop();
197 WriteProperties(std::move(callback));
198 } else if (callback) {
199 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
200 std::move(callback));
201 }
202}
203
204bool HttpServerProperties::SupportsRequestPriority(
Matt Menkefe1f1c82019-08-20 17:49:11205 const url::SchemeHostPort& server,
206 const net::NetworkIsolationKey& network_isolation_key) {
Matt Menke609160742019-08-02 18:47:26207 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
208 if (server.host().empty())
209 return false;
210
Matt Menkefe1f1c82019-08-20 17:49:11211 if (GetSupportsSpdy(server, network_isolation_key))
Matt Menke609160742019-08-02 18:47:26212 return true;
213 const AlternativeServiceInfoVector alternative_service_info_vector =
Matt Menke3233d8f22019-08-20 21:01:49214 GetAlternativeServiceInfos(server, network_isolation_key);
Matt Menke609160742019-08-02 18:47:26215 for (const AlternativeServiceInfo& alternative_service_info :
216 alternative_service_info_vector) {
217 if (alternative_service_info.alternative_service().protocol == kProtoQUIC) {
218 return true;
219 }
220 }
221 return false;
222}
223
Matt Menkefe1f1c82019-08-20 17:49:11224bool HttpServerProperties::GetSupportsSpdy(
225 const url::SchemeHostPort& server,
226 const net::NetworkIsolationKey& network_isolation_key) {
Matt Menke609160742019-08-02 18:47:26227 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
Matt Menked9b24f02019-09-26 17:07:17228 return GetSupportsSpdyInternal(NormalizeSchemeHostPort(server),
229 network_isolation_key);
Matt Menke609160742019-08-02 18:47:26230}
231
Matt Menkefe1f1c82019-08-20 17:49:11232void HttpServerProperties::SetSupportsSpdy(
233 const url::SchemeHostPort& server,
234 const net::NetworkIsolationKey& network_isolation_key,
235 bool supports_spdy) {
Matt Menke609160742019-08-02 18:47:26236 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
Matt Menked9b24f02019-09-26 17:07:17237 SetSupportsSpdyInternal(NormalizeSchemeHostPort(server),
238 network_isolation_key, supports_spdy);
Matt Menke609160742019-08-02 18:47:26239}
240
Matt Menkef2ee07c2019-08-29 02:10:36241bool HttpServerProperties::RequiresHTTP11(
242 const url::SchemeHostPort& server,
243 const net::NetworkIsolationKey& network_isolation_key) {
Matt Menke609160742019-08-02 18:47:26244 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
Matt Menked9b24f02019-09-26 17:07:17245 return RequiresHTTP11Internal(NormalizeSchemeHostPort(server),
246 network_isolation_key);
Matt Menke609160742019-08-02 18:47:26247}
248
249void HttpServerProperties::SetHTTP11Required(
Matt Menkef2ee07c2019-08-29 02:10:36250 const url::SchemeHostPort& server,
251 const net::NetworkIsolationKey& network_isolation_key) {
Matt Menke609160742019-08-02 18:47:26252 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
Matt Menked9b24f02019-09-26 17:07:17253 SetHTTP11RequiredInternal(NormalizeSchemeHostPort(server),
254 network_isolation_key);
Matt Menke609160742019-08-02 18:47:26255}
256
Matt Menkef2ee07c2019-08-29 02:10:36257void HttpServerProperties::MaybeForceHTTP11(
258 const url::SchemeHostPort& server,
259 const net::NetworkIsolationKey& network_isolation_key,
260 SSLConfig* ssl_config) {
Matt Menked9b24f02019-09-26 17:07:17261 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
262 MaybeForceHTTP11Internal(NormalizeSchemeHostPort(server),
263 network_isolation_key, ssl_config);
Matt Menke609160742019-08-02 18:47:26264}
265
266AlternativeServiceInfoVector HttpServerProperties::GetAlternativeServiceInfos(
Matt Menke3233d8f22019-08-20 21:01:49267 const url::SchemeHostPort& origin,
268 const net::NetworkIsolationKey& network_isolation_key) {
Matt Menked9b24f02019-09-26 17:07:17269 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
270 return GetAlternativeServiceInfosInternal(NormalizeSchemeHostPort(origin),
271 network_isolation_key);
Matt Menke609160742019-08-02 18:47:26272}
273
Matt Menke2f63ef692019-08-02 22:48:03274void HttpServerProperties::SetHttp2AlternativeService(
Matt Menke609160742019-08-02 18:47:26275 const url::SchemeHostPort& origin,
Matt Menke9aa86262019-08-21 15:52:07276 const NetworkIsolationKey& network_isolation_key,
Matt Menke609160742019-08-02 18:47:26277 const AlternativeService& alternative_service,
278 base::Time expiration) {
279 DCHECK_EQ(alternative_service.protocol, kProtoHTTP2);
280
Matt Menke2f63ef692019-08-02 22:48:03281 SetAlternativeServices(
Matt Menke9aa86262019-08-21 15:52:07282 origin, network_isolation_key,
Matt Menke609160742019-08-02 18:47:26283 AlternativeServiceInfoVector(
284 /*size=*/1, AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
285 alternative_service, expiration)));
286}
287
Matt Menke2f63ef692019-08-02 22:48:03288void HttpServerProperties::SetQuicAlternativeService(
Matt Menke609160742019-08-02 18:47:26289 const url::SchemeHostPort& origin,
Matt Menke9aa86262019-08-21 15:52:07290 const NetworkIsolationKey& network_isolation_key,
Matt Menke609160742019-08-02 18:47:26291 const AlternativeService& alternative_service,
292 base::Time expiration,
293 const quic::ParsedQuicVersionVector& advertised_versions) {
294 DCHECK(alternative_service.protocol == kProtoQUIC);
295
Matt Menke2f63ef692019-08-02 22:48:03296 SetAlternativeServices(
Matt Menke9aa86262019-08-21 15:52:07297 origin, network_isolation_key,
Matt Menke3233d8f22019-08-20 21:01:49298 AlternativeServiceInfoVector(
299 /*size=*/1,
300 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
301 alternative_service, expiration, advertised_versions)));
Matt Menke609160742019-08-02 18:47:26302}
303
Matt Menke2f63ef692019-08-02 22:48:03304void HttpServerProperties::SetAlternativeServices(
Matt Menke609160742019-08-02 18:47:26305 const url::SchemeHostPort& origin,
Matt Menke3233d8f22019-08-20 21:01:49306 const net::NetworkIsolationKey& network_isolation_key,
Matt Menke609160742019-08-02 18:47:26307 const AlternativeServiceInfoVector& alternative_service_info_vector) {
Matt Menked9b24f02019-09-26 17:07:17308 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
309 SetAlternativeServicesInternal(NormalizeSchemeHostPort(origin),
310 network_isolation_key,
311 alternative_service_info_vector);
Matt Menke609160742019-08-02 18:47:26312}
313
314void HttpServerProperties::MarkAlternativeServiceBroken(
Matt Menke977f02792019-09-10 16:23:09315 const AlternativeService& alternative_service,
316 const net::NetworkIsolationKey& network_isolation_key) {
Matt Menke9d0e9952019-09-10 16:09:38317 broken_alternative_services_.MarkBroken(BrokenAlternativeService(
Matt Menke977f02792019-09-10 16:23:09318 alternative_service, network_isolation_key, use_network_isolation_key_));
Matt Menke609160742019-08-02 18:47:26319 MaybeQueueWriteProperties();
320}
321
322void HttpServerProperties::
323 MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
Matt Menke977f02792019-09-10 16:23:09324 const AlternativeService& alternative_service,
325 const net::NetworkIsolationKey& network_isolation_key) {
Matt Menke609160742019-08-02 18:47:26326 broken_alternative_services_.MarkBrokenUntilDefaultNetworkChanges(
Matt Menke977f02792019-09-10 16:23:09327 BrokenAlternativeService(alternative_service, network_isolation_key,
Matt Menke9d0e9952019-09-10 16:09:38328 use_network_isolation_key_));
Matt Menke609160742019-08-02 18:47:26329 MaybeQueueWriteProperties();
330}
331
332void HttpServerProperties::MarkAlternativeServiceRecentlyBroken(
Matt Menke977f02792019-09-10 16:23:09333 const AlternativeService& alternative_service,
334 const net::NetworkIsolationKey& network_isolation_key) {
Matt Menke9d0e9952019-09-10 16:09:38335 broken_alternative_services_.MarkRecentlyBroken(BrokenAlternativeService(
Matt Menke977f02792019-09-10 16:23:09336 alternative_service, network_isolation_key, use_network_isolation_key_));
Matt Menke609160742019-08-02 18:47:26337 MaybeQueueWriteProperties();
338}
339
340bool HttpServerProperties::IsAlternativeServiceBroken(
Matt Menke977f02792019-09-10 16:23:09341 const AlternativeService& alternative_service,
342 const net::NetworkIsolationKey& network_isolation_key) const {
Matt Menke9d0e9952019-09-10 16:09:38343 return broken_alternative_services_.IsBroken(BrokenAlternativeService(
Matt Menke977f02792019-09-10 16:23:09344 alternative_service, network_isolation_key, use_network_isolation_key_));
Matt Menke609160742019-08-02 18:47:26345}
346
347bool HttpServerProperties::WasAlternativeServiceRecentlyBroken(
Matt Menke977f02792019-09-10 16:23:09348 const AlternativeService& alternative_service,
349 const net::NetworkIsolationKey& network_isolation_key) {
Matt Menke9d0e9952019-09-10 16:09:38350 return broken_alternative_services_.WasRecentlyBroken(
Matt Menke977f02792019-09-10 16:23:09351 BrokenAlternativeService(alternative_service, network_isolation_key,
Matt Menke9d0e9952019-09-10 16:09:38352 use_network_isolation_key_));
Matt Menke609160742019-08-02 18:47:26353}
354
355void HttpServerProperties::ConfirmAlternativeService(
Matt Menke977f02792019-09-10 16:23:09356 const AlternativeService& alternative_service,
357 const net::NetworkIsolationKey& network_isolation_key) {
Matt Menkeb32ba5122019-09-10 19:17:05358 bool old_value =
359 IsAlternativeServiceBroken(alternative_service, network_isolation_key);
Matt Menke9d0e9952019-09-10 16:09:38360 broken_alternative_services_.Confirm(BrokenAlternativeService(
Matt Menke977f02792019-09-10 16:23:09361 alternative_service, network_isolation_key, use_network_isolation_key_));
Matt Menkeb32ba5122019-09-10 19:17:05362 bool new_value =
363 IsAlternativeServiceBroken(alternative_service, network_isolation_key);
Matt Menke609160742019-08-02 18:47:26364
365 // For persisting, we only care about the value returned by
366 // IsAlternativeServiceBroken. If that value changes, then call persist.
367 if (old_value != new_value)
368 MaybeQueueWriteProperties();
369}
370
Matt Menke2f63ef692019-08-02 22:48:03371void HttpServerProperties::OnDefaultNetworkChanged() {
Matt Menke609160742019-08-02 18:47:26372 bool changed = broken_alternative_services_.OnDefaultNetworkChanged();
373 if (changed)
374 MaybeQueueWriteProperties();
Matt Menke609160742019-08-02 18:47:26375}
376
Matt Menke609160742019-08-02 18:47:26377std::unique_ptr<base::Value>
378HttpServerProperties::GetAlternativeServiceInfoAsValue() const {
379 const base::Time now = clock_->Now();
380 const base::TimeTicks now_ticks = tick_clock_->NowTicks();
381 std::unique_ptr<base::ListValue> dict_list(new base::ListValue);
Matt Menkefe9b5962019-08-14 20:56:14382 for (const auto& server_info : server_info_map_) {
383 if (!server_info.second.alternative_services.has_value())
384 continue;
Matt Menke609160742019-08-02 18:47:26385 std::unique_ptr<base::ListValue> alternative_service_list(
386 new base::ListValue);
Matt Menke1be93d22019-08-20 16:57:58387 const ServerInfoMapKey& key = server_info.first;
Matt Menke609160742019-08-02 18:47:26388 for (const AlternativeServiceInfo& alternative_service_info :
Matt Menkefe9b5962019-08-14 20:56:14389 server_info.second.alternative_services.value()) {
Matt Menke609160742019-08-02 18:47:26390 std::string alternative_service_string(
391 alternative_service_info.ToString());
392 AlternativeService alternative_service(
393 alternative_service_info.alternative_service());
394 if (alternative_service.host.empty()) {
Matt Menke1be93d22019-08-20 16:57:58395 alternative_service.host = key.server.host();
Matt Menke609160742019-08-02 18:47:26396 }
397 base::TimeTicks brokenness_expiration_ticks;
Matt Menke9d0e9952019-09-10 16:09:38398 if (broken_alternative_services_.IsBroken(
399 BrokenAlternativeService(alternative_service,
400 server_info.first.network_isolation_key,
401 use_network_isolation_key_),
402 &brokenness_expiration_ticks)) {
Matt Menke609160742019-08-02 18:47:26403 // Convert |brokenness_expiration| from TimeTicks to Time
404 base::Time brokenness_expiration =
405 now + (brokenness_expiration_ticks - now_ticks);
406 base::Time::Exploded exploded;
407 brokenness_expiration.LocalExplode(&exploded);
408 std::string broken_info_string =
409 " (broken until " +
410 base::StringPrintf("%04d-%02d-%02d %0d:%0d:%0d", exploded.year,
411 exploded.month, exploded.day_of_month,
412 exploded.hour, exploded.minute,
413 exploded.second) +
414 ")";
415 alternative_service_string.append(broken_info_string);
416 }
417 alternative_service_list->AppendString(alternative_service_string);
418 }
419 if (alternative_service_list->empty())
420 continue;
421 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
Matt Menke1be93d22019-08-20 16:57:58422 dict->SetString("server", key.server.Serialize());
423 dict->SetString("network_isolation_key",
424 key.network_isolation_key.ToDebugString());
Matt Menke609160742019-08-02 18:47:26425 dict->Set("alternative_service", std::unique_ptr<base::Value>(
426 std::move(alternative_service_list)));
427 dict_list->Append(std::move(dict));
428 }
429 return std::move(dict_list);
430}
431
Matt Menkeb566c392019-09-11 23:22:43432bool HttpServerProperties::WasLastLocalAddressWhenQuicWorked(
433 const IPAddress& local_address) const {
434 return !last_local_address_when_quic_worked_.empty() &&
435 last_local_address_when_quic_worked_ == local_address;
Matt Menke609160742019-08-02 18:47:26436}
437
Matt Menkeb566c392019-09-11 23:22:43438bool HttpServerProperties::HasLastLocalAddressWhenQuicWorked() const {
439 return !last_local_address_when_quic_worked_.empty();
440}
Matt Menke609160742019-08-02 18:47:26441
Matt Menkeb566c392019-09-11 23:22:43442void HttpServerProperties::SetLastLocalAddressWhenQuicWorked(
443 IPAddress last_local_address_when_quic_worked) {
444 DCHECK(!last_local_address_when_quic_worked.empty());
445 if (last_local_address_when_quic_worked_ ==
446 last_local_address_when_quic_worked) {
447 return;
448 }
449
450 last_local_address_when_quic_worked_ = last_local_address_when_quic_worked;
451 MaybeQueueWriteProperties();
452}
453
454void HttpServerProperties::ClearLastLocalAddressWhenQuicWorked() {
455 if (last_local_address_when_quic_worked_.empty())
Matt Menke609160742019-08-02 18:47:26456 return;
457
Matt Menkeb566c392019-09-11 23:22:43458 last_local_address_when_quic_worked_ = IPAddress();
Matt Menke609160742019-08-02 18:47:26459 MaybeQueueWriteProperties();
460}
461
462void HttpServerProperties::SetServerNetworkStats(
463 const url::SchemeHostPort& server,
Matt Menke19475f72019-08-21 18:57:44464 const NetworkIsolationKey& network_isolation_key,
Matt Menke609160742019-08-02 18:47:26465 ServerNetworkStats stats) {
Matt Menked9b24f02019-09-26 17:07:17466 SetServerNetworkStatsInternal(NormalizeSchemeHostPort(server),
467 network_isolation_key, std::move(stats));
Matt Menke609160742019-08-02 18:47:26468}
469
470void HttpServerProperties::ClearServerNetworkStats(
Matt Menke19475f72019-08-21 18:57:44471 const url::SchemeHostPort& server,
472 const NetworkIsolationKey& network_isolation_key) {
Matt Menked9b24f02019-09-26 17:07:17473 ClearServerNetworkStatsInternal(NormalizeSchemeHostPort(server),
474 network_isolation_key);
Matt Menke609160742019-08-02 18:47:26475}
476
477const ServerNetworkStats* HttpServerProperties::GetServerNetworkStats(
Matt Menke19475f72019-08-21 18:57:44478 const url::SchemeHostPort& server,
479 const NetworkIsolationKey& network_isolation_key) {
Matt Menked9b24f02019-09-26 17:07:17480 return GetServerNetworkStatsInternal(NormalizeSchemeHostPort(server),
481 network_isolation_key);
Matt Menke609160742019-08-02 18:47:26482}
483
Matt Menke2f63ef692019-08-02 22:48:03484void HttpServerProperties::SetQuicServerInfo(
Matt Menke609160742019-08-02 18:47:26485 const quic::QuicServerId& server_id,
Matt Menke0142bc02019-09-13 20:17:45486 const NetworkIsolationKey& network_isolation_key,
Matt Menke609160742019-08-02 18:47:26487 const std::string& server_info) {
Matt Menke0142bc02019-09-13 20:17:45488 QuicServerInfoMapKey key =
489 CreateQuicServerInfoKey(server_id, network_isolation_key);
490 auto it = quic_server_info_map_.Peek(key);
Matt Menke609160742019-08-02 18:47:26491 bool changed =
492 (it == quic_server_info_map_.end() || it->second != server_info);
Matt Menke0142bc02019-09-13 20:17:45493 quic_server_info_map_.Put(key, server_info);
494 UpdateCanonicalServerInfoMap(key);
Matt Menke609160742019-08-02 18:47:26495 if (changed)
496 MaybeQueueWriteProperties();
Matt Menke609160742019-08-02 18:47:26497}
498
499const std::string* HttpServerProperties::GetQuicServerInfo(
Matt Menke0142bc02019-09-13 20:17:45500 const quic::QuicServerId& server_id,
501 const NetworkIsolationKey& network_isolation_key) {
502 QuicServerInfoMapKey key =
503 CreateQuicServerInfoKey(server_id, network_isolation_key);
504 auto it = quic_server_info_map_.Get(key);
Matt Menke609160742019-08-02 18:47:26505 if (it != quic_server_info_map_.end()) {
506 // Since |canonical_server_info_map_| should always map to the most
507 // recent host, update it with the one that became MRU in
508 // |quic_server_info_map_|.
Matt Menke0142bc02019-09-13 20:17:45509 UpdateCanonicalServerInfoMap(key);
Matt Menke609160742019-08-02 18:47:26510 return &it->second;
511 }
512
513 // If the exact match for |server_id| wasn't found, check
514 // |canonical_server_info_map_| whether there is server info for a host with
515 // the same canonical host suffix.
Matt Menke0142bc02019-09-13 20:17:45516 auto canonical_itr = GetCanonicalServerInfoHost(key);
Matt Menke609160742019-08-02 18:47:26517 if (canonical_itr == canonical_server_info_map_.end())
518 return nullptr;
519
520 // When search in |quic_server_info_map_|, do not change the MRU order.
Matt Menke0142bc02019-09-13 20:17:45521 it = quic_server_info_map_.Peek(
522 CreateQuicServerInfoKey(canonical_itr->second, network_isolation_key));
Matt Menke609160742019-08-02 18:47:26523 if (it != quic_server_info_map_.end())
524 return &it->second;
525
526 return nullptr;
527}
528
Matt Menke0142bc02019-09-13 20:17:45529const HttpServerProperties::QuicServerInfoMap&
530HttpServerProperties::quic_server_info_map() const {
Matt Menke609160742019-08-02 18:47:26531 return quic_server_info_map_;
532}
533
534size_t HttpServerProperties::max_server_configs_stored_in_properties() const {
535 return max_server_configs_stored_in_properties_;
536}
537
538void HttpServerProperties::SetMaxServerConfigsStoredInProperties(
539 size_t max_server_configs_stored_in_properties) {
540 // Do nothing if the new size is the same as the old one.
541 if (max_server_configs_stored_in_properties_ ==
542 max_server_configs_stored_in_properties) {
543 return;
544 }
545
546 max_server_configs_stored_in_properties_ =
547 max_server_configs_stored_in_properties;
548
549 // MRUCache doesn't allow the capacity of the cache to be changed. Thus create
550 // a new map with the new size and add current elements and swap the new map.
551 quic_server_info_map_.ShrinkToSize(max_server_configs_stored_in_properties_);
552 QuicServerInfoMap temp_map(max_server_configs_stored_in_properties_);
553 // Update the |canonical_server_info_map_| as well, so it stays in sync with
554 // |quic_server_info_map_|.
Matt Menke0142bc02019-09-13 20:17:45555 canonical_server_info_map_ = QuicCanonicalMap();
Matt Menke609160742019-08-02 18:47:26556 for (auto it = quic_server_info_map_.rbegin();
557 it != quic_server_info_map_.rend(); ++it) {
558 temp_map.Put(it->first, it->second);
559 UpdateCanonicalServerInfoMap(it->first);
560 }
561
562 quic_server_info_map_.Swap(temp_map);
563 if (properties_manager_) {
564 properties_manager_->set_max_server_configs_stored_in_properties(
565 max_server_configs_stored_in_properties);
566 }
567}
568
569bool HttpServerProperties::IsInitialized() const {
570 return is_initialized_;
571}
572
573void HttpServerProperties::OnExpireBrokenAlternativeService(
Matt Menke9d0e9952019-09-10 16:09:38574 const AlternativeService& expired_alternative_service,
575 const NetworkIsolationKey& network_isolation_key) {
Matt Menke609160742019-08-02 18:47:26576 // Remove every occurrence of |expired_alternative_service| from
577 // |alternative_service_map_|.
Matt Menkefe9b5962019-08-14 20:56:14578 for (auto map_it = server_info_map_.begin();
579 map_it != server_info_map_.end();) {
Matt Menke9d0e9952019-09-10 16:09:38580 if (!map_it->second.alternative_services.has_value() ||
581 map_it->first.network_isolation_key != network_isolation_key) {
Matt Menkee04cd242019-08-16 18:00:07582 ++map_it;
Matt Menkefe9b5962019-08-14 20:56:14583 continue;
Matt Menkee04cd242019-08-16 18:00:07584 }
Matt Menkefe9b5962019-08-14 20:56:14585 AlternativeServiceInfoVector* service_info =
586 &map_it->second.alternative_services.value();
587 for (auto it = service_info->begin(); it != service_info->end();) {
Matt Menke609160742019-08-02 18:47:26588 AlternativeService alternative_service(it->alternative_service());
589 // Empty hostname in map means hostname of key: substitute before
590 // comparing to |expired_alternative_service|.
591 if (alternative_service.host.empty()) {
Matt Menke1be93d22019-08-20 16:57:58592 alternative_service.host = map_it->first.server.host();
Matt Menke609160742019-08-02 18:47:26593 }
594 if (alternative_service == expired_alternative_service) {
Matt Menkefe9b5962019-08-14 20:56:14595 it = service_info->erase(it);
Matt Menke609160742019-08-02 18:47:26596 continue;
597 }
598 ++it;
599 }
600 // If an origin has an empty list of alternative services, then remove it
601 // from both |canonical_alt_svc_map_| and
602 // |alternative_service_map_|.
Matt Menkefe9b5962019-08-14 20:56:14603 if (service_info->empty()) {
Matt Menke9d0e9952019-09-10 16:09:38604 RemoveAltSvcCanonicalHost(map_it->first.server, network_isolation_key);
Matt Menkefe9b5962019-08-14 20:56:14605 map_it->second.alternative_services.reset();
606 map_it = server_info_map_.EraseIfEmpty(map_it);
Matt Menke609160742019-08-02 18:47:26607 continue;
608 }
609 ++map_it;
610 }
611}
612
613base::TimeDelta HttpServerProperties::GetUpdatePrefsDelayForTesting() {
614 return kUpdatePrefsDelay;
615}
616
Matt Menked9b24f02019-09-26 17:07:17617bool HttpServerProperties::GetSupportsSpdyInternal(
618 url::SchemeHostPort server,
619 const net::NetworkIsolationKey& network_isolation_key) {
620 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
621 DCHECK_NE(server.scheme(), url::kWsScheme);
622 DCHECK_NE(server.scheme(), url::kWssScheme);
623 if (server.host().empty())
624 return false;
625
626 auto server_info = server_info_map_.Get(
627 CreateServerInfoKey(std::move(server), network_isolation_key));
628 return server_info != server_info_map_.end() &&
629 server_info->second.supports_spdy.value_or(false);
630}
631
632void HttpServerProperties::SetSupportsSpdyInternal(
633 url::SchemeHostPort server,
634 const net::NetworkIsolationKey& network_isolation_key,
635 bool supports_spdy) {
636 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
637 DCHECK_NE(server.scheme(), url::kWsScheme);
638 DCHECK_NE(server.scheme(), url::kWssScheme);
639 if (server.host().empty())
640 return;
641
642 auto server_info = server_info_map_.GetOrPut(
643 CreateServerInfoKey(std::move(server), network_isolation_key));
644 // If value is already the same as |supports_spdy|, or value is unset and
645 // |supports_spdy| is false, don't queue a write.
646 bool queue_write =
647 server_info->second.supports_spdy.value_or(false) != supports_spdy;
648 server_info->second.supports_spdy = supports_spdy;
649
650 if (queue_write)
651 MaybeQueueWriteProperties();
652}
653
654bool HttpServerProperties::RequiresHTTP11Internal(
655 url::SchemeHostPort server,
656 const net::NetworkIsolationKey& network_isolation_key) {
657 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
658 DCHECK_NE(server.scheme(), url::kWsScheme);
659 DCHECK_NE(server.scheme(), url::kWssScheme);
660 if (server.host().empty())
661 return false;
662
663 auto spdy_info = server_info_map_.Get(
664 CreateServerInfoKey(std::move(server), network_isolation_key));
665 return spdy_info != server_info_map_.end() &&
666 spdy_info->second.requires_http11.value_or(false);
667}
668
669void HttpServerProperties::SetHTTP11RequiredInternal(
670 url::SchemeHostPort server,
671 const net::NetworkIsolationKey& network_isolation_key) {
672 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
673 DCHECK_NE(server.scheme(), url::kWsScheme);
674 DCHECK_NE(server.scheme(), url::kWssScheme);
675 if (server.host().empty())
676 return;
677
678 server_info_map_
679 .GetOrPut(CreateServerInfoKey(std::move(server), network_isolation_key))
680 ->second.requires_http11 = true;
681 // No need to call MaybeQueueWriteProperties(), as this information is not
682 // persisted to preferences.
683}
684
685void HttpServerProperties::MaybeForceHTTP11Internal(
686 url::SchemeHostPort server,
687 const net::NetworkIsolationKey& network_isolation_key,
688 SSLConfig* ssl_config) {
689 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
690 DCHECK_NE(server.scheme(), url::kWsScheme);
691 DCHECK_NE(server.scheme(), url::kWssScheme);
692 if (RequiresHTTP11(std::move(server), network_isolation_key)) {
693 ssl_config->alpn_protos.clear();
694 ssl_config->alpn_protos.push_back(kProtoHTTP11);
695 }
696}
697
698AlternativeServiceInfoVector
699HttpServerProperties::GetAlternativeServiceInfosInternal(
700 const url::SchemeHostPort& origin,
701 const net::NetworkIsolationKey& network_isolation_key) {
702 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
703 DCHECK_NE(origin.scheme(), url::kWsScheme);
704 DCHECK_NE(origin.scheme(), url::kWssScheme);
705
706 // Copy valid alternative service infos into
707 // |valid_alternative_service_infos|.
708 AlternativeServiceInfoVector valid_alternative_service_infos;
709 const base::Time now = clock_->Now();
710 auto map_it =
711 server_info_map_.Get(CreateServerInfoKey(origin, network_isolation_key));
712 if (map_it != server_info_map_.end() &&
713 map_it->second.alternative_services.has_value()) {
714 AlternativeServiceInfoVector* service_info =
715 &map_it->second.alternative_services.value();
716 HostPortPair host_port_pair(origin.host(), origin.port());
717 for (auto it = service_info->begin(); it != service_info->end();) {
718 if (it->expiration() < now) {
719 it = service_info->erase(it);
720 continue;
721 }
722 AlternativeService alternative_service(it->alternative_service());
723 if (alternative_service.host.empty()) {
724 alternative_service.host = origin.host();
725 }
726 // If the alternative service is equivalent to the origin (same host, same
727 // port, and both TCP), skip it.
728 if (host_port_pair.Equals(alternative_service.host_port_pair()) &&
729 alternative_service.protocol == kProtoHTTP2) {
730 ++it;
731 continue;
732 }
733 if (alternative_service.protocol == kProtoQUIC) {
734 valid_alternative_service_infos.push_back(
735 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
736 alternative_service, it->expiration(),
737 it->advertised_versions()));
738 } else {
739 valid_alternative_service_infos.push_back(
740 AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
741 alternative_service, it->expiration()));
742 }
743 ++it;
744 }
745 if (service_info->empty()) {
746 map_it->second.alternative_services.reset();
747 server_info_map_.EraseIfEmpty(map_it);
748 }
749 return valid_alternative_service_infos;
750 }
751
752 auto canonical = GetCanonicalAltSvcHost(origin, network_isolation_key);
753 if (canonical == canonical_alt_svc_map_.end()) {
754 return AlternativeServiceInfoVector();
755 }
756 map_it = server_info_map_.Get(
757 CreateServerInfoKey(canonical->second, network_isolation_key));
758 if (map_it == server_info_map_.end() ||
759 !map_it->second.alternative_services.has_value()) {
760 return AlternativeServiceInfoVector();
761 }
762 AlternativeServiceInfoVector* service_info =
763 &map_it->second.alternative_services.value();
764 for (auto it = service_info->begin(); it != service_info->end();) {
765 if (it->expiration() < now) {
766 it = service_info->erase(it);
767 continue;
768 }
769 AlternativeService alternative_service(it->alternative_service());
770 if (alternative_service.host.empty()) {
771 alternative_service.host = canonical->second.host();
772 if (IsAlternativeServiceBroken(alternative_service,
773 network_isolation_key)) {
774 ++it;
775 continue;
776 }
777 alternative_service.host = origin.host();
778 } else if (IsAlternativeServiceBroken(alternative_service,
779 network_isolation_key)) {
780 ++it;
781 continue;
782 }
783 if (alternative_service.protocol == kProtoQUIC) {
784 valid_alternative_service_infos.push_back(
785 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
786 alternative_service, it->expiration(),
787 it->advertised_versions()));
788 } else {
789 valid_alternative_service_infos.push_back(
790 AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
791 alternative_service, it->expiration()));
792 }
793 ++it;
794 }
795 if (service_info->empty())
796 server_info_map_.EraseIfEmpty(map_it);
797 return valid_alternative_service_infos;
798}
799
800void HttpServerProperties::SetAlternativeServicesInternal(
801 const url::SchemeHostPort& origin,
802 const net::NetworkIsolationKey& network_isolation_key,
803 const AlternativeServiceInfoVector& alternative_service_info_vector) {
804 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
805 DCHECK_NE(origin.scheme(), url::kWsScheme);
806 DCHECK_NE(origin.scheme(), url::kWssScheme);
807
808 if (alternative_service_info_vector.empty()) {
809 RemoveAltSvcCanonicalHost(origin, network_isolation_key);
810 // Don't bother moving to front when erasing information.
811 auto it = server_info_map_.Peek(
812 CreateServerInfoKey(origin, network_isolation_key));
813
814 if (it == server_info_map_.end() ||
815 !it->second.alternative_services.has_value()) {
816 return;
817 }
818
819 it->second.alternative_services.reset();
820 server_info_map_.EraseIfEmpty(it);
821 MaybeQueueWriteProperties();
822 return;
823 }
824
825 auto it = server_info_map_.GetOrPut(
826 CreateServerInfoKey(origin, network_isolation_key));
827 bool need_update_pref = true;
828 if (it->second.alternative_services.has_value()) {
829 DCHECK(!it->second.empty());
830 if (it->second.alternative_services->size() ==
831 alternative_service_info_vector.size()) {
832 const base::Time now = clock_->Now();
833 need_update_pref = false;
834 auto new_it = alternative_service_info_vector.begin();
835 for (const auto& old : *it->second.alternative_services) {
836 // Persist to disk immediately if new entry has different scheme, host,
837 // or port.
838 if (old.alternative_service() != new_it->alternative_service()) {
839 need_update_pref = true;
840 break;
841 }
842 // Also persist to disk if new expiration it more that twice as far or
843 // less than half as far in the future.
844 base::Time old_time = old.expiration();
845 base::Time new_time = new_it->expiration();
846 if (new_time - now > 2 * (old_time - now) ||
847 2 * (new_time - now) < (old_time - now)) {
848 need_update_pref = true;
849 break;
850 }
851 // Also persist to disk if new entry has a different list of advertised
852 // versions.
853 if (old.advertised_versions() != new_it->advertised_versions()) {
854 need_update_pref = true;
855 break;
856 }
857 ++new_it;
858 }
859 }
860 }
861
862 const bool previously_no_alternative_services =
863 (GetIteratorWithAlternativeServiceInfo(origin, network_isolation_key) ==
864 server_info_map_.end());
865
866 it->second.alternative_services = alternative_service_info_vector;
867
868 if (previously_no_alternative_services &&
869 !GetAlternativeServiceInfos(origin, network_isolation_key).empty()) {
870 // TODO(rch): Consider the case where multiple requests are started
871 // before the first completes. In this case, only one of the jobs
872 // would reach this code, whereas all of them should should have.
873 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_MAPPING_MISSING,
874 false);
875 }
876
877 // If this host ends with a canonical suffix, then set it as the
878 // canonical host.
879 const char* kCanonicalScheme = "https";
880 if (origin.scheme() == kCanonicalScheme) {
881 const std::string* canonical_suffix = GetCanonicalSuffix(origin.host());
882 if (canonical_suffix != nullptr) {
883 url::SchemeHostPort canonical_server(kCanonicalScheme, *canonical_suffix,
884 origin.port());
885 canonical_alt_svc_map_[CreateServerInfoKey(
886 canonical_server, network_isolation_key)] = origin;
887 }
888 }
889
890 if (need_update_pref)
891 MaybeQueueWriteProperties();
892}
893
894void HttpServerProperties::SetServerNetworkStatsInternal(
895 url::SchemeHostPort server,
896 const NetworkIsolationKey& network_isolation_key,
897 ServerNetworkStats stats) {
898 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
899 DCHECK_NE(server.scheme(), url::kWsScheme);
900 DCHECK_NE(server.scheme(), url::kWssScheme);
901
902 auto server_info = server_info_map_.GetOrPut(
903 CreateServerInfoKey(std::move(server), network_isolation_key));
904 bool changed = !server_info->second.server_network_stats.has_value() ||
905 server_info->second.server_network_stats.value() != stats;
906
907 if (changed) {
908 server_info->second.server_network_stats = stats;
909 MaybeQueueWriteProperties();
910 }
911}
912
913void HttpServerProperties::ClearServerNetworkStatsInternal(
914 url::SchemeHostPort server,
915 const NetworkIsolationKey& network_isolation_key) {
916 auto server_info = server_info_map_.Peek(
917 CreateServerInfoKey(std::move(server), network_isolation_key));
918 // If stats are empty, nothing to do.
919 if (server_info == server_info_map_.end() ||
920 !server_info->second.server_network_stats.has_value()) {
921 return;
922 }
923
924 // Otherwise, clear and delete if needed. No need to bring to front of MRU
925 // cache when clearing data.
926 server_info->second.server_network_stats.reset();
927 if (server_info->second.empty())
928 server_info_map_.EraseIfEmpty(server_info);
929 MaybeQueueWriteProperties();
930}
931
932const ServerNetworkStats* HttpServerProperties::GetServerNetworkStatsInternal(
933 url::SchemeHostPort server,
934 const NetworkIsolationKey& network_isolation_key) {
935 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
936 DCHECK_NE(server.scheme(), url::kWsScheme);
937 DCHECK_NE(server.scheme(), url::kWssScheme);
938
939 auto server_info = server_info_map_.Get(
940 CreateServerInfoKey(std::move(server), network_isolation_key));
941 if (server_info == server_info_map_.end() ||
942 !server_info->second.server_network_stats.has_value()) {
943 return nullptr;
944 }
945 return &server_info->second.server_network_stats.value();
946}
947
Matt Menke0142bc02019-09-13 20:17:45948HttpServerProperties::QuicServerInfoMapKey
949HttpServerProperties::CreateQuicServerInfoKey(
950 const quic::QuicServerId& server_id,
951 const NetworkIsolationKey& network_isolation_key) const {
952 return QuicServerInfoMapKey(server_id, network_isolation_key,
953 use_network_isolation_key_);
954}
955
Matt Menke1be93d22019-08-20 16:57:58956HttpServerProperties::ServerInfoMapKey
957HttpServerProperties::CreateServerInfoKey(
958 const url::SchemeHostPort& server,
Matt Menke04a5a082019-08-21 15:07:07959 const NetworkIsolationKey& network_isolation_key) const {
Matt Menke1be93d22019-08-20 16:57:58960 return ServerInfoMapKey(server, network_isolation_key,
961 use_network_isolation_key_);
962}
963
Matt Menkefe9b5962019-08-14 20:56:14964HttpServerProperties::ServerInfoMap::const_iterator
965HttpServerProperties::GetIteratorWithAlternativeServiceInfo(
Matt Menke04a5a082019-08-21 15:07:07966 const url::SchemeHostPort& server,
967 const net::NetworkIsolationKey& network_isolation_key) {
Matt Menke1be93d22019-08-20 16:57:58968 ServerInfoMap::const_iterator it =
Matt Menke04a5a082019-08-21 15:07:07969 server_info_map_.Get(CreateServerInfoKey(server, network_isolation_key));
Matt Menkefe9b5962019-08-14 20:56:14970 if (it != server_info_map_.end() && it->second.alternative_services)
Matt Menke609160742019-08-02 18:47:26971 return it;
972
Matt Menke04a5a082019-08-21 15:07:07973 auto canonical = GetCanonicalAltSvcHost(server, network_isolation_key);
Matt Menke609160742019-08-02 18:47:26974 if (canonical == canonical_alt_svc_map_.end()) {
Matt Menkefe9b5962019-08-14 20:56:14975 return server_info_map_.end();
Matt Menke609160742019-08-02 18:47:26976 }
977
978 const url::SchemeHostPort canonical_server = canonical->second;
Matt Menke1be93d22019-08-20 16:57:58979 it = server_info_map_.Get(
Matt Menke04a5a082019-08-21 15:07:07980 CreateServerInfoKey(canonical_server, network_isolation_key));
Matt Menkefe9b5962019-08-14 20:56:14981 if (it == server_info_map_.end() || !it->second.alternative_services)
982 return server_info_map_.end();
Matt Menke609160742019-08-02 18:47:26983
Matt Menkefe9b5962019-08-14 20:56:14984 for (const AlternativeServiceInfo& alternative_service_info :
985 it->second.alternative_services.value()) {
Matt Menke609160742019-08-02 18:47:26986 AlternativeService alternative_service(
987 alternative_service_info.alternative_service());
988 if (alternative_service.host.empty()) {
989 alternative_service.host = canonical_server.host();
990 }
Matt Menkeb32ba5122019-09-10 19:17:05991 if (!IsAlternativeServiceBroken(alternative_service,
992 network_isolation_key)) {
Matt Menke609160742019-08-02 18:47:26993 return it;
994 }
995 }
996
Matt Menke04a5a082019-08-21 15:07:07997 RemoveAltSvcCanonicalHost(canonical_server, network_isolation_key);
Matt Menkefe9b5962019-08-14 20:56:14998 return server_info_map_.end();
Matt Menke609160742019-08-02 18:47:26999}
1000
Matt Menke0142bc02019-09-13 20:17:451001HttpServerProperties::CanonicalMap::const_iterator
Matt Menke609160742019-08-02 18:47:261002HttpServerProperties::GetCanonicalAltSvcHost(
Matt Menke04a5a082019-08-21 15:07:071003 const url::SchemeHostPort& server,
1004 const net::NetworkIsolationKey& network_isolation_key) const {
Matt Menke609160742019-08-02 18:47:261005 const char* kCanonicalScheme = "https";
1006 if (server.scheme() != kCanonicalScheme)
1007 return canonical_alt_svc_map_.end();
1008
1009 const std::string* canonical_suffix = GetCanonicalSuffix(server.host());
1010 if (canonical_suffix == nullptr)
1011 return canonical_alt_svc_map_.end();
1012
1013 url::SchemeHostPort canonical_server(kCanonicalScheme, *canonical_suffix,
1014 server.port());
Matt Menke04a5a082019-08-21 15:07:071015 return canonical_alt_svc_map_.find(
1016 CreateServerInfoKey(canonical_server, network_isolation_key));
Matt Menke609160742019-08-02 18:47:261017}
1018
Matt Menke0142bc02019-09-13 20:17:451019HttpServerProperties::QuicCanonicalMap::const_iterator
Matt Menke609160742019-08-02 18:47:261020HttpServerProperties::GetCanonicalServerInfoHost(
Matt Menke0142bc02019-09-13 20:17:451021 const QuicServerInfoMapKey& key) const {
1022 const std::string* canonical_suffix =
1023 GetCanonicalSuffix(key.server_id.host());
Matt Menke609160742019-08-02 18:47:261024 if (canonical_suffix == nullptr)
1025 return canonical_server_info_map_.end();
1026
Matt Menke0142bc02019-09-13 20:17:451027 quic::QuicServerId canonical_server_id(*canonical_suffix,
1028 key.server_id.privacy_mode_enabled(),
1029 key.server_id.port());
1030 return canonical_server_info_map_.find(
1031 CreateQuicServerInfoKey(canonical_server_id, key.network_isolation_key));
Matt Menke609160742019-08-02 18:47:261032}
1033
1034void HttpServerProperties::RemoveAltSvcCanonicalHost(
Matt Menke04a5a082019-08-21 15:07:071035 const url::SchemeHostPort& server,
1036 const NetworkIsolationKey& network_isolation_key) {
1037 auto canonical = GetCanonicalAltSvcHost(server, network_isolation_key);
Matt Menke609160742019-08-02 18:47:261038 if (canonical == canonical_alt_svc_map_.end())
1039 return;
1040
1041 canonical_alt_svc_map_.erase(canonical->first);
1042}
1043
1044void HttpServerProperties::UpdateCanonicalServerInfoMap(
Matt Menke0142bc02019-09-13 20:17:451045 const QuicServerInfoMapKey& key) {
1046 const std::string* suffix = GetCanonicalSuffix(key.server_id.host());
1047 if (!suffix)
1048 return;
1049 quic::QuicServerId canonical_server(
1050 *suffix, key.server_id.privacy_mode_enabled(), key.server_id.port());
1051
1052 canonical_server_info_map_[CreateQuicServerInfoKey(
1053 canonical_server, key.network_isolation_key)] = key.server_id;
Matt Menke609160742019-08-02 18:47:261054}
1055
1056const std::string* HttpServerProperties::GetCanonicalSuffix(
1057 const std::string& host) const {
1058 // If this host ends with a canonical suffix, then return the canonical
1059 // suffix.
1060 for (const std::string& canonical_suffix : canonical_suffixes_) {
1061 if (base::EndsWith(host, canonical_suffix,
1062 base::CompareCase::INSENSITIVE_ASCII)) {
1063 return &canonical_suffix;
1064 }
1065 }
1066 return nullptr;
1067}
1068
1069void HttpServerProperties::OnPrefsLoaded(
Matt Menke5e7dcd32019-08-09 22:25:211070 std::unique_ptr<ServerInfoMap> server_info_map,
Matt Menkeb566c392019-09-11 23:22:431071 const IPAddress& last_local_address_when_quic_worked,
Matt Menke609160742019-08-02 18:47:261072 std::unique_ptr<QuicServerInfoMap> quic_server_info_map,
1073 std::unique_ptr<BrokenAlternativeServiceList>
1074 broken_alternative_service_list,
1075 std::unique_ptr<RecentlyBrokenAlternativeServices>
Matt Menke7932d812019-08-02 21:26:081076 recently_broken_alternative_services) {
Matt Menke609160742019-08-02 18:47:261077 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
1078
1079 DCHECK(!is_initialized_);
1080
1081 // Either all of these are nullptr, or none of them are (except the broken alt
1082 // service fields).
Matt Menke5e7dcd32019-08-09 22:25:211083 if (server_info_map) {
1084 OnServerInfoLoaded(std::move(server_info_map));
Matt Menkeb566c392019-09-11 23:22:431085 OnLastLocalAddressWhenQuicWorkedLoaded(last_local_address_when_quic_worked);
Matt Menke609160742019-08-02 18:47:261086 OnQuicServerInfoMapLoaded(std::move(quic_server_info_map));
1087 if (recently_broken_alternative_services) {
1088 DCHECK(broken_alternative_service_list);
1089 OnBrokenAndRecentlyBrokenAlternativeServicesLoaded(
1090 std::move(broken_alternative_service_list),
1091 std::move(recently_broken_alternative_services));
1092 }
1093 }
1094
1095 is_initialized_ = true;
1096
Matt Menke7932d812019-08-02 21:26:081097 if (queue_write_on_load_) {
Matt Menke723f10292019-08-02 21:13:101098 // Leaving this as true doesn't actually have any effect, but seems best to
1099 // be safe.
1100 queue_write_on_load_ = false;
Matt Menke609160742019-08-02 18:47:261101 MaybeQueueWriteProperties();
Matt Menke723f10292019-08-02 21:13:101102 }
Matt Menke609160742019-08-02 18:47:261103}
1104
Matt Menke5e7dcd32019-08-09 22:25:211105void HttpServerProperties::OnServerInfoLoaded(
1106 std::unique_ptr<ServerInfoMap> server_info_map) {
Matt Menke609160742019-08-02 18:47:261107 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
1108
Matt Menke1be93d22019-08-20 16:57:581109 // Perform a simple sanity check on loaded data, when DCHECKs are enabled.
1110#if DCHECK_IS_ON()
1111 if (!use_network_isolation_key_) {
1112 for (auto server_info = server_info_map->begin();
1113 server_info != server_info_map->end(); ++server_info) {
1114 DCHECK(server_info->first.network_isolation_key.IsEmpty());
1115 }
1116 }
1117#endif // DCHECK_IS_ON()
1118
Matt Menke5e7dcd32019-08-09 22:25:211119 // Swap in the entries from persisted data. This allows the MRU cache to be
1120 // sorted based on the order of the entries in the newer in-memory cache.
1121 server_info_map_.Swap(*server_info_map);
Matt Menke609160742019-08-02 18:47:261122
1123 // Add the entries from the memory cache.
Matt Menke5e7dcd32019-08-09 22:25:211124 for (auto it = server_info_map->rbegin(); it != server_info_map->rend();
Matt Menke609160742019-08-02 18:47:261125 ++it) {
Matt Menke5e7dcd32019-08-09 22:25:211126 // If there's no corresponding old entry, add the new entry directly.
1127 auto old_entry = server_info_map_.Get(it->first);
1128 if (old_entry == server_info_map_.end()) {
1129 server_info_map_.Put(it->first, std::move(it->second));
1130 continue;
1131 }
1132
1133 // Otherwise, merge the old and new entries. Prefer values from older
1134 // entries.
1135 if (!old_entry->second.supports_spdy.has_value())
1136 old_entry->second.supports_spdy = it->second.supports_spdy;
Matt Menkef2ee07c2019-08-29 02:10:361137 if (!old_entry->second.alternative_services.has_value())
Matt Menkefe9b5962019-08-14 20:56:141138 old_entry->second.alternative_services = it->second.alternative_services;
Matt Menke86878a62019-08-14 21:01:111139 if (!old_entry->second.server_network_stats.has_value())
1140 old_entry->second.server_network_stats = it->second.server_network_stats;
Matt Menkef2ee07c2019-08-29 02:10:361141
1142 // |requires_http11| isn't saved to prefs, so the loaded entry should not
1143 // have it set. Unconditionally copy it from the new entry.
1144 DCHECK(!old_entry->second.requires_http11.has_value());
1145 old_entry->second.requires_http11 = it->second.requires_http11;
Matt Menke609160742019-08-02 18:47:261146 }
1147
1148 // Attempt to find canonical servers. Canonical suffix only apply to HTTPS.
1149 const uint16_t kCanonicalPort = 443;
1150 const char* kCanonicalScheme = "https";
Matt Menke04a5a082019-08-21 15:07:071151 for (auto it = server_info_map_.begin(); it != server_info_map_.end(); ++it) {
1152 if (!it->second.alternative_services ||
1153 it->first.server.scheme() != kCanonicalScheme) {
1154 continue;
1155 }
1156 const std::string* canonical_suffix =
1157 GetCanonicalSuffix(it->first.server.host());
1158 if (!canonical_suffix)
1159 continue;
1160 ServerInfoMapKey key = CreateServerInfoKey(
1161 url::SchemeHostPort(kCanonicalScheme, *canonical_suffix,
1162 kCanonicalPort),
1163 it->first.network_isolation_key);
Matt Menke609160742019-08-02 18:47:261164 // If we already have a valid canonical server, we're done.
Matt Menke04a5a082019-08-21 15:07:071165 if (base::Contains(canonical_alt_svc_map_, key)) {
1166 auto it = server_info_map_.Peek(key);
Matt Menkefe9b5962019-08-14 20:56:141167 if (it != server_info_map_.end() &&
1168 it->second.alternative_services.has_value()) {
1169 continue;
1170 }
Matt Menke609160742019-08-02 18:47:261171 }
Matt Menke04a5a082019-08-21 15:07:071172 canonical_alt_svc_map_[key] = it->first.server;
Matt Menke609160742019-08-02 18:47:261173 }
1174}
1175
Matt Menkeb566c392019-09-11 23:22:431176void HttpServerProperties::OnLastLocalAddressWhenQuicWorkedLoaded(
1177 const IPAddress& last_local_address_when_quic_worked) {
1178 last_local_address_when_quic_worked_ = last_local_address_when_quic_worked;
Matt Menke609160742019-08-02 18:47:261179}
1180
1181void HttpServerProperties::OnQuicServerInfoMapLoaded(
1182 std::unique_ptr<QuicServerInfoMap> quic_server_info_map) {
1183 DCHECK_EQ(quic_server_info_map->max_size(), quic_server_info_map_.max_size());
1184
1185 // Add the entries from persisted data.
1186 quic_server_info_map_.Swap(*quic_server_info_map);
1187
1188 // Add the entries from the memory cache.
1189 for (auto it = quic_server_info_map->rbegin();
1190 it != quic_server_info_map->rend(); ++it) {
1191 if (quic_server_info_map_.Get(it->first) == quic_server_info_map_.end()) {
1192 quic_server_info_map_.Put(it->first, it->second);
1193 }
1194 }
1195
1196 // Repopulate |canonical_server_info_map_| to stay in sync with
1197 // |quic_server_info_map_|.
1198 canonical_server_info_map_.clear();
1199 for (auto it = quic_server_info_map_.rbegin();
1200 it != quic_server_info_map_.rend(); ++it) {
1201 UpdateCanonicalServerInfoMap(it->first);
1202 }
1203}
1204
1205void HttpServerProperties::OnBrokenAndRecentlyBrokenAlternativeServicesLoaded(
1206 std::unique_ptr<BrokenAlternativeServiceList>
1207 broken_alternative_service_list,
1208 std::unique_ptr<RecentlyBrokenAlternativeServices>
1209 recently_broken_alternative_services) {
1210 broken_alternative_services_.SetBrokenAndRecentlyBrokenAlternativeServices(
1211 std::move(broken_alternative_service_list),
1212 std::move(recently_broken_alternative_services));
1213}
1214
1215void HttpServerProperties::MaybeQueueWriteProperties() {
1216 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
1217
Matt Menke723f10292019-08-02 21:13:101218 if (prefs_update_timer_.IsRunning() || !properties_manager_)
1219 return;
1220
1221 if (!is_initialized_) {
1222 queue_write_on_load_ = true;
Matt Menke609160742019-08-02 18:47:261223 return;
1224 }
1225
1226 prefs_update_timer_.Start(
1227 FROM_HERE, kUpdatePrefsDelay,
1228 base::BindOnce(&HttpServerProperties::WriteProperties,
1229 base::Unretained(this), base::OnceClosure()));
1230}
1231
1232void HttpServerProperties::WriteProperties(base::OnceClosure callback) const {
1233 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
1234 DCHECK(properties_manager_);
1235
1236 // |this| shouldn't be waiting to load properties cached to disk when this
1237 // method is invoked, since this method will overwrite any cached properties.
1238 DCHECK(is_initialized_);
1239
1240 // There shouldn't be a queued update when this is run, since this method
1241 // removes the need for any update to be queued.
1242 DCHECK(!prefs_update_timer_.IsRunning());
1243
1244 properties_manager_->WriteToPrefs(
Matt Menkefe9b5962019-08-14 20:56:141245 server_info_map_,
Matt Menke609160742019-08-02 18:47:261246 base::BindRepeating(&HttpServerProperties::GetCanonicalSuffix,
1247 base::Unretained(this)),
Matt Menkeb566c392019-09-11 23:22:431248 last_local_address_when_quic_worked_, quic_server_info_map_,
Matt Menke609160742019-08-02 18:47:261249 broken_alternative_services_.broken_alternative_service_list(),
1250 broken_alternative_services_.recently_broken_alternative_services(),
1251 std::move(callback));
1252}
1253
[email protected]17291a022011-10-10 07:32:531254} // namespace net