Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / net / http_server_properties_manager.cc
blob77579d3da1f90d0c6d63b2e2fdbb2e43dae0080d
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"
7 #include "base/bind.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 {
25 namespace {
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
29 // timer.
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"
38 // property.
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 } // namespace
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));
56 DCHECK(pref_service);
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(
84 BrowserThread::UI,
85 FROM_HERE,
86 base::Bind(&HttpServerPropertiesManager::UpdateCacheFromPrefsOnUI,
87 ui_weak_ptr_));
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();
98 // static
99 void HttpServerPropertiesManager::RegisterProfilePrefs(
100 user_prefs::PrefRegistrySyncable* prefs) {
101 prefs->RegisterDictionaryPref(
102 prefs::kHttpServerProperties,
103 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
106 // static
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,
143 bool support_spdy) {
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,
197 uint32 value) {
198 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
199 bool persist = http_server_properties_impl_->SetSpdySetting(
200 host_port_pair, id, flags, value);
201 if (persist)
202 ScheduleUpdatePrefsOnIO();
203 return persist;
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 net::HttpPipelinedHostCapability
226 HttpServerPropertiesManager::GetPipelineCapability(
227 const net::HostPortPair& origin) {
228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
229 return http_server_properties_impl_->GetPipelineCapability(origin);
232 void HttpServerPropertiesManager::SetPipelineCapability(
233 const net::HostPortPair& origin,
234 net::HttpPipelinedHostCapability capability) {
235 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
236 http_server_properties_impl_->SetPipelineCapability(origin, capability);
237 ScheduleUpdatePrefsOnIO();
240 void HttpServerPropertiesManager::ClearPipelineCapabilities() {
241 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
242 http_server_properties_impl_->ClearPipelineCapabilities();
243 ScheduleUpdatePrefsOnIO();
246 net::PipelineCapabilityMap
247 HttpServerPropertiesManager::GetPipelineCapabilityMap() const {
248 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
249 return http_server_properties_impl_->GetPipelineCapabilityMap();
253 // Update the HttpServerPropertiesImpl's cache with data from preferences.
255 void HttpServerPropertiesManager::ScheduleUpdateCacheOnUI() {
256 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
257 // Cancel pending updates, if any.
258 ui_cache_update_timer_->Stop();
259 StartCacheUpdateTimerOnUI(
260 base::TimeDelta::FromMilliseconds(kUpdateCacheDelayMs));
263 void HttpServerPropertiesManager::StartCacheUpdateTimerOnUI(
264 base::TimeDelta delay) {
265 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
266 ui_cache_update_timer_->Start(
267 FROM_HERE, delay, this,
268 &HttpServerPropertiesManager::UpdateCacheFromPrefsOnUI);
271 void HttpServerPropertiesManager::UpdateCacheFromPrefsOnUI() {
272 // The preferences can only be read on the UI thread.
273 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
275 if (!pref_service_->HasPrefPath(prefs::kHttpServerProperties))
276 return;
278 bool detected_corrupted_prefs = false;
279 const base::DictionaryValue& http_server_properties_dict =
280 *pref_service_->GetDictionary(prefs::kHttpServerProperties);
282 int version = kMissingVersion;
283 if (!http_server_properties_dict.GetIntegerWithoutPathExpansion(
284 "version", &version)) {
285 DVLOG(1) << "Missing version. Clearing all properties.";
286 return;
289 // The properties for a given server is in
290 // http_server_properties_dict["servers"][server].
291 const base::DictionaryValue* servers_dict = NULL;
292 if (!http_server_properties_dict.GetDictionaryWithoutPathExpansion(
293 "servers", &servers_dict)) {
294 DVLOG(1) << "Malformed http_server_properties for servers.";
295 return;
298 // TODO(rtenneti): Mark entries with an LRU sequence number (date of access?),
299 // and then truncate down deleting old stuff.
300 if (version != kVersionNumber && servers_dict->size() > 300) {
301 DVLOG(1) << "Size is too large. Clearing all properties.";
302 return;
305 // String is host/port pair of spdy server.
306 scoped_ptr<StringVector> spdy_servers(new StringVector);
307 scoped_ptr<net::SpdySettingsMap> spdy_settings_map(new net::SpdySettingsMap);
308 scoped_ptr<net::PipelineCapabilityMap> pipeline_capability_map(
309 new net::PipelineCapabilityMap);
310 scoped_ptr<net::AlternateProtocolMap> alternate_protocol_map(
311 new net::AlternateProtocolMap);
313 for (base::DictionaryValue::Iterator it(*servers_dict); !it.IsAtEnd();
314 it.Advance()) {
315 // Get server's host/pair.
316 const std::string& server_str = it.key();
317 net::HostPortPair server = net::HostPortPair::FromString(server_str);
318 if (server.host().empty()) {
319 DVLOG(1) << "Malformed http_server_properties for server: " << server_str;
320 detected_corrupted_prefs = true;
321 continue;
324 const base::DictionaryValue* server_pref_dict = NULL;
325 if (!it.value().GetAsDictionary(&server_pref_dict)) {
326 DVLOG(1) << "Malformed http_server_properties server: " << server_str;
327 detected_corrupted_prefs = true;
328 continue;
331 // Get if server supports Spdy.
332 bool supports_spdy = false;
333 if ((server_pref_dict->GetBoolean(
334 "supports_spdy", &supports_spdy)) && supports_spdy) {
335 spdy_servers->push_back(server_str);
338 // Get SpdySettings.
339 DCHECK(!ContainsKey(*spdy_settings_map, server));
340 const base::DictionaryValue* spdy_settings_dict = NULL;
341 if (server_pref_dict->GetDictionaryWithoutPathExpansion(
342 "settings", &spdy_settings_dict)) {
343 net::SettingsMap settings_map;
344 for (base::DictionaryValue::Iterator dict_it(*spdy_settings_dict);
345 !dict_it.IsAtEnd(); dict_it.Advance()) {
346 const std::string& id_str = dict_it.key();
347 int id = 0;
348 if (!base::StringToInt(id_str, &id)) {
349 DVLOG(1) << "Malformed id in SpdySettings for server: " <<
350 server_str;
351 NOTREACHED();
352 continue;
354 int value = 0;
355 if (!dict_it.value().GetAsInteger(&value)) {
356 DVLOG(1) << "Malformed value in SpdySettings for server: " <<
357 server_str;
358 NOTREACHED();
359 continue;
361 net::SettingsFlagsAndValue flags_and_value(
362 net::SETTINGS_FLAG_PERSISTED, value);
363 settings_map[static_cast<net::SpdySettingsIds>(id)] = flags_and_value;
365 (*spdy_settings_map)[server] = settings_map;
368 int pipeline_capability = net::PIPELINE_UNKNOWN;
369 if ((server_pref_dict->GetInteger(
370 "pipeline_capability", &pipeline_capability)) &&
371 pipeline_capability != net::PIPELINE_UNKNOWN) {
372 (*pipeline_capability_map)[server] =
373 static_cast<net::HttpPipelinedHostCapability>(pipeline_capability);
376 // Get alternate_protocol server.
377 DCHECK(!ContainsKey(*alternate_protocol_map, server));
378 const base::DictionaryValue* port_alternate_protocol_dict = NULL;
379 if (!server_pref_dict->GetDictionaryWithoutPathExpansion(
380 "alternate_protocol", &port_alternate_protocol_dict)) {
381 continue;
384 do {
385 int port = 0;
386 if (!port_alternate_protocol_dict->GetIntegerWithoutPathExpansion(
387 "port", &port) || (port > (1 << 16))) {
388 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str;
389 detected_corrupted_prefs = true;
390 continue;
392 std::string protocol_str;
393 if (!port_alternate_protocol_dict->GetStringWithoutPathExpansion(
394 "protocol_str", &protocol_str)) {
395 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str;
396 detected_corrupted_prefs = true;
397 continue;
399 net::AlternateProtocol protocol =
400 net::AlternateProtocolFromString(protocol_str);
401 if (!net::IsAlternateProtocolValid(protocol)) {
402 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str;
403 detected_corrupted_prefs = true;
404 continue;
407 net::PortAlternateProtocolPair port_alternate_protocol;
408 port_alternate_protocol.port = port;
409 port_alternate_protocol.protocol = protocol;
411 (*alternate_protocol_map)[server] = port_alternate_protocol;
412 } while (false);
415 BrowserThread::PostTask(
416 BrowserThread::IO,
417 FROM_HERE,
418 base::Bind(&HttpServerPropertiesManager::
419 UpdateCacheFromPrefsOnIO,
420 base::Unretained(this),
421 base::Owned(spdy_servers.release()),
422 base::Owned(spdy_settings_map.release()),
423 base::Owned(alternate_protocol_map.release()),
424 base::Owned(pipeline_capability_map.release()),
425 detected_corrupted_prefs));
428 void HttpServerPropertiesManager::UpdateCacheFromPrefsOnIO(
429 StringVector* spdy_servers,
430 net::SpdySettingsMap* spdy_settings_map,
431 net::AlternateProtocolMap* alternate_protocol_map,
432 net::PipelineCapabilityMap* pipeline_capability_map,
433 bool detected_corrupted_prefs) {
434 // Preferences have the master data because admins might have pushed new
435 // preferences. Update the cached data with new data from preferences.
436 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
438 UMA_HISTOGRAM_COUNTS("Net.CountOfSpdyServers", spdy_servers->size());
439 http_server_properties_impl_->InitializeSpdyServers(spdy_servers, true);
441 // Clear the cached data and use the new spdy_settings from preferences.
442 UMA_HISTOGRAM_COUNTS("Net.CountOfSpdySettings", spdy_settings_map->size());
443 http_server_properties_impl_->InitializeSpdySettingsServers(
444 spdy_settings_map);
446 // Clear the cached data and use the new Alternate-Protocol server list from
447 // preferences.
448 UMA_HISTOGRAM_COUNTS("Net.CountOfAlternateProtocolServers",
449 alternate_protocol_map->size());
450 http_server_properties_impl_->InitializeAlternateProtocolServers(
451 alternate_protocol_map);
453 UMA_HISTOGRAM_COUNTS("Net.CountOfPipelineCapableServers",
454 pipeline_capability_map->size());
455 http_server_properties_impl_->InitializePipelineCapabilities(
456 pipeline_capability_map);
458 // Update the prefs with what we have read (delete all corrupted prefs).
459 if (detected_corrupted_prefs)
460 ScheduleUpdatePrefsOnIO();
465 // Update Preferences with data from the cached data.
467 void HttpServerPropertiesManager::ScheduleUpdatePrefsOnIO() {
468 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
469 // Cancel pending updates, if any.
470 io_prefs_update_timer_->Stop();
471 StartPrefsUpdateTimerOnIO(
472 base::TimeDelta::FromMilliseconds(kUpdatePrefsDelayMs));
475 void HttpServerPropertiesManager::StartPrefsUpdateTimerOnIO(
476 base::TimeDelta delay) {
477 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
478 // This is overridden in tests to post the task without the delay.
479 io_prefs_update_timer_->Start(
480 FROM_HERE, delay, this,
481 &HttpServerPropertiesManager::UpdatePrefsFromCacheOnIO);
484 // This is required so we can set this as the callback for a timer.
485 void HttpServerPropertiesManager::UpdatePrefsFromCacheOnIO() {
486 UpdatePrefsFromCacheOnIO(base::Closure());
489 void HttpServerPropertiesManager::UpdatePrefsFromCacheOnIO(
490 const base::Closure& completion) {
491 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
493 base::ListValue* spdy_server_list = new base::ListValue;
494 http_server_properties_impl_->GetSpdyServerList(spdy_server_list);
496 net::SpdySettingsMap* spdy_settings_map = new net::SpdySettingsMap;
497 *spdy_settings_map = http_server_properties_impl_->spdy_settings_map();
499 net::AlternateProtocolMap* alternate_protocol_map =
500 new net::AlternateProtocolMap;
501 *alternate_protocol_map =
502 http_server_properties_impl_->alternate_protocol_map();
504 net::PipelineCapabilityMap* pipeline_capability_map =
505 new net::PipelineCapabilityMap;
506 *pipeline_capability_map =
507 http_server_properties_impl_->GetPipelineCapabilityMap();
509 // Update the preferences on the UI thread.
510 BrowserThread::PostTask(
511 BrowserThread::UI,
512 FROM_HERE,
513 base::Bind(&HttpServerPropertiesManager::UpdatePrefsOnUI,
514 ui_weak_ptr_,
515 base::Owned(spdy_server_list),
516 base::Owned(spdy_settings_map),
517 base::Owned(alternate_protocol_map),
518 base::Owned(pipeline_capability_map),
519 completion));
522 // A local or temporary data structure to hold |supports_spdy|, SpdySettings,
523 // PortAlternateProtocolPair, and |pipeline_capability| preferences for a
524 // server. This is used only in UpdatePrefsOnUI.
525 struct ServerPref {
526 ServerPref()
527 : supports_spdy(false),
528 settings_map(NULL),
529 alternate_protocol(NULL),
530 pipeline_capability(net::PIPELINE_UNKNOWN) {
532 ServerPref(bool supports_spdy,
533 const net::SettingsMap* settings_map,
534 const net::PortAlternateProtocolPair* alternate_protocol)
535 : supports_spdy(supports_spdy),
536 settings_map(settings_map),
537 alternate_protocol(alternate_protocol),
538 pipeline_capability(net::PIPELINE_UNKNOWN) {
540 bool supports_spdy;
541 const net::SettingsMap* settings_map;
542 const net::PortAlternateProtocolPair* alternate_protocol;
543 net::HttpPipelinedHostCapability pipeline_capability;
546 void HttpServerPropertiesManager::UpdatePrefsOnUI(
547 base::ListValue* spdy_server_list,
548 net::SpdySettingsMap* spdy_settings_map,
549 net::AlternateProtocolMap* alternate_protocol_map,
550 net::PipelineCapabilityMap* pipeline_capability_map,
551 const base::Closure& completion) {
553 typedef std::map<net::HostPortPair, ServerPref> ServerPrefMap;
554 ServerPrefMap server_pref_map;
556 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
558 // Add servers that support spdy to server_pref_map.
559 std::string s;
560 for (base::ListValue::const_iterator list_it = spdy_server_list->begin();
561 list_it != spdy_server_list->end(); ++list_it) {
562 if ((*list_it)->GetAsString(&s)) {
563 net::HostPortPair server = net::HostPortPair::FromString(s);
565 ServerPrefMap::iterator it = server_pref_map.find(server);
566 if (it == server_pref_map.end()) {
567 ServerPref server_pref(true, NULL, NULL);
568 server_pref_map[server] = server_pref;
569 } else {
570 it->second.supports_spdy = true;
575 // Add servers that have SpdySettings to server_pref_map.
576 for (net::SpdySettingsMap::iterator map_it =
577 spdy_settings_map->begin();
578 map_it != spdy_settings_map->end(); ++map_it) {
579 const net::HostPortPair& server = map_it->first;
581 ServerPrefMap::iterator it = server_pref_map.find(server);
582 if (it == server_pref_map.end()) {
583 ServerPref server_pref(false, &map_it->second, NULL);
584 server_pref_map[server] = server_pref;
585 } else {
586 it->second.settings_map = &map_it->second;
590 // Add AlternateProtocol servers to server_pref_map.
591 for (net::AlternateProtocolMap::const_iterator map_it =
592 alternate_protocol_map->begin();
593 map_it != alternate_protocol_map->end(); ++map_it) {
594 const net::HostPortPair& server = map_it->first;
595 const net::PortAlternateProtocolPair& port_alternate_protocol =
596 map_it->second;
597 if (!net::IsAlternateProtocolValid(port_alternate_protocol.protocol)) {
598 continue;
601 ServerPrefMap::iterator it = server_pref_map.find(server);
602 if (it == server_pref_map.end()) {
603 ServerPref server_pref(false, NULL, &map_it->second);
604 server_pref_map[server] = server_pref;
605 } else {
606 it->second.alternate_protocol = &map_it->second;
610 for (net::PipelineCapabilityMap::const_iterator map_it =
611 pipeline_capability_map->begin();
612 map_it != pipeline_capability_map->end(); ++map_it) {
613 const net::HostPortPair& server = map_it->first;
614 const net::HttpPipelinedHostCapability& pipeline_capability =
615 map_it->second;
617 ServerPrefMap::iterator it = server_pref_map.find(server);
618 if (it == server_pref_map.end()) {
619 ServerPref server_pref;
620 server_pref.pipeline_capability = pipeline_capability;
621 server_pref_map[server] = server_pref;
622 } else {
623 it->second.pipeline_capability = pipeline_capability;
627 // Persist the prefs::kHttpServerProperties.
628 base::DictionaryValue http_server_properties_dict;
629 base::DictionaryValue* servers_dict = new base::DictionaryValue;
630 for (ServerPrefMap::const_iterator map_it =
631 server_pref_map.begin();
632 map_it != server_pref_map.end(); ++map_it) {
633 const net::HostPortPair& server = map_it->first;
634 const ServerPref& server_pref = map_it->second;
636 base::DictionaryValue* server_pref_dict = new base::DictionaryValue;
638 // Save supports_spdy.
639 server_pref_dict->SetBoolean("supports_spdy", server_pref.supports_spdy);
641 // Save SPDY settings.
642 if (server_pref.settings_map) {
643 base::DictionaryValue* spdy_settings_dict = new base::DictionaryValue;
644 for (net::SettingsMap::const_iterator it =
645 server_pref.settings_map->begin();
646 it != server_pref.settings_map->end(); ++it) {
647 net::SpdySettingsIds id = it->first;
648 uint32 value = it->second.second;
649 std::string key = base::StringPrintf("%u", id);
650 spdy_settings_dict->SetInteger(key, value);
652 server_pref_dict->SetWithoutPathExpansion("settings", spdy_settings_dict);
655 // Save alternate_protocol.
656 if (server_pref.alternate_protocol) {
657 base::DictionaryValue* port_alternate_protocol_dict =
658 new base::DictionaryValue;
659 const net::PortAlternateProtocolPair* port_alternate_protocol =
660 server_pref.alternate_protocol;
661 port_alternate_protocol_dict->SetInteger(
662 "port", port_alternate_protocol->port);
663 const char* protocol_str =
664 net::AlternateProtocolToString(port_alternate_protocol->protocol);
665 port_alternate_protocol_dict->SetString("protocol_str", protocol_str);
666 server_pref_dict->SetWithoutPathExpansion(
667 "alternate_protocol", port_alternate_protocol_dict);
670 if (server_pref.pipeline_capability != net::PIPELINE_UNKNOWN) {
671 server_pref_dict->SetInteger("pipeline_capability",
672 server_pref.pipeline_capability);
675 servers_dict->SetWithoutPathExpansion(server.ToString(), server_pref_dict);
678 http_server_properties_dict.SetWithoutPathExpansion("servers", servers_dict);
679 SetVersion(&http_server_properties_dict, kVersionNumber);
680 setting_prefs_ = true;
681 pref_service_->Set(prefs::kHttpServerProperties,
682 http_server_properties_dict);
683 setting_prefs_ = false;
685 // Note that |completion| will be fired after we have written everything to
686 // the Preferences, but likely before these changes are serialized to disk.
687 // This is not a problem though, as JSONPrefStore guarantees that this will
688 // happen, pretty soon, and even in the case we shut down immediately.
689 if (!completion.is_null())
690 completion.Run();
693 void HttpServerPropertiesManager::OnHttpServerPropertiesChanged() {
694 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
695 if (!setting_prefs_)
696 ScheduleUpdateCacheOnUI();
699 } // namespace chrome_browser_net