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
;
48 ////////////////////////////////////////////////////////////////////////////////
49 // HttpServerPropertiesManager
51 HttpServerPropertiesManager::HttpServerPropertiesManager(
52 PrefService
* pref_service
)
53 : pref_service_(pref_service
),
54 setting_prefs_(false) {
55 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
57 ui_weak_ptr_factory_
.reset(
58 new base::WeakPtrFactory
<HttpServerPropertiesManager
>(this));
59 ui_weak_ptr_
= ui_weak_ptr_factory_
->GetWeakPtr();
60 ui_cache_update_timer_
.reset(
61 new base::OneShotTimer
<HttpServerPropertiesManager
>);
62 pref_change_registrar_
.Init(pref_service_
);
63 pref_change_registrar_
.Add(
64 prefs::kHttpServerProperties
,
65 base::Bind(&HttpServerPropertiesManager::OnHttpServerPropertiesChanged
,
66 base::Unretained(this)));
69 HttpServerPropertiesManager::~HttpServerPropertiesManager() {
70 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
71 io_weak_ptr_factory_
.reset();
74 void HttpServerPropertiesManager::InitializeOnIOThread() {
75 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
76 io_weak_ptr_factory_
.reset(
77 new base::WeakPtrFactory
<HttpServerPropertiesManager
>(this));
78 http_server_properties_impl_
.reset(new net::HttpServerPropertiesImpl());
80 io_prefs_update_timer_
.reset(
81 new base::OneShotTimer
<HttpServerPropertiesManager
>);
83 BrowserThread::PostTask(
86 base::Bind(&HttpServerPropertiesManager::UpdateCacheFromPrefsOnUI
,
90 void HttpServerPropertiesManager::ShutdownOnUIThread() {
91 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
92 // Cancel any pending updates, and stop listening for pref change updates.
93 ui_cache_update_timer_
->Stop();
94 ui_weak_ptr_factory_
.reset();
95 pref_change_registrar_
.RemoveAll();
99 void HttpServerPropertiesManager::RegisterProfilePrefs(
100 user_prefs::PrefRegistrySyncable
* prefs
) {
101 prefs
->RegisterDictionaryPref(
102 prefs::kHttpServerProperties
,
103 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
107 void HttpServerPropertiesManager::SetVersion(
108 base::DictionaryValue
* http_server_properties_dict
,
109 int version_number
) {
110 if (version_number
< 0)
111 version_number
= kVersionNumber
;
112 DCHECK_LE(version_number
, kVersionNumber
);
113 if (version_number
<= kVersionNumber
)
114 http_server_properties_dict
->SetInteger("version", version_number
);
117 // This is required for conformance with the HttpServerProperties interface.
118 base::WeakPtr
<net::HttpServerProperties
>
119 HttpServerPropertiesManager::GetWeakPtr() {
120 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
121 return io_weak_ptr_factory_
->GetWeakPtr();
124 void HttpServerPropertiesManager::Clear() {
125 Clear(base::Closure());
128 void HttpServerPropertiesManager::Clear(const base::Closure
& completion
) {
129 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
131 http_server_properties_impl_
->Clear();
132 UpdatePrefsFromCacheOnIO(completion
);
135 bool HttpServerPropertiesManager::SupportsSpdy(
136 const net::HostPortPair
& server
) const {
137 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
138 return http_server_properties_impl_
->SupportsSpdy(server
);
141 void HttpServerPropertiesManager::SetSupportsSpdy(
142 const net::HostPortPair
& server
,
144 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
146 http_server_properties_impl_
->SetSupportsSpdy(server
, support_spdy
);
147 ScheduleUpdatePrefsOnIO();
150 bool HttpServerPropertiesManager::HasAlternateProtocol(
151 const net::HostPortPair
& server
) const {
152 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
153 return http_server_properties_impl_
->HasAlternateProtocol(server
);
156 net::PortAlternateProtocolPair
157 HttpServerPropertiesManager::GetAlternateProtocol(
158 const net::HostPortPair
& server
) const {
159 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
160 return http_server_properties_impl_
->GetAlternateProtocol(server
);
163 void HttpServerPropertiesManager::SetAlternateProtocol(
164 const net::HostPortPair
& server
,
165 uint16 alternate_port
,
166 net::AlternateProtocol alternate_protocol
) {
167 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
168 http_server_properties_impl_
->SetAlternateProtocol(
169 server
, alternate_port
, alternate_protocol
);
170 ScheduleUpdatePrefsOnIO();
173 void HttpServerPropertiesManager::SetBrokenAlternateProtocol(
174 const net::HostPortPair
& server
) {
175 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
176 http_server_properties_impl_
->SetBrokenAlternateProtocol(server
);
177 ScheduleUpdatePrefsOnIO();
180 const net::AlternateProtocolMap
&
181 HttpServerPropertiesManager::alternate_protocol_map() const {
182 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
183 return http_server_properties_impl_
->alternate_protocol_map();
186 const net::SettingsMap
&
187 HttpServerPropertiesManager::GetSpdySettings(
188 const net::HostPortPair
& host_port_pair
) const {
189 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
190 return http_server_properties_impl_
->GetSpdySettings(host_port_pair
);
193 bool HttpServerPropertiesManager::SetSpdySetting(
194 const net::HostPortPair
& host_port_pair
,
195 net::SpdySettingsIds id
,
196 net::SpdySettingsFlags flags
,
198 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
199 bool persist
= http_server_properties_impl_
->SetSpdySetting(
200 host_port_pair
, id
, flags
, value
);
202 ScheduleUpdatePrefsOnIO();
206 void HttpServerPropertiesManager::ClearSpdySettings(
207 const net::HostPortPair
& host_port_pair
) {
208 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
209 http_server_properties_impl_
->ClearSpdySettings(host_port_pair
);
210 ScheduleUpdatePrefsOnIO();
213 void HttpServerPropertiesManager::ClearAllSpdySettings() {
214 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
215 http_server_properties_impl_
->ClearAllSpdySettings();
216 ScheduleUpdatePrefsOnIO();
219 const net::SpdySettingsMap
&
220 HttpServerPropertiesManager::spdy_settings_map() const {
221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
222 return http_server_properties_impl_
->spdy_settings_map();
225 void HttpServerPropertiesManager::SetServerNetworkStats(
226 const net::HostPortPair
& host_port_pair
,
227 NetworkStats stats
) {
228 http_server_properties_impl_
->SetServerNetworkStats(host_port_pair
, stats
);
231 const HttpServerPropertiesManager::NetworkStats
*
232 HttpServerPropertiesManager::GetServerNetworkStats(
233 const net::HostPortPair
& host_port_pair
) const {
234 return http_server_properties_impl_
->GetServerNetworkStats(host_port_pair
);
237 net::HttpPipelinedHostCapability
238 HttpServerPropertiesManager::GetPipelineCapability(
239 const net::HostPortPair
& origin
) {
240 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
241 return http_server_properties_impl_
->GetPipelineCapability(origin
);
244 void HttpServerPropertiesManager::SetPipelineCapability(
245 const net::HostPortPair
& origin
,
246 net::HttpPipelinedHostCapability capability
) {
247 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
248 http_server_properties_impl_
->SetPipelineCapability(origin
, capability
);
249 ScheduleUpdatePrefsOnIO();
252 void HttpServerPropertiesManager::ClearPipelineCapabilities() {
253 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
254 http_server_properties_impl_
->ClearPipelineCapabilities();
255 ScheduleUpdatePrefsOnIO();
258 net::PipelineCapabilityMap
259 HttpServerPropertiesManager::GetPipelineCapabilityMap() const {
260 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
261 return http_server_properties_impl_
->GetPipelineCapabilityMap();
265 // Update the HttpServerPropertiesImpl's cache with data from preferences.
267 void HttpServerPropertiesManager::ScheduleUpdateCacheOnUI() {
268 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
269 // Cancel pending updates, if any.
270 ui_cache_update_timer_
->Stop();
271 StartCacheUpdateTimerOnUI(
272 base::TimeDelta::FromMilliseconds(kUpdateCacheDelayMs
));
275 void HttpServerPropertiesManager::StartCacheUpdateTimerOnUI(
276 base::TimeDelta delay
) {
277 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
278 ui_cache_update_timer_
->Start(
279 FROM_HERE
, delay
, this,
280 &HttpServerPropertiesManager::UpdateCacheFromPrefsOnUI
);
283 void HttpServerPropertiesManager::UpdateCacheFromPrefsOnUI() {
284 // The preferences can only be read on the UI thread.
285 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
287 if (!pref_service_
->HasPrefPath(prefs::kHttpServerProperties
))
290 bool detected_corrupted_prefs
= false;
291 const base::DictionaryValue
& http_server_properties_dict
=
292 *pref_service_
->GetDictionary(prefs::kHttpServerProperties
);
294 int version
= kMissingVersion
;
295 if (!http_server_properties_dict
.GetIntegerWithoutPathExpansion(
296 "version", &version
)) {
297 DVLOG(1) << "Missing version. Clearing all properties.";
301 // The properties for a given server is in
302 // http_server_properties_dict["servers"][server].
303 const base::DictionaryValue
* servers_dict
= NULL
;
304 if (!http_server_properties_dict
.GetDictionaryWithoutPathExpansion(
305 "servers", &servers_dict
)) {
306 DVLOG(1) << "Malformed http_server_properties for servers.";
310 // TODO(rtenneti): Mark entries with an LRU sequence number (date of access?),
311 // and then truncate down deleting old stuff.
312 if (version
!= kVersionNumber
&& servers_dict
->size() > 300) {
313 DVLOG(1) << "Size is too large. Clearing all properties.";
317 // String is host/port pair of spdy server.
318 scoped_ptr
<StringVector
> spdy_servers(new StringVector
);
319 scoped_ptr
<net::SpdySettingsMap
> spdy_settings_map(new net::SpdySettingsMap
);
320 scoped_ptr
<net::PipelineCapabilityMap
> pipeline_capability_map(
321 new net::PipelineCapabilityMap
);
322 scoped_ptr
<net::AlternateProtocolMap
> alternate_protocol_map(
323 new net::AlternateProtocolMap
);
325 for (base::DictionaryValue::Iterator
it(*servers_dict
); !it
.IsAtEnd();
327 // Get server's host/pair.
328 const std::string
& server_str
= it
.key();
329 net::HostPortPair server
= net::HostPortPair::FromString(server_str
);
330 if (server
.host().empty()) {
331 DVLOG(1) << "Malformed http_server_properties for server: " << server_str
;
332 detected_corrupted_prefs
= true;
336 const base::DictionaryValue
* server_pref_dict
= NULL
;
337 if (!it
.value().GetAsDictionary(&server_pref_dict
)) {
338 DVLOG(1) << "Malformed http_server_properties server: " << server_str
;
339 detected_corrupted_prefs
= true;
343 // Get if server supports Spdy.
344 bool supports_spdy
= false;
345 if ((server_pref_dict
->GetBoolean(
346 "supports_spdy", &supports_spdy
)) && supports_spdy
) {
347 spdy_servers
->push_back(server_str
);
351 DCHECK(!ContainsKey(*spdy_settings_map
, server
));
352 const base::DictionaryValue
* spdy_settings_dict
= NULL
;
353 if (server_pref_dict
->GetDictionaryWithoutPathExpansion(
354 "settings", &spdy_settings_dict
)) {
355 net::SettingsMap settings_map
;
356 for (base::DictionaryValue::Iterator
dict_it(*spdy_settings_dict
);
357 !dict_it
.IsAtEnd(); dict_it
.Advance()) {
358 const std::string
& id_str
= dict_it
.key();
360 if (!base::StringToInt(id_str
, &id
)) {
361 DVLOG(1) << "Malformed id in SpdySettings for server: " <<
367 if (!dict_it
.value().GetAsInteger(&value
)) {
368 DVLOG(1) << "Malformed value in SpdySettings for server: " <<
373 net::SettingsFlagsAndValue
flags_and_value(
374 net::SETTINGS_FLAG_PERSISTED
, value
);
375 settings_map
[static_cast<net::SpdySettingsIds
>(id
)] = flags_and_value
;
377 (*spdy_settings_map
)[server
] = settings_map
;
380 int pipeline_capability
= net::PIPELINE_UNKNOWN
;
381 if ((server_pref_dict
->GetInteger(
382 "pipeline_capability", &pipeline_capability
)) &&
383 pipeline_capability
!= net::PIPELINE_UNKNOWN
) {
384 (*pipeline_capability_map
)[server
] =
385 static_cast<net::HttpPipelinedHostCapability
>(pipeline_capability
);
388 // Get alternate_protocol server.
389 DCHECK(!ContainsKey(*alternate_protocol_map
, server
));
390 const base::DictionaryValue
* port_alternate_protocol_dict
= NULL
;
391 if (!server_pref_dict
->GetDictionaryWithoutPathExpansion(
392 "alternate_protocol", &port_alternate_protocol_dict
)) {
398 if (!port_alternate_protocol_dict
->GetIntegerWithoutPathExpansion(
399 "port", &port
) || (port
> (1 << 16))) {
400 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str
;
401 detected_corrupted_prefs
= true;
404 std::string protocol_str
;
405 if (!port_alternate_protocol_dict
->GetStringWithoutPathExpansion(
406 "protocol_str", &protocol_str
)) {
407 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str
;
408 detected_corrupted_prefs
= true;
411 net::AlternateProtocol protocol
=
412 net::AlternateProtocolFromString(protocol_str
);
413 if (!net::IsAlternateProtocolValid(protocol
)) {
414 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str
;
415 detected_corrupted_prefs
= true;
419 net::PortAlternateProtocolPair port_alternate_protocol
;
420 port_alternate_protocol
.port
= port
;
421 port_alternate_protocol
.protocol
= protocol
;
423 (*alternate_protocol_map
)[server
] = port_alternate_protocol
;
427 BrowserThread::PostTask(
430 base::Bind(&HttpServerPropertiesManager::
431 UpdateCacheFromPrefsOnIO
,
432 base::Unretained(this),
433 base::Owned(spdy_servers
.release()),
434 base::Owned(spdy_settings_map
.release()),
435 base::Owned(alternate_protocol_map
.release()),
436 base::Owned(pipeline_capability_map
.release()),
437 detected_corrupted_prefs
));
440 void HttpServerPropertiesManager::UpdateCacheFromPrefsOnIO(
441 StringVector
* spdy_servers
,
442 net::SpdySettingsMap
* spdy_settings_map
,
443 net::AlternateProtocolMap
* alternate_protocol_map
,
444 net::PipelineCapabilityMap
* pipeline_capability_map
,
445 bool detected_corrupted_prefs
) {
446 // Preferences have the master data because admins might have pushed new
447 // preferences. Update the cached data with new data from preferences.
448 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
450 UMA_HISTOGRAM_COUNTS("Net.CountOfSpdyServers", spdy_servers
->size());
451 http_server_properties_impl_
->InitializeSpdyServers(spdy_servers
, true);
453 // Clear the cached data and use the new spdy_settings from preferences.
454 UMA_HISTOGRAM_COUNTS("Net.CountOfSpdySettings", spdy_settings_map
->size());
455 http_server_properties_impl_
->InitializeSpdySettingsServers(
458 // Clear the cached data and use the new Alternate-Protocol server list from
460 UMA_HISTOGRAM_COUNTS("Net.CountOfAlternateProtocolServers",
461 alternate_protocol_map
->size());
462 http_server_properties_impl_
->InitializeAlternateProtocolServers(
463 alternate_protocol_map
);
465 UMA_HISTOGRAM_COUNTS("Net.CountOfPipelineCapableServers",
466 pipeline_capability_map
->size());
467 http_server_properties_impl_
->InitializePipelineCapabilities(
468 pipeline_capability_map
);
470 // Update the prefs with what we have read (delete all corrupted prefs).
471 if (detected_corrupted_prefs
)
472 ScheduleUpdatePrefsOnIO();
477 // Update Preferences with data from the cached data.
479 void HttpServerPropertiesManager::ScheduleUpdatePrefsOnIO() {
480 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
481 // Cancel pending updates, if any.
482 io_prefs_update_timer_
->Stop();
483 StartPrefsUpdateTimerOnIO(
484 base::TimeDelta::FromMilliseconds(kUpdatePrefsDelayMs
));
487 void HttpServerPropertiesManager::StartPrefsUpdateTimerOnIO(
488 base::TimeDelta delay
) {
489 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
490 // This is overridden in tests to post the task without the delay.
491 io_prefs_update_timer_
->Start(
492 FROM_HERE
, delay
, this,
493 &HttpServerPropertiesManager::UpdatePrefsFromCacheOnIO
);
496 // This is required so we can set this as the callback for a timer.
497 void HttpServerPropertiesManager::UpdatePrefsFromCacheOnIO() {
498 UpdatePrefsFromCacheOnIO(base::Closure());
501 void HttpServerPropertiesManager::UpdatePrefsFromCacheOnIO(
502 const base::Closure
& completion
) {
503 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
505 base::ListValue
* spdy_server_list
= new base::ListValue
;
506 http_server_properties_impl_
->GetSpdyServerList(spdy_server_list
);
508 net::SpdySettingsMap
* spdy_settings_map
= new net::SpdySettingsMap
;
509 *spdy_settings_map
= http_server_properties_impl_
->spdy_settings_map();
511 net::AlternateProtocolMap
* alternate_protocol_map
=
512 new net::AlternateProtocolMap
;
513 *alternate_protocol_map
=
514 http_server_properties_impl_
->alternate_protocol_map();
516 net::PipelineCapabilityMap
* pipeline_capability_map
=
517 new net::PipelineCapabilityMap
;
518 *pipeline_capability_map
=
519 http_server_properties_impl_
->GetPipelineCapabilityMap();
521 // Update the preferences on the UI thread.
522 BrowserThread::PostTask(
525 base::Bind(&HttpServerPropertiesManager::UpdatePrefsOnUI
,
527 base::Owned(spdy_server_list
),
528 base::Owned(spdy_settings_map
),
529 base::Owned(alternate_protocol_map
),
530 base::Owned(pipeline_capability_map
),
534 // A local or temporary data structure to hold |supports_spdy|, SpdySettings,
535 // PortAlternateProtocolPair, and |pipeline_capability| preferences for a
536 // server. This is used only in UpdatePrefsOnUI.
539 : supports_spdy(false),
541 alternate_protocol(NULL
),
542 pipeline_capability(net::PIPELINE_UNKNOWN
) {
544 ServerPref(bool supports_spdy
,
545 const net::SettingsMap
* settings_map
,
546 const net::PortAlternateProtocolPair
* alternate_protocol
)
547 : supports_spdy(supports_spdy
),
548 settings_map(settings_map
),
549 alternate_protocol(alternate_protocol
),
550 pipeline_capability(net::PIPELINE_UNKNOWN
) {
553 const net::SettingsMap
* settings_map
;
554 const net::PortAlternateProtocolPair
* alternate_protocol
;
555 net::HttpPipelinedHostCapability pipeline_capability
;
558 void HttpServerPropertiesManager::UpdatePrefsOnUI(
559 base::ListValue
* spdy_server_list
,
560 net::SpdySettingsMap
* spdy_settings_map
,
561 net::AlternateProtocolMap
* alternate_protocol_map
,
562 net::PipelineCapabilityMap
* pipeline_capability_map
,
563 const base::Closure
& completion
) {
565 typedef std::map
<net::HostPortPair
, ServerPref
> ServerPrefMap
;
566 ServerPrefMap server_pref_map
;
568 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
570 // Add servers that support spdy to server_pref_map.
572 for (base::ListValue::const_iterator list_it
= spdy_server_list
->begin();
573 list_it
!= spdy_server_list
->end(); ++list_it
) {
574 if ((*list_it
)->GetAsString(&s
)) {
575 net::HostPortPair server
= net::HostPortPair::FromString(s
);
577 ServerPrefMap::iterator it
= server_pref_map
.find(server
);
578 if (it
== server_pref_map
.end()) {
579 ServerPref
server_pref(true, NULL
, NULL
);
580 server_pref_map
[server
] = server_pref
;
582 it
->second
.supports_spdy
= true;
587 // Add servers that have SpdySettings to server_pref_map.
588 for (net::SpdySettingsMap::iterator map_it
=
589 spdy_settings_map
->begin();
590 map_it
!= spdy_settings_map
->end(); ++map_it
) {
591 const net::HostPortPair
& server
= map_it
->first
;
593 ServerPrefMap::iterator it
= server_pref_map
.find(server
);
594 if (it
== server_pref_map
.end()) {
595 ServerPref
server_pref(false, &map_it
->second
, NULL
);
596 server_pref_map
[server
] = server_pref
;
598 it
->second
.settings_map
= &map_it
->second
;
602 // Add AlternateProtocol servers to server_pref_map.
603 for (net::AlternateProtocolMap::const_iterator map_it
=
604 alternate_protocol_map
->begin();
605 map_it
!= alternate_protocol_map
->end(); ++map_it
) {
606 const net::HostPortPair
& server
= map_it
->first
;
607 const net::PortAlternateProtocolPair
& port_alternate_protocol
=
609 if (!net::IsAlternateProtocolValid(port_alternate_protocol
.protocol
)) {
613 ServerPrefMap::iterator it
= server_pref_map
.find(server
);
614 if (it
== server_pref_map
.end()) {
615 ServerPref
server_pref(false, NULL
, &map_it
->second
);
616 server_pref_map
[server
] = server_pref
;
618 it
->second
.alternate_protocol
= &map_it
->second
;
622 for (net::PipelineCapabilityMap::const_iterator map_it
=
623 pipeline_capability_map
->begin();
624 map_it
!= pipeline_capability_map
->end(); ++map_it
) {
625 const net::HostPortPair
& server
= map_it
->first
;
626 const net::HttpPipelinedHostCapability
& pipeline_capability
=
629 ServerPrefMap::iterator it
= server_pref_map
.find(server
);
630 if (it
== server_pref_map
.end()) {
631 ServerPref server_pref
;
632 server_pref
.pipeline_capability
= pipeline_capability
;
633 server_pref_map
[server
] = server_pref
;
635 it
->second
.pipeline_capability
= pipeline_capability
;
639 // Persist the prefs::kHttpServerProperties.
640 base::DictionaryValue http_server_properties_dict
;
641 base::DictionaryValue
* servers_dict
= new base::DictionaryValue
;
642 for (ServerPrefMap::const_iterator map_it
=
643 server_pref_map
.begin();
644 map_it
!= server_pref_map
.end(); ++map_it
) {
645 const net::HostPortPair
& server
= map_it
->first
;
646 const ServerPref
& server_pref
= map_it
->second
;
648 base::DictionaryValue
* server_pref_dict
= new base::DictionaryValue
;
650 // Save supports_spdy.
651 server_pref_dict
->SetBoolean("supports_spdy", server_pref
.supports_spdy
);
653 // Save SPDY settings.
654 if (server_pref
.settings_map
) {
655 base::DictionaryValue
* spdy_settings_dict
= new base::DictionaryValue
;
656 for (net::SettingsMap::const_iterator it
=
657 server_pref
.settings_map
->begin();
658 it
!= server_pref
.settings_map
->end(); ++it
) {
659 net::SpdySettingsIds id
= it
->first
;
660 uint32 value
= it
->second
.second
;
661 std::string key
= base::StringPrintf("%u", id
);
662 spdy_settings_dict
->SetInteger(key
, value
);
664 server_pref_dict
->SetWithoutPathExpansion("settings", spdy_settings_dict
);
667 // Save alternate_protocol.
668 if (server_pref
.alternate_protocol
) {
669 base::DictionaryValue
* port_alternate_protocol_dict
=
670 new base::DictionaryValue
;
671 const net::PortAlternateProtocolPair
* port_alternate_protocol
=
672 server_pref
.alternate_protocol
;
673 port_alternate_protocol_dict
->SetInteger(
674 "port", port_alternate_protocol
->port
);
675 const char* protocol_str
=
676 net::AlternateProtocolToString(port_alternate_protocol
->protocol
);
677 port_alternate_protocol_dict
->SetString("protocol_str", protocol_str
);
678 server_pref_dict
->SetWithoutPathExpansion(
679 "alternate_protocol", port_alternate_protocol_dict
);
682 if (server_pref
.pipeline_capability
!= net::PIPELINE_UNKNOWN
) {
683 server_pref_dict
->SetInteger("pipeline_capability",
684 server_pref
.pipeline_capability
);
687 servers_dict
->SetWithoutPathExpansion(server
.ToString(), server_pref_dict
);
690 http_server_properties_dict
.SetWithoutPathExpansion("servers", servers_dict
);
691 SetVersion(&http_server_properties_dict
, kVersionNumber
);
692 setting_prefs_
= true;
693 pref_service_
->Set(prefs::kHttpServerProperties
,
694 http_server_properties_dict
);
695 setting_prefs_
= false;
697 // Note that |completion| will be fired after we have written everything to
698 // the Preferences, but likely before these changes are serialized to disk.
699 // This is not a problem though, as JSONPrefStore guarantees that this will
700 // happen, pretty soon, and even in the case we shut down immediately.
701 if (!completion
.is_null())
705 void HttpServerPropertiesManager::OnHttpServerPropertiesChanged() {
706 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
708 ScheduleUpdateCacheOnUI();
711 } // namespace chrome_browser_net