OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "content/browser/background_sync/background_sync_manager.h" | |
6 | |
7 #include "base/barrier_closure.h" | |
8 #include "base/bind.h" | |
9 #include "content/browser/background_sync/background_sync.pb.h" | |
10 #include "content/browser/service_worker/service_worker_context_wrapper.h" | |
11 #include "content/browser/service_worker/service_worker_storage.h" | |
12 #include "content/public/browser/browser_thread.h" | |
13 | |
14 namespace { | |
15 const char kBackgroundSyncUserDataKey[] = "BackgroundSyncUserData"; | |
16 } | |
17 | |
18 namespace content { | |
19 | |
20 const BackgroundSyncManager::BackgroundSyncRegistration::RegistrationId | |
21 BackgroundSyncManager::BackgroundSyncRegistration::kInvalidRegistrationId = | |
22 -1; | |
23 | |
24 const BackgroundSyncManager::BackgroundSyncRegistration::RegistrationId | |
25 BackgroundSyncManager::BackgroundSyncRegistrations::kInitialId = 0; | |
26 | |
27 BackgroundSyncManager::BackgroundSyncRegistrations:: | |
28 BackgroundSyncRegistrations() | |
29 : next_id(kInitialId) { | |
30 } | |
31 BackgroundSyncManager::BackgroundSyncRegistrations::BackgroundSyncRegistrations( | |
32 BackgroundSyncRegistration::RegistrationId next_id) | |
33 : next_id(next_id) { | |
34 } | |
35 BackgroundSyncManager::BackgroundSyncRegistrations:: | |
36 ~BackgroundSyncRegistrations() { | |
37 } | |
38 | |
39 // static | |
40 scoped_ptr<BackgroundSyncManager> BackgroundSyncManager::Create( | |
41 const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context) { | |
42 BackgroundSyncManager* sync_manager = | |
43 new BackgroundSyncManager(service_worker_context); | |
44 sync_manager->Init(); | |
45 return make_scoped_ptr(sync_manager); | |
46 } | |
47 | |
48 BackgroundSyncManager::~BackgroundSyncManager() { | |
49 } | |
50 | |
51 void BackgroundSyncManager::Register( | |
52 const GURL& origin, | |
53 int64 sw_registration_id, | |
54 const BackgroundSyncRegistration& sync_registration, | |
55 const StatusAndRegistrationCallback& callback) { | |
56 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
57 DCHECK_EQ(BackgroundSyncRegistration::kInvalidRegistrationId, | |
58 sync_registration.id); | |
59 | |
60 StatusAndRegistrationCallback pending_callback = | |
61 base::Bind(&BackgroundSyncManager::PendingStatusAndRegistrationCallback, | |
62 weak_ptr_factory_.GetWeakPtr(), callback); | |
63 | |
64 op_scheduler_.ScheduleOperation(base::Bind( | |
65 &BackgroundSyncManager::RegisterImpl, weak_ptr_factory_.GetWeakPtr(), | |
66 origin, sw_registration_id, sync_registration, pending_callback)); | |
67 } | |
68 | |
69 void BackgroundSyncManager::Unregister( | |
70 const GURL& origin, | |
71 int64 sw_registration_id, | |
72 const std::string& sync_registration_name, | |
73 BackgroundSyncRegistration::RegistrationId sync_registration_id, | |
74 const StatusCallback& callback) { | |
75 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
76 | |
77 StatusCallback pending_callback = | |
78 base::Bind(&BackgroundSyncManager::PendingStatusCallback, | |
79 weak_ptr_factory_.GetWeakPtr(), callback); | |
80 | |
81 op_scheduler_.ScheduleOperation(base::Bind( | |
82 &BackgroundSyncManager::UnregisterImpl, weak_ptr_factory_.GetWeakPtr(), | |
83 origin, sw_registration_id, sync_registration_name, sync_registration_id, | |
84 pending_callback)); | |
85 } | |
86 | |
87 void BackgroundSyncManager::GetRegistration( | |
88 const GURL& origin, | |
89 int64 sw_registration_id, | |
90 const std::string sync_registration_name, | |
91 const StatusAndRegistrationCallback& callback) { | |
92 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
93 | |
94 StatusAndRegistrationCallback pending_callback = | |
95 base::Bind(&BackgroundSyncManager::PendingStatusAndRegistrationCallback, | |
96 weak_ptr_factory_.GetWeakPtr(), callback); | |
97 | |
98 op_scheduler_.ScheduleOperation( | |
99 base::Bind(&BackgroundSyncManager::GetRegistrationImpl, | |
100 weak_ptr_factory_.GetWeakPtr(), origin, sw_registration_id, | |
101 sync_registration_name, pending_callback)); | |
102 } | |
103 | |
104 BackgroundSyncManager::BackgroundSyncManager( | |
105 const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context) | |
106 : service_worker_context_(service_worker_context), weak_ptr_factory_(this) { | |
107 } | |
108 | |
109 void BackgroundSyncManager::Init() { | |
110 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
111 DCHECK(!op_scheduler_.ScheduledOperations()); | |
112 | |
113 op_scheduler_.ScheduleOperation(base::Bind(&BackgroundSyncManager::InitImpl, | |
114 weak_ptr_factory_.GetWeakPtr())); | |
115 } | |
116 | |
117 void BackgroundSyncManager::InitImpl() { | |
118 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
119 | |
120 GetDataFromBackend( | |
121 kBackgroundSyncUserDataKey, | |
122 base::Bind(&BackgroundSyncManager::InitDidGetDataFromBackend, | |
123 weak_ptr_factory_.GetWeakPtr())); | |
124 } | |
125 | |
126 void BackgroundSyncManager::InitDidGetDataFromBackend( | |
127 const std::vector<std::pair<int64, std::string>>& user_data, | |
128 ServiceWorkerStatusCode status) { | |
davidben
2015/03/25 19:42:03
Should this check status? Looks like this'll just
jkarlin
2015/03/25 20:45:45
Added a LOG error and a TODO to the header file th
| |
129 bool corruption_detected = false; | |
130 for (const std::pair<int64, std::string>& data : user_data) { | |
131 BackgroundSyncRegistrationsProto registrations_proto; | |
132 if (registrations_proto.ParseFromString(data.second)) { | |
133 sw_to_registrations_map_[data.first] = BackgroundSyncRegistrations( | |
134 registrations_proto.next_registration_id()); | |
135 BackgroundSyncRegistrations* registrations = | |
136 &sw_to_registrations_map_[data.first]; | |
137 | |
138 for (int i = 0, max = registrations_proto.registration_size(); i < max; | |
139 ++i) { | |
140 const BackgroundSyncRegistrationProto& registration_proto = | |
141 registrations_proto.registration(i); | |
142 | |
143 if (registration_proto.id() >= registrations->next_id) { | |
144 corruption_detected = true; | |
145 break; | |
146 } | |
147 | |
148 BackgroundSyncRegistration registration(registration_proto.id(), | |
149 registration_proto.name()); | |
150 if (registration_proto.has_min_period()) | |
151 registration.min_period = registration_proto.min_period(); | |
152 registrations->name_to_registration_map[registration_proto.name()] = | |
153 registration; | |
154 } | |
155 } | |
156 | |
157 if (corruption_detected) | |
158 break; | |
159 } | |
160 | |
161 if (corruption_detected) | |
davidben
2015/03/25 19:42:03
Nit: Maybe spew to LOG(ERROR) or something? Though
jkarlin
2015/03/25 20:45:45
Done.
| |
162 sw_to_registrations_map_.clear(); | |
163 | |
164 // TODO(jkarlin): Call the scheduling algorithm here. | |
165 | |
166 op_scheduler_.CompleteOperationAndRunNext(); | |
167 } | |
168 | |
169 void BackgroundSyncManager::RegisterImpl( | |
170 const GURL& origin, | |
171 int64 sw_registration_id, | |
172 const BackgroundSyncRegistration& sync_registration, | |
173 const StatusAndRegistrationCallback& callback) { | |
174 BackgroundSyncRegistration existing_registration; | |
175 if (LookupRegistration(sw_registration_id, sync_registration.name, | |
176 &existing_registration)) { | |
177 if (existing_registration.Equals(sync_registration)) { | |
178 base::MessageLoop::current()->PostTask( | |
179 FROM_HERE, | |
180 base::Bind(callback, ERROR_TYPE_OK, existing_registration)); | |
181 return; | |
182 } | |
183 } | |
184 | |
185 BackgroundSyncRegistration new_registration = sync_registration; | |
186 BackgroundSyncRegistrations* registrations = | |
187 &sw_to_registrations_map_[sw_registration_id]; | |
188 new_registration.id = registrations->next_id++; | |
189 | |
190 AddRegistrationToMap(sw_registration_id, new_registration); | |
191 | |
192 StoreRegistrations( | |
193 origin, sw_registration_id, | |
194 base::Bind(&BackgroundSyncManager::RegisterDidStore, | |
195 weak_ptr_factory_.GetWeakPtr(), sw_registration_id, | |
196 new_registration, existing_registration, callback)); | |
197 } | |
198 | |
199 bool BackgroundSyncManager::LookupRegistration( | |
200 int64 sw_registration_id, | |
201 const std::string& sync_registration_name, | |
202 BackgroundSyncRegistration* existing_registration) { | |
203 SWIdToRegistrationsMap::iterator it = | |
204 sw_to_registrations_map_.find(sw_registration_id); | |
205 if (it == sw_to_registrations_map_.end()) | |
206 return false; | |
207 | |
208 const BackgroundSyncRegistrations& registrations = it->second; | |
209 const auto name_and_registration_iter = | |
210 registrations.name_to_registration_map.find(sync_registration_name); | |
211 if (name_and_registration_iter == | |
212 registrations.name_to_registration_map.end()) | |
213 return false; | |
214 | |
215 if (existing_registration) | |
216 *existing_registration = name_and_registration_iter->second; | |
217 | |
218 return true; | |
219 } | |
220 | |
221 void BackgroundSyncManager::StoreRegistrations( | |
222 const GURL& origin, | |
223 int64 sw_registration_id, | |
224 const ServiceWorkerStorage::StatusCallback& callback) { | |
225 // Serialize the data. | |
226 const BackgroundSyncRegistrations& registrations = | |
227 sw_to_registrations_map_[sw_registration_id]; | |
228 BackgroundSyncRegistrationsProto registrations_proto; | |
229 registrations_proto.set_next_registration_id(registrations.next_id); | |
230 | |
231 for (const auto& name_and_registration : | |
232 registrations.name_to_registration_map) { | |
233 const BackgroundSyncRegistration& registration = | |
234 name_and_registration.second; | |
235 BackgroundSyncRegistrationProto* registration_proto = | |
236 registrations_proto.add_registration(); | |
237 registration_proto->set_id(registration.id); | |
238 registration_proto->set_name(registration.name); | |
239 if (registration.min_period != 0) | |
240 registration_proto->set_min_period(registration.min_period); | |
241 } | |
242 std::string serialized; | |
243 bool success = registrations_proto.SerializeToString(&serialized); | |
244 DCHECK(success); | |
245 | |
246 StoreDataInBackend(sw_registration_id, origin, kBackgroundSyncUserDataKey, | |
247 serialized, callback); | |
248 } | |
249 | |
250 void BackgroundSyncManager::RegisterDidStore( | |
251 int64 sw_registration_id, | |
252 const BackgroundSyncRegistration& new_registration, | |
253 const BackgroundSyncRegistration& previous_registration, | |
254 const StatusAndRegistrationCallback& callback, | |
255 ServiceWorkerStatusCode status) { | |
256 if (status != SERVICE_WORKER_OK) { | |
257 // Restore the previous state. | |
258 if (previous_registration.id != | |
259 BackgroundSyncRegistration::kInvalidRegistrationId) { | |
260 AddRegistrationToMap(sw_registration_id, previous_registration); | |
261 } else { | |
262 RemoveRegistrationFromMap(sw_registration_id, new_registration.name, | |
263 nullptr); | |
264 } | |
265 base::MessageLoop::current()->PostTask( | |
266 FROM_HERE, | |
267 base::Bind(callback, ERROR_TYPE_STORAGE, BackgroundSyncRegistration())); | |
268 return; | |
269 } | |
270 | |
271 // TODO(jkarlin): Run the registration algorithm. | |
272 base::MessageLoop::current()->PostTask( | |
273 FROM_HERE, base::Bind(callback, ERROR_TYPE_OK, new_registration)); | |
274 } | |
275 | |
276 void BackgroundSyncManager::RemoveRegistrationFromMap( | |
277 int64 sw_registration_id, | |
278 const std::string& sync_registration_name, | |
279 BackgroundSyncRegistration* old_registration) { | |
280 DCHECK( | |
281 LookupRegistration(sw_registration_id, sync_registration_name, nullptr)); | |
282 | |
283 BackgroundSyncRegistrations* registrations = | |
284 &sw_to_registrations_map_[sw_registration_id]; | |
285 | |
286 const auto name_and_registration_iter = | |
287 registrations->name_to_registration_map.find(sync_registration_name); | |
288 if (old_registration) | |
289 *old_registration = name_and_registration_iter->second; | |
290 | |
291 registrations->name_to_registration_map.erase(name_and_registration_iter); | |
292 } | |
293 | |
294 void BackgroundSyncManager::AddRegistrationToMap( | |
295 int64 sw_registration_id, | |
296 const BackgroundSyncRegistration& sync_registration) { | |
297 DCHECK_NE(BackgroundSyncRegistration::kInvalidRegistrationId, | |
298 sw_registration_id); | |
299 | |
300 BackgroundSyncRegistrations* registrations = | |
301 &sw_to_registrations_map_[sw_registration_id]; | |
302 registrations->name_to_registration_map[sync_registration.name] = | |
303 sync_registration; | |
304 } | |
305 | |
306 void BackgroundSyncManager::StoreDataInBackend( | |
307 int64 sw_registration_id, | |
308 const GURL& origin, | |
309 const std::string& key, | |
310 const std::string& data, | |
311 const ServiceWorkerStorage::StatusCallback& callback) { | |
312 service_worker_context_->context()->storage()->StoreUserData( | |
313 sw_registration_id, origin, key, data, callback); | |
314 } | |
315 | |
316 void BackgroundSyncManager::GetDataFromBackend( | |
317 const std::string& key, | |
318 const ServiceWorkerStorage::GetUserDataForAllRegistrationsCallback& | |
319 callback) { | |
320 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
321 | |
322 service_worker_context_->context()->storage()->GetUserDataForAllRegistrations( | |
323 key, callback); | |
324 } | |
325 | |
326 void BackgroundSyncManager::UnregisterImpl( | |
327 const GURL& origin, | |
328 int64 sw_registration_id, | |
329 const std::string& sync_registration_name, | |
330 BackgroundSyncRegistration::RegistrationId sync_registration_id, | |
331 const StatusCallback& callback) { | |
332 BackgroundSyncRegistration existing_registration; | |
333 if (!LookupRegistration(sw_registration_id, sync_registration_name, | |
334 &existing_registration) || | |
335 existing_registration.id != sync_registration_id) { | |
336 base::MessageLoop::current()->PostTask( | |
337 FROM_HERE, base::Bind(callback, ERROR_TYPE_NOT_FOUND)); | |
338 return; | |
339 } | |
340 | |
341 BackgroundSyncRegistration old_sync_registration; | |
342 RemoveRegistrationFromMap(sw_registration_id, sync_registration_name, | |
343 &old_sync_registration); | |
344 | |
345 StoreRegistrations( | |
346 origin, sw_registration_id, | |
347 base::Bind(&BackgroundSyncManager::UnregisterDidStore, | |
348 weak_ptr_factory_.GetWeakPtr(), sw_registration_id, | |
349 old_sync_registration, callback)); | |
350 } | |
351 | |
352 void BackgroundSyncManager::UnregisterDidStore( | |
353 int64 sw_registration_id, | |
354 const BackgroundSyncRegistration& old_sync_registration, | |
355 const StatusCallback& callback, | |
356 ServiceWorkerStatusCode status) { | |
357 if (status != SERVICE_WORKER_OK) { | |
358 // Restore the previous state. | |
359 AddRegistrationToMap(sw_registration_id, old_sync_registration); | |
360 base::MessageLoop::current()->PostTask( | |
361 FROM_HERE, base::Bind(callback, ERROR_TYPE_STORAGE)); | |
362 return; | |
363 } | |
364 | |
365 // TODO(jkarlin): Run the registration algorithm. | |
366 base::MessageLoop::current()->PostTask(FROM_HERE, | |
367 base::Bind(callback, ERROR_TYPE_OK)); | |
368 } | |
369 | |
370 void BackgroundSyncManager::GetRegistrationImpl( | |
371 const GURL& origin, | |
372 int64 sw_registration_id, | |
373 const std::string sync_registration_name, | |
374 const StatusAndRegistrationCallback& callback) { | |
375 BackgroundSyncRegistration out_registration; | |
376 if (!LookupRegistration(sw_registration_id, sync_registration_name, | |
377 &out_registration)) { | |
378 base::MessageLoop::current()->PostTask( | |
379 FROM_HERE, base::Bind(callback, ERROR_TYPE_NOT_FOUND, | |
380 BackgroundSyncRegistration())); | |
381 return; | |
382 } | |
383 | |
384 base::MessageLoop::current()->PostTask( | |
385 FROM_HERE, base::Bind(callback, ERROR_TYPE_OK, out_registration)); | |
386 } | |
387 | |
388 void BackgroundSyncManager::PendingStatusAndRegistrationCallback( | |
389 const StatusAndRegistrationCallback& callback, | |
390 ErrorType error, | |
391 const BackgroundSyncRegistration& sync_registration) { | |
392 // The callback might delete this object, so hang onto a weak ptr to find out. | |
393 base::WeakPtr<BackgroundSyncManager> manager = weak_ptr_factory_.GetWeakPtr(); | |
394 callback.Run(error, sync_registration); | |
395 if (manager) | |
396 op_scheduler_.CompleteOperationAndRunNext(); | |
397 } | |
398 | |
399 void BackgroundSyncManager::PendingStatusCallback( | |
400 const StatusCallback& callback, | |
401 ErrorType error) { | |
402 // The callback might delete this object, so hang onto a weak ptr to find out. | |
403 base::WeakPtr<BackgroundSyncManager> manager = weak_ptr_factory_.GetWeakPtr(); | |
404 callback.Run(error); | |
405 if (manager) | |
406 op_scheduler_.CompleteOperationAndRunNext(); | |
407 } | |
408 | |
409 } // namespace content | |
OLD | NEW |