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/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"
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 // 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;
52 ////////////////////////////////////////////////////////////////////////////////
53 // HttpServerPropertiesManager
55 HttpServerPropertiesManager::HttpServerPropertiesManager(
56 PrefService
* pref_service
,
57 const char* pref_path
,
58 scoped_refptr
<base::SequencedTaskRunner
> network_task_runner
)
59 : pref_task_runner_(base::ThreadTaskRunnerHandle::Get()),
60 pref_service_(pref_service
),
61 setting_prefs_(false),
63 network_task_runner_(network_task_runner
) {
65 pref_weak_ptr_factory_
.reset(
66 new base::WeakPtrFactory
<HttpServerPropertiesManager
>(this));
67 pref_weak_ptr_
= pref_weak_ptr_factory_
->GetWeakPtr();
68 pref_cache_update_timer_
.reset(
69 new base::OneShotTimer
<HttpServerPropertiesManager
>);
70 pref_change_registrar_
.Init(pref_service_
);
71 pref_change_registrar_
.Add(
73 base::Bind(&HttpServerPropertiesManager::OnHttpServerPropertiesChanged
,
74 base::Unretained(this)));
77 HttpServerPropertiesManager::~HttpServerPropertiesManager() {
78 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
79 network_weak_ptr_factory_
.reset();
82 void HttpServerPropertiesManager::InitializeOnNetworkThread() {
83 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
84 network_weak_ptr_factory_
.reset(
85 new base::WeakPtrFactory
<HttpServerPropertiesManager
>(this));
86 http_server_properties_impl_
.reset(new net::HttpServerPropertiesImpl());
88 network_prefs_update_timer_
.reset(
89 new base::OneShotTimer
<HttpServerPropertiesManager
>);
91 pref_task_runner_
->PostTask(
93 base::Bind(&HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread
,
97 void HttpServerPropertiesManager::ShutdownOnPrefThread() {
98 DCHECK(pref_task_runner_
->RunsTasksOnCurrentThread());
99 // Cancel any pending updates, and stop listening for pref change updates.
100 pref_cache_update_timer_
->Stop();
101 pref_weak_ptr_factory_
.reset();
102 pref_change_registrar_
.RemoveAll();
106 void HttpServerPropertiesManager::SetVersion(
107 base::DictionaryValue
* http_server_properties_dict
,
108 int version_number
) {
109 if (version_number
< 0)
110 version_number
= kVersionNumber
;
111 DCHECK_LE(version_number
, kVersionNumber
);
112 if (version_number
<= kVersionNumber
)
113 http_server_properties_dict
->SetInteger("version", version_number
);
116 // This is required for conformance with the HttpServerProperties interface.
117 base::WeakPtr
<net::HttpServerProperties
>
118 HttpServerPropertiesManager::GetWeakPtr() {
119 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
120 return network_weak_ptr_factory_
->GetWeakPtr();
123 void HttpServerPropertiesManager::Clear() {
124 Clear(base::Closure());
127 void HttpServerPropertiesManager::Clear(const base::Closure
& completion
) {
128 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
130 http_server_properties_impl_
->Clear();
131 UpdatePrefsFromCacheOnNetworkThread(completion
);
134 bool HttpServerPropertiesManager::SupportsSpdy(
135 const net::HostPortPair
& server
) {
136 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
137 return http_server_properties_impl_
->SupportsSpdy(server
);
140 void HttpServerPropertiesManager::SetSupportsSpdy(
141 const net::HostPortPair
& server
,
143 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
145 http_server_properties_impl_
->SetSupportsSpdy(server
, support_spdy
);
146 ScheduleUpdatePrefsOnNetworkThread();
149 bool HttpServerPropertiesManager::HasAlternateProtocol(
150 const net::HostPortPair
& server
) {
151 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
152 return http_server_properties_impl_
->HasAlternateProtocol(server
);
155 net::AlternateProtocolInfo
156 HttpServerPropertiesManager::GetAlternateProtocol(
157 const net::HostPortPair
& server
) {
158 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
159 return http_server_properties_impl_
->GetAlternateProtocol(server
);
162 void HttpServerPropertiesManager::SetAlternateProtocol(
163 const net::HostPortPair
& server
,
164 uint16 alternate_port
,
165 AlternateProtocol alternate_protocol
,
166 double alternate_probability
) {
167 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
168 http_server_properties_impl_
->SetAlternateProtocol(
169 server
, alternate_port
, alternate_protocol
, alternate_probability
);
170 ScheduleUpdatePrefsOnNetworkThread();
173 void HttpServerPropertiesManager::SetBrokenAlternateProtocol(
174 const net::HostPortPair
& server
) {
175 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
176 http_server_properties_impl_
->SetBrokenAlternateProtocol(server
);
177 ScheduleUpdatePrefsOnNetworkThread();
180 bool HttpServerPropertiesManager::WasAlternateProtocolRecentlyBroken(
181 const net::HostPortPair
& server
) {
182 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
183 return http_server_properties_impl_
->WasAlternateProtocolRecentlyBroken(
187 void HttpServerPropertiesManager::ConfirmAlternateProtocol(
188 const net::HostPortPair
& server
) {
189 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
190 http_server_properties_impl_
->ConfirmAlternateProtocol(server
);
191 ScheduleUpdatePrefsOnNetworkThread();
194 void HttpServerPropertiesManager::ClearAlternateProtocol(
195 const net::HostPortPair
& server
) {
196 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
197 http_server_properties_impl_
->ClearAlternateProtocol(server
);
198 ScheduleUpdatePrefsOnNetworkThread();
201 const net::AlternateProtocolMap
&
202 HttpServerPropertiesManager::alternate_protocol_map() const {
203 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
204 return http_server_properties_impl_
->alternate_protocol_map();
207 void HttpServerPropertiesManager::SetAlternateProtocolProbabilityThreshold(
209 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
210 http_server_properties_impl_
->SetAlternateProtocolProbabilityThreshold(
214 const SettingsMap
& HttpServerPropertiesManager::GetSpdySettings(
215 const HostPortPair
& host_port_pair
) {
216 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
217 return http_server_properties_impl_
->GetSpdySettings(host_port_pair
);
220 bool HttpServerPropertiesManager::SetSpdySetting(
221 const HostPortPair
& host_port_pair
,
223 SpdySettingsFlags flags
,
225 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
226 bool persist
= http_server_properties_impl_
->SetSpdySetting(
227 host_port_pair
, id
, flags
, value
);
229 ScheduleUpdatePrefsOnNetworkThread();
233 void HttpServerPropertiesManager::ClearSpdySettings(
234 const HostPortPair
& host_port_pair
) {
235 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
236 http_server_properties_impl_
->ClearSpdySettings(host_port_pair
);
237 ScheduleUpdatePrefsOnNetworkThread();
240 void HttpServerPropertiesManager::ClearAllSpdySettings() {
241 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
242 http_server_properties_impl_
->ClearAllSpdySettings();
243 ScheduleUpdatePrefsOnNetworkThread();
246 const SpdySettingsMap
& HttpServerPropertiesManager::spdy_settings_map()
248 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
249 return http_server_properties_impl_
->spdy_settings_map();
253 HttpServerPropertiesManager::GetSupportsQuic(
254 const net::HostPortPair
& host_port_pair
) const {
255 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
256 return http_server_properties_impl_
->GetSupportsQuic(host_port_pair
);
259 void HttpServerPropertiesManager::SetSupportsQuic(
260 const net::HostPortPair
& host_port_pair
,
262 const std::string
& address
) {
263 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
264 http_server_properties_impl_
->SetSupportsQuic(
265 host_port_pair
, used_quic
, address
);
266 ScheduleUpdatePrefsOnNetworkThread();
269 const SupportsQuicMap
& HttpServerPropertiesManager::supports_quic_map()
271 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
272 return http_server_properties_impl_
->supports_quic_map();
275 void HttpServerPropertiesManager::SetServerNetworkStats(
276 const net::HostPortPair
& host_port_pair
,
277 NetworkStats stats
) {
278 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
279 http_server_properties_impl_
->SetServerNetworkStats(host_port_pair
, stats
);
282 const HttpServerPropertiesManager::NetworkStats
*
283 HttpServerPropertiesManager::GetServerNetworkStats(
284 const net::HostPortPair
& host_port_pair
) const {
285 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
286 return http_server_properties_impl_
->GetServerNetworkStats(host_port_pair
);
290 // Update the HttpServerPropertiesImpl's cache with data from preferences.
292 void HttpServerPropertiesManager::ScheduleUpdateCacheOnPrefThread() {
293 DCHECK(pref_task_runner_
->RunsTasksOnCurrentThread());
294 // Cancel pending updates, if any.
295 pref_cache_update_timer_
->Stop();
296 StartCacheUpdateTimerOnPrefThread(
297 base::TimeDelta::FromMilliseconds(kUpdateCacheDelayMs
));
300 void HttpServerPropertiesManager::StartCacheUpdateTimerOnPrefThread(
301 base::TimeDelta delay
) {
302 DCHECK(pref_task_runner_
->RunsTasksOnCurrentThread());
303 pref_cache_update_timer_
->Start(
307 &HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread
);
310 void HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread() {
311 // The preferences can only be read on the pref thread.
312 DCHECK(pref_task_runner_
->RunsTasksOnCurrentThread());
314 if (!pref_service_
->HasPrefPath(path_
))
317 bool detected_corrupted_prefs
= false;
318 const base::DictionaryValue
& http_server_properties_dict
=
319 *pref_service_
->GetDictionary(path_
);
321 int version
= kMissingVersion
;
322 if (!http_server_properties_dict
.GetIntegerWithoutPathExpansion("version",
324 DVLOG(1) << "Missing version. Clearing all properties.";
328 // The properties for a given server is in
329 // http_server_properties_dict["servers"][server].
330 const base::DictionaryValue
* servers_dict
= NULL
;
331 if (!http_server_properties_dict
.GetDictionaryWithoutPathExpansion(
332 "servers", &servers_dict
)) {
333 DVLOG(1) << "Malformed http_server_properties for servers.";
337 // String is host/port pair of spdy server.
338 scoped_ptr
<StringVector
> spdy_servers(new StringVector
);
339 scoped_ptr
<net::SpdySettingsMap
> spdy_settings_map(
340 new net::SpdySettingsMap(kMaxSpdySettingsHostsToPersist
));
341 scoped_ptr
<net::AlternateProtocolMap
> alternate_protocol_map(
342 new net::AlternateProtocolMap(kMaxAlternateProtocolHostsToPersist
));
343 scoped_ptr
<net::SupportsQuicMap
> supports_quic_map(
344 new net::SupportsQuicMap());
347 for (base::DictionaryValue::Iterator
it(*servers_dict
); !it
.IsAtEnd();
349 // Get server's host/pair.
350 const std::string
& server_str
= it
.key();
351 net::HostPortPair server
= net::HostPortPair::FromString(server_str
);
352 if (server
.host().empty()) {
353 DVLOG(1) << "Malformed http_server_properties for server: " << server_str
;
354 detected_corrupted_prefs
= true;
358 const base::DictionaryValue
* server_pref_dict
= NULL
;
359 if (!it
.value().GetAsDictionary(&server_pref_dict
)) {
360 DVLOG(1) << "Malformed http_server_properties server: " << server_str
;
361 detected_corrupted_prefs
= true;
365 // Get if server supports Spdy.
366 bool supports_spdy
= false;
367 if ((server_pref_dict
->GetBoolean("supports_spdy", &supports_spdy
)) &&
369 spdy_servers
->push_back(server_str
);
373 DCHECK(spdy_settings_map
->Peek(server
) == spdy_settings_map
->end());
374 const base::DictionaryValue
* spdy_settings_dict
= NULL
;
375 if (server_pref_dict
->GetDictionaryWithoutPathExpansion(
376 "settings", &spdy_settings_dict
)) {
377 net::SettingsMap settings_map
;
378 for (base::DictionaryValue::Iterator
dict_it(*spdy_settings_dict
);
381 const std::string
& id_str
= dict_it
.key();
383 if (!base::StringToInt(id_str
, &id
)) {
384 DVLOG(1) << "Malformed id in SpdySettings for server: " << server_str
;
389 if (!dict_it
.value().GetAsInteger(&value
)) {
390 DVLOG(1) << "Malformed value in SpdySettings for server: "
395 net::SettingsFlagsAndValue
flags_and_value(net::SETTINGS_FLAG_PERSISTED
,
397 settings_map
[static_cast<net::SpdySettingsIds
>(id
)] = flags_and_value
;
399 spdy_settings_map
->Put(server
, settings_map
);
402 // Get alternate_protocol server.
403 DCHECK(alternate_protocol_map
->Peek(server
) ==
404 alternate_protocol_map
->end());
405 const base::DictionaryValue
* port_alternate_protocol_dict
= NULL
;
406 if (!server_pref_dict
->GetDictionaryWithoutPathExpansion(
407 "alternate_protocol", &port_alternate_protocol_dict
)) {
411 if (count
>= kMaxAlternateProtocolHostsToPersist
)
415 if (!port_alternate_protocol_dict
->GetIntegerWithoutPathExpansion(
417 !IsPortValid(port
)) {
418 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str
;
419 detected_corrupted_prefs
= true;
422 std::string protocol_str
;
423 if (!port_alternate_protocol_dict
->GetStringWithoutPathExpansion(
424 "protocol_str", &protocol_str
)) {
425 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str
;
426 detected_corrupted_prefs
= true;
429 net::AlternateProtocol protocol
=
430 net::AlternateProtocolFromString(protocol_str
);
431 if (!net::IsAlternateProtocolValid(protocol
)) {
432 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str
;
433 detected_corrupted_prefs
= true;
437 double probability
= 1;
438 if (port_alternate_protocol_dict
->HasKey("probability") &&
439 !port_alternate_protocol_dict
->GetDoubleWithoutPathExpansion(
440 "probability", &probability
)) {
441 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str
;
442 detected_corrupted_prefs
= true;
446 net::AlternateProtocolInfo
port_alternate_protocol(
447 static_cast<uint16
>(port
), protocol
, probability
);
448 alternate_protocol_map
->Put(server
, port_alternate_protocol
);
453 DCHECK(supports_quic_map
->find(server
) == supports_quic_map
->end());
454 const base::DictionaryValue
* supports_quic_dict
= NULL
;
455 if (!server_pref_dict
->GetDictionaryWithoutPathExpansion(
456 "supports_quic", &supports_quic_dict
)) {
461 if (!supports_quic_dict
->GetBooleanWithoutPathExpansion(
462 "used_quic", &used_quic
)) {
463 DVLOG(1) << "Malformed SupportsQuic server: " << server_str
;
464 detected_corrupted_prefs
= true;
468 if (!supports_quic_dict
->GetStringWithoutPathExpansion(
469 "address", &address
)) {
470 DVLOG(1) << "Malformed SupportsQuic server: " << server_str
;
471 detected_corrupted_prefs
= true;
474 net::SupportsQuic
supports_quic(used_quic
, address
);
475 supports_quic_map
->insert(std::make_pair(server
, supports_quic
));
479 network_task_runner_
->PostTask(
482 &HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread
,
483 base::Unretained(this),
484 base::Owned(spdy_servers
.release()),
485 base::Owned(spdy_settings_map
.release()),
486 base::Owned(alternate_protocol_map
.release()),
487 base::Owned(supports_quic_map
.release()),
488 detected_corrupted_prefs
));
491 void HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread(
492 StringVector
* spdy_servers
,
493 net::SpdySettingsMap
* spdy_settings_map
,
494 net::AlternateProtocolMap
* alternate_protocol_map
,
495 net::SupportsQuicMap
* supports_quic_map
,
496 bool detected_corrupted_prefs
) {
497 // Preferences have the master data because admins might have pushed new
498 // preferences. Update the cached data with new data from preferences.
499 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
501 UMA_HISTOGRAM_COUNTS("Net.CountOfSpdyServers", spdy_servers
->size());
502 http_server_properties_impl_
->InitializeSpdyServers(spdy_servers
, true);
504 // Update the cached data and use the new spdy_settings from preferences.
505 UMA_HISTOGRAM_COUNTS("Net.CountOfSpdySettings", spdy_settings_map
->size());
506 http_server_properties_impl_
->InitializeSpdySettingsServers(
509 // Update the cached data and use the new Alternate-Protocol server list from
511 UMA_HISTOGRAM_COUNTS("Net.CountOfAlternateProtocolServers",
512 alternate_protocol_map
->size());
513 http_server_properties_impl_
->InitializeAlternateProtocolServers(
514 alternate_protocol_map
);
516 http_server_properties_impl_
->InitializeSupportsQuic(supports_quic_map
);
518 // Update the prefs with what we have read (delete all corrupted prefs).
519 if (detected_corrupted_prefs
)
520 ScheduleUpdatePrefsOnNetworkThread();
524 // Update Preferences with data from the cached data.
526 void HttpServerPropertiesManager::ScheduleUpdatePrefsOnNetworkThread() {
527 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
528 // Cancel pending updates, if any.
529 network_prefs_update_timer_
->Stop();
530 StartPrefsUpdateTimerOnNetworkThread(
531 base::TimeDelta::FromMilliseconds(kUpdatePrefsDelayMs
));
534 void HttpServerPropertiesManager::StartPrefsUpdateTimerOnNetworkThread(
535 base::TimeDelta delay
) {
536 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
537 // This is overridden in tests to post the task without the delay.
538 network_prefs_update_timer_
->Start(
542 &HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread
);
545 // This is required so we can set this as the callback for a timer.
546 void HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread() {
547 UpdatePrefsFromCacheOnNetworkThread(base::Closure());
550 void HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread(
551 const base::Closure
& completion
) {
552 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
554 base::ListValue
* spdy_server_list
= new base::ListValue
;
555 http_server_properties_impl_
->GetSpdyServerList(
556 spdy_server_list
, kMaxSupportsSpdyServerHostsToPersist
);
558 net::SpdySettingsMap
* spdy_settings_map
=
559 new net::SpdySettingsMap(kMaxSpdySettingsHostsToPersist
);
560 const net::SpdySettingsMap
& main_map
=
561 http_server_properties_impl_
->spdy_settings_map();
563 for (net::SpdySettingsMap::const_iterator it
= main_map
.begin();
564 it
!= main_map
.end() && count
< kMaxSpdySettingsHostsToPersist
;
566 spdy_settings_map
->Put(it
->first
, it
->second
);
569 net::AlternateProtocolMap
* alternate_protocol_map
=
570 new net::AlternateProtocolMap(kMaxAlternateProtocolHostsToPersist
);
571 const net::AlternateProtocolMap
& map
=
572 http_server_properties_impl_
->alternate_protocol_map();
574 typedef std::map
<std::string
, bool> CanonicalHostPersistedMap
;
575 CanonicalHostPersistedMap persisted_map
;
576 for (net::AlternateProtocolMap::const_iterator it
= map
.begin();
577 it
!= map
.end() && count
< kMaxAlternateProtocolHostsToPersist
;
579 const net::HostPortPair
& server
= it
->first
;
580 std::string canonical_suffix
=
581 http_server_properties_impl_
->GetCanonicalSuffix(server
);
582 if (!canonical_suffix
.empty()) {
583 if (persisted_map
.find(canonical_suffix
) != persisted_map
.end())
585 persisted_map
[canonical_suffix
] = true;
587 alternate_protocol_map
->Put(server
, it
->second
);
591 net::SupportsQuicMap
* supports_quic_map
= new net::SupportsQuicMap();
592 const net::SupportsQuicMap
& main_supports_quic_map
=
593 http_server_properties_impl_
->supports_quic_map();
594 for (net::SupportsQuicMap::const_iterator it
= main_supports_quic_map
.begin();
595 it
!= main_supports_quic_map
.end(); ++it
) {
596 supports_quic_map
->insert(std::make_pair(it
->first
, it
->second
));
599 // Update the preferences on the pref thread.
600 pref_task_runner_
->PostTask(
602 base::Bind(&HttpServerPropertiesManager::UpdatePrefsOnPrefThread
,
604 base::Owned(spdy_server_list
),
605 base::Owned(spdy_settings_map
),
606 base::Owned(alternate_protocol_map
),
607 base::Owned(supports_quic_map
),
611 // A local or temporary data structure to hold |supports_spdy|, SpdySettings,
612 // AlternateProtocolInfo and SupportsQuic preferences for a server. This is used
613 // only in UpdatePrefsOnPrefThread.
615 ServerPref() : supports_spdy(false),
617 alternate_protocol(NULL
),
618 supports_quic(NULL
) {}
619 ServerPref(bool supports_spdy
,
620 const net::SettingsMap
* settings_map
,
621 const net::AlternateProtocolInfo
* alternate_protocol
,
622 const net::SupportsQuic
* supports_quic
)
623 : supports_spdy(supports_spdy
),
624 settings_map(settings_map
),
625 alternate_protocol(alternate_protocol
),
626 supports_quic(supports_quic
) {}
628 const net::SettingsMap
* settings_map
;
629 const net::AlternateProtocolInfo
* alternate_protocol
;
630 const net::SupportsQuic
* supports_quic
;
633 void HttpServerPropertiesManager::UpdatePrefsOnPrefThread(
634 base::ListValue
* spdy_server_list
,
635 net::SpdySettingsMap
* spdy_settings_map
,
636 net::AlternateProtocolMap
* alternate_protocol_map
,
637 net::SupportsQuicMap
* supports_quic_map
,
638 const base::Closure
& completion
) {
639 typedef std::map
<net::HostPortPair
, ServerPref
> ServerPrefMap
;
640 ServerPrefMap server_pref_map
;
642 DCHECK(pref_task_runner_
->RunsTasksOnCurrentThread());
644 // Add servers that support spdy to server_pref_map.
646 for (base::ListValue::const_iterator list_it
= spdy_server_list
->begin();
647 list_it
!= spdy_server_list
->end();
649 if ((*list_it
)->GetAsString(&s
)) {
650 net::HostPortPair server
= net::HostPortPair::FromString(s
);
652 ServerPrefMap::iterator it
= server_pref_map
.find(server
);
653 if (it
== server_pref_map
.end()) {
654 ServerPref
server_pref(true, NULL
, NULL
, NULL
);
655 server_pref_map
[server
] = server_pref
;
657 it
->second
.supports_spdy
= true;
662 // Add servers that have SpdySettings to server_pref_map.
663 for (net::SpdySettingsMap::iterator map_it
= spdy_settings_map
->begin();
664 map_it
!= spdy_settings_map
->end();
666 const net::HostPortPair
& server
= map_it
->first
;
668 ServerPrefMap::iterator it
= server_pref_map
.find(server
);
669 if (it
== server_pref_map
.end()) {
670 ServerPref
server_pref(false, &map_it
->second
, NULL
, NULL
);
671 server_pref_map
[server
] = server_pref
;
673 it
->second
.settings_map
= &map_it
->second
;
677 // Add AlternateProtocol servers to server_pref_map.
678 for (net::AlternateProtocolMap::const_iterator map_it
=
679 alternate_protocol_map
->begin();
680 map_it
!= alternate_protocol_map
->end();
682 const net::HostPortPair
& server
= map_it
->first
;
683 const net::AlternateProtocolInfo
& port_alternate_protocol
=
685 if (!net::IsAlternateProtocolValid(port_alternate_protocol
.protocol
)) {
689 ServerPrefMap::iterator it
= server_pref_map
.find(server
);
690 if (it
== server_pref_map
.end()) {
691 ServerPref
server_pref(false, NULL
, &map_it
->second
, NULL
);
692 server_pref_map
[server
] = server_pref
;
694 it
->second
.alternate_protocol
= &map_it
->second
;
698 // Add SupportsQuic servers to server_pref_map.
699 for (net::SupportsQuicMap::const_iterator map_it
= supports_quic_map
->begin();
700 map_it
!= supports_quic_map
->end(); ++map_it
) {
701 const net::HostPortPair
& server
= map_it
->first
;
703 ServerPrefMap::iterator it
= server_pref_map
.find(server
);
704 if (it
== server_pref_map
.end()) {
705 ServerPref
server_pref(false, NULL
, NULL
, &map_it
->second
);
706 server_pref_map
[server
] = server_pref
;
708 it
->second
.supports_quic
= &map_it
->second
;
712 // Persist properties to the |path_|.
713 base::DictionaryValue http_server_properties_dict
;
714 base::DictionaryValue
* servers_dict
= new base::DictionaryValue
;
715 for (ServerPrefMap::const_iterator map_it
= server_pref_map
.begin();
716 map_it
!= server_pref_map
.end();
718 const net::HostPortPair
& server
= map_it
->first
;
719 const ServerPref
& server_pref
= map_it
->second
;
721 base::DictionaryValue
* server_pref_dict
= new base::DictionaryValue
;
723 // Save supports_spdy.
724 if (server_pref
.supports_spdy
)
725 server_pref_dict
->SetBoolean("supports_spdy", server_pref
.supports_spdy
);
727 // Save SPDY settings.
728 if (server_pref
.settings_map
) {
729 base::DictionaryValue
* spdy_settings_dict
= new base::DictionaryValue
;
730 for (net::SettingsMap::const_iterator it
=
731 server_pref
.settings_map
->begin();
732 it
!= server_pref
.settings_map
->end();
734 net::SpdySettingsIds id
= it
->first
;
735 uint32 value
= it
->second
.second
;
736 std::string key
= base::StringPrintf("%u", id
);
737 spdy_settings_dict
->SetInteger(key
, value
);
739 server_pref_dict
->SetWithoutPathExpansion("settings", spdy_settings_dict
);
742 // Save alternate_protocol.
743 const net::AlternateProtocolInfo
* port_alternate_protocol
=
744 server_pref
.alternate_protocol
;
745 if (port_alternate_protocol
&& !port_alternate_protocol
->is_broken
) {
746 base::DictionaryValue
* port_alternate_protocol_dict
=
747 new base::DictionaryValue
;
748 port_alternate_protocol_dict
->SetInteger("port",
749 port_alternate_protocol
->port
);
750 const char* protocol_str
=
751 net::AlternateProtocolToString(port_alternate_protocol
->protocol
);
752 port_alternate_protocol_dict
->SetString("protocol_str", protocol_str
);
753 port_alternate_protocol_dict
->SetDouble(
754 "probability", port_alternate_protocol
->probability
);
755 server_pref_dict
->SetWithoutPathExpansion(
756 "alternate_protocol", port_alternate_protocol_dict
);
759 // Save supports_quic.
760 if (server_pref
.supports_quic
) {
761 base::DictionaryValue
* supports_quic_dict
= new base::DictionaryValue
;
762 const net::SupportsQuic
* supports_quic
= server_pref
.supports_quic
;
763 supports_quic_dict
->SetBoolean("used_quic", supports_quic
->used_quic
);
764 supports_quic_dict
->SetString("address", supports_quic
->address
);
765 server_pref_dict
->SetWithoutPathExpansion(
766 "supports_quic", supports_quic_dict
);
769 servers_dict
->SetWithoutPathExpansion(server
.ToString(), server_pref_dict
);
772 http_server_properties_dict
.SetWithoutPathExpansion("servers", servers_dict
);
773 SetVersion(&http_server_properties_dict
, kVersionNumber
);
774 setting_prefs_
= true;
775 pref_service_
->Set(path_
, http_server_properties_dict
);
776 setting_prefs_
= false;
778 // Note that |completion| will be fired after we have written everything to
779 // the Preferences, but likely before these changes are serialized to disk.
780 // This is not a problem though, as JSONPrefStore guarantees that this will
781 // happen, pretty soon, and even in the case we shut down immediately.
782 if (!completion
.is_null())
786 void HttpServerPropertiesManager::OnHttpServerPropertiesChanged() {
787 DCHECK(pref_task_runner_
->RunsTasksOnCurrentThread());
789 ScheduleUpdateCacheOnPrefThread();