1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/http/http_server_properties.h"
6
7 #include "base/check_op.h"
8 #include "base/containers/adapters.h"
9 #include "base/containers/contains.h"
10 #include "base/feature_list.h"
11 #include "base/functional/bind.h"
12 #include "base/location.h"
13 #include "base/metrics/histogram_macros.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/task/single_thread_task_runner.h"
17 #include "base/time/default_clock.h"
18 #include "base/time/default_tick_clock.h"
19 #include "base/values.h"
20 #include "net/base/features.h"
21 #include "net/base/network_anonymization_key.h"
22 #include "net/base/url_util.h"
23 #include "net/http/http_network_session.h"
24 #include "net/http/http_server_properties_manager.h"
25 #include "net/socket/ssl_client_socket.h"
26 #include "net/ssl/ssl_config.h"
27
28 namespace net {
29
30 namespace {
31
32 // Time to wait before starting an update the preferences from the
33 // http_server_properties_impl_ cache. Scheduling another update during this
34 // period will be a no-op.
35 constexpr base::TimeDelta kUpdatePrefsDelay = base::Seconds(60);
36
NormalizeSchemeHostPort(const url::SchemeHostPort & scheme_host_port)37 url::SchemeHostPort NormalizeSchemeHostPort(
38 const url::SchemeHostPort& scheme_host_port) {
39 if (scheme_host_port.scheme() == url::kWssScheme) {
40 return url::SchemeHostPort(url::kHttpsScheme, scheme_host_port.host(),
41 scheme_host_port.port());
42 }
43 if (scheme_host_port.scheme() == url::kWsScheme) {
44 return url::SchemeHostPort(url::kHttpScheme, scheme_host_port.host(),
45 scheme_host_port.port());
46 }
47 return scheme_host_port;
48 }
49
50 } // namespace
51
52 HttpServerProperties::PrefDelegate::~PrefDelegate() = default;
53
54 HttpServerProperties::ServerInfo::ServerInfo() = default;
55 HttpServerProperties::ServerInfo::ServerInfo(const ServerInfo& server_info) =
56 default;
57 HttpServerProperties::ServerInfo::ServerInfo(ServerInfo&& server_info) =
58 default;
59 HttpServerProperties::ServerInfo::~ServerInfo() = default;
60
empty() const61 bool HttpServerProperties::ServerInfo::empty() const {
62 return !supports_spdy.has_value() && !alternative_services.has_value() &&
63 !server_network_stats.has_value();
64 }
65
operator ==(const ServerInfo & other) const66 bool HttpServerProperties::ServerInfo::operator==(
67 const ServerInfo& other) const {
68 return supports_spdy == other.supports_spdy &&
69 alternative_services == other.alternative_services &&
70 server_network_stats == other.server_network_stats;
71 }
72
ServerInfoMapKey(url::SchemeHostPort server,const NetworkAnonymizationKey & network_anonymization_key,bool use_network_anonymization_key)73 HttpServerProperties::ServerInfoMapKey::ServerInfoMapKey(
74 url::SchemeHostPort server,
75 const NetworkAnonymizationKey& network_anonymization_key,
76 bool use_network_anonymization_key)
77 : server(std::move(server)),
78 network_anonymization_key(use_network_anonymization_key
79 ? network_anonymization_key
80 : NetworkAnonymizationKey()) {
81 // Scheme should have been normalized before this method was called.
82 DCHECK_NE(this->server.scheme(), url::kWsScheme);
83 DCHECK_NE(this->server.scheme(), url::kWssScheme);
84 }
85
86 HttpServerProperties::ServerInfoMapKey::~ServerInfoMapKey() = default;
87
operator <(const ServerInfoMapKey & other) const88 bool HttpServerProperties::ServerInfoMapKey::operator<(
89 const ServerInfoMapKey& other) const {
90 return std::tie(server, network_anonymization_key) <
91 std::tie(other.server, other.network_anonymization_key);
92 }
93
QuicServerInfoMapKey(const quic::QuicServerId & server_id,PrivacyMode privacy_mode,const NetworkAnonymizationKey & network_anonymization_key,bool use_network_anonymization_key)94 HttpServerProperties::QuicServerInfoMapKey::QuicServerInfoMapKey(
95 const quic::QuicServerId& server_id,
96 PrivacyMode privacy_mode,
97 const NetworkAnonymizationKey& network_anonymization_key,
98 bool use_network_anonymization_key)
99 : server_id(server_id),
100 privacy_mode(privacy_mode),
101 network_anonymization_key(use_network_anonymization_key
102 ? network_anonymization_key
103 : NetworkAnonymizationKey()) {}
104
105 HttpServerProperties::QuicServerInfoMapKey::~QuicServerInfoMapKey() = default;
106
operator <(const QuicServerInfoMapKey & other) const107 bool HttpServerProperties::QuicServerInfoMapKey::operator<(
108 const QuicServerInfoMapKey& other) const {
109 return std::tie(server_id, privacy_mode, network_anonymization_key) <
110 std::tie(other.server_id, other.privacy_mode,
111 other.network_anonymization_key);
112 }
113
114 // Used in tests.
operator ==(const QuicServerInfoMapKey & other) const115 bool HttpServerProperties::QuicServerInfoMapKey::operator==(
116 const QuicServerInfoMapKey& other) const {
117 return std::tie(server_id, privacy_mode, network_anonymization_key) ==
118 std::tie(other.server_id, other.privacy_mode,
119 other.network_anonymization_key);
120 }
121
ServerInfoMap()122 HttpServerProperties::ServerInfoMap::ServerInfoMap()
123 : base::LRUCache<ServerInfoMapKey, ServerInfo>(kMaxServerInfoEntries) {}
124
125 HttpServerProperties::ServerInfoMap::iterator
GetOrPut(const ServerInfoMapKey & key)126 HttpServerProperties::ServerInfoMap::GetOrPut(const ServerInfoMapKey& key) {
127 auto it = Get(key);
128 if (it != end())
129 return it;
130 return Put(key, ServerInfo());
131 }
132
133 HttpServerProperties::ServerInfoMap::iterator
EraseIfEmpty(iterator server_info_it)134 HttpServerProperties::ServerInfoMap::EraseIfEmpty(iterator server_info_it) {
135 if (server_info_it->second.empty())
136 return Erase(server_info_it);
137 return ++server_info_it;
138 }
139
HttpServerProperties(std::unique_ptr<PrefDelegate> pref_delegate,NetLog * net_log,const base::TickClock * tick_clock,base::Clock * clock)140 HttpServerProperties::HttpServerProperties(
141 std::unique_ptr<PrefDelegate> pref_delegate,
142 NetLog* net_log,
143 const base::TickClock* tick_clock,
144 base::Clock* clock)
145 : tick_clock_(tick_clock ? tick_clock
146 : base::DefaultTickClock::GetInstance()),
147 clock_(clock ? clock : base::DefaultClock::GetInstance()),
148 use_network_anonymization_key_(
149 NetworkAnonymizationKey::IsPartitioningEnabled()),
150 is_initialized_(pref_delegate.get() == nullptr),
151 properties_manager_(
152 pref_delegate
153 ? std::make_unique<HttpServerPropertiesManager>(
154 std::move(pref_delegate),
155 base::BindOnce(&HttpServerProperties::OnPrefsLoaded,
156 base::Unretained(this)),
157 kDefaultMaxQuicServerEntries,
158 net_log,
159 tick_clock_)
160 : nullptr),
161 broken_alternative_services_(kMaxRecentlyBrokenAlternativeServiceEntries,
162 this,
163 tick_clock_),
164 canonical_suffixes_({".ggpht.com", ".c.youtube.com", ".googlevideo.com",
165 ".googleusercontent.com", ".gvt1.com"}),
166 quic_server_info_map_(kDefaultMaxQuicServerEntries),
167 max_server_configs_stored_in_properties_(kDefaultMaxQuicServerEntries) {}
168
~HttpServerProperties()169 HttpServerProperties::~HttpServerProperties() {
170 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
171
172 if (properties_manager_) {
173 // Stop waiting for initial settings.
174 is_initialized_ = true;
175
176 // Stop the timer if it's running, since this will write to the properties
177 // file immediately.
178 prefs_update_timer_.Stop();
179
180 WriteProperties(base::OnceClosure());
181 }
182 }
183
Clear(base::OnceClosure callback)184 void HttpServerProperties::Clear(base::OnceClosure callback) {
185 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
186 server_info_map_.Clear();
187 broken_alternative_services_.Clear();
188 canonical_alt_svc_map_.clear();
189 last_local_address_when_quic_worked_ = IPAddress();
190 quic_server_info_map_.Clear();
191 canonical_server_info_map_.clear();
192
193 if (properties_manager_) {
194 // Stop waiting for initial settings.
195 is_initialized_ = true;
196 // Leaving this as-is doesn't actually have any effect, if it's true, but
197 // seems best to be safe.
198 queue_write_on_load_ = false;
199
200 // Stop the timer if it's running, since this will write to the properties
201 // file immediately.
202 prefs_update_timer_.Stop();
203 WriteProperties(std::move(callback));
204 } else if (callback) {
205 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
206 FROM_HERE, std::move(callback));
207 }
208 }
209
SupportsRequestPriority(const url::SchemeHostPort & server,const NetworkAnonymizationKey & network_anonymization_key)210 bool HttpServerProperties::SupportsRequestPriority(
211 const url::SchemeHostPort& server,
212 const NetworkAnonymizationKey& network_anonymization_key) {
213 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
214 if (server.host().empty())
215 return false;
216
217 if (GetSupportsSpdy(server, network_anonymization_key))
218 return true;
219 const AlternativeServiceInfoVector alternative_service_info_vector =
220 GetAlternativeServiceInfos(server, network_anonymization_key);
221 for (const AlternativeServiceInfo& alternative_service_info :
222 alternative_service_info_vector) {
223 if (alternative_service_info.alternative_service().protocol == kProtoQUIC) {
224 return true;
225 }
226 }
227 return false;
228 }
229
GetSupportsSpdy(const url::SchemeHostPort & server,const NetworkAnonymizationKey & network_anonymization_key)230 bool HttpServerProperties::GetSupportsSpdy(
231 const url::SchemeHostPort& server,
232 const NetworkAnonymizationKey& network_anonymization_key) {
233 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
234 return GetSupportsSpdyInternal(NormalizeSchemeHostPort(server),
235 network_anonymization_key);
236 }
237
SetSupportsSpdy(const url::SchemeHostPort & server,const NetworkAnonymizationKey & network_anonymization_key,bool supports_spdy)238 void HttpServerProperties::SetSupportsSpdy(
239 const url::SchemeHostPort& server,
240 const NetworkAnonymizationKey& network_anonymization_key,
241 bool supports_spdy) {
242 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
243 SetSupportsSpdyInternal(NormalizeSchemeHostPort(server),
244 network_anonymization_key, supports_spdy);
245 }
246
RequiresHTTP11(const url::SchemeHostPort & server,const NetworkAnonymizationKey & network_anonymization_key)247 bool HttpServerProperties::RequiresHTTP11(
248 const url::SchemeHostPort& server,
249 const NetworkAnonymizationKey& network_anonymization_key) {
250 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
251 return RequiresHTTP11Internal(NormalizeSchemeHostPort(server),
252 network_anonymization_key);
253 }
254
SetHTTP11Required(const url::SchemeHostPort & server,const NetworkAnonymizationKey & network_anonymization_key)255 void HttpServerProperties::SetHTTP11Required(
256 const url::SchemeHostPort& server,
257 const NetworkAnonymizationKey& network_anonymization_key) {
258 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
259 SetHTTP11RequiredInternal(NormalizeSchemeHostPort(server),
260 network_anonymization_key);
261 }
262
MaybeForceHTTP11(const url::SchemeHostPort & server,const NetworkAnonymizationKey & network_anonymization_key,SSLConfig * ssl_config)263 void HttpServerProperties::MaybeForceHTTP11(
264 const url::SchemeHostPort& server,
265 const NetworkAnonymizationKey& network_anonymization_key,
266 SSLConfig* ssl_config) {
267 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
268 MaybeForceHTTP11Internal(NormalizeSchemeHostPort(server),
269 network_anonymization_key, ssl_config);
270 }
271
GetAlternativeServiceInfos(const url::SchemeHostPort & origin,const NetworkAnonymizationKey & network_anonymization_key)272 AlternativeServiceInfoVector HttpServerProperties::GetAlternativeServiceInfos(
273 const url::SchemeHostPort& origin,
274 const NetworkAnonymizationKey& network_anonymization_key) {
275 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
276 return GetAlternativeServiceInfosInternal(NormalizeSchemeHostPort(origin),
277 network_anonymization_key);
278 }
279
SetHttp2AlternativeService(const url::SchemeHostPort & origin,const NetworkAnonymizationKey & network_anonymization_key,const AlternativeService & alternative_service,base::Time expiration)280 void HttpServerProperties::SetHttp2AlternativeService(
281 const url::SchemeHostPort& origin,
282 const NetworkAnonymizationKey& network_anonymization_key,
283 const AlternativeService& alternative_service,
284 base::Time expiration) {
285 DCHECK_EQ(alternative_service.protocol, kProtoHTTP2);
286
287 SetAlternativeServices(
288 origin, network_anonymization_key,
289 AlternativeServiceInfoVector(
290 /*size=*/1, AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
291 alternative_service, expiration)));
292 }
293
SetQuicAlternativeService(const url::SchemeHostPort & origin,const NetworkAnonymizationKey & network_anonymization_key,const AlternativeService & alternative_service,base::Time expiration,const quic::ParsedQuicVersionVector & advertised_versions)294 void HttpServerProperties::SetQuicAlternativeService(
295 const url::SchemeHostPort& origin,
296 const NetworkAnonymizationKey& network_anonymization_key,
297 const AlternativeService& alternative_service,
298 base::Time expiration,
299 const quic::ParsedQuicVersionVector& advertised_versions) {
300 DCHECK(alternative_service.protocol == kProtoQUIC);
301
302 SetAlternativeServices(
303 origin, network_anonymization_key,
304 AlternativeServiceInfoVector(
305 /*size=*/1,
306 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
307 alternative_service, expiration, advertised_versions)));
308 }
309
SetAlternativeServices(const url::SchemeHostPort & origin,const NetworkAnonymizationKey & network_anonymization_key,const AlternativeServiceInfoVector & alternative_service_info_vector)310 void HttpServerProperties::SetAlternativeServices(
311 const url::SchemeHostPort& origin,
312 const NetworkAnonymizationKey& network_anonymization_key,
313 const AlternativeServiceInfoVector& alternative_service_info_vector) {
314 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
315 SetAlternativeServicesInternal(NormalizeSchemeHostPort(origin),
316 network_anonymization_key,
317 alternative_service_info_vector);
318 }
319
MarkAlternativeServiceBroken(const AlternativeService & alternative_service,const NetworkAnonymizationKey & network_anonymization_key)320 void HttpServerProperties::MarkAlternativeServiceBroken(
321 const AlternativeService& alternative_service,
322 const NetworkAnonymizationKey& network_anonymization_key) {
323 broken_alternative_services_.MarkBroken(
324 BrokenAlternativeService(alternative_service, network_anonymization_key,
325 use_network_anonymization_key_));
326 MaybeQueueWriteProperties();
327 }
328
329 void HttpServerProperties::
MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(const AlternativeService & alternative_service,const NetworkAnonymizationKey & network_anonymization_key)330 MarkAlternativeServiceBrokenUntilDefaultNetworkChanges(
331 const AlternativeService& alternative_service,
332 const NetworkAnonymizationKey& network_anonymization_key) {
333 broken_alternative_services_.MarkBrokenUntilDefaultNetworkChanges(
334 BrokenAlternativeService(alternative_service, network_anonymization_key,
335 use_network_anonymization_key_));
336 MaybeQueueWriteProperties();
337 }
338
MarkAlternativeServiceRecentlyBroken(const AlternativeService & alternative_service,const NetworkAnonymizationKey & network_anonymization_key)339 void HttpServerProperties::MarkAlternativeServiceRecentlyBroken(
340 const AlternativeService& alternative_service,
341 const NetworkAnonymizationKey& network_anonymization_key) {
342 broken_alternative_services_.MarkRecentlyBroken(
343 BrokenAlternativeService(alternative_service, network_anonymization_key,
344 use_network_anonymization_key_));
345 MaybeQueueWriteProperties();
346 }
347
IsAlternativeServiceBroken(const AlternativeService & alternative_service,const NetworkAnonymizationKey & network_anonymization_key) const348 bool HttpServerProperties::IsAlternativeServiceBroken(
349 const AlternativeService& alternative_service,
350 const NetworkAnonymizationKey& network_anonymization_key) const {
351 return broken_alternative_services_.IsBroken(
352 BrokenAlternativeService(alternative_service, network_anonymization_key,
353 use_network_anonymization_key_));
354 }
355
WasAlternativeServiceRecentlyBroken(const AlternativeService & alternative_service,const NetworkAnonymizationKey & network_anonymization_key)356 bool HttpServerProperties::WasAlternativeServiceRecentlyBroken(
357 const AlternativeService& alternative_service,
358 const NetworkAnonymizationKey& network_anonymization_key) {
359 return broken_alternative_services_.WasRecentlyBroken(
360 BrokenAlternativeService(alternative_service, network_anonymization_key,
361 use_network_anonymization_key_));
362 }
363
ConfirmAlternativeService(const AlternativeService & alternative_service,const NetworkAnonymizationKey & network_anonymization_key)364 void HttpServerProperties::ConfirmAlternativeService(
365 const AlternativeService& alternative_service,
366 const NetworkAnonymizationKey& network_anonymization_key) {
367 bool old_value = IsAlternativeServiceBroken(alternative_service,
368 network_anonymization_key);
369 broken_alternative_services_.Confirm(
370 BrokenAlternativeService(alternative_service, network_anonymization_key,
371 use_network_anonymization_key_));
372 bool new_value = IsAlternativeServiceBroken(alternative_service,
373 network_anonymization_key);
374
375 // For persisting, we only care about the value returned by
376 // IsAlternativeServiceBroken. If that value changes, then call persist.
377 if (old_value != new_value)
378 MaybeQueueWriteProperties();
379 }
380
OnDefaultNetworkChanged()381 void HttpServerProperties::OnDefaultNetworkChanged() {
382 bool changed = broken_alternative_services_.OnDefaultNetworkChanged();
383 if (changed)
384 MaybeQueueWriteProperties();
385 }
386
GetAlternativeServiceInfoAsValue() const387 base::Value HttpServerProperties::GetAlternativeServiceInfoAsValue() const {
388 const base::Time now = clock_->Now();
389 const base::TimeTicks now_ticks = tick_clock_->NowTicks();
390 base::Value::List dict_list;
391 for (const auto& server_info : server_info_map_) {
392 if (!server_info.second.alternative_services.has_value())
393 continue;
394 base::Value::List alternative_service_list;
395 const ServerInfoMapKey& key = server_info.first;
396 for (const AlternativeServiceInfo& alternative_service_info :
397 server_info.second.alternative_services.value()) {
398 std::string alternative_service_string(
399 alternative_service_info.ToString());
400 AlternativeService alternative_service(
401 alternative_service_info.alternative_service());
402 if (alternative_service.host.empty()) {
403 alternative_service.host = key.server.host();
404 }
405 base::TimeTicks brokenness_expiration_ticks;
406 if (broken_alternative_services_.IsBroken(
407 BrokenAlternativeService(
408 alternative_service,
409 server_info.first.network_anonymization_key,
410 use_network_anonymization_key_),
411 &brokenness_expiration_ticks)) {
412 // Convert |brokenness_expiration| from TimeTicks to Time.
413 //
414 // Note: Cannot use `base::UnlocalizedTimeFormatWithPattern()` since
415 // `net/DEPS` disallows `base/i18n`.
416 base::Time brokenness_expiration =
417 now + (brokenness_expiration_ticks - now_ticks);
418 base::Time::Exploded exploded;
419 brokenness_expiration.LocalExplode(&exploded);
420 std::string broken_info_string =
421 " (broken until " +
422 base::StringPrintf("%04d-%02d-%02d %0d:%0d:%0d", exploded.year,
423 exploded.month, exploded.day_of_month,
424 exploded.hour, exploded.minute,
425 exploded.second) +
426 ")";
427 alternative_service_string.append(broken_info_string);
428 }
429 alternative_service_list.Append(std::move(alternative_service_string));
430 }
431 if (alternative_service_list.empty())
432 continue;
433 base::Value::Dict dict;
434 dict.Set("server", key.server.Serialize());
435 dict.Set("network_anonymization_key",
436 key.network_anonymization_key.ToDebugString());
437 dict.Set("alternative_service", std::move(alternative_service_list));
438 dict_list.Append(std::move(dict));
439 }
440 return base::Value(std::move(dict_list));
441 }
442
WasLastLocalAddressWhenQuicWorked(const IPAddress & local_address) const443 bool HttpServerProperties::WasLastLocalAddressWhenQuicWorked(
444 const IPAddress& local_address) const {
445 return !last_local_address_when_quic_worked_.empty() &&
446 last_local_address_when_quic_worked_ == local_address;
447 }
448
HasLastLocalAddressWhenQuicWorked() const449 bool HttpServerProperties::HasLastLocalAddressWhenQuicWorked() const {
450 return !last_local_address_when_quic_worked_.empty();
451 }
452
SetLastLocalAddressWhenQuicWorked(IPAddress last_local_address_when_quic_worked)453 void HttpServerProperties::SetLastLocalAddressWhenQuicWorked(
454 IPAddress last_local_address_when_quic_worked) {
455 DCHECK(!last_local_address_when_quic_worked.empty());
456 if (last_local_address_when_quic_worked_ ==
457 last_local_address_when_quic_worked) {
458 return;
459 }
460
461 last_local_address_when_quic_worked_ = last_local_address_when_quic_worked;
462 MaybeQueueWriteProperties();
463 }
464
ClearLastLocalAddressWhenQuicWorked()465 void HttpServerProperties::ClearLastLocalAddressWhenQuicWorked() {
466 if (last_local_address_when_quic_worked_.empty())
467 return;
468
469 last_local_address_when_quic_worked_ = IPAddress();
470 MaybeQueueWriteProperties();
471 }
472
SetServerNetworkStats(const url::SchemeHostPort & server,const NetworkAnonymizationKey & network_anonymization_key,ServerNetworkStats stats)473 void HttpServerProperties::SetServerNetworkStats(
474 const url::SchemeHostPort& server,
475 const NetworkAnonymizationKey& network_anonymization_key,
476 ServerNetworkStats stats) {
477 SetServerNetworkStatsInternal(NormalizeSchemeHostPort(server),
478 network_anonymization_key, std::move(stats));
479 }
480
ClearServerNetworkStats(const url::SchemeHostPort & server,const NetworkAnonymizationKey & network_anonymization_key)481 void HttpServerProperties::ClearServerNetworkStats(
482 const url::SchemeHostPort& server,
483 const NetworkAnonymizationKey& network_anonymization_key) {
484 ClearServerNetworkStatsInternal(NormalizeSchemeHostPort(server),
485 network_anonymization_key);
486 }
487
GetServerNetworkStats(const url::SchemeHostPort & server,const NetworkAnonymizationKey & network_anonymization_key)488 const ServerNetworkStats* HttpServerProperties::GetServerNetworkStats(
489 const url::SchemeHostPort& server,
490 const NetworkAnonymizationKey& network_anonymization_key) {
491 return GetServerNetworkStatsInternal(NormalizeSchemeHostPort(server),
492 network_anonymization_key);
493 }
494
SetQuicServerInfo(const quic::QuicServerId & server_id,PrivacyMode privacy_mode,const NetworkAnonymizationKey & network_anonymization_key,const std::string & server_info)495 void HttpServerProperties::SetQuicServerInfo(
496 const quic::QuicServerId& server_id,
497 PrivacyMode privacy_mode,
498 const NetworkAnonymizationKey& network_anonymization_key,
499 const std::string& server_info) {
500 QuicServerInfoMapKey key = CreateQuicServerInfoKey(server_id, privacy_mode,
501 network_anonymization_key);
502 auto it = quic_server_info_map_.Peek(key);
503 bool changed =
504 (it == quic_server_info_map_.end() || it->second != server_info);
505 quic_server_info_map_.Put(key, server_info);
506 UpdateCanonicalServerInfoMap(key);
507 if (changed)
508 MaybeQueueWriteProperties();
509 }
510
GetQuicServerInfo(const quic::QuicServerId & server_id,PrivacyMode privacy_mode,const NetworkAnonymizationKey & network_anonymization_key)511 const std::string* HttpServerProperties::GetQuicServerInfo(
512 const quic::QuicServerId& server_id,
513 PrivacyMode privacy_mode,
514 const NetworkAnonymizationKey& network_anonymization_key) {
515 QuicServerInfoMapKey key = CreateQuicServerInfoKey(server_id, privacy_mode,
516 network_anonymization_key);
517 auto it = quic_server_info_map_.Get(key);
518 if (it != quic_server_info_map_.end()) {
519 // Since |canonical_server_info_map_| should always map to the most
520 // recent host, update it with the one that became MRU in
521 // |quic_server_info_map_|.
522 UpdateCanonicalServerInfoMap(key);
523 return &it->second;
524 }
525
526 // If the exact match for |server_id| wasn't found, check
527 // |canonical_server_info_map_| whether there is server info for a host with
528 // the same canonical host suffix.
529 auto canonical_itr = GetCanonicalServerInfoHost(key);
530 if (canonical_itr == canonical_server_info_map_.end())
531 return nullptr;
532
533 // When search in |quic_server_info_map_|, do not change the MRU order.
534 it = quic_server_info_map_.Peek(CreateQuicServerInfoKey(
535 canonical_itr->second, privacy_mode, network_anonymization_key));
536 if (it != quic_server_info_map_.end())
537 return &it->second;
538
539 return nullptr;
540 }
541
542 const HttpServerProperties::QuicServerInfoMap&
quic_server_info_map() const543 HttpServerProperties::quic_server_info_map() const {
544 return quic_server_info_map_;
545 }
546
max_server_configs_stored_in_properties() const547 size_t HttpServerProperties::max_server_configs_stored_in_properties() const {
548 return max_server_configs_stored_in_properties_;
549 }
550
SetMaxServerConfigsStoredInProperties(size_t max_server_configs_stored_in_properties)551 void HttpServerProperties::SetMaxServerConfigsStoredInProperties(
552 size_t max_server_configs_stored_in_properties) {
553 // Do nothing if the new size is the same as the old one.
554 if (max_server_configs_stored_in_properties_ ==
555 max_server_configs_stored_in_properties) {
556 return;
557 }
558
559 max_server_configs_stored_in_properties_ =
560 max_server_configs_stored_in_properties;
561
562 // LRUCache doesn't allow the capacity of the cache to be changed. Thus create
563 // a new map with the new size and add current elements and swap the new map.
564 quic_server_info_map_.ShrinkToSize(max_server_configs_stored_in_properties_);
565 QuicServerInfoMap temp_map(max_server_configs_stored_in_properties_);
566 // Update the |canonical_server_info_map_| as well, so it stays in sync with
567 // |quic_server_info_map_|.
568 canonical_server_info_map_ = QuicCanonicalMap();
569 for (const auto& [key, server_info] : base::Reversed(quic_server_info_map_)) {
570 temp_map.Put(key, server_info);
571 UpdateCanonicalServerInfoMap(key);
572 }
573
574 quic_server_info_map_.Swap(temp_map);
575 if (properties_manager_) {
576 properties_manager_->set_max_server_configs_stored_in_properties(
577 max_server_configs_stored_in_properties);
578 }
579 }
580
SetBrokenAlternativeServicesDelayParams(std::optional<base::TimeDelta> initial_delay,std::optional<bool> exponential_backoff_on_initial_delay)581 void HttpServerProperties::SetBrokenAlternativeServicesDelayParams(
582 std::optional<base::TimeDelta> initial_delay,
583 std::optional<bool> exponential_backoff_on_initial_delay) {
584 broken_alternative_services_.SetDelayParams(
585 initial_delay, exponential_backoff_on_initial_delay);
586 }
587
IsInitialized() const588 bool HttpServerProperties::IsInitialized() const {
589 return is_initialized_;
590 }
591
OnExpireBrokenAlternativeService(const AlternativeService & expired_alternative_service,const NetworkAnonymizationKey & network_anonymization_key)592 void HttpServerProperties::OnExpireBrokenAlternativeService(
593 const AlternativeService& expired_alternative_service,
594 const NetworkAnonymizationKey& network_anonymization_key) {
595 // Remove every occurrence of |expired_alternative_service| from
596 // |alternative_service_map_|.
597 for (auto map_it = server_info_map_.begin();
598 map_it != server_info_map_.end();) {
599 if (!map_it->second.alternative_services.has_value() ||
600 map_it->first.network_anonymization_key != network_anonymization_key) {
601 ++map_it;
602 continue;
603 }
604 AlternativeServiceInfoVector* service_info =
605 &map_it->second.alternative_services.value();
606 for (auto it = service_info->begin(); it != service_info->end();) {
607 AlternativeService alternative_service(it->alternative_service());
608 // Empty hostname in map means hostname of key: substitute before
609 // comparing to |expired_alternative_service|.
610 if (alternative_service.host.empty()) {
611 alternative_service.host = map_it->first.server.host();
612 }
613 if (alternative_service == expired_alternative_service) {
614 it = service_info->erase(it);
615 continue;
616 }
617 ++it;
618 }
619 // If an origin has an empty list of alternative services, then remove it
620 // from both |canonical_alt_svc_map_| and
621 // |alternative_service_map_|.
622 if (service_info->empty()) {
623 RemoveAltSvcCanonicalHost(map_it->first.server,
624 network_anonymization_key);
625 map_it->second.alternative_services.reset();
626 map_it = server_info_map_.EraseIfEmpty(map_it);
627 continue;
628 }
629 ++map_it;
630 }
631 }
632
GetUpdatePrefsDelayForTesting()633 base::TimeDelta HttpServerProperties::GetUpdatePrefsDelayForTesting() {
634 return kUpdatePrefsDelay;
635 }
636
GetSupportsSpdyInternal(url::SchemeHostPort server,const NetworkAnonymizationKey & network_anonymization_key)637 bool HttpServerProperties::GetSupportsSpdyInternal(
638 url::SchemeHostPort server,
639 const NetworkAnonymizationKey& network_anonymization_key) {
640 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
641 DCHECK_NE(server.scheme(), url::kWsScheme);
642 DCHECK_NE(server.scheme(), url::kWssScheme);
643 if (server.host().empty())
644 return false;
645
646 auto server_info = server_info_map_.Get(
647 CreateServerInfoKey(std::move(server), network_anonymization_key));
648 return server_info != server_info_map_.end() &&
649 server_info->second.supports_spdy.value_or(false);
650 }
651
SetSupportsSpdyInternal(url::SchemeHostPort server,const NetworkAnonymizationKey & network_anonymization_key,bool supports_spdy)652 void HttpServerProperties::SetSupportsSpdyInternal(
653 url::SchemeHostPort server,
654 const NetworkAnonymizationKey& network_anonymization_key,
655 bool supports_spdy) {
656 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
657 DCHECK_NE(server.scheme(), url::kWsScheme);
658 DCHECK_NE(server.scheme(), url::kWssScheme);
659 if (server.host().empty())
660 return;
661
662 auto server_info = server_info_map_.GetOrPut(
663 CreateServerInfoKey(std::move(server), network_anonymization_key));
664 // If value is already the same as |supports_spdy|, or value is unset and
665 // |supports_spdy| is false, don't queue a write.
666 bool queue_write =
667 server_info->second.supports_spdy.value_or(false) != supports_spdy;
668 server_info->second.supports_spdy = supports_spdy;
669
670 if (queue_write)
671 MaybeQueueWriteProperties();
672 }
673
RequiresHTTP11Internal(url::SchemeHostPort server,const NetworkAnonymizationKey & network_anonymization_key)674 bool HttpServerProperties::RequiresHTTP11Internal(
675 url::SchemeHostPort server,
676 const NetworkAnonymizationKey& network_anonymization_key) {
677 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
678 DCHECK_NE(server.scheme(), url::kWsScheme);
679 DCHECK_NE(server.scheme(), url::kWssScheme);
680 if (server.host().empty())
681 return false;
682
683 auto spdy_info = server_info_map_.Get(
684 CreateServerInfoKey(std::move(server), network_anonymization_key));
685 return spdy_info != server_info_map_.end() &&
686 spdy_info->second.requires_http11.value_or(false);
687 }
688
SetHTTP11RequiredInternal(url::SchemeHostPort server,const NetworkAnonymizationKey & network_anonymization_key)689 void HttpServerProperties::SetHTTP11RequiredInternal(
690 url::SchemeHostPort server,
691 const NetworkAnonymizationKey& network_anonymization_key) {
692 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
693 DCHECK_NE(server.scheme(), url::kWsScheme);
694 DCHECK_NE(server.scheme(), url::kWssScheme);
695 if (server.host().empty())
696 return;
697
698 server_info_map_
699 .GetOrPut(
700 CreateServerInfoKey(std::move(server), network_anonymization_key))
701 ->second.requires_http11 = true;
702 // No need to call MaybeQueueWriteProperties(), as this information is not
703 // persisted to preferences.
704 }
705
MaybeForceHTTP11Internal(url::SchemeHostPort server,const NetworkAnonymizationKey & network_anonymization_key,SSLConfig * ssl_config)706 void HttpServerProperties::MaybeForceHTTP11Internal(
707 url::SchemeHostPort server,
708 const NetworkAnonymizationKey& network_anonymization_key,
709 SSLConfig* ssl_config) {
710 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
711 DCHECK_NE(server.scheme(), url::kWsScheme);
712 DCHECK_NE(server.scheme(), url::kWssScheme);
713 if (RequiresHTTP11(std::move(server), network_anonymization_key)) {
714 ssl_config->alpn_protos.clear();
715 ssl_config->alpn_protos.push_back(kProtoHTTP11);
716 }
717 }
718
719 AlternativeServiceInfoVector
GetAlternativeServiceInfosInternal(const url::SchemeHostPort & origin,const NetworkAnonymizationKey & network_anonymization_key)720 HttpServerProperties::GetAlternativeServiceInfosInternal(
721 const url::SchemeHostPort& origin,
722 const NetworkAnonymizationKey& network_anonymization_key) {
723 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
724 DCHECK_NE(origin.scheme(), url::kWsScheme);
725 DCHECK_NE(origin.scheme(), url::kWssScheme);
726
727 // Copy valid alternative service infos into
728 // |valid_alternative_service_infos|.
729 AlternativeServiceInfoVector valid_alternative_service_infos;
730 const base::Time now = clock_->Now();
731 auto map_it = server_info_map_.Get(
732 CreateServerInfoKey(origin, network_anonymization_key));
733 if (map_it != server_info_map_.end() &&
734 map_it->second.alternative_services.has_value()) {
735 AlternativeServiceInfoVector* service_info =
736 &map_it->second.alternative_services.value();
737 HostPortPair host_port_pair(origin.host(), origin.port());
738 for (auto it = service_info->begin(); it != service_info->end();) {
739 if (it->expiration() < now) {
740 it = service_info->erase(it);
741 continue;
742 }
743 AlternativeService alternative_service(it->alternative_service());
744 if (alternative_service.host.empty()) {
745 alternative_service.host = origin.host();
746 }
747 // If the alternative service is equivalent to the origin (same host, same
748 // port, and both TCP), skip it.
749 if (host_port_pair.Equals(alternative_service.GetHostPortPair()) &&
750 alternative_service.protocol == kProtoHTTP2) {
751 ++it;
752 continue;
753 }
754 if (alternative_service.protocol == kProtoQUIC) {
755 valid_alternative_service_infos.push_back(
756 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
757 alternative_service, it->expiration(),
758 it->advertised_versions()));
759 } else {
760 valid_alternative_service_infos.push_back(
761 AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
762 alternative_service, it->expiration()));
763 }
764 ++it;
765 }
766 if (service_info->empty()) {
767 map_it->second.alternative_services.reset();
768 server_info_map_.EraseIfEmpty(map_it);
769 }
770 return valid_alternative_service_infos;
771 }
772
773 auto canonical = GetCanonicalAltSvcHost(origin, network_anonymization_key);
774 if (canonical == canonical_alt_svc_map_.end()) {
775 return AlternativeServiceInfoVector();
776 }
777 map_it = server_info_map_.Get(
778 CreateServerInfoKey(canonical->second, network_anonymization_key));
779 if (map_it == server_info_map_.end() ||
780 !map_it->second.alternative_services.has_value()) {
781 return AlternativeServiceInfoVector();
782 }
783 AlternativeServiceInfoVector* service_info =
784 &map_it->second.alternative_services.value();
785 for (auto it = service_info->begin(); it != service_info->end();) {
786 if (it->expiration() < now) {
787 it = service_info->erase(it);
788 continue;
789 }
790 AlternativeService alternative_service(it->alternative_service());
791 if (alternative_service.host.empty()) {
792 alternative_service.host = canonical->second.host();
793 if (IsAlternativeServiceBroken(alternative_service,
794 network_anonymization_key)) {
795 ++it;
796 continue;
797 }
798 alternative_service.host = origin.host();
799 } else if (IsAlternativeServiceBroken(alternative_service,
800 network_anonymization_key)) {
801 ++it;
802 continue;
803 }
804 if (alternative_service.protocol == kProtoQUIC) {
805 valid_alternative_service_infos.push_back(
806 AlternativeServiceInfo::CreateQuicAlternativeServiceInfo(
807 alternative_service, it->expiration(),
808 it->advertised_versions()));
809 } else {
810 valid_alternative_service_infos.push_back(
811 AlternativeServiceInfo::CreateHttp2AlternativeServiceInfo(
812 alternative_service, it->expiration()));
813 }
814 ++it;
815 }
816 if (service_info->empty())
817 server_info_map_.EraseIfEmpty(map_it);
818 return valid_alternative_service_infos;
819 }
820
SetAlternativeServicesInternal(const url::SchemeHostPort & origin,const NetworkAnonymizationKey & network_anonymization_key,const AlternativeServiceInfoVector & alternative_service_info_vector)821 void HttpServerProperties::SetAlternativeServicesInternal(
822 const url::SchemeHostPort& origin,
823 const NetworkAnonymizationKey& network_anonymization_key,
824 const AlternativeServiceInfoVector& alternative_service_info_vector) {
825 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
826 DCHECK_NE(origin.scheme(), url::kWsScheme);
827 DCHECK_NE(origin.scheme(), url::kWssScheme);
828
829 if (alternative_service_info_vector.empty()) {
830 RemoveAltSvcCanonicalHost(origin, network_anonymization_key);
831 // Don't bother moving to front when erasing information.
832 auto it = server_info_map_.Peek(
833 CreateServerInfoKey(origin, network_anonymization_key));
834
835 if (it == server_info_map_.end() ||
836 !it->second.alternative_services.has_value()) {
837 return;
838 }
839
840 it->second.alternative_services.reset();
841 server_info_map_.EraseIfEmpty(it);
842 MaybeQueueWriteProperties();
843 return;
844 }
845
846 auto it = server_info_map_.GetOrPut(
847 CreateServerInfoKey(origin, network_anonymization_key));
848 bool need_update_pref = true;
849 if (it->second.alternative_services.has_value()) {
850 DCHECK(!it->second.empty());
851 if (it->second.alternative_services->size() ==
852 alternative_service_info_vector.size()) {
853 const base::Time now = clock_->Now();
854 need_update_pref = false;
855 auto new_it = alternative_service_info_vector.begin();
856 for (const auto& old : *it->second.alternative_services) {
857 // Persist to disk immediately if new entry has different scheme, host,
858 // or port.
859 if (old.alternative_service() != new_it->alternative_service()) {
860 need_update_pref = true;
861 break;
862 }
863 // Also persist to disk if new expiration it more that twice as far or
864 // less than half as far in the future.
865 base::Time old_time = old.expiration();
866 base::Time new_time = new_it->expiration();
867 if (new_time - now > 2 * (old_time - now) ||
868 2 * (new_time - now) < (old_time - now)) {
869 need_update_pref = true;
870 break;
871 }
872 // Also persist to disk if new entry has a different list of advertised
873 // versions.
874 if (old.advertised_versions() != new_it->advertised_versions()) {
875 need_update_pref = true;
876 break;
877 }
878 ++new_it;
879 }
880 }
881 }
882
883 const bool previously_no_alternative_services =
884 (GetIteratorWithAlternativeServiceInfo(
885 origin, network_anonymization_key) == server_info_map_.end());
886
887 it->second.alternative_services = alternative_service_info_vector;
888
889 if (previously_no_alternative_services &&
890 !GetAlternativeServiceInfos(origin, network_anonymization_key).empty()) {
891 // TODO(rch): Consider the case where multiple requests are started
892 // before the first completes. In this case, only one of the jobs
893 // would reach this code, whereas all of them should should have.
894 HistogramAlternateProtocolUsage(ALTERNATE_PROTOCOL_USAGE_MAPPING_MISSING,
895 IsGoogleHost(origin.host()));
896 }
897
898 // If this host ends with a canonical suffix, then set it as the
899 // canonical host.
900 const char* kCanonicalScheme = "https";
901 if (origin.scheme() == kCanonicalScheme) {
902 const std::string* canonical_suffix = GetCanonicalSuffix(origin.host());
903 if (canonical_suffix != nullptr) {
904 url::SchemeHostPort canonical_server(kCanonicalScheme, *canonical_suffix,
905 origin.port());
906 canonical_alt_svc_map_[CreateServerInfoKey(
907 canonical_server, network_anonymization_key)] = origin;
908 }
909 }
910
911 if (need_update_pref)
912 MaybeQueueWriteProperties();
913 }
914
SetServerNetworkStatsInternal(url::SchemeHostPort server,const NetworkAnonymizationKey & network_anonymization_key,ServerNetworkStats stats)915 void HttpServerProperties::SetServerNetworkStatsInternal(
916 url::SchemeHostPort server,
917 const NetworkAnonymizationKey& network_anonymization_key,
918 ServerNetworkStats stats) {
919 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
920 DCHECK_NE(server.scheme(), url::kWsScheme);
921 DCHECK_NE(server.scheme(), url::kWssScheme);
922
923 auto server_info = server_info_map_.GetOrPut(
924 CreateServerInfoKey(std::move(server), network_anonymization_key));
925 bool changed = !server_info->second.server_network_stats.has_value() ||
926 server_info->second.server_network_stats.value() != stats;
927
928 if (changed) {
929 server_info->second.server_network_stats = stats;
930 MaybeQueueWriteProperties();
931 }
932 }
933
ClearServerNetworkStatsInternal(url::SchemeHostPort server,const NetworkAnonymizationKey & network_anonymization_key)934 void HttpServerProperties::ClearServerNetworkStatsInternal(
935 url::SchemeHostPort server,
936 const NetworkAnonymizationKey& network_anonymization_key) {
937 auto server_info = server_info_map_.Peek(
938 CreateServerInfoKey(std::move(server), network_anonymization_key));
939 // If stats are empty, nothing to do.
940 if (server_info == server_info_map_.end() ||
941 !server_info->second.server_network_stats.has_value()) {
942 return;
943 }
944
945 // Otherwise, clear and delete if needed. No need to bring to front of MRU
946 // cache when clearing data.
947 server_info->second.server_network_stats.reset();
948 if (server_info->second.empty())
949 server_info_map_.EraseIfEmpty(server_info);
950 MaybeQueueWriteProperties();
951 }
952
GetServerNetworkStatsInternal(url::SchemeHostPort server,const NetworkAnonymizationKey & network_anonymization_key)953 const ServerNetworkStats* HttpServerProperties::GetServerNetworkStatsInternal(
954 url::SchemeHostPort server,
955 const NetworkAnonymizationKey& network_anonymization_key) {
956 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
957 DCHECK_NE(server.scheme(), url::kWsScheme);
958 DCHECK_NE(server.scheme(), url::kWssScheme);
959
960 auto server_info = server_info_map_.Get(
961 CreateServerInfoKey(std::move(server), network_anonymization_key));
962 if (server_info == server_info_map_.end() ||
963 !server_info->second.server_network_stats.has_value()) {
964 return nullptr;
965 }
966 return &server_info->second.server_network_stats.value();
967 }
968
969 HttpServerProperties::QuicServerInfoMapKey
CreateQuicServerInfoKey(const quic::QuicServerId & server_id,PrivacyMode privacy_mode,const NetworkAnonymizationKey & network_anonymization_key) const970 HttpServerProperties::CreateQuicServerInfoKey(
971 const quic::QuicServerId& server_id,
972 PrivacyMode privacy_mode,
973 const NetworkAnonymizationKey& network_anonymization_key) const {
974 return QuicServerInfoMapKey(server_id, privacy_mode,
975 network_anonymization_key,
976 use_network_anonymization_key_);
977 }
978
979 HttpServerProperties::ServerInfoMapKey
CreateServerInfoKey(const url::SchemeHostPort & server,const NetworkAnonymizationKey & network_anonymization_key) const980 HttpServerProperties::CreateServerInfoKey(
981 const url::SchemeHostPort& server,
982 const NetworkAnonymizationKey& network_anonymization_key) const {
983 return ServerInfoMapKey(server, network_anonymization_key,
984 use_network_anonymization_key_);
985 }
986
987 HttpServerProperties::ServerInfoMap::const_iterator
GetIteratorWithAlternativeServiceInfo(const url::SchemeHostPort & server,const NetworkAnonymizationKey & network_anonymization_key)988 HttpServerProperties::GetIteratorWithAlternativeServiceInfo(
989 const url::SchemeHostPort& server,
990 const NetworkAnonymizationKey& network_anonymization_key) {
991 ServerInfoMap::const_iterator it = server_info_map_.Get(
992 CreateServerInfoKey(server, network_anonymization_key));
993 if (it != server_info_map_.end() && it->second.alternative_services)
994 return it;
995
996 auto canonical = GetCanonicalAltSvcHost(server, network_anonymization_key);
997 if (canonical == canonical_alt_svc_map_.end()) {
998 return server_info_map_.end();
999 }
1000
1001 const url::SchemeHostPort canonical_server = canonical->second;
1002 it = server_info_map_.Get(
1003 CreateServerInfoKey(canonical_server, network_anonymization_key));
1004 if (it == server_info_map_.end() || !it->second.alternative_services)
1005 return server_info_map_.end();
1006
1007 for (const AlternativeServiceInfo& alternative_service_info :
1008 it->second.alternative_services.value()) {
1009 AlternativeService alternative_service(
1010 alternative_service_info.alternative_service());
1011 if (alternative_service.host.empty()) {
1012 alternative_service.host = canonical_server.host();
1013 }
1014 if (!IsAlternativeServiceBroken(alternative_service,
1015 network_anonymization_key)) {
1016 return it;
1017 }
1018 }
1019
1020 RemoveAltSvcCanonicalHost(canonical_server, network_anonymization_key);
1021 return server_info_map_.end();
1022 }
1023
1024 HttpServerProperties::CanonicalMap::const_iterator
GetCanonicalAltSvcHost(const url::SchemeHostPort & server,const NetworkAnonymizationKey & network_anonymization_key) const1025 HttpServerProperties::GetCanonicalAltSvcHost(
1026 const url::SchemeHostPort& server,
1027 const NetworkAnonymizationKey& network_anonymization_key) const {
1028 const char* kCanonicalScheme = "https";
1029 if (server.scheme() != kCanonicalScheme)
1030 return canonical_alt_svc_map_.end();
1031
1032 const std::string* canonical_suffix = GetCanonicalSuffix(server.host());
1033 if (canonical_suffix == nullptr)
1034 return canonical_alt_svc_map_.end();
1035
1036 url::SchemeHostPort canonical_server(kCanonicalScheme, *canonical_suffix,
1037 server.port());
1038 return canonical_alt_svc_map_.find(
1039 CreateServerInfoKey(canonical_server, network_anonymization_key));
1040 }
1041
1042 HttpServerProperties::QuicCanonicalMap::const_iterator
GetCanonicalServerInfoHost(const QuicServerInfoMapKey & key) const1043 HttpServerProperties::GetCanonicalServerInfoHost(
1044 const QuicServerInfoMapKey& key) const {
1045 const std::string* canonical_suffix =
1046 GetCanonicalSuffix(key.server_id.host());
1047 if (canonical_suffix == nullptr)
1048 return canonical_server_info_map_.end();
1049
1050 quic::QuicServerId canonical_server_id(*canonical_suffix,
1051 key.server_id.port());
1052 return canonical_server_info_map_.find(CreateQuicServerInfoKey(
1053 canonical_server_id, key.privacy_mode, key.network_anonymization_key));
1054 }
1055
RemoveAltSvcCanonicalHost(const url::SchemeHostPort & server,const NetworkAnonymizationKey & network_anonymization_key)1056 void HttpServerProperties::RemoveAltSvcCanonicalHost(
1057 const url::SchemeHostPort& server,
1058 const NetworkAnonymizationKey& network_anonymization_key) {
1059 auto canonical = GetCanonicalAltSvcHost(server, network_anonymization_key);
1060 if (canonical == canonical_alt_svc_map_.end())
1061 return;
1062
1063 canonical_alt_svc_map_.erase(canonical->first);
1064 }
1065
UpdateCanonicalServerInfoMap(const QuicServerInfoMapKey & key)1066 void HttpServerProperties::UpdateCanonicalServerInfoMap(
1067 const QuicServerInfoMapKey& key) {
1068 const std::string* suffix = GetCanonicalSuffix(key.server_id.host());
1069 if (!suffix)
1070 return;
1071 quic::QuicServerId canonical_server(*suffix, key.server_id.port());
1072
1073 canonical_server_info_map_[CreateQuicServerInfoKey(
1074 canonical_server, key.privacy_mode, key.network_anonymization_key)] =
1075 key.server_id;
1076 }
1077
GetCanonicalSuffix(const std::string & host) const1078 const std::string* HttpServerProperties::GetCanonicalSuffix(
1079 const std::string& host) const {
1080 // If this host ends with a canonical suffix, then return the canonical
1081 // suffix.
1082 for (const std::string& canonical_suffix : canonical_suffixes_) {
1083 if (base::EndsWith(host, canonical_suffix,
1084 base::CompareCase::INSENSITIVE_ASCII)) {
1085 return &canonical_suffix;
1086 }
1087 }
1088 return nullptr;
1089 }
1090
OnPrefsLoaded(std::unique_ptr<ServerInfoMap> server_info_map,const IPAddress & last_local_address_when_quic_worked,std::unique_ptr<QuicServerInfoMap> quic_server_info_map,std::unique_ptr<BrokenAlternativeServiceList> broken_alternative_service_list,std::unique_ptr<RecentlyBrokenAlternativeServices> recently_broken_alternative_services)1091 void HttpServerProperties::OnPrefsLoaded(
1092 std::unique_ptr<ServerInfoMap> server_info_map,
1093 const IPAddress& last_local_address_when_quic_worked,
1094 std::unique_ptr<QuicServerInfoMap> quic_server_info_map,
1095 std::unique_ptr<BrokenAlternativeServiceList>
1096 broken_alternative_service_list,
1097 std::unique_ptr<RecentlyBrokenAlternativeServices>
1098 recently_broken_alternative_services) {
1099 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
1100
1101 DCHECK(!is_initialized_);
1102
1103 // Either all of these are nullptr, or none of them are (except the broken alt
1104 // service fields).
1105 if (server_info_map) {
1106 OnServerInfoLoaded(std::move(server_info_map));
1107 OnLastLocalAddressWhenQuicWorkedLoaded(last_local_address_when_quic_worked);
1108 OnQuicServerInfoMapLoaded(std::move(quic_server_info_map));
1109 if (recently_broken_alternative_services) {
1110 DCHECK(broken_alternative_service_list);
1111 OnBrokenAndRecentlyBrokenAlternativeServicesLoaded(
1112 std::move(broken_alternative_service_list),
1113 std::move(recently_broken_alternative_services));
1114 }
1115 }
1116
1117 is_initialized_ = true;
1118
1119 if (queue_write_on_load_) {
1120 // Leaving this as true doesn't actually have any effect, but seems best to
1121 // be safe.
1122 queue_write_on_load_ = false;
1123 MaybeQueueWriteProperties();
1124 }
1125 }
1126
OnServerInfoLoaded(std::unique_ptr<ServerInfoMap> server_info_map)1127 void HttpServerProperties::OnServerInfoLoaded(
1128 std::unique_ptr<ServerInfoMap> server_info_map) {
1129 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
1130
1131 // Perform a simple sanity check on loaded data, when DCHECKs are enabled.
1132 #if DCHECK_IS_ON()
1133 if (!use_network_anonymization_key_) {
1134 for (auto server_info = server_info_map->begin();
1135 server_info != server_info_map->end(); ++server_info) {
1136 DCHECK(server_info->first.network_anonymization_key.IsEmpty());
1137 }
1138 }
1139 #endif // DCHECK_IS_ON()
1140
1141 // Swap in the entries from persisted data. This allows the MRU cache to be
1142 // sorted based on the order of the entries in the newer in-memory cache.
1143 server_info_map_.Swap(*server_info_map);
1144
1145 // Add the entries from the memory cache.
1146 for (auto& [key, server_info] : base::Reversed(*server_info_map)) {
1147 // If there's no corresponding old entry, add the new entry directly.
1148 auto old_entry = server_info_map_.Get(key);
1149 if (old_entry == server_info_map_.end()) {
1150 server_info_map_.Put(key, std::move(server_info));
1151 continue;
1152 }
1153
1154 // Otherwise, merge the old and new entries. Prefer values from older
1155 // entries.
1156 if (!old_entry->second.supports_spdy.has_value())
1157 old_entry->second.supports_spdy = server_info.supports_spdy;
1158 if (!old_entry->second.alternative_services.has_value())
1159 old_entry->second.alternative_services = server_info.alternative_services;
1160 if (!old_entry->second.server_network_stats.has_value())
1161 old_entry->second.server_network_stats = server_info.server_network_stats;
1162
1163 // |requires_http11| isn't saved to prefs, so the loaded entry should not
1164 // have it set. Unconditionally copy it from the new entry.
1165 DCHECK(!old_entry->second.requires_http11.has_value());
1166 old_entry->second.requires_http11 = server_info.requires_http11;
1167 }
1168
1169 // Attempt to find canonical servers. Canonical suffix only apply to HTTPS.
1170 const uint16_t kCanonicalPort = 443;
1171 const char* kCanonicalScheme = "https";
1172 for (const auto& it : server_info_map_) {
1173 if (!it.second.alternative_services ||
1174 it.first.server.scheme() != kCanonicalScheme) {
1175 continue;
1176 }
1177 const std::string* canonical_suffix =
1178 GetCanonicalSuffix(it.first.server.host());
1179 if (!canonical_suffix)
1180 continue;
1181 ServerInfoMapKey key = CreateServerInfoKey(
1182 url::SchemeHostPort(kCanonicalScheme, *canonical_suffix,
1183 kCanonicalPort),
1184 it.first.network_anonymization_key);
1185 // If we already have a valid canonical server, we're done.
1186 if (base::Contains(canonical_alt_svc_map_, key)) {
1187 auto key_it = server_info_map_.Peek(key);
1188 if (key_it != server_info_map_.end() &&
1189 key_it->second.alternative_services.has_value()) {
1190 continue;
1191 }
1192 }
1193 canonical_alt_svc_map_[key] = it.first.server;
1194 }
1195 }
1196
OnLastLocalAddressWhenQuicWorkedLoaded(const IPAddress & last_local_address_when_quic_worked)1197 void HttpServerProperties::OnLastLocalAddressWhenQuicWorkedLoaded(
1198 const IPAddress& last_local_address_when_quic_worked) {
1199 last_local_address_when_quic_worked_ = last_local_address_when_quic_worked;
1200 }
1201
OnQuicServerInfoMapLoaded(std::unique_ptr<QuicServerInfoMap> quic_server_info_map)1202 void HttpServerProperties::OnQuicServerInfoMapLoaded(
1203 std::unique_ptr<QuicServerInfoMap> quic_server_info_map) {
1204 DCHECK_EQ(quic_server_info_map->max_size(), quic_server_info_map_.max_size());
1205
1206 // Add the entries from persisted data.
1207 quic_server_info_map_.Swap(*quic_server_info_map);
1208
1209 // Add the entries from the memory cache.
1210 for (const auto& [key, server_info] : base::Reversed(*quic_server_info_map)) {
1211 if (quic_server_info_map_.Get(key) == quic_server_info_map_.end()) {
1212 quic_server_info_map_.Put(key, server_info);
1213 }
1214 }
1215
1216 // Repopulate |canonical_server_info_map_| to stay in sync with
1217 // |quic_server_info_map_|.
1218 canonical_server_info_map_.clear();
1219 for (const auto& [key, server_info] : base::Reversed(quic_server_info_map_)) {
1220 UpdateCanonicalServerInfoMap(key);
1221 }
1222 }
1223
OnBrokenAndRecentlyBrokenAlternativeServicesLoaded(std::unique_ptr<BrokenAlternativeServiceList> broken_alternative_service_list,std::unique_ptr<RecentlyBrokenAlternativeServices> recently_broken_alternative_services)1224 void HttpServerProperties::OnBrokenAndRecentlyBrokenAlternativeServicesLoaded(
1225 std::unique_ptr<BrokenAlternativeServiceList>
1226 broken_alternative_service_list,
1227 std::unique_ptr<RecentlyBrokenAlternativeServices>
1228 recently_broken_alternative_services) {
1229 broken_alternative_services_.SetBrokenAndRecentlyBrokenAlternativeServices(
1230 std::move(broken_alternative_service_list),
1231 std::move(recently_broken_alternative_services));
1232 }
1233
MaybeQueueWriteProperties()1234 void HttpServerProperties::MaybeQueueWriteProperties() {
1235 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
1236 if (prefs_update_timer_.IsRunning() || !properties_manager_)
1237 return;
1238
1239 if (!is_initialized_) {
1240 queue_write_on_load_ = true;
1241 return;
1242 }
1243
1244 prefs_update_timer_.Start(
1245 FROM_HERE, kUpdatePrefsDelay,
1246 base::BindOnce(&HttpServerProperties::WriteProperties,
1247 base::Unretained(this), base::OnceClosure()));
1248 }
1249
FlushWritePropertiesForTesting(base::OnceClosure callback)1250 void HttpServerProperties::FlushWritePropertiesForTesting(
1251 base::OnceClosure callback) {
1252 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
1253 if (!properties_manager_) {
1254 return;
1255 }
1256
1257 // initialising the |properties_manager_| is not a concern here. So skip
1258 // it and set |is_initalized_| to true.
1259 is_initialized_ = true;
1260 // Stop the timer if it's running, since this will write to the properties
1261 // file immediately.
1262 prefs_update_timer_.Stop();
1263 WriteProperties(std::move(callback));
1264 }
1265
WriteProperties(base::OnceClosure callback) const1266 void HttpServerProperties::WriteProperties(base::OnceClosure callback) const {
1267 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
1268 DCHECK(properties_manager_);
1269
1270 // |this| shouldn't be waiting to load properties cached to disk when this
1271 // method is invoked, since this method will overwrite any cached properties.
1272 DCHECK(is_initialized_);
1273
1274 // There shouldn't be a queued update when this is run, since this method
1275 // removes the need for any update to be queued.
1276 DCHECK(!prefs_update_timer_.IsRunning());
1277
1278 properties_manager_->WriteToPrefs(
1279 server_info_map_,
1280 base::BindRepeating(&HttpServerProperties::GetCanonicalSuffix,
1281 base::Unretained(this)),
1282 last_local_address_when_quic_worked_, quic_server_info_map_,
1283 broken_alternative_services_.broken_alternative_service_list(),
1284 broken_alternative_services_.recently_broken_alternative_services(),
1285 std::move(callback));
1286 }
1287
1288 } // namespace net
1289