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"
8 #include "base/metrics/histogram.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/rand_util.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/stl_util.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/stringprintf.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "base/values.h"
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
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"
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 // Load either 200 or 1000 servers based on a coin flip.
42 const int k200AlternateProtocolHostsToLoad
= 200;
43 const int k1000AlternateProtocolHostsToLoad
= 1000;
44 // Persist 1000 MRU AlternateProtocolHostPortPairs.
45 const int kMaxAlternateProtocolHostsToPersist
= 1000;
47 // Persist 200 MRU SpdySettingsHostPortPairs.
48 const int kMaxSpdySettingsHostsToPersist
= 200;
50 // Persist 300 MRU SupportsSpdyServerHostPortPairs.
51 const int kMaxSupportsSpdyServerHostsToPersist
= 300;
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),
66 network_task_runner_(network_task_runner
) {
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(
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 net::HttpServerPropertiesImpl());
91 network_prefs_update_timer_
.reset(
92 new base::OneShotTimer
<HttpServerPropertiesManager
>);
94 pref_task_runner_
->PostTask(
96 base::Bind(&HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread
,
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();
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
<net::HttpServerProperties
>
121 HttpServerPropertiesManager::GetWeakPtr() {
122 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
123 return network_weak_ptr_factory_
->GetWeakPtr();
126 void HttpServerPropertiesManager::Clear() {
127 Clear(base::Closure());
130 void HttpServerPropertiesManager::Clear(const base::Closure
& completion
) {
131 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
133 http_server_properties_impl_
->Clear();
134 UpdatePrefsFromCacheOnNetworkThread(completion
);
137 bool HttpServerPropertiesManager::SupportsSpdy(
138 const net::HostPortPair
& server
) {
139 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
140 return http_server_properties_impl_
->SupportsSpdy(server
);
143 void HttpServerPropertiesManager::SetSupportsSpdy(
144 const net::HostPortPair
& server
,
146 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
148 http_server_properties_impl_
->SetSupportsSpdy(server
, support_spdy
);
149 ScheduleUpdatePrefsOnNetworkThread();
152 bool HttpServerPropertiesManager::HasAlternateProtocol(
153 const net::HostPortPair
& server
) {
154 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
155 return http_server_properties_impl_
->HasAlternateProtocol(server
);
158 net::AlternateProtocolInfo
159 HttpServerPropertiesManager::GetAlternateProtocol(
160 const net::HostPortPair
& server
) {
161 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
162 return http_server_properties_impl_
->GetAlternateProtocol(server
);
165 void HttpServerPropertiesManager::SetAlternateProtocol(
166 const net::HostPortPair
& server
,
167 uint16 alternate_port
,
168 AlternateProtocol alternate_protocol
,
169 double alternate_probability
) {
170 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
171 http_server_properties_impl_
->SetAlternateProtocol(
172 server
, alternate_port
, alternate_protocol
, alternate_probability
);
173 ScheduleUpdatePrefsOnNetworkThread();
176 void HttpServerPropertiesManager::SetBrokenAlternateProtocol(
177 const net::HostPortPair
& server
) {
178 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
179 http_server_properties_impl_
->SetBrokenAlternateProtocol(server
);
180 ScheduleUpdatePrefsOnNetworkThread();
183 bool HttpServerPropertiesManager::WasAlternateProtocolRecentlyBroken(
184 const net::HostPortPair
& server
) {
185 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
186 return http_server_properties_impl_
->WasAlternateProtocolRecentlyBroken(
190 void HttpServerPropertiesManager::ConfirmAlternateProtocol(
191 const net::HostPortPair
& server
) {
192 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
193 http_server_properties_impl_
->ConfirmAlternateProtocol(server
);
194 ScheduleUpdatePrefsOnNetworkThread();
197 void HttpServerPropertiesManager::ClearAlternateProtocol(
198 const net::HostPortPair
& server
) {
199 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
200 http_server_properties_impl_
->ClearAlternateProtocol(server
);
201 ScheduleUpdatePrefsOnNetworkThread();
204 const net::AlternateProtocolMap
&
205 HttpServerPropertiesManager::alternate_protocol_map() const {
206 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
207 return http_server_properties_impl_
->alternate_protocol_map();
210 void HttpServerPropertiesManager::SetAlternateProtocolExperiment(
211 AlternateProtocolExperiment experiment
) {
212 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
213 http_server_properties_impl_
->SetAlternateProtocolExperiment(experiment
);
216 void HttpServerPropertiesManager::SetAlternateProtocolProbabilityThreshold(
218 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
219 http_server_properties_impl_
->SetAlternateProtocolProbabilityThreshold(
223 AlternateProtocolExperiment
224 HttpServerPropertiesManager::GetAlternateProtocolExperiment() const {
225 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
226 return http_server_properties_impl_
->GetAlternateProtocolExperiment();
229 const SettingsMap
& HttpServerPropertiesManager::GetSpdySettings(
230 const HostPortPair
& host_port_pair
) {
231 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
232 return http_server_properties_impl_
->GetSpdySettings(host_port_pair
);
235 bool HttpServerPropertiesManager::SetSpdySetting(
236 const HostPortPair
& host_port_pair
,
238 SpdySettingsFlags flags
,
240 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
241 bool persist
= http_server_properties_impl_
->SetSpdySetting(
242 host_port_pair
, id
, flags
, value
);
244 ScheduleUpdatePrefsOnNetworkThread();
248 void HttpServerPropertiesManager::ClearSpdySettings(
249 const HostPortPair
& host_port_pair
) {
250 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
251 http_server_properties_impl_
->ClearSpdySettings(host_port_pair
);
252 ScheduleUpdatePrefsOnNetworkThread();
255 void HttpServerPropertiesManager::ClearAllSpdySettings() {
256 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
257 http_server_properties_impl_
->ClearAllSpdySettings();
258 ScheduleUpdatePrefsOnNetworkThread();
261 const SpdySettingsMap
& HttpServerPropertiesManager::spdy_settings_map()
263 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
264 return http_server_properties_impl_
->spdy_settings_map();
267 void HttpServerPropertiesManager::SetServerNetworkStats(
268 const net::HostPortPair
& host_port_pair
,
269 NetworkStats stats
) {
270 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
271 http_server_properties_impl_
->SetServerNetworkStats(host_port_pair
, stats
);
274 const HttpServerPropertiesManager::NetworkStats
*
275 HttpServerPropertiesManager::GetServerNetworkStats(
276 const net::HostPortPair
& host_port_pair
) const {
277 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
278 return http_server_properties_impl_
->GetServerNetworkStats(host_port_pair
);
282 // Update the HttpServerPropertiesImpl's cache with data from preferences.
284 void HttpServerPropertiesManager::ScheduleUpdateCacheOnPrefThread() {
285 DCHECK(pref_task_runner_
->RunsTasksOnCurrentThread());
286 // Cancel pending updates, if any.
287 pref_cache_update_timer_
->Stop();
288 StartCacheUpdateTimerOnPrefThread(
289 base::TimeDelta::FromMilliseconds(kUpdateCacheDelayMs
));
292 void HttpServerPropertiesManager::StartCacheUpdateTimerOnPrefThread(
293 base::TimeDelta delay
) {
294 DCHECK(pref_task_runner_
->RunsTasksOnCurrentThread());
295 pref_cache_update_timer_
->Start(
299 &HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread
);
302 void HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread() {
303 // The preferences can only be read on the pref thread.
304 DCHECK(pref_task_runner_
->RunsTasksOnCurrentThread());
306 if (!pref_service_
->HasPrefPath(path_
))
309 bool detected_corrupted_prefs
= false;
310 const base::DictionaryValue
& http_server_properties_dict
=
311 *pref_service_
->GetDictionary(path_
);
313 int version
= kMissingVersion
;
314 if (!http_server_properties_dict
.GetIntegerWithoutPathExpansion("version",
316 DVLOG(1) << "Missing version. Clearing all properties.";
320 // The properties for a given server is in
321 // http_server_properties_dict["servers"][server].
322 const base::DictionaryValue
* servers_dict
= NULL
;
323 if (!http_server_properties_dict
.GetDictionaryWithoutPathExpansion(
324 "servers", &servers_dict
)) {
325 DVLOG(1) << "Malformed http_server_properties for servers.";
329 // String is host/port pair of spdy server.
330 scoped_ptr
<StringVector
> spdy_servers(new StringVector
);
331 scoped_ptr
<net::SpdySettingsMap
> spdy_settings_map(
332 new net::SpdySettingsMap(kMaxSpdySettingsHostsToPersist
));
333 scoped_ptr
<net::AlternateProtocolMap
> alternate_protocol_map(
334 new net::AlternateProtocolMap(kMaxAlternateProtocolHostsToPersist
));
335 // TODO(rtenneti): Delete the following code after the experiment.
336 int alternate_protocols_to_load
= k200AlternateProtocolHostsToLoad
;
337 net::AlternateProtocolExperiment alternate_protocol_experiment
=
338 net::ALTERNATE_PROTOCOL_NOT_PART_OF_EXPERIMENT
;
339 if (version
== kVersionNumber
) {
340 if (base::RandInt(0, 99) == 0) {
341 alternate_protocol_experiment
=
342 net::ALTERNATE_PROTOCOL_TRUNCATED_200_SERVERS
;
344 alternate_protocols_to_load
= k1000AlternateProtocolHostsToLoad
;
345 alternate_protocol_experiment
=
346 net::ALTERNATE_PROTOCOL_TRUNCATED_1000_SERVERS
;
348 DVLOG(1) << "# of servers that support alternate_protocol: "
349 << alternate_protocols_to_load
;
353 for (base::DictionaryValue::Iterator
it(*servers_dict
); !it
.IsAtEnd();
355 // Get server's host/pair.
356 const std::string
& server_str
= it
.key();
357 net::HostPortPair server
= net::HostPortPair::FromString(server_str
);
358 if (server
.host().empty()) {
359 DVLOG(1) << "Malformed http_server_properties for server: " << server_str
;
360 detected_corrupted_prefs
= true;
364 const base::DictionaryValue
* server_pref_dict
= NULL
;
365 if (!it
.value().GetAsDictionary(&server_pref_dict
)) {
366 DVLOG(1) << "Malformed http_server_properties server: " << server_str
;
367 detected_corrupted_prefs
= true;
371 // Get if server supports Spdy.
372 bool supports_spdy
= false;
373 if ((server_pref_dict
->GetBoolean("supports_spdy", &supports_spdy
)) &&
375 spdy_servers
->push_back(server_str
);
379 DCHECK(spdy_settings_map
->Peek(server
) == spdy_settings_map
->end());
380 const base::DictionaryValue
* spdy_settings_dict
= NULL
;
381 if (server_pref_dict
->GetDictionaryWithoutPathExpansion(
382 "settings", &spdy_settings_dict
)) {
383 net::SettingsMap settings_map
;
384 for (base::DictionaryValue::Iterator
dict_it(*spdy_settings_dict
);
387 const std::string
& id_str
= dict_it
.key();
389 if (!base::StringToInt(id_str
, &id
)) {
390 DVLOG(1) << "Malformed id in SpdySettings for server: " << server_str
;
395 if (!dict_it
.value().GetAsInteger(&value
)) {
396 DVLOG(1) << "Malformed value in SpdySettings for server: "
401 net::SettingsFlagsAndValue
flags_and_value(net::SETTINGS_FLAG_PERSISTED
,
403 settings_map
[static_cast<net::SpdySettingsIds
>(id
)] = flags_and_value
;
405 spdy_settings_map
->Put(server
, settings_map
);
408 // Get alternate_protocol server.
409 DCHECK(alternate_protocol_map
->Peek(server
) ==
410 alternate_protocol_map
->end());
411 const base::DictionaryValue
* port_alternate_protocol_dict
= NULL
;
412 if (!server_pref_dict
->GetDictionaryWithoutPathExpansion(
413 "alternate_protocol", &port_alternate_protocol_dict
)) {
417 if (count
>= alternate_protocols_to_load
)
421 if (!port_alternate_protocol_dict
->GetIntegerWithoutPathExpansion(
423 (port
> (1 << 16))) {
424 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str
;
425 detected_corrupted_prefs
= true;
428 std::string protocol_str
;
429 if (!port_alternate_protocol_dict
->GetStringWithoutPathExpansion(
430 "protocol_str", &protocol_str
)) {
431 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str
;
432 detected_corrupted_prefs
= true;
435 net::AlternateProtocol protocol
=
436 net::AlternateProtocolFromString(protocol_str
);
437 if (!net::IsAlternateProtocolValid(protocol
)) {
438 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str
;
439 detected_corrupted_prefs
= true;
443 double probability
= 1;
444 if (port_alternate_protocol_dict
->HasKey("probability") &&
445 !port_alternate_protocol_dict
->GetDoubleWithoutPathExpansion(
446 "probability", &probability
)) {
447 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str
;
448 detected_corrupted_prefs
= true;
452 net::AlternateProtocolInfo
port_alternate_protocol(port
,
455 alternate_protocol_map
->Put(server
, port_alternate_protocol
);
460 network_task_runner_
->PostTask(
463 &HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread
,
464 base::Unretained(this),
465 base::Owned(spdy_servers
.release()),
466 base::Owned(spdy_settings_map
.release()),
467 base::Owned(alternate_protocol_map
.release()),
468 alternate_protocol_experiment
,
469 detected_corrupted_prefs
));
472 void HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread(
473 StringVector
* spdy_servers
,
474 net::SpdySettingsMap
* spdy_settings_map
,
475 net::AlternateProtocolMap
* alternate_protocol_map
,
476 net::AlternateProtocolExperiment alternate_protocol_experiment
,
477 bool detected_corrupted_prefs
) {
478 // Preferences have the master data because admins might have pushed new
479 // preferences. Update the cached data with new data from preferences.
480 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
482 UMA_HISTOGRAM_COUNTS("Net.CountOfSpdyServers", spdy_servers
->size());
483 http_server_properties_impl_
->InitializeSpdyServers(spdy_servers
, true);
485 // Update the cached data and use the new spdy_settings from preferences.
486 UMA_HISTOGRAM_COUNTS("Net.CountOfSpdySettings", spdy_settings_map
->size());
487 http_server_properties_impl_
->InitializeSpdySettingsServers(
490 // Update the cached data and use the new Alternate-Protocol server list from
492 UMA_HISTOGRAM_COUNTS("Net.CountOfAlternateProtocolServers",
493 alternate_protocol_map
->size());
494 http_server_properties_impl_
->InitializeAlternateProtocolServers(
495 alternate_protocol_map
);
496 http_server_properties_impl_
->SetAlternateProtocolExperiment(
497 alternate_protocol_experiment
);
499 // Update the prefs with what we have read (delete all corrupted prefs).
500 if (detected_corrupted_prefs
)
501 ScheduleUpdatePrefsOnNetworkThread();
505 // Update Preferences with data from the cached data.
507 void HttpServerPropertiesManager::ScheduleUpdatePrefsOnNetworkThread() {
508 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
509 // Cancel pending updates, if any.
510 network_prefs_update_timer_
->Stop();
511 StartPrefsUpdateTimerOnNetworkThread(
512 base::TimeDelta::FromMilliseconds(kUpdatePrefsDelayMs
));
515 void HttpServerPropertiesManager::StartPrefsUpdateTimerOnNetworkThread(
516 base::TimeDelta delay
) {
517 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
518 // This is overridden in tests to post the task without the delay.
519 network_prefs_update_timer_
->Start(
523 &HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread
);
526 // This is required so we can set this as the callback for a timer.
527 void HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread() {
528 UpdatePrefsFromCacheOnNetworkThread(base::Closure());
531 void HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread(
532 const base::Closure
& completion
) {
533 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
535 base::ListValue
* spdy_server_list
= new base::ListValue
;
536 http_server_properties_impl_
->GetSpdyServerList(
537 spdy_server_list
, kMaxSupportsSpdyServerHostsToPersist
);
539 net::SpdySettingsMap
* spdy_settings_map
=
540 new net::SpdySettingsMap(kMaxSpdySettingsHostsToPersist
);
541 const net::SpdySettingsMap
& main_map
=
542 http_server_properties_impl_
->spdy_settings_map();
544 for (net::SpdySettingsMap::const_iterator it
= main_map
.begin();
545 it
!= main_map
.end() && count
< kMaxSpdySettingsHostsToPersist
;
547 spdy_settings_map
->Put(it
->first
, it
->second
);
550 net::AlternateProtocolMap
* alternate_protocol_map
=
551 new net::AlternateProtocolMap(kMaxAlternateProtocolHostsToPersist
);
552 const net::AlternateProtocolMap
& map
=
553 http_server_properties_impl_
->alternate_protocol_map();
555 typedef std::map
<std::string
, bool> CanonicalHostPersistedMap
;
556 CanonicalHostPersistedMap persisted_map
;
557 for (net::AlternateProtocolMap::const_iterator it
= map
.begin();
558 it
!= map
.end() && count
< kMaxAlternateProtocolHostsToPersist
;
560 const net::HostPortPair
& server
= it
->first
;
561 std::string canonical_suffix
=
562 http_server_properties_impl_
->GetCanonicalSuffix(server
);
563 if (!canonical_suffix
.empty()) {
564 if (persisted_map
.find(canonical_suffix
) != persisted_map
.end())
566 persisted_map
[canonical_suffix
] = true;
568 alternate_protocol_map
->Put(server
, it
->second
);
572 // Update the preferences on the pref thread.
573 pref_task_runner_
->PostTask(
575 base::Bind(&HttpServerPropertiesManager::UpdatePrefsOnPrefThread
,
577 base::Owned(spdy_server_list
),
578 base::Owned(spdy_settings_map
),
579 base::Owned(alternate_protocol_map
),
583 // A local or temporary data structure to hold |supports_spdy|, SpdySettings,
584 // and AlternateProtocolInfo preferences for a server. This is used only in
585 // UpdatePrefsOnPrefThread.
588 : supports_spdy(false), settings_map(NULL
), alternate_protocol(NULL
) {}
589 ServerPref(bool supports_spdy
,
590 const net::SettingsMap
* settings_map
,
591 const net::AlternateProtocolInfo
* alternate_protocol
)
592 : supports_spdy(supports_spdy
),
593 settings_map(settings_map
),
594 alternate_protocol(alternate_protocol
) {}
596 const net::SettingsMap
* settings_map
;
597 const net::AlternateProtocolInfo
* alternate_protocol
;
600 void HttpServerPropertiesManager::UpdatePrefsOnPrefThread(
601 base::ListValue
* spdy_server_list
,
602 net::SpdySettingsMap
* spdy_settings_map
,
603 net::AlternateProtocolMap
* alternate_protocol_map
,
604 const base::Closure
& completion
) {
605 typedef std::map
<net::HostPortPair
, ServerPref
> ServerPrefMap
;
606 ServerPrefMap server_pref_map
;
608 DCHECK(pref_task_runner_
->RunsTasksOnCurrentThread());
610 // Add servers that support spdy to server_pref_map.
612 for (base::ListValue::const_iterator list_it
= spdy_server_list
->begin();
613 list_it
!= spdy_server_list
->end();
615 if ((*list_it
)->GetAsString(&s
)) {
616 net::HostPortPair server
= net::HostPortPair::FromString(s
);
618 ServerPrefMap::iterator it
= server_pref_map
.find(server
);
619 if (it
== server_pref_map
.end()) {
620 ServerPref
server_pref(true, NULL
, NULL
);
621 server_pref_map
[server
] = server_pref
;
623 it
->second
.supports_spdy
= true;
628 // Add servers that have SpdySettings to server_pref_map.
629 for (net::SpdySettingsMap::iterator map_it
= spdy_settings_map
->begin();
630 map_it
!= spdy_settings_map
->end();
632 const net::HostPortPair
& server
= map_it
->first
;
634 ServerPrefMap::iterator it
= server_pref_map
.find(server
);
635 if (it
== server_pref_map
.end()) {
636 ServerPref
server_pref(false, &map_it
->second
, NULL
);
637 server_pref_map
[server
] = server_pref
;
639 it
->second
.settings_map
= &map_it
->second
;
643 // Add AlternateProtocol servers to server_pref_map.
644 for (net::AlternateProtocolMap::const_iterator map_it
=
645 alternate_protocol_map
->begin();
646 map_it
!= alternate_protocol_map
->end();
648 const net::HostPortPair
& server
= map_it
->first
;
649 const net::AlternateProtocolInfo
& port_alternate_protocol
=
651 if (!net::IsAlternateProtocolValid(port_alternate_protocol
.protocol
)) {
655 ServerPrefMap::iterator it
= server_pref_map
.find(server
);
656 if (it
== server_pref_map
.end()) {
657 ServerPref
server_pref(false, NULL
, &map_it
->second
);
658 server_pref_map
[server
] = server_pref
;
660 it
->second
.alternate_protocol
= &map_it
->second
;
664 // Persist properties to the |path_|.
665 base::DictionaryValue http_server_properties_dict
;
666 base::DictionaryValue
* servers_dict
= new base::DictionaryValue
;
667 for (ServerPrefMap::const_iterator map_it
= server_pref_map
.begin();
668 map_it
!= server_pref_map
.end();
670 const net::HostPortPair
& server
= map_it
->first
;
671 const ServerPref
& server_pref
= map_it
->second
;
673 base::DictionaryValue
* server_pref_dict
= new base::DictionaryValue
;
675 // Save supports_spdy.
676 if (server_pref
.supports_spdy
)
677 server_pref_dict
->SetBoolean("supports_spdy", server_pref
.supports_spdy
);
679 // Save SPDY settings.
680 if (server_pref
.settings_map
) {
681 base::DictionaryValue
* spdy_settings_dict
= new base::DictionaryValue
;
682 for (net::SettingsMap::const_iterator it
=
683 server_pref
.settings_map
->begin();
684 it
!= server_pref
.settings_map
->end();
686 net::SpdySettingsIds id
= it
->first
;
687 uint32 value
= it
->second
.second
;
688 std::string key
= base::StringPrintf("%u", id
);
689 spdy_settings_dict
->SetInteger(key
, value
);
691 server_pref_dict
->SetWithoutPathExpansion("settings", spdy_settings_dict
);
694 // Save alternate_protocol.
695 if (server_pref
.alternate_protocol
) {
696 base::DictionaryValue
* port_alternate_protocol_dict
=
697 new base::DictionaryValue
;
698 const net::AlternateProtocolInfo
* port_alternate_protocol
=
699 server_pref
.alternate_protocol
;
700 port_alternate_protocol_dict
->SetInteger("port",
701 port_alternate_protocol
->port
);
702 const char* protocol_str
=
703 net::AlternateProtocolToString(port_alternate_protocol
->protocol
);
704 port_alternate_protocol_dict
->SetString("protocol_str", protocol_str
);
705 port_alternate_protocol_dict
->SetDouble(
706 "probability", port_alternate_protocol
->probability
);
707 server_pref_dict
->SetWithoutPathExpansion(
708 "alternate_protocol", port_alternate_protocol_dict
);
711 servers_dict
->SetWithoutPathExpansion(server
.ToString(), server_pref_dict
);
714 http_server_properties_dict
.SetWithoutPathExpansion("servers", servers_dict
);
715 SetVersion(&http_server_properties_dict
, kVersionNumber
);
716 setting_prefs_
= true;
717 pref_service_
->Set(path_
, http_server_properties_dict
);
718 setting_prefs_
= false;
720 // Note that |completion| will be fired after we have written everything to
721 // the Preferences, but likely before these changes are serialized to disk.
722 // This is not a problem though, as JSONPrefStore guarantees that this will
723 // happen, pretty soon, and even in the case we shut down immediately.
724 if (!completion
.is_null())
728 void HttpServerPropertiesManager::OnHttpServerPropertiesChanged() {
729 DCHECK(pref_task_runner_
->RunsTasksOnCurrentThread());
731 ScheduleUpdateCacheOnPrefThread();