Chromecast Android buildfix: rework CommandLine initialization logic.
[chromium-blink-merge.git] / net / http / http_server_properties_manager.cc
blob55aa0194c6ffff99fa1e789102e90a81f4f26a2f
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/rand_util.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/stl_util.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/stringprintf.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "base/values.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 // Load either 200 or 1000 servers based on a coin flip.
42 const int k200AlternateProtocolHostsToLoad = 200;
43 const int k1000AlternateProtocolHostsToLoad = 1000;
44 // Persist 1000 MRU AlternateProtocolHostPortPairs.
45 const int kMaxAlternateProtocolHostsToPersist = 1000;
47 // Persist 200 MRU SpdySettingsHostPortPairs.
48 const int kMaxSpdySettingsHostsToPersist = 200;
50 // Persist 300 MRU SupportsSpdyServerHostPortPairs.
51 const int kMaxSupportsSpdyServerHostsToPersist = 300;
53 } // namespace
55 ////////////////////////////////////////////////////////////////////////////////
56 // HttpServerPropertiesManager
58 HttpServerPropertiesManager::HttpServerPropertiesManager(
59 PrefService* pref_service,
60 const char* pref_path,
61 scoped_refptr<base::SequencedTaskRunner> network_task_runner)
62 : pref_task_runner_(base::ThreadTaskRunnerHandle::Get()),
63 pref_service_(pref_service),
64 setting_prefs_(false),
65 path_(pref_path),
66 network_task_runner_(network_task_runner) {
67 DCHECK(pref_service);
68 pref_weak_ptr_factory_.reset(
69 new base::WeakPtrFactory<HttpServerPropertiesManager>(this));
70 pref_weak_ptr_ = pref_weak_ptr_factory_->GetWeakPtr();
71 pref_cache_update_timer_.reset(
72 new base::OneShotTimer<HttpServerPropertiesManager>);
73 pref_change_registrar_.Init(pref_service_);
74 pref_change_registrar_.Add(
75 path_,
76 base::Bind(&HttpServerPropertiesManager::OnHttpServerPropertiesChanged,
77 base::Unretained(this)));
80 HttpServerPropertiesManager::~HttpServerPropertiesManager() {
81 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
82 network_weak_ptr_factory_.reset();
85 void HttpServerPropertiesManager::InitializeOnNetworkThread() {
86 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
87 network_weak_ptr_factory_.reset(
88 new base::WeakPtrFactory<HttpServerPropertiesManager>(this));
89 http_server_properties_impl_.reset(new net::HttpServerPropertiesImpl());
91 network_prefs_update_timer_.reset(
92 new base::OneShotTimer<HttpServerPropertiesManager>);
94 pref_task_runner_->PostTask(
95 FROM_HERE,
96 base::Bind(&HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread,
97 pref_weak_ptr_));
100 void HttpServerPropertiesManager::ShutdownOnPrefThread() {
101 DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
102 // Cancel any pending updates, and stop listening for pref change updates.
103 pref_cache_update_timer_->Stop();
104 pref_weak_ptr_factory_.reset();
105 pref_change_registrar_.RemoveAll();
108 // static
109 void HttpServerPropertiesManager::SetVersion(
110 base::DictionaryValue* http_server_properties_dict,
111 int version_number) {
112 if (version_number < 0)
113 version_number = kVersionNumber;
114 DCHECK_LE(version_number, kVersionNumber);
115 if (version_number <= kVersionNumber)
116 http_server_properties_dict->SetInteger("version", version_number);
119 // This is required for conformance with the HttpServerProperties interface.
120 base::WeakPtr<net::HttpServerProperties>
121 HttpServerPropertiesManager::GetWeakPtr() {
122 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
123 return network_weak_ptr_factory_->GetWeakPtr();
126 void HttpServerPropertiesManager::Clear() {
127 Clear(base::Closure());
130 void HttpServerPropertiesManager::Clear(const base::Closure& completion) {
131 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
133 http_server_properties_impl_->Clear();
134 UpdatePrefsFromCacheOnNetworkThread(completion);
137 bool HttpServerPropertiesManager::SupportsSpdy(
138 const net::HostPortPair& server) {
139 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
140 return http_server_properties_impl_->SupportsSpdy(server);
143 void HttpServerPropertiesManager::SetSupportsSpdy(
144 const net::HostPortPair& server,
145 bool support_spdy) {
146 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
148 http_server_properties_impl_->SetSupportsSpdy(server, support_spdy);
149 ScheduleUpdatePrefsOnNetworkThread();
152 bool HttpServerPropertiesManager::HasAlternateProtocol(
153 const net::HostPortPair& server) {
154 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
155 return http_server_properties_impl_->HasAlternateProtocol(server);
158 net::AlternateProtocolInfo
159 HttpServerPropertiesManager::GetAlternateProtocol(
160 const net::HostPortPair& server) {
161 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
162 return http_server_properties_impl_->GetAlternateProtocol(server);
165 void HttpServerPropertiesManager::SetAlternateProtocol(
166 const net::HostPortPair& server,
167 uint16 alternate_port,
168 AlternateProtocol alternate_protocol,
169 double alternate_probability) {
170 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
171 http_server_properties_impl_->SetAlternateProtocol(
172 server, alternate_port, alternate_protocol, alternate_probability);
173 ScheduleUpdatePrefsOnNetworkThread();
176 void HttpServerPropertiesManager::SetBrokenAlternateProtocol(
177 const net::HostPortPair& server) {
178 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
179 http_server_properties_impl_->SetBrokenAlternateProtocol(server);
180 ScheduleUpdatePrefsOnNetworkThread();
183 bool HttpServerPropertiesManager::WasAlternateProtocolRecentlyBroken(
184 const net::HostPortPair& server) {
185 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
186 return http_server_properties_impl_->WasAlternateProtocolRecentlyBroken(
187 server);
190 void HttpServerPropertiesManager::ConfirmAlternateProtocol(
191 const net::HostPortPair& server) {
192 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
193 http_server_properties_impl_->ConfirmAlternateProtocol(server);
194 ScheduleUpdatePrefsOnNetworkThread();
197 void HttpServerPropertiesManager::ClearAlternateProtocol(
198 const net::HostPortPair& server) {
199 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
200 http_server_properties_impl_->ClearAlternateProtocol(server);
201 ScheduleUpdatePrefsOnNetworkThread();
204 const net::AlternateProtocolMap&
205 HttpServerPropertiesManager::alternate_protocol_map() const {
206 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
207 return http_server_properties_impl_->alternate_protocol_map();
210 void HttpServerPropertiesManager::SetAlternateProtocolExperiment(
211 AlternateProtocolExperiment experiment) {
212 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
213 http_server_properties_impl_->SetAlternateProtocolExperiment(experiment);
216 void HttpServerPropertiesManager::SetAlternateProtocolProbabilityThreshold(
217 double threshold) {
218 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
219 http_server_properties_impl_->SetAlternateProtocolProbabilityThreshold(
220 threshold);
223 AlternateProtocolExperiment
224 HttpServerPropertiesManager::GetAlternateProtocolExperiment() const {
225 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
226 return http_server_properties_impl_->GetAlternateProtocolExperiment();
229 const SettingsMap& HttpServerPropertiesManager::GetSpdySettings(
230 const HostPortPair& host_port_pair) {
231 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
232 return http_server_properties_impl_->GetSpdySettings(host_port_pair);
235 bool HttpServerPropertiesManager::SetSpdySetting(
236 const HostPortPair& host_port_pair,
237 SpdySettingsIds id,
238 SpdySettingsFlags flags,
239 uint32 value) {
240 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
241 bool persist = http_server_properties_impl_->SetSpdySetting(
242 host_port_pair, id, flags, value);
243 if (persist)
244 ScheduleUpdatePrefsOnNetworkThread();
245 return persist;
248 void HttpServerPropertiesManager::ClearSpdySettings(
249 const HostPortPair& host_port_pair) {
250 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
251 http_server_properties_impl_->ClearSpdySettings(host_port_pair);
252 ScheduleUpdatePrefsOnNetworkThread();
255 void HttpServerPropertiesManager::ClearAllSpdySettings() {
256 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
257 http_server_properties_impl_->ClearAllSpdySettings();
258 ScheduleUpdatePrefsOnNetworkThread();
261 const SpdySettingsMap& HttpServerPropertiesManager::spdy_settings_map()
262 const {
263 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
264 return http_server_properties_impl_->spdy_settings_map();
267 net::SupportsQuic
268 HttpServerPropertiesManager::GetSupportsQuic(
269 const net::HostPortPair& host_port_pair) const {
270 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
271 return http_server_properties_impl_->GetSupportsQuic(host_port_pair);
274 void HttpServerPropertiesManager::SetSupportsQuic(
275 const net::HostPortPair& host_port_pair,
276 bool used_quic,
277 const std::string& address) {
278 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
279 http_server_properties_impl_->SetSupportsQuic(
280 host_port_pair, used_quic, address);
281 ScheduleUpdatePrefsOnNetworkThread();
284 const SupportsQuicMap& HttpServerPropertiesManager::supports_quic_map()
285 const {
286 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
287 return http_server_properties_impl_->supports_quic_map();
290 void HttpServerPropertiesManager::SetServerNetworkStats(
291 const net::HostPortPair& host_port_pair,
292 NetworkStats stats) {
293 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
294 http_server_properties_impl_->SetServerNetworkStats(host_port_pair, stats);
297 const HttpServerPropertiesManager::NetworkStats*
298 HttpServerPropertiesManager::GetServerNetworkStats(
299 const net::HostPortPair& host_port_pair) const {
300 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
301 return http_server_properties_impl_->GetServerNetworkStats(host_port_pair);
305 // Update the HttpServerPropertiesImpl's cache with data from preferences.
307 void HttpServerPropertiesManager::ScheduleUpdateCacheOnPrefThread() {
308 DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
309 // Cancel pending updates, if any.
310 pref_cache_update_timer_->Stop();
311 StartCacheUpdateTimerOnPrefThread(
312 base::TimeDelta::FromMilliseconds(kUpdateCacheDelayMs));
315 void HttpServerPropertiesManager::StartCacheUpdateTimerOnPrefThread(
316 base::TimeDelta delay) {
317 DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
318 pref_cache_update_timer_->Start(
319 FROM_HERE,
320 delay,
321 this,
322 &HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread);
325 void HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread() {
326 // The preferences can only be read on the pref thread.
327 DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
329 if (!pref_service_->HasPrefPath(path_))
330 return;
332 bool detected_corrupted_prefs = false;
333 const base::DictionaryValue& http_server_properties_dict =
334 *pref_service_->GetDictionary(path_);
336 int version = kMissingVersion;
337 if (!http_server_properties_dict.GetIntegerWithoutPathExpansion("version",
338 &version)) {
339 DVLOG(1) << "Missing version. Clearing all properties.";
340 return;
343 // The properties for a given server is in
344 // http_server_properties_dict["servers"][server].
345 const base::DictionaryValue* servers_dict = NULL;
346 if (!http_server_properties_dict.GetDictionaryWithoutPathExpansion(
347 "servers", &servers_dict)) {
348 DVLOG(1) << "Malformed http_server_properties for servers.";
349 return;
352 // String is host/port pair of spdy server.
353 scoped_ptr<StringVector> spdy_servers(new StringVector);
354 scoped_ptr<net::SpdySettingsMap> spdy_settings_map(
355 new net::SpdySettingsMap(kMaxSpdySettingsHostsToPersist));
356 scoped_ptr<net::AlternateProtocolMap> alternate_protocol_map(
357 new net::AlternateProtocolMap(kMaxAlternateProtocolHostsToPersist));
358 scoped_ptr<net::SupportsQuicMap> supports_quic_map(
359 new net::SupportsQuicMap());
360 // TODO(rtenneti): Delete the following code after the experiment.
361 int alternate_protocols_to_load = k200AlternateProtocolHostsToLoad;
362 net::AlternateProtocolExperiment alternate_protocol_experiment =
363 net::ALTERNATE_PROTOCOL_NOT_PART_OF_EXPERIMENT;
364 if (version == kVersionNumber) {
365 if (base::RandInt(0, 99) == 0) {
366 alternate_protocol_experiment =
367 net::ALTERNATE_PROTOCOL_TRUNCATED_200_SERVERS;
368 } else {
369 alternate_protocols_to_load = k1000AlternateProtocolHostsToLoad;
370 alternate_protocol_experiment =
371 net::ALTERNATE_PROTOCOL_TRUNCATED_1000_SERVERS;
373 DVLOG(1) << "# of servers that support alternate_protocol: "
374 << alternate_protocols_to_load;
377 int count = 0;
378 for (base::DictionaryValue::Iterator it(*servers_dict); !it.IsAtEnd();
379 it.Advance()) {
380 // Get server's host/pair.
381 const std::string& server_str = it.key();
382 net::HostPortPair server = net::HostPortPair::FromString(server_str);
383 if (server.host().empty()) {
384 DVLOG(1) << "Malformed http_server_properties for server: " << server_str;
385 detected_corrupted_prefs = true;
386 continue;
389 const base::DictionaryValue* server_pref_dict = NULL;
390 if (!it.value().GetAsDictionary(&server_pref_dict)) {
391 DVLOG(1) << "Malformed http_server_properties server: " << server_str;
392 detected_corrupted_prefs = true;
393 continue;
396 // Get if server supports Spdy.
397 bool supports_spdy = false;
398 if ((server_pref_dict->GetBoolean("supports_spdy", &supports_spdy)) &&
399 supports_spdy) {
400 spdy_servers->push_back(server_str);
403 // Get SpdySettings.
404 DCHECK(spdy_settings_map->Peek(server) == spdy_settings_map->end());
405 const base::DictionaryValue* spdy_settings_dict = NULL;
406 if (server_pref_dict->GetDictionaryWithoutPathExpansion(
407 "settings", &spdy_settings_dict)) {
408 net::SettingsMap settings_map;
409 for (base::DictionaryValue::Iterator dict_it(*spdy_settings_dict);
410 !dict_it.IsAtEnd();
411 dict_it.Advance()) {
412 const std::string& id_str = dict_it.key();
413 int id = 0;
414 if (!base::StringToInt(id_str, &id)) {
415 DVLOG(1) << "Malformed id in SpdySettings for server: " << server_str;
416 NOTREACHED();
417 continue;
419 int value = 0;
420 if (!dict_it.value().GetAsInteger(&value)) {
421 DVLOG(1) << "Malformed value in SpdySettings for server: "
422 << server_str;
423 NOTREACHED();
424 continue;
426 net::SettingsFlagsAndValue flags_and_value(net::SETTINGS_FLAG_PERSISTED,
427 value);
428 settings_map[static_cast<net::SpdySettingsIds>(id)] = flags_and_value;
430 spdy_settings_map->Put(server, settings_map);
433 // Get alternate_protocol server.
434 DCHECK(alternate_protocol_map->Peek(server) ==
435 alternate_protocol_map->end());
436 const base::DictionaryValue* port_alternate_protocol_dict = NULL;
437 if (!server_pref_dict->GetDictionaryWithoutPathExpansion(
438 "alternate_protocol", &port_alternate_protocol_dict)) {
439 continue;
442 if (count >= alternate_protocols_to_load)
443 continue;
444 do {
445 int port = 0;
446 if (!port_alternate_protocol_dict->GetIntegerWithoutPathExpansion(
447 "port", &port) ||
448 (port > (1 << 16))) {
449 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str;
450 detected_corrupted_prefs = true;
451 continue;
453 std::string protocol_str;
454 if (!port_alternate_protocol_dict->GetStringWithoutPathExpansion(
455 "protocol_str", &protocol_str)) {
456 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str;
457 detected_corrupted_prefs = true;
458 continue;
460 net::AlternateProtocol protocol =
461 net::AlternateProtocolFromString(protocol_str);
462 if (!net::IsAlternateProtocolValid(protocol)) {
463 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str;
464 detected_corrupted_prefs = true;
465 continue;
468 double probability = 1;
469 if (port_alternate_protocol_dict->HasKey("probability") &&
470 !port_alternate_protocol_dict->GetDoubleWithoutPathExpansion(
471 "probability", &probability)) {
472 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str;
473 detected_corrupted_prefs = true;
474 continue;
477 net::AlternateProtocolInfo port_alternate_protocol(port,
478 protocol,
479 probability);
480 alternate_protocol_map->Put(server, port_alternate_protocol);
481 ++count;
482 } while (false);
484 // Get SupportsQuic.
485 DCHECK(supports_quic_map->find(server) == supports_quic_map->end());
486 const base::DictionaryValue* supports_quic_dict = NULL;
487 if (!server_pref_dict->GetDictionaryWithoutPathExpansion(
488 "supports_quic", &supports_quic_dict)) {
489 continue;
491 do {
492 bool used_quic = 0;
493 if (!supports_quic_dict->GetBooleanWithoutPathExpansion(
494 "used_quic", &used_quic)) {
495 DVLOG(1) << "Malformed SupportsQuic server: " << server_str;
496 detected_corrupted_prefs = true;
497 continue;
499 std::string address;
500 if (!supports_quic_dict->GetStringWithoutPathExpansion(
501 "address", &address)) {
502 DVLOG(1) << "Malformed SupportsQuic server: " << server_str;
503 detected_corrupted_prefs = true;
504 continue;
506 net::SupportsQuic supports_quic(used_quic, address);
507 supports_quic_map->insert(std::make_pair(server, supports_quic));
508 } while (false);
511 network_task_runner_->PostTask(
512 FROM_HERE,
513 base::Bind(
514 &HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread,
515 base::Unretained(this),
516 base::Owned(spdy_servers.release()),
517 base::Owned(spdy_settings_map.release()),
518 base::Owned(alternate_protocol_map.release()),
519 alternate_protocol_experiment,
520 base::Owned(supports_quic_map.release()),
521 detected_corrupted_prefs));
524 void HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread(
525 StringVector* spdy_servers,
526 net::SpdySettingsMap* spdy_settings_map,
527 net::AlternateProtocolMap* alternate_protocol_map,
528 net::AlternateProtocolExperiment alternate_protocol_experiment,
529 net::SupportsQuicMap* supports_quic_map,
530 bool detected_corrupted_prefs) {
531 // Preferences have the master data because admins might have pushed new
532 // preferences. Update the cached data with new data from preferences.
533 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
535 UMA_HISTOGRAM_COUNTS("Net.CountOfSpdyServers", spdy_servers->size());
536 http_server_properties_impl_->InitializeSpdyServers(spdy_servers, true);
538 // Update the cached data and use the new spdy_settings from preferences.
539 UMA_HISTOGRAM_COUNTS("Net.CountOfSpdySettings", spdy_settings_map->size());
540 http_server_properties_impl_->InitializeSpdySettingsServers(
541 spdy_settings_map);
543 // Update the cached data and use the new Alternate-Protocol server list from
544 // preferences.
545 UMA_HISTOGRAM_COUNTS("Net.CountOfAlternateProtocolServers",
546 alternate_protocol_map->size());
547 http_server_properties_impl_->InitializeAlternateProtocolServers(
548 alternate_protocol_map);
549 http_server_properties_impl_->SetAlternateProtocolExperiment(
550 alternate_protocol_experiment);
552 http_server_properties_impl_->InitializeSupportsQuic(supports_quic_map);
554 // Update the prefs with what we have read (delete all corrupted prefs).
555 if (detected_corrupted_prefs)
556 ScheduleUpdatePrefsOnNetworkThread();
560 // Update Preferences with data from the cached data.
562 void HttpServerPropertiesManager::ScheduleUpdatePrefsOnNetworkThread() {
563 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
564 // Cancel pending updates, if any.
565 network_prefs_update_timer_->Stop();
566 StartPrefsUpdateTimerOnNetworkThread(
567 base::TimeDelta::FromMilliseconds(kUpdatePrefsDelayMs));
570 void HttpServerPropertiesManager::StartPrefsUpdateTimerOnNetworkThread(
571 base::TimeDelta delay) {
572 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
573 // This is overridden in tests to post the task without the delay.
574 network_prefs_update_timer_->Start(
575 FROM_HERE,
576 delay,
577 this,
578 &HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread);
581 // This is required so we can set this as the callback for a timer.
582 void HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread() {
583 UpdatePrefsFromCacheOnNetworkThread(base::Closure());
586 void HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread(
587 const base::Closure& completion) {
588 DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
590 base::ListValue* spdy_server_list = new base::ListValue;
591 http_server_properties_impl_->GetSpdyServerList(
592 spdy_server_list, kMaxSupportsSpdyServerHostsToPersist);
594 net::SpdySettingsMap* spdy_settings_map =
595 new net::SpdySettingsMap(kMaxSpdySettingsHostsToPersist);
596 const net::SpdySettingsMap& main_map =
597 http_server_properties_impl_->spdy_settings_map();
598 int count = 0;
599 for (net::SpdySettingsMap::const_iterator it = main_map.begin();
600 it != main_map.end() && count < kMaxSpdySettingsHostsToPersist;
601 ++it, ++count) {
602 spdy_settings_map->Put(it->first, it->second);
605 net::AlternateProtocolMap* alternate_protocol_map =
606 new net::AlternateProtocolMap(kMaxAlternateProtocolHostsToPersist);
607 const net::AlternateProtocolMap& map =
608 http_server_properties_impl_->alternate_protocol_map();
609 count = 0;
610 typedef std::map<std::string, bool> CanonicalHostPersistedMap;
611 CanonicalHostPersistedMap persisted_map;
612 for (net::AlternateProtocolMap::const_iterator it = map.begin();
613 it != map.end() && count < kMaxAlternateProtocolHostsToPersist;
614 ++it) {
615 const net::HostPortPair& server = it->first;
616 std::string canonical_suffix =
617 http_server_properties_impl_->GetCanonicalSuffix(server);
618 if (!canonical_suffix.empty()) {
619 if (persisted_map.find(canonical_suffix) != persisted_map.end())
620 continue;
621 persisted_map[canonical_suffix] = true;
623 alternate_protocol_map->Put(server, it->second);
624 ++count;
627 net::SupportsQuicMap* supports_quic_map = new net::SupportsQuicMap();
628 const net::SupportsQuicMap& main_supports_quic_map =
629 http_server_properties_impl_->supports_quic_map();
630 for (net::SupportsQuicMap::const_iterator it = main_supports_quic_map.begin();
631 it != main_supports_quic_map.end(); ++it) {
632 supports_quic_map->insert(std::make_pair(it->first, it->second));
635 // Update the preferences on the pref thread.
636 pref_task_runner_->PostTask(
637 FROM_HERE,
638 base::Bind(&HttpServerPropertiesManager::UpdatePrefsOnPrefThread,
639 pref_weak_ptr_,
640 base::Owned(spdy_server_list),
641 base::Owned(spdy_settings_map),
642 base::Owned(alternate_protocol_map),
643 base::Owned(supports_quic_map),
644 completion));
647 // A local or temporary data structure to hold |supports_spdy|, SpdySettings,
648 // AlternateProtocolInfo and SupportsQuic preferences for a server. This is used
649 // only in UpdatePrefsOnPrefThread.
650 struct ServerPref {
651 ServerPref() : supports_spdy(false),
652 settings_map(NULL),
653 alternate_protocol(NULL),
654 supports_quic(NULL) {}
655 ServerPref(bool supports_spdy,
656 const net::SettingsMap* settings_map,
657 const net::AlternateProtocolInfo* alternate_protocol,
658 const net::SupportsQuic* supports_quic)
659 : supports_spdy(supports_spdy),
660 settings_map(settings_map),
661 alternate_protocol(alternate_protocol),
662 supports_quic(supports_quic) {}
663 bool supports_spdy;
664 const net::SettingsMap* settings_map;
665 const net::AlternateProtocolInfo* alternate_protocol;
666 const net::SupportsQuic* supports_quic;
669 void HttpServerPropertiesManager::UpdatePrefsOnPrefThread(
670 base::ListValue* spdy_server_list,
671 net::SpdySettingsMap* spdy_settings_map,
672 net::AlternateProtocolMap* alternate_protocol_map,
673 net::SupportsQuicMap* supports_quic_map,
674 const base::Closure& completion) {
675 typedef std::map<net::HostPortPair, ServerPref> ServerPrefMap;
676 ServerPrefMap server_pref_map;
678 DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
680 // Add servers that support spdy to server_pref_map.
681 std::string s;
682 for (base::ListValue::const_iterator list_it = spdy_server_list->begin();
683 list_it != spdy_server_list->end();
684 ++list_it) {
685 if ((*list_it)->GetAsString(&s)) {
686 net::HostPortPair server = net::HostPortPair::FromString(s);
688 ServerPrefMap::iterator it = server_pref_map.find(server);
689 if (it == server_pref_map.end()) {
690 ServerPref server_pref(true, NULL, NULL, NULL);
691 server_pref_map[server] = server_pref;
692 } else {
693 it->second.supports_spdy = true;
698 // Add servers that have SpdySettings to server_pref_map.
699 for (net::SpdySettingsMap::iterator map_it = spdy_settings_map->begin();
700 map_it != spdy_settings_map->end();
701 ++map_it) {
702 const net::HostPortPair& server = map_it->first;
704 ServerPrefMap::iterator it = server_pref_map.find(server);
705 if (it == server_pref_map.end()) {
706 ServerPref server_pref(false, &map_it->second, NULL, NULL);
707 server_pref_map[server] = server_pref;
708 } else {
709 it->second.settings_map = &map_it->second;
713 // Add AlternateProtocol servers to server_pref_map.
714 for (net::AlternateProtocolMap::const_iterator map_it =
715 alternate_protocol_map->begin();
716 map_it != alternate_protocol_map->end();
717 ++map_it) {
718 const net::HostPortPair& server = map_it->first;
719 const net::AlternateProtocolInfo& port_alternate_protocol =
720 map_it->second;
721 if (!net::IsAlternateProtocolValid(port_alternate_protocol.protocol)) {
722 continue;
725 ServerPrefMap::iterator it = server_pref_map.find(server);
726 if (it == server_pref_map.end()) {
727 ServerPref server_pref(false, NULL, &map_it->second, NULL);
728 server_pref_map[server] = server_pref;
729 } else {
730 it->second.alternate_protocol = &map_it->second;
734 // Add SupportsQuic servers to server_pref_map.
735 for (net::SupportsQuicMap::const_iterator map_it = supports_quic_map->begin();
736 map_it != supports_quic_map->end(); ++map_it) {
737 const net::HostPortPair& server = map_it->first;
739 ServerPrefMap::iterator it = server_pref_map.find(server);
740 if (it == server_pref_map.end()) {
741 ServerPref server_pref(false, NULL, NULL, &map_it->second);
742 server_pref_map[server] = server_pref;
743 } else {
744 it->second.supports_quic = &map_it->second;
748 // Persist properties to the |path_|.
749 base::DictionaryValue http_server_properties_dict;
750 base::DictionaryValue* servers_dict = new base::DictionaryValue;
751 for (ServerPrefMap::const_iterator map_it = server_pref_map.begin();
752 map_it != server_pref_map.end();
753 ++map_it) {
754 const net::HostPortPair& server = map_it->first;
755 const ServerPref& server_pref = map_it->second;
757 base::DictionaryValue* server_pref_dict = new base::DictionaryValue;
759 // Save supports_spdy.
760 if (server_pref.supports_spdy)
761 server_pref_dict->SetBoolean("supports_spdy", server_pref.supports_spdy);
763 // Save SPDY settings.
764 if (server_pref.settings_map) {
765 base::DictionaryValue* spdy_settings_dict = new base::DictionaryValue;
766 for (net::SettingsMap::const_iterator it =
767 server_pref.settings_map->begin();
768 it != server_pref.settings_map->end();
769 ++it) {
770 net::SpdySettingsIds id = it->first;
771 uint32 value = it->second.second;
772 std::string key = base::StringPrintf("%u", id);
773 spdy_settings_dict->SetInteger(key, value);
775 server_pref_dict->SetWithoutPathExpansion("settings", spdy_settings_dict);
778 // Save alternate_protocol.
779 if (server_pref.alternate_protocol) {
780 base::DictionaryValue* port_alternate_protocol_dict =
781 new base::DictionaryValue;
782 const net::AlternateProtocolInfo* port_alternate_protocol =
783 server_pref.alternate_protocol;
784 port_alternate_protocol_dict->SetInteger("port",
785 port_alternate_protocol->port);
786 const char* protocol_str =
787 net::AlternateProtocolToString(port_alternate_protocol->protocol);
788 port_alternate_protocol_dict->SetString("protocol_str", protocol_str);
789 port_alternate_protocol_dict->SetDouble(
790 "probability", port_alternate_protocol->probability);
791 server_pref_dict->SetWithoutPathExpansion(
792 "alternate_protocol", port_alternate_protocol_dict);
795 // Save supports_quic.
796 if (server_pref.supports_quic) {
797 base::DictionaryValue* supports_quic_dict = new base::DictionaryValue;
798 const net::SupportsQuic* supports_quic = server_pref.supports_quic;
799 supports_quic_dict->SetBoolean("used_quic", supports_quic->used_quic);
800 supports_quic_dict->SetString("address", supports_quic->address);
801 server_pref_dict->SetWithoutPathExpansion(
802 "supports_quic", supports_quic_dict);
805 servers_dict->SetWithoutPathExpansion(server.ToString(), server_pref_dict);
808 http_server_properties_dict.SetWithoutPathExpansion("servers", servers_dict);
809 SetVersion(&http_server_properties_dict, kVersionNumber);
810 setting_prefs_ = true;
811 pref_service_->Set(path_, http_server_properties_dict);
812 setting_prefs_ = false;
814 // Note that |completion| will be fired after we have written everything to
815 // the Preferences, but likely before these changes are serialized to disk.
816 // This is not a problem though, as JSONPrefStore guarantees that this will
817 // happen, pretty soon, and even in the case we shut down immediately.
818 if (!completion.is_null())
819 completion.Run();
822 void HttpServerPropertiesManager::OnHttpServerPropertiesChanged() {
823 DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
824 if (!setting_prefs_)
825 ScheduleUpdateCacheOnPrefThread();
828 } // namespace net