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

Side by Side Diff: content/browser/background_sync/background_sync_manager.cc

Issue 950343006: [BackgroundSync] Initial land of the BackgroundSyncManager (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address issues from PS15 Created 5 years, 9 months 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
OLDNEW
(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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698