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 |