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;
50 // Persist 200 ServerNetworkStats.
51 const int kMaxServerNetworkStatsHostsToPersist
= 200;
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 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
<HttpServerProperties
> HttpServerPropertiesManager::GetWeakPtr() {
121 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
122 return network_weak_ptr_factory_
->GetWeakPtr();
125 void HttpServerPropertiesManager::Clear() {
126 Clear(base::Closure());
129 void HttpServerPropertiesManager::Clear(const base::Closure
& completion
) {
130 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
132 http_server_properties_impl_
->Clear();
133 UpdatePrefsFromCacheOnNetworkThread(completion
);
136 bool HttpServerPropertiesManager::SupportsSpdy(const HostPortPair
& server
) {
137 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
138 return http_server_properties_impl_
->SupportsSpdy(server
);
141 void HttpServerPropertiesManager::SetSupportsSpdy(const HostPortPair
& server
,
143 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
145 http_server_properties_impl_
->SetSupportsSpdy(server
, support_spdy
);
146 ScheduleUpdatePrefsOnNetworkThread();
149 bool HttpServerPropertiesManager::RequiresHTTP11(
150 const net::HostPortPair
& server
) {
151 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
152 return http_server_properties_impl_
->RequiresHTTP11(server
);
155 void HttpServerPropertiesManager::SetHTTP11Required(
156 const net::HostPortPair
& server
) {
157 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
159 http_server_properties_impl_
->SetHTTP11Required(server
);
160 ScheduleUpdatePrefsOnNetworkThread();
163 void HttpServerPropertiesManager::MaybeForceHTTP11(const HostPortPair
& server
,
164 SSLConfig
* ssl_config
) {
165 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
166 http_server_properties_impl_
->MaybeForceHTTP11(server
, ssl_config
);
169 bool HttpServerPropertiesManager::HasAlternateProtocol(
170 const HostPortPair
& server
) {
171 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
172 return http_server_properties_impl_
->HasAlternateProtocol(server
);
175 AlternateProtocolInfo
HttpServerPropertiesManager::GetAlternateProtocol(
176 const HostPortPair
& server
) {
177 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
178 return http_server_properties_impl_
->GetAlternateProtocol(server
);
181 void HttpServerPropertiesManager::SetAlternateProtocol(
182 const HostPortPair
& server
,
183 uint16 alternate_port
,
184 AlternateProtocol alternate_protocol
,
185 double alternate_probability
) {
186 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
187 http_server_properties_impl_
->SetAlternateProtocol(
188 server
, alternate_port
, alternate_protocol
, alternate_probability
);
189 ScheduleUpdatePrefsOnNetworkThread();
192 void HttpServerPropertiesManager::SetBrokenAlternateProtocol(
193 const HostPortPair
& server
) {
194 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
195 http_server_properties_impl_
->SetBrokenAlternateProtocol(server
);
196 ScheduleUpdatePrefsOnNetworkThread();
199 bool HttpServerPropertiesManager::WasAlternateProtocolRecentlyBroken(
200 const HostPortPair
& server
) {
201 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
202 return http_server_properties_impl_
->WasAlternateProtocolRecentlyBroken(
206 void HttpServerPropertiesManager::ConfirmAlternateProtocol(
207 const HostPortPair
& server
) {
208 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
209 http_server_properties_impl_
->ConfirmAlternateProtocol(server
);
210 ScheduleUpdatePrefsOnNetworkThread();
213 void HttpServerPropertiesManager::ClearAlternateProtocol(
214 const HostPortPair
& server
) {
215 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
216 http_server_properties_impl_
->ClearAlternateProtocol(server
);
217 ScheduleUpdatePrefsOnNetworkThread();
220 const AlternateProtocolMap
&
221 HttpServerPropertiesManager::alternate_protocol_map() const {
222 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
223 return http_server_properties_impl_
->alternate_protocol_map();
226 void HttpServerPropertiesManager::SetAlternateProtocolProbabilityThreshold(
228 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
229 http_server_properties_impl_
->SetAlternateProtocolProbabilityThreshold(
233 const SettingsMap
& HttpServerPropertiesManager::GetSpdySettings(
234 const HostPortPair
& host_port_pair
) {
235 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
236 return http_server_properties_impl_
->GetSpdySettings(host_port_pair
);
239 bool HttpServerPropertiesManager::SetSpdySetting(
240 const HostPortPair
& host_port_pair
,
242 SpdySettingsFlags flags
,
244 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
245 bool persist
= http_server_properties_impl_
->SetSpdySetting(
246 host_port_pair
, id
, flags
, value
);
248 ScheduleUpdatePrefsOnNetworkThread();
252 void HttpServerPropertiesManager::ClearSpdySettings(
253 const HostPortPair
& host_port_pair
) {
254 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
255 http_server_properties_impl_
->ClearSpdySettings(host_port_pair
);
256 ScheduleUpdatePrefsOnNetworkThread();
259 void HttpServerPropertiesManager::ClearAllSpdySettings() {
260 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
261 http_server_properties_impl_
->ClearAllSpdySettings();
262 ScheduleUpdatePrefsOnNetworkThread();
265 const SpdySettingsMap
& HttpServerPropertiesManager::spdy_settings_map()
267 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
268 return http_server_properties_impl_
->spdy_settings_map();
271 SupportsQuic
HttpServerPropertiesManager::GetSupportsQuic(
272 const HostPortPair
& host_port_pair
) const {
273 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
274 return http_server_properties_impl_
->GetSupportsQuic(host_port_pair
);
277 void HttpServerPropertiesManager::SetSupportsQuic(
278 const HostPortPair
& host_port_pair
,
280 const std::string
& address
) {
281 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
282 http_server_properties_impl_
->SetSupportsQuic(
283 host_port_pair
, used_quic
, address
);
284 ScheduleUpdatePrefsOnNetworkThread();
287 const SupportsQuicMap
& HttpServerPropertiesManager::supports_quic_map()
289 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
290 return http_server_properties_impl_
->supports_quic_map();
293 void HttpServerPropertiesManager::SetServerNetworkStats(
294 const HostPortPair
& host_port_pair
,
295 ServerNetworkStats stats
) {
296 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
297 http_server_properties_impl_
->SetServerNetworkStats(host_port_pair
, stats
);
298 ScheduleUpdatePrefsOnNetworkThread();
301 const ServerNetworkStats
* HttpServerPropertiesManager::GetServerNetworkStats(
302 const HostPortPair
& host_port_pair
) {
303 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
304 return http_server_properties_impl_
->GetServerNetworkStats(host_port_pair
);
307 const ServerNetworkStatsMap
&
308 HttpServerPropertiesManager::server_network_stats_map() const {
309 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
310 return http_server_properties_impl_
->server_network_stats_map();
314 // Update the HttpServerPropertiesImpl's cache with data from preferences.
316 void HttpServerPropertiesManager::ScheduleUpdateCacheOnPrefThread() {
317 DCHECK(pref_task_runner_
->RunsTasksOnCurrentThread());
318 // Cancel pending updates, if any.
319 pref_cache_update_timer_
->Stop();
320 StartCacheUpdateTimerOnPrefThread(
321 base::TimeDelta::FromMilliseconds(kUpdateCacheDelayMs
));
324 void HttpServerPropertiesManager::StartCacheUpdateTimerOnPrefThread(
325 base::TimeDelta delay
) {
326 DCHECK(pref_task_runner_
->RunsTasksOnCurrentThread());
327 pref_cache_update_timer_
->Start(
331 &HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread
);
334 void HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread() {
335 // The preferences can only be read on the pref thread.
336 DCHECK(pref_task_runner_
->RunsTasksOnCurrentThread());
338 if (!pref_service_
->HasPrefPath(path_
))
341 bool detected_corrupted_prefs
= false;
342 const base::DictionaryValue
& http_server_properties_dict
=
343 *pref_service_
->GetDictionary(path_
);
345 int version
= kMissingVersion
;
346 if (!http_server_properties_dict
.GetIntegerWithoutPathExpansion("version",
348 DVLOG(1) << "Missing version. Clearing all properties.";
352 // The properties for a given server is in
353 // http_server_properties_dict["servers"][server].
354 const base::DictionaryValue
* servers_dict
= NULL
;
355 if (!http_server_properties_dict
.GetDictionaryWithoutPathExpansion(
356 "servers", &servers_dict
)) {
357 DVLOG(1) << "Malformed http_server_properties for servers.";
361 // String is host/port pair of spdy server.
362 scoped_ptr
<StringVector
> spdy_servers(new StringVector
);
363 scoped_ptr
<SpdySettingsMap
> spdy_settings_map(
364 new SpdySettingsMap(kMaxSpdySettingsHostsToPersist
));
365 scoped_ptr
<AlternateProtocolMap
> alternate_protocol_map(
366 new AlternateProtocolMap(kMaxAlternateProtocolHostsToPersist
));
367 scoped_ptr
<SupportsQuicMap
> supports_quic_map(new SupportsQuicMap());
368 scoped_ptr
<ServerNetworkStatsMap
> server_network_stats_map(
369 new ServerNetworkStatsMap(kMaxServerNetworkStatsHostsToPersist
));
371 for (base::DictionaryValue::Iterator
it(*servers_dict
); !it
.IsAtEnd();
373 // Get server's host/pair.
374 const std::string
& server_str
= it
.key();
375 HostPortPair server
= HostPortPair::FromString(server_str
);
376 if (server
.host().empty()) {
377 DVLOG(1) << "Malformed http_server_properties for server: " << server_str
;
378 detected_corrupted_prefs
= true;
382 const base::DictionaryValue
* server_pref_dict
= NULL
;
383 if (!it
.value().GetAsDictionary(&server_pref_dict
)) {
384 DVLOG(1) << "Malformed http_server_properties server: " << server_str
;
385 detected_corrupted_prefs
= true;
389 // Get if server supports Spdy.
390 bool supports_spdy
= false;
391 if ((server_pref_dict
->GetBoolean("supports_spdy", &supports_spdy
)) &&
393 spdy_servers
->push_back(server_str
);
397 DCHECK(spdy_settings_map
->Peek(server
) == spdy_settings_map
->end());
398 const base::DictionaryValue
* spdy_settings_dict
= NULL
;
399 if (server_pref_dict
->GetDictionaryWithoutPathExpansion(
400 "settings", &spdy_settings_dict
)) {
401 SettingsMap settings_map
;
402 for (base::DictionaryValue::Iterator
dict_it(*spdy_settings_dict
);
405 const std::string
& id_str
= dict_it
.key();
407 if (!base::StringToInt(id_str
, &id
)) {
408 DVLOG(1) << "Malformed id in SpdySettings for server: " << server_str
;
413 if (!dict_it
.value().GetAsInteger(&value
)) {
414 DVLOG(1) << "Malformed value in SpdySettings for server: "
419 SettingsFlagsAndValue
flags_and_value(SETTINGS_FLAG_PERSISTED
, value
);
420 settings_map
[static_cast<SpdySettingsIds
>(id
)] = flags_and_value
;
422 spdy_settings_map
->Put(server
, settings_map
);
425 // Get alternate_protocol server.
426 DCHECK(alternate_protocol_map
->Peek(server
) ==
427 alternate_protocol_map
->end());
428 const base::DictionaryValue
* port_alternate_protocol_dict
= NULL
;
429 if (server_pref_dict
->GetDictionaryWithoutPathExpansion(
430 "alternate_protocol", &port_alternate_protocol_dict
)) {
432 if (!port_alternate_protocol_dict
->GetIntegerWithoutPathExpansion(
434 !IsPortValid(port
)) {
435 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str
;
436 detected_corrupted_prefs
= true;
439 std::string protocol_str
;
440 if (!port_alternate_protocol_dict
->GetStringWithoutPathExpansion(
441 "protocol_str", &protocol_str
)) {
442 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str
;
443 detected_corrupted_prefs
= true;
446 AlternateProtocol protocol
= AlternateProtocolFromString(protocol_str
);
447 if (!IsAlternateProtocolValid(protocol
)) {
448 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str
;
449 detected_corrupted_prefs
= true;
453 double probability
= 1;
454 if (port_alternate_protocol_dict
->HasKey("probability") &&
455 !port_alternate_protocol_dict
->GetDoubleWithoutPathExpansion(
456 "probability", &probability
)) {
457 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str
;
458 detected_corrupted_prefs
= true;
462 AlternateProtocolInfo
port_alternate_protocol(static_cast<uint16
>(port
),
463 protocol
, probability
);
464 alternate_protocol_map
->Put(server
, port_alternate_protocol
);
468 DCHECK(supports_quic_map
->find(server
) == supports_quic_map
->end());
469 const base::DictionaryValue
* supports_quic_dict
= NULL
;
470 if (server_pref_dict
->GetDictionaryWithoutPathExpansion(
471 "supports_quic", &supports_quic_dict
)) {
473 if (!supports_quic_dict
->GetBooleanWithoutPathExpansion(
474 "used_quic", &used_quic
)) {
475 DVLOG(1) << "Malformed SupportsQuic server: " << server_str
;
476 detected_corrupted_prefs
= true;
480 if (!supports_quic_dict
->GetStringWithoutPathExpansion(
481 "address", &address
)) {
482 DVLOG(1) << "Malformed SupportsQuic server: " << server_str
;
483 detected_corrupted_prefs
= true;
486 SupportsQuic
supports_quic(used_quic
, address
);
487 supports_quic_map
->insert(std::make_pair(server
, supports_quic
));
490 // Get ServerNetworkStats.
491 DCHECK(server_network_stats_map
->Peek(server
) ==
492 server_network_stats_map
->end());
493 const base::DictionaryValue
* server_network_stats_dict
= NULL
;
494 if (server_pref_dict
->GetDictionaryWithoutPathExpansion(
495 "network_stats", &server_network_stats_dict
)) {
497 if (!server_network_stats_dict
->GetIntegerWithoutPathExpansion("srtt",
499 DVLOG(1) << "Malformed ServerNetworkStats for server: " << server_str
;
500 detected_corrupted_prefs
= true;
503 ServerNetworkStats server_network_stats
;
504 server_network_stats
.srtt
= base::TimeDelta::FromInternalValue(srtt
);
505 // TODO(rtenneti): When QUIC starts using bandwidth_estimate, then persist
506 // bandwidth_estimate.
507 server_network_stats_map
->Put(server
, server_network_stats
);
511 network_task_runner_
->PostTask(
514 &HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread
,
515 base::Unretained(this), base::Owned(spdy_servers
.release()),
516 base::Owned(spdy_settings_map
.release()),
517 base::Owned(alternate_protocol_map
.release()),
518 base::Owned(supports_quic_map
.release()),
519 base::Owned(server_network_stats_map
.release()),
520 detected_corrupted_prefs
));
523 void HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread(
524 StringVector
* spdy_servers
,
525 SpdySettingsMap
* spdy_settings_map
,
526 AlternateProtocolMap
* alternate_protocol_map
,
527 SupportsQuicMap
* supports_quic_map
,
528 ServerNetworkStatsMap
* server_network_stats_map
,
529 bool detected_corrupted_prefs
) {
530 // Preferences have the master data because admins might have pushed new
531 // preferences. Update the cached data with new data from preferences.
532 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
534 UMA_HISTOGRAM_COUNTS("Net.CountOfSpdyServers", spdy_servers
->size());
535 http_server_properties_impl_
->InitializeSpdyServers(spdy_servers
, true);
537 // Update the cached data and use the new spdy_settings from preferences.
538 UMA_HISTOGRAM_COUNTS("Net.CountOfSpdySettings", spdy_settings_map
->size());
539 http_server_properties_impl_
->InitializeSpdySettingsServers(
542 // Update the cached data and use the new Alternate-Protocol server list from
544 UMA_HISTOGRAM_COUNTS("Net.CountOfAlternateProtocolServers",
545 alternate_protocol_map
->size());
546 http_server_properties_impl_
->InitializeAlternateProtocolServers(
547 alternate_protocol_map
);
549 http_server_properties_impl_
->InitializeSupportsQuic(supports_quic_map
);
551 http_server_properties_impl_
->InitializeServerNetworkStats(
552 server_network_stats_map
);
554 // Update the prefs with what we have read (delete all corrupted prefs).
555 if (detected_corrupted_prefs
)
556 ScheduleUpdatePrefsOnNetworkThread();
560 // Update Preferences with data from the cached data.
562 void HttpServerPropertiesManager::ScheduleUpdatePrefsOnNetworkThread() {
563 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
564 // Cancel pending updates, if any.
565 network_prefs_update_timer_
->Stop();
566 StartPrefsUpdateTimerOnNetworkThread(
567 base::TimeDelta::FromMilliseconds(kUpdatePrefsDelayMs
));
570 void HttpServerPropertiesManager::StartPrefsUpdateTimerOnNetworkThread(
571 base::TimeDelta delay
) {
572 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
573 // This is overridden in tests to post the task without the delay.
574 network_prefs_update_timer_
->Start(
578 &HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread
);
581 // This is required so we can set this as the callback for a timer.
582 void HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread() {
583 UpdatePrefsFromCacheOnNetworkThread(base::Closure());
586 void HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread(
587 const base::Closure
& completion
) {
588 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
590 base::ListValue
* spdy_server_list
= new base::ListValue
;
591 http_server_properties_impl_
->GetSpdyServerList(
592 spdy_server_list
, kMaxSupportsSpdyServerHostsToPersist
);
594 SpdySettingsMap
* spdy_settings_map
=
595 new SpdySettingsMap(kMaxSpdySettingsHostsToPersist
);
596 const SpdySettingsMap
& main_map
=
597 http_server_properties_impl_
->spdy_settings_map();
599 for (SpdySettingsMap::const_iterator it
= main_map
.begin();
600 it
!= main_map
.end() && count
< kMaxSpdySettingsHostsToPersist
;
602 spdy_settings_map
->Put(it
->first
, it
->second
);
605 AlternateProtocolMap
* alternate_protocol_map
=
606 new AlternateProtocolMap(kMaxAlternateProtocolHostsToPersist
);
607 const AlternateProtocolMap
& map
=
608 http_server_properties_impl_
->alternate_protocol_map();
610 typedef std::map
<std::string
, bool> CanonicalHostPersistedMap
;
611 CanonicalHostPersistedMap persisted_map
;
612 for (AlternateProtocolMap::const_iterator it
= map
.begin();
613 it
!= map
.end() && count
< kMaxAlternateProtocolHostsToPersist
; ++it
) {
614 const HostPortPair
& server
= it
->first
;
615 std::string canonical_suffix
=
616 http_server_properties_impl_
->GetCanonicalSuffix(server
);
617 if (!canonical_suffix
.empty()) {
618 if (persisted_map
.find(canonical_suffix
) != persisted_map
.end())
620 persisted_map
[canonical_suffix
] = true;
622 alternate_protocol_map
->Put(server
, it
->second
);
626 SupportsQuicMap
* supports_quic_map
= new SupportsQuicMap();
627 const SupportsQuicMap
& main_supports_quic_map
=
628 http_server_properties_impl_
->supports_quic_map();
629 for (SupportsQuicMap::const_iterator it
= main_supports_quic_map
.begin();
630 it
!= main_supports_quic_map
.end(); ++it
) {
631 supports_quic_map
->insert(std::make_pair(it
->first
, it
->second
));
634 ServerNetworkStatsMap
* server_network_stats_map
=
635 new ServerNetworkStatsMap(kMaxServerNetworkStatsHostsToPersist
);
636 const ServerNetworkStatsMap
& main_server_network_stats_map
=
637 http_server_properties_impl_
->server_network_stats_map();
638 for (ServerNetworkStatsMap::const_iterator it
=
639 main_server_network_stats_map
.begin();
640 it
!= main_server_network_stats_map
.end(); ++it
) {
641 server_network_stats_map
->Put(it
->first
, it
->second
);
644 // Update the preferences on the pref thread.
645 pref_task_runner_
->PostTask(
648 &HttpServerPropertiesManager::UpdatePrefsOnPrefThread
, pref_weak_ptr_
,
649 base::Owned(spdy_server_list
), base::Owned(spdy_settings_map
),
650 base::Owned(alternate_protocol_map
), base::Owned(supports_quic_map
),
651 base::Owned(server_network_stats_map
), completion
));
654 // A local or temporary data structure to hold |supports_spdy|, SpdySettings,
655 // AlternateProtocolInfo and SupportsQuic preferences for a server. This is used
656 // only in UpdatePrefsOnPrefThread.
659 : supports_spdy(false),
661 alternate_protocol(NULL
),
663 server_network_stats(NULL
) {}
664 ServerPref(bool supports_spdy
,
665 const SettingsMap
* settings_map
,
666 const AlternateProtocolInfo
* alternate_protocol
,
667 const SupportsQuic
* supports_quic
,
668 const ServerNetworkStats
* server_network_stats
)
669 : supports_spdy(supports_spdy
),
670 settings_map(settings_map
),
671 alternate_protocol(alternate_protocol
),
672 supports_quic(supports_quic
),
673 server_network_stats(server_network_stats
) {}
675 const SettingsMap
* settings_map
;
676 const AlternateProtocolInfo
* alternate_protocol
;
677 const SupportsQuic
* supports_quic
;
678 const ServerNetworkStats
* server_network_stats
;
681 void HttpServerPropertiesManager::UpdatePrefsOnPrefThread(
682 base::ListValue
* spdy_server_list
,
683 SpdySettingsMap
* spdy_settings_map
,
684 AlternateProtocolMap
* alternate_protocol_map
,
685 SupportsQuicMap
* supports_quic_map
,
686 ServerNetworkStatsMap
* server_network_stats_map
,
687 const base::Closure
& completion
) {
688 typedef std::map
<HostPortPair
, ServerPref
> ServerPrefMap
;
689 ServerPrefMap server_pref_map
;
691 DCHECK(pref_task_runner_
->RunsTasksOnCurrentThread());
693 // Add servers that support spdy to server_pref_map.
695 for (base::ListValue::const_iterator list_it
= spdy_server_list
->begin();
696 list_it
!= spdy_server_list
->end();
698 if ((*list_it
)->GetAsString(&s
)) {
699 HostPortPair server
= HostPortPair::FromString(s
);
701 ServerPrefMap::iterator it
= server_pref_map
.find(server
);
702 if (it
== server_pref_map
.end()) {
703 ServerPref
server_pref(true, NULL
, NULL
, NULL
, NULL
);
704 server_pref_map
[server
] = server_pref
;
706 it
->second
.supports_spdy
= true;
711 // Add servers that have SpdySettings to server_pref_map.
712 for (SpdySettingsMap::iterator map_it
= spdy_settings_map
->begin();
713 map_it
!= spdy_settings_map
->end(); ++map_it
) {
714 const HostPortPair
& server
= map_it
->first
;
716 ServerPrefMap::iterator it
= server_pref_map
.find(server
);
717 if (it
== server_pref_map
.end()) {
718 ServerPref
server_pref(false, &map_it
->second
, NULL
, NULL
, NULL
);
719 server_pref_map
[server
] = server_pref
;
721 it
->second
.settings_map
= &map_it
->second
;
725 // Add AlternateProtocol servers to server_pref_map.
726 for (AlternateProtocolMap::const_iterator map_it
=
727 alternate_protocol_map
->begin();
728 map_it
!= alternate_protocol_map
->end(); ++map_it
) {
729 const HostPortPair
& server
= map_it
->first
;
730 const AlternateProtocolInfo
& port_alternate_protocol
= map_it
->second
;
731 if (!IsAlternateProtocolValid(port_alternate_protocol
.protocol
)) {
735 ServerPrefMap::iterator it
= server_pref_map
.find(server
);
736 if (it
== server_pref_map
.end()) {
737 ServerPref
server_pref(false, NULL
, &map_it
->second
, NULL
, NULL
);
738 server_pref_map
[server
] = server_pref
;
740 it
->second
.alternate_protocol
= &map_it
->second
;
744 // Add SupportsQuic servers to server_pref_map.
745 for (SupportsQuicMap::const_iterator map_it
= supports_quic_map
->begin();
746 map_it
!= supports_quic_map
->end(); ++map_it
) {
747 const HostPortPair
& server
= map_it
->first
;
749 ServerPrefMap::iterator it
= server_pref_map
.find(server
);
750 if (it
== server_pref_map
.end()) {
751 ServerPref
server_pref(false, NULL
, NULL
, &map_it
->second
, NULL
);
752 server_pref_map
[server
] = server_pref
;
754 it
->second
.supports_quic
= &map_it
->second
;
758 // Add ServerNetworkStats servers to server_pref_map.
759 for (ServerNetworkStatsMap::const_iterator map_it
=
760 server_network_stats_map
->begin();
761 map_it
!= server_network_stats_map
->end(); ++map_it
) {
762 const HostPortPair
& server
= map_it
->first
;
764 ServerPrefMap::iterator it
= server_pref_map
.find(server
);
765 if (it
== server_pref_map
.end()) {
766 ServerPref
server_pref(false, NULL
, NULL
, NULL
, &map_it
->second
);
767 server_pref_map
[server
] = server_pref
;
769 it
->second
.server_network_stats
= &map_it
->second
;
773 // Persist properties to the |path_|.
774 base::DictionaryValue http_server_properties_dict
;
775 base::DictionaryValue
* servers_dict
= new base::DictionaryValue
;
776 for (ServerPrefMap::const_iterator map_it
= server_pref_map
.begin();
777 map_it
!= server_pref_map
.end();
779 const HostPortPair
& server
= map_it
->first
;
780 const ServerPref
& server_pref
= map_it
->second
;
782 base::DictionaryValue
* server_pref_dict
= new base::DictionaryValue
;
784 // Save supports_spdy.
785 if (server_pref
.supports_spdy
)
786 server_pref_dict
->SetBoolean("supports_spdy", server_pref
.supports_spdy
);
788 // Save SPDY settings.
789 if (server_pref
.settings_map
) {
790 base::DictionaryValue
* spdy_settings_dict
= new base::DictionaryValue
;
791 for (SettingsMap::const_iterator it
= server_pref
.settings_map
->begin();
792 it
!= server_pref
.settings_map
->end(); ++it
) {
793 SpdySettingsIds id
= it
->first
;
794 uint32 value
= it
->second
.second
;
795 std::string key
= base::StringPrintf("%u", id
);
796 spdy_settings_dict
->SetInteger(key
, value
);
798 server_pref_dict
->SetWithoutPathExpansion("settings", spdy_settings_dict
);
801 // Save alternate_protocol.
802 const AlternateProtocolInfo
* port_alternate_protocol
=
803 server_pref
.alternate_protocol
;
804 if (port_alternate_protocol
&& !port_alternate_protocol
->is_broken
) {
805 base::DictionaryValue
* port_alternate_protocol_dict
=
806 new base::DictionaryValue
;
807 port_alternate_protocol_dict
->SetInteger("port",
808 port_alternate_protocol
->port
);
809 const char* protocol_str
=
810 AlternateProtocolToString(port_alternate_protocol
->protocol
);
811 port_alternate_protocol_dict
->SetString("protocol_str", protocol_str
);
812 port_alternate_protocol_dict
->SetDouble(
813 "probability", port_alternate_protocol
->probability
);
814 server_pref_dict
->SetWithoutPathExpansion(
815 "alternate_protocol", port_alternate_protocol_dict
);
818 // Save supports_quic.
819 if (server_pref
.supports_quic
) {
820 base::DictionaryValue
* supports_quic_dict
= new base::DictionaryValue
;
821 const SupportsQuic
* supports_quic
= server_pref
.supports_quic
;
822 supports_quic_dict
->SetBoolean("used_quic", supports_quic
->used_quic
);
823 supports_quic_dict
->SetString("address", supports_quic
->address
);
824 server_pref_dict
->SetWithoutPathExpansion(
825 "supports_quic", supports_quic_dict
);
828 // Save ServerNetworkStats.
829 if (server_pref
.server_network_stats
) {
830 base::DictionaryValue
* server_network_stats_dict
=
831 new base::DictionaryValue
;
832 const ServerNetworkStats
* server_network_stats
=
833 server_pref
.server_network_stats
;
834 // Becasue JSON doesn't support int64, persist int64 as a string.
835 server_network_stats_dict
->SetInteger(
837 static_cast<int>(server_network_stats
->srtt
.ToInternalValue()));
838 // TODO(rtenneti): When QUIC starts using bandwidth_estimate, then persist
839 // bandwidth_estimate.
840 server_pref_dict
->SetWithoutPathExpansion("network_stats",
841 server_network_stats_dict
);
844 servers_dict
->SetWithoutPathExpansion(server
.ToString(), server_pref_dict
);
847 http_server_properties_dict
.SetWithoutPathExpansion("servers", servers_dict
);
848 SetVersion(&http_server_properties_dict
, kVersionNumber
);
849 setting_prefs_
= true;
850 pref_service_
->Set(path_
, http_server_properties_dict
);
851 setting_prefs_
= false;
853 // Note that |completion| will be fired after we have written everything to
854 // the Preferences, but likely before these changes are serialized to disk.
855 // This is not a problem though, as JSONPrefStore guarantees that this will
856 // happen, pretty soon, and even in the case we shut down immediately.
857 if (!completion
.is_null())
861 void HttpServerPropertiesManager::OnHttpServerPropertiesChanged() {
862 DCHECK(pref_task_runner_
->RunsTasksOnCurrentThread());
864 ScheduleUpdateCacheOnPrefThread();