[safe-browsing] Database full hash matches like prefix match.
[chromium-blink-merge.git] / chrome / browser / net / http_server_properties_manager.cc
blob24ccfa0e6db5b92f7b87f21ea22c30a3c32df7a6
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 // 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;
55 } // namespace
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));
65 DCHECK(pref_service);
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(
93 BrowserThread::UI,
94 FROM_HERE,
95 base::Bind(&HttpServerPropertiesManager::UpdateCacheFromPrefsOnUI,
96 ui_weak_ptr_));
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();
107 // static
108 void HttpServerPropertiesManager::RegisterProfilePrefs(
109 user_prefs::PrefRegistrySyncable* prefs) {
110 prefs->RegisterDictionaryPref(
111 prefs::kHttpServerProperties,
112 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
115 // static
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,
152 bool support_spdy) {
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(
193 server);
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,
227 uint32 value) {
228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
229 bool persist = http_server_properties_impl_->SetSpdySetting(
230 host_port_pair, id, flags, value);
231 if (persist)
232 ScheduleUpdatePrefsOnIO();
233 return persist;
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))
318 return;
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.";
328 return;
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.";
337 return;
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();
350 it.Advance()) {
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;
357 continue;
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;
364 continue;
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);
374 // Get SpdySettings.
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();
383 int id = 0;
384 if (!base::StringToInt(id_str, &id)) {
385 DVLOG(1) << "Malformed id in SpdySettings for server: " <<
386 server_str;
387 NOTREACHED();
388 continue;
390 int value = 0;
391 if (!dict_it.value().GetAsInteger(&value)) {
392 DVLOG(1) << "Malformed value in SpdySettings for server: " <<
393 server_str;
394 NOTREACHED();
395 continue;
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)) {
418 continue;
421 do {
422 int port = 0;
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;
427 continue;
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;
434 continue;
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;
441 continue;
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);
449 } while (false);
452 BrowserThread::PostTask(
453 BrowserThread::IO,
454 FROM_HERE,
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(
481 spdy_settings_map);
483 // Clear the cached data and use the new Alternate-Protocol server list from
484 // preferences.
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();
538 int count = 0;
539 for (net::SpdySettingsMap::const_iterator it = main_map.begin();
540 it != main_map.end() && count < kMaxSpdySettingsHostsToPersist;
541 ++it, ++count) {
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();
549 count = 0;
550 for (net::AlternateProtocolMap::const_iterator it = map.begin();
551 it != map.end() && count < kMaxAlternateProtocolHostsToPersist;
552 ++it, ++count) {
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(
563 BrowserThread::UI,
564 FROM_HERE,
565 base::Bind(&HttpServerPropertiesManager::UpdatePrefsOnUI,
566 ui_weak_ptr_,
567 base::Owned(spdy_server_list),
568 base::Owned(spdy_settings_map),
569 base::Owned(alternate_protocol_map),
570 base::Owned(pipeline_capability_map),
571 completion));
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.
577 struct ServerPref {
578 ServerPref()
579 : supports_spdy(false),
580 settings_map(NULL),
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) {
592 bool supports_spdy;
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.
611 std::string s;
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;
621 } else {
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;
636 } else {
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 =
647 map_it->second;
648 if (!net::IsAlternateProtocolValid(port_alternate_protocol.protocol)) {
649 continue;
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;
656 } else {
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 =
666 map_it->second;
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;
673 } else {
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())
742 completion.Run();
745 void HttpServerPropertiesManager::OnHttpServerPropertiesChanged() {
746 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
747 if (!setting_prefs_)
748 ScheduleUpdateCacheOnUI();
751 } // namespace chrome_browser_net