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