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"
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
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;
34 const int64 kUpdatePrefsDelayMs
= 5000;
37 // "version" 0 indicates, http_server_properties doesn't have "version"
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;
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),
68 network_task_runner_(network_task_runner
) {
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(
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(
98 base::Bind(&HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread
,
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();
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
,
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(
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(
214 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
215 http_server_properties_impl_
->SetAlternateProtocolProbabilityThreshold(
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
,
228 SpdySettingsFlags flags
,
230 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
231 bool persist
= http_server_properties_impl_
->SetSpdySetting(
232 host_port_pair
, id
, flags
, value
);
234 ScheduleUpdatePrefsOnNetworkThread();
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()
253 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
254 return http_server_properties_impl_
->spdy_settings_map();
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
,
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()
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(
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_
))
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",
329 DVLOG(1) << "Missing version. Clearing all properties.";
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.";
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());
352 for (base::DictionaryValue::Iterator
it(*servers_dict
); !it
.IsAtEnd();
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;
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;
370 // Get if server supports Spdy.
371 bool supports_spdy
= false;
372 if ((server_pref_dict
->GetBoolean("supports_spdy", &supports_spdy
)) &&
374 spdy_servers
->push_back(server_str
);
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
);
386 const std::string
& id_str
= dict_it
.key();
388 if (!base::StringToInt(id_str
, &id
)) {
389 DVLOG(1) << "Malformed id in SpdySettings for server: " << server_str
;
394 if (!dict_it
.value().GetAsInteger(&value
)) {
395 DVLOG(1) << "Malformed value in SpdySettings for server: "
400 net::SettingsFlagsAndValue
flags_and_value(net::SETTINGS_FLAG_PERSISTED
,
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
)) {
416 if (count
>= kMaxAlternateProtocolHostsToPersist
)
420 if (!port_alternate_protocol_dict
->GetIntegerWithoutPathExpansion(
422 (port
> (1 << 16))) {
423 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str
;
424 detected_corrupted_prefs
= true;
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;
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;
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;
451 net::AlternateProtocolInfo
port_alternate_protocol(port
,
454 alternate_protocol_map
->Put(server
, port_alternate_protocol
);
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
)) {
467 if (!supports_quic_dict
->GetBooleanWithoutPathExpansion(
468 "used_quic", &used_quic
)) {
469 DVLOG(1) << "Malformed SupportsQuic server: " << server_str
;
470 detected_corrupted_prefs
= true;
474 if (!supports_quic_dict
->GetStringWithoutPathExpansion(
475 "address", &address
)) {
476 DVLOG(1) << "Malformed SupportsQuic server: " << server_str
;
477 detected_corrupted_prefs
= true;
480 net::SupportsQuic
supports_quic(used_quic
, address
);
481 supports_quic_map
->insert(std::make_pair(server
, supports_quic
));
485 network_task_runner_
->PostTask(
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(
515 // Update the cached data and use the new Alternate-Protocol server list from
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(
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();
569 for (net::SpdySettingsMap::const_iterator it
= main_map
.begin();
570 it
!= main_map
.end() && count
< kMaxSpdySettingsHostsToPersist
;
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();
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
;
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())
591 persisted_map
[canonical_suffix
] = true;
593 alternate_protocol_map
->Put(server
, it
->second
);
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(
608 base::Bind(&HttpServerPropertiesManager::UpdatePrefsOnPrefThread
,
610 base::Owned(spdy_server_list
),
611 base::Owned(spdy_settings_map
),
612 base::Owned(alternate_protocol_map
),
613 base::Owned(supports_quic_map
),
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.
621 ServerPref() : supports_spdy(false),
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
) {}
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.
652 for (base::ListValue::const_iterator list_it
= spdy_server_list
->begin();
653 list_it
!= spdy_server_list
->end();
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
;
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();
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
;
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();
688 const net::HostPortPair
& server
= map_it
->first
;
689 const net::AlternateProtocolInfo
& port_alternate_protocol
=
691 if (!net::IsAlternateProtocolValid(port_alternate_protocol
.protocol
)) {
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
;
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
;
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();
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();
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())
792 void HttpServerPropertiesManager::OnHttpServerPropertiesChanged() {
793 DCHECK(pref_task_runner_
->RunsTasksOnCurrentThread());
795 ScheduleUpdateCacheOnPrefThread();