Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(126)

Side by Side Diff: chrome/browser/net/http_server_properties_manager.cc

Issue 8423028: Persist dynamically learned SPDY settings (like CWND). (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
OLDNEW
« no previous file with comments | « chrome/browser/net/http_server_properties_manager.h ('k') | chrome/browser/net/http_server_properties_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698