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;
53 const char kVersionKey
[] = "version";
54 const char kServersKey
[] = "servers";
55 const char kSupportsSpdyKey
[] = "supports_spdy";
56 const char kSettingsKey
[] = "settings";
57 const char kSupportsQuicKey
[] = "supports_quic";
58 const char kUsedQuicKey
[] = "used_quic";
59 const char kAddressKey
[] = "address";
60 const char kAlternateProtocolKey
[] = "alternate_protocol";
61 const char kPortKey
[] = "port";
62 const char kProtocolKey
[] = "protocol_str";
63 const char kProbabilityKey
[] = "probability";
64 const char kNetworkStatsKey
[] = "network_stats";
65 const char kSrttKey
[] = "srtt";
69 ////////////////////////////////////////////////////////////////////////////////
70 // HttpServerPropertiesManager
72 HttpServerPropertiesManager::HttpServerPropertiesManager(
73 PrefService
* pref_service
,
74 const char* pref_path
,
75 scoped_refptr
<base::SequencedTaskRunner
> network_task_runner
)
76 : pref_task_runner_(base::ThreadTaskRunnerHandle::Get()),
77 pref_service_(pref_service
),
78 setting_prefs_(false),
80 network_task_runner_(network_task_runner
) {
82 pref_weak_ptr_factory_
.reset(
83 new base::WeakPtrFactory
<HttpServerPropertiesManager
>(this));
84 pref_weak_ptr_
= pref_weak_ptr_factory_
->GetWeakPtr();
85 pref_cache_update_timer_
.reset(
86 new base::OneShotTimer
<HttpServerPropertiesManager
>);
87 pref_change_registrar_
.Init(pref_service_
);
88 pref_change_registrar_
.Add(
90 base::Bind(&HttpServerPropertiesManager::OnHttpServerPropertiesChanged
,
91 base::Unretained(this)));
94 HttpServerPropertiesManager::~HttpServerPropertiesManager() {
95 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
96 network_weak_ptr_factory_
.reset();
99 void HttpServerPropertiesManager::InitializeOnNetworkThread() {
100 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
101 network_weak_ptr_factory_
.reset(
102 new base::WeakPtrFactory
<HttpServerPropertiesManager
>(this));
103 http_server_properties_impl_
.reset(new HttpServerPropertiesImpl());
105 network_prefs_update_timer_
.reset(
106 new base::OneShotTimer
<HttpServerPropertiesManager
>);
108 pref_task_runner_
->PostTask(
110 base::Bind(&HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread
,
114 void HttpServerPropertiesManager::ShutdownOnPrefThread() {
115 DCHECK(pref_task_runner_
->RunsTasksOnCurrentThread());
116 // Cancel any pending updates, and stop listening for pref change updates.
117 pref_cache_update_timer_
->Stop();
118 pref_weak_ptr_factory_
.reset();
119 pref_change_registrar_
.RemoveAll();
123 void HttpServerPropertiesManager::SetVersion(
124 base::DictionaryValue
* http_server_properties_dict
,
125 int version_number
) {
126 if (version_number
< 0)
127 version_number
= kVersionNumber
;
128 DCHECK_LE(version_number
, kVersionNumber
);
129 if (version_number
<= kVersionNumber
)
130 http_server_properties_dict
->SetInteger(kVersionKey
, version_number
);
133 // This is required for conformance with the HttpServerProperties interface.
134 base::WeakPtr
<HttpServerProperties
> HttpServerPropertiesManager::GetWeakPtr() {
135 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
136 return network_weak_ptr_factory_
->GetWeakPtr();
139 void HttpServerPropertiesManager::Clear() {
140 Clear(base::Closure());
143 void HttpServerPropertiesManager::Clear(const base::Closure
& completion
) {
144 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
146 http_server_properties_impl_
->Clear();
147 UpdatePrefsFromCacheOnNetworkThread(completion
);
150 bool HttpServerPropertiesManager::SupportsRequestPriority(
151 const HostPortPair
& server
) {
152 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
153 return http_server_properties_impl_
->SupportsRequestPriority(server
);
156 void HttpServerPropertiesManager::SetSupportsSpdy(const HostPortPair
& server
,
158 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
160 http_server_properties_impl_
->SetSupportsSpdy(server
, support_spdy
);
161 ScheduleUpdatePrefsOnNetworkThread();
164 bool HttpServerPropertiesManager::RequiresHTTP11(const HostPortPair
& server
) {
165 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
166 return http_server_properties_impl_
->RequiresHTTP11(server
);
169 void HttpServerPropertiesManager::SetHTTP11Required(
170 const HostPortPair
& server
) {
171 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
173 http_server_properties_impl_
->SetHTTP11Required(server
);
174 ScheduleUpdatePrefsOnNetworkThread();
177 void HttpServerPropertiesManager::MaybeForceHTTP11(const HostPortPair
& server
,
178 SSLConfig
* ssl_config
) {
179 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
180 http_server_properties_impl_
->MaybeForceHTTP11(server
, ssl_config
);
183 AlternateProtocolInfo
HttpServerPropertiesManager::GetAlternateProtocol(
184 const HostPortPair
& server
) {
185 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
186 return http_server_properties_impl_
->GetAlternateProtocol(server
);
189 void HttpServerPropertiesManager::SetAlternateProtocol(
190 const HostPortPair
& server
,
191 uint16 alternate_port
,
192 AlternateProtocol alternate_protocol
,
193 double alternate_probability
) {
194 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
195 http_server_properties_impl_
->SetAlternateProtocol(
196 server
, alternate_port
, alternate_protocol
, alternate_probability
);
197 ScheduleUpdatePrefsOnNetworkThread();
200 void HttpServerPropertiesManager::SetBrokenAlternateProtocol(
201 const HostPortPair
& server
) {
202 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
203 http_server_properties_impl_
->SetBrokenAlternateProtocol(server
);
204 ScheduleUpdatePrefsOnNetworkThread();
207 bool HttpServerPropertiesManager::WasAlternateProtocolRecentlyBroken(
208 const HostPortPair
& server
) {
209 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
210 return http_server_properties_impl_
->WasAlternateProtocolRecentlyBroken(
214 void HttpServerPropertiesManager::ConfirmAlternateProtocol(
215 const HostPortPair
& server
) {
216 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
217 http_server_properties_impl_
->ConfirmAlternateProtocol(server
);
218 ScheduleUpdatePrefsOnNetworkThread();
221 void HttpServerPropertiesManager::ClearAlternateProtocol(
222 const HostPortPair
& server
) {
223 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
224 http_server_properties_impl_
->ClearAlternateProtocol(server
);
225 ScheduleUpdatePrefsOnNetworkThread();
228 const AlternateProtocolMap
&
229 HttpServerPropertiesManager::alternate_protocol_map() const {
230 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
231 return http_server_properties_impl_
->alternate_protocol_map();
234 void HttpServerPropertiesManager::SetAlternateProtocolProbabilityThreshold(
236 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
237 http_server_properties_impl_
->SetAlternateProtocolProbabilityThreshold(
241 const SettingsMap
& HttpServerPropertiesManager::GetSpdySettings(
242 const HostPortPair
& host_port_pair
) {
243 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
244 return http_server_properties_impl_
->GetSpdySettings(host_port_pair
);
247 bool HttpServerPropertiesManager::SetSpdySetting(
248 const HostPortPair
& host_port_pair
,
250 SpdySettingsFlags flags
,
252 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
253 bool persist
= http_server_properties_impl_
->SetSpdySetting(
254 host_port_pair
, id
, flags
, value
);
256 ScheduleUpdatePrefsOnNetworkThread();
260 void HttpServerPropertiesManager::ClearSpdySettings(
261 const HostPortPair
& host_port_pair
) {
262 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
263 http_server_properties_impl_
->ClearSpdySettings(host_port_pair
);
264 ScheduleUpdatePrefsOnNetworkThread();
267 void HttpServerPropertiesManager::ClearAllSpdySettings() {
268 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
269 http_server_properties_impl_
->ClearAllSpdySettings();
270 ScheduleUpdatePrefsOnNetworkThread();
273 const SpdySettingsMap
& HttpServerPropertiesManager::spdy_settings_map()
275 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
276 return http_server_properties_impl_
->spdy_settings_map();
279 bool HttpServerPropertiesManager::GetSupportsQuic(
280 IPAddressNumber
* last_address
) const {
281 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
282 return http_server_properties_impl_
->GetSupportsQuic(last_address
);
285 void HttpServerPropertiesManager::SetSupportsQuic(
287 const IPAddressNumber
& address
) {
288 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
289 http_server_properties_impl_
->SetSupportsQuic(used_quic
, address
);
290 ScheduleUpdatePrefsOnNetworkThread();
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(kVersionKey
,
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 kServersKey
, &servers_dict
)) {
357 DVLOG(1) << "Malformed http_server_properties for servers.";
361 IPAddressNumber
* addr
= new IPAddressNumber
;
362 ReadSupportsQuic(http_server_properties_dict
, addr
);
364 // String is host/port pair of spdy server.
365 scoped_ptr
<StringVector
> spdy_servers(new StringVector
);
366 scoped_ptr
<SpdySettingsMap
> spdy_settings_map(
367 new SpdySettingsMap(kMaxSpdySettingsHostsToPersist
));
368 scoped_ptr
<AlternateProtocolMap
> alternate_protocol_map(
369 new AlternateProtocolMap(kMaxAlternateProtocolHostsToPersist
));
370 scoped_ptr
<ServerNetworkStatsMap
> server_network_stats_map(
371 new ServerNetworkStatsMap(kMaxServerNetworkStatsHostsToPersist
));
373 for (base::DictionaryValue::Iterator
it(*servers_dict
); !it
.IsAtEnd();
375 // Get server's host/pair.
376 const std::string
& server_str
= it
.key();
377 HostPortPair server
= HostPortPair::FromString(server_str
);
378 if (server
.host().empty()) {
379 DVLOG(1) << "Malformed http_server_properties for server: " << server_str
;
380 detected_corrupted_prefs
= true;
384 const base::DictionaryValue
* server_pref_dict
= NULL
;
385 if (!it
.value().GetAsDictionary(&server_pref_dict
)) {
386 DVLOG(1) << "Malformed http_server_properties server: " << server_str
;
387 detected_corrupted_prefs
= true;
391 // Get if server supports Spdy.
392 bool supports_spdy
= false;
393 if ((server_pref_dict
->GetBoolean(kSupportsSpdyKey
, &supports_spdy
)) &&
395 spdy_servers
->push_back(server_str
);
398 AddToSpdySettingsMap(server
, *server_pref_dict
, spdy_settings_map
.get());
399 if (!AddToAlternateProtocolMap(server
, *server_pref_dict
,
400 alternate_protocol_map
.get()) ||
401 !AddToNetworkStatsMap(server
, *server_pref_dict
,
402 server_network_stats_map
.get())) {
403 detected_corrupted_prefs
= true;
407 network_task_runner_
->PostTask(
410 &HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread
,
411 base::Unretained(this), base::Owned(spdy_servers
.release()),
412 base::Owned(spdy_settings_map
.release()),
413 base::Owned(alternate_protocol_map
.release()), base::Owned(addr
),
414 base::Owned(server_network_stats_map
.release()),
415 detected_corrupted_prefs
));
418 void HttpServerPropertiesManager::AddToSpdySettingsMap(
419 const HostPortPair
& server
,
420 const base::DictionaryValue
& server_pref_dict
,
421 SpdySettingsMap
* spdy_settings_map
) {
423 DCHECK(spdy_settings_map
->Peek(server
) == spdy_settings_map
->end());
424 const base::DictionaryValue
* spdy_settings_dict
= NULL
;
425 if (!server_pref_dict
.GetDictionaryWithoutPathExpansion(
426 kSettingsKey
, &spdy_settings_dict
)) {
429 SettingsMap settings_map
;
430 for (base::DictionaryValue::Iterator
dict_it(*spdy_settings_dict
);
431 !dict_it
.IsAtEnd(); dict_it
.Advance()) {
432 const std::string
& id_str
= dict_it
.key();
434 if (!base::StringToInt(id_str
, &id
)) {
435 DVLOG(1) << "Malformed id in SpdySettings for server: "
436 << server
.ToString();
441 if (!dict_it
.value().GetAsInteger(&value
)) {
442 DVLOG(1) << "Malformed value in SpdySettings for server: "
443 << server
.ToString();
447 SettingsFlagsAndValue
flags_and_value(SETTINGS_FLAG_PERSISTED
, value
);
448 settings_map
[static_cast<SpdySettingsIds
>(id
)] = flags_and_value
;
450 spdy_settings_map
->Put(server
, settings_map
);
453 AlternateProtocolInfo
HttpServerPropertiesManager::ParseAlternateProtocolDict(
454 const base::DictionaryValue
& alternate_protocol_dict
,
455 const std::string
& server_str
) {
456 AlternateProtocolInfo alternate_protocol
;
458 if (!alternate_protocol_dict
.GetInteger(kPortKey
, &port
) ||
459 !IsPortValid(port
)) {
460 DVLOG(1) << "Malformed AltSvc port for server: " << server_str
;
461 return alternate_protocol
;
463 alternate_protocol
.port
= static_cast<uint16
>(port
);
465 double probability
= 1.0;
466 if (alternate_protocol_dict
.HasKey(kProbabilityKey
) &&
467 !alternate_protocol_dict
.GetDoubleWithoutPathExpansion(kProbabilityKey
,
469 DVLOG(1) << "Malformed AltSvc probability for server: " << server_str
;
470 return alternate_protocol
;
472 alternate_protocol
.probability
= probability
;
474 std::string protocol_str
;
475 if (!alternate_protocol_dict
.GetStringWithoutPathExpansion(kProtocolKey
,
477 DVLOG(1) << "Malformed AltSvc protocol string for server: " << server_str
;
478 return alternate_protocol
;
480 AlternateProtocol protocol
= AlternateProtocolFromString(protocol_str
);
481 if (!IsAlternateProtocolValid(protocol
)) {
482 DVLOG(1) << "Invalid AltSvc protocol string for server: " << server_str
;
483 return alternate_protocol
;
485 alternate_protocol
.protocol
= protocol
;
487 return alternate_protocol
;
490 bool HttpServerPropertiesManager::AddToAlternateProtocolMap(
491 const HostPortPair
& server
,
492 const base::DictionaryValue
& server_pref_dict
,
493 AlternateProtocolMap
* alternate_protocol_map
) {
494 // Get alternate_protocol server.
495 DCHECK(alternate_protocol_map
->Peek(server
) == alternate_protocol_map
->end());
496 const base::DictionaryValue
* alternate_protocol_dict
= NULL
;
497 if (!server_pref_dict
.GetDictionaryWithoutPathExpansion(
498 kAlternateProtocolKey
, &alternate_protocol_dict
)) {
501 AlternateProtocolInfo alternate_protocol
=
502 ParseAlternateProtocolDict(*alternate_protocol_dict
, server
.ToString());
503 if (alternate_protocol
.protocol
== UNINITIALIZED_ALTERNATE_PROTOCOL
)
505 alternate_protocol_map
->Put(server
, alternate_protocol
);
509 bool HttpServerPropertiesManager::ReadSupportsQuic(
510 const base::DictionaryValue
& http_server_properties_dict
,
511 IPAddressNumber
* last_quic_address
) {
512 const base::DictionaryValue
* supports_quic_dict
= NULL
;
513 if (!http_server_properties_dict
.GetDictionaryWithoutPathExpansion(
514 kSupportsQuicKey
, &supports_quic_dict
)) {
517 bool used_quic
= false;
518 if (!supports_quic_dict
->GetBooleanWithoutPathExpansion(kUsedQuicKey
,
520 DVLOG(1) << "Malformed SupportsQuic";
527 if (!supports_quic_dict
->GetStringWithoutPathExpansion(kAddressKey
,
529 !ParseIPLiteralToNumber(address
, last_quic_address
)) {
530 DVLOG(1) << "Malformed SupportsQuic";
536 bool HttpServerPropertiesManager::AddToNetworkStatsMap(
537 const HostPortPair
& server
,
538 const base::DictionaryValue
& server_pref_dict
,
539 ServerNetworkStatsMap
* network_stats_map
) {
540 DCHECK(network_stats_map
->Peek(server
) == network_stats_map
->end());
541 const base::DictionaryValue
* server_network_stats_dict
= NULL
;
542 if (!server_pref_dict
.GetDictionaryWithoutPathExpansion(
543 kNetworkStatsKey
, &server_network_stats_dict
)) {
547 if (!server_network_stats_dict
->GetIntegerWithoutPathExpansion(kSrttKey
,
549 DVLOG(1) << "Malformed ServerNetworkStats for server: "
550 << server
.ToString();
553 ServerNetworkStats server_network_stats
;
554 server_network_stats
.srtt
= base::TimeDelta::FromInternalValue(srtt
);
555 // TODO(rtenneti): When QUIC starts using bandwidth_estimate, then persist
556 // bandwidth_estimate.
557 network_stats_map
->Put(server
, server_network_stats
);
561 void HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread(
562 StringVector
* spdy_servers
,
563 SpdySettingsMap
* spdy_settings_map
,
564 AlternateProtocolMap
* alternate_protocol_map
,
565 IPAddressNumber
* last_quic_address
,
566 ServerNetworkStatsMap
* server_network_stats_map
,
567 bool detected_corrupted_prefs
) {
568 // Preferences have the master data because admins might have pushed new
569 // preferences. Update the cached data with new data from preferences.
570 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
572 UMA_HISTOGRAM_COUNTS("Net.CountOfSpdyServers", spdy_servers
->size());
573 http_server_properties_impl_
->InitializeSpdyServers(spdy_servers
, true);
575 // Update the cached data and use the new spdy_settings from preferences.
576 UMA_HISTOGRAM_COUNTS("Net.CountOfSpdySettings", spdy_settings_map
->size());
577 http_server_properties_impl_
->InitializeSpdySettingsServers(
580 // Update the cached data and use the new Alternate-Protocol server list from
582 UMA_HISTOGRAM_COUNTS("Net.CountOfAlternateProtocolServers",
583 alternate_protocol_map
->size());
584 http_server_properties_impl_
->InitializeAlternateProtocolServers(
585 alternate_protocol_map
);
587 http_server_properties_impl_
->InitializeSupportsQuic(last_quic_address
);
589 http_server_properties_impl_
->InitializeServerNetworkStats(
590 server_network_stats_map
);
592 // Update the prefs with what we have read (delete all corrupted prefs).
593 if (detected_corrupted_prefs
)
594 ScheduleUpdatePrefsOnNetworkThread();
598 // Update Preferences with data from the cached data.
600 void HttpServerPropertiesManager::ScheduleUpdatePrefsOnNetworkThread() {
601 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
602 // Cancel pending updates, if any.
603 network_prefs_update_timer_
->Stop();
604 StartPrefsUpdateTimerOnNetworkThread(
605 base::TimeDelta::FromMilliseconds(kUpdatePrefsDelayMs
));
608 void HttpServerPropertiesManager::StartPrefsUpdateTimerOnNetworkThread(
609 base::TimeDelta delay
) {
610 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
611 // This is overridden in tests to post the task without the delay.
612 network_prefs_update_timer_
->Start(
616 &HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread
);
619 // This is required so we can set this as the callback for a timer.
620 void HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread() {
621 UpdatePrefsFromCacheOnNetworkThread(base::Closure());
624 void HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread(
625 const base::Closure
& completion
) {
626 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
628 base::ListValue
* spdy_server_list
= new base::ListValue
;
629 http_server_properties_impl_
->GetSpdyServerList(
630 spdy_server_list
, kMaxSupportsSpdyServerHostsToPersist
);
632 SpdySettingsMap
* spdy_settings_map
=
633 new SpdySettingsMap(kMaxSpdySettingsHostsToPersist
);
634 const SpdySettingsMap
& main_map
=
635 http_server_properties_impl_
->spdy_settings_map();
637 for (SpdySettingsMap::const_iterator it
= main_map
.begin();
638 it
!= main_map
.end() && count
< kMaxSpdySettingsHostsToPersist
;
640 spdy_settings_map
->Put(it
->first
, it
->second
);
643 AlternateProtocolMap
* alternate_protocol_map
=
644 new AlternateProtocolMap(kMaxAlternateProtocolHostsToPersist
);
645 const AlternateProtocolMap
& map
=
646 http_server_properties_impl_
->alternate_protocol_map();
648 typedef std::map
<std::string
, bool> CanonicalHostPersistedMap
;
649 CanonicalHostPersistedMap persisted_map
;
650 for (AlternateProtocolMap::const_iterator it
= map
.begin();
651 it
!= map
.end() && count
< kMaxAlternateProtocolHostsToPersist
; ++it
) {
652 const HostPortPair
& server
= it
->first
;
653 std::string canonical_suffix
=
654 http_server_properties_impl_
->GetCanonicalSuffix(server
.host());
655 if (!canonical_suffix
.empty()) {
656 if (persisted_map
.find(canonical_suffix
) != persisted_map
.end())
658 persisted_map
[canonical_suffix
] = true;
660 alternate_protocol_map
->Put(server
, it
->second
);
664 ServerNetworkStatsMap
* server_network_stats_map
=
665 new ServerNetworkStatsMap(kMaxServerNetworkStatsHostsToPersist
);
666 const ServerNetworkStatsMap
& main_server_network_stats_map
=
667 http_server_properties_impl_
->server_network_stats_map();
668 for (ServerNetworkStatsMap::const_iterator it
=
669 main_server_network_stats_map
.begin();
670 it
!= main_server_network_stats_map
.end(); ++it
) {
671 server_network_stats_map
->Put(it
->first
, it
->second
);
674 IPAddressNumber
* last_quic_addr
= new IPAddressNumber
;
675 http_server_properties_impl_
->GetSupportsQuic(last_quic_addr
);
676 // Update the preferences on the pref thread.
677 pref_task_runner_
->PostTask(
680 &HttpServerPropertiesManager::UpdatePrefsOnPrefThread
, pref_weak_ptr_
,
681 base::Owned(spdy_server_list
), base::Owned(spdy_settings_map
),
682 base::Owned(alternate_protocol_map
), base::Owned(last_quic_addr
),
683 base::Owned(server_network_stats_map
), completion
));
686 // A local or temporary data structure to hold |supports_spdy|, SpdySettings,
687 // AlternateProtocolInfo and SupportsQuic preferences for a server. This is used
688 // only in UpdatePrefsOnPrefThread.
691 : supports_spdy(false),
693 alternate_protocol(NULL
),
695 server_network_stats(NULL
) {}
696 ServerPref(bool supports_spdy
,
697 const SettingsMap
* settings_map
,
698 const AlternateProtocolInfo
* alternate_protocol
,
699 const SupportsQuic
* supports_quic
,
700 const ServerNetworkStats
* server_network_stats
)
701 : supports_spdy(supports_spdy
),
702 settings_map(settings_map
),
703 alternate_protocol(alternate_protocol
),
704 supports_quic(supports_quic
),
705 server_network_stats(server_network_stats
) {}
707 const SettingsMap
* settings_map
;
708 const AlternateProtocolInfo
* alternate_protocol
;
709 const SupportsQuic
* supports_quic
;
710 const ServerNetworkStats
* server_network_stats
;
713 void HttpServerPropertiesManager::UpdatePrefsOnPrefThread(
714 base::ListValue
* spdy_server_list
,
715 SpdySettingsMap
* spdy_settings_map
,
716 AlternateProtocolMap
* alternate_protocol_map
,
717 IPAddressNumber
* last_quic_address
,
718 ServerNetworkStatsMap
* server_network_stats_map
,
719 const base::Closure
& completion
) {
720 typedef std::map
<HostPortPair
, ServerPref
> ServerPrefMap
;
721 ServerPrefMap server_pref_map
;
723 DCHECK(pref_task_runner_
->RunsTasksOnCurrentThread());
725 // Add servers that support spdy to server_pref_map.
727 for (base::ListValue::const_iterator list_it
= spdy_server_list
->begin();
728 list_it
!= spdy_server_list
->end();
730 if ((*list_it
)->GetAsString(&s
)) {
731 HostPortPair server
= HostPortPair::FromString(s
);
732 server_pref_map
[server
].supports_spdy
= true;
736 // Add servers that have SpdySettings to server_pref_map.
737 for (SpdySettingsMap::iterator map_it
= spdy_settings_map
->begin();
738 map_it
!= spdy_settings_map
->end(); ++map_it
) {
739 const HostPortPair
& server
= map_it
->first
;
740 server_pref_map
[server
].settings_map
= &map_it
->second
;
743 // Add AlternateProtocol servers to server_pref_map.
744 for (AlternateProtocolMap::const_iterator map_it
=
745 alternate_protocol_map
->begin();
746 map_it
!= alternate_protocol_map
->end(); ++map_it
) {
747 const HostPortPair
& server
= map_it
->first
;
748 const AlternateProtocolInfo
& port_alternate_protocol
= map_it
->second
;
749 if (!IsAlternateProtocolValid(port_alternate_protocol
.protocol
)) {
752 server_pref_map
[server
].alternate_protocol
= &map_it
->second
;
755 // Add ServerNetworkStats servers to server_pref_map.
756 for (ServerNetworkStatsMap::const_iterator map_it
=
757 server_network_stats_map
->begin();
758 map_it
!= server_network_stats_map
->end(); ++map_it
) {
759 const HostPortPair
& server
= map_it
->first
;
760 server_pref_map
[server
].server_network_stats
= &map_it
->second
;
763 // Persist properties to the |path_|.
764 base::DictionaryValue http_server_properties_dict
;
765 base::DictionaryValue
* servers_dict
= new base::DictionaryValue
;
766 for (ServerPrefMap::const_iterator map_it
= server_pref_map
.begin();
767 map_it
!= server_pref_map
.end();
769 const HostPortPair
& server
= map_it
->first
;
770 const ServerPref
& server_pref
= map_it
->second
;
772 base::DictionaryValue
* server_pref_dict
= new base::DictionaryValue
;
774 // Save supports_spdy.
775 if (server_pref
.supports_spdy
)
776 server_pref_dict
->SetBoolean(kSupportsSpdyKey
, server_pref
.supports_spdy
);
777 SaveSpdySettingsToServerPrefs(server_pref
.settings_map
, server_pref_dict
);
778 SaveAlternateProtocolToServerPrefs(server_pref
.alternate_protocol
,
780 SaveNetworkStatsToServerPrefs(server_pref
.server_network_stats
,
783 servers_dict
->SetWithoutPathExpansion(server
.ToString(), server_pref_dict
);
786 http_server_properties_dict
.SetWithoutPathExpansion(kServersKey
,
788 SetVersion(&http_server_properties_dict
, kVersionNumber
);
790 SaveSupportsQuicToPrefs(last_quic_address
, &http_server_properties_dict
);
792 setting_prefs_
= true;
793 pref_service_
->Set(path_
, http_server_properties_dict
);
794 setting_prefs_
= false;
796 // Note that |completion| will be fired after we have written everything to
797 // the Preferences, but likely before these changes are serialized to disk.
798 // This is not a problem though, as JSONPrefStore guarantees that this will
799 // happen, pretty soon, and even in the case we shut down immediately.
800 if (!completion
.is_null())
804 void HttpServerPropertiesManager::SaveSpdySettingsToServerPrefs(
805 const SettingsMap
* settings_map
,
806 base::DictionaryValue
* server_pref_dict
) {
810 base::DictionaryValue
* spdy_settings_dict
= new base::DictionaryValue
;
811 for (SettingsMap::const_iterator it
= settings_map
->begin();
812 it
!= settings_map
->end(); ++it
) {
813 SpdySettingsIds id
= it
->first
;
814 uint32 value
= it
->second
.second
;
815 std::string key
= base::StringPrintf("%u", id
);
816 spdy_settings_dict
->SetInteger(key
, value
);
818 server_pref_dict
->SetWithoutPathExpansion(kSettingsKey
, spdy_settings_dict
);
821 void HttpServerPropertiesManager::SaveAlternateProtocolToServerPrefs(
822 const AlternateProtocolInfo
* port_alternate_protocol
,
823 base::DictionaryValue
* server_pref_dict
) {
824 if (!port_alternate_protocol
|| port_alternate_protocol
->is_broken
)
827 base::DictionaryValue
* port_alternate_protocol_dict
=
828 new base::DictionaryValue
;
829 port_alternate_protocol_dict
->SetInteger(kPortKey
,
830 port_alternate_protocol
->port
);
831 const char* protocol_str
=
832 AlternateProtocolToString(port_alternate_protocol
->protocol
);
833 port_alternate_protocol_dict
->SetString(kProtocolKey
, protocol_str
);
834 port_alternate_protocol_dict
->SetDouble(kProbabilityKey
,
835 port_alternate_protocol
->probability
);
836 server_pref_dict
->SetWithoutPathExpansion(kAlternateProtocolKey
,
837 port_alternate_protocol_dict
);
840 void HttpServerPropertiesManager::SaveSupportsQuicToPrefs(
841 const IPAddressNumber
* last_quic_address
,
842 base::DictionaryValue
* http_server_properties_dict
) {
843 if (!last_quic_address
|| last_quic_address
->empty())
846 base::DictionaryValue
* supports_quic_dict
= new base::DictionaryValue
;
847 supports_quic_dict
->SetBoolean(kUsedQuicKey
, true);
848 supports_quic_dict
->SetString(kAddressKey
,
849 IPAddressToString(*last_quic_address
));
850 http_server_properties_dict
->SetWithoutPathExpansion(kSupportsQuicKey
,
854 void HttpServerPropertiesManager::SaveNetworkStatsToServerPrefs(
855 const ServerNetworkStats
* server_network_stats
,
856 base::DictionaryValue
* server_pref_dict
) {
857 if (!server_network_stats
)
860 base::DictionaryValue
* server_network_stats_dict
= new base::DictionaryValue
;
861 // Becasue JSON doesn't support int64, persist int64 as a string.
862 server_network_stats_dict
->SetInteger(
863 kSrttKey
, static_cast<int>(server_network_stats
->srtt
.ToInternalValue()));
864 // TODO(rtenneti): When QUIC starts using bandwidth_estimate, then persist
865 // bandwidth_estimate.
866 server_pref_dict
->SetWithoutPathExpansion(kNetworkStatsKey
,
867 server_network_stats_dict
);
870 void HttpServerPropertiesManager::OnHttpServerPropertiesChanged() {
871 DCHECK(pref_task_runner_
->RunsTasksOnCurrentThread());
873 ScheduleUpdateCacheOnPrefThread();