| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 #include "chrome/browser/net/http_server_properties_manager.h" | 4 #include "chrome/browser/net/http_server_properties_manager.h" |
| 5 | 5 |
| 6 #include "base/bind.h" | 6 #include "base/bind.h" |
| 7 #include "base/stl_util.h" | 7 #include "base/stl_util.h" |
| 8 #include "base/values.h" | 8 #include "base/values.h" |
| 9 #include "chrome/browser/prefs/pref_service.h" | 9 #include "chrome/browser/prefs/pref_service.h" |
| 10 #include "chrome/common/chrome_notification_types.h" | 10 #include "chrome/common/chrome_notification_types.h" |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 // timer. | 24 // timer. |
| 25 const int64 kUpdateCacheDelayMs = 1000; | 25 const int64 kUpdateCacheDelayMs = 1000; |
| 26 | 26 |
| 27 // Time to wait before starting an update the preferences from the | 27 // Time to wait before starting an update the preferences from the |
| 28 // spdy_servers cache. Scheduling another update during this period will | 28 // spdy_servers cache. Scheduling another update during this period will |
| 29 // reset the timer. | 29 // reset the timer. |
| 30 const int64 kUpdatePrefsDelayMs = 5000; | 30 const int64 kUpdatePrefsDelayMs = 5000; |
| 31 | 31 |
| 32 typedef std::vector<std::string> StringVector; | 32 typedef std::vector<std::string> StringVector; |
| 33 | 33 |
| 34 // String is host/port pair of spdy server. | |
| 35 StringVector* ListValueToStringVector(const base::ListValue* list) { | |
| 36 StringVector* vector = new StringVector; | |
| 37 | |
| 38 if (!list) | |
| 39 return vector; | |
| 40 | |
| 41 vector->reserve(list->GetSize()); | |
| 42 std::string s; | |
| 43 for (base::ListValue::const_iterator it = list->begin(); | |
| 44 it != list->end(); ++it) { | |
| 45 if ((*it)->GetAsString(&s)) | |
| 46 vector->push_back(s); | |
| 47 } | |
| 48 | |
| 49 return vector; | |
| 50 } | |
| 51 | |
| 52 } // namespace | 34 } // namespace |
| 53 | 35 |
| 54 //////////////////////////////////////////////////////////////////////////////// | 36 //////////////////////////////////////////////////////////////////////////////// |
| 55 // HttpServerPropertiesManager | 37 // HttpServerPropertiesManager |
| 56 | 38 |
| 57 HttpServerPropertiesManager::HttpServerPropertiesManager( | 39 HttpServerPropertiesManager::HttpServerPropertiesManager( |
| 58 PrefService* pref_service) | 40 PrefService* pref_service) |
| 59 : pref_service_(pref_service), | 41 : pref_service_(pref_service), |
| 60 setting_spdy_servers_(false), | 42 setting_prefs_(false) { |
| 61 setting_alternate_protocol_servers_(false) { | |
| 62 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 43 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 63 DCHECK(pref_service); | 44 DCHECK(pref_service); |
| 64 ui_weak_ptr_factory_.reset( | 45 ui_weak_ptr_factory_.reset( |
| 65 new base::WeakPtrFactory<HttpServerPropertiesManager>(this)); | 46 new base::WeakPtrFactory<HttpServerPropertiesManager>(this)); |
| 66 ui_weak_ptr_ = ui_weak_ptr_factory_->GetWeakPtr(); | 47 ui_weak_ptr_ = ui_weak_ptr_factory_->GetWeakPtr(); |
| 67 ui_spdy_cache_update_timer_.reset( | 48 ui_cache_update_timer_.reset( |
| 68 new base::OneShotTimer<HttpServerPropertiesManager>); | |
| 69 ui_alternate_protocol_cache_update_timer_.reset( | |
| 70 new base::OneShotTimer<HttpServerPropertiesManager>); | 49 new base::OneShotTimer<HttpServerPropertiesManager>); |
| 71 pref_change_registrar_.Init(pref_service_); | 50 pref_change_registrar_.Init(pref_service_); |
| 72 pref_change_registrar_.Add(prefs::kSpdyServers, this); | 51 pref_change_registrar_.Add(prefs::kHttpServerProperties, this); |
| 73 pref_change_registrar_.Add(prefs::kAlternateProtocolServers, this); | |
| 74 } | 52 } |
| 75 | 53 |
| 76 HttpServerPropertiesManager::~HttpServerPropertiesManager() { | 54 HttpServerPropertiesManager::~HttpServerPropertiesManager() { |
| 77 } | 55 } |
| 78 | 56 |
| 79 void HttpServerPropertiesManager::InitializeOnIOThread() { | 57 void HttpServerPropertiesManager::InitializeOnIOThread() { |
| 80 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 58 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 81 http_server_properties_impl_.reset(new net::HttpServerPropertiesImpl()); | 59 http_server_properties_impl_.reset(new net::HttpServerPropertiesImpl()); |
| 82 | 60 |
| 83 io_spdy_prefs_update_timer_.reset( | 61 io_spdy_prefs_update_timer_.reset( |
| 84 new base::OneShotTimer<HttpServerPropertiesManager>); | 62 new base::OneShotTimer<HttpServerPropertiesManager>); |
| 85 io_alternate_protocol_prefs_update_timer_.reset( | |
| 86 new base::OneShotTimer<HttpServerPropertiesManager>); | |
| 87 | 63 |
| 88 BrowserThread::PostTask( | 64 BrowserThread::PostTask( |
| 89 BrowserThread::UI, | 65 BrowserThread::UI, |
| 90 FROM_HERE, | 66 FROM_HERE, |
| 91 base::Bind(&HttpServerPropertiesManager::UpdateSpdyCacheFromPrefs, | 67 base::Bind(&HttpServerPropertiesManager::UpdateCacheFromPrefsOnUI, |
| 92 ui_weak_ptr_)); | 68 ui_weak_ptr_)); |
| 93 BrowserThread::PostTask( | |
| 94 BrowserThread::UI, | |
| 95 FROM_HERE, | |
| 96 base::Bind( | |
| 97 &HttpServerPropertiesManager::UpdateAlternateProtocolCacheFromPrefs, | |
| 98 ui_weak_ptr_)); | |
| 99 } | 69 } |
| 100 | 70 |
| 101 void HttpServerPropertiesManager::ShutdownOnUIThread() { | 71 void HttpServerPropertiesManager::ShutdownOnUIThread() { |
| 102 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 72 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 103 // Cancel any pending updates, and stop listening for pref change updates. | 73 // Cancel any pending updates, and stop listening for pref change updates. |
| 104 ui_spdy_cache_update_timer_->Stop(); | 74 ui_cache_update_timer_->Stop(); |
| 105 ui_alternate_protocol_cache_update_timer_->Stop(); | |
| 106 ui_weak_ptr_factory_.reset(); | 75 ui_weak_ptr_factory_.reset(); |
| 107 pref_change_registrar_.RemoveAll(); | 76 pref_change_registrar_.RemoveAll(); |
| 108 } | 77 } |
| 109 | 78 |
| 110 // static | 79 // static |
| 111 void HttpServerPropertiesManager::RegisterPrefs(PrefService* prefs) { | 80 void HttpServerPropertiesManager::RegisterPrefs(PrefService* prefs) { |
| 112 prefs->RegisterListPref(prefs::kSpdyServers, PrefService::UNSYNCABLE_PREF); | 81 prefs->RegisterDictionaryPref(prefs::kHttpServerProperties, |
| 113 prefs->RegisterDictionaryPref(prefs::kAlternateProtocolServers, | |
| 114 PrefService::UNSYNCABLE_PREF); | 82 PrefService::UNSYNCABLE_PREF); |
| 115 } | 83 } |
| 116 | 84 |
| 117 void HttpServerPropertiesManager::Clear() { | 85 void HttpServerPropertiesManager::Clear() { |
| 118 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 86 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 119 | 87 |
| 120 http_server_properties_impl_->Clear(); | 88 http_server_properties_impl_->Clear(); |
| 121 ScheduleUpdateSpdyPrefsOnIO(); | 89 ScheduleUpdatePrefsOnIO(); |
| 122 ScheduleUpdateAlternateProtocolPrefsOnIO(); | |
| 123 } | 90 } |
| 124 | 91 |
| 125 bool HttpServerPropertiesManager::SupportsSpdy( | 92 bool HttpServerPropertiesManager::SupportsSpdy( |
| 126 const net::HostPortPair& server) const { | 93 const net::HostPortPair& server) const { |
| 127 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 94 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 128 return http_server_properties_impl_->SupportsSpdy(server); | 95 return http_server_properties_impl_->SupportsSpdy(server); |
| 129 } | 96 } |
| 130 | 97 |
| 131 void HttpServerPropertiesManager::SetSupportsSpdy( | 98 void HttpServerPropertiesManager::SetSupportsSpdy( |
| 132 const net::HostPortPair& server, | 99 const net::HostPortPair& server, |
| 133 bool support_spdy) { | 100 bool support_spdy) { |
| 134 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 101 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 135 | 102 |
| 136 http_server_properties_impl_->SetSupportsSpdy(server, support_spdy); | 103 http_server_properties_impl_->SetSupportsSpdy(server, support_spdy); |
| 137 ScheduleUpdateSpdyPrefsOnIO(); | 104 ScheduleUpdatePrefsOnIO(); |
| 138 } | 105 } |
| 139 | 106 |
| 140 bool HttpServerPropertiesManager::HasAlternateProtocol( | 107 bool HttpServerPropertiesManager::HasAlternateProtocol( |
| 141 const net::HostPortPair& server) const { | 108 const net::HostPortPair& server) const { |
| 142 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 109 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 143 return http_server_properties_impl_->HasAlternateProtocol(server); | 110 return http_server_properties_impl_->HasAlternateProtocol(server); |
| 144 } | 111 } |
| 145 | 112 |
| 146 net::PortAlternateProtocolPair | 113 net::PortAlternateProtocolPair |
| 147 HttpServerPropertiesManager::GetAlternateProtocol( | 114 HttpServerPropertiesManager::GetAlternateProtocol( |
| 148 const net::HostPortPair& server) const { | 115 const net::HostPortPair& server) const { |
| 149 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 116 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 150 return http_server_properties_impl_->GetAlternateProtocol(server); | 117 return http_server_properties_impl_->GetAlternateProtocol(server); |
| 151 } | 118 } |
| 152 | 119 |
| 153 void HttpServerPropertiesManager::SetAlternateProtocol( | 120 void HttpServerPropertiesManager::SetAlternateProtocol( |
| 154 const net::HostPortPair& server, | 121 const net::HostPortPair& server, |
| 155 uint16 alternate_port, | 122 uint16 alternate_port, |
| 156 net::AlternateProtocol alternate_protocol) { | 123 net::AlternateProtocol alternate_protocol) { |
| 157 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 124 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 158 http_server_properties_impl_->SetAlternateProtocol( | 125 http_server_properties_impl_->SetAlternateProtocol( |
| 159 server, alternate_port, alternate_protocol); | 126 server, alternate_port, alternate_protocol); |
| 160 ScheduleUpdateAlternateProtocolPrefsOnIO(); | 127 ScheduleUpdatePrefsOnIO(); |
| 161 } | 128 } |
| 162 | 129 |
| 163 void HttpServerPropertiesManager::SetBrokenAlternateProtocol( | 130 void HttpServerPropertiesManager::SetBrokenAlternateProtocol( |
| 164 const net::HostPortPair& server) { | 131 const net::HostPortPair& server) { |
| 165 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 132 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 166 http_server_properties_impl_->SetBrokenAlternateProtocol(server); | 133 http_server_properties_impl_->SetBrokenAlternateProtocol(server); |
| 167 ScheduleUpdateAlternateProtocolPrefsOnIO(); | 134 ScheduleUpdatePrefsOnIO(); |
| 168 } | 135 } |
| 169 | 136 |
| 170 const net::AlternateProtocolMap& | 137 const net::AlternateProtocolMap& |
| 171 HttpServerPropertiesManager::alternate_protocol_map() const { | 138 HttpServerPropertiesManager::alternate_protocol_map() const { |
| 172 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 173 return http_server_properties_impl_->alternate_protocol_map(); | 140 return http_server_properties_impl_->alternate_protocol_map(); |
| 174 } | 141 } |
| 175 | 142 |
| 176 // | 143 const spdy::SpdySettings& |
| 177 // Update spdy_servers (the cached data) with data from preferences. | 144 HttpServerPropertiesManager::GetSpdySettings( |
| 178 // | 145 const net::HostPortPair& host_port_pair) const { |
| 179 void HttpServerPropertiesManager::ScheduleUpdateSpdyCacheOnUI() { | 146 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 147 return http_server_properties_impl_->GetSpdySettings(host_port_pair); |
| 148 } |
| 149 |
| 150 // Saves settings for a host. |
| 151 bool HttpServerPropertiesManager::SetSpdySettings( |
| 152 const net::HostPortPair& host_port_pair, |
| 153 const spdy::SpdySettings& settings) { |
| 154 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 155 bool persist = http_server_properties_impl_->SetSpdySettings( |
| 156 host_port_pair, settings); |
| 157 if (persist) |
| 158 ScheduleUpdatePrefsOnIO(); |
| 159 return persist; |
| 160 } |
| 161 |
| 162 void HttpServerPropertiesManager::ClearSpdySettings() { |
| 163 http_server_properties_impl_->ClearSpdySettings(); |
| 164 ScheduleUpdatePrefsOnIO(); |
| 165 } |
| 166 |
| 167 const net::SpdySettingsMap& |
| 168 HttpServerPropertiesManager::spdy_settings_map() const { |
| 169 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 170 return http_server_properties_impl_->spdy_settings_map(); |
| 171 } |
| 172 |
| 173 // |
| 174 // Update the HttpServerPropertiesImpl's cache with data from preferences. |
| 175 // |
| 176 void HttpServerPropertiesManager::ScheduleUpdateCacheOnUI() { |
| 180 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 177 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 181 // Cancel pending updates, if any. | 178 // Cancel pending updates, if any. |
| 182 ui_spdy_cache_update_timer_->Stop(); | 179 ui_cache_update_timer_->Stop(); |
| 183 StartSpdyCacheUpdateTimerOnUI( | 180 StartCacheUpdateTimerOnUI( |
| 184 base::TimeDelta::FromMilliseconds(kUpdateCacheDelayMs)); | 181 base::TimeDelta::FromMilliseconds(kUpdateCacheDelayMs)); |
| 185 } | 182 } |
| 186 | 183 |
| 187 void HttpServerPropertiesManager::UpdateSpdyCacheFromPrefs() { | 184 void HttpServerPropertiesManager::StartCacheUpdateTimerOnUI( |
| 185 base::TimeDelta delay) { |
| 188 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 186 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 189 | 187 ui_cache_update_timer_->Start( |
| 190 if (!pref_service_->HasPrefPath(prefs::kSpdyServers)) | 188 FROM_HERE, delay, this, |
| 189 &HttpServerPropertiesManager::UpdateCacheFromPrefsOnUI); |
| 190 } |
| 191 |
| 192 void HttpServerPropertiesManager::UpdateCacheFromPrefsOnUI() { |
| 193 // The preferences can only be read on the UI thread. |
| 194 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 195 |
| 196 if (!pref_service_->HasPrefPath(prefs::kHttpServerProperties)) |
| 191 return; | 197 return; |
| 192 | 198 |
| 193 // The preferences can only be read on the UI thread. | 199 // String is host/port pair of spdy server. |
| 194 StringVector* spdy_servers = | 200 StringVector* spdy_servers = new StringVector; |
| 195 ListValueToStringVector(pref_service_->GetList(prefs::kSpdyServers)); | 201 |
| 196 | 202 // Parse the preferences into a SpdySettingsMap. |
| 197 BrowserThread::PostTask( | 203 net::SpdySettingsMap spdy_settings_map; |
| 198 BrowserThread::IO, | |
| 199 FROM_HERE, | |
| 200 base::Bind(&HttpServerPropertiesManager::UpdateSpdyCacheFromPrefsOnIO, | |
| 201 base::Unretained(this), spdy_servers, true)); | |
| 202 } | |
| 203 | |
| 204 void HttpServerPropertiesManager::UpdateSpdyCacheFromPrefsOnIO( | |
| 205 StringVector* spdy_servers, | |
| 206 bool support_spdy) { | |
| 207 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 208 // Preferences have the master data because admins might have pushed new | |
| 209 // preferences. Clear the cached data and use the new spdy server list from | |
| 210 // preferences. | |
| 211 scoped_ptr<StringVector> scoped_spdy_servers(spdy_servers); | |
| 212 http_server_properties_impl_->InitializeSpdyServers(spdy_servers, | |
| 213 support_spdy); | |
| 214 } | |
| 215 | |
| 216 // | |
| 217 // Update Preferences with data from spdy_servers (the cached data). | |
| 218 // | |
| 219 void HttpServerPropertiesManager::ScheduleUpdateSpdyPrefsOnIO() { | |
| 220 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 221 // Cancel pending updates, if any. | |
| 222 io_spdy_prefs_update_timer_->Stop(); | |
| 223 StartSpdyPrefsUpdateTimerOnIO( | |
| 224 base::TimeDelta::FromMilliseconds(kUpdatePrefsDelayMs)); | |
| 225 } | |
| 226 | |
| 227 void HttpServerPropertiesManager::UpdateSpdyPrefsFromCache() { | |
| 228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 229 | |
| 230 scoped_refptr<RefCountedListValue> spdy_server_list = | |
| 231 new RefCountedListValue(); | |
| 232 http_server_properties_impl_->GetSpdyServerList(&spdy_server_list->data); | |
| 233 | |
| 234 // Update the preferences on the UI thread. | |
| 235 BrowserThread::PostTask( | |
| 236 BrowserThread::UI, | |
| 237 FROM_HERE, | |
| 238 base::Bind(&HttpServerPropertiesManager::SetSpdyServersInPrefsOnUI, | |
| 239 ui_weak_ptr_, spdy_server_list)); | |
| 240 } | |
| 241 | |
| 242 void HttpServerPropertiesManager::SetSpdyServersInPrefsOnUI( | |
| 243 scoped_refptr<RefCountedListValue> spdy_server_list) { | |
| 244 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 245 setting_spdy_servers_ = true; | |
| 246 pref_service_->Set(prefs::kSpdyServers, spdy_server_list->data); | |
| 247 setting_spdy_servers_ = false; | |
| 248 } | |
| 249 | |
| 250 void HttpServerPropertiesManager::ScheduleUpdateAlternateProtocolCacheOnUI() { | |
| 251 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 252 // Cancel pending updates, if any. | |
| 253 ui_alternate_protocol_cache_update_timer_->Stop(); | |
| 254 StartAlternateProtocolCacheUpdateTimerOnUI( | |
| 255 base::TimeDelta::FromMilliseconds(kUpdateCacheDelayMs)); | |
| 256 } | |
| 257 | |
| 258 void HttpServerPropertiesManager::UpdateAlternateProtocolCacheFromPrefs() { | |
| 259 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 260 | |
| 261 if (!pref_service_->HasPrefPath(prefs::kAlternateProtocolServers)) | |
| 262 return; | |
| 263 | 204 |
| 264 // Parse the preferences into a AlternateProtocolMap. | 205 // Parse the preferences into a AlternateProtocolMap. |
| 265 net::AlternateProtocolMap alternate_protocol_map; | 206 net::AlternateProtocolMap alternate_protocol_map; |
| 266 const base::DictionaryValue& alternate_protocol_servers = | 207 |
| 267 *pref_service_->GetDictionary(prefs::kAlternateProtocolServers); | 208 const base::DictionaryValue& http_server_properties_dict = |
| 209 *pref_service_->GetDictionary(prefs::kHttpServerProperties); |
| 268 for (base::DictionaryValue::key_iterator it = | 210 for (base::DictionaryValue::key_iterator it = |
| 269 alternate_protocol_servers.begin_keys(); | 211 http_server_properties_dict.begin_keys(); |
| 270 it != alternate_protocol_servers.end_keys(); ++it) { | 212 it != http_server_properties_dict.end_keys(); ++it) { |
| 213 // Get server's host/pair. |
| 271 const std::string& server_str = *it; | 214 const std::string& server_str = *it; |
| 272 net::HostPortPair server = net::HostPortPair::FromString(server_str); | 215 net::HostPortPair server = net::HostPortPair::FromString(server_str); |
| 273 if (server.host().empty()) { | 216 if (server.host().empty()) { |
| 274 VLOG(1) << "Malformed Alternate-Protocol server: " << server_str; | 217 VLOG(1) << "Malformed http_server_properties for server: " << server_str; |
| 275 NOTREACHED(); | 218 NOTREACHED(); |
| 276 continue; | 219 continue; |
| 277 } | 220 } |
| 278 DCHECK(!ContainsKey(alternate_protocol_map, server)); | 221 |
| 279 | 222 base::DictionaryValue* server_pref_dict = NULL; |
| 280 base::DictionaryValue* port_alternate_protocol_dict = NULL; | 223 if (!http_server_properties_dict.GetDictionaryWithoutPathExpansion( |
| 281 if (!alternate_protocol_servers.GetDictionaryWithoutPathExpansion( | 224 server_str, &server_pref_dict)) { |
| 282 server_str, &port_alternate_protocol_dict)) { | 225 VLOG(1) << "Malformed http_server_properties server: " << server_str; |
| 283 VLOG(1) << "Malformed Alternate-Protocol server: " << server_str; | |
| 284 NOTREACHED(); | 226 NOTREACHED(); |
| 285 continue; | 227 continue; |
| 286 } | 228 } |
| 287 | 229 |
| 288 int port = 0; | 230 // Get if server supports Spdy. |
| 289 if (!port_alternate_protocol_dict->GetIntegerWithoutPathExpansion( | 231 bool supports_spdy = false; |
| 290 "port", &port) || (port > (1 << 16))) { | 232 if ((server_pref_dict->GetBoolean( |
| 291 VLOG(1) << "Malformed Alternate-Protocol server: " << server_str; | 233 "supports_spdy", &supports_spdy)) && supports_spdy) { |
| 292 NOTREACHED(); | 234 spdy_servers->push_back(server_str); |
| 235 } |
| 236 |
| 237 // Get SpdySettings. |
| 238 DCHECK(!ContainsKey(spdy_settings_map, server)); |
| 239 base::ListValue* spdy_settings_list = NULL; |
| 240 if (server_pref_dict->GetListWithoutPathExpansion( |
| 241 "settings", &spdy_settings_list)) { |
| 242 spdy::SpdySettings spdy_settings; |
| 243 |
| 244 for (base::ListValue::const_iterator list_it = |
| 245 spdy_settings_list->begin(); |
| 246 list_it != spdy_settings_list->end(); ++list_it) { |
| 247 if ((*list_it)->GetType() != Value::TYPE_DICTIONARY) { |
| 248 VLOG(1) << "Malformed SpdySettingsList for server: " << server_str; |
| 249 NOTREACHED(); |
| 250 continue; |
| 251 } |
| 252 |
| 253 const base::DictionaryValue* spdy_setting_dict = |
| 254 static_cast<const base::DictionaryValue*>(*list_it); |
| 255 |
| 256 int id = 0; |
| 257 if (!spdy_setting_dict->GetIntegerWithoutPathExpansion("id", &id)) { |
| 258 VLOG(1) << "Malformed id in SpdySettings for server: " << server_str; |
| 259 NOTREACHED(); |
| 260 continue; |
| 261 } |
| 262 |
| 263 int value = 0; |
| 264 if (!spdy_setting_dict->GetIntegerWithoutPathExpansion("value", |
| 265 &value)) { |
| 266 VLOG(1) << "Malformed value in SpdySettings for server: " << |
| 267 server_str; |
| 268 NOTREACHED(); |
| 269 continue; |
| 270 } |
| 271 |
| 272 spdy::SettingsFlagsAndId flags_and_id(0); |
| 273 flags_and_id.set_id(id); |
| 274 flags_and_id.set_flags(spdy::SETTINGS_FLAG_PERSISTED); |
| 275 |
| 276 spdy_settings.push_back(spdy::SpdySetting(flags_and_id, value)); |
| 277 } |
| 278 |
| 279 spdy_settings_map[server] = spdy_settings; |
| 280 } |
| 281 |
| 282 // Get alternate_protocol server. |
| 283 DCHECK(!ContainsKey(alternate_protocol_map, server)); |
| 284 base::DictionaryValue* port_alternate_protocol_dict = NULL; |
| 285 if (!server_pref_dict->GetDictionaryWithoutPathExpansion( |
| 286 "alternate_protocol", &port_alternate_protocol_dict)) { |
| 293 continue; | 287 continue; |
| 294 } | 288 } |
| 295 int protocol = 0; | 289 |
| 296 if (!port_alternate_protocol_dict->GetIntegerWithoutPathExpansion( | 290 do { |
| 297 "protocol", &protocol) || (protocol < 0) || | 291 int port = 0; |
| 298 (protocol > net::NUM_ALTERNATE_PROTOCOLS)) { | 292 if (!port_alternate_protocol_dict->GetIntegerWithoutPathExpansion( |
| 299 VLOG(1) << "Malformed Alternate-Protocol server: " << server_str; | 293 "port", &port) || (port > (1 << 16))) { |
| 300 NOTREACHED(); | 294 VLOG(1) << "Malformed Alternate-Protocol server: " << server_str; |
| 301 continue; | 295 NOTREACHED(); |
| 302 } | 296 continue; |
| 303 | 297 } |
| 304 net::PortAlternateProtocolPair port_alternate_protocol; | 298 int protocol = 0; |
| 305 port_alternate_protocol.port = port; | 299 if (!port_alternate_protocol_dict->GetIntegerWithoutPathExpansion( |
| 306 port_alternate_protocol.protocol = static_cast<net::AlternateProtocol>( | 300 "protocol", &protocol) || (protocol < 0) || |
| 307 protocol); | 301 (protocol > net::NUM_ALTERNATE_PROTOCOLS)) { |
| 308 | 302 VLOG(1) << "Malformed Alternate-Protocol server: " << server_str; |
| 309 alternate_protocol_map[server] = port_alternate_protocol; | 303 NOTREACHED(); |
| 304 continue; |
| 305 } |
| 306 |
| 307 net::PortAlternateProtocolPair port_alternate_protocol; |
| 308 port_alternate_protocol.port = port; |
| 309 port_alternate_protocol.protocol = static_cast<net::AlternateProtocol>( |
| 310 protocol); |
| 311 |
| 312 alternate_protocol_map[server] = port_alternate_protocol; |
| 313 } while (false); |
| 310 } | 314 } |
| 311 | 315 |
| 312 scoped_refptr<RefCountedAlternateProtocolMap> alternate_protocol_map_arg = | 316 scoped_refptr<RefCountedAlternateProtocolMap> alternate_protocol_map_arg = |
| 313 new RefCountedAlternateProtocolMap; | 317 new RefCountedAlternateProtocolMap; |
| 314 alternate_protocol_map_arg->data.swap(alternate_protocol_map); | 318 alternate_protocol_map_arg->data.swap(alternate_protocol_map); |
| 315 | 319 |
| 320 scoped_refptr<RefCountedSpdySettingsMap> spdy_settings_map_arg = |
| 321 new RefCountedSpdySettingsMap; |
| 322 spdy_settings_map_arg->data.swap(spdy_settings_map); |
| 323 |
| 316 BrowserThread::PostTask( | 324 BrowserThread::PostTask( |
| 317 BrowserThread::IO, | 325 BrowserThread::IO, |
| 318 FROM_HERE, | 326 FROM_HERE, |
| 319 base::Bind(&HttpServerPropertiesManager:: | 327 base::Bind(&HttpServerPropertiesManager:: |
| 320 UpdateAlternateProtocolCacheFromPrefsOnIO, | 328 UpdateCacheFromPrefsOnIO, |
| 321 base::Unretained(this), alternate_protocol_map_arg)); | 329 base::Unretained(this), |
| 322 } | 330 spdy_servers, |
| 323 | 331 spdy_settings_map_arg, |
| 324 void HttpServerPropertiesManager::UpdateAlternateProtocolCacheFromPrefsOnIO( | 332 alternate_protocol_map_arg)); |
| 325 RefCountedAlternateProtocolMap* alternate_protocol_map) { | 333 } |
| 326 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 334 |
| 335 void HttpServerPropertiesManager::UpdateCacheFromPrefsOnIO( |
| 336 StringVector* spdy_servers, |
| 337 RefCountedSpdySettingsMap* spdy_settings_map, |
| 338 RefCountedAlternateProtocolMap* alternate_protocol_map) { |
| 327 // Preferences have the master data because admins might have pushed new | 339 // Preferences have the master data because admins might have pushed new |
| 328 // preferences. Clear the cached data and use the new spdy server list from | 340 // preferences. Update the cached data with new data from preferences. |
| 341 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 342 |
| 343 // Clear the cached data and use the new spdy_servers list from preferences. |
| 344 scoped_ptr<StringVector> scoped_spdy_servers(spdy_servers); |
| 345 http_server_properties_impl_->InitializeSpdyServers(spdy_servers, true); |
| 346 |
| 347 // Clear the cached data and use the new spdy_settings from preferences. |
| 348 http_server_properties_impl_->InitializeSpdySettingsServers( |
| 349 &spdy_settings_map->data); |
| 350 |
| 351 // Clear the cached data and use the new Alternate-Protocol server list from |
| 329 // preferences. | 352 // preferences. |
| 330 http_server_properties_impl_->InitializeAlternateProtocolServers( | 353 http_server_properties_impl_->InitializeAlternateProtocolServers( |
| 331 &alternate_protocol_map->data); | 354 &alternate_protocol_map->data); |
| 332 } | 355 } |
| 333 | 356 |
| 334 // | 357 |
| 335 // Update Preferences with data from alternate_protocol_servers (the cached | 358 // |
| 336 // data). | 359 // Update Preferences with data from the cached data. |
| 337 // | 360 // |
| 338 void HttpServerPropertiesManager::ScheduleUpdateAlternateProtocolPrefsOnIO() { | 361 void HttpServerPropertiesManager::ScheduleUpdatePrefsOnIO() { |
| 339 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 362 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 340 // Cancel pending updates, if any. | 363 // Cancel pending updates, if any. |
| 341 io_alternate_protocol_prefs_update_timer_->Stop(); | 364 io_spdy_prefs_update_timer_->Stop(); |
| 342 StartAlternateProtocolPrefsUpdateTimerOnIO( | 365 StartPrefsUpdateTimerOnIO( |
| 343 base::TimeDelta::FromMilliseconds(kUpdatePrefsDelayMs)); | 366 base::TimeDelta::FromMilliseconds(kUpdatePrefsDelayMs)); |
| 344 } | 367 } |
| 345 | 368 |
| 346 void HttpServerPropertiesManager::UpdateAlternateProtocolPrefsFromCache() { | 369 void HttpServerPropertiesManager::StartPrefsUpdateTimerOnIO( |
| 347 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 370 base::TimeDelta delay) { |
| 371 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 372 // This is overridden in tests to post the task without the delay. |
| 373 io_spdy_prefs_update_timer_->Start( |
| 374 FROM_HERE, delay, this, |
| 375 &HttpServerPropertiesManager::UpdatePrefsFromCacheOnIO); |
| 376 } |
| 377 |
| 378 void HttpServerPropertiesManager::UpdatePrefsFromCacheOnIO() { |
| 379 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 380 |
| 381 scoped_refptr<RefCountedListValue> spdy_server_list = |
| 382 new RefCountedListValue(); |
| 383 http_server_properties_impl_->GetSpdyServerList(&spdy_server_list->data); |
| 384 |
| 385 scoped_refptr<RefCountedSpdySettingsMap> spdy_settings_map = |
| 386 new RefCountedSpdySettingsMap; |
| 387 spdy_settings_map->data = |
| 388 http_server_properties_impl_->spdy_settings_map(); |
| 348 | 389 |
| 349 scoped_refptr<RefCountedAlternateProtocolMap> alternate_protocol_map = | 390 scoped_refptr<RefCountedAlternateProtocolMap> alternate_protocol_map = |
| 350 new RefCountedAlternateProtocolMap; | 391 new RefCountedAlternateProtocolMap; |
| 351 alternate_protocol_map->data = | 392 alternate_protocol_map->data = |
| 352 http_server_properties_impl_->alternate_protocol_map(); | 393 http_server_properties_impl_->alternate_protocol_map(); |
| 353 | 394 |
| 354 // Update the preferences on the UI thread. | 395 // Update the preferences on the UI thread. |
| 355 BrowserThread::PostTask( | 396 BrowserThread::PostTask( |
| 356 BrowserThread::UI, | 397 BrowserThread::UI, |
| 357 FROM_HERE, | 398 FROM_HERE, |
| 358 base::Bind(&HttpServerPropertiesManager:: | 399 base::Bind(&HttpServerPropertiesManager::UpdatePrefsOnUI, |
| 359 SetAlternateProtocolServersInPrefsOnUI, | 400 ui_weak_ptr_, spdy_server_list, spdy_settings_map, |
| 360 ui_weak_ptr_, alternate_protocol_map)); | 401 alternate_protocol_map)); |
| 361 } | 402 } |
| 362 | 403 |
| 363 void HttpServerPropertiesManager::SetAlternateProtocolServersInPrefsOnUI( | 404 // A local or temporary data structure to hold supports_spdy, SpdySettings and |
| 405 // PortAlternateProtocolPair preferences for a server. This is used only in |
| 406 // UpdatePrefsOnUI. |
| 407 struct ServerPref { |
| 408 ServerPref() |
| 409 : supports_spdy(false), |
| 410 settings(NULL), |
| 411 alternate_protocol(NULL) { |
| 412 } |
| 413 ServerPref(bool supports_spdy, |
| 414 const spdy::SpdySettings* settings, |
| 415 const net::PortAlternateProtocolPair* alternate_protocol) |
| 416 : supports_spdy(supports_spdy), |
| 417 settings(settings), |
| 418 alternate_protocol(alternate_protocol) { |
| 419 } |
| 420 bool supports_spdy; |
| 421 const spdy::SpdySettings* settings; |
| 422 const net::PortAlternateProtocolPair* alternate_protocol; |
| 423 }; |
| 424 |
| 425 void HttpServerPropertiesManager::UpdatePrefsOnUI( |
| 426 scoped_refptr<RefCountedListValue> spdy_server_list, |
| 427 RefCountedSpdySettingsMap* spdy_settings_map, |
| 364 RefCountedAlternateProtocolMap* alternate_protocol_map) { | 428 RefCountedAlternateProtocolMap* alternate_protocol_map) { |
| 429 |
| 430 typedef std::map<net::HostPortPair, ServerPref> ServerPrefMap; |
| 431 ServerPrefMap server_pref_map; |
| 432 |
| 365 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 433 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 366 base::DictionaryValue alternate_protocol_dict; | 434 |
| 367 for (net::AlternateProtocolMap::const_iterator it = | 435 // Add servers that support spdy to server_pref_map. |
| 436 std::string s; |
| 437 for (base::ListValue::const_iterator list_it = spdy_server_list->data.begin(); |
| 438 list_it != spdy_server_list->data.end(); ++list_it) { |
| 439 if ((*list_it)->GetAsString(&s)) { |
| 440 net::HostPortPair server = net::HostPortPair::FromString(s); |
| 441 |
| 442 ServerPrefMap::iterator it = server_pref_map.find(server); |
| 443 if (it == server_pref_map.end()) { |
| 444 ServerPref server_pref(true, NULL, NULL); |
| 445 server_pref_map[server] = server_pref; |
| 446 } else { |
| 447 it->second.supports_spdy = true; |
| 448 } |
| 449 } |
| 450 } |
| 451 |
| 452 // Add servers that have SpdySettings to server_pref_map. |
| 453 for (net::SpdySettingsMap::iterator map_it = |
| 454 spdy_settings_map->data.begin(); |
| 455 map_it != spdy_settings_map->data.end(); ++map_it) { |
| 456 const net::HostPortPair& server = map_it->first; |
| 457 |
| 458 ServerPrefMap::iterator it = server_pref_map.find(server); |
| 459 if (it == server_pref_map.end()) { |
| 460 ServerPref server_pref(false, &map_it->second, NULL); |
| 461 server_pref_map[server] = server_pref; |
| 462 } else { |
| 463 it->second.settings = &map_it->second; |
| 464 } |
| 465 } |
| 466 |
| 467 // Add AlternateProtocol servers to server_pref_map. |
| 468 for (net::AlternateProtocolMap::const_iterator map_it = |
| 368 alternate_protocol_map->data.begin(); | 469 alternate_protocol_map->data.begin(); |
| 369 it != alternate_protocol_map->data.end(); ++it) { | 470 map_it != alternate_protocol_map->data.end(); ++map_it) { |
| 370 const net::HostPortPair& server = it->first; | 471 const net::HostPortPair& server = map_it->first; |
| 371 const net::PortAlternateProtocolPair& port_alternate_protocol = | 472 const net::PortAlternateProtocolPair& port_alternate_protocol = |
| 372 it->second; | 473 map_it->second; |
| 373 if (port_alternate_protocol.protocol < 0 || | 474 if (port_alternate_protocol.protocol < 0 || |
| 374 port_alternate_protocol.protocol >= net::NUM_ALTERNATE_PROTOCOLS) { | 475 port_alternate_protocol.protocol >= net::NUM_ALTERNATE_PROTOCOLS) { |
| 375 continue; | 476 continue; |
| 376 } | 477 } |
| 377 base::DictionaryValue* port_alternate_protocol_dict = | 478 |
| 378 new base::DictionaryValue; | 479 ServerPrefMap::iterator it = server_pref_map.find(server); |
| 379 port_alternate_protocol_dict->SetInteger( | 480 if (it == server_pref_map.end()) { |
| 380 "port", port_alternate_protocol.port); | 481 ServerPref server_pref(false, NULL, &map_it->second); |
| 381 port_alternate_protocol_dict->SetInteger( | 482 server_pref_map[server] = server_pref; |
| 382 "protocol", port_alternate_protocol.protocol); | 483 } else { |
| 383 alternate_protocol_dict.SetWithoutPathExpansion( | 484 it->second.alternate_protocol = &map_it->second; |
| 384 server.ToString(), port_alternate_protocol_dict); | 485 } |
| 385 } | 486 } |
| 386 setting_alternate_protocol_servers_ = true; | |
| 387 pref_service_->Set(prefs::kAlternateProtocolServers, | |
| 388 alternate_protocol_dict); | |
| 389 setting_alternate_protocol_servers_ = false; | |
| 390 } | |
| 391 | 487 |
| 392 void HttpServerPropertiesManager::StartSpdyCacheUpdateTimerOnUI( | 488 // Persist the prefs::kHttpServerProperties. |
| 393 base::TimeDelta delay) { | 489 base::DictionaryValue http_server_properties_dict; |
| 394 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 490 for (ServerPrefMap::const_iterator map_it = |
| 395 ui_spdy_cache_update_timer_->Start( | 491 server_pref_map.begin(); |
| 396 FROM_HERE, delay, this, | 492 map_it != server_pref_map.end(); ++map_it) { |
| 397 &HttpServerPropertiesManager::UpdateSpdyCacheFromPrefs); | 493 const net::HostPortPair& server = map_it->first; |
| 398 } | 494 const ServerPref& server_pref = map_it->second; |
| 399 | 495 |
| 400 void HttpServerPropertiesManager::StartSpdyPrefsUpdateTimerOnIO( | 496 base::DictionaryValue* server_pref_dict = new base::DictionaryValue; |
| 401 base::TimeDelta delay) { | |
| 402 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
| 403 // This is overridden in tests to post the task without the delay. | |
| 404 io_spdy_prefs_update_timer_->Start( | |
| 405 FROM_HERE, delay, this, | |
| 406 &HttpServerPropertiesManager::UpdateSpdyPrefsFromCache); | |
| 407 } | |
| 408 | 497 |
| 409 void HttpServerPropertiesManager::StartAlternateProtocolCacheUpdateTimerOnUI( | 498 // Save supports_spdy. |
| 410 base::TimeDelta delay) { | 499 server_pref_dict->SetBoolean("supports_spdy", server_pref.supports_spdy); |
| 411 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 412 ui_alternate_protocol_cache_update_timer_->Start( | |
| 413 FROM_HERE, delay, this, | |
| 414 &HttpServerPropertiesManager::UpdateAlternateProtocolCacheFromPrefs); | |
| 415 } | |
| 416 | 500 |
| 417 void HttpServerPropertiesManager::StartAlternateProtocolPrefsUpdateTimerOnIO( | 501 // Save SpdySettings. |
| 418 base::TimeDelta delay) { | 502 if (server_pref.settings) { |
| 419 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 503 base::ListValue* spdy_settings_list = new ListValue(); |
| 420 // This is overridden in tests to post the task without the delay. | 504 for (spdy::SpdySettings::const_iterator it = |
| 421 io_alternate_protocol_prefs_update_timer_->Start( | 505 server_pref.settings->begin(); |
| 422 FROM_HERE, delay, this, | 506 it != server_pref.settings->end(); ++it) { |
| 423 &HttpServerPropertiesManager::UpdateAlternateProtocolPrefsFromCache); | 507 uint32 id = it->first.id(); |
| 508 uint32 value = it->second; |
| 509 base::DictionaryValue* spdy_setting_dict = new base::DictionaryValue; |
| 510 spdy_setting_dict->SetInteger("id", id); |
| 511 spdy_setting_dict->SetInteger("value", value); |
| 512 spdy_settings_list->Append(spdy_setting_dict); |
| 513 } |
| 514 server_pref_dict->Set("settings", spdy_settings_list); |
| 515 } |
| 516 |
| 517 // Save alternate_protocol. |
| 518 if (server_pref.alternate_protocol) { |
| 519 base::DictionaryValue* port_alternate_protocol_dict = |
| 520 new base::DictionaryValue; |
| 521 const net::PortAlternateProtocolPair* port_alternate_protocol = |
| 522 server_pref.alternate_protocol; |
| 523 port_alternate_protocol_dict->SetInteger( |
| 524 "port", port_alternate_protocol->port); |
| 525 port_alternate_protocol_dict->SetInteger( |
| 526 "protocol", port_alternate_protocol->protocol); |
| 527 server_pref_dict->SetWithoutPathExpansion( |
| 528 "alternate_protocol", port_alternate_protocol_dict); |
| 529 } |
| 530 http_server_properties_dict.SetWithoutPathExpansion( |
| 531 server.ToString(), server_pref_dict); |
| 532 } |
| 533 |
| 534 setting_prefs_ = true; |
| 535 pref_service_->Set(prefs::kHttpServerProperties, |
| 536 http_server_properties_dict); |
| 537 setting_prefs_ = false; |
| 424 } | 538 } |
| 425 | 539 |
| 426 void HttpServerPropertiesManager::Observe( | 540 void HttpServerPropertiesManager::Observe( |
| 427 int type, | 541 int type, |
| 428 const content::NotificationSource& source, | 542 const content::NotificationSource& source, |
| 429 const content::NotificationDetails& details) { | 543 const content::NotificationDetails& details) { |
| 430 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 544 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 431 DCHECK(type == chrome::NOTIFICATION_PREF_CHANGED); | 545 DCHECK(type == chrome::NOTIFICATION_PREF_CHANGED); |
| 432 PrefService* prefs = content::Source<PrefService>(source).ptr(); | 546 PrefService* prefs = content::Source<PrefService>(source).ptr(); |
| 433 DCHECK(prefs == pref_service_); | 547 DCHECK(prefs == pref_service_); |
| 434 std::string* pref_name = content::Details<std::string>(details).ptr(); | 548 std::string* pref_name = content::Details<std::string>(details).ptr(); |
| 435 if (*pref_name == prefs::kSpdyServers) { | 549 if (*pref_name == prefs::kHttpServerProperties) { |
| 436 if (!setting_spdy_servers_) | 550 if (!setting_prefs_) |
| 437 ScheduleUpdateSpdyCacheOnUI(); | 551 ScheduleUpdateCacheOnUI(); |
| 438 } else if (*pref_name == prefs::kAlternateProtocolServers) { | |
| 439 if (!setting_alternate_protocol_servers_) | |
| 440 ScheduleUpdateAlternateProtocolCacheOnUI(); | |
| 441 } else { | 552 } else { |
| 442 NOTREACHED(); | 553 NOTREACHED(); |
| 443 } | 554 } |
| 444 } | 555 } |
| 445 | 556 |
| 446 } // namespace chrome_browser_net | 557 } // namespace chrome_browser_net |
| OLD | NEW |