Sort unlaunched apps on app list start page by apps grid order.
[chromium-blink-merge.git] / net / http / http_server_properties_manager.cc
blobd6bfb38cce1ecbf584ea098a4c1a40fe1f8f5ec7
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/http/http_server_properties_manager.h"
7 #include "base/bind.h"
8 #include "base/metrics/histogram.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/stl_util.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "base/values.h"
16 #include "net/base/net_util.h"
18 namespace net {
20 namespace {
22 // Time to wait before starting an update the http_server_properties_impl_ cache
23 // from preferences. Scheduling another update during this period will reset the
24 // timer.
25 const int64 kUpdateCacheDelayMs = 1000;
27 // Time to wait before starting an update the preferences from the
28 // http_server_properties_impl_ cache. Scheduling another update during this
29 // period will reset the timer.
30 const int64 kUpdatePrefsDelayMs = 5000;
32 // "version" 0 indicates, http_server_properties doesn't have "version"
33 // property.
34 const int kMissingVersion = 0;
36 // The version number of persisted http_server_properties.
37 const int kVersionNumber = 3;
39 typedef std::vector<std::string> StringVector;
41 // Persist 200 MRU AlternateProtocolHostPortPairs.
42 const int kMaxAlternateProtocolHostsToPersist = 200;
44 // Persist 200 MRU SpdySettingsHostPortPairs.
45 const int kMaxSpdySettingsHostsToPersist = 200;
47 // Persist 300 MRU SupportsSpdyServerHostPortPairs.
48 const int kMaxSupportsSpdyServerHostsToPersist = 300;
50 // Persist 200 ServerNetworkStats.
51 const int kMaxServerNetworkStatsHostsToPersist = 200;
53 const char kVersionKey[] = "version";
54 const char kServersKey[] = "servers";
55 const char kSupportsSpdyKey[] = "supports_spdy";
56 const char kSettingsKey[] = "settings";
57 const char kSupportsQuicKey[] = "supports_quic";
58 const char kUsedQuicKey[] = "used_quic";
59 const char kAddressKey[] = "address";
60 const char kAlternateProtocolKey[] = "alternate_protocol";
61 const char kPortKey[] = "port";
62 const char kProtocolKey[] = "protocol_str";
63 const char kProbabilityKey[] = "probability";
64 const char kNetworkStatsKey[] = "network_stats";
65 const char kSrttKey[] = "srtt";
67 } // namespace
69 ////////////////////////////////////////////////////////////////////////////////
70 // HttpServerPropertiesManager
72 HttpServerPropertiesManager::HttpServerPropertiesManager(
73 PrefService* pref_service,
74 const char* pref_path,
75 scoped_refptr<base::SequencedTaskRunner> network_task_runner)
76 : pref_task_runner_(base::ThreadTaskRunnerHandle::Get()),
77 pref_service_(pref_service),
78 setting_prefs_(false),
79 path_(pref_path),
80 network_task_runner_(network_task_runner) {
81 DCHECK(pref_service);
82 pref_weak_ptr_factory_.reset(
83 new base::WeakPtrFactory<HttpServerPropertiesManager>(this));
84 pref_weak_ptr_ = pref_weak_ptr_factory_->GetWeakPtr();
85 pref_cache_update_timer_.reset(
86 new base::OneShotTimer<HttpServerPropertiesManager>);
87 pref_change_registrar_.Init(pref_service_);
88 pref_change_registrar_.Add(
89 path_,
90 base::Bind(&HttpServerPropertiesManager::OnHttpServerPropertiesChanged,
91 base::Unretained(this)));
94 HttpServerPropertiesManager::~HttpServerPropertiesManager() {
95 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
96 network_weak_ptr_factory_.reset();
99 void HttpServerPropertiesManager::InitializeOnNetworkThread() {
100 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
101 network_weak_ptr_factory_.reset(
102 new base::WeakPtrFactory<HttpServerPropertiesManager>(this));
103 http_server_properties_impl_.reset(new HttpServerPropertiesImpl());
105 network_prefs_update_timer_.reset(
106 new base::OneShotTimer<HttpServerPropertiesManager>);
108 pref_task_runner_->PostTask(
109 FROM_HERE,
110 base::Bind(&HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread,
111 pref_weak_ptr_));
114 void HttpServerPropertiesManager::ShutdownOnPrefThread() {
115 DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
116 // Cancel any pending updates, and stop listening for pref change updates.
117 pref_cache_update_timer_->Stop();
118 pref_weak_ptr_factory_.reset();
119 pref_change_registrar_.RemoveAll();
122 // static
123 void HttpServerPropertiesManager::SetVersion(
124 base::DictionaryValue* http_server_properties_dict,
125 int version_number) {
126 if (version_number < 0)
127 version_number = kVersionNumber;
128 DCHECK_LE(version_number, kVersionNumber);
129 if (version_number <= kVersionNumber)
130 http_server_properties_dict->SetInteger(kVersionKey, version_number);
133 // This is required for conformance with the HttpServerProperties interface.
134 base::WeakPtr<HttpServerProperties> HttpServerPropertiesManager::GetWeakPtr() {
135 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
136 return network_weak_ptr_factory_->GetWeakPtr();
139 void HttpServerPropertiesManager::Clear() {
140 Clear(base::Closure());
143 void HttpServerPropertiesManager::Clear(const base::Closure& completion) {
144 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
146 http_server_properties_impl_->Clear();
147 UpdatePrefsFromCacheOnNetworkThread(completion);
150 bool HttpServerPropertiesManager::SupportsRequestPriority(
151 const HostPortPair& server) {
152 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
153 return http_server_properties_impl_->SupportsRequestPriority(server);
156 void HttpServerPropertiesManager::SetSupportsSpdy(const HostPortPair& server,
157 bool support_spdy) {
158 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
160 http_server_properties_impl_->SetSupportsSpdy(server, support_spdy);
161 ScheduleUpdatePrefsOnNetworkThread();
164 bool HttpServerPropertiesManager::RequiresHTTP11(const HostPortPair& server) {
165 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
166 return http_server_properties_impl_->RequiresHTTP11(server);
169 void HttpServerPropertiesManager::SetHTTP11Required(
170 const HostPortPair& server) {
171 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
173 http_server_properties_impl_->SetHTTP11Required(server);
174 ScheduleUpdatePrefsOnNetworkThread();
177 void HttpServerPropertiesManager::MaybeForceHTTP11(const HostPortPair& server,
178 SSLConfig* ssl_config) {
179 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
180 http_server_properties_impl_->MaybeForceHTTP11(server, ssl_config);
183 AlternateProtocolInfo HttpServerPropertiesManager::GetAlternateProtocol(
184 const HostPortPair& server) {
185 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
186 return http_server_properties_impl_->GetAlternateProtocol(server);
189 void HttpServerPropertiesManager::SetAlternateProtocol(
190 const HostPortPair& server,
191 uint16 alternate_port,
192 AlternateProtocol alternate_protocol,
193 double alternate_probability) {
194 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
195 http_server_properties_impl_->SetAlternateProtocol(
196 server, alternate_port, alternate_protocol, alternate_probability);
197 ScheduleUpdatePrefsOnNetworkThread();
200 void HttpServerPropertiesManager::SetBrokenAlternateProtocol(
201 const HostPortPair& server) {
202 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
203 http_server_properties_impl_->SetBrokenAlternateProtocol(server);
204 ScheduleUpdatePrefsOnNetworkThread();
207 bool HttpServerPropertiesManager::WasAlternateProtocolRecentlyBroken(
208 const HostPortPair& server) {
209 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
210 return http_server_properties_impl_->WasAlternateProtocolRecentlyBroken(
211 server);
214 void HttpServerPropertiesManager::ConfirmAlternateProtocol(
215 const HostPortPair& server) {
216 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
217 http_server_properties_impl_->ConfirmAlternateProtocol(server);
218 ScheduleUpdatePrefsOnNetworkThread();
221 void HttpServerPropertiesManager::ClearAlternateProtocol(
222 const HostPortPair& server) {
223 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
224 http_server_properties_impl_->ClearAlternateProtocol(server);
225 ScheduleUpdatePrefsOnNetworkThread();
228 const AlternateProtocolMap&
229 HttpServerPropertiesManager::alternate_protocol_map() const {
230 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
231 return http_server_properties_impl_->alternate_protocol_map();
234 void HttpServerPropertiesManager::SetAlternateProtocolProbabilityThreshold(
235 double threshold) {
236 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
237 http_server_properties_impl_->SetAlternateProtocolProbabilityThreshold(
238 threshold);
241 const SettingsMap& HttpServerPropertiesManager::GetSpdySettings(
242 const HostPortPair& host_port_pair) {
243 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
244 return http_server_properties_impl_->GetSpdySettings(host_port_pair);
247 bool HttpServerPropertiesManager::SetSpdySetting(
248 const HostPortPair& host_port_pair,
249 SpdySettingsIds id,
250 SpdySettingsFlags flags,
251 uint32 value) {
252 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
253 bool persist = http_server_properties_impl_->SetSpdySetting(
254 host_port_pair, id, flags, value);
255 if (persist)
256 ScheduleUpdatePrefsOnNetworkThread();
257 return persist;
260 void HttpServerPropertiesManager::ClearSpdySettings(
261 const HostPortPair& host_port_pair) {
262 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
263 http_server_properties_impl_->ClearSpdySettings(host_port_pair);
264 ScheduleUpdatePrefsOnNetworkThread();
267 void HttpServerPropertiesManager::ClearAllSpdySettings() {
268 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
269 http_server_properties_impl_->ClearAllSpdySettings();
270 ScheduleUpdatePrefsOnNetworkThread();
273 const SpdySettingsMap& HttpServerPropertiesManager::spdy_settings_map()
274 const {
275 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
276 return http_server_properties_impl_->spdy_settings_map();
279 bool HttpServerPropertiesManager::GetSupportsQuic(
280 IPAddressNumber* last_address) const {
281 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
282 return http_server_properties_impl_->GetSupportsQuic(last_address);
285 void HttpServerPropertiesManager::SetSupportsQuic(
286 bool used_quic,
287 const IPAddressNumber& address) {
288 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
289 http_server_properties_impl_->SetSupportsQuic(used_quic, address);
290 ScheduleUpdatePrefsOnNetworkThread();
293 void HttpServerPropertiesManager::SetServerNetworkStats(
294 const HostPortPair& host_port_pair,
295 ServerNetworkStats stats) {
296 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
297 http_server_properties_impl_->SetServerNetworkStats(host_port_pair, stats);
298 ScheduleUpdatePrefsOnNetworkThread();
301 const ServerNetworkStats* HttpServerPropertiesManager::GetServerNetworkStats(
302 const HostPortPair& host_port_pair) {
303 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
304 return http_server_properties_impl_->GetServerNetworkStats(host_port_pair);
307 const ServerNetworkStatsMap&
308 HttpServerPropertiesManager::server_network_stats_map() const {
309 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
310 return http_server_properties_impl_->server_network_stats_map();
314 // Update the HttpServerPropertiesImpl's cache with data from preferences.
316 void HttpServerPropertiesManager::ScheduleUpdateCacheOnPrefThread() {
317 DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
318 // Cancel pending updates, if any.
319 pref_cache_update_timer_->Stop();
320 StartCacheUpdateTimerOnPrefThread(
321 base::TimeDelta::FromMilliseconds(kUpdateCacheDelayMs));
324 void HttpServerPropertiesManager::StartCacheUpdateTimerOnPrefThread(
325 base::TimeDelta delay) {
326 DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
327 pref_cache_update_timer_->Start(
328 FROM_HERE,
329 delay,
330 this,
331 &HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread);
334 void HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread() {
335 // The preferences can only be read on the pref thread.
336 DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
338 if (!pref_service_->HasPrefPath(path_))
339 return;
341 bool detected_corrupted_prefs = false;
342 const base::DictionaryValue& http_server_properties_dict =
343 *pref_service_->GetDictionary(path_);
345 int version = kMissingVersion;
346 if (!http_server_properties_dict.GetIntegerWithoutPathExpansion(kVersionKey,
347 &version)) {
348 DVLOG(1) << "Missing version. Clearing all properties.";
349 return;
352 // The properties for a given server is in
353 // http_server_properties_dict["servers"][server].
354 const base::DictionaryValue* servers_dict = NULL;
355 if (!http_server_properties_dict.GetDictionaryWithoutPathExpansion(
356 kServersKey, &servers_dict)) {
357 DVLOG(1) << "Malformed http_server_properties for servers.";
358 return;
361 IPAddressNumber* addr = new IPAddressNumber;
362 ReadSupportsQuic(http_server_properties_dict, addr);
364 // String is host/port pair of spdy server.
365 scoped_ptr<StringVector> spdy_servers(new StringVector);
366 scoped_ptr<SpdySettingsMap> spdy_settings_map(
367 new SpdySettingsMap(kMaxSpdySettingsHostsToPersist));
368 scoped_ptr<AlternateProtocolMap> alternate_protocol_map(
369 new AlternateProtocolMap(kMaxAlternateProtocolHostsToPersist));
370 scoped_ptr<ServerNetworkStatsMap> server_network_stats_map(
371 new ServerNetworkStatsMap(kMaxServerNetworkStatsHostsToPersist));
373 for (base::DictionaryValue::Iterator it(*servers_dict); !it.IsAtEnd();
374 it.Advance()) {
375 // Get server's host/pair.
376 const std::string& server_str = it.key();
377 HostPortPair server = HostPortPair::FromString(server_str);
378 if (server.host().empty()) {
379 DVLOG(1) << "Malformed http_server_properties for server: " << server_str;
380 detected_corrupted_prefs = true;
381 continue;
384 const base::DictionaryValue* server_pref_dict = NULL;
385 if (!it.value().GetAsDictionary(&server_pref_dict)) {
386 DVLOG(1) << "Malformed http_server_properties server: " << server_str;
387 detected_corrupted_prefs = true;
388 continue;
391 // Get if server supports Spdy.
392 bool supports_spdy = false;
393 if ((server_pref_dict->GetBoolean(kSupportsSpdyKey, &supports_spdy)) &&
394 supports_spdy) {
395 spdy_servers->push_back(server_str);
398 AddToSpdySettingsMap(server, *server_pref_dict, spdy_settings_map.get());
399 if (!AddToAlternateProtocolMap(server, *server_pref_dict,
400 alternate_protocol_map.get()) ||
401 !AddToNetworkStatsMap(server, *server_pref_dict,
402 server_network_stats_map.get())) {
403 detected_corrupted_prefs = true;
407 network_task_runner_->PostTask(
408 FROM_HERE,
409 base::Bind(
410 &HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread,
411 base::Unretained(this), base::Owned(spdy_servers.release()),
412 base::Owned(spdy_settings_map.release()),
413 base::Owned(alternate_protocol_map.release()), base::Owned(addr),
414 base::Owned(server_network_stats_map.release()),
415 detected_corrupted_prefs));
418 void HttpServerPropertiesManager::AddToSpdySettingsMap(
419 const HostPortPair& server,
420 const base::DictionaryValue& server_pref_dict,
421 SpdySettingsMap* spdy_settings_map) {
422 // Get SpdySettings.
423 DCHECK(spdy_settings_map->Peek(server) == spdy_settings_map->end());
424 const base::DictionaryValue* spdy_settings_dict = NULL;
425 if (!server_pref_dict.GetDictionaryWithoutPathExpansion(
426 kSettingsKey, &spdy_settings_dict)) {
427 return;
429 SettingsMap settings_map;
430 for (base::DictionaryValue::Iterator dict_it(*spdy_settings_dict);
431 !dict_it.IsAtEnd(); dict_it.Advance()) {
432 const std::string& id_str = dict_it.key();
433 int id = 0;
434 if (!base::StringToInt(id_str, &id)) {
435 DVLOG(1) << "Malformed id in SpdySettings for server: "
436 << server.ToString();
437 NOTREACHED();
438 continue;
440 int value = 0;
441 if (!dict_it.value().GetAsInteger(&value)) {
442 DVLOG(1) << "Malformed value in SpdySettings for server: "
443 << server.ToString();
444 NOTREACHED();
445 continue;
447 SettingsFlagsAndValue flags_and_value(SETTINGS_FLAG_PERSISTED, value);
448 settings_map[static_cast<SpdySettingsIds>(id)] = flags_and_value;
450 spdy_settings_map->Put(server, settings_map);
453 AlternateProtocolInfo HttpServerPropertiesManager::ParseAlternateProtocolDict(
454 const base::DictionaryValue& alternate_protocol_dict,
455 const std::string& server_str) {
456 AlternateProtocolInfo alternate_protocol;
457 int port = 0;
458 if (!alternate_protocol_dict.GetInteger(kPortKey, &port) ||
459 !IsPortValid(port)) {
460 DVLOG(1) << "Malformed AltSvc port for server: " << server_str;
461 return alternate_protocol;
463 alternate_protocol.port = static_cast<uint16>(port);
465 double probability = 1.0;
466 if (alternate_protocol_dict.HasKey(kProbabilityKey) &&
467 !alternate_protocol_dict.GetDoubleWithoutPathExpansion(kProbabilityKey,
468 &probability)) {
469 DVLOG(1) << "Malformed AltSvc probability for server: " << server_str;
470 return alternate_protocol;
472 alternate_protocol.probability = probability;
474 std::string protocol_str;
475 if (!alternate_protocol_dict.GetStringWithoutPathExpansion(kProtocolKey,
476 &protocol_str)) {
477 DVLOG(1) << "Malformed AltSvc protocol string for server: " << server_str;
478 return alternate_protocol;
480 AlternateProtocol protocol = AlternateProtocolFromString(protocol_str);
481 if (!IsAlternateProtocolValid(protocol)) {
482 DVLOG(1) << "Invalid AltSvc protocol string for server: " << server_str;
483 return alternate_protocol;
485 alternate_protocol.protocol = protocol;
487 return alternate_protocol;
490 bool HttpServerPropertiesManager::AddToAlternateProtocolMap(
491 const HostPortPair& server,
492 const base::DictionaryValue& server_pref_dict,
493 AlternateProtocolMap* alternate_protocol_map) {
494 // Get alternate_protocol server.
495 DCHECK(alternate_protocol_map->Peek(server) == alternate_protocol_map->end());
496 const base::DictionaryValue* alternate_protocol_dict = NULL;
497 if (!server_pref_dict.GetDictionaryWithoutPathExpansion(
498 kAlternateProtocolKey, &alternate_protocol_dict)) {
499 return true;
501 AlternateProtocolInfo alternate_protocol =
502 ParseAlternateProtocolDict(*alternate_protocol_dict, server.ToString());
503 if (alternate_protocol.protocol == UNINITIALIZED_ALTERNATE_PROTOCOL)
504 return false;
505 alternate_protocol_map->Put(server, alternate_protocol);
506 return true;
509 bool HttpServerPropertiesManager::ReadSupportsQuic(
510 const base::DictionaryValue& http_server_properties_dict,
511 IPAddressNumber* last_quic_address) {
512 const base::DictionaryValue* supports_quic_dict = NULL;
513 if (!http_server_properties_dict.GetDictionaryWithoutPathExpansion(
514 kSupportsQuicKey, &supports_quic_dict)) {
515 return true;
517 bool used_quic = false;
518 if (!supports_quic_dict->GetBooleanWithoutPathExpansion(kUsedQuicKey,
519 &used_quic)) {
520 DVLOG(1) << "Malformed SupportsQuic";
521 return false;
523 if (!used_quic)
524 return false;
526 std::string address;
527 if (!supports_quic_dict->GetStringWithoutPathExpansion(kAddressKey,
528 &address) ||
529 !ParseIPLiteralToNumber(address, last_quic_address)) {
530 DVLOG(1) << "Malformed SupportsQuic";
531 return false;
533 return true;
536 bool HttpServerPropertiesManager::AddToNetworkStatsMap(
537 const HostPortPair& server,
538 const base::DictionaryValue& server_pref_dict,
539 ServerNetworkStatsMap* network_stats_map) {
540 DCHECK(network_stats_map->Peek(server) == network_stats_map->end());
541 const base::DictionaryValue* server_network_stats_dict = NULL;
542 if (!server_pref_dict.GetDictionaryWithoutPathExpansion(
543 kNetworkStatsKey, &server_network_stats_dict)) {
544 return true;
546 int srtt;
547 if (!server_network_stats_dict->GetIntegerWithoutPathExpansion(kSrttKey,
548 &srtt)) {
549 DVLOG(1) << "Malformed ServerNetworkStats for server: "
550 << server.ToString();
551 return false;
553 ServerNetworkStats server_network_stats;
554 server_network_stats.srtt = base::TimeDelta::FromInternalValue(srtt);
555 // TODO(rtenneti): When QUIC starts using bandwidth_estimate, then persist
556 // bandwidth_estimate.
557 network_stats_map->Put(server, server_network_stats);
558 return true;
561 void HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread(
562 StringVector* spdy_servers,
563 SpdySettingsMap* spdy_settings_map,
564 AlternateProtocolMap* alternate_protocol_map,
565 IPAddressNumber* last_quic_address,
566 ServerNetworkStatsMap* server_network_stats_map,
567 bool detected_corrupted_prefs) {
568 // Preferences have the master data because admins might have pushed new
569 // preferences. Update the cached data with new data from preferences.
570 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
572 UMA_HISTOGRAM_COUNTS("Net.CountOfSpdyServers", spdy_servers->size());
573 http_server_properties_impl_->InitializeSpdyServers(spdy_servers, true);
575 // Update the cached data and use the new spdy_settings from preferences.
576 UMA_HISTOGRAM_COUNTS("Net.CountOfSpdySettings", spdy_settings_map->size());
577 http_server_properties_impl_->InitializeSpdySettingsServers(
578 spdy_settings_map);
580 // Update the cached data and use the new Alternate-Protocol server list from
581 // preferences.
582 UMA_HISTOGRAM_COUNTS("Net.CountOfAlternateProtocolServers",
583 alternate_protocol_map->size());
584 http_server_properties_impl_->InitializeAlternateProtocolServers(
585 alternate_protocol_map);
587 http_server_properties_impl_->InitializeSupportsQuic(last_quic_address);
589 http_server_properties_impl_->InitializeServerNetworkStats(
590 server_network_stats_map);
592 // Update the prefs with what we have read (delete all corrupted prefs).
593 if (detected_corrupted_prefs)
594 ScheduleUpdatePrefsOnNetworkThread();
598 // Update Preferences with data from the cached data.
600 void HttpServerPropertiesManager::ScheduleUpdatePrefsOnNetworkThread() {
601 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
602 // Cancel pending updates, if any.
603 network_prefs_update_timer_->Stop();
604 StartPrefsUpdateTimerOnNetworkThread(
605 base::TimeDelta::FromMilliseconds(kUpdatePrefsDelayMs));
608 void HttpServerPropertiesManager::StartPrefsUpdateTimerOnNetworkThread(
609 base::TimeDelta delay) {
610 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
611 // This is overridden in tests to post the task without the delay.
612 network_prefs_update_timer_->Start(
613 FROM_HERE,
614 delay,
615 this,
616 &HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread);
619 // This is required so we can set this as the callback for a timer.
620 void HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread() {
621 UpdatePrefsFromCacheOnNetworkThread(base::Closure());
624 void HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread(
625 const base::Closure& completion) {
626 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
628 base::ListValue* spdy_server_list = new base::ListValue;
629 http_server_properties_impl_->GetSpdyServerList(
630 spdy_server_list, kMaxSupportsSpdyServerHostsToPersist);
632 SpdySettingsMap* spdy_settings_map =
633 new SpdySettingsMap(kMaxSpdySettingsHostsToPersist);
634 const SpdySettingsMap& main_map =
635 http_server_properties_impl_->spdy_settings_map();
636 int count = 0;
637 for (SpdySettingsMap::const_iterator it = main_map.begin();
638 it != main_map.end() && count < kMaxSpdySettingsHostsToPersist;
639 ++it, ++count) {
640 spdy_settings_map->Put(it->first, it->second);
643 AlternateProtocolMap* alternate_protocol_map =
644 new AlternateProtocolMap(kMaxAlternateProtocolHostsToPersist);
645 const AlternateProtocolMap& map =
646 http_server_properties_impl_->alternate_protocol_map();
647 count = 0;
648 typedef std::map<std::string, bool> CanonicalHostPersistedMap;
649 CanonicalHostPersistedMap persisted_map;
650 for (AlternateProtocolMap::const_iterator it = map.begin();
651 it != map.end() && count < kMaxAlternateProtocolHostsToPersist; ++it) {
652 const HostPortPair& server = it->first;
653 std::string canonical_suffix =
654 http_server_properties_impl_->GetCanonicalSuffix(server.host());
655 if (!canonical_suffix.empty()) {
656 if (persisted_map.find(canonical_suffix) != persisted_map.end())
657 continue;
658 persisted_map[canonical_suffix] = true;
660 alternate_protocol_map->Put(server, it->second);
661 ++count;
664 ServerNetworkStatsMap* server_network_stats_map =
665 new ServerNetworkStatsMap(kMaxServerNetworkStatsHostsToPersist);
666 const ServerNetworkStatsMap& main_server_network_stats_map =
667 http_server_properties_impl_->server_network_stats_map();
668 for (ServerNetworkStatsMap::const_iterator it =
669 main_server_network_stats_map.begin();
670 it != main_server_network_stats_map.end(); ++it) {
671 server_network_stats_map->Put(it->first, it->second);
674 IPAddressNumber* last_quic_addr = new IPAddressNumber;
675 http_server_properties_impl_->GetSupportsQuic(last_quic_addr);
676 // Update the preferences on the pref thread.
677 pref_task_runner_->PostTask(
678 FROM_HERE,
679 base::Bind(
680 &HttpServerPropertiesManager::UpdatePrefsOnPrefThread, pref_weak_ptr_,
681 base::Owned(spdy_server_list), base::Owned(spdy_settings_map),
682 base::Owned(alternate_protocol_map), base::Owned(last_quic_addr),
683 base::Owned(server_network_stats_map), completion));
686 // A local or temporary data structure to hold |supports_spdy|, SpdySettings,
687 // AlternateProtocolInfo and SupportsQuic preferences for a server. This is used
688 // only in UpdatePrefsOnPrefThread.
689 struct ServerPref {
690 ServerPref()
691 : supports_spdy(false),
692 settings_map(NULL),
693 alternate_protocol(NULL),
694 supports_quic(NULL),
695 server_network_stats(NULL) {}
696 ServerPref(bool supports_spdy,
697 const SettingsMap* settings_map,
698 const AlternateProtocolInfo* alternate_protocol,
699 const SupportsQuic* supports_quic,
700 const ServerNetworkStats* server_network_stats)
701 : supports_spdy(supports_spdy),
702 settings_map(settings_map),
703 alternate_protocol(alternate_protocol),
704 supports_quic(supports_quic),
705 server_network_stats(server_network_stats) {}
706 bool supports_spdy;
707 const SettingsMap* settings_map;
708 const AlternateProtocolInfo* alternate_protocol;
709 const SupportsQuic* supports_quic;
710 const ServerNetworkStats* server_network_stats;
713 void HttpServerPropertiesManager::UpdatePrefsOnPrefThread(
714 base::ListValue* spdy_server_list,
715 SpdySettingsMap* spdy_settings_map,
716 AlternateProtocolMap* alternate_protocol_map,
717 IPAddressNumber* last_quic_address,
718 ServerNetworkStatsMap* server_network_stats_map,
719 const base::Closure& completion) {
720 typedef std::map<HostPortPair, ServerPref> ServerPrefMap;
721 ServerPrefMap server_pref_map;
723 DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
725 // Add servers that support spdy to server_pref_map.
726 std::string s;
727 for (base::ListValue::const_iterator list_it = spdy_server_list->begin();
728 list_it != spdy_server_list->end();
729 ++list_it) {
730 if ((*list_it)->GetAsString(&s)) {
731 HostPortPair server = HostPortPair::FromString(s);
732 server_pref_map[server].supports_spdy = true;
736 // Add servers that have SpdySettings to server_pref_map.
737 for (SpdySettingsMap::iterator map_it = spdy_settings_map->begin();
738 map_it != spdy_settings_map->end(); ++map_it) {
739 const HostPortPair& server = map_it->first;
740 server_pref_map[server].settings_map = &map_it->second;
743 // Add AlternateProtocol servers to server_pref_map.
744 for (AlternateProtocolMap::const_iterator map_it =
745 alternate_protocol_map->begin();
746 map_it != alternate_protocol_map->end(); ++map_it) {
747 const HostPortPair& server = map_it->first;
748 const AlternateProtocolInfo& port_alternate_protocol = map_it->second;
749 if (!IsAlternateProtocolValid(port_alternate_protocol.protocol)) {
750 continue;
752 server_pref_map[server].alternate_protocol = &map_it->second;
755 // Add ServerNetworkStats servers to server_pref_map.
756 for (ServerNetworkStatsMap::const_iterator map_it =
757 server_network_stats_map->begin();
758 map_it != server_network_stats_map->end(); ++map_it) {
759 const HostPortPair& server = map_it->first;
760 server_pref_map[server].server_network_stats = &map_it->second;
763 // Persist properties to the |path_|.
764 base::DictionaryValue http_server_properties_dict;
765 base::DictionaryValue* servers_dict = new base::DictionaryValue;
766 for (ServerPrefMap::const_iterator map_it = server_pref_map.begin();
767 map_it != server_pref_map.end();
768 ++map_it) {
769 const HostPortPair& server = map_it->first;
770 const ServerPref& server_pref = map_it->second;
772 base::DictionaryValue* server_pref_dict = new base::DictionaryValue;
774 // Save supports_spdy.
775 if (server_pref.supports_spdy)
776 server_pref_dict->SetBoolean(kSupportsSpdyKey, server_pref.supports_spdy);
777 SaveSpdySettingsToServerPrefs(server_pref.settings_map, server_pref_dict);
778 SaveAlternateProtocolToServerPrefs(server_pref.alternate_protocol,
779 server_pref_dict);
780 SaveNetworkStatsToServerPrefs(server_pref.server_network_stats,
781 server_pref_dict);
783 servers_dict->SetWithoutPathExpansion(server.ToString(), server_pref_dict);
786 http_server_properties_dict.SetWithoutPathExpansion(kServersKey,
787 servers_dict);
788 SetVersion(&http_server_properties_dict, kVersionNumber);
790 SaveSupportsQuicToPrefs(last_quic_address, &http_server_properties_dict);
792 setting_prefs_ = true;
793 pref_service_->Set(path_, http_server_properties_dict);
794 setting_prefs_ = false;
796 // Note that |completion| will be fired after we have written everything to
797 // the Preferences, but likely before these changes are serialized to disk.
798 // This is not a problem though, as JSONPrefStore guarantees that this will
799 // happen, pretty soon, and even in the case we shut down immediately.
800 if (!completion.is_null())
801 completion.Run();
804 void HttpServerPropertiesManager::SaveSpdySettingsToServerPrefs(
805 const SettingsMap* settings_map,
806 base::DictionaryValue* server_pref_dict) {
807 if (!settings_map) {
808 return;
810 base::DictionaryValue* spdy_settings_dict = new base::DictionaryValue;
811 for (SettingsMap::const_iterator it = settings_map->begin();
812 it != settings_map->end(); ++it) {
813 SpdySettingsIds id = it->first;
814 uint32 value = it->second.second;
815 std::string key = base::StringPrintf("%u", id);
816 spdy_settings_dict->SetInteger(key, value);
818 server_pref_dict->SetWithoutPathExpansion(kSettingsKey, spdy_settings_dict);
821 void HttpServerPropertiesManager::SaveAlternateProtocolToServerPrefs(
822 const AlternateProtocolInfo* port_alternate_protocol,
823 base::DictionaryValue* server_pref_dict) {
824 if (!port_alternate_protocol || port_alternate_protocol->is_broken)
825 return;
827 base::DictionaryValue* port_alternate_protocol_dict =
828 new base::DictionaryValue;
829 port_alternate_protocol_dict->SetInteger(kPortKey,
830 port_alternate_protocol->port);
831 const char* protocol_str =
832 AlternateProtocolToString(port_alternate_protocol->protocol);
833 port_alternate_protocol_dict->SetString(kProtocolKey, protocol_str);
834 port_alternate_protocol_dict->SetDouble(kProbabilityKey,
835 port_alternate_protocol->probability);
836 server_pref_dict->SetWithoutPathExpansion(kAlternateProtocolKey,
837 port_alternate_protocol_dict);
840 void HttpServerPropertiesManager::SaveSupportsQuicToPrefs(
841 const IPAddressNumber* last_quic_address,
842 base::DictionaryValue* http_server_properties_dict) {
843 if (!last_quic_address || last_quic_address->empty())
844 return;
846 base::DictionaryValue* supports_quic_dict = new base::DictionaryValue;
847 supports_quic_dict->SetBoolean(kUsedQuicKey, true);
848 supports_quic_dict->SetString(kAddressKey,
849 IPAddressToString(*last_quic_address));
850 http_server_properties_dict->SetWithoutPathExpansion(kSupportsQuicKey,
851 supports_quic_dict);
854 void HttpServerPropertiesManager::SaveNetworkStatsToServerPrefs(
855 const ServerNetworkStats* server_network_stats,
856 base::DictionaryValue* server_pref_dict) {
857 if (!server_network_stats)
858 return;
860 base::DictionaryValue* server_network_stats_dict = new base::DictionaryValue;
861 // Becasue JSON doesn't support int64, persist int64 as a string.
862 server_network_stats_dict->SetInteger(
863 kSrttKey, static_cast<int>(server_network_stats->srtt.ToInternalValue()));
864 // TODO(rtenneti): When QUIC starts using bandwidth_estimate, then persist
865 // bandwidth_estimate.
866 server_pref_dict->SetWithoutPathExpansion(kNetworkStatsKey,
867 server_network_stats_dict);
870 void HttpServerPropertiesManager::OnHttpServerPropertiesChanged() {
871 DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
872 if (!setting_prefs_)
873 ScheduleUpdateCacheOnPrefThread();
876 } // namespace net