1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/http/http_server_properties_manager.h"
8 #include "base/metrics/histogram.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/rand_util.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/stl_util.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/stringprintf.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "base/values.h"
22 // Time to wait before starting an update the http_server_properties_impl_ cache
23 // from preferences. Scheduling another update during this period will reset the
25 const int64 kUpdateCacheDelayMs
= 1000;
27 // Time to wait before starting an update the preferences from the
28 // http_server_properties_impl_ cache. Scheduling another update during this
29 // period will reset the timer.
30 const int64 kUpdatePrefsDelayMs
= 5000;
32 // "version" 0 indicates, http_server_properties doesn't have "version"
34 const int kMissingVersion
= 0;
36 // The version number of persisted http_server_properties.
37 const int kVersionNumber
= 3;
39 typedef std::vector
<std::string
> StringVector
;
41 // Load either 200 or 1000 servers based on a coin flip.
42 const int k200AlternateProtocolHostsToLoad
= 200;
43 const int k1000AlternateProtocolHostsToLoad
= 1000;
44 // Persist 1000 MRU AlternateProtocolHostPortPairs.
45 const int kMaxAlternateProtocolHostsToPersist
= 1000;
47 // Persist 200 MRU SpdySettingsHostPortPairs.
48 const int kMaxSpdySettingsHostsToPersist
= 200;
50 // Persist 300 MRU SupportsSpdyServerHostPortPairs.
51 const int kMaxSupportsSpdyServerHostsToPersist
= 300;
55 ////////////////////////////////////////////////////////////////////////////////
56 // HttpServerPropertiesManager
58 HttpServerPropertiesManager::HttpServerPropertiesManager(
59 PrefService
* pref_service
,
60 const char* pref_path
,
61 scoped_refptr
<base::SequencedTaskRunner
> network_task_runner
)
62 : pref_task_runner_(base::ThreadTaskRunnerHandle::Get()),
63 pref_service_(pref_service
),
64 setting_prefs_(false),
66 network_task_runner_(network_task_runner
) {
68 pref_weak_ptr_factory_
.reset(
69 new base::WeakPtrFactory
<HttpServerPropertiesManager
>(this));
70 pref_weak_ptr_
= pref_weak_ptr_factory_
->GetWeakPtr();
71 pref_cache_update_timer_
.reset(
72 new base::OneShotTimer
<HttpServerPropertiesManager
>);
73 pref_change_registrar_
.Init(pref_service_
);
74 pref_change_registrar_
.Add(
76 base::Bind(&HttpServerPropertiesManager::OnHttpServerPropertiesChanged
,
77 base::Unretained(this)));
80 HttpServerPropertiesManager::~HttpServerPropertiesManager() {
81 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
82 network_weak_ptr_factory_
.reset();
85 void HttpServerPropertiesManager::InitializeOnNetworkThread() {
86 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
87 network_weak_ptr_factory_
.reset(
88 new base::WeakPtrFactory
<HttpServerPropertiesManager
>(this));
89 http_server_properties_impl_
.reset(new net::HttpServerPropertiesImpl());
91 network_prefs_update_timer_
.reset(
92 new base::OneShotTimer
<HttpServerPropertiesManager
>);
94 pref_task_runner_
->PostTask(
96 base::Bind(&HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread
,
100 void HttpServerPropertiesManager::ShutdownOnPrefThread() {
101 DCHECK(pref_task_runner_
->RunsTasksOnCurrentThread());
102 // Cancel any pending updates, and stop listening for pref change updates.
103 pref_cache_update_timer_
->Stop();
104 pref_weak_ptr_factory_
.reset();
105 pref_change_registrar_
.RemoveAll();
109 void HttpServerPropertiesManager::SetVersion(
110 base::DictionaryValue
* http_server_properties_dict
,
111 int version_number
) {
112 if (version_number
< 0)
113 version_number
= kVersionNumber
;
114 DCHECK_LE(version_number
, kVersionNumber
);
115 if (version_number
<= kVersionNumber
)
116 http_server_properties_dict
->SetInteger("version", version_number
);
119 // This is required for conformance with the HttpServerProperties interface.
120 base::WeakPtr
<net::HttpServerProperties
>
121 HttpServerPropertiesManager::GetWeakPtr() {
122 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
123 return network_weak_ptr_factory_
->GetWeakPtr();
126 void HttpServerPropertiesManager::Clear() {
127 Clear(base::Closure());
130 void HttpServerPropertiesManager::Clear(const base::Closure
& completion
) {
131 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
133 http_server_properties_impl_
->Clear();
134 UpdatePrefsFromCacheOnNetworkThread(completion
);
137 bool HttpServerPropertiesManager::SupportsSpdy(
138 const net::HostPortPair
& server
) {
139 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
140 return http_server_properties_impl_
->SupportsSpdy(server
);
143 void HttpServerPropertiesManager::SetSupportsSpdy(
144 const net::HostPortPair
& server
,
146 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
148 http_server_properties_impl_
->SetSupportsSpdy(server
, support_spdy
);
149 ScheduleUpdatePrefsOnNetworkThread();
152 bool HttpServerPropertiesManager::HasAlternateProtocol(
153 const net::HostPortPair
& server
) {
154 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
155 return http_server_properties_impl_
->HasAlternateProtocol(server
);
158 net::AlternateProtocolInfo
159 HttpServerPropertiesManager::GetAlternateProtocol(
160 const net::HostPortPair
& server
) {
161 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
162 return http_server_properties_impl_
->GetAlternateProtocol(server
);
165 void HttpServerPropertiesManager::SetAlternateProtocol(
166 const net::HostPortPair
& server
,
167 uint16 alternate_port
,
168 AlternateProtocol alternate_protocol
,
169 double alternate_probability
) {
170 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
171 http_server_properties_impl_
->SetAlternateProtocol(
172 server
, alternate_port
, alternate_protocol
, alternate_probability
);
173 ScheduleUpdatePrefsOnNetworkThread();
176 void HttpServerPropertiesManager::SetBrokenAlternateProtocol(
177 const net::HostPortPair
& server
) {
178 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
179 http_server_properties_impl_
->SetBrokenAlternateProtocol(server
);
180 ScheduleUpdatePrefsOnNetworkThread();
183 bool HttpServerPropertiesManager::WasAlternateProtocolRecentlyBroken(
184 const net::HostPortPair
& server
) {
185 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
186 return http_server_properties_impl_
->WasAlternateProtocolRecentlyBroken(
190 void HttpServerPropertiesManager::ConfirmAlternateProtocol(
191 const net::HostPortPair
& server
) {
192 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
193 http_server_properties_impl_
->ConfirmAlternateProtocol(server
);
194 ScheduleUpdatePrefsOnNetworkThread();
197 void HttpServerPropertiesManager::ClearAlternateProtocol(
198 const net::HostPortPair
& server
) {
199 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
200 http_server_properties_impl_
->ClearAlternateProtocol(server
);
201 ScheduleUpdatePrefsOnNetworkThread();
204 const net::AlternateProtocolMap
&
205 HttpServerPropertiesManager::alternate_protocol_map() const {
206 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
207 return http_server_properties_impl_
->alternate_protocol_map();
210 void HttpServerPropertiesManager::SetAlternateProtocolExperiment(
211 AlternateProtocolExperiment experiment
) {
212 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
213 http_server_properties_impl_
->SetAlternateProtocolExperiment(experiment
);
216 void HttpServerPropertiesManager::SetAlternateProtocolProbabilityThreshold(
218 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
219 http_server_properties_impl_
->SetAlternateProtocolProbabilityThreshold(
223 AlternateProtocolExperiment
224 HttpServerPropertiesManager::GetAlternateProtocolExperiment() const {
225 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
226 return http_server_properties_impl_
->GetAlternateProtocolExperiment();
229 const SettingsMap
& HttpServerPropertiesManager::GetSpdySettings(
230 const HostPortPair
& host_port_pair
) {
231 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
232 return http_server_properties_impl_
->GetSpdySettings(host_port_pair
);
235 bool HttpServerPropertiesManager::SetSpdySetting(
236 const HostPortPair
& host_port_pair
,
238 SpdySettingsFlags flags
,
240 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
241 bool persist
= http_server_properties_impl_
->SetSpdySetting(
242 host_port_pair
, id
, flags
, value
);
244 ScheduleUpdatePrefsOnNetworkThread();
248 void HttpServerPropertiesManager::ClearSpdySettings(
249 const HostPortPair
& host_port_pair
) {
250 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
251 http_server_properties_impl_
->ClearSpdySettings(host_port_pair
);
252 ScheduleUpdatePrefsOnNetworkThread();
255 void HttpServerPropertiesManager::ClearAllSpdySettings() {
256 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
257 http_server_properties_impl_
->ClearAllSpdySettings();
258 ScheduleUpdatePrefsOnNetworkThread();
261 const SpdySettingsMap
& HttpServerPropertiesManager::spdy_settings_map()
263 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
264 return http_server_properties_impl_
->spdy_settings_map();
268 HttpServerPropertiesManager::GetSupportsQuic(
269 const net::HostPortPair
& host_port_pair
) const {
270 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
271 return http_server_properties_impl_
->GetSupportsQuic(host_port_pair
);
274 void HttpServerPropertiesManager::SetSupportsQuic(
275 const net::HostPortPair
& host_port_pair
,
277 const std::string
& address
) {
278 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
279 http_server_properties_impl_
->SetSupportsQuic(
280 host_port_pair
, used_quic
, address
);
281 ScheduleUpdatePrefsOnNetworkThread();
284 const SupportsQuicMap
& HttpServerPropertiesManager::supports_quic_map()
286 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
287 return http_server_properties_impl_
->supports_quic_map();
290 void HttpServerPropertiesManager::SetServerNetworkStats(
291 const net::HostPortPair
& host_port_pair
,
292 NetworkStats stats
) {
293 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
294 http_server_properties_impl_
->SetServerNetworkStats(host_port_pair
, stats
);
297 const HttpServerPropertiesManager::NetworkStats
*
298 HttpServerPropertiesManager::GetServerNetworkStats(
299 const net::HostPortPair
& host_port_pair
) const {
300 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
301 return http_server_properties_impl_
->GetServerNetworkStats(host_port_pair
);
305 // Update the HttpServerPropertiesImpl's cache with data from preferences.
307 void HttpServerPropertiesManager::ScheduleUpdateCacheOnPrefThread() {
308 DCHECK(pref_task_runner_
->RunsTasksOnCurrentThread());
309 // Cancel pending updates, if any.
310 pref_cache_update_timer_
->Stop();
311 StartCacheUpdateTimerOnPrefThread(
312 base::TimeDelta::FromMilliseconds(kUpdateCacheDelayMs
));
315 void HttpServerPropertiesManager::StartCacheUpdateTimerOnPrefThread(
316 base::TimeDelta delay
) {
317 DCHECK(pref_task_runner_
->RunsTasksOnCurrentThread());
318 pref_cache_update_timer_
->Start(
322 &HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread
);
325 void HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread() {
326 // The preferences can only be read on the pref thread.
327 DCHECK(pref_task_runner_
->RunsTasksOnCurrentThread());
329 if (!pref_service_
->HasPrefPath(path_
))
332 bool detected_corrupted_prefs
= false;
333 const base::DictionaryValue
& http_server_properties_dict
=
334 *pref_service_
->GetDictionary(path_
);
336 int version
= kMissingVersion
;
337 if (!http_server_properties_dict
.GetIntegerWithoutPathExpansion("version",
339 DVLOG(1) << "Missing version. Clearing all properties.";
343 // The properties for a given server is in
344 // http_server_properties_dict["servers"][server].
345 const base::DictionaryValue
* servers_dict
= NULL
;
346 if (!http_server_properties_dict
.GetDictionaryWithoutPathExpansion(
347 "servers", &servers_dict
)) {
348 DVLOG(1) << "Malformed http_server_properties for servers.";
352 // String is host/port pair of spdy server.
353 scoped_ptr
<StringVector
> spdy_servers(new StringVector
);
354 scoped_ptr
<net::SpdySettingsMap
> spdy_settings_map(
355 new net::SpdySettingsMap(kMaxSpdySettingsHostsToPersist
));
356 scoped_ptr
<net::AlternateProtocolMap
> alternate_protocol_map(
357 new net::AlternateProtocolMap(kMaxAlternateProtocolHostsToPersist
));
358 scoped_ptr
<net::SupportsQuicMap
> supports_quic_map(
359 new net::SupportsQuicMap());
360 // TODO(rtenneti): Delete the following code after the experiment.
361 int alternate_protocols_to_load
= k200AlternateProtocolHostsToLoad
;
362 net::AlternateProtocolExperiment alternate_protocol_experiment
=
363 net::ALTERNATE_PROTOCOL_NOT_PART_OF_EXPERIMENT
;
364 if (version
== kVersionNumber
) {
365 if (base::RandInt(0, 99) == 0) {
366 alternate_protocol_experiment
=
367 net::ALTERNATE_PROTOCOL_TRUNCATED_200_SERVERS
;
369 alternate_protocols_to_load
= k1000AlternateProtocolHostsToLoad
;
370 alternate_protocol_experiment
=
371 net::ALTERNATE_PROTOCOL_TRUNCATED_1000_SERVERS
;
373 DVLOG(1) << "# of servers that support alternate_protocol: "
374 << alternate_protocols_to_load
;
378 for (base::DictionaryValue::Iterator
it(*servers_dict
); !it
.IsAtEnd();
380 // Get server's host/pair.
381 const std::string
& server_str
= it
.key();
382 net::HostPortPair server
= net::HostPortPair::FromString(server_str
);
383 if (server
.host().empty()) {
384 DVLOG(1) << "Malformed http_server_properties for server: " << server_str
;
385 detected_corrupted_prefs
= true;
389 const base::DictionaryValue
* server_pref_dict
= NULL
;
390 if (!it
.value().GetAsDictionary(&server_pref_dict
)) {
391 DVLOG(1) << "Malformed http_server_properties server: " << server_str
;
392 detected_corrupted_prefs
= true;
396 // Get if server supports Spdy.
397 bool supports_spdy
= false;
398 if ((server_pref_dict
->GetBoolean("supports_spdy", &supports_spdy
)) &&
400 spdy_servers
->push_back(server_str
);
404 DCHECK(spdy_settings_map
->Peek(server
) == spdy_settings_map
->end());
405 const base::DictionaryValue
* spdy_settings_dict
= NULL
;
406 if (server_pref_dict
->GetDictionaryWithoutPathExpansion(
407 "settings", &spdy_settings_dict
)) {
408 net::SettingsMap settings_map
;
409 for (base::DictionaryValue::Iterator
dict_it(*spdy_settings_dict
);
412 const std::string
& id_str
= dict_it
.key();
414 if (!base::StringToInt(id_str
, &id
)) {
415 DVLOG(1) << "Malformed id in SpdySettings for server: " << server_str
;
420 if (!dict_it
.value().GetAsInteger(&value
)) {
421 DVLOG(1) << "Malformed value in SpdySettings for server: "
426 net::SettingsFlagsAndValue
flags_and_value(net::SETTINGS_FLAG_PERSISTED
,
428 settings_map
[static_cast<net::SpdySettingsIds
>(id
)] = flags_and_value
;
430 spdy_settings_map
->Put(server
, settings_map
);
433 // Get alternate_protocol server.
434 DCHECK(alternate_protocol_map
->Peek(server
) ==
435 alternate_protocol_map
->end());
436 const base::DictionaryValue
* port_alternate_protocol_dict
= NULL
;
437 if (!server_pref_dict
->GetDictionaryWithoutPathExpansion(
438 "alternate_protocol", &port_alternate_protocol_dict
)) {
442 if (count
>= alternate_protocols_to_load
)
446 if (!port_alternate_protocol_dict
->GetIntegerWithoutPathExpansion(
448 (port
> (1 << 16))) {
449 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str
;
450 detected_corrupted_prefs
= true;
453 std::string protocol_str
;
454 if (!port_alternate_protocol_dict
->GetStringWithoutPathExpansion(
455 "protocol_str", &protocol_str
)) {
456 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str
;
457 detected_corrupted_prefs
= true;
460 net::AlternateProtocol protocol
=
461 net::AlternateProtocolFromString(protocol_str
);
462 if (!net::IsAlternateProtocolValid(protocol
)) {
463 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str
;
464 detected_corrupted_prefs
= true;
468 double probability
= 1;
469 if (port_alternate_protocol_dict
->HasKey("probability") &&
470 !port_alternate_protocol_dict
->GetDoubleWithoutPathExpansion(
471 "probability", &probability
)) {
472 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str
;
473 detected_corrupted_prefs
= true;
477 net::AlternateProtocolInfo
port_alternate_protocol(port
,
480 alternate_protocol_map
->Put(server
, port_alternate_protocol
);
485 DCHECK(supports_quic_map
->find(server
) == supports_quic_map
->end());
486 const base::DictionaryValue
* supports_quic_dict
= NULL
;
487 if (!server_pref_dict
->GetDictionaryWithoutPathExpansion(
488 "supports_quic", &supports_quic_dict
)) {
493 if (!supports_quic_dict
->GetBooleanWithoutPathExpansion(
494 "used_quic", &used_quic
)) {
495 DVLOG(1) << "Malformed SupportsQuic server: " << server_str
;
496 detected_corrupted_prefs
= true;
500 if (!supports_quic_dict
->GetStringWithoutPathExpansion(
501 "address", &address
)) {
502 DVLOG(1) << "Malformed SupportsQuic server: " << server_str
;
503 detected_corrupted_prefs
= true;
506 net::SupportsQuic
supports_quic(used_quic
, address
);
507 supports_quic_map
->insert(std::make_pair(server
, supports_quic
));
511 network_task_runner_
->PostTask(
514 &HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread
,
515 base::Unretained(this),
516 base::Owned(spdy_servers
.release()),
517 base::Owned(spdy_settings_map
.release()),
518 base::Owned(alternate_protocol_map
.release()),
519 alternate_protocol_experiment
,
520 base::Owned(supports_quic_map
.release()),
521 detected_corrupted_prefs
));
524 void HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread(
525 StringVector
* spdy_servers
,
526 net::SpdySettingsMap
* spdy_settings_map
,
527 net::AlternateProtocolMap
* alternate_protocol_map
,
528 net::AlternateProtocolExperiment alternate_protocol_experiment
,
529 net::SupportsQuicMap
* supports_quic_map
,
530 bool detected_corrupted_prefs
) {
531 // Preferences have the master data because admins might have pushed new
532 // preferences. Update the cached data with new data from preferences.
533 DCHECK(network_task_runner_
->RunsTasksOnCurrentThread());
535 UMA_HISTOGRAM_COUNTS("Net.CountOfSpdyServers", spdy_servers
->size());
536 http_server_properties_impl_
->InitializeSpdyServers(spdy_servers
, true);
538 // Update the cached data and use the new spdy_settings from preferences.
539 UMA_HISTOGRAM_COUNTS("Net.CountOfSpdySettings", spdy_settings_map
->size());
540 http_server_properties_impl_
->InitializeSpdySettingsServers(
543 // Update the cached data and use the new Alternate-Protocol server list from
545 UMA_HISTOGRAM_COUNTS("Net.CountOfAlternateProtocolServers",
546 alternate_protocol_map
->size());
547 http_server_properties_impl_
->InitializeAlternateProtocolServers(
548 alternate_protocol_map
);
549 http_server_properties_impl_
->SetAlternateProtocolExperiment(
550 alternate_protocol_experiment
);
552 http_server_properties_impl_
->InitializeSupportsQuic(supports_quic_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 net::SpdySettingsMap
* spdy_settings_map
=
595 new net::SpdySettingsMap(kMaxSpdySettingsHostsToPersist
);
596 const net::SpdySettingsMap
& main_map
=
597 http_server_properties_impl_
->spdy_settings_map();
599 for (net::SpdySettingsMap::const_iterator it
= main_map
.begin();
600 it
!= main_map
.end() && count
< kMaxSpdySettingsHostsToPersist
;
602 spdy_settings_map
->Put(it
->first
, it
->second
);
605 net::AlternateProtocolMap
* alternate_protocol_map
=
606 new net::AlternateProtocolMap(kMaxAlternateProtocolHostsToPersist
);
607 const net::AlternateProtocolMap
& map
=
608 http_server_properties_impl_
->alternate_protocol_map();
610 typedef std::map
<std::string
, bool> CanonicalHostPersistedMap
;
611 CanonicalHostPersistedMap persisted_map
;
612 for (net::AlternateProtocolMap::const_iterator it
= map
.begin();
613 it
!= map
.end() && count
< kMaxAlternateProtocolHostsToPersist
;
615 const net::HostPortPair
& server
= it
->first
;
616 std::string canonical_suffix
=
617 http_server_properties_impl_
->GetCanonicalSuffix(server
);
618 if (!canonical_suffix
.empty()) {
619 if (persisted_map
.find(canonical_suffix
) != persisted_map
.end())
621 persisted_map
[canonical_suffix
] = true;
623 alternate_protocol_map
->Put(server
, it
->second
);
627 net::SupportsQuicMap
* supports_quic_map
= new net::SupportsQuicMap();
628 const net::SupportsQuicMap
& main_supports_quic_map
=
629 http_server_properties_impl_
->supports_quic_map();
630 for (net::SupportsQuicMap::const_iterator it
= main_supports_quic_map
.begin();
631 it
!= main_supports_quic_map
.end(); ++it
) {
632 supports_quic_map
->insert(std::make_pair(it
->first
, it
->second
));
635 // Update the preferences on the pref thread.
636 pref_task_runner_
->PostTask(
638 base::Bind(&HttpServerPropertiesManager::UpdatePrefsOnPrefThread
,
640 base::Owned(spdy_server_list
),
641 base::Owned(spdy_settings_map
),
642 base::Owned(alternate_protocol_map
),
643 base::Owned(supports_quic_map
),
647 // A local or temporary data structure to hold |supports_spdy|, SpdySettings,
648 // AlternateProtocolInfo and SupportsQuic preferences for a server. This is used
649 // only in UpdatePrefsOnPrefThread.
651 ServerPref() : supports_spdy(false),
653 alternate_protocol(NULL
),
654 supports_quic(NULL
) {}
655 ServerPref(bool supports_spdy
,
656 const net::SettingsMap
* settings_map
,
657 const net::AlternateProtocolInfo
* alternate_protocol
,
658 const net::SupportsQuic
* supports_quic
)
659 : supports_spdy(supports_spdy
),
660 settings_map(settings_map
),
661 alternate_protocol(alternate_protocol
),
662 supports_quic(supports_quic
) {}
664 const net::SettingsMap
* settings_map
;
665 const net::AlternateProtocolInfo
* alternate_protocol
;
666 const net::SupportsQuic
* supports_quic
;
669 void HttpServerPropertiesManager::UpdatePrefsOnPrefThread(
670 base::ListValue
* spdy_server_list
,
671 net::SpdySettingsMap
* spdy_settings_map
,
672 net::AlternateProtocolMap
* alternate_protocol_map
,
673 net::SupportsQuicMap
* supports_quic_map
,
674 const base::Closure
& completion
) {
675 typedef std::map
<net::HostPortPair
, ServerPref
> ServerPrefMap
;
676 ServerPrefMap server_pref_map
;
678 DCHECK(pref_task_runner_
->RunsTasksOnCurrentThread());
680 // Add servers that support spdy to server_pref_map.
682 for (base::ListValue::const_iterator list_it
= spdy_server_list
->begin();
683 list_it
!= spdy_server_list
->end();
685 if ((*list_it
)->GetAsString(&s
)) {
686 net::HostPortPair server
= net::HostPortPair::FromString(s
);
688 ServerPrefMap::iterator it
= server_pref_map
.find(server
);
689 if (it
== server_pref_map
.end()) {
690 ServerPref
server_pref(true, NULL
, NULL
, NULL
);
691 server_pref_map
[server
] = server_pref
;
693 it
->second
.supports_spdy
= true;
698 // Add servers that have SpdySettings to server_pref_map.
699 for (net::SpdySettingsMap::iterator map_it
= spdy_settings_map
->begin();
700 map_it
!= spdy_settings_map
->end();
702 const net::HostPortPair
& server
= map_it
->first
;
704 ServerPrefMap::iterator it
= server_pref_map
.find(server
);
705 if (it
== server_pref_map
.end()) {
706 ServerPref
server_pref(false, &map_it
->second
, NULL
, NULL
);
707 server_pref_map
[server
] = server_pref
;
709 it
->second
.settings_map
= &map_it
->second
;
713 // Add AlternateProtocol servers to server_pref_map.
714 for (net::AlternateProtocolMap::const_iterator map_it
=
715 alternate_protocol_map
->begin();
716 map_it
!= alternate_protocol_map
->end();
718 const net::HostPortPair
& server
= map_it
->first
;
719 const net::AlternateProtocolInfo
& port_alternate_protocol
=
721 if (!net::IsAlternateProtocolValid(port_alternate_protocol
.protocol
)) {
725 ServerPrefMap::iterator it
= server_pref_map
.find(server
);
726 if (it
== server_pref_map
.end()) {
727 ServerPref
server_pref(false, NULL
, &map_it
->second
, NULL
);
728 server_pref_map
[server
] = server_pref
;
730 it
->second
.alternate_protocol
= &map_it
->second
;
734 // Add SupportsQuic servers to server_pref_map.
735 for (net::SupportsQuicMap::const_iterator map_it
= supports_quic_map
->begin();
736 map_it
!= supports_quic_map
->end(); ++map_it
) {
737 const net::HostPortPair
& server
= map_it
->first
;
739 ServerPrefMap::iterator it
= server_pref_map
.find(server
);
740 if (it
== server_pref_map
.end()) {
741 ServerPref
server_pref(false, NULL
, NULL
, &map_it
->second
);
742 server_pref_map
[server
] = server_pref
;
744 it
->second
.supports_quic
= &map_it
->second
;
748 // Persist properties to the |path_|.
749 base::DictionaryValue http_server_properties_dict
;
750 base::DictionaryValue
* servers_dict
= new base::DictionaryValue
;
751 for (ServerPrefMap::const_iterator map_it
= server_pref_map
.begin();
752 map_it
!= server_pref_map
.end();
754 const net::HostPortPair
& server
= map_it
->first
;
755 const ServerPref
& server_pref
= map_it
->second
;
757 base::DictionaryValue
* server_pref_dict
= new base::DictionaryValue
;
759 // Save supports_spdy.
760 if (server_pref
.supports_spdy
)
761 server_pref_dict
->SetBoolean("supports_spdy", server_pref
.supports_spdy
);
763 // Save SPDY settings.
764 if (server_pref
.settings_map
) {
765 base::DictionaryValue
* spdy_settings_dict
= new base::DictionaryValue
;
766 for (net::SettingsMap::const_iterator it
=
767 server_pref
.settings_map
->begin();
768 it
!= server_pref
.settings_map
->end();
770 net::SpdySettingsIds id
= it
->first
;
771 uint32 value
= it
->second
.second
;
772 std::string key
= base::StringPrintf("%u", id
);
773 spdy_settings_dict
->SetInteger(key
, value
);
775 server_pref_dict
->SetWithoutPathExpansion("settings", spdy_settings_dict
);
778 // Save alternate_protocol.
779 if (server_pref
.alternate_protocol
) {
780 base::DictionaryValue
* port_alternate_protocol_dict
=
781 new base::DictionaryValue
;
782 const net::AlternateProtocolInfo
* port_alternate_protocol
=
783 server_pref
.alternate_protocol
;
784 port_alternate_protocol_dict
->SetInteger("port",
785 port_alternate_protocol
->port
);
786 const char* protocol_str
=
787 net::AlternateProtocolToString(port_alternate_protocol
->protocol
);
788 port_alternate_protocol_dict
->SetString("protocol_str", protocol_str
);
789 port_alternate_protocol_dict
->SetDouble(
790 "probability", port_alternate_protocol
->probability
);
791 server_pref_dict
->SetWithoutPathExpansion(
792 "alternate_protocol", port_alternate_protocol_dict
);
795 // Save supports_quic.
796 if (server_pref
.supports_quic
) {
797 base::DictionaryValue
* supports_quic_dict
= new base::DictionaryValue
;
798 const net::SupportsQuic
* supports_quic
= server_pref
.supports_quic
;
799 supports_quic_dict
->SetBoolean("used_quic", supports_quic
->used_quic
);
800 supports_quic_dict
->SetString("address", supports_quic
->address
);
801 server_pref_dict
->SetWithoutPathExpansion(
802 "supports_quic", supports_quic_dict
);
805 servers_dict
->SetWithoutPathExpansion(server
.ToString(), server_pref_dict
);
808 http_server_properties_dict
.SetWithoutPathExpansion("servers", servers_dict
);
809 SetVersion(&http_server_properties_dict
, kVersionNumber
);
810 setting_prefs_
= true;
811 pref_service_
->Set(path_
, http_server_properties_dict
);
812 setting_prefs_
= false;
814 // Note that |completion| will be fired after we have written everything to
815 // the Preferences, but likely before these changes are serialized to disk.
816 // This is not a problem though, as JSONPrefStore guarantees that this will
817 // happen, pretty soon, and even in the case we shut down immediately.
818 if (!completion
.is_null())
822 void HttpServerPropertiesManager::OnHttpServerPropertiesChanged() {
823 DCHECK(pref_task_runner_
->RunsTasksOnCurrentThread());
825 ScheduleUpdateCacheOnPrefThread();