Roll src/third_party/WebKit 8b42d1d:744641d (svn 186770:186771)
[chromium-blink-merge.git] / net / http / http_server_properties_manager.cc
blob62db0b4a26fe5d658a32704f12f30ba39d20c84f
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/http/http_server_properties_manager.h"
7 #include "base/bind.h"
8 #include "base/metrics/histogram.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/stl_util.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "base/values.h"
16 #include "net/base/net_util.h"
18 namespace net {
20 namespace {
22 // Time to wait before starting an update the http_server_properties_impl_ cache
23 // from preferences. Scheduling another update during this period will reset the
24 // timer.
25 const int64 kUpdateCacheDelayMs = 1000;
27 // Time to wait before starting an update the preferences from the
28 // http_server_properties_impl_ cache. Scheduling another update during this
29 // period will reset the timer.
30 const int64 kUpdatePrefsDelayMs = 5000;
32 // "version" 0 indicates, http_server_properties doesn't have "version"
33 // property.
34 const int kMissingVersion = 0;
36 // The version number of persisted http_server_properties.
37 const int kVersionNumber = 3;
39 typedef std::vector<std::string> StringVector;
41 // Persist 200 MRU AlternateProtocolHostPortPairs.
42 const int kMaxAlternateProtocolHostsToPersist = 200;
44 // Persist 200 MRU SpdySettingsHostPortPairs.
45 const int kMaxSpdySettingsHostsToPersist = 200;
47 // Persist 300 MRU SupportsSpdyServerHostPortPairs.
48 const int kMaxSupportsSpdyServerHostsToPersist = 300;
50 } // namespace
52 ////////////////////////////////////////////////////////////////////////////////
53 // HttpServerPropertiesManager
55 HttpServerPropertiesManager::HttpServerPropertiesManager(
56 PrefService* pref_service,
57 const char* pref_path,
58 scoped_refptr<base::SequencedTaskRunner> network_task_runner)
59 : pref_task_runner_(base::ThreadTaskRunnerHandle::Get()),
60 pref_service_(pref_service),
61 setting_prefs_(false),
62 path_(pref_path),
63 network_task_runner_(network_task_runner) {
64 DCHECK(pref_service);
65 pref_weak_ptr_factory_.reset(
66 new base::WeakPtrFactory<HttpServerPropertiesManager>(this));
67 pref_weak_ptr_ = pref_weak_ptr_factory_->GetWeakPtr();
68 pref_cache_update_timer_.reset(
69 new base::OneShotTimer<HttpServerPropertiesManager>);
70 pref_change_registrar_.Init(pref_service_);
71 pref_change_registrar_.Add(
72 path_,
73 base::Bind(&HttpServerPropertiesManager::OnHttpServerPropertiesChanged,
74 base::Unretained(this)));
77 HttpServerPropertiesManager::~HttpServerPropertiesManager() {
78 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
79 network_weak_ptr_factory_.reset();
82 void HttpServerPropertiesManager::InitializeOnNetworkThread() {
83 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
84 network_weak_ptr_factory_.reset(
85 new base::WeakPtrFactory<HttpServerPropertiesManager>(this));
86 http_server_properties_impl_.reset(new net::HttpServerPropertiesImpl());
88 network_prefs_update_timer_.reset(
89 new base::OneShotTimer<HttpServerPropertiesManager>);
91 pref_task_runner_->PostTask(
92 FROM_HERE,
93 base::Bind(&HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread,
94 pref_weak_ptr_));
97 void HttpServerPropertiesManager::ShutdownOnPrefThread() {
98 DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
99 // Cancel any pending updates, and stop listening for pref change updates.
100 pref_cache_update_timer_->Stop();
101 pref_weak_ptr_factory_.reset();
102 pref_change_registrar_.RemoveAll();
105 // static
106 void HttpServerPropertiesManager::SetVersion(
107 base::DictionaryValue* http_server_properties_dict,
108 int version_number) {
109 if (version_number < 0)
110 version_number = kVersionNumber;
111 DCHECK_LE(version_number, kVersionNumber);
112 if (version_number <= kVersionNumber)
113 http_server_properties_dict->SetInteger("version", version_number);
116 // This is required for conformance with the HttpServerProperties interface.
117 base::WeakPtr<net::HttpServerProperties>
118 HttpServerPropertiesManager::GetWeakPtr() {
119 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
120 return network_weak_ptr_factory_->GetWeakPtr();
123 void HttpServerPropertiesManager::Clear() {
124 Clear(base::Closure());
127 void HttpServerPropertiesManager::Clear(const base::Closure& completion) {
128 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
130 http_server_properties_impl_->Clear();
131 UpdatePrefsFromCacheOnNetworkThread(completion);
134 bool HttpServerPropertiesManager::SupportsSpdy(
135 const net::HostPortPair& server) {
136 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
137 return http_server_properties_impl_->SupportsSpdy(server);
140 void HttpServerPropertiesManager::SetSupportsSpdy(
141 const net::HostPortPair& server,
142 bool support_spdy) {
143 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
145 http_server_properties_impl_->SetSupportsSpdy(server, support_spdy);
146 ScheduleUpdatePrefsOnNetworkThread();
149 bool HttpServerPropertiesManager::HasAlternateProtocol(
150 const net::HostPortPair& server) {
151 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
152 return http_server_properties_impl_->HasAlternateProtocol(server);
155 net::AlternateProtocolInfo
156 HttpServerPropertiesManager::GetAlternateProtocol(
157 const net::HostPortPair& server) {
158 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
159 return http_server_properties_impl_->GetAlternateProtocol(server);
162 void HttpServerPropertiesManager::SetAlternateProtocol(
163 const net::HostPortPair& server,
164 uint16 alternate_port,
165 AlternateProtocol alternate_protocol,
166 double alternate_probability) {
167 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
168 http_server_properties_impl_->SetAlternateProtocol(
169 server, alternate_port, alternate_protocol, alternate_probability);
170 ScheduleUpdatePrefsOnNetworkThread();
173 void HttpServerPropertiesManager::SetBrokenAlternateProtocol(
174 const net::HostPortPair& server) {
175 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
176 http_server_properties_impl_->SetBrokenAlternateProtocol(server);
177 ScheduleUpdatePrefsOnNetworkThread();
180 bool HttpServerPropertiesManager::WasAlternateProtocolRecentlyBroken(
181 const net::HostPortPair& server) {
182 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
183 return http_server_properties_impl_->WasAlternateProtocolRecentlyBroken(
184 server);
187 void HttpServerPropertiesManager::ConfirmAlternateProtocol(
188 const net::HostPortPair& server) {
189 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
190 http_server_properties_impl_->ConfirmAlternateProtocol(server);
191 ScheduleUpdatePrefsOnNetworkThread();
194 void HttpServerPropertiesManager::ClearAlternateProtocol(
195 const net::HostPortPair& server) {
196 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
197 http_server_properties_impl_->ClearAlternateProtocol(server);
198 ScheduleUpdatePrefsOnNetworkThread();
201 const net::AlternateProtocolMap&
202 HttpServerPropertiesManager::alternate_protocol_map() const {
203 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
204 return http_server_properties_impl_->alternate_protocol_map();
207 void HttpServerPropertiesManager::SetAlternateProtocolProbabilityThreshold(
208 double threshold) {
209 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
210 http_server_properties_impl_->SetAlternateProtocolProbabilityThreshold(
211 threshold);
214 const SettingsMap& HttpServerPropertiesManager::GetSpdySettings(
215 const HostPortPair& host_port_pair) {
216 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
217 return http_server_properties_impl_->GetSpdySettings(host_port_pair);
220 bool HttpServerPropertiesManager::SetSpdySetting(
221 const HostPortPair& host_port_pair,
222 SpdySettingsIds id,
223 SpdySettingsFlags flags,
224 uint32 value) {
225 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
226 bool persist = http_server_properties_impl_->SetSpdySetting(
227 host_port_pair, id, flags, value);
228 if (persist)
229 ScheduleUpdatePrefsOnNetworkThread();
230 return persist;
233 void HttpServerPropertiesManager::ClearSpdySettings(
234 const HostPortPair& host_port_pair) {
235 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
236 http_server_properties_impl_->ClearSpdySettings(host_port_pair);
237 ScheduleUpdatePrefsOnNetworkThread();
240 void HttpServerPropertiesManager::ClearAllSpdySettings() {
241 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
242 http_server_properties_impl_->ClearAllSpdySettings();
243 ScheduleUpdatePrefsOnNetworkThread();
246 const SpdySettingsMap& HttpServerPropertiesManager::spdy_settings_map()
247 const {
248 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
249 return http_server_properties_impl_->spdy_settings_map();
252 net::SupportsQuic
253 HttpServerPropertiesManager::GetSupportsQuic(
254 const net::HostPortPair& host_port_pair) const {
255 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
256 return http_server_properties_impl_->GetSupportsQuic(host_port_pair);
259 void HttpServerPropertiesManager::SetSupportsQuic(
260 const net::HostPortPair& host_port_pair,
261 bool used_quic,
262 const std::string& address) {
263 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
264 http_server_properties_impl_->SetSupportsQuic(
265 host_port_pair, used_quic, address);
266 ScheduleUpdatePrefsOnNetworkThread();
269 const SupportsQuicMap& HttpServerPropertiesManager::supports_quic_map()
270 const {
271 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
272 return http_server_properties_impl_->supports_quic_map();
275 void HttpServerPropertiesManager::SetServerNetworkStats(
276 const net::HostPortPair& host_port_pair,
277 NetworkStats stats) {
278 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
279 http_server_properties_impl_->SetServerNetworkStats(host_port_pair, stats);
282 const HttpServerPropertiesManager::NetworkStats*
283 HttpServerPropertiesManager::GetServerNetworkStats(
284 const net::HostPortPair& host_port_pair) const {
285 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
286 return http_server_properties_impl_->GetServerNetworkStats(host_port_pair);
290 // Update the HttpServerPropertiesImpl's cache with data from preferences.
292 void HttpServerPropertiesManager::ScheduleUpdateCacheOnPrefThread() {
293 DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
294 // Cancel pending updates, if any.
295 pref_cache_update_timer_->Stop();
296 StartCacheUpdateTimerOnPrefThread(
297 base::TimeDelta::FromMilliseconds(kUpdateCacheDelayMs));
300 void HttpServerPropertiesManager::StartCacheUpdateTimerOnPrefThread(
301 base::TimeDelta delay) {
302 DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
303 pref_cache_update_timer_->Start(
304 FROM_HERE,
305 delay,
306 this,
307 &HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread);
310 void HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread() {
311 // The preferences can only be read on the pref thread.
312 DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
314 if (!pref_service_->HasPrefPath(path_))
315 return;
317 bool detected_corrupted_prefs = false;
318 const base::DictionaryValue& http_server_properties_dict =
319 *pref_service_->GetDictionary(path_);
321 int version = kMissingVersion;
322 if (!http_server_properties_dict.GetIntegerWithoutPathExpansion("version",
323 &version)) {
324 DVLOG(1) << "Missing version. Clearing all properties.";
325 return;
328 // The properties for a given server is in
329 // http_server_properties_dict["servers"][server].
330 const base::DictionaryValue* servers_dict = NULL;
331 if (!http_server_properties_dict.GetDictionaryWithoutPathExpansion(
332 "servers", &servers_dict)) {
333 DVLOG(1) << "Malformed http_server_properties for servers.";
334 return;
337 // String is host/port pair of spdy server.
338 scoped_ptr<StringVector> spdy_servers(new StringVector);
339 scoped_ptr<net::SpdySettingsMap> spdy_settings_map(
340 new net::SpdySettingsMap(kMaxSpdySettingsHostsToPersist));
341 scoped_ptr<net::AlternateProtocolMap> alternate_protocol_map(
342 new net::AlternateProtocolMap(kMaxAlternateProtocolHostsToPersist));
343 scoped_ptr<net::SupportsQuicMap> supports_quic_map(
344 new net::SupportsQuicMap());
346 int count = 0;
347 for (base::DictionaryValue::Iterator it(*servers_dict); !it.IsAtEnd();
348 it.Advance()) {
349 // Get server's host/pair.
350 const std::string& server_str = it.key();
351 net::HostPortPair server = net::HostPortPair::FromString(server_str);
352 if (server.host().empty()) {
353 DVLOG(1) << "Malformed http_server_properties for server: " << server_str;
354 detected_corrupted_prefs = true;
355 continue;
358 const base::DictionaryValue* server_pref_dict = NULL;
359 if (!it.value().GetAsDictionary(&server_pref_dict)) {
360 DVLOG(1) << "Malformed http_server_properties server: " << server_str;
361 detected_corrupted_prefs = true;
362 continue;
365 // Get if server supports Spdy.
366 bool supports_spdy = false;
367 if ((server_pref_dict->GetBoolean("supports_spdy", &supports_spdy)) &&
368 supports_spdy) {
369 spdy_servers->push_back(server_str);
372 // Get SpdySettings.
373 DCHECK(spdy_settings_map->Peek(server) == spdy_settings_map->end());
374 const base::DictionaryValue* spdy_settings_dict = NULL;
375 if (server_pref_dict->GetDictionaryWithoutPathExpansion(
376 "settings", &spdy_settings_dict)) {
377 net::SettingsMap settings_map;
378 for (base::DictionaryValue::Iterator dict_it(*spdy_settings_dict);
379 !dict_it.IsAtEnd();
380 dict_it.Advance()) {
381 const std::string& id_str = dict_it.key();
382 int id = 0;
383 if (!base::StringToInt(id_str, &id)) {
384 DVLOG(1) << "Malformed id in SpdySettings for server: " << server_str;
385 NOTREACHED();
386 continue;
388 int value = 0;
389 if (!dict_it.value().GetAsInteger(&value)) {
390 DVLOG(1) << "Malformed value in SpdySettings for server: "
391 << server_str;
392 NOTREACHED();
393 continue;
395 net::SettingsFlagsAndValue flags_and_value(net::SETTINGS_FLAG_PERSISTED,
396 value);
397 settings_map[static_cast<net::SpdySettingsIds>(id)] = flags_and_value;
399 spdy_settings_map->Put(server, settings_map);
402 // Get alternate_protocol server.
403 DCHECK(alternate_protocol_map->Peek(server) ==
404 alternate_protocol_map->end());
405 const base::DictionaryValue* port_alternate_protocol_dict = NULL;
406 if (!server_pref_dict->GetDictionaryWithoutPathExpansion(
407 "alternate_protocol", &port_alternate_protocol_dict)) {
408 continue;
411 if (count >= kMaxAlternateProtocolHostsToPersist)
412 continue;
413 do {
414 int port = 0;
415 if (!port_alternate_protocol_dict->GetIntegerWithoutPathExpansion(
416 "port", &port) ||
417 !IsPortValid(port)) {
418 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str;
419 detected_corrupted_prefs = true;
420 continue;
422 std::string protocol_str;
423 if (!port_alternate_protocol_dict->GetStringWithoutPathExpansion(
424 "protocol_str", &protocol_str)) {
425 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str;
426 detected_corrupted_prefs = true;
427 continue;
429 net::AlternateProtocol protocol =
430 net::AlternateProtocolFromString(protocol_str);
431 if (!net::IsAlternateProtocolValid(protocol)) {
432 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str;
433 detected_corrupted_prefs = true;
434 continue;
437 double probability = 1;
438 if (port_alternate_protocol_dict->HasKey("probability") &&
439 !port_alternate_protocol_dict->GetDoubleWithoutPathExpansion(
440 "probability", &probability)) {
441 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str;
442 detected_corrupted_prefs = true;
443 continue;
446 net::AlternateProtocolInfo port_alternate_protocol(
447 static_cast<uint16>(port), protocol, probability);
448 alternate_protocol_map->Put(server, port_alternate_protocol);
449 ++count;
450 } while (false);
452 // Get SupportsQuic.
453 DCHECK(supports_quic_map->find(server) == supports_quic_map->end());
454 const base::DictionaryValue* supports_quic_dict = NULL;
455 if (!server_pref_dict->GetDictionaryWithoutPathExpansion(
456 "supports_quic", &supports_quic_dict)) {
457 continue;
459 do {
460 bool used_quic = 0;
461 if (!supports_quic_dict->GetBooleanWithoutPathExpansion(
462 "used_quic", &used_quic)) {
463 DVLOG(1) << "Malformed SupportsQuic server: " << server_str;
464 detected_corrupted_prefs = true;
465 continue;
467 std::string address;
468 if (!supports_quic_dict->GetStringWithoutPathExpansion(
469 "address", &address)) {
470 DVLOG(1) << "Malformed SupportsQuic server: " << server_str;
471 detected_corrupted_prefs = true;
472 continue;
474 net::SupportsQuic supports_quic(used_quic, address);
475 supports_quic_map->insert(std::make_pair(server, supports_quic));
476 } while (false);
479 network_task_runner_->PostTask(
480 FROM_HERE,
481 base::Bind(
482 &HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread,
483 base::Unretained(this),
484 base::Owned(spdy_servers.release()),
485 base::Owned(spdy_settings_map.release()),
486 base::Owned(alternate_protocol_map.release()),
487 base::Owned(supports_quic_map.release()),
488 detected_corrupted_prefs));
491 void HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread(
492 StringVector* spdy_servers,
493 net::SpdySettingsMap* spdy_settings_map,
494 net::AlternateProtocolMap* alternate_protocol_map,
495 net::SupportsQuicMap* supports_quic_map,
496 bool detected_corrupted_prefs) {
497 // Preferences have the master data because admins might have pushed new
498 // preferences. Update the cached data with new data from preferences.
499 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
501 UMA_HISTOGRAM_COUNTS("Net.CountOfSpdyServers", spdy_servers->size());
502 http_server_properties_impl_->InitializeSpdyServers(spdy_servers, true);
504 // Update the cached data and use the new spdy_settings from preferences.
505 UMA_HISTOGRAM_COUNTS("Net.CountOfSpdySettings", spdy_settings_map->size());
506 http_server_properties_impl_->InitializeSpdySettingsServers(
507 spdy_settings_map);
509 // Update the cached data and use the new Alternate-Protocol server list from
510 // preferences.
511 UMA_HISTOGRAM_COUNTS("Net.CountOfAlternateProtocolServers",
512 alternate_protocol_map->size());
513 http_server_properties_impl_->InitializeAlternateProtocolServers(
514 alternate_protocol_map);
516 http_server_properties_impl_->InitializeSupportsQuic(supports_quic_map);
518 // Update the prefs with what we have read (delete all corrupted prefs).
519 if (detected_corrupted_prefs)
520 ScheduleUpdatePrefsOnNetworkThread();
524 // Update Preferences with data from the cached data.
526 void HttpServerPropertiesManager::ScheduleUpdatePrefsOnNetworkThread() {
527 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
528 // Cancel pending updates, if any.
529 network_prefs_update_timer_->Stop();
530 StartPrefsUpdateTimerOnNetworkThread(
531 base::TimeDelta::FromMilliseconds(kUpdatePrefsDelayMs));
534 void HttpServerPropertiesManager::StartPrefsUpdateTimerOnNetworkThread(
535 base::TimeDelta delay) {
536 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
537 // This is overridden in tests to post the task without the delay.
538 network_prefs_update_timer_->Start(
539 FROM_HERE,
540 delay,
541 this,
542 &HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread);
545 // This is required so we can set this as the callback for a timer.
546 void HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread() {
547 UpdatePrefsFromCacheOnNetworkThread(base::Closure());
550 void HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread(
551 const base::Closure& completion) {
552 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
554 base::ListValue* spdy_server_list = new base::ListValue;
555 http_server_properties_impl_->GetSpdyServerList(
556 spdy_server_list, kMaxSupportsSpdyServerHostsToPersist);
558 net::SpdySettingsMap* spdy_settings_map =
559 new net::SpdySettingsMap(kMaxSpdySettingsHostsToPersist);
560 const net::SpdySettingsMap& main_map =
561 http_server_properties_impl_->spdy_settings_map();
562 int count = 0;
563 for (net::SpdySettingsMap::const_iterator it = main_map.begin();
564 it != main_map.end() && count < kMaxSpdySettingsHostsToPersist;
565 ++it, ++count) {
566 spdy_settings_map->Put(it->first, it->second);
569 net::AlternateProtocolMap* alternate_protocol_map =
570 new net::AlternateProtocolMap(kMaxAlternateProtocolHostsToPersist);
571 const net::AlternateProtocolMap& map =
572 http_server_properties_impl_->alternate_protocol_map();
573 count = 0;
574 typedef std::map<std::string, bool> CanonicalHostPersistedMap;
575 CanonicalHostPersistedMap persisted_map;
576 for (net::AlternateProtocolMap::const_iterator it = map.begin();
577 it != map.end() && count < kMaxAlternateProtocolHostsToPersist;
578 ++it) {
579 const net::HostPortPair& server = it->first;
580 std::string canonical_suffix =
581 http_server_properties_impl_->GetCanonicalSuffix(server);
582 if (!canonical_suffix.empty()) {
583 if (persisted_map.find(canonical_suffix) != persisted_map.end())
584 continue;
585 persisted_map[canonical_suffix] = true;
587 alternate_protocol_map->Put(server, it->second);
588 ++count;
591 net::SupportsQuicMap* supports_quic_map = new net::SupportsQuicMap();
592 const net::SupportsQuicMap& main_supports_quic_map =
593 http_server_properties_impl_->supports_quic_map();
594 for (net::SupportsQuicMap::const_iterator it = main_supports_quic_map.begin();
595 it != main_supports_quic_map.end(); ++it) {
596 supports_quic_map->insert(std::make_pair(it->first, it->second));
599 // Update the preferences on the pref thread.
600 pref_task_runner_->PostTask(
601 FROM_HERE,
602 base::Bind(&HttpServerPropertiesManager::UpdatePrefsOnPrefThread,
603 pref_weak_ptr_,
604 base::Owned(spdy_server_list),
605 base::Owned(spdy_settings_map),
606 base::Owned(alternate_protocol_map),
607 base::Owned(supports_quic_map),
608 completion));
611 // A local or temporary data structure to hold |supports_spdy|, SpdySettings,
612 // AlternateProtocolInfo and SupportsQuic preferences for a server. This is used
613 // only in UpdatePrefsOnPrefThread.
614 struct ServerPref {
615 ServerPref() : supports_spdy(false),
616 settings_map(NULL),
617 alternate_protocol(NULL),
618 supports_quic(NULL) {}
619 ServerPref(bool supports_spdy,
620 const net::SettingsMap* settings_map,
621 const net::AlternateProtocolInfo* alternate_protocol,
622 const net::SupportsQuic* supports_quic)
623 : supports_spdy(supports_spdy),
624 settings_map(settings_map),
625 alternate_protocol(alternate_protocol),
626 supports_quic(supports_quic) {}
627 bool supports_spdy;
628 const net::SettingsMap* settings_map;
629 const net::AlternateProtocolInfo* alternate_protocol;
630 const net::SupportsQuic* supports_quic;
633 void HttpServerPropertiesManager::UpdatePrefsOnPrefThread(
634 base::ListValue* spdy_server_list,
635 net::SpdySettingsMap* spdy_settings_map,
636 net::AlternateProtocolMap* alternate_protocol_map,
637 net::SupportsQuicMap* supports_quic_map,
638 const base::Closure& completion) {
639 typedef std::map<net::HostPortPair, ServerPref> ServerPrefMap;
640 ServerPrefMap server_pref_map;
642 DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
644 // Add servers that support spdy to server_pref_map.
645 std::string s;
646 for (base::ListValue::const_iterator list_it = spdy_server_list->begin();
647 list_it != spdy_server_list->end();
648 ++list_it) {
649 if ((*list_it)->GetAsString(&s)) {
650 net::HostPortPair server = net::HostPortPair::FromString(s);
652 ServerPrefMap::iterator it = server_pref_map.find(server);
653 if (it == server_pref_map.end()) {
654 ServerPref server_pref(true, NULL, NULL, NULL);
655 server_pref_map[server] = server_pref;
656 } else {
657 it->second.supports_spdy = true;
662 // Add servers that have SpdySettings to server_pref_map.
663 for (net::SpdySettingsMap::iterator map_it = spdy_settings_map->begin();
664 map_it != spdy_settings_map->end();
665 ++map_it) {
666 const net::HostPortPair& server = map_it->first;
668 ServerPrefMap::iterator it = server_pref_map.find(server);
669 if (it == server_pref_map.end()) {
670 ServerPref server_pref(false, &map_it->second, NULL, NULL);
671 server_pref_map[server] = server_pref;
672 } else {
673 it->second.settings_map = &map_it->second;
677 // Add AlternateProtocol servers to server_pref_map.
678 for (net::AlternateProtocolMap::const_iterator map_it =
679 alternate_protocol_map->begin();
680 map_it != alternate_protocol_map->end();
681 ++map_it) {
682 const net::HostPortPair& server = map_it->first;
683 const net::AlternateProtocolInfo& port_alternate_protocol =
684 map_it->second;
685 if (!net::IsAlternateProtocolValid(port_alternate_protocol.protocol)) {
686 continue;
689 ServerPrefMap::iterator it = server_pref_map.find(server);
690 if (it == server_pref_map.end()) {
691 ServerPref server_pref(false, NULL, &map_it->second, NULL);
692 server_pref_map[server] = server_pref;
693 } else {
694 it->second.alternate_protocol = &map_it->second;
698 // Add SupportsQuic servers to server_pref_map.
699 for (net::SupportsQuicMap::const_iterator map_it = supports_quic_map->begin();
700 map_it != supports_quic_map->end(); ++map_it) {
701 const net::HostPortPair& server = map_it->first;
703 ServerPrefMap::iterator it = server_pref_map.find(server);
704 if (it == server_pref_map.end()) {
705 ServerPref server_pref(false, NULL, NULL, &map_it->second);
706 server_pref_map[server] = server_pref;
707 } else {
708 it->second.supports_quic = &map_it->second;
712 // Persist properties to the |path_|.
713 base::DictionaryValue http_server_properties_dict;
714 base::DictionaryValue* servers_dict = new base::DictionaryValue;
715 for (ServerPrefMap::const_iterator map_it = server_pref_map.begin();
716 map_it != server_pref_map.end();
717 ++map_it) {
718 const net::HostPortPair& server = map_it->first;
719 const ServerPref& server_pref = map_it->second;
721 base::DictionaryValue* server_pref_dict = new base::DictionaryValue;
723 // Save supports_spdy.
724 if (server_pref.supports_spdy)
725 server_pref_dict->SetBoolean("supports_spdy", server_pref.supports_spdy);
727 // Save SPDY settings.
728 if (server_pref.settings_map) {
729 base::DictionaryValue* spdy_settings_dict = new base::DictionaryValue;
730 for (net::SettingsMap::const_iterator it =
731 server_pref.settings_map->begin();
732 it != server_pref.settings_map->end();
733 ++it) {
734 net::SpdySettingsIds id = it->first;
735 uint32 value = it->second.second;
736 std::string key = base::StringPrintf("%u", id);
737 spdy_settings_dict->SetInteger(key, value);
739 server_pref_dict->SetWithoutPathExpansion("settings", spdy_settings_dict);
742 // Save alternate_protocol.
743 const net::AlternateProtocolInfo* port_alternate_protocol =
744 server_pref.alternate_protocol;
745 if (port_alternate_protocol && !port_alternate_protocol->is_broken) {
746 base::DictionaryValue* port_alternate_protocol_dict =
747 new base::DictionaryValue;
748 port_alternate_protocol_dict->SetInteger("port",
749 port_alternate_protocol->port);
750 const char* protocol_str =
751 net::AlternateProtocolToString(port_alternate_protocol->protocol);
752 port_alternate_protocol_dict->SetString("protocol_str", protocol_str);
753 port_alternate_protocol_dict->SetDouble(
754 "probability", port_alternate_protocol->probability);
755 server_pref_dict->SetWithoutPathExpansion(
756 "alternate_protocol", port_alternate_protocol_dict);
759 // Save supports_quic.
760 if (server_pref.supports_quic) {
761 base::DictionaryValue* supports_quic_dict = new base::DictionaryValue;
762 const net::SupportsQuic* supports_quic = server_pref.supports_quic;
763 supports_quic_dict->SetBoolean("used_quic", supports_quic->used_quic);
764 supports_quic_dict->SetString("address", supports_quic->address);
765 server_pref_dict->SetWithoutPathExpansion(
766 "supports_quic", supports_quic_dict);
769 servers_dict->SetWithoutPathExpansion(server.ToString(), server_pref_dict);
772 http_server_properties_dict.SetWithoutPathExpansion("servers", servers_dict);
773 SetVersion(&http_server_properties_dict, kVersionNumber);
774 setting_prefs_ = true;
775 pref_service_->Set(path_, http_server_properties_dict);
776 setting_prefs_ = false;
778 // Note that |completion| will be fired after we have written everything to
779 // the Preferences, but likely before these changes are serialized to disk.
780 // This is not a problem though, as JSONPrefStore guarantees that this will
781 // happen, pretty soon, and even in the case we shut down immediately.
782 if (!completion.is_null())
783 completion.Run();
786 void HttpServerPropertiesManager::OnHttpServerPropertiesChanged() {
787 DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
788 if (!setting_prefs_)
789 ScheduleUpdateCacheOnPrefThread();
792 } // namespace net