1 // Copyright (c) 2012 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 "chrome/browser/net/http_server_properties_manager.h"
8 #include "base/metrics/histogram.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/stl_util.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/values.h"
14 #include "chrome/browser/chrome_notification_types.h"
15 #include "chrome/common/pref_names.h"
16 #include "components/user_prefs/pref_registry_syncable.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "content/public/browser/notification_details.h"
19 #include "content/public/browser/notification_source.h"
21 using content::BrowserThread
;
23 namespace chrome_browser_net
{
27 // Time to wait before starting an update the http_server_properties_impl_ cache
28 // from preferences. Scheduling another update during this period will reset the
30 const int64 kUpdateCacheDelayMs
= 1000;
32 // Time to wait before starting an update the preferences from the
33 // http_server_properties_impl_ cache. Scheduling another update during this
34 // period will reset the timer.
35 const int64 kUpdatePrefsDelayMs
= 5000;
37 // "version" 0 indicates, http_server_properties doesn't have "version"
39 const int kMissingVersion
= 0;
41 // The version number of persisted http_server_properties.
42 const int kVersionNumber
= 2;
44 typedef std::vector
<std::string
> StringVector
;
46 // Persist 200 MRU AlternateProtocolHostPortPairs.
47 const int kMaxAlternateProtocolHostsToPersist
= 200;
49 // Persist 200 MRU SpdySettingsHostPortPairs.
50 const int kMaxSpdySettingsHostsToPersist
= 200;
52 // Persist 300 MRU SupportsSpdyServerHostPortPairs.
53 const int kMaxSupportsSpdyServerHostsToPersist
= 300;
57 ////////////////////////////////////////////////////////////////////////////////
58 // HttpServerPropertiesManager
60 HttpServerPropertiesManager::HttpServerPropertiesManager(
61 PrefService
* pref_service
)
62 : pref_service_(pref_service
),
63 setting_prefs_(false) {
64 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
66 ui_weak_ptr_factory_
.reset(
67 new base::WeakPtrFactory
<HttpServerPropertiesManager
>(this));
68 ui_weak_ptr_
= ui_weak_ptr_factory_
->GetWeakPtr();
69 ui_cache_update_timer_
.reset(
70 new base::OneShotTimer
<HttpServerPropertiesManager
>);
71 pref_change_registrar_
.Init(pref_service_
);
72 pref_change_registrar_
.Add(
73 prefs::kHttpServerProperties
,
74 base::Bind(&HttpServerPropertiesManager::OnHttpServerPropertiesChanged
,
75 base::Unretained(this)));
78 HttpServerPropertiesManager::~HttpServerPropertiesManager() {
79 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
80 io_weak_ptr_factory_
.reset();
83 void HttpServerPropertiesManager::InitializeOnIOThread() {
84 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
85 io_weak_ptr_factory_
.reset(
86 new base::WeakPtrFactory
<HttpServerPropertiesManager
>(this));
87 http_server_properties_impl_
.reset(new net::HttpServerPropertiesImpl());
89 io_prefs_update_timer_
.reset(
90 new base::OneShotTimer
<HttpServerPropertiesManager
>);
92 BrowserThread::PostTask(
95 base::Bind(&HttpServerPropertiesManager::UpdateCacheFromPrefsOnUI
,
99 void HttpServerPropertiesManager::ShutdownOnUIThread() {
100 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
101 // Cancel any pending updates, and stop listening for pref change updates.
102 ui_cache_update_timer_
->Stop();
103 ui_weak_ptr_factory_
.reset();
104 pref_change_registrar_
.RemoveAll();
108 void HttpServerPropertiesManager::RegisterProfilePrefs(
109 user_prefs::PrefRegistrySyncable
* prefs
) {
110 prefs
->RegisterDictionaryPref(
111 prefs::kHttpServerProperties
,
112 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
116 void HttpServerPropertiesManager::SetVersion(
117 base::DictionaryValue
* http_server_properties_dict
,
118 int version_number
) {
119 if (version_number
< 0)
120 version_number
= kVersionNumber
;
121 DCHECK_LE(version_number
, kVersionNumber
);
122 if (version_number
<= kVersionNumber
)
123 http_server_properties_dict
->SetInteger("version", version_number
);
126 // This is required for conformance with the HttpServerProperties interface.
127 base::WeakPtr
<net::HttpServerProperties
>
128 HttpServerPropertiesManager::GetWeakPtr() {
129 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
130 return io_weak_ptr_factory_
->GetWeakPtr();
133 void HttpServerPropertiesManager::Clear() {
134 Clear(base::Closure());
137 void HttpServerPropertiesManager::Clear(const base::Closure
& completion
) {
138 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
140 http_server_properties_impl_
->Clear();
141 UpdatePrefsFromCacheOnIO(completion
);
144 bool HttpServerPropertiesManager::SupportsSpdy(
145 const net::HostPortPair
& server
) {
146 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
147 return http_server_properties_impl_
->SupportsSpdy(server
);
150 void HttpServerPropertiesManager::SetSupportsSpdy(
151 const net::HostPortPair
& server
,
153 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
155 http_server_properties_impl_
->SetSupportsSpdy(server
, support_spdy
);
156 ScheduleUpdatePrefsOnIO();
159 bool HttpServerPropertiesManager::HasAlternateProtocol(
160 const net::HostPortPair
& server
) {
161 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
162 return http_server_properties_impl_
->HasAlternateProtocol(server
);
165 net::PortAlternateProtocolPair
166 HttpServerPropertiesManager::GetAlternateProtocol(
167 const net::HostPortPair
& server
) {
168 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
169 return http_server_properties_impl_
->GetAlternateProtocol(server
);
172 void HttpServerPropertiesManager::SetAlternateProtocol(
173 const net::HostPortPair
& server
,
174 uint16 alternate_port
,
175 net::AlternateProtocol alternate_protocol
) {
176 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
177 http_server_properties_impl_
->SetAlternateProtocol(
178 server
, alternate_port
, alternate_protocol
);
179 ScheduleUpdatePrefsOnIO();
182 void HttpServerPropertiesManager::SetBrokenAlternateProtocol(
183 const net::HostPortPair
& server
) {
184 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
185 http_server_properties_impl_
->SetBrokenAlternateProtocol(server
);
186 ScheduleUpdatePrefsOnIO();
189 bool HttpServerPropertiesManager::WasAlternateProtocolRecentlyBroken(
190 const net::HostPortPair
& server
) {
191 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
192 return http_server_properties_impl_
->WasAlternateProtocolRecentlyBroken(
196 void HttpServerPropertiesManager::ConfirmAlternateProtocol(
197 const net::HostPortPair
& server
) {
198 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
199 http_server_properties_impl_
->ConfirmAlternateProtocol(server
);
200 ScheduleUpdatePrefsOnIO();
203 void HttpServerPropertiesManager::ClearAlternateProtocol(
204 const net::HostPortPair
& server
) {
205 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
206 http_server_properties_impl_
->ClearAlternateProtocol(server
);
207 ScheduleUpdatePrefsOnIO();
210 const net::AlternateProtocolMap
&
211 HttpServerPropertiesManager::alternate_protocol_map() const {
212 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
213 return http_server_properties_impl_
->alternate_protocol_map();
216 const net::SettingsMap
&
217 HttpServerPropertiesManager::GetSpdySettings(
218 const net::HostPortPair
& host_port_pair
) {
219 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
220 return http_server_properties_impl_
->GetSpdySettings(host_port_pair
);
223 bool HttpServerPropertiesManager::SetSpdySetting(
224 const net::HostPortPair
& host_port_pair
,
225 net::SpdySettingsIds id
,
226 net::SpdySettingsFlags flags
,
228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
229 bool persist
= http_server_properties_impl_
->SetSpdySetting(
230 host_port_pair
, id
, flags
, value
);
232 ScheduleUpdatePrefsOnIO();
236 void HttpServerPropertiesManager::ClearSpdySettings(
237 const net::HostPortPair
& host_port_pair
) {
238 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
239 http_server_properties_impl_
->ClearSpdySettings(host_port_pair
);
240 ScheduleUpdatePrefsOnIO();
243 void HttpServerPropertiesManager::ClearAllSpdySettings() {
244 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
245 http_server_properties_impl_
->ClearAllSpdySettings();
246 ScheduleUpdatePrefsOnIO();
249 const net::SpdySettingsMap
&
250 HttpServerPropertiesManager::spdy_settings_map() const {
251 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
252 return http_server_properties_impl_
->spdy_settings_map();
255 void HttpServerPropertiesManager::SetServerNetworkStats(
256 const net::HostPortPair
& host_port_pair
,
257 NetworkStats stats
) {
258 http_server_properties_impl_
->SetServerNetworkStats(host_port_pair
, stats
);
261 const HttpServerPropertiesManager::NetworkStats
*
262 HttpServerPropertiesManager::GetServerNetworkStats(
263 const net::HostPortPair
& host_port_pair
) const {
264 return http_server_properties_impl_
->GetServerNetworkStats(host_port_pair
);
267 net::HttpPipelinedHostCapability
268 HttpServerPropertiesManager::GetPipelineCapability(
269 const net::HostPortPair
& origin
) {
270 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
271 return http_server_properties_impl_
->GetPipelineCapability(origin
);
274 void HttpServerPropertiesManager::SetPipelineCapability(
275 const net::HostPortPair
& origin
,
276 net::HttpPipelinedHostCapability capability
) {
277 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
278 http_server_properties_impl_
->SetPipelineCapability(origin
, capability
);
279 ScheduleUpdatePrefsOnIO();
282 void HttpServerPropertiesManager::ClearPipelineCapabilities() {
283 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
284 http_server_properties_impl_
->ClearPipelineCapabilities();
285 ScheduleUpdatePrefsOnIO();
288 net::PipelineCapabilityMap
289 HttpServerPropertiesManager::GetPipelineCapabilityMap() const {
290 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
291 return http_server_properties_impl_
->GetPipelineCapabilityMap();
295 // Update the HttpServerPropertiesImpl's cache with data from preferences.
297 void HttpServerPropertiesManager::ScheduleUpdateCacheOnUI() {
298 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
299 // Cancel pending updates, if any.
300 ui_cache_update_timer_
->Stop();
301 StartCacheUpdateTimerOnUI(
302 base::TimeDelta::FromMilliseconds(kUpdateCacheDelayMs
));
305 void HttpServerPropertiesManager::StartCacheUpdateTimerOnUI(
306 base::TimeDelta delay
) {
307 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
308 ui_cache_update_timer_
->Start(
309 FROM_HERE
, delay
, this,
310 &HttpServerPropertiesManager::UpdateCacheFromPrefsOnUI
);
313 void HttpServerPropertiesManager::UpdateCacheFromPrefsOnUI() {
314 // The preferences can only be read on the UI thread.
315 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
317 if (!pref_service_
->HasPrefPath(prefs::kHttpServerProperties
))
320 bool detected_corrupted_prefs
= false;
321 const base::DictionaryValue
& http_server_properties_dict
=
322 *pref_service_
->GetDictionary(prefs::kHttpServerProperties
);
324 int version
= kMissingVersion
;
325 if (!http_server_properties_dict
.GetIntegerWithoutPathExpansion(
326 "version", &version
)) {
327 DVLOG(1) << "Missing version. Clearing all properties.";
331 // The properties for a given server is in
332 // http_server_properties_dict["servers"][server].
333 const base::DictionaryValue
* servers_dict
= NULL
;
334 if (!http_server_properties_dict
.GetDictionaryWithoutPathExpansion(
335 "servers", &servers_dict
)) {
336 DVLOG(1) << "Malformed http_server_properties for servers.";
340 // String is host/port pair of spdy server.
341 scoped_ptr
<StringVector
> spdy_servers(new StringVector
);
342 scoped_ptr
<net::SpdySettingsMap
> spdy_settings_map(
343 new net::SpdySettingsMap(kMaxSpdySettingsHostsToPersist
));
344 scoped_ptr
<net::PipelineCapabilityMap
> pipeline_capability_map(
345 new net::PipelineCapabilityMap
);
346 scoped_ptr
<net::AlternateProtocolMap
> alternate_protocol_map(
347 new net::AlternateProtocolMap(kMaxAlternateProtocolHostsToPersist
));
349 for (base::DictionaryValue::Iterator
it(*servers_dict
); !it
.IsAtEnd();
351 // Get server's host/pair.
352 const std::string
& server_str
= it
.key();
353 net::HostPortPair server
= net::HostPortPair::FromString(server_str
);
354 if (server
.host().empty()) {
355 DVLOG(1) << "Malformed http_server_properties for server: " << server_str
;
356 detected_corrupted_prefs
= true;
360 const base::DictionaryValue
* server_pref_dict
= NULL
;
361 if (!it
.value().GetAsDictionary(&server_pref_dict
)) {
362 DVLOG(1) << "Malformed http_server_properties server: " << server_str
;
363 detected_corrupted_prefs
= true;
367 // Get if server supports Spdy.
368 bool supports_spdy
= false;
369 if ((server_pref_dict
->GetBoolean(
370 "supports_spdy", &supports_spdy
)) && supports_spdy
) {
371 spdy_servers
->push_back(server_str
);
375 DCHECK(spdy_settings_map
->Peek(server
) == spdy_settings_map
->end());
376 const base::DictionaryValue
* spdy_settings_dict
= NULL
;
377 if (server_pref_dict
->GetDictionaryWithoutPathExpansion(
378 "settings", &spdy_settings_dict
)) {
379 net::SettingsMap settings_map
;
380 for (base::DictionaryValue::Iterator
dict_it(*spdy_settings_dict
);
381 !dict_it
.IsAtEnd(); dict_it
.Advance()) {
382 const std::string
& id_str
= dict_it
.key();
384 if (!base::StringToInt(id_str
, &id
)) {
385 DVLOG(1) << "Malformed id in SpdySettings for server: " <<
391 if (!dict_it
.value().GetAsInteger(&value
)) {
392 DVLOG(1) << "Malformed value in SpdySettings for server: " <<
397 net::SettingsFlagsAndValue
flags_and_value(
398 net::SETTINGS_FLAG_PERSISTED
, value
);
399 settings_map
[static_cast<net::SpdySettingsIds
>(id
)] = flags_and_value
;
401 spdy_settings_map
->Put(server
, settings_map
);
404 int pipeline_capability
= net::PIPELINE_UNKNOWN
;
405 if ((server_pref_dict
->GetInteger(
406 "pipeline_capability", &pipeline_capability
)) &&
407 pipeline_capability
!= net::PIPELINE_UNKNOWN
) {
408 (*pipeline_capability_map
)[server
] =
409 static_cast<net::HttpPipelinedHostCapability
>(pipeline_capability
);
412 // Get alternate_protocol server.
413 DCHECK(alternate_protocol_map
->Peek(server
) ==
414 alternate_protocol_map
->end());
415 const base::DictionaryValue
* port_alternate_protocol_dict
= NULL
;
416 if (!server_pref_dict
->GetDictionaryWithoutPathExpansion(
417 "alternate_protocol", &port_alternate_protocol_dict
)) {
423 if (!port_alternate_protocol_dict
->GetIntegerWithoutPathExpansion(
424 "port", &port
) || (port
> (1 << 16))) {
425 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str
;
426 detected_corrupted_prefs
= true;
429 std::string protocol_str
;
430 if (!port_alternate_protocol_dict
->GetStringWithoutPathExpansion(
431 "protocol_str", &protocol_str
)) {
432 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str
;
433 detected_corrupted_prefs
= true;
436 net::AlternateProtocol protocol
=
437 net::AlternateProtocolFromString(protocol_str
);
438 if (!net::IsAlternateProtocolValid(protocol
)) {
439 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str
;
440 detected_corrupted_prefs
= true;
444 net::PortAlternateProtocolPair port_alternate_protocol
;
445 port_alternate_protocol
.port
= port
;
446 port_alternate_protocol
.protocol
= protocol
;
448 alternate_protocol_map
->Put(server
, port_alternate_protocol
);
452 BrowserThread::PostTask(
455 base::Bind(&HttpServerPropertiesManager::
456 UpdateCacheFromPrefsOnIO
,
457 base::Unretained(this),
458 base::Owned(spdy_servers
.release()),
459 base::Owned(spdy_settings_map
.release()),
460 base::Owned(alternate_protocol_map
.release()),
461 base::Owned(pipeline_capability_map
.release()),
462 detected_corrupted_prefs
));
465 void HttpServerPropertiesManager::UpdateCacheFromPrefsOnIO(
466 StringVector
* spdy_servers
,
467 net::SpdySettingsMap
* spdy_settings_map
,
468 net::AlternateProtocolMap
* alternate_protocol_map
,
469 net::PipelineCapabilityMap
* pipeline_capability_map
,
470 bool detected_corrupted_prefs
) {
471 // Preferences have the master data because admins might have pushed new
472 // preferences. Update the cached data with new data from preferences.
473 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
475 UMA_HISTOGRAM_COUNTS("Net.CountOfSpdyServers", spdy_servers
->size());
476 http_server_properties_impl_
->InitializeSpdyServers(spdy_servers
, true);
478 // Clear the cached data and use the new spdy_settings from preferences.
479 UMA_HISTOGRAM_COUNTS("Net.CountOfSpdySettings", spdy_settings_map
->size());
480 http_server_properties_impl_
->InitializeSpdySettingsServers(
483 // Clear the cached data and use the new Alternate-Protocol server list from
485 UMA_HISTOGRAM_COUNTS("Net.CountOfAlternateProtocolServers",
486 alternate_protocol_map
->size());
487 http_server_properties_impl_
->InitializeAlternateProtocolServers(
488 alternate_protocol_map
);
490 UMA_HISTOGRAM_COUNTS("Net.CountOfPipelineCapableServers",
491 pipeline_capability_map
->size());
492 http_server_properties_impl_
->InitializePipelineCapabilities(
493 pipeline_capability_map
);
495 // Update the prefs with what we have read (delete all corrupted prefs).
496 if (detected_corrupted_prefs
)
497 ScheduleUpdatePrefsOnIO();
502 // Update Preferences with data from the cached data.
504 void HttpServerPropertiesManager::ScheduleUpdatePrefsOnIO() {
505 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
506 // Cancel pending updates, if any.
507 io_prefs_update_timer_
->Stop();
508 StartPrefsUpdateTimerOnIO(
509 base::TimeDelta::FromMilliseconds(kUpdatePrefsDelayMs
));
512 void HttpServerPropertiesManager::StartPrefsUpdateTimerOnIO(
513 base::TimeDelta delay
) {
514 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
515 // This is overridden in tests to post the task without the delay.
516 io_prefs_update_timer_
->Start(
517 FROM_HERE
, delay
, this,
518 &HttpServerPropertiesManager::UpdatePrefsFromCacheOnIO
);
521 // This is required so we can set this as the callback for a timer.
522 void HttpServerPropertiesManager::UpdatePrefsFromCacheOnIO() {
523 UpdatePrefsFromCacheOnIO(base::Closure());
526 void HttpServerPropertiesManager::UpdatePrefsFromCacheOnIO(
527 const base::Closure
& completion
) {
528 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
530 base::ListValue
* spdy_server_list
= new base::ListValue
;
531 http_server_properties_impl_
->GetSpdyServerList(
532 spdy_server_list
, kMaxSupportsSpdyServerHostsToPersist
);
534 net::SpdySettingsMap
* spdy_settings_map
=
535 new net::SpdySettingsMap(kMaxSpdySettingsHostsToPersist
);
536 const net::SpdySettingsMap
& main_map
=
537 http_server_properties_impl_
->spdy_settings_map();
539 for (net::SpdySettingsMap::const_iterator it
= main_map
.begin();
540 it
!= main_map
.end() && count
< kMaxSpdySettingsHostsToPersist
;
542 spdy_settings_map
->Put(it
->first
, it
->second
);
545 net::AlternateProtocolMap
* alternate_protocol_map
=
546 new net::AlternateProtocolMap(kMaxAlternateProtocolHostsToPersist
);
547 const net::AlternateProtocolMap
& map
=
548 http_server_properties_impl_
->alternate_protocol_map();
550 for (net::AlternateProtocolMap::const_iterator it
= map
.begin();
551 it
!= map
.end() && count
< kMaxAlternateProtocolHostsToPersist
;
553 alternate_protocol_map
->Put(it
->first
, it
->second
);
556 net::PipelineCapabilityMap
* pipeline_capability_map
=
557 new net::PipelineCapabilityMap
;
558 *pipeline_capability_map
=
559 http_server_properties_impl_
->GetPipelineCapabilityMap();
561 // Update the preferences on the UI thread.
562 BrowserThread::PostTask(
565 base::Bind(&HttpServerPropertiesManager::UpdatePrefsOnUI
,
567 base::Owned(spdy_server_list
),
568 base::Owned(spdy_settings_map
),
569 base::Owned(alternate_protocol_map
),
570 base::Owned(pipeline_capability_map
),
574 // A local or temporary data structure to hold |supports_spdy|, SpdySettings,
575 // PortAlternateProtocolPair, and |pipeline_capability| preferences for a
576 // server. This is used only in UpdatePrefsOnUI.
579 : supports_spdy(false),
581 alternate_protocol(NULL
),
582 pipeline_capability(net::PIPELINE_UNKNOWN
) {
584 ServerPref(bool supports_spdy
,
585 const net::SettingsMap
* settings_map
,
586 const net::PortAlternateProtocolPair
* alternate_protocol
)
587 : supports_spdy(supports_spdy
),
588 settings_map(settings_map
),
589 alternate_protocol(alternate_protocol
),
590 pipeline_capability(net::PIPELINE_UNKNOWN
) {
593 const net::SettingsMap
* settings_map
;
594 const net::PortAlternateProtocolPair
* alternate_protocol
;
595 net::HttpPipelinedHostCapability pipeline_capability
;
598 void HttpServerPropertiesManager::UpdatePrefsOnUI(
599 base::ListValue
* spdy_server_list
,
600 net::SpdySettingsMap
* spdy_settings_map
,
601 net::AlternateProtocolMap
* alternate_protocol_map
,
602 net::PipelineCapabilityMap
* pipeline_capability_map
,
603 const base::Closure
& completion
) {
605 typedef std::map
<net::HostPortPair
, ServerPref
> ServerPrefMap
;
606 ServerPrefMap server_pref_map
;
608 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
610 // Add servers that support spdy to server_pref_map.
612 for (base::ListValue::const_iterator list_it
= spdy_server_list
->begin();
613 list_it
!= spdy_server_list
->end(); ++list_it
) {
614 if ((*list_it
)->GetAsString(&s
)) {
615 net::HostPortPair server
= net::HostPortPair::FromString(s
);
617 ServerPrefMap::iterator it
= server_pref_map
.find(server
);
618 if (it
== server_pref_map
.end()) {
619 ServerPref
server_pref(true, NULL
, NULL
);
620 server_pref_map
[server
] = server_pref
;
622 it
->second
.supports_spdy
= true;
627 // Add servers that have SpdySettings to server_pref_map.
628 for (net::SpdySettingsMap::iterator map_it
= spdy_settings_map
->begin();
629 map_it
!= spdy_settings_map
->end(); ++map_it
) {
630 const net::HostPortPair
& server
= map_it
->first
;
632 ServerPrefMap::iterator it
= server_pref_map
.find(server
);
633 if (it
== server_pref_map
.end()) {
634 ServerPref
server_pref(false, &map_it
->second
, NULL
);
635 server_pref_map
[server
] = server_pref
;
637 it
->second
.settings_map
= &map_it
->second
;
641 // Add AlternateProtocol servers to server_pref_map.
642 for (net::AlternateProtocolMap::const_iterator map_it
=
643 alternate_protocol_map
->begin();
644 map_it
!= alternate_protocol_map
->end(); ++map_it
) {
645 const net::HostPortPair
& server
= map_it
->first
;
646 const net::PortAlternateProtocolPair
& port_alternate_protocol
=
648 if (!net::IsAlternateProtocolValid(port_alternate_protocol
.protocol
)) {
652 ServerPrefMap::iterator it
= server_pref_map
.find(server
);
653 if (it
== server_pref_map
.end()) {
654 ServerPref
server_pref(false, NULL
, &map_it
->second
);
655 server_pref_map
[server
] = server_pref
;
657 it
->second
.alternate_protocol
= &map_it
->second
;
661 for (net::PipelineCapabilityMap::const_iterator map_it
=
662 pipeline_capability_map
->begin();
663 map_it
!= pipeline_capability_map
->end(); ++map_it
) {
664 const net::HostPortPair
& server
= map_it
->first
;
665 const net::HttpPipelinedHostCapability
& pipeline_capability
=
668 ServerPrefMap::iterator it
= server_pref_map
.find(server
);
669 if (it
== server_pref_map
.end()) {
670 ServerPref server_pref
;
671 server_pref
.pipeline_capability
= pipeline_capability
;
672 server_pref_map
[server
] = server_pref
;
674 it
->second
.pipeline_capability
= pipeline_capability
;
678 // Persist the prefs::kHttpServerProperties.
679 base::DictionaryValue http_server_properties_dict
;
680 base::DictionaryValue
* servers_dict
= new base::DictionaryValue
;
681 for (ServerPrefMap::const_iterator map_it
=
682 server_pref_map
.begin();
683 map_it
!= server_pref_map
.end(); ++map_it
) {
684 const net::HostPortPair
& server
= map_it
->first
;
685 const ServerPref
& server_pref
= map_it
->second
;
687 base::DictionaryValue
* server_pref_dict
= new base::DictionaryValue
;
689 // Save supports_spdy.
690 if (server_pref
.supports_spdy
)
691 server_pref_dict
->SetBoolean("supports_spdy", server_pref
.supports_spdy
);
693 // Save SPDY settings.
694 if (server_pref
.settings_map
) {
695 base::DictionaryValue
* spdy_settings_dict
= new base::DictionaryValue
;
696 for (net::SettingsMap::const_iterator it
=
697 server_pref
.settings_map
->begin();
698 it
!= server_pref
.settings_map
->end(); ++it
) {
699 net::SpdySettingsIds id
= it
->first
;
700 uint32 value
= it
->second
.second
;
701 std::string key
= base::StringPrintf("%u", id
);
702 spdy_settings_dict
->SetInteger(key
, value
);
704 server_pref_dict
->SetWithoutPathExpansion("settings", spdy_settings_dict
);
707 // Save alternate_protocol.
708 if (server_pref
.alternate_protocol
) {
709 base::DictionaryValue
* port_alternate_protocol_dict
=
710 new base::DictionaryValue
;
711 const net::PortAlternateProtocolPair
* port_alternate_protocol
=
712 server_pref
.alternate_protocol
;
713 port_alternate_protocol_dict
->SetInteger(
714 "port", port_alternate_protocol
->port
);
715 const char* protocol_str
=
716 net::AlternateProtocolToString(port_alternate_protocol
->protocol
);
717 port_alternate_protocol_dict
->SetString("protocol_str", protocol_str
);
718 server_pref_dict
->SetWithoutPathExpansion(
719 "alternate_protocol", port_alternate_protocol_dict
);
722 if (server_pref
.pipeline_capability
!= net::PIPELINE_UNKNOWN
) {
723 server_pref_dict
->SetInteger("pipeline_capability",
724 server_pref
.pipeline_capability
);
727 servers_dict
->SetWithoutPathExpansion(server
.ToString(), server_pref_dict
);
730 http_server_properties_dict
.SetWithoutPathExpansion("servers", servers_dict
);
731 SetVersion(&http_server_properties_dict
, kVersionNumber
);
732 setting_prefs_
= true;
733 pref_service_
->Set(prefs::kHttpServerProperties
,
734 http_server_properties_dict
);
735 setting_prefs_
= false;
737 // Note that |completion| will be fired after we have written everything to
738 // the Preferences, but likely before these changes are serialized to disk.
739 // This is not a problem though, as JSONPrefStore guarantees that this will
740 // happen, pretty soon, and even in the case we shut down immediately.
741 if (!completion
.is_null())
745 void HttpServerPropertiesManager::OnHttpServerPropertiesChanged() {
746 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
748 ScheduleUpdateCacheOnUI();
751 } // namespace chrome_browser_net