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" |
11 #include "chrome/common/pref_names.h" | 11 #include "chrome/common/pref_names.h" |
12 #include "content/public/browser/browser_thread.h" | 12 #include "content/public/browser/browser_thread.h" |
13 #include "content/public/browser/notification_details.h" | 13 #include "content/public/browser/notification_details.h" |
14 #include "content/public/browser/notification_source.h" | 14 #include "content/public/browser/notification_source.h" |
15 | 15 |
16 using content::BrowserThread; | 16 using content::BrowserThread; |
17 | 17 |
18 namespace chrome_browser_net { | 18 namespace chrome_browser_net { |
19 | 19 |
20 namespace { | 20 namespace { |
21 | 21 |
22 // Time to wait before starting an update the spdy_servers_table_ cache from | 22 // Time to wait before starting an update the http_server_properties_impl_ cache |
23 // preferences. Scheduling another update during this period will reset the | 23 // from preferences. Scheduling another update during this period will reset the |
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 // http_server_properties_impl_ cache. Scheduling another update during this |
29 // reset the timer. | 29 // period will 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_prefs_update_timer_.reset( |
84 new base::OneShotTimer<HttpServerPropertiesManager>); | |
85 io_alternate_protocol_prefs_update_timer_.reset( | |
86 new base::OneShotTimer<HttpServerPropertiesManager>); | 62 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 |
| 143 const spdy::SpdySettings& |
| 144 HttpServerPropertiesManager::GetSpdySettings( |
| 145 const net::HostPortPair& host_port_pair) const { |
| 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 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 164 http_server_properties_impl_->ClearSpdySettings(); |
| 165 ScheduleUpdatePrefsOnIO(); |
| 166 } |
| 167 |
| 168 const net::SpdySettingsMap& |
| 169 HttpServerPropertiesManager::spdy_settings_map() const { |
| 170 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 171 return http_server_properties_impl_->spdy_settings_map(); |
| 172 } |
| 173 |
176 // | 174 // |
177 // Update spdy_servers (the cached data) with data from preferences. | 175 // Update the HttpServerPropertiesImpl's cache with data from preferences. |
178 // | 176 // |
179 void HttpServerPropertiesManager::ScheduleUpdateSpdyCacheOnUI() { | 177 void HttpServerPropertiesManager::ScheduleUpdateCacheOnUI() { |
180 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 178 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
181 // Cancel pending updates, if any. | 179 // Cancel pending updates, if any. |
182 ui_spdy_cache_update_timer_->Stop(); | 180 ui_cache_update_timer_->Stop(); |
183 StartSpdyCacheUpdateTimerOnUI( | 181 StartCacheUpdateTimerOnUI( |
184 base::TimeDelta::FromMilliseconds(kUpdateCacheDelayMs)); | 182 base::TimeDelta::FromMilliseconds(kUpdateCacheDelayMs)); |
185 } | 183 } |
186 | 184 |
187 void HttpServerPropertiesManager::UpdateSpdyCacheFromPrefs() { | 185 void HttpServerPropertiesManager::StartCacheUpdateTimerOnUI( |
| 186 base::TimeDelta delay) { |
188 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 187 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
189 | 188 ui_cache_update_timer_->Start( |
190 if (!pref_service_->HasPrefPath(prefs::kSpdyServers)) | 189 FROM_HERE, delay, this, |
| 190 &HttpServerPropertiesManager::UpdateCacheFromPrefsOnUI); |
| 191 } |
| 192 |
| 193 void HttpServerPropertiesManager::UpdateCacheFromPrefsOnUI() { |
| 194 // The preferences can only be read on the UI thread. |
| 195 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 196 |
| 197 if (!pref_service_->HasPrefPath(prefs::kHttpServerProperties)) |
191 return; | 198 return; |
192 | 199 |
193 // The preferences can only be read on the UI thread. | 200 // String is host/port pair of spdy server. |
194 StringVector* spdy_servers = | 201 StringVector* spdy_servers = new StringVector; |
195 ListValueToStringVector(pref_service_->GetList(prefs::kSpdyServers)); | 202 |
| 203 // Parse the preferences into a SpdySettingsMap. |
| 204 net::SpdySettingsMap* spdy_settings_map = new net::SpdySettingsMap; |
| 205 |
| 206 // Parse the preferences into a AlternateProtocolMap. |
| 207 net::AlternateProtocolMap* alternate_protocol_map = |
| 208 new net::AlternateProtocolMap; |
| 209 |
| 210 const base::DictionaryValue& http_server_properties_dict = |
| 211 *pref_service_->GetDictionary(prefs::kHttpServerProperties); |
| 212 for (base::DictionaryValue::key_iterator it = |
| 213 http_server_properties_dict.begin_keys(); |
| 214 it != http_server_properties_dict.end_keys(); ++it) { |
| 215 // Get server's host/pair. |
| 216 const std::string& server_str = *it; |
| 217 net::HostPortPair server = net::HostPortPair::FromString(server_str); |
| 218 if (server.host().empty()) { |
| 219 DVLOG(1) << "Malformed http_server_properties for server: " << server_str; |
| 220 NOTREACHED(); |
| 221 continue; |
| 222 } |
| 223 |
| 224 base::DictionaryValue* server_pref_dict = NULL; |
| 225 if (!http_server_properties_dict.GetDictionaryWithoutPathExpansion( |
| 226 server_str, &server_pref_dict)) { |
| 227 DVLOG(1) << "Malformed http_server_properties server: " << server_str; |
| 228 NOTREACHED(); |
| 229 continue; |
| 230 } |
| 231 |
| 232 // Get if server supports Spdy. |
| 233 bool supports_spdy = false; |
| 234 if ((server_pref_dict->GetBoolean( |
| 235 "supports_spdy", &supports_spdy)) && supports_spdy) { |
| 236 spdy_servers->push_back(server_str); |
| 237 } |
| 238 |
| 239 // Get SpdySettings. |
| 240 DCHECK(!ContainsKey(*spdy_settings_map, server)); |
| 241 base::ListValue* spdy_settings_list = NULL; |
| 242 if (server_pref_dict->GetListWithoutPathExpansion( |
| 243 "settings", &spdy_settings_list)) { |
| 244 spdy::SpdySettings spdy_settings; |
| 245 |
| 246 for (base::ListValue::const_iterator list_it = |
| 247 spdy_settings_list->begin(); |
| 248 list_it != spdy_settings_list->end(); ++list_it) { |
| 249 if ((*list_it)->GetType() != Value::TYPE_DICTIONARY) { |
| 250 DVLOG(1) << "Malformed SpdySettingsList for server: " << server_str; |
| 251 NOTREACHED(); |
| 252 continue; |
| 253 } |
| 254 |
| 255 const base::DictionaryValue* spdy_setting_dict = |
| 256 static_cast<const base::DictionaryValue*>(*list_it); |
| 257 |
| 258 int id = 0; |
| 259 if (!spdy_setting_dict->GetIntegerWithoutPathExpansion("id", &id)) { |
| 260 DVLOG(1) << "Malformed id in SpdySettings for server: " << server_str; |
| 261 NOTREACHED(); |
| 262 continue; |
| 263 } |
| 264 |
| 265 int value = 0; |
| 266 if (!spdy_setting_dict->GetIntegerWithoutPathExpansion("value", |
| 267 &value)) { |
| 268 DVLOG(1) << "Malformed value in SpdySettings for server: " << |
| 269 server_str; |
| 270 NOTREACHED(); |
| 271 continue; |
| 272 } |
| 273 |
| 274 spdy::SettingsFlagsAndId flags_and_id(0); |
| 275 flags_and_id.set_id(id); |
| 276 flags_and_id.set_flags(spdy::SETTINGS_FLAG_PERSISTED); |
| 277 |
| 278 spdy_settings.push_back(spdy::SpdySetting(flags_and_id, value)); |
| 279 } |
| 280 |
| 281 (*spdy_settings_map)[server] = spdy_settings; |
| 282 } |
| 283 |
| 284 // Get alternate_protocol server. |
| 285 DCHECK(!ContainsKey(*alternate_protocol_map, server)); |
| 286 base::DictionaryValue* port_alternate_protocol_dict = NULL; |
| 287 if (!server_pref_dict->GetDictionaryWithoutPathExpansion( |
| 288 "alternate_protocol", &port_alternate_protocol_dict)) { |
| 289 continue; |
| 290 } |
| 291 |
| 292 do { |
| 293 int port = 0; |
| 294 if (!port_alternate_protocol_dict->GetIntegerWithoutPathExpansion( |
| 295 "port", &port) || (port > (1 << 16))) { |
| 296 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str; |
| 297 NOTREACHED(); |
| 298 continue; |
| 299 } |
| 300 int protocol = 0; |
| 301 if (!port_alternate_protocol_dict->GetIntegerWithoutPathExpansion( |
| 302 "protocol", &protocol) || (protocol < 0) || |
| 303 (protocol > net::NUM_ALTERNATE_PROTOCOLS)) { |
| 304 DVLOG(1) << "Malformed Alternate-Protocol server: " << server_str; |
| 305 NOTREACHED(); |
| 306 continue; |
| 307 } |
| 308 |
| 309 net::PortAlternateProtocolPair port_alternate_protocol; |
| 310 port_alternate_protocol.port = port; |
| 311 port_alternate_protocol.protocol = static_cast<net::AlternateProtocol>( |
| 312 protocol); |
| 313 |
| 314 (*alternate_protocol_map)[server] = port_alternate_protocol; |
| 315 } while (false); |
| 316 } |
196 | 317 |
197 BrowserThread::PostTask( | 318 BrowserThread::PostTask( |
198 BrowserThread::IO, | 319 BrowserThread::IO, |
199 FROM_HERE, | 320 FROM_HERE, |
200 base::Bind(&HttpServerPropertiesManager::UpdateSpdyCacheFromPrefsOnIO, | 321 base::Bind(&HttpServerPropertiesManager:: |
201 base::Unretained(this), spdy_servers, true)); | 322 UpdateCacheFromPrefsOnIO, |
202 } | 323 base::Unretained(this), |
203 | 324 base::Owned(spdy_servers), |
204 void HttpServerPropertiesManager::UpdateSpdyCacheFromPrefsOnIO( | 325 base::Owned(spdy_settings_map), |
| 326 base::Owned(alternate_protocol_map))); |
| 327 } |
| 328 |
| 329 void HttpServerPropertiesManager::UpdateCacheFromPrefsOnIO( |
205 StringVector* spdy_servers, | 330 StringVector* spdy_servers, |
206 bool support_spdy) { | 331 net::SpdySettingsMap* spdy_settings_map, |
207 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 332 net::AlternateProtocolMap* alternate_protocol_map) { |
208 // Preferences have the master data because admins might have pushed new | 333 // 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 | 334 // preferences. Update the cached data with new data from preferences. |
| 335 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 336 |
| 337 http_server_properties_impl_->InitializeSpdyServers(spdy_servers, true); |
| 338 |
| 339 // Clear the cached data and use the new spdy_settings from preferences. |
| 340 http_server_properties_impl_->InitializeSpdySettingsServers( |
| 341 spdy_settings_map); |
| 342 |
| 343 // Clear the cached data and use the new Alternate-Protocol server list from |
210 // preferences. | 344 // preferences. |
211 scoped_ptr<StringVector> scoped_spdy_servers(spdy_servers); | 345 http_server_properties_impl_->InitializeAlternateProtocolServers( |
212 http_server_properties_impl_->InitializeSpdyServers(spdy_servers, | 346 alternate_protocol_map); |
213 support_spdy); | 347 } |
214 } | 348 |
215 | 349 |
216 // | 350 // |
217 // Update Preferences with data from spdy_servers (the cached data). | 351 // Update Preferences with data from the cached data. |
218 // | 352 // |
219 void HttpServerPropertiesManager::ScheduleUpdateSpdyPrefsOnIO() { | 353 void HttpServerPropertiesManager::ScheduleUpdatePrefsOnIO() { |
220 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 354 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
221 // Cancel pending updates, if any. | 355 // Cancel pending updates, if any. |
222 io_spdy_prefs_update_timer_->Stop(); | 356 io_prefs_update_timer_->Stop(); |
223 StartSpdyPrefsUpdateTimerOnIO( | 357 StartPrefsUpdateTimerOnIO( |
224 base::TimeDelta::FromMilliseconds(kUpdatePrefsDelayMs)); | 358 base::TimeDelta::FromMilliseconds(kUpdatePrefsDelayMs)); |
225 } | 359 } |
226 | 360 |
227 void HttpServerPropertiesManager::UpdateSpdyPrefsFromCache() { | 361 void HttpServerPropertiesManager::StartPrefsUpdateTimerOnIO( |
228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 362 base::TimeDelta delay) { |
229 | 363 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
230 scoped_refptr<RefCountedListValue> spdy_server_list = | 364 // This is overridden in tests to post the task without the delay. |
231 new RefCountedListValue(); | 365 io_prefs_update_timer_->Start( |
232 http_server_properties_impl_->GetSpdyServerList(&spdy_server_list->data); | 366 FROM_HERE, delay, this, |
| 367 &HttpServerPropertiesManager::UpdatePrefsFromCacheOnIO); |
| 368 } |
| 369 |
| 370 void HttpServerPropertiesManager::UpdatePrefsFromCacheOnIO() { |
| 371 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 372 |
| 373 base::ListValue* spdy_server_list = new base::ListValue; |
| 374 http_server_properties_impl_->GetSpdyServerList(spdy_server_list); |
| 375 |
| 376 net::SpdySettingsMap* spdy_settings_map = new net::SpdySettingsMap; |
| 377 *spdy_settings_map = http_server_properties_impl_->spdy_settings_map(); |
| 378 |
| 379 net::AlternateProtocolMap* alternate_protocol_map = |
| 380 new net::AlternateProtocolMap; |
| 381 *alternate_protocol_map = |
| 382 http_server_properties_impl_->alternate_protocol_map(); |
233 | 383 |
234 // Update the preferences on the UI thread. | 384 // Update the preferences on the UI thread. |
235 BrowserThread::PostTask( | 385 BrowserThread::PostTask( |
236 BrowserThread::UI, | 386 BrowserThread::UI, |
237 FROM_HERE, | 387 FROM_HERE, |
238 base::Bind(&HttpServerPropertiesManager::SetSpdyServersInPrefsOnUI, | 388 base::Bind(&HttpServerPropertiesManager::UpdatePrefsOnUI, |
239 ui_weak_ptr_, spdy_server_list)); | 389 ui_weak_ptr_, |
240 } | 390 base::Owned(spdy_server_list), |
241 | 391 base::Owned(spdy_settings_map), |
242 void HttpServerPropertiesManager::SetSpdyServersInPrefsOnUI( | 392 base::Owned(alternate_protocol_map))); |
243 scoped_refptr<RefCountedListValue> spdy_server_list) { | 393 } |
| 394 |
| 395 // A local or temporary data structure to hold supports_spdy, SpdySettings and |
| 396 // PortAlternateProtocolPair preferences for a server. This is used only in |
| 397 // UpdatePrefsOnUI. |
| 398 struct ServerPref { |
| 399 ServerPref() |
| 400 : supports_spdy(false), |
| 401 settings(NULL), |
| 402 alternate_protocol(NULL) { |
| 403 } |
| 404 ServerPref(bool supports_spdy, |
| 405 const spdy::SpdySettings* settings, |
| 406 const net::PortAlternateProtocolPair* alternate_protocol) |
| 407 : supports_spdy(supports_spdy), |
| 408 settings(settings), |
| 409 alternate_protocol(alternate_protocol) { |
| 410 } |
| 411 bool supports_spdy; |
| 412 const spdy::SpdySettings* settings; |
| 413 const net::PortAlternateProtocolPair* alternate_protocol; |
| 414 }; |
| 415 |
| 416 void HttpServerPropertiesManager::UpdatePrefsOnUI( |
| 417 base::ListValue* spdy_server_list, |
| 418 net::SpdySettingsMap* spdy_settings_map, |
| 419 net::AlternateProtocolMap* alternate_protocol_map) { |
| 420 |
| 421 typedef std::map<net::HostPortPair, ServerPref> ServerPrefMap; |
| 422 ServerPrefMap server_pref_map; |
| 423 |
244 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 424 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
245 setting_spdy_servers_ = true; | 425 |
246 pref_service_->Set(prefs::kSpdyServers, spdy_server_list->data); | 426 // Add servers that support spdy to server_pref_map. |
247 setting_spdy_servers_ = false; | 427 std::string s; |
248 } | 428 for (base::ListValue::const_iterator list_it = spdy_server_list->begin(); |
249 | 429 list_it != spdy_server_list->end(); ++list_it) { |
250 void HttpServerPropertiesManager::ScheduleUpdateAlternateProtocolCacheOnUI() { | 430 if ((*list_it)->GetAsString(&s)) { |
251 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 431 net::HostPortPair server = net::HostPortPair::FromString(s); |
252 // Cancel pending updates, if any. | 432 |
253 ui_alternate_protocol_cache_update_timer_->Stop(); | 433 ServerPrefMap::iterator it = server_pref_map.find(server); |
254 StartAlternateProtocolCacheUpdateTimerOnUI( | 434 if (it == server_pref_map.end()) { |
255 base::TimeDelta::FromMilliseconds(kUpdateCacheDelayMs)); | 435 ServerPref server_pref(true, NULL, NULL); |
256 } | 436 server_pref_map[server] = server_pref; |
257 | 437 } else { |
258 void HttpServerPropertiesManager::UpdateAlternateProtocolCacheFromPrefs() { | 438 it->second.supports_spdy = true; |
259 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 439 } |
260 | 440 } |
261 if (!pref_service_->HasPrefPath(prefs::kAlternateProtocolServers)) | 441 } |
262 return; | 442 |
263 | 443 // Add servers that have SpdySettings to server_pref_map. |
264 // Parse the preferences into a AlternateProtocolMap. | 444 for (net::SpdySettingsMap::iterator map_it = |
265 net::AlternateProtocolMap alternate_protocol_map; | 445 spdy_settings_map->begin(); |
266 const base::DictionaryValue& alternate_protocol_servers = | 446 map_it != spdy_settings_map->end(); ++map_it) { |
267 *pref_service_->GetDictionary(prefs::kAlternateProtocolServers); | 447 const net::HostPortPair& server = map_it->first; |
268 for (base::DictionaryValue::key_iterator it = | 448 |
269 alternate_protocol_servers.begin_keys(); | 449 ServerPrefMap::iterator it = server_pref_map.find(server); |
270 it != alternate_protocol_servers.end_keys(); ++it) { | 450 if (it == server_pref_map.end()) { |
271 const std::string& server_str = *it; | 451 ServerPref server_pref(false, &map_it->second, NULL); |
272 net::HostPortPair server = net::HostPortPair::FromString(server_str); | 452 server_pref_map[server] = server_pref; |
273 if (server.host().empty()) { | 453 } else { |
274 VLOG(1) << "Malformed Alternate-Protocol server: " << server_str; | 454 it->second.settings = &map_it->second; |
275 NOTREACHED(); | 455 } |
276 continue; | 456 } |
277 } | 457 |
278 DCHECK(!ContainsKey(alternate_protocol_map, server)); | 458 // Add AlternateProtocol servers to server_pref_map. |
279 | 459 for (net::AlternateProtocolMap::const_iterator map_it = |
280 base::DictionaryValue* port_alternate_protocol_dict = NULL; | 460 alternate_protocol_map->begin(); |
281 if (!alternate_protocol_servers.GetDictionaryWithoutPathExpansion( | 461 map_it != alternate_protocol_map->end(); ++map_it) { |
282 server_str, &port_alternate_protocol_dict)) { | 462 const net::HostPortPair& server = map_it->first; |
283 VLOG(1) << "Malformed Alternate-Protocol server: " << server_str; | |
284 NOTREACHED(); | |
285 continue; | |
286 } | |
287 | |
288 int port = 0; | |
289 if (!port_alternate_protocol_dict->GetIntegerWithoutPathExpansion( | |
290 "port", &port) || (port > (1 << 16))) { | |
291 VLOG(1) << "Malformed Alternate-Protocol server: " << server_str; | |
292 NOTREACHED(); | |
293 continue; | |
294 } | |
295 int protocol = 0; | |
296 if (!port_alternate_protocol_dict->GetIntegerWithoutPathExpansion( | |
297 "protocol", &protocol) || (protocol < 0) || | |
298 (protocol > net::NUM_ALTERNATE_PROTOCOLS)) { | |
299 VLOG(1) << "Malformed Alternate-Protocol server: " << server_str; | |
300 NOTREACHED(); | |
301 continue; | |
302 } | |
303 | |
304 net::PortAlternateProtocolPair port_alternate_protocol; | |
305 port_alternate_protocol.port = port; | |
306 port_alternate_protocol.protocol = static_cast<net::AlternateProtocol>( | |
307 protocol); | |
308 | |
309 alternate_protocol_map[server] = port_alternate_protocol; | |
310 } | |
311 | |
312 scoped_refptr<RefCountedAlternateProtocolMap> alternate_protocol_map_arg = | |
313 new RefCountedAlternateProtocolMap; | |
314 alternate_protocol_map_arg->data.swap(alternate_protocol_map); | |
315 | |
316 BrowserThread::PostTask( | |
317 BrowserThread::IO, | |
318 FROM_HERE, | |
319 base::Bind(&HttpServerPropertiesManager:: | |
320 UpdateAlternateProtocolCacheFromPrefsOnIO, | |
321 base::Unretained(this), alternate_protocol_map_arg)); | |
322 } | |
323 | |
324 void HttpServerPropertiesManager::UpdateAlternateProtocolCacheFromPrefsOnIO( | |
325 RefCountedAlternateProtocolMap* alternate_protocol_map) { | |
326 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
327 // 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 | |
329 // preferences. | |
330 http_server_properties_impl_->InitializeAlternateProtocolServers( | |
331 &alternate_protocol_map->data); | |
332 } | |
333 | |
334 // | |
335 // Update Preferences with data from alternate_protocol_servers (the cached | |
336 // data). | |
337 // | |
338 void HttpServerPropertiesManager::ScheduleUpdateAlternateProtocolPrefsOnIO() { | |
339 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
340 // Cancel pending updates, if any. | |
341 io_alternate_protocol_prefs_update_timer_->Stop(); | |
342 StartAlternateProtocolPrefsUpdateTimerOnIO( | |
343 base::TimeDelta::FromMilliseconds(kUpdatePrefsDelayMs)); | |
344 } | |
345 | |
346 void HttpServerPropertiesManager::UpdateAlternateProtocolPrefsFromCache() { | |
347 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
348 | |
349 scoped_refptr<RefCountedAlternateProtocolMap> alternate_protocol_map = | |
350 new RefCountedAlternateProtocolMap; | |
351 alternate_protocol_map->data = | |
352 http_server_properties_impl_->alternate_protocol_map(); | |
353 | |
354 // Update the preferences on the UI thread. | |
355 BrowserThread::PostTask( | |
356 BrowserThread::UI, | |
357 FROM_HERE, | |
358 base::Bind(&HttpServerPropertiesManager:: | |
359 SetAlternateProtocolServersInPrefsOnUI, | |
360 ui_weak_ptr_, alternate_protocol_map)); | |
361 } | |
362 | |
363 void HttpServerPropertiesManager::SetAlternateProtocolServersInPrefsOnUI( | |
364 RefCountedAlternateProtocolMap* alternate_protocol_map) { | |
365 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
366 base::DictionaryValue alternate_protocol_dict; | |
367 for (net::AlternateProtocolMap::const_iterator it = | |
368 alternate_protocol_map->data.begin(); | |
369 it != alternate_protocol_map->data.end(); ++it) { | |
370 const net::HostPortPair& server = it->first; | |
371 const net::PortAlternateProtocolPair& port_alternate_protocol = | 463 const net::PortAlternateProtocolPair& port_alternate_protocol = |
372 it->second; | 464 map_it->second; |
373 if (port_alternate_protocol.protocol < 0 || | 465 if (port_alternate_protocol.protocol < 0 || |
374 port_alternate_protocol.protocol >= net::NUM_ALTERNATE_PROTOCOLS) { | 466 port_alternate_protocol.protocol >= net::NUM_ALTERNATE_PROTOCOLS) { |
375 continue; | 467 continue; |
376 } | 468 } |
377 base::DictionaryValue* port_alternate_protocol_dict = | 469 |
378 new base::DictionaryValue; | 470 ServerPrefMap::iterator it = server_pref_map.find(server); |
379 port_alternate_protocol_dict->SetInteger( | 471 if (it == server_pref_map.end()) { |
380 "port", port_alternate_protocol.port); | 472 ServerPref server_pref(false, NULL, &map_it->second); |
381 port_alternate_protocol_dict->SetInteger( | 473 server_pref_map[server] = server_pref; |
382 "protocol", port_alternate_protocol.protocol); | 474 } else { |
383 alternate_protocol_dict.SetWithoutPathExpansion( | 475 it->second.alternate_protocol = &map_it->second; |
384 server.ToString(), port_alternate_protocol_dict); | 476 } |
385 } | 477 } |
386 setting_alternate_protocol_servers_ = true; | 478 |
387 pref_service_->Set(prefs::kAlternateProtocolServers, | 479 // Persist the prefs::kHttpServerProperties. |
388 alternate_protocol_dict); | 480 base::DictionaryValue http_server_properties_dict; |
389 setting_alternate_protocol_servers_ = false; | 481 for (ServerPrefMap::const_iterator map_it = |
390 } | 482 server_pref_map.begin(); |
391 | 483 map_it != server_pref_map.end(); ++map_it) { |
392 void HttpServerPropertiesManager::StartSpdyCacheUpdateTimerOnUI( | 484 const net::HostPortPair& server = map_it->first; |
393 base::TimeDelta delay) { | 485 const ServerPref& server_pref = map_it->second; |
394 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 486 |
395 ui_spdy_cache_update_timer_->Start( | 487 base::DictionaryValue* server_pref_dict = new base::DictionaryValue; |
396 FROM_HERE, delay, this, | 488 |
397 &HttpServerPropertiesManager::UpdateSpdyCacheFromPrefs); | 489 // Save supports_spdy. |
398 } | 490 server_pref_dict->SetBoolean("supports_spdy", server_pref.supports_spdy); |
399 | 491 |
400 void HttpServerPropertiesManager::StartSpdyPrefsUpdateTimerOnIO( | 492 // Save SpdySettings. |
401 base::TimeDelta delay) { | 493 if (server_pref.settings) { |
402 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 494 base::ListValue* spdy_settings_list = new ListValue(); |
403 // This is overridden in tests to post the task without the delay. | 495 for (spdy::SpdySettings::const_iterator it = |
404 io_spdy_prefs_update_timer_->Start( | 496 server_pref.settings->begin(); |
405 FROM_HERE, delay, this, | 497 it != server_pref.settings->end(); ++it) { |
406 &HttpServerPropertiesManager::UpdateSpdyPrefsFromCache); | 498 uint32 id = it->first.id(); |
407 } | 499 uint32 value = it->second; |
408 | 500 base::DictionaryValue* spdy_setting_dict = new base::DictionaryValue; |
409 void HttpServerPropertiesManager::StartAlternateProtocolCacheUpdateTimerOnUI( | 501 spdy_setting_dict->SetInteger("id", id); |
410 base::TimeDelta delay) { | 502 spdy_setting_dict->SetInteger("value", value); |
411 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 503 spdy_settings_list->Append(spdy_setting_dict); |
412 ui_alternate_protocol_cache_update_timer_->Start( | 504 } |
413 FROM_HERE, delay, this, | 505 server_pref_dict->Set("settings", spdy_settings_list); |
414 &HttpServerPropertiesManager::UpdateAlternateProtocolCacheFromPrefs); | 506 } |
415 } | 507 |
416 | 508 // Save alternate_protocol. |
417 void HttpServerPropertiesManager::StartAlternateProtocolPrefsUpdateTimerOnIO( | 509 if (server_pref.alternate_protocol) { |
418 base::TimeDelta delay) { | 510 base::DictionaryValue* port_alternate_protocol_dict = |
419 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 511 new base::DictionaryValue; |
420 // This is overridden in tests to post the task without the delay. | 512 const net::PortAlternateProtocolPair* port_alternate_protocol = |
421 io_alternate_protocol_prefs_update_timer_->Start( | 513 server_pref.alternate_protocol; |
422 FROM_HERE, delay, this, | 514 port_alternate_protocol_dict->SetInteger( |
423 &HttpServerPropertiesManager::UpdateAlternateProtocolPrefsFromCache); | 515 "port", port_alternate_protocol->port); |
| 516 port_alternate_protocol_dict->SetInteger( |
| 517 "protocol", port_alternate_protocol->protocol); |
| 518 server_pref_dict->SetWithoutPathExpansion( |
| 519 "alternate_protocol", port_alternate_protocol_dict); |
| 520 } |
| 521 http_server_properties_dict.SetWithoutPathExpansion( |
| 522 server.ToString(), server_pref_dict); |
| 523 } |
| 524 |
| 525 setting_prefs_ = true; |
| 526 pref_service_->Set(prefs::kHttpServerProperties, |
| 527 http_server_properties_dict); |
| 528 setting_prefs_ = false; |
424 } | 529 } |
425 | 530 |
426 void HttpServerPropertiesManager::Observe( | 531 void HttpServerPropertiesManager::Observe( |
427 int type, | 532 int type, |
428 const content::NotificationSource& source, | 533 const content::NotificationSource& source, |
429 const content::NotificationDetails& details) { | 534 const content::NotificationDetails& details) { |
430 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 535 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
431 DCHECK(type == chrome::NOTIFICATION_PREF_CHANGED); | 536 DCHECK(type == chrome::NOTIFICATION_PREF_CHANGED); |
432 PrefService* prefs = content::Source<PrefService>(source).ptr(); | 537 PrefService* prefs = content::Source<PrefService>(source).ptr(); |
433 DCHECK(prefs == pref_service_); | 538 DCHECK(prefs == pref_service_); |
434 std::string* pref_name = content::Details<std::string>(details).ptr(); | 539 std::string* pref_name = content::Details<std::string>(details).ptr(); |
435 if (*pref_name == prefs::kSpdyServers) { | 540 if (*pref_name == prefs::kHttpServerProperties) { |
436 if (!setting_spdy_servers_) | 541 if (!setting_prefs_) |
437 ScheduleUpdateSpdyCacheOnUI(); | 542 ScheduleUpdateCacheOnUI(); |
438 } else if (*pref_name == prefs::kAlternateProtocolServers) { | |
439 if (!setting_alternate_protocol_servers_) | |
440 ScheduleUpdateAlternateProtocolCacheOnUI(); | |
441 } else { | 543 } else { |
442 NOTREACHED(); | 544 NOTREACHED(); |
443 } | 545 } |
444 } | 546 } |
445 | 547 |
446 } // namespace chrome_browser_net | 548 } // namespace chrome_browser_net |
OLD | NEW |