Delete chrome.mediaGalleriesPrivate because the functionality unique to it has since...
[chromium-blink-merge.git] / net / http / http_server_properties_manager.cc
blob873c8ca700faae8a9b1b39de9e47877d9000828b
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 } // namespace
55 ////////////////////////////////////////////////////////////////////////////////
56 // HttpServerPropertiesManager
58 HttpServerPropertiesManager::HttpServerPropertiesManager(
59 PrefService* pref_service,
60 const char* pref_path,
61 scoped_refptr<base::SequencedTaskRunner> network_task_runner)
62 : pref_task_runner_(base::ThreadTaskRunnerHandle::Get()),
63 pref_service_(pref_service),
64 setting_prefs_(false),
65 path_(pref_path),
66 network_task_runner_(network_task_runner) {
67 DCHECK(pref_service);
68 pref_weak_ptr_factory_.reset(
69 new base::WeakPtrFactory<HttpServerPropertiesManager>(this));
70 pref_weak_ptr_ = pref_weak_ptr_factory_->GetWeakPtr();
71 pref_cache_update_timer_.reset(
72 new base::OneShotTimer<HttpServerPropertiesManager>);
73 pref_change_registrar_.Init(pref_service_);
74 pref_change_registrar_.Add(
75 path_,
76 base::Bind(&HttpServerPropertiesManager::OnHttpServerPropertiesChanged,
77 base::Unretained(this)));
80 HttpServerPropertiesManager::~HttpServerPropertiesManager() {
81 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
82 network_weak_ptr_factory_.reset();
85 void HttpServerPropertiesManager::InitializeOnNetworkThread() {
86 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
87 network_weak_ptr_factory_.reset(
88 new base::WeakPtrFactory<HttpServerPropertiesManager>(this));
89 http_server_properties_impl_.reset(new HttpServerPropertiesImpl());
91 network_prefs_update_timer_.reset(
92 new base::OneShotTimer<HttpServerPropertiesManager>);
94 pref_task_runner_->PostTask(
95 FROM_HERE,
96 base::Bind(&HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread,
97 pref_weak_ptr_));
100 void HttpServerPropertiesManager::ShutdownOnPrefThread() {
101 DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
102 // Cancel any pending updates, and stop listening for pref change updates.
103 pref_cache_update_timer_->Stop();
104 pref_weak_ptr_factory_.reset();
105 pref_change_registrar_.RemoveAll();
108 // static
109 void HttpServerPropertiesManager::SetVersion(
110 base::DictionaryValue* http_server_properties_dict,
111 int version_number) {
112 if (version_number < 0)
113 version_number = kVersionNumber;
114 DCHECK_LE(version_number, kVersionNumber);
115 if (version_number <= kVersionNumber)
116 http_server_properties_dict->SetInteger("version", version_number);
119 // This is required for conformance with the HttpServerProperties interface.
120 base::WeakPtr<HttpServerProperties> HttpServerPropertiesManager::GetWeakPtr() {
121 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
122 return network_weak_ptr_factory_->GetWeakPtr();
125 void HttpServerPropertiesManager::Clear() {
126 Clear(base::Closure());
129 void HttpServerPropertiesManager::Clear(const base::Closure& completion) {
130 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
132 http_server_properties_impl_->Clear();
133 UpdatePrefsFromCacheOnNetworkThread(completion);
136 bool HttpServerPropertiesManager::SupportsSpdy(const HostPortPair& server) {
137 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
138 return http_server_properties_impl_->SupportsSpdy(server);
141 void HttpServerPropertiesManager::SetSupportsSpdy(const HostPortPair& server,
142 bool support_spdy) {
143 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
145 http_server_properties_impl_->SetSupportsSpdy(server, support_spdy);
146 ScheduleUpdatePrefsOnNetworkThread();
149 bool HttpServerPropertiesManager::RequiresHTTP11(
150 const net::HostPortPair& server) {
151 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
152 return http_server_properties_impl_->RequiresHTTP11(server);
155 void HttpServerPropertiesManager::SetHTTP11Required(
156 const net::HostPortPair& server) {
157 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
159 http_server_properties_impl_->SetHTTP11Required(server);
160 ScheduleUpdatePrefsOnNetworkThread();
163 void HttpServerPropertiesManager::MaybeForceHTTP11(const HostPortPair& server,
164 SSLConfig* ssl_config) {
165 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
166 http_server_properties_impl_->MaybeForceHTTP11(server, ssl_config);
169 bool HttpServerPropertiesManager::HasAlternateProtocol(
170 const HostPortPair& server) {
171 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
172 return http_server_properties_impl_->HasAlternateProtocol(server);
175 AlternateProtocolInfo HttpServerPropertiesManager::GetAlternateProtocol(
176 const HostPortPair& server) {
177 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
178 return http_server_properties_impl_->GetAlternateProtocol(server);
181 void HttpServerPropertiesManager::SetAlternateProtocol(
182 const HostPortPair& server,
183 uint16 alternate_port,
184 AlternateProtocol alternate_protocol,
185 double alternate_probability) {
186 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
187 http_server_properties_impl_->SetAlternateProtocol(
188 server, alternate_port, alternate_protocol, alternate_probability);
189 ScheduleUpdatePrefsOnNetworkThread();
192 void HttpServerPropertiesManager::SetBrokenAlternateProtocol(
193 const HostPortPair& server) {
194 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
195 http_server_properties_impl_->SetBrokenAlternateProtocol(server);
196 ScheduleUpdatePrefsOnNetworkThread();
199 bool HttpServerPropertiesManager::WasAlternateProtocolRecentlyBroken(
200 const HostPortPair& server) {
201 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
202 return http_server_properties_impl_->WasAlternateProtocolRecentlyBroken(
203 server);
206 void HttpServerPropertiesManager::ConfirmAlternateProtocol(
207 const HostPortPair& server) {
208 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
209 http_server_properties_impl_->ConfirmAlternateProtocol(server);
210 ScheduleUpdatePrefsOnNetworkThread();
213 void HttpServerPropertiesManager::ClearAlternateProtocol(
214 const HostPortPair& server) {
215 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
216 http_server_properties_impl_->ClearAlternateProtocol(server);
217 ScheduleUpdatePrefsOnNetworkThread();
220 const AlternateProtocolMap&
221 HttpServerPropertiesManager::alternate_protocol_map() const {
222 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
223 return http_server_properties_impl_->alternate_protocol_map();
226 void HttpServerPropertiesManager::SetAlternateProtocolProbabilityThreshold(
227 double threshold) {
228 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
229 http_server_properties_impl_->SetAlternateProtocolProbabilityThreshold(
230 threshold);
233 const SettingsMap& HttpServerPropertiesManager::GetSpdySettings(
234 const HostPortPair& host_port_pair) {
235 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
236 return http_server_properties_impl_->GetSpdySettings(host_port_pair);
239 bool HttpServerPropertiesManager::SetSpdySetting(
240 const HostPortPair& host_port_pair,
241 SpdySettingsIds id,
242 SpdySettingsFlags flags,
243 uint32 value) {
244 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
245 bool persist = http_server_properties_impl_->SetSpdySetting(
246 host_port_pair, id, flags, value);
247 if (persist)
248 ScheduleUpdatePrefsOnNetworkThread();
249 return persist;
252 void HttpServerPropertiesManager::ClearSpdySettings(
253 const HostPortPair& host_port_pair) {
254 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
255 http_server_properties_impl_->ClearSpdySettings(host_port_pair);
256 ScheduleUpdatePrefsOnNetworkThread();
259 void HttpServerPropertiesManager::ClearAllSpdySettings() {
260 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
261 http_server_properties_impl_->ClearAllSpdySettings();
262 ScheduleUpdatePrefsOnNetworkThread();
265 const SpdySettingsMap& HttpServerPropertiesManager::spdy_settings_map()
266 const {
267 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
268 return http_server_properties_impl_->spdy_settings_map();
271 SupportsQuic HttpServerPropertiesManager::GetSupportsQuic(
272 const HostPortPair& host_port_pair) const {
273 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
274 return http_server_properties_impl_->GetSupportsQuic(host_port_pair);
277 void HttpServerPropertiesManager::SetSupportsQuic(
278 const HostPortPair& host_port_pair,
279 bool used_quic,
280 const std::string& address) {
281 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
282 http_server_properties_impl_->SetSupportsQuic(
283 host_port_pair, used_quic, address);
284 ScheduleUpdatePrefsOnNetworkThread();
287 const SupportsQuicMap& HttpServerPropertiesManager::supports_quic_map()
288 const {
289 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
290 return http_server_properties_impl_->supports_quic_map();
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("version",
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 "servers", &servers_dict)) {
357 DVLOG(1) << "Malformed http_server_properties for servers.";
358 return;
361 // String is host/port pair of spdy server.
362 scoped_ptr<StringVector> spdy_servers(new StringVector);
363 scoped_ptr<SpdySettingsMap> spdy_settings_map(
364 new SpdySettingsMap(kMaxSpdySettingsHostsToPersist));
365 scoped_ptr<AlternateProtocolMap> alternate_protocol_map(
366 new AlternateProtocolMap(kMaxAlternateProtocolHostsToPersist));
367 scoped_ptr<SupportsQuicMap> supports_quic_map(new SupportsQuicMap());
368 scoped_ptr<ServerNetworkStatsMap> server_network_stats_map(
369 new ServerNetworkStatsMap(kMaxServerNetworkStatsHostsToPersist));
371 for (base::DictionaryValue::Iterator it(*servers_dict); !it.IsAtEnd();
372 it.Advance()) {
373 // Get server's host/pair.
374 const std::string& server_str = it.key();
375 HostPortPair server = HostPortPair::FromString(server_str);
376 if (server.host().empty()) {
377 DVLOG(1) << "Malformed http_server_properties for server: " << server_str;
378 detected_corrupted_prefs = true;
379 continue;
382 const base::DictionaryValue* server_pref_dict = NULL;
383 if (!it.value().GetAsDictionary(&server_pref_dict)) {
384 DVLOG(1) << "Malformed http_server_properties server: " << server_str;
385 detected_corrupted_prefs = true;
386 continue;
389 // Get if server supports Spdy.
390 bool supports_spdy = false;
391 if ((server_pref_dict->GetBoolean("supports_spdy", &supports_spdy)) &&
392 supports_spdy) {
393 spdy_servers->push_back(server_str);
396 // Get SpdySettings.
397 DCHECK(spdy_settings_map->Peek(server) == spdy_settings_map->end());
398 const base::DictionaryValue* spdy_settings_dict = NULL;
399 if (server_pref_dict->GetDictionaryWithoutPathExpansion(
400 "settings", &spdy_settings_dict)) {
401 SettingsMap settings_map;
402 for (base::DictionaryValue::Iterator dict_it(*spdy_settings_dict);
403 !dict_it.IsAtEnd();
404 dict_it.Advance()) {
405 const std::string& id_str = dict_it.key();
406 int id = 0;
407 if (!base::StringToInt(id_str, &id)) {
408 DVLOG(1) << "Malformed id in SpdySettings for server: " << server_str;
409 NOTREACHED();
410 continue;
412 int value = 0;
413 if (!dict_it.value().GetAsInteger(&value)) {
414 DVLOG(1) << "Malformed value in SpdySettings for server: "
415 << server_str;
416 NOTREACHED();
417 continue;
419 SettingsFlagsAndValue flags_and_value(SETTINGS_FLAG_PERSISTED, value);
420 settings_map[static_cast<SpdySettingsIds>(id)] = flags_and_value;
422 spdy_settings_map->Put(server, settings_map);
425 // Get alternate_protocol server.
426 DCHECK(alternate_protocol_map->Peek(server) ==
427 alternate_protocol_map->end());
428 const base::DictionaryValue* port_alternate_protocol_dict = NULL;
429 if (server_pref_dict->GetDictionaryWithoutPathExpansion(
430 "alternate_protocol", &port_alternate_protocol_dict)) {
431 int port = 0;
432 if (!port_alternate_protocol_dict->GetIntegerWithoutPathExpansion(
433 "port", &port) ||
434 !IsPortValid(port)) {
435 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str;
436 detected_corrupted_prefs = true;
437 continue;
439 std::string protocol_str;
440 if (!port_alternate_protocol_dict->GetStringWithoutPathExpansion(
441 "protocol_str", &protocol_str)) {
442 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str;
443 detected_corrupted_prefs = true;
444 continue;
446 AlternateProtocol protocol = AlternateProtocolFromString(protocol_str);
447 if (!IsAlternateProtocolValid(protocol)) {
448 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str;
449 detected_corrupted_prefs = true;
450 continue;
453 double probability = 1;
454 if (port_alternate_protocol_dict->HasKey("probability") &&
455 !port_alternate_protocol_dict->GetDoubleWithoutPathExpansion(
456 "probability", &probability)) {
457 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str;
458 detected_corrupted_prefs = true;
459 continue;
462 AlternateProtocolInfo port_alternate_protocol(static_cast<uint16>(port),
463 protocol, probability);
464 alternate_protocol_map->Put(server, port_alternate_protocol);
467 // Get SupportsQuic.
468 DCHECK(supports_quic_map->find(server) == supports_quic_map->end());
469 const base::DictionaryValue* supports_quic_dict = NULL;
470 if (server_pref_dict->GetDictionaryWithoutPathExpansion(
471 "supports_quic", &supports_quic_dict)) {
472 bool used_quic = 0;
473 if (!supports_quic_dict->GetBooleanWithoutPathExpansion(
474 "used_quic", &used_quic)) {
475 DVLOG(1) << "Malformed SupportsQuic server: " << server_str;
476 detected_corrupted_prefs = true;
477 continue;
479 std::string address;
480 if (!supports_quic_dict->GetStringWithoutPathExpansion(
481 "address", &address)) {
482 DVLOG(1) << "Malformed SupportsQuic server: " << server_str;
483 detected_corrupted_prefs = true;
484 continue;
486 SupportsQuic supports_quic(used_quic, address);
487 supports_quic_map->insert(std::make_pair(server, supports_quic));
490 // Get ServerNetworkStats.
491 DCHECK(server_network_stats_map->Peek(server) ==
492 server_network_stats_map->end());
493 const base::DictionaryValue* server_network_stats_dict = NULL;
494 if (server_pref_dict->GetDictionaryWithoutPathExpansion(
495 "network_stats", &server_network_stats_dict)) {
496 int srtt;
497 if (!server_network_stats_dict->GetIntegerWithoutPathExpansion("srtt",
498 &srtt)) {
499 DVLOG(1) << "Malformed ServerNetworkStats for server: " << server_str;
500 detected_corrupted_prefs = true;
501 continue;
503 ServerNetworkStats server_network_stats;
504 server_network_stats.srtt = base::TimeDelta::FromInternalValue(srtt);
505 // TODO(rtenneti): When QUIC starts using bandwidth_estimate, then persist
506 // bandwidth_estimate.
507 server_network_stats_map->Put(server, server_network_stats);
511 network_task_runner_->PostTask(
512 FROM_HERE,
513 base::Bind(
514 &HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread,
515 base::Unretained(this), base::Owned(spdy_servers.release()),
516 base::Owned(spdy_settings_map.release()),
517 base::Owned(alternate_protocol_map.release()),
518 base::Owned(supports_quic_map.release()),
519 base::Owned(server_network_stats_map.release()),
520 detected_corrupted_prefs));
523 void HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread(
524 StringVector* spdy_servers,
525 SpdySettingsMap* spdy_settings_map,
526 AlternateProtocolMap* alternate_protocol_map,
527 SupportsQuicMap* supports_quic_map,
528 ServerNetworkStatsMap* server_network_stats_map,
529 bool detected_corrupted_prefs) {
530 // Preferences have the master data because admins might have pushed new
531 // preferences. Update the cached data with new data from preferences.
532 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
534 UMA_HISTOGRAM_COUNTS("Net.CountOfSpdyServers", spdy_servers->size());
535 http_server_properties_impl_->InitializeSpdyServers(spdy_servers, true);
537 // Update the cached data and use the new spdy_settings from preferences.
538 UMA_HISTOGRAM_COUNTS("Net.CountOfSpdySettings", spdy_settings_map->size());
539 http_server_properties_impl_->InitializeSpdySettingsServers(
540 spdy_settings_map);
542 // Update the cached data and use the new Alternate-Protocol server list from
543 // preferences.
544 UMA_HISTOGRAM_COUNTS("Net.CountOfAlternateProtocolServers",
545 alternate_protocol_map->size());
546 http_server_properties_impl_->InitializeAlternateProtocolServers(
547 alternate_protocol_map);
549 http_server_properties_impl_->InitializeSupportsQuic(supports_quic_map);
551 http_server_properties_impl_->InitializeServerNetworkStats(
552 server_network_stats_map);
554 // Update the prefs with what we have read (delete all corrupted prefs).
555 if (detected_corrupted_prefs)
556 ScheduleUpdatePrefsOnNetworkThread();
560 // Update Preferences with data from the cached data.
562 void HttpServerPropertiesManager::ScheduleUpdatePrefsOnNetworkThread() {
563 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
564 // Cancel pending updates, if any.
565 network_prefs_update_timer_->Stop();
566 StartPrefsUpdateTimerOnNetworkThread(
567 base::TimeDelta::FromMilliseconds(kUpdatePrefsDelayMs));
570 void HttpServerPropertiesManager::StartPrefsUpdateTimerOnNetworkThread(
571 base::TimeDelta delay) {
572 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
573 // This is overridden in tests to post the task without the delay.
574 network_prefs_update_timer_->Start(
575 FROM_HERE,
576 delay,
577 this,
578 &HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread);
581 // This is required so we can set this as the callback for a timer.
582 void HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread() {
583 UpdatePrefsFromCacheOnNetworkThread(base::Closure());
586 void HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread(
587 const base::Closure& completion) {
588 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
590 base::ListValue* spdy_server_list = new base::ListValue;
591 http_server_properties_impl_->GetSpdyServerList(
592 spdy_server_list, kMaxSupportsSpdyServerHostsToPersist);
594 SpdySettingsMap* spdy_settings_map =
595 new SpdySettingsMap(kMaxSpdySettingsHostsToPersist);
596 const SpdySettingsMap& main_map =
597 http_server_properties_impl_->spdy_settings_map();
598 int count = 0;
599 for (SpdySettingsMap::const_iterator it = main_map.begin();
600 it != main_map.end() && count < kMaxSpdySettingsHostsToPersist;
601 ++it, ++count) {
602 spdy_settings_map->Put(it->first, it->second);
605 AlternateProtocolMap* alternate_protocol_map =
606 new AlternateProtocolMap(kMaxAlternateProtocolHostsToPersist);
607 const AlternateProtocolMap& map =
608 http_server_properties_impl_->alternate_protocol_map();
609 count = 0;
610 typedef std::map<std::string, bool> CanonicalHostPersistedMap;
611 CanonicalHostPersistedMap persisted_map;
612 for (AlternateProtocolMap::const_iterator it = map.begin();
613 it != map.end() && count < kMaxAlternateProtocolHostsToPersist; ++it) {
614 const HostPortPair& server = it->first;
615 std::string canonical_suffix =
616 http_server_properties_impl_->GetCanonicalSuffix(server);
617 if (!canonical_suffix.empty()) {
618 if (persisted_map.find(canonical_suffix) != persisted_map.end())
619 continue;
620 persisted_map[canonical_suffix] = true;
622 alternate_protocol_map->Put(server, it->second);
623 ++count;
626 SupportsQuicMap* supports_quic_map = new SupportsQuicMap();
627 const SupportsQuicMap& main_supports_quic_map =
628 http_server_properties_impl_->supports_quic_map();
629 for (SupportsQuicMap::const_iterator it = main_supports_quic_map.begin();
630 it != main_supports_quic_map.end(); ++it) {
631 supports_quic_map->insert(std::make_pair(it->first, it->second));
634 ServerNetworkStatsMap* server_network_stats_map =
635 new ServerNetworkStatsMap(kMaxServerNetworkStatsHostsToPersist);
636 const ServerNetworkStatsMap& main_server_network_stats_map =
637 http_server_properties_impl_->server_network_stats_map();
638 for (ServerNetworkStatsMap::const_iterator it =
639 main_server_network_stats_map.begin();
640 it != main_server_network_stats_map.end(); ++it) {
641 server_network_stats_map->Put(it->first, it->second);
644 // Update the preferences on the pref thread.
645 pref_task_runner_->PostTask(
646 FROM_HERE,
647 base::Bind(
648 &HttpServerPropertiesManager::UpdatePrefsOnPrefThread, pref_weak_ptr_,
649 base::Owned(spdy_server_list), base::Owned(spdy_settings_map),
650 base::Owned(alternate_protocol_map), base::Owned(supports_quic_map),
651 base::Owned(server_network_stats_map), completion));
654 // A local or temporary data structure to hold |supports_spdy|, SpdySettings,
655 // AlternateProtocolInfo and SupportsQuic preferences for a server. This is used
656 // only in UpdatePrefsOnPrefThread.
657 struct ServerPref {
658 ServerPref()
659 : supports_spdy(false),
660 settings_map(NULL),
661 alternate_protocol(NULL),
662 supports_quic(NULL),
663 server_network_stats(NULL) {}
664 ServerPref(bool supports_spdy,
665 const SettingsMap* settings_map,
666 const AlternateProtocolInfo* alternate_protocol,
667 const SupportsQuic* supports_quic,
668 const ServerNetworkStats* server_network_stats)
669 : supports_spdy(supports_spdy),
670 settings_map(settings_map),
671 alternate_protocol(alternate_protocol),
672 supports_quic(supports_quic),
673 server_network_stats(server_network_stats) {}
674 bool supports_spdy;
675 const SettingsMap* settings_map;
676 const AlternateProtocolInfo* alternate_protocol;
677 const SupportsQuic* supports_quic;
678 const ServerNetworkStats* server_network_stats;
681 void HttpServerPropertiesManager::UpdatePrefsOnPrefThread(
682 base::ListValue* spdy_server_list,
683 SpdySettingsMap* spdy_settings_map,
684 AlternateProtocolMap* alternate_protocol_map,
685 SupportsQuicMap* supports_quic_map,
686 ServerNetworkStatsMap* server_network_stats_map,
687 const base::Closure& completion) {
688 typedef std::map<HostPortPair, ServerPref> ServerPrefMap;
689 ServerPrefMap server_pref_map;
691 DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
693 // Add servers that support spdy to server_pref_map.
694 std::string s;
695 for (base::ListValue::const_iterator list_it = spdy_server_list->begin();
696 list_it != spdy_server_list->end();
697 ++list_it) {
698 if ((*list_it)->GetAsString(&s)) {
699 HostPortPair server = HostPortPair::FromString(s);
701 ServerPrefMap::iterator it = server_pref_map.find(server);
702 if (it == server_pref_map.end()) {
703 ServerPref server_pref(true, NULL, NULL, NULL, NULL);
704 server_pref_map[server] = server_pref;
705 } else {
706 it->second.supports_spdy = true;
711 // Add servers that have SpdySettings to server_pref_map.
712 for (SpdySettingsMap::iterator map_it = spdy_settings_map->begin();
713 map_it != spdy_settings_map->end(); ++map_it) {
714 const HostPortPair& server = map_it->first;
716 ServerPrefMap::iterator it = server_pref_map.find(server);
717 if (it == server_pref_map.end()) {
718 ServerPref server_pref(false, &map_it->second, NULL, NULL, NULL);
719 server_pref_map[server] = server_pref;
720 } else {
721 it->second.settings_map = &map_it->second;
725 // Add AlternateProtocol servers to server_pref_map.
726 for (AlternateProtocolMap::const_iterator map_it =
727 alternate_protocol_map->begin();
728 map_it != alternate_protocol_map->end(); ++map_it) {
729 const HostPortPair& server = map_it->first;
730 const AlternateProtocolInfo& port_alternate_protocol = map_it->second;
731 if (!IsAlternateProtocolValid(port_alternate_protocol.protocol)) {
732 continue;
735 ServerPrefMap::iterator it = server_pref_map.find(server);
736 if (it == server_pref_map.end()) {
737 ServerPref server_pref(false, NULL, &map_it->second, NULL, NULL);
738 server_pref_map[server] = server_pref;
739 } else {
740 it->second.alternate_protocol = &map_it->second;
744 // Add SupportsQuic servers to server_pref_map.
745 for (SupportsQuicMap::const_iterator map_it = supports_quic_map->begin();
746 map_it != supports_quic_map->end(); ++map_it) {
747 const HostPortPair& server = map_it->first;
749 ServerPrefMap::iterator it = server_pref_map.find(server);
750 if (it == server_pref_map.end()) {
751 ServerPref server_pref(false, NULL, NULL, &map_it->second, NULL);
752 server_pref_map[server] = server_pref;
753 } else {
754 it->second.supports_quic = &map_it->second;
758 // Add ServerNetworkStats servers to server_pref_map.
759 for (ServerNetworkStatsMap::const_iterator map_it =
760 server_network_stats_map->begin();
761 map_it != server_network_stats_map->end(); ++map_it) {
762 const HostPortPair& server = map_it->first;
764 ServerPrefMap::iterator it = server_pref_map.find(server);
765 if (it == server_pref_map.end()) {
766 ServerPref server_pref(false, NULL, NULL, NULL, &map_it->second);
767 server_pref_map[server] = server_pref;
768 } else {
769 it->second.server_network_stats = &map_it->second;
773 // Persist properties to the |path_|.
774 base::DictionaryValue http_server_properties_dict;
775 base::DictionaryValue* servers_dict = new base::DictionaryValue;
776 for (ServerPrefMap::const_iterator map_it = server_pref_map.begin();
777 map_it != server_pref_map.end();
778 ++map_it) {
779 const HostPortPair& server = map_it->first;
780 const ServerPref& server_pref = map_it->second;
782 base::DictionaryValue* server_pref_dict = new base::DictionaryValue;
784 // Save supports_spdy.
785 if (server_pref.supports_spdy)
786 server_pref_dict->SetBoolean("supports_spdy", server_pref.supports_spdy);
788 // Save SPDY settings.
789 if (server_pref.settings_map) {
790 base::DictionaryValue* spdy_settings_dict = new base::DictionaryValue;
791 for (SettingsMap::const_iterator it = server_pref.settings_map->begin();
792 it != server_pref.settings_map->end(); ++it) {
793 SpdySettingsIds id = it->first;
794 uint32 value = it->second.second;
795 std::string key = base::StringPrintf("%u", id);
796 spdy_settings_dict->SetInteger(key, value);
798 server_pref_dict->SetWithoutPathExpansion("settings", spdy_settings_dict);
801 // Save alternate_protocol.
802 const AlternateProtocolInfo* port_alternate_protocol =
803 server_pref.alternate_protocol;
804 if (port_alternate_protocol && !port_alternate_protocol->is_broken) {
805 base::DictionaryValue* port_alternate_protocol_dict =
806 new base::DictionaryValue;
807 port_alternate_protocol_dict->SetInteger("port",
808 port_alternate_protocol->port);
809 const char* protocol_str =
810 AlternateProtocolToString(port_alternate_protocol->protocol);
811 port_alternate_protocol_dict->SetString("protocol_str", protocol_str);
812 port_alternate_protocol_dict->SetDouble(
813 "probability", port_alternate_protocol->probability);
814 server_pref_dict->SetWithoutPathExpansion(
815 "alternate_protocol", port_alternate_protocol_dict);
818 // Save supports_quic.
819 if (server_pref.supports_quic) {
820 base::DictionaryValue* supports_quic_dict = new base::DictionaryValue;
821 const SupportsQuic* supports_quic = server_pref.supports_quic;
822 supports_quic_dict->SetBoolean("used_quic", supports_quic->used_quic);
823 supports_quic_dict->SetString("address", supports_quic->address);
824 server_pref_dict->SetWithoutPathExpansion(
825 "supports_quic", supports_quic_dict);
828 // Save ServerNetworkStats.
829 if (server_pref.server_network_stats) {
830 base::DictionaryValue* server_network_stats_dict =
831 new base::DictionaryValue;
832 const ServerNetworkStats* server_network_stats =
833 server_pref.server_network_stats;
834 // Becasue JSON doesn't support int64, persist int64 as a string.
835 server_network_stats_dict->SetInteger(
836 "srtt",
837 static_cast<int>(server_network_stats->srtt.ToInternalValue()));
838 // TODO(rtenneti): When QUIC starts using bandwidth_estimate, then persist
839 // bandwidth_estimate.
840 server_pref_dict->SetWithoutPathExpansion("network_stats",
841 server_network_stats_dict);
844 servers_dict->SetWithoutPathExpansion(server.ToString(), server_pref_dict);
847 http_server_properties_dict.SetWithoutPathExpansion("servers", servers_dict);
848 SetVersion(&http_server_properties_dict, kVersionNumber);
849 setting_prefs_ = true;
850 pref_service_->Set(path_, http_server_properties_dict);
851 setting_prefs_ = false;
853 // Note that |completion| will be fired after we have written everything to
854 // the Preferences, but likely before these changes are serialized to disk.
855 // This is not a problem though, as JSONPrefStore guarantees that this will
856 // happen, pretty soon, and even in the case we shut down immediately.
857 if (!completion.is_null())
858 completion.Run();
861 void HttpServerPropertiesManager::OnHttpServerPropertiesChanged() {
862 DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
863 if (!setting_prefs_)
864 ScheduleUpdateCacheOnPrefThread();
867 } // namespace net