Index: chrome/browser/net/chrome_http_server_properties.cc |
diff --git a/chrome/browser/net/chrome_http_server_properties.cc b/chrome/browser/net/chrome_http_server_properties.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..6a94e948b13c95de5f8d1b07f9b6b5e7a44a2d5a |
--- /dev/null |
+++ b/chrome/browser/net/chrome_http_server_properties.cc |
@@ -0,0 +1,346 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome/browser/net/chrome_http_server_properties.h" |
+ |
+#include "base/bind.h" |
+#include "base/metrics/histogram.h" |
+#include "base/rand_util.h" |
+#include "base/stl_util.h" |
+#include "base/strings/string_number_conversions.h" |
+#include "base/strings/stringprintf.h" |
+#include "base/values.h" |
+#include "chrome/browser/chrome_notification_types.h" |
+#include "chrome/common/pref_names.h" |
+#include "components/pref_registry/pref_registry_syncable.h" |
+#include "content/public/browser/browser_thread.h" |
+#include "content/public/browser/notification_details.h" |
+#include "content/public/browser/notification_source.h" |
+ |
+using content::BrowserThread; |
+ |
+namespace chrome_browser_net { |
+ |
+namespace { |
+ |
+// Time to wait before starting an update the preferences from the |
+// http_server_properties_impl_ cache. Scheduling another update during this |
+// period will reset the timer. |
+const int64 kUpdatePrefsDelayMs = 5000; |
+ |
+// The version number of persisted http_server_properties. |
+const int kVersionNumber = 3; |
+ |
+typedef std::vector<std::string> StringVector; |
+ |
+// Persist 1000 MRU AlternateProtocolHostPortPairs. |
+const int kMaxAlternateProtocolHostsToPersist = 1000; |
+ |
+// Persist 200 MRU SpdySettingsHostPortPairs. |
+const int kMaxSpdySettingsHostsToPersist = 200; |
+ |
+// Persist 300 MRU SupportsSpdyServerHostPortPairs. |
+const int kMaxSupportsSpdyServerHostsToPersist = 300; |
+ |
+} // namespace |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// ChromeHttpServerProperties |
+ |
+ChromeHttpServerProperties::ChromeHttpServerProperties( |
+ UpdateCallback update_callback) |
+ : http_server_properties_impl_(new net::HttpServerPropertiesImpl()), |
+ update_callback_(update_callback), |
+ prefs_update_timer_(new base::OneShotTimer<ChromeHttpServerProperties>), |
+ weak_ptr_factory_( |
+ new base::WeakPtrFactory<ChromeHttpServerProperties>(this)) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+} |
+ |
+ChromeHttpServerProperties::~ChromeHttpServerProperties() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ weak_ptr_factory_.reset(); |
+} |
+ |
+// static |
+void ChromeHttpServerProperties::SetVersion( |
+ base::DictionaryValue* http_server_properties_dict, |
+ int version_number) { |
+ if (version_number < 0) |
+ version_number = kVersionNumber; |
+ DCHECK_LE(version_number, kVersionNumber); |
+ if (version_number <= kVersionNumber) |
+ http_server_properties_dict->SetInteger("version", version_number); |
+} |
+ |
+// This is required for conformance with the HttpServerProperties interface. |
+base::WeakPtr<net::HttpServerProperties> |
+ChromeHttpServerProperties::GetWeakPtr() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ return weak_ptr_factory_->GetWeakPtr(); |
+} |
+ |
+void ChromeHttpServerProperties::Clear() { |
+ Clear(base::Closure()); |
+} |
+ |
+void ChromeHttpServerProperties::Clear(const base::Closure& completion) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ |
+ http_server_properties_impl_->Clear(); |
+ UpdatePrefsFromCacheOnIO(completion); |
+} |
+ |
+bool ChromeHttpServerProperties::SupportsSpdy( |
+ const net::HostPortPair& server) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ return http_server_properties_impl_->SupportsSpdy(server); |
+} |
+ |
+void ChromeHttpServerProperties::SetSupportsSpdy( |
+ const net::HostPortPair& server, |
+ bool support_spdy) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ |
+ http_server_properties_impl_->SetSupportsSpdy(server, support_spdy); |
+ ScheduleUpdatePrefsOnIO(); |
+} |
+ |
+bool ChromeHttpServerProperties::HasAlternateProtocol( |
+ const net::HostPortPair& server) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ return http_server_properties_impl_->HasAlternateProtocol(server); |
+} |
+ |
+net::PortAlternateProtocolPair |
+ChromeHttpServerProperties::GetAlternateProtocol( |
+ const net::HostPortPair& server) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ return http_server_properties_impl_->GetAlternateProtocol(server); |
+} |
+ |
+void ChromeHttpServerProperties::SetAlternateProtocol( |
+ const net::HostPortPair& server, |
+ uint16 alternate_port, |
+ net::AlternateProtocol alternate_protocol) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ http_server_properties_impl_->SetAlternateProtocol( |
+ server, alternate_port, alternate_protocol); |
+ ScheduleUpdatePrefsOnIO(); |
+} |
+ |
+void ChromeHttpServerProperties::SetBrokenAlternateProtocol( |
+ const net::HostPortPair& server) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ http_server_properties_impl_->SetBrokenAlternateProtocol(server); |
+ ScheduleUpdatePrefsOnIO(); |
+} |
+ |
+bool ChromeHttpServerProperties::WasAlternateProtocolRecentlyBroken( |
+ const net::HostPortPair& server) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ return http_server_properties_impl_->WasAlternateProtocolRecentlyBroken( |
+ server); |
+} |
+ |
+void ChromeHttpServerProperties::ConfirmAlternateProtocol( |
+ const net::HostPortPair& server) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ http_server_properties_impl_->ConfirmAlternateProtocol(server); |
+ ScheduleUpdatePrefsOnIO(); |
+} |
+ |
+void ChromeHttpServerProperties::ClearAlternateProtocol( |
+ const net::HostPortPair& server) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ http_server_properties_impl_->ClearAlternateProtocol(server); |
+ ScheduleUpdatePrefsOnIO(); |
+} |
+ |
+const net::AlternateProtocolMap& |
+ChromeHttpServerProperties::alternate_protocol_map() const { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ return http_server_properties_impl_->alternate_protocol_map(); |
+} |
+ |
+void ChromeHttpServerProperties::SetAlternateProtocolExperiment( |
+ net::AlternateProtocolExperiment experiment) { |
+ http_server_properties_impl_->SetAlternateProtocolExperiment(experiment); |
+} |
+ |
+net::AlternateProtocolExperiment |
+ChromeHttpServerProperties::GetAlternateProtocolExperiment() const { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ return http_server_properties_impl_->GetAlternateProtocolExperiment(); |
+} |
+ |
+const net::SettingsMap& |
+ChromeHttpServerProperties::GetSpdySettings( |
+ const net::HostPortPair& host_port_pair) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ return http_server_properties_impl_->GetSpdySettings(host_port_pair); |
+} |
+ |
+bool ChromeHttpServerProperties::SetSpdySetting( |
+ const net::HostPortPair& host_port_pair, |
+ net::SpdySettingsIds id, |
+ net::SpdySettingsFlags flags, |
+ uint32 value) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ bool persist = http_server_properties_impl_->SetSpdySetting( |
+ host_port_pair, id, flags, value); |
+ if (persist) |
+ ScheduleUpdatePrefsOnIO(); |
+ return persist; |
+} |
+ |
+void ChromeHttpServerProperties::ClearSpdySettings( |
+ const net::HostPortPair& host_port_pair) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ http_server_properties_impl_->ClearSpdySettings(host_port_pair); |
+ ScheduleUpdatePrefsOnIO(); |
+} |
+ |
+void ChromeHttpServerProperties::ClearAllSpdySettings() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ http_server_properties_impl_->ClearAllSpdySettings(); |
+ ScheduleUpdatePrefsOnIO(); |
+} |
+ |
+const net::SpdySettingsMap& |
+ChromeHttpServerProperties::spdy_settings_map() const { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ return http_server_properties_impl_->spdy_settings_map(); |
+} |
+ |
+void ChromeHttpServerProperties::SetServerNetworkStats( |
+ const net::HostPortPair& host_port_pair, |
+ NetworkStats stats) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ http_server_properties_impl_->SetServerNetworkStats(host_port_pair, stats); |
+} |
+ |
+const ChromeHttpServerProperties::NetworkStats* |
+ChromeHttpServerProperties::GetServerNetworkStats( |
+ const net::HostPortPair& host_port_pair) const { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ return http_server_properties_impl_->GetServerNetworkStats(host_port_pair); |
+} |
+ |
+void ChromeHttpServerProperties::UpdateCacheFromPrefsOnIO( |
+ StringVector* spdy_servers, |
+ net::SpdySettingsMap* spdy_settings_map, |
+ net::AlternateProtocolMap* alternate_protocol_map, |
+ net::AlternateProtocolExperiment alternate_protocol_experiment, |
+ bool detected_corrupted_prefs) { |
+ // Preferences have the master data because admins might have pushed new |
+ // preferences. Update the cached data with new data from preferences. |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ |
+ UMA_HISTOGRAM_COUNTS("Net.CountOfSpdyServers", spdy_servers->size()); |
+ http_server_properties_impl_->InitializeSpdyServers(spdy_servers, true); |
+ |
+ // Update the cached data and use the new spdy_settings from preferences. |
+ UMA_HISTOGRAM_COUNTS("Net.CountOfSpdySettings", spdy_settings_map->size()); |
+ http_server_properties_impl_->InitializeSpdySettingsServers( |
+ spdy_settings_map); |
+ |
+ // Update the cached data and use the new Alternate-Protocol server list from |
+ // preferences. |
+ UMA_HISTOGRAM_COUNTS("Net.CountOfAlternateProtocolServers", |
+ alternate_protocol_map->size()); |
+ http_server_properties_impl_->InitializeAlternateProtocolServers( |
+ alternate_protocol_map); |
+ http_server_properties_impl_->SetAlternateProtocolExperiment( |
+ alternate_protocol_experiment); |
+ |
+ // Update the prefs with what we have read (delete all corrupted prefs). |
+ if (detected_corrupted_prefs) |
+ ScheduleUpdatePrefsOnIO(); |
+} |
+ |
+ |
+// |
+// Update Preferences with data from the cached data. |
+// |
+void ChromeHttpServerProperties::ScheduleUpdatePrefsOnIO() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ // Cancel pending updates, if any. |
+ prefs_update_timer_->Stop(); |
+ StartPrefsUpdateTimerOnIO( |
+ base::TimeDelta::FromMilliseconds(kUpdatePrefsDelayMs)); |
+} |
+ |
+void ChromeHttpServerProperties::StartPrefsUpdateTimerOnIO( |
+ base::TimeDelta delay) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ // This is overridden in tests to post the task without the delay. |
+ prefs_update_timer_->Start( |
+ FROM_HERE, delay, this, |
+ &ChromeHttpServerProperties::UpdatePrefsFromCacheOnIO); |
+} |
+ |
+// This is required so we can set this as the callback for a timer. |
+void ChromeHttpServerProperties::UpdatePrefsFromCacheOnIO() { |
+ UpdatePrefsFromCacheOnIO(base::Closure()); |
+} |
+ |
+void ChromeHttpServerProperties::UpdatePrefsFromCacheOnIO( |
+ const base::Closure& completion) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ |
+ base::ListValue* spdy_server_list = new base::ListValue; |
+ http_server_properties_impl_->GetSpdyServerList( |
+ spdy_server_list, kMaxSupportsSpdyServerHostsToPersist); |
+ |
+ net::SpdySettingsMap* spdy_settings_map = |
+ new net::SpdySettingsMap(kMaxSpdySettingsHostsToPersist); |
+ const net::SpdySettingsMap& main_map = |
+ http_server_properties_impl_->spdy_settings_map(); |
+ int count = 0; |
+ for (net::SpdySettingsMap::const_iterator it = main_map.begin(); |
+ it != main_map.end() && count < kMaxSpdySettingsHostsToPersist; |
+ ++it, ++count) { |
+ spdy_settings_map->Put(it->first, it->second); |
+ } |
+ |
+ net::AlternateProtocolMap* alternate_protocol_map = |
+ new net::AlternateProtocolMap(kMaxAlternateProtocolHostsToPersist); |
+ const net::AlternateProtocolMap& map = |
+ http_server_properties_impl_->alternate_protocol_map(); |
+ count = 0; |
+ typedef std::map<std::string, bool> CanonicalHostPersistedMap; |
+ CanonicalHostPersistedMap persisted_map; |
+ for (net::AlternateProtocolMap::const_iterator it = map.begin(); |
+ it != map.end() && count < kMaxAlternateProtocolHostsToPersist; |
+ ++it) { |
+ const net::HostPortPair& server = it->first; |
+ std::string canonical_suffix = |
+ http_server_properties_impl_->GetCanonicalSuffix(server); |
+ if (!canonical_suffix.empty()) { |
+ if (persisted_map.find(canonical_suffix) != persisted_map.end()) |
+ continue; |
+ persisted_map[canonical_suffix] = true; |
+ } |
+ alternate_protocol_map->Put(server, it->second); |
+ ++count; |
+ } |
+ |
+ /* |
+ // Update the preferences on the UI thread. |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, |
+ FROM_HERE, |
+ base::Bind(&ChromeHttpServerProperties::UpdatePrefsOnUI, |
+ manager_, |
+ base::Owned(spdy_server_list), |
+ base::Owned(spdy_settings_map), |
+ base::Owned(alternate_protocol_map), |
+ completion)); |
+ */ |
+ update_callback_.Run(spdy_server_list, spdy_settings_map, |
+ alternate_protocol_map, completion); |
+} |
+ |
+} // namespace chrome_browser_net |