Added #ifdefs around PrintHeaderAndFooter for Windows and Mac.
[chromium-blink-merge.git] / net / http / http_server_properties_manager.cc
blob794030d8a531ee7148257c97c99db85baf8e6850
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"
17 namespace net {
19 namespace {
21 // Time to wait before starting an update the http_server_properties_impl_ cache
22 // from preferences. Scheduling another update during this period will reset the
23 // timer.
24 const int64 kUpdateCacheDelayMs = 1000;
26 // Time to wait before starting an update the preferences from the
27 // http_server_properties_impl_ cache. Scheduling another update during this
28 // period will reset the timer.
29 // TODO(rtenneti): Remove OS_ANDROID ifdef after testing if flushing of
30 // AlternateProtocolHosts to disk in 500ms helps with QUIC's 0RTT or not.
31 #if defined(OS_ANDROID)
32 const int64 kUpdatePrefsDelayMs = 500;
33 #else
34 const int64 kUpdatePrefsDelayMs = 5000;
35 #endif
37 // "version" 0 indicates, http_server_properties doesn't have "version"
38 // property.
39 const int kMissingVersion = 0;
41 // The version number of persisted http_server_properties.
42 const int kVersionNumber = 3;
44 typedef std::vector<std::string> StringVector;
46 // Persist 200 MRU AlternateProtocolHostPortPairs.
47 const int kMaxAlternateProtocolHostsToPersist = 200;
49 // Persist 200 MRU SpdySettingsHostPortPairs.
50 const int kMaxSpdySettingsHostsToPersist = 200;
52 // Persist 300 MRU SupportsSpdyServerHostPortPairs.
53 const int kMaxSupportsSpdyServerHostsToPersist = 300;
55 } // namespace
57 ////////////////////////////////////////////////////////////////////////////////
58 // HttpServerPropertiesManager
60 HttpServerPropertiesManager::HttpServerPropertiesManager(
61 PrefService* pref_service,
62 const char* pref_path,
63 scoped_refptr<base::SequencedTaskRunner> network_task_runner)
64 : pref_task_runner_(base::ThreadTaskRunnerHandle::Get()),
65 pref_service_(pref_service),
66 setting_prefs_(false),
67 path_(pref_path),
68 network_task_runner_(network_task_runner) {
69 DCHECK(pref_service);
70 pref_weak_ptr_factory_.reset(
71 new base::WeakPtrFactory<HttpServerPropertiesManager>(this));
72 pref_weak_ptr_ = pref_weak_ptr_factory_->GetWeakPtr();
73 pref_cache_update_timer_.reset(
74 new base::OneShotTimer<HttpServerPropertiesManager>);
75 pref_change_registrar_.Init(pref_service_);
76 pref_change_registrar_.Add(
77 path_,
78 base::Bind(&HttpServerPropertiesManager::OnHttpServerPropertiesChanged,
79 base::Unretained(this)));
82 HttpServerPropertiesManager::~HttpServerPropertiesManager() {
83 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
84 network_weak_ptr_factory_.reset();
87 void HttpServerPropertiesManager::InitializeOnNetworkThread() {
88 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
89 network_weak_ptr_factory_.reset(
90 new base::WeakPtrFactory<HttpServerPropertiesManager>(this));
91 http_server_properties_impl_.reset(new net::HttpServerPropertiesImpl());
93 network_prefs_update_timer_.reset(
94 new base::OneShotTimer<HttpServerPropertiesManager>);
96 pref_task_runner_->PostTask(
97 FROM_HERE,
98 base::Bind(&HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread,
99 pref_weak_ptr_));
102 void HttpServerPropertiesManager::ShutdownOnPrefThread() {
103 DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
104 // Cancel any pending updates, and stop listening for pref change updates.
105 pref_cache_update_timer_->Stop();
106 pref_weak_ptr_factory_.reset();
107 pref_change_registrar_.RemoveAll();
110 // static
111 void HttpServerPropertiesManager::SetVersion(
112 base::DictionaryValue* http_server_properties_dict,
113 int version_number) {
114 if (version_number < 0)
115 version_number = kVersionNumber;
116 DCHECK_LE(version_number, kVersionNumber);
117 if (version_number <= kVersionNumber)
118 http_server_properties_dict->SetInteger("version", version_number);
121 // This is required for conformance with the HttpServerProperties interface.
122 base::WeakPtr<net::HttpServerProperties>
123 HttpServerPropertiesManager::GetWeakPtr() {
124 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
125 return network_weak_ptr_factory_->GetWeakPtr();
128 void HttpServerPropertiesManager::Clear() {
129 Clear(base::Closure());
132 void HttpServerPropertiesManager::Clear(const base::Closure& completion) {
133 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
135 http_server_properties_impl_->Clear();
136 UpdatePrefsFromCacheOnNetworkThread(completion);
139 bool HttpServerPropertiesManager::SupportsSpdy(
140 const net::HostPortPair& server) {
141 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
142 return http_server_properties_impl_->SupportsSpdy(server);
145 void HttpServerPropertiesManager::SetSupportsSpdy(
146 const net::HostPortPair& server,
147 bool support_spdy) {
148 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
150 http_server_properties_impl_->SetSupportsSpdy(server, support_spdy);
151 ScheduleUpdatePrefsOnNetworkThread();
154 bool HttpServerPropertiesManager::HasAlternateProtocol(
155 const net::HostPortPair& server) {
156 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
157 return http_server_properties_impl_->HasAlternateProtocol(server);
160 net::AlternateProtocolInfo
161 HttpServerPropertiesManager::GetAlternateProtocol(
162 const net::HostPortPair& server) {
163 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
164 return http_server_properties_impl_->GetAlternateProtocol(server);
167 void HttpServerPropertiesManager::SetAlternateProtocol(
168 const net::HostPortPair& server,
169 uint16 alternate_port,
170 AlternateProtocol alternate_protocol,
171 double alternate_probability) {
172 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
173 http_server_properties_impl_->SetAlternateProtocol(
174 server, alternate_port, alternate_protocol, alternate_probability);
175 ScheduleUpdatePrefsOnNetworkThread();
178 void HttpServerPropertiesManager::SetBrokenAlternateProtocol(
179 const net::HostPortPair& server) {
180 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
181 http_server_properties_impl_->SetBrokenAlternateProtocol(server);
182 ScheduleUpdatePrefsOnNetworkThread();
185 bool HttpServerPropertiesManager::WasAlternateProtocolRecentlyBroken(
186 const net::HostPortPair& server) {
187 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
188 return http_server_properties_impl_->WasAlternateProtocolRecentlyBroken(
189 server);
192 void HttpServerPropertiesManager::ConfirmAlternateProtocol(
193 const net::HostPortPair& server) {
194 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
195 http_server_properties_impl_->ConfirmAlternateProtocol(server);
196 ScheduleUpdatePrefsOnNetworkThread();
199 void HttpServerPropertiesManager::ClearAlternateProtocol(
200 const net::HostPortPair& server) {
201 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
202 http_server_properties_impl_->ClearAlternateProtocol(server);
203 ScheduleUpdatePrefsOnNetworkThread();
206 const net::AlternateProtocolMap&
207 HttpServerPropertiesManager::alternate_protocol_map() const {
208 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
209 return http_server_properties_impl_->alternate_protocol_map();
212 void HttpServerPropertiesManager::SetAlternateProtocolProbabilityThreshold(
213 double threshold) {
214 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
215 http_server_properties_impl_->SetAlternateProtocolProbabilityThreshold(
216 threshold);
219 const SettingsMap& HttpServerPropertiesManager::GetSpdySettings(
220 const HostPortPair& host_port_pair) {
221 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
222 return http_server_properties_impl_->GetSpdySettings(host_port_pair);
225 bool HttpServerPropertiesManager::SetSpdySetting(
226 const HostPortPair& host_port_pair,
227 SpdySettingsIds id,
228 SpdySettingsFlags flags,
229 uint32 value) {
230 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
231 bool persist = http_server_properties_impl_->SetSpdySetting(
232 host_port_pair, id, flags, value);
233 if (persist)
234 ScheduleUpdatePrefsOnNetworkThread();
235 return persist;
238 void HttpServerPropertiesManager::ClearSpdySettings(
239 const HostPortPair& host_port_pair) {
240 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
241 http_server_properties_impl_->ClearSpdySettings(host_port_pair);
242 ScheduleUpdatePrefsOnNetworkThread();
245 void HttpServerPropertiesManager::ClearAllSpdySettings() {
246 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
247 http_server_properties_impl_->ClearAllSpdySettings();
248 ScheduleUpdatePrefsOnNetworkThread();
251 const SpdySettingsMap& HttpServerPropertiesManager::spdy_settings_map()
252 const {
253 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
254 return http_server_properties_impl_->spdy_settings_map();
257 net::SupportsQuic
258 HttpServerPropertiesManager::GetSupportsQuic(
259 const net::HostPortPair& host_port_pair) const {
260 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
261 return http_server_properties_impl_->GetSupportsQuic(host_port_pair);
264 void HttpServerPropertiesManager::SetSupportsQuic(
265 const net::HostPortPair& host_port_pair,
266 bool used_quic,
267 const std::string& address) {
268 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
269 http_server_properties_impl_->SetSupportsQuic(
270 host_port_pair, used_quic, address);
271 ScheduleUpdatePrefsOnNetworkThread();
274 const SupportsQuicMap& HttpServerPropertiesManager::supports_quic_map()
275 const {
276 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
277 return http_server_properties_impl_->supports_quic_map();
280 void HttpServerPropertiesManager::SetServerNetworkStats(
281 const net::HostPortPair& host_port_pair,
282 NetworkStats stats) {
283 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
284 http_server_properties_impl_->SetServerNetworkStats(host_port_pair, stats);
287 const HttpServerPropertiesManager::NetworkStats*
288 HttpServerPropertiesManager::GetServerNetworkStats(
289 const net::HostPortPair& host_port_pair) const {
290 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
291 return http_server_properties_impl_->GetServerNetworkStats(host_port_pair);
295 // Update the HttpServerPropertiesImpl's cache with data from preferences.
297 void HttpServerPropertiesManager::ScheduleUpdateCacheOnPrefThread() {
298 DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
299 // Cancel pending updates, if any.
300 pref_cache_update_timer_->Stop();
301 StartCacheUpdateTimerOnPrefThread(
302 base::TimeDelta::FromMilliseconds(kUpdateCacheDelayMs));
305 void HttpServerPropertiesManager::StartCacheUpdateTimerOnPrefThread(
306 base::TimeDelta delay) {
307 DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
308 pref_cache_update_timer_->Start(
309 FROM_HERE,
310 delay,
311 this,
312 &HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread);
315 void HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread() {
316 // The preferences can only be read on the pref thread.
317 DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
319 if (!pref_service_->HasPrefPath(path_))
320 return;
322 bool detected_corrupted_prefs = false;
323 const base::DictionaryValue& http_server_properties_dict =
324 *pref_service_->GetDictionary(path_);
326 int version = kMissingVersion;
327 if (!http_server_properties_dict.GetIntegerWithoutPathExpansion("version",
328 &version)) {
329 DVLOG(1) << "Missing version. Clearing all properties.";
330 return;
333 // The properties for a given server is in
334 // http_server_properties_dict["servers"][server].
335 const base::DictionaryValue* servers_dict = NULL;
336 if (!http_server_properties_dict.GetDictionaryWithoutPathExpansion(
337 "servers", &servers_dict)) {
338 DVLOG(1) << "Malformed http_server_properties for servers.";
339 return;
342 // String is host/port pair of spdy server.
343 scoped_ptr<StringVector> spdy_servers(new StringVector);
344 scoped_ptr<net::SpdySettingsMap> spdy_settings_map(
345 new net::SpdySettingsMap(kMaxSpdySettingsHostsToPersist));
346 scoped_ptr<net::AlternateProtocolMap> alternate_protocol_map(
347 new net::AlternateProtocolMap(kMaxAlternateProtocolHostsToPersist));
348 scoped_ptr<net::SupportsQuicMap> supports_quic_map(
349 new net::SupportsQuicMap());
351 int count = 0;
352 for (base::DictionaryValue::Iterator it(*servers_dict); !it.IsAtEnd();
353 it.Advance()) {
354 // Get server's host/pair.
355 const std::string& server_str = it.key();
356 net::HostPortPair server = net::HostPortPair::FromString(server_str);
357 if (server.host().empty()) {
358 DVLOG(1) << "Malformed http_server_properties for server: " << server_str;
359 detected_corrupted_prefs = true;
360 continue;
363 const base::DictionaryValue* server_pref_dict = NULL;
364 if (!it.value().GetAsDictionary(&server_pref_dict)) {
365 DVLOG(1) << "Malformed http_server_properties server: " << server_str;
366 detected_corrupted_prefs = true;
367 continue;
370 // Get if server supports Spdy.
371 bool supports_spdy = false;
372 if ((server_pref_dict->GetBoolean("supports_spdy", &supports_spdy)) &&
373 supports_spdy) {
374 spdy_servers->push_back(server_str);
377 // Get SpdySettings.
378 DCHECK(spdy_settings_map->Peek(server) == spdy_settings_map->end());
379 const base::DictionaryValue* spdy_settings_dict = NULL;
380 if (server_pref_dict->GetDictionaryWithoutPathExpansion(
381 "settings", &spdy_settings_dict)) {
382 net::SettingsMap settings_map;
383 for (base::DictionaryValue::Iterator dict_it(*spdy_settings_dict);
384 !dict_it.IsAtEnd();
385 dict_it.Advance()) {
386 const std::string& id_str = dict_it.key();
387 int id = 0;
388 if (!base::StringToInt(id_str, &id)) {
389 DVLOG(1) << "Malformed id in SpdySettings for server: " << server_str;
390 NOTREACHED();
391 continue;
393 int value = 0;
394 if (!dict_it.value().GetAsInteger(&value)) {
395 DVLOG(1) << "Malformed value in SpdySettings for server: "
396 << server_str;
397 NOTREACHED();
398 continue;
400 net::SettingsFlagsAndValue flags_and_value(net::SETTINGS_FLAG_PERSISTED,
401 value);
402 settings_map[static_cast<net::SpdySettingsIds>(id)] = flags_and_value;
404 spdy_settings_map->Put(server, settings_map);
407 // Get alternate_protocol server.
408 DCHECK(alternate_protocol_map->Peek(server) ==
409 alternate_protocol_map->end());
410 const base::DictionaryValue* port_alternate_protocol_dict = NULL;
411 if (!server_pref_dict->GetDictionaryWithoutPathExpansion(
412 "alternate_protocol", &port_alternate_protocol_dict)) {
413 continue;
416 if (count >= kMaxAlternateProtocolHostsToPersist)
417 continue;
418 do {
419 int port = 0;
420 if (!port_alternate_protocol_dict->GetIntegerWithoutPathExpansion(
421 "port", &port) ||
422 (port > (1 << 16))) {
423 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str;
424 detected_corrupted_prefs = true;
425 continue;
427 std::string protocol_str;
428 if (!port_alternate_protocol_dict->GetStringWithoutPathExpansion(
429 "protocol_str", &protocol_str)) {
430 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str;
431 detected_corrupted_prefs = true;
432 continue;
434 net::AlternateProtocol protocol =
435 net::AlternateProtocolFromString(protocol_str);
436 if (!net::IsAlternateProtocolValid(protocol)) {
437 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str;
438 detected_corrupted_prefs = true;
439 continue;
442 double probability = 1;
443 if (port_alternate_protocol_dict->HasKey("probability") &&
444 !port_alternate_protocol_dict->GetDoubleWithoutPathExpansion(
445 "probability", &probability)) {
446 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str;
447 detected_corrupted_prefs = true;
448 continue;
451 net::AlternateProtocolInfo port_alternate_protocol(port,
452 protocol,
453 probability);
454 alternate_protocol_map->Put(server, port_alternate_protocol);
455 ++count;
456 } while (false);
458 // Get SupportsQuic.
459 DCHECK(supports_quic_map->find(server) == supports_quic_map->end());
460 const base::DictionaryValue* supports_quic_dict = NULL;
461 if (!server_pref_dict->GetDictionaryWithoutPathExpansion(
462 "supports_quic", &supports_quic_dict)) {
463 continue;
465 do {
466 bool used_quic = 0;
467 if (!supports_quic_dict->GetBooleanWithoutPathExpansion(
468 "used_quic", &used_quic)) {
469 DVLOG(1) << "Malformed SupportsQuic server: " << server_str;
470 detected_corrupted_prefs = true;
471 continue;
473 std::string address;
474 if (!supports_quic_dict->GetStringWithoutPathExpansion(
475 "address", &address)) {
476 DVLOG(1) << "Malformed SupportsQuic server: " << server_str;
477 detected_corrupted_prefs = true;
478 continue;
480 net::SupportsQuic supports_quic(used_quic, address);
481 supports_quic_map->insert(std::make_pair(server, supports_quic));
482 } while (false);
485 network_task_runner_->PostTask(
486 FROM_HERE,
487 base::Bind(
488 &HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread,
489 base::Unretained(this),
490 base::Owned(spdy_servers.release()),
491 base::Owned(spdy_settings_map.release()),
492 base::Owned(alternate_protocol_map.release()),
493 base::Owned(supports_quic_map.release()),
494 detected_corrupted_prefs));
497 void HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread(
498 StringVector* spdy_servers,
499 net::SpdySettingsMap* spdy_settings_map,
500 net::AlternateProtocolMap* alternate_protocol_map,
501 net::SupportsQuicMap* supports_quic_map,
502 bool detected_corrupted_prefs) {
503 // Preferences have the master data because admins might have pushed new
504 // preferences. Update the cached data with new data from preferences.
505 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
507 UMA_HISTOGRAM_COUNTS("Net.CountOfSpdyServers", spdy_servers->size());
508 http_server_properties_impl_->InitializeSpdyServers(spdy_servers, true);
510 // Update the cached data and use the new spdy_settings from preferences.
511 UMA_HISTOGRAM_COUNTS("Net.CountOfSpdySettings", spdy_settings_map->size());
512 http_server_properties_impl_->InitializeSpdySettingsServers(
513 spdy_settings_map);
515 // Update the cached data and use the new Alternate-Protocol server list from
516 // preferences.
517 UMA_HISTOGRAM_COUNTS("Net.CountOfAlternateProtocolServers",
518 alternate_protocol_map->size());
519 http_server_properties_impl_->InitializeAlternateProtocolServers(
520 alternate_protocol_map);
522 http_server_properties_impl_->InitializeSupportsQuic(supports_quic_map);
524 // Update the prefs with what we have read (delete all corrupted prefs).
525 if (detected_corrupted_prefs)
526 ScheduleUpdatePrefsOnNetworkThread();
530 // Update Preferences with data from the cached data.
532 void HttpServerPropertiesManager::ScheduleUpdatePrefsOnNetworkThread() {
533 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
534 // Cancel pending updates, if any.
535 network_prefs_update_timer_->Stop();
536 StartPrefsUpdateTimerOnNetworkThread(
537 base::TimeDelta::FromMilliseconds(kUpdatePrefsDelayMs));
540 void HttpServerPropertiesManager::StartPrefsUpdateTimerOnNetworkThread(
541 base::TimeDelta delay) {
542 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
543 // This is overridden in tests to post the task without the delay.
544 network_prefs_update_timer_->Start(
545 FROM_HERE,
546 delay,
547 this,
548 &HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread);
551 // This is required so we can set this as the callback for a timer.
552 void HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread() {
553 UpdatePrefsFromCacheOnNetworkThread(base::Closure());
556 void HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread(
557 const base::Closure& completion) {
558 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
560 base::ListValue* spdy_server_list = new base::ListValue;
561 http_server_properties_impl_->GetSpdyServerList(
562 spdy_server_list, kMaxSupportsSpdyServerHostsToPersist);
564 net::SpdySettingsMap* spdy_settings_map =
565 new net::SpdySettingsMap(kMaxSpdySettingsHostsToPersist);
566 const net::SpdySettingsMap& main_map =
567 http_server_properties_impl_->spdy_settings_map();
568 int count = 0;
569 for (net::SpdySettingsMap::const_iterator it = main_map.begin();
570 it != main_map.end() && count < kMaxSpdySettingsHostsToPersist;
571 ++it, ++count) {
572 spdy_settings_map->Put(it->first, it->second);
575 net::AlternateProtocolMap* alternate_protocol_map =
576 new net::AlternateProtocolMap(kMaxAlternateProtocolHostsToPersist);
577 const net::AlternateProtocolMap& map =
578 http_server_properties_impl_->alternate_protocol_map();
579 count = 0;
580 typedef std::map<std::string, bool> CanonicalHostPersistedMap;
581 CanonicalHostPersistedMap persisted_map;
582 for (net::AlternateProtocolMap::const_iterator it = map.begin();
583 it != map.end() && count < kMaxAlternateProtocolHostsToPersist;
584 ++it) {
585 const net::HostPortPair& server = it->first;
586 std::string canonical_suffix =
587 http_server_properties_impl_->GetCanonicalSuffix(server);
588 if (!canonical_suffix.empty()) {
589 if (persisted_map.find(canonical_suffix) != persisted_map.end())
590 continue;
591 persisted_map[canonical_suffix] = true;
593 alternate_protocol_map->Put(server, it->second);
594 ++count;
597 net::SupportsQuicMap* supports_quic_map = new net::SupportsQuicMap();
598 const net::SupportsQuicMap& main_supports_quic_map =
599 http_server_properties_impl_->supports_quic_map();
600 for (net::SupportsQuicMap::const_iterator it = main_supports_quic_map.begin();
601 it != main_supports_quic_map.end(); ++it) {
602 supports_quic_map->insert(std::make_pair(it->first, it->second));
605 // Update the preferences on the pref thread.
606 pref_task_runner_->PostTask(
607 FROM_HERE,
608 base::Bind(&HttpServerPropertiesManager::UpdatePrefsOnPrefThread,
609 pref_weak_ptr_,
610 base::Owned(spdy_server_list),
611 base::Owned(spdy_settings_map),
612 base::Owned(alternate_protocol_map),
613 base::Owned(supports_quic_map),
614 completion));
617 // A local or temporary data structure to hold |supports_spdy|, SpdySettings,
618 // AlternateProtocolInfo and SupportsQuic preferences for a server. This is used
619 // only in UpdatePrefsOnPrefThread.
620 struct ServerPref {
621 ServerPref() : supports_spdy(false),
622 settings_map(NULL),
623 alternate_protocol(NULL),
624 supports_quic(NULL) {}
625 ServerPref(bool supports_spdy,
626 const net::SettingsMap* settings_map,
627 const net::AlternateProtocolInfo* alternate_protocol,
628 const net::SupportsQuic* supports_quic)
629 : supports_spdy(supports_spdy),
630 settings_map(settings_map),
631 alternate_protocol(alternate_protocol),
632 supports_quic(supports_quic) {}
633 bool supports_spdy;
634 const net::SettingsMap* settings_map;
635 const net::AlternateProtocolInfo* alternate_protocol;
636 const net::SupportsQuic* supports_quic;
639 void HttpServerPropertiesManager::UpdatePrefsOnPrefThread(
640 base::ListValue* spdy_server_list,
641 net::SpdySettingsMap* spdy_settings_map,
642 net::AlternateProtocolMap* alternate_protocol_map,
643 net::SupportsQuicMap* supports_quic_map,
644 const base::Closure& completion) {
645 typedef std::map<net::HostPortPair, ServerPref> ServerPrefMap;
646 ServerPrefMap server_pref_map;
648 DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
650 // Add servers that support spdy to server_pref_map.
651 std::string s;
652 for (base::ListValue::const_iterator list_it = spdy_server_list->begin();
653 list_it != spdy_server_list->end();
654 ++list_it) {
655 if ((*list_it)->GetAsString(&s)) {
656 net::HostPortPair server = net::HostPortPair::FromString(s);
658 ServerPrefMap::iterator it = server_pref_map.find(server);
659 if (it == server_pref_map.end()) {
660 ServerPref server_pref(true, NULL, NULL, NULL);
661 server_pref_map[server] = server_pref;
662 } else {
663 it->second.supports_spdy = true;
668 // Add servers that have SpdySettings to server_pref_map.
669 for (net::SpdySettingsMap::iterator map_it = spdy_settings_map->begin();
670 map_it != spdy_settings_map->end();
671 ++map_it) {
672 const net::HostPortPair& server = map_it->first;
674 ServerPrefMap::iterator it = server_pref_map.find(server);
675 if (it == server_pref_map.end()) {
676 ServerPref server_pref(false, &map_it->second, NULL, NULL);
677 server_pref_map[server] = server_pref;
678 } else {
679 it->second.settings_map = &map_it->second;
683 // Add AlternateProtocol servers to server_pref_map.
684 for (net::AlternateProtocolMap::const_iterator map_it =
685 alternate_protocol_map->begin();
686 map_it != alternate_protocol_map->end();
687 ++map_it) {
688 const net::HostPortPair& server = map_it->first;
689 const net::AlternateProtocolInfo& port_alternate_protocol =
690 map_it->second;
691 if (!net::IsAlternateProtocolValid(port_alternate_protocol.protocol)) {
692 continue;
695 ServerPrefMap::iterator it = server_pref_map.find(server);
696 if (it == server_pref_map.end()) {
697 ServerPref server_pref(false, NULL, &map_it->second, NULL);
698 server_pref_map[server] = server_pref;
699 } else {
700 it->second.alternate_protocol = &map_it->second;
704 // Add SupportsQuic servers to server_pref_map.
705 for (net::SupportsQuicMap::const_iterator map_it = supports_quic_map->begin();
706 map_it != supports_quic_map->end(); ++map_it) {
707 const net::HostPortPair& server = map_it->first;
709 ServerPrefMap::iterator it = server_pref_map.find(server);
710 if (it == server_pref_map.end()) {
711 ServerPref server_pref(false, NULL, NULL, &map_it->second);
712 server_pref_map[server] = server_pref;
713 } else {
714 it->second.supports_quic = &map_it->second;
718 // Persist properties to the |path_|.
719 base::DictionaryValue http_server_properties_dict;
720 base::DictionaryValue* servers_dict = new base::DictionaryValue;
721 for (ServerPrefMap::const_iterator map_it = server_pref_map.begin();
722 map_it != server_pref_map.end();
723 ++map_it) {
724 const net::HostPortPair& server = map_it->first;
725 const ServerPref& server_pref = map_it->second;
727 base::DictionaryValue* server_pref_dict = new base::DictionaryValue;
729 // Save supports_spdy.
730 if (server_pref.supports_spdy)
731 server_pref_dict->SetBoolean("supports_spdy", server_pref.supports_spdy);
733 // Save SPDY settings.
734 if (server_pref.settings_map) {
735 base::DictionaryValue* spdy_settings_dict = new base::DictionaryValue;
736 for (net::SettingsMap::const_iterator it =
737 server_pref.settings_map->begin();
738 it != server_pref.settings_map->end();
739 ++it) {
740 net::SpdySettingsIds id = it->first;
741 uint32 value = it->second.second;
742 std::string key = base::StringPrintf("%u", id);
743 spdy_settings_dict->SetInteger(key, value);
745 server_pref_dict->SetWithoutPathExpansion("settings", spdy_settings_dict);
748 // Save alternate_protocol.
749 const net::AlternateProtocolInfo* port_alternate_protocol =
750 server_pref.alternate_protocol;
751 if (port_alternate_protocol && !port_alternate_protocol->is_broken) {
752 base::DictionaryValue* port_alternate_protocol_dict =
753 new base::DictionaryValue;
754 port_alternate_protocol_dict->SetInteger("port",
755 port_alternate_protocol->port);
756 const char* protocol_str =
757 net::AlternateProtocolToString(port_alternate_protocol->protocol);
758 port_alternate_protocol_dict->SetString("protocol_str", protocol_str);
759 port_alternate_protocol_dict->SetDouble(
760 "probability", port_alternate_protocol->probability);
761 server_pref_dict->SetWithoutPathExpansion(
762 "alternate_protocol", port_alternate_protocol_dict);
765 // Save supports_quic.
766 if (server_pref.supports_quic) {
767 base::DictionaryValue* supports_quic_dict = new base::DictionaryValue;
768 const net::SupportsQuic* supports_quic = server_pref.supports_quic;
769 supports_quic_dict->SetBoolean("used_quic", supports_quic->used_quic);
770 supports_quic_dict->SetString("address", supports_quic->address);
771 server_pref_dict->SetWithoutPathExpansion(
772 "supports_quic", supports_quic_dict);
775 servers_dict->SetWithoutPathExpansion(server.ToString(), server_pref_dict);
778 http_server_properties_dict.SetWithoutPathExpansion("servers", servers_dict);
779 SetVersion(&http_server_properties_dict, kVersionNumber);
780 setting_prefs_ = true;
781 pref_service_->Set(path_, http_server_properties_dict);
782 setting_prefs_ = false;
784 // Note that |completion| will be fired after we have written everything to
785 // the Preferences, but likely before these changes are serialized to disk.
786 // This is not a problem though, as JSONPrefStore guarantees that this will
787 // happen, pretty soon, and even in the case we shut down immediately.
788 if (!completion.is_null())
789 completion.Run();
792 void HttpServerPropertiesManager::OnHttpServerPropertiesChanged() {
793 DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
794 if (!setting_prefs_)
795 ScheduleUpdateCacheOnPrefThread();
798 } // namespace net