OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 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 | 4 |
5 #include "content/browser/background_sync/background_sync_manager.h" | 5 #include "content/browser/background_sync/background_sync_manager.h" |
6 | 6 |
7 #include "base/barrier_closure.h" | 7 #include "base/barrier_closure.h" |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "content/browser/background_sync/background_sync_network_observer.h" | 9 #include "content/browser/background_sync/background_sync_network_observer.h" |
10 #include "content/browser/service_worker/service_worker_context_wrapper.h" | 10 #include "content/browser/service_worker/service_worker_context_wrapper.h" |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 // Operations already in the queue will either fail when they write to storage | 133 // Operations already in the queue will either fail when they write to storage |
134 // or return stale results based on registrations loaded in memory. This is | 134 // or return stale results based on registrations loaded in memory. This is |
135 // inconsequential since the service worker is gone. | 135 // inconsequential since the service worker is gone. |
136 op_scheduler_.ScheduleOperation(base::Bind( | 136 op_scheduler_.ScheduleOperation(base::Bind( |
137 &BackgroundSyncManager::OnRegistrationDeletedImpl, | 137 &BackgroundSyncManager::OnRegistrationDeletedImpl, |
138 weak_ptr_factory_.GetWeakPtr(), registration_id, MakeEmptyCompletion())); | 138 weak_ptr_factory_.GetWeakPtr(), registration_id, MakeEmptyCompletion())); |
139 } | 139 } |
140 | 140 |
141 void BackgroundSyncManager::OnStorageWiped() { | 141 void BackgroundSyncManager::OnStorageWiped() { |
142 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 142 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 143 |
143 // Operations already in the queue will either fail when they write to storage | 144 // Operations already in the queue will either fail when they write to storage |
144 // or return stale results based on registrations loaded in memory. This is | 145 // or return stale results based on registrations loaded in memory. This is |
145 // inconsequential since the service workers are gone. | 146 // inconsequential since the service workers are gone. |
146 op_scheduler_.ScheduleOperation( | 147 op_scheduler_.ScheduleOperation( |
147 base::Bind(&BackgroundSyncManager::OnStorageWipedImpl, | 148 base::Bind(&BackgroundSyncManager::OnStorageWipedImpl, |
148 weak_ptr_factory_.GetWeakPtr(), MakeEmptyCompletion())); | 149 weak_ptr_factory_.GetWeakPtr(), MakeEmptyCompletion())); |
149 } | 150 } |
150 | 151 |
151 BackgroundSyncManager::BackgroundSyncManager( | 152 BackgroundSyncManager::BackgroundSyncManager( |
152 const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context) | 153 const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context) |
(...skipping 30 matching lines...) Expand all Loading... |
183 GetDataFromBackend( | 184 GetDataFromBackend( |
184 kBackgroundSyncUserDataKey, | 185 kBackgroundSyncUserDataKey, |
185 base::Bind(&BackgroundSyncManager::InitDidGetDataFromBackend, | 186 base::Bind(&BackgroundSyncManager::InitDidGetDataFromBackend, |
186 weak_ptr_factory_.GetWeakPtr(), callback)); | 187 weak_ptr_factory_.GetWeakPtr(), callback)); |
187 } | 188 } |
188 | 189 |
189 void BackgroundSyncManager::InitDidGetDataFromBackend( | 190 void BackgroundSyncManager::InitDidGetDataFromBackend( |
190 const base::Closure& callback, | 191 const base::Closure& callback, |
191 const std::vector<std::pair<int64, std::string>>& user_data, | 192 const std::vector<std::pair<int64, std::string>>& user_data, |
192 ServiceWorkerStatusCode status) { | 193 ServiceWorkerStatusCode status) { |
| 194 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 195 |
193 if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) { | 196 if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) { |
194 LOG(ERROR) << "BackgroundSync failed to init due to backend failure."; | 197 LOG(ERROR) << "BackgroundSync failed to init due to backend failure."; |
195 DisableAndClearManager(base::Bind(callback)); | 198 DisableAndClearManager(base::Bind(callback)); |
196 return; | 199 return; |
197 } | 200 } |
198 | 201 |
199 bool corruption_detected = false; | 202 bool corruption_detected = false; |
200 for (const std::pair<int64, std::string>& data : user_data) { | 203 for (const std::pair<int64, std::string>& data : user_data) { |
201 BackgroundSyncRegistrationsProto registrations_proto; | 204 BackgroundSyncRegistrationsProto registrations_proto; |
202 if (registrations_proto.ParseFromString(data.second)) { | 205 if (registrations_proto.ParseFromString(data.second)) { |
(...skipping 16 matching lines...) Expand all Loading... |
219 registration_proto.periodicity()); | 222 registration_proto.periodicity()); |
220 BackgroundSyncRegistration* registration = | 223 BackgroundSyncRegistration* registration = |
221 ®istrations->registration_map[registration_key]; | 224 ®istrations->registration_map[registration_key]; |
222 | 225 |
223 registration->id = registration_proto.id(); | 226 registration->id = registration_proto.id(); |
224 registration->tag = registration_proto.tag(); | 227 registration->tag = registration_proto.tag(); |
225 registration->periodicity = registration_proto.periodicity(); | 228 registration->periodicity = registration_proto.periodicity(); |
226 registration->min_period = registration_proto.min_period(); | 229 registration->min_period = registration_proto.min_period(); |
227 registration->network_state = registration_proto.network_state(); | 230 registration->network_state = registration_proto.network_state(); |
228 registration->power_state = registration_proto.power_state(); | 231 registration->power_state = registration_proto.power_state(); |
| 232 registration->sync_state = registration_proto.sync_state(); |
| 233 if (registration->sync_state == SYNC_STATE_FIRING) { |
| 234 // If the browser (or worker) closed while firing the event, consider |
| 235 // it pending again> |
| 236 registration->sync_state = SYNC_STATE_PENDING; |
| 237 } |
229 } | 238 } |
230 } | 239 } |
231 | 240 |
232 if (corruption_detected) | 241 if (corruption_detected) |
233 break; | 242 break; |
234 } | 243 } |
235 | 244 |
236 if (corruption_detected) { | 245 if (corruption_detected) { |
237 LOG(ERROR) << "Corruption detected in background sync backend"; | 246 LOG(ERROR) << "Corruption detected in background sync backend"; |
238 DisableAndClearManager(base::Bind(callback)); | 247 DisableAndClearManager(base::Bind(callback)); |
239 return; | 248 return; |
240 } | 249 } |
241 | 250 |
242 // TODO(jkarlin): Call the scheduling algorithm here. | 251 FireReadyEvents(); |
243 | 252 |
244 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback)); | 253 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback)); |
245 } | 254 } |
246 | 255 |
247 void BackgroundSyncManager::RegisterImpl( | 256 void BackgroundSyncManager::RegisterImpl( |
248 int64 sw_registration_id, | 257 int64 sw_registration_id, |
249 const BackgroundSyncRegistration& sync_registration, | 258 const BackgroundSyncRegistration& sync_registration, |
250 const StatusAndRegistrationCallback& callback) { | 259 const StatusAndRegistrationCallback& callback) { |
| 260 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 261 |
251 if (disabled_) { | 262 if (disabled_) { |
252 base::MessageLoop::current()->PostTask( | 263 base::MessageLoop::current()->PostTask( |
253 FROM_HERE, | 264 FROM_HERE, |
254 base::Bind(callback, ERROR_TYPE_STORAGE, BackgroundSyncRegistration())); | 265 base::Bind(callback, ERROR_TYPE_STORAGE, BackgroundSyncRegistration())); |
255 return; | 266 return; |
256 } | 267 } |
257 | 268 |
258 const BackgroundSyncRegistration* existing_registration = LookupRegistration( | 269 const BackgroundSyncRegistration* existing_registration = LookupRegistration( |
259 sw_registration_id, RegistrationKey(sync_registration)); | 270 sw_registration_id, RegistrationKey(sync_registration)); |
260 if (existing_registration && | 271 if (existing_registration && |
(...skipping 23 matching lines...) Expand all Loading... |
284 | 295 |
285 StoreRegistrations( | 296 StoreRegistrations( |
286 sw_registration_id, | 297 sw_registration_id, |
287 base::Bind(&BackgroundSyncManager::RegisterDidStore, | 298 base::Bind(&BackgroundSyncManager::RegisterDidStore, |
288 weak_ptr_factory_.GetWeakPtr(), sw_registration_id, | 299 weak_ptr_factory_.GetWeakPtr(), sw_registration_id, |
289 new_registration, callback)); | 300 new_registration, callback)); |
290 } | 301 } |
291 | 302 |
292 void BackgroundSyncManager::DisableAndClearManager( | 303 void BackgroundSyncManager::DisableAndClearManager( |
293 const base::Closure& callback) { | 304 const base::Closure& callback) { |
| 305 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 306 |
294 if (disabled_) { | 307 if (disabled_) { |
295 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback)); | 308 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback)); |
296 return; | 309 return; |
297 } | 310 } |
298 | 311 |
299 disabled_ = true; | 312 disabled_ = true; |
300 sw_to_registrations_map_.clear(); | 313 sw_to_registrations_map_.clear(); |
301 | 314 |
302 // Delete all backend entries. The memory representation of registered syncs | 315 // Delete all backend entries. The memory representation of registered syncs |
303 // may be out of sync with storage (e.g., due to corruption detection on | 316 // may be out of sync with storage (e.g., due to corruption detection on |
304 // loading from storage), so reload the registrations from storage again. | 317 // loading from storage), so reload the registrations from storage again. |
305 GetDataFromBackend( | 318 GetDataFromBackend( |
306 kBackgroundSyncUserDataKey, | 319 kBackgroundSyncUserDataKey, |
307 base::Bind(&BackgroundSyncManager::DisableAndClearDidGetRegistrations, | 320 base::Bind(&BackgroundSyncManager::DisableAndClearDidGetRegistrations, |
308 weak_ptr_factory_.GetWeakPtr(), callback)); | 321 weak_ptr_factory_.GetWeakPtr(), callback)); |
309 } | 322 } |
310 | 323 |
311 void BackgroundSyncManager::DisableAndClearDidGetRegistrations( | 324 void BackgroundSyncManager::DisableAndClearDidGetRegistrations( |
312 const base::Closure& callback, | 325 const base::Closure& callback, |
313 const std::vector<std::pair<int64, std::string>>& user_data, | 326 const std::vector<std::pair<int64, std::string>>& user_data, |
314 ServiceWorkerStatusCode status) { | 327 ServiceWorkerStatusCode status) { |
| 328 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 329 |
315 if (status != SERVICE_WORKER_OK || user_data.empty()) { | 330 if (status != SERVICE_WORKER_OK || user_data.empty()) { |
316 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback)); | 331 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback)); |
317 return; | 332 return; |
318 } | 333 } |
319 | 334 |
320 base::Closure barrier_closure = | 335 base::Closure barrier_closure = |
321 base::BarrierClosure(user_data.size(), base::Bind(callback)); | 336 base::BarrierClosure(user_data.size(), base::Bind(callback)); |
322 | 337 |
323 for (const auto& sw_id_and_regs : user_data) { | 338 for (const auto& sw_id_and_regs : user_data) { |
324 service_worker_context_->ClearRegistrationUserData( | 339 service_worker_context_->ClearRegistrationUserData( |
325 sw_id_and_regs.first, kBackgroundSyncUserDataKey, | 340 sw_id_and_regs.first, kBackgroundSyncUserDataKey, |
326 base::Bind(&BackgroundSyncManager::DisableAndClearManagerClearedOne, | 341 base::Bind(&BackgroundSyncManager::DisableAndClearManagerClearedOne, |
327 weak_ptr_factory_.GetWeakPtr(), barrier_closure)); | 342 weak_ptr_factory_.GetWeakPtr(), barrier_closure)); |
328 } | 343 } |
329 } | 344 } |
330 | 345 |
331 void BackgroundSyncManager::DisableAndClearManagerClearedOne( | 346 void BackgroundSyncManager::DisableAndClearManagerClearedOne( |
332 const base::Closure& barrier_closure, | 347 const base::Closure& barrier_closure, |
333 ServiceWorkerStatusCode status) { | 348 ServiceWorkerStatusCode status) { |
| 349 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 350 |
334 // The status doesn't matter at this point, there is nothing else to be done. | 351 // The status doesn't matter at this point, there is nothing else to be done. |
335 base::MessageLoop::current()->PostTask(FROM_HERE, | 352 base::MessageLoop::current()->PostTask(FROM_HERE, |
336 base::Bind(barrier_closure)); | 353 base::Bind(barrier_closure)); |
337 } | 354 } |
338 | 355 |
339 BackgroundSyncManager::BackgroundSyncRegistration* | 356 BackgroundSyncManager::BackgroundSyncRegistration* |
340 BackgroundSyncManager::LookupRegistration( | 357 BackgroundSyncManager::LookupRegistration( |
341 int64 sw_registration_id, | 358 int64 sw_registration_id, |
342 const RegistrationKey& registration_key) { | 359 const RegistrationKey& registration_key) { |
| 360 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 361 |
343 SWIdToRegistrationsMap::iterator it = | 362 SWIdToRegistrationsMap::iterator it = |
344 sw_to_registrations_map_.find(sw_registration_id); | 363 sw_to_registrations_map_.find(sw_registration_id); |
345 if (it == sw_to_registrations_map_.end()) | 364 if (it == sw_to_registrations_map_.end()) |
346 return nullptr; | 365 return nullptr; |
347 | 366 |
348 BackgroundSyncRegistrations& registrations = it->second; | 367 BackgroundSyncRegistrations& registrations = it->second; |
349 DCHECK_LE(BackgroundSyncRegistration::kInitialId, registrations.next_id); | 368 DCHECK_LE(BackgroundSyncRegistration::kInitialId, registrations.next_id); |
350 DCHECK(!registrations.origin.is_empty()); | 369 DCHECK(!registrations.origin.is_empty()); |
351 | 370 |
352 auto key_and_registration_iter = | 371 auto key_and_registration_iter = |
353 registrations.registration_map.find(registration_key); | 372 registrations.registration_map.find(registration_key); |
354 if (key_and_registration_iter == registrations.registration_map.end()) | 373 if (key_and_registration_iter == registrations.registration_map.end()) |
355 return nullptr; | 374 return nullptr; |
356 | 375 |
357 return &key_and_registration_iter->second; | 376 return &key_and_registration_iter->second; |
358 } | 377 } |
359 | 378 |
360 void BackgroundSyncManager::StoreRegistrations( | 379 void BackgroundSyncManager::StoreRegistrations( |
361 int64 sw_registration_id, | 380 int64 sw_registration_id, |
362 const ServiceWorkerStorage::StatusCallback& callback) { | 381 const ServiceWorkerStorage::StatusCallback& callback) { |
| 382 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 383 |
363 // Serialize the data. | 384 // Serialize the data. |
364 const BackgroundSyncRegistrations& registrations = | 385 const BackgroundSyncRegistrations& registrations = |
365 sw_to_registrations_map_[sw_registration_id]; | 386 sw_to_registrations_map_[sw_registration_id]; |
366 BackgroundSyncRegistrationsProto registrations_proto; | 387 BackgroundSyncRegistrationsProto registrations_proto; |
367 registrations_proto.set_next_registration_id(registrations.next_id); | 388 registrations_proto.set_next_registration_id(registrations.next_id); |
368 registrations_proto.set_origin(registrations.origin.spec()); | 389 registrations_proto.set_origin(registrations.origin.spec()); |
369 | 390 |
370 for (const auto& key_and_registration : registrations.registration_map) { | 391 for (const auto& key_and_registration : registrations.registration_map) { |
371 const BackgroundSyncRegistration& registration = | 392 const BackgroundSyncRegistration& registration = |
372 key_and_registration.second; | 393 key_and_registration.second; |
373 BackgroundSyncRegistrationProto* registration_proto = | 394 BackgroundSyncRegistrationProto* registration_proto = |
374 registrations_proto.add_registration(); | 395 registrations_proto.add_registration(); |
375 registration_proto->set_id(registration.id); | 396 registration_proto->set_id(registration.id); |
376 registration_proto->set_tag(registration.tag); | 397 registration_proto->set_tag(registration.tag); |
377 registration_proto->set_periodicity(registration.periodicity); | 398 registration_proto->set_periodicity(registration.periodicity); |
378 registration_proto->set_min_period(registration.min_period); | 399 registration_proto->set_min_period(registration.min_period); |
379 registration_proto->set_network_state(registration.network_state); | 400 registration_proto->set_network_state(registration.network_state); |
380 registration_proto->set_power_state(registration.power_state); | 401 registration_proto->set_power_state(registration.power_state); |
| 402 registration_proto->set_sync_state(registration.sync_state); |
381 } | 403 } |
382 std::string serialized; | 404 std::string serialized; |
383 bool success = registrations_proto.SerializeToString(&serialized); | 405 bool success = registrations_proto.SerializeToString(&serialized); |
384 DCHECK(success); | 406 DCHECK(success); |
385 | 407 |
386 StoreDataInBackend(sw_registration_id, registrations.origin, | 408 StoreDataInBackend(sw_registration_id, registrations.origin, |
387 kBackgroundSyncUserDataKey, serialized, callback); | 409 kBackgroundSyncUserDataKey, serialized, callback); |
388 } | 410 } |
389 | 411 |
390 void BackgroundSyncManager::RegisterDidStore( | 412 void BackgroundSyncManager::RegisterDidStore( |
391 int64 sw_registration_id, | 413 int64 sw_registration_id, |
392 const BackgroundSyncRegistration& new_registration, | 414 const BackgroundSyncRegistration& new_registration, |
393 const StatusAndRegistrationCallback& callback, | 415 const StatusAndRegistrationCallback& callback, |
394 ServiceWorkerStatusCode status) { | 416 ServiceWorkerStatusCode status) { |
| 417 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 418 |
395 if (status == SERVICE_WORKER_ERROR_NOT_FOUND) { | 419 if (status == SERVICE_WORKER_ERROR_NOT_FOUND) { |
396 // The registration is gone. | 420 // The registration is gone. |
397 sw_to_registrations_map_.erase(sw_registration_id); | 421 sw_to_registrations_map_.erase(sw_registration_id); |
398 base::MessageLoop::current()->PostTask( | 422 base::MessageLoop::current()->PostTask( |
399 FROM_HERE, | 423 FROM_HERE, |
400 base::Bind(callback, ERROR_TYPE_STORAGE, BackgroundSyncRegistration())); | 424 base::Bind(callback, ERROR_TYPE_STORAGE, BackgroundSyncRegistration())); |
401 return; | 425 return; |
402 } | 426 } |
403 | 427 |
404 if (status != SERVICE_WORKER_OK) { | 428 if (status != SERVICE_WORKER_OK) { |
405 LOG(ERROR) << "BackgroundSync failed to store registration due to backend " | 429 LOG(ERROR) << "BackgroundSync failed to store registration due to backend " |
406 "failure."; | 430 "failure."; |
407 DisableAndClearManager( | 431 DisableAndClearManager( |
408 base::Bind(callback, ERROR_TYPE_STORAGE, BackgroundSyncRegistration())); | 432 base::Bind(callback, ERROR_TYPE_STORAGE, BackgroundSyncRegistration())); |
409 return; | 433 return; |
410 } | 434 } |
411 | 435 |
412 // TODO(jkarlin): Run the registration algorithm. | 436 FireReadyEvents(); |
413 base::MessageLoop::current()->PostTask( | 437 base::MessageLoop::current()->PostTask( |
414 FROM_HERE, base::Bind(callback, ERROR_TYPE_OK, new_registration)); | 438 FROM_HERE, base::Bind(callback, ERROR_TYPE_OK, new_registration)); |
415 } | 439 } |
416 | 440 |
417 void BackgroundSyncManager::RemoveRegistrationFromMap( | 441 void BackgroundSyncManager::RemoveRegistrationFromMap( |
418 int64 sw_registration_id, | 442 int64 sw_registration_id, |
419 const RegistrationKey& registration_key) { | 443 const RegistrationKey& registration_key) { |
| 444 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
420 DCHECK(LookupRegistration(sw_registration_id, registration_key)); | 445 DCHECK(LookupRegistration(sw_registration_id, registration_key)); |
421 | 446 |
422 BackgroundSyncRegistrations* registrations = | 447 BackgroundSyncRegistrations* registrations = |
423 &sw_to_registrations_map_[sw_registration_id]; | 448 &sw_to_registrations_map_[sw_registration_id]; |
424 | 449 |
425 registrations->registration_map.erase(registration_key); | 450 registrations->registration_map.erase(registration_key); |
426 } | 451 } |
427 | 452 |
428 void BackgroundSyncManager::AddRegistrationToMap( | 453 void BackgroundSyncManager::AddRegistrationToMap( |
429 int64 sw_registration_id, | 454 int64 sw_registration_id, |
430 const GURL& origin, | 455 const GURL& origin, |
431 const BackgroundSyncRegistration& sync_registration) { | 456 const BackgroundSyncRegistration& sync_registration) { |
| 457 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
432 DCHECK_NE(BackgroundSyncRegistration::kInvalidRegistrationId, | 458 DCHECK_NE(BackgroundSyncRegistration::kInvalidRegistrationId, |
433 sw_registration_id); | 459 sw_registration_id); |
434 | 460 |
435 BackgroundSyncRegistrations* registrations = | 461 BackgroundSyncRegistrations* registrations = |
436 &sw_to_registrations_map_[sw_registration_id]; | 462 &sw_to_registrations_map_[sw_registration_id]; |
437 registrations->origin = origin; | 463 registrations->origin = origin; |
438 | 464 |
439 RegistrationKey registration_key(sync_registration); | 465 RegistrationKey registration_key(sync_registration); |
440 registrations->registration_map[registration_key] = sync_registration; | 466 registrations->registration_map[registration_key] = sync_registration; |
441 } | 467 } |
442 | 468 |
443 void BackgroundSyncManager::StoreDataInBackend( | 469 void BackgroundSyncManager::StoreDataInBackend( |
444 int64 sw_registration_id, | 470 int64 sw_registration_id, |
445 const GURL& origin, | 471 const GURL& origin, |
446 const std::string& backend_key, | 472 const std::string& backend_key, |
447 const std::string& data, | 473 const std::string& data, |
448 const ServiceWorkerStorage::StatusCallback& callback) { | 474 const ServiceWorkerStorage::StatusCallback& callback) { |
| 475 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 476 |
449 service_worker_context_->StoreRegistrationUserData( | 477 service_worker_context_->StoreRegistrationUserData( |
450 sw_registration_id, origin, backend_key, data, callback); | 478 sw_registration_id, origin, backend_key, data, callback); |
451 } | 479 } |
452 | 480 |
453 void BackgroundSyncManager::GetDataFromBackend( | 481 void BackgroundSyncManager::GetDataFromBackend( |
454 const std::string& backend_key, | 482 const std::string& backend_key, |
455 const ServiceWorkerStorage::GetUserDataForAllRegistrationsCallback& | 483 const ServiceWorkerStorage::GetUserDataForAllRegistrationsCallback& |
456 callback) { | 484 callback) { |
457 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 485 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
458 | 486 |
459 service_worker_context_->GetUserDataForAllRegistrations(backend_key, | 487 service_worker_context_->GetUserDataForAllRegistrations(backend_key, |
460 callback); | 488 callback); |
461 } | 489 } |
462 | 490 |
| 491 void BackgroundSyncManager::FireOneShotSync( |
| 492 const scoped_refptr<ServiceWorkerVersion>& active_version, |
| 493 const ServiceWorkerVersion::StatusCallback& callback) { |
| 494 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 495 |
| 496 active_version->DispatchSyncEvent(callback); |
| 497 } |
| 498 |
463 void BackgroundSyncManager::UnregisterImpl( | 499 void BackgroundSyncManager::UnregisterImpl( |
464 int64 sw_registration_id, | 500 int64 sw_registration_id, |
465 const RegistrationKey& registration_key, | 501 const RegistrationKey& registration_key, |
466 BackgroundSyncRegistration::RegistrationId sync_registration_id, | 502 BackgroundSyncRegistration::RegistrationId sync_registration_id, |
467 const StatusCallback& callback) { | 503 const StatusCallback& callback) { |
| 504 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 505 |
468 if (disabled_) { | 506 if (disabled_) { |
469 base::MessageLoop::current()->PostTask( | 507 base::MessageLoop::current()->PostTask( |
470 FROM_HERE, base::Bind(callback, ERROR_TYPE_STORAGE)); | 508 FROM_HERE, base::Bind(callback, ERROR_TYPE_STORAGE)); |
471 return; | 509 return; |
472 } | 510 } |
473 | 511 |
474 const BackgroundSyncRegistration* existing_registration = | 512 const BackgroundSyncRegistration* existing_registration = |
475 LookupRegistration(sw_registration_id, registration_key); | 513 LookupRegistration(sw_registration_id, registration_key); |
476 if (!existing_registration || | 514 if (!existing_registration || |
477 existing_registration->id != sync_registration_id) { | 515 existing_registration->id != sync_registration_id) { |
478 base::MessageLoop::current()->PostTask( | 516 base::MessageLoop::current()->PostTask( |
479 FROM_HERE, base::Bind(callback, ERROR_TYPE_NOT_FOUND)); | 517 FROM_HERE, base::Bind(callback, ERROR_TYPE_NOT_FOUND)); |
480 return; | 518 return; |
481 } | 519 } |
482 | 520 |
483 RemoveRegistrationFromMap(sw_registration_id, registration_key); | 521 RemoveRegistrationFromMap(sw_registration_id, registration_key); |
484 | 522 |
485 StoreRegistrations( | 523 StoreRegistrations( |
486 sw_registration_id, | 524 sw_registration_id, |
487 base::Bind(&BackgroundSyncManager::UnregisterDidStore, | 525 base::Bind(&BackgroundSyncManager::UnregisterDidStore, |
488 weak_ptr_factory_.GetWeakPtr(), sw_registration_id, callback)); | 526 weak_ptr_factory_.GetWeakPtr(), sw_registration_id, callback)); |
489 } | 527 } |
490 | 528 |
491 void BackgroundSyncManager::UnregisterDidStore( | 529 void BackgroundSyncManager::UnregisterDidStore( |
492 int64 sw_registration_id, | 530 int64 sw_registration_id, |
493 const StatusCallback& callback, | 531 const StatusCallback& callback, |
494 ServiceWorkerStatusCode status) { | 532 ServiceWorkerStatusCode status) { |
| 533 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 534 |
495 if (status == SERVICE_WORKER_ERROR_NOT_FOUND) { | 535 if (status == SERVICE_WORKER_ERROR_NOT_FOUND) { |
496 // ServiceWorker was unregistered. | 536 // ServiceWorker was unregistered. |
497 sw_to_registrations_map_.erase(sw_registration_id); | 537 sw_to_registrations_map_.erase(sw_registration_id); |
498 base::MessageLoop::current()->PostTask( | 538 base::MessageLoop::current()->PostTask( |
499 FROM_HERE, base::Bind(callback, ERROR_TYPE_STORAGE)); | 539 FROM_HERE, base::Bind(callback, ERROR_TYPE_STORAGE)); |
500 return; | 540 return; |
501 } | 541 } |
502 | 542 |
503 if (status != SERVICE_WORKER_OK) { | 543 if (status != SERVICE_WORKER_OK) { |
504 LOG(ERROR) << "BackgroundSync failed to unregister due to backend failure."; | 544 LOG(ERROR) << "BackgroundSync failed to unregister due to backend failure."; |
505 DisableAndClearManager(base::Bind(callback, ERROR_TYPE_STORAGE)); | 545 DisableAndClearManager(base::Bind(callback, ERROR_TYPE_STORAGE)); |
506 return; | 546 return; |
507 } | 547 } |
508 | 548 |
509 // TODO(jkarlin): Run the registration algorithm. | |
510 base::MessageLoop::current()->PostTask(FROM_HERE, | 549 base::MessageLoop::current()->PostTask(FROM_HERE, |
511 base::Bind(callback, ERROR_TYPE_OK)); | 550 base::Bind(callback, ERROR_TYPE_OK)); |
512 } | 551 } |
513 | 552 |
514 void BackgroundSyncManager::GetRegistrationImpl( | 553 void BackgroundSyncManager::GetRegistrationImpl( |
515 int64 sw_registration_id, | 554 int64 sw_registration_id, |
516 const RegistrationKey& registration_key, | 555 const RegistrationKey& registration_key, |
517 const StatusAndRegistrationCallback& callback) { | 556 const StatusAndRegistrationCallback& callback) { |
| 557 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 558 |
518 if (disabled_) { | 559 if (disabled_) { |
519 base::MessageLoop::current()->PostTask( | 560 base::MessageLoop::current()->PostTask( |
520 FROM_HERE, | 561 FROM_HERE, |
521 base::Bind(callback, ERROR_TYPE_STORAGE, BackgroundSyncRegistration())); | 562 base::Bind(callback, ERROR_TYPE_STORAGE, BackgroundSyncRegistration())); |
522 return; | 563 return; |
523 } | 564 } |
524 | 565 |
525 const BackgroundSyncRegistration* out_registration = | 566 const BackgroundSyncRegistration* out_registration = |
526 LookupRegistration(sw_registration_id, registration_key); | 567 LookupRegistration(sw_registration_id, registration_key); |
527 if (!out_registration) { | 568 if (!out_registration) { |
528 base::MessageLoop::current()->PostTask( | 569 base::MessageLoop::current()->PostTask( |
529 FROM_HERE, base::Bind(callback, ERROR_TYPE_NOT_FOUND, | 570 FROM_HERE, base::Bind(callback, ERROR_TYPE_NOT_FOUND, |
530 BackgroundSyncRegistration())); | 571 BackgroundSyncRegistration())); |
531 return; | 572 return; |
532 } | 573 } |
533 | 574 |
534 base::MessageLoop::current()->PostTask( | 575 base::MessageLoop::current()->PostTask( |
535 FROM_HERE, base::Bind(callback, ERROR_TYPE_OK, *out_registration)); | 576 FROM_HERE, base::Bind(callback, ERROR_TYPE_OK, *out_registration)); |
536 } | 577 } |
537 | 578 |
| 579 bool BackgroundSyncManager::IsRegistrationReadyToFire( |
| 580 const BackgroundSyncRegistration& registration) { |
| 581 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 582 |
| 583 // TODO(jkarlin): Add support for firing periodic registrations. |
| 584 if (registration.periodicity == SYNC_PERIODIC) |
| 585 return false; |
| 586 |
| 587 if (registration.sync_state != SYNC_STATE_PENDING) |
| 588 return false; |
| 589 |
| 590 DCHECK_EQ(SYNC_ONE_SHOT, registration.periodicity); |
| 591 |
| 592 return network_observer_->NetworkSufficient(registration.network_state); |
| 593 } |
| 594 |
| 595 void BackgroundSyncManager::FireReadyEvents() { |
| 596 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 597 |
| 598 if (disabled_) |
| 599 return; |
| 600 |
| 601 op_scheduler_.ScheduleOperation( |
| 602 base::Bind(&BackgroundSyncManager::FireReadyEventsImpl, |
| 603 weak_ptr_factory_.GetWeakPtr(), MakeEmptyCompletion())); |
| 604 } |
| 605 |
| 606 void BackgroundSyncManager::FireReadyEventsImpl(const base::Closure& callback) { |
| 607 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 608 |
| 609 if (disabled_) { |
| 610 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback)); |
| 611 return; |
| 612 } |
| 613 |
| 614 // Find the registrations that are ready to run. |
| 615 std::vector<std::pair<int64, RegistrationKey>> sw_id_and_keys_to_fire; |
| 616 |
| 617 for (auto& sw_id_and_registrations : sw_to_registrations_map_) { |
| 618 const int64 service_worker_id = sw_id_and_registrations.first; |
| 619 for (auto& key_and_registration : |
| 620 sw_id_and_registrations.second.registration_map) { |
| 621 BackgroundSyncRegistration* registration = &key_and_registration.second; |
| 622 if (IsRegistrationReadyToFire(*registration)) { |
| 623 sw_id_and_keys_to_fire.push_back( |
| 624 std::make_pair(service_worker_id, key_and_registration.first)); |
| 625 // The state change is not saved to persistent storage because |
| 626 // if the sync event is killed mid-sync then it should return to |
| 627 // SYNC_STATE_PENDING. |
| 628 registration->sync_state = SYNC_STATE_FIRING; |
| 629 } |
| 630 } |
| 631 } |
| 632 |
| 633 // Fire the sync event of the ready registrations and run |callback| once |
| 634 // they're all done. |
| 635 base::Closure barrier_closure = |
| 636 base::BarrierClosure(sw_id_and_keys_to_fire.size(), base::Bind(callback)); |
| 637 |
| 638 for (const auto& sw_id_and_key : sw_id_and_keys_to_fire) { |
| 639 int64 service_worker_id = sw_id_and_key.first; |
| 640 const BackgroundSyncRegistration* registration = |
| 641 LookupRegistration(service_worker_id, sw_id_and_key.second); |
| 642 |
| 643 service_worker_context_->FindRegistrationForId( |
| 644 service_worker_id, sw_to_registrations_map_[service_worker_id].origin, |
| 645 base::Bind(&BackgroundSyncManager::FireReadyEventsDidFindRegistration, |
| 646 weak_ptr_factory_.GetWeakPtr(), sw_id_and_key.second, |
| 647 registration->id, barrier_closure)); |
| 648 } |
| 649 } |
| 650 |
| 651 void BackgroundSyncManager::FireReadyEventsDidFindRegistration( |
| 652 const RegistrationKey& registration_key, |
| 653 BackgroundSyncRegistration::RegistrationId registration_id, |
| 654 const base::Closure& callback, |
| 655 ServiceWorkerStatusCode service_worker_status, |
| 656 const scoped_refptr<ServiceWorkerRegistration>& |
| 657 service_worker_registration) { |
| 658 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 659 |
| 660 if (service_worker_status != SERVICE_WORKER_OK) { |
| 661 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback)); |
| 662 return; |
| 663 } |
| 664 |
| 665 FireOneShotSync( |
| 666 service_worker_registration->active_version(), |
| 667 base::Bind(&BackgroundSyncManager::EventComplete, |
| 668 weak_ptr_factory_.GetWeakPtr(), service_worker_registration, |
| 669 service_worker_registration->id(), registration_key, |
| 670 registration_id)); |
| 671 |
| 672 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback)); |
| 673 } |
| 674 |
| 675 // |service_worker_registration| is just to keep the registration alive |
| 676 // while the event is firing. |
| 677 void BackgroundSyncManager::EventComplete( |
| 678 const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration, |
| 679 int64 service_worker_id, |
| 680 const RegistrationKey& key, |
| 681 BackgroundSyncRegistration::RegistrationId sync_registration_id, |
| 682 ServiceWorkerStatusCode status_code) { |
| 683 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 684 |
| 685 if (disabled_) |
| 686 return; |
| 687 |
| 688 op_scheduler_.ScheduleOperation( |
| 689 base::Bind(&BackgroundSyncManager::EventCompleteImpl, |
| 690 weak_ptr_factory_.GetWeakPtr(), service_worker_id, key, |
| 691 sync_registration_id, status_code, MakeEmptyCompletion())); |
| 692 } |
| 693 |
| 694 void BackgroundSyncManager::EventCompleteImpl( |
| 695 int64 service_worker_id, |
| 696 const RegistrationKey& key, |
| 697 BackgroundSyncRegistration::RegistrationId sync_registration_id, |
| 698 ServiceWorkerStatusCode status_code, |
| 699 const base::Closure& callback) { |
| 700 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 701 |
| 702 if (disabled_) { |
| 703 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback)); |
| 704 return; |
| 705 } |
| 706 |
| 707 BackgroundSyncRegistration* registration = |
| 708 LookupRegistration(service_worker_id, key); |
| 709 if (!registration || registration->id != sync_registration_id) { |
| 710 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback)); |
| 711 return; |
| 712 } |
| 713 |
| 714 if (registration->periodicity == SYNC_ONE_SHOT) { |
| 715 if (status_code != SERVICE_WORKER_OK) { |
| 716 // TODO(jkarlin) Fire the sync event on the next page load controlled by |
| 717 // this registration. (crbug.com/479665) |
| 718 registration->sync_state = SYNC_STATE_FAILED; |
| 719 } else { |
| 720 registration = nullptr; |
| 721 RemoveRegistrationFromMap(service_worker_id, key); |
| 722 } |
| 723 } else { |
| 724 // TODO(jkarlin): Add support for running periodic syncs. (crbug.com/479674) |
| 725 NOTREACHED(); |
| 726 } |
| 727 |
| 728 StoreRegistrations( |
| 729 service_worker_id, |
| 730 base::Bind(&BackgroundSyncManager::EventCompleteDidStore, |
| 731 weak_ptr_factory_.GetWeakPtr(), service_worker_id, callback)); |
| 732 } |
| 733 |
| 734 void BackgroundSyncManager::EventCompleteDidStore( |
| 735 int64 service_worker_id, |
| 736 const base::Closure& callback, |
| 737 ServiceWorkerStatusCode status_code) { |
| 738 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 739 |
| 740 if (status_code == SERVICE_WORKER_ERROR_NOT_FOUND) { |
| 741 // The registration is gone. |
| 742 sw_to_registrations_map_.erase(service_worker_id); |
| 743 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback)); |
| 744 return; |
| 745 } |
| 746 |
| 747 if (status_code != SERVICE_WORKER_OK) { |
| 748 LOG(ERROR) << "BackgroundSync failed to store registration due to backend " |
| 749 "failure."; |
| 750 DisableAndClearManager(base::Bind(callback)); |
| 751 return; |
| 752 } |
| 753 |
| 754 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback)); |
| 755 } |
| 756 |
538 void BackgroundSyncManager::OnRegistrationDeletedImpl( | 757 void BackgroundSyncManager::OnRegistrationDeletedImpl( |
539 int64 registration_id, | 758 int64 registration_id, |
540 const base::Closure& callback) { | 759 const base::Closure& callback) { |
| 760 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 761 |
541 // The backend (ServiceWorkerStorage) will delete the data, so just delete the | 762 // The backend (ServiceWorkerStorage) will delete the data, so just delete the |
542 // memory representation here. | 763 // memory representation here. |
543 sw_to_registrations_map_.erase(registration_id); | 764 sw_to_registrations_map_.erase(registration_id); |
544 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback)); | 765 base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback)); |
545 } | 766 } |
546 | 767 |
547 void BackgroundSyncManager::OnStorageWipedImpl(const base::Closure& callback) { | 768 void BackgroundSyncManager::OnStorageWipedImpl(const base::Closure& callback) { |
| 769 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 770 |
548 sw_to_registrations_map_.clear(); | 771 sw_to_registrations_map_.clear(); |
549 disabled_ = false; | 772 disabled_ = false; |
550 InitImpl(callback); | 773 InitImpl(callback); |
551 } | 774 } |
552 | 775 |
553 void BackgroundSyncManager::OnNetworkChanged() { | 776 void BackgroundSyncManager::OnNetworkChanged() { |
554 // TODO(jkarlin): Run the scheduling algorithm here if initialized and not | 777 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
555 // disabled. | 778 |
| 779 FireReadyEvents(); |
556 } | 780 } |
557 | 781 |
558 void BackgroundSyncManager::PendingStatusAndRegistrationCallback( | 782 void BackgroundSyncManager::PendingStatusAndRegistrationCallback( |
559 const StatusAndRegistrationCallback& callback, | 783 const StatusAndRegistrationCallback& callback, |
560 ErrorType error, | 784 ErrorType error, |
561 const BackgroundSyncRegistration& sync_registration) { | 785 const BackgroundSyncRegistration& sync_registration) { |
| 786 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 787 |
562 // The callback might delete this object, so hang onto a weak ptr to find out. | 788 // The callback might delete this object, so hang onto a weak ptr to find out. |
563 base::WeakPtr<BackgroundSyncManager> manager = weak_ptr_factory_.GetWeakPtr(); | 789 base::WeakPtr<BackgroundSyncManager> manager = weak_ptr_factory_.GetWeakPtr(); |
564 callback.Run(error, sync_registration); | 790 callback.Run(error, sync_registration); |
565 if (manager) | 791 if (manager) |
566 op_scheduler_.CompleteOperationAndRunNext(); | 792 op_scheduler_.CompleteOperationAndRunNext(); |
567 } | 793 } |
568 | 794 |
569 void BackgroundSyncManager::PendingStatusCallback( | 795 void BackgroundSyncManager::PendingStatusCallback( |
570 const StatusCallback& callback, | 796 const StatusCallback& callback, |
571 ErrorType error) { | 797 ErrorType error) { |
| 798 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 799 |
572 // The callback might delete this object, so hang onto a weak ptr to find out. | 800 // The callback might delete this object, so hang onto a weak ptr to find out. |
573 base::WeakPtr<BackgroundSyncManager> manager = weak_ptr_factory_.GetWeakPtr(); | 801 base::WeakPtr<BackgroundSyncManager> manager = weak_ptr_factory_.GetWeakPtr(); |
574 callback.Run(error); | 802 callback.Run(error); |
575 if (manager) | 803 if (manager) |
576 op_scheduler_.CompleteOperationAndRunNext(); | 804 op_scheduler_.CompleteOperationAndRunNext(); |
577 } | 805 } |
578 | 806 |
579 void BackgroundSyncManager::PendingClosure(const base::Closure& callback) { | 807 void BackgroundSyncManager::PendingClosure(const base::Closure& callback) { |
| 808 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 809 |
580 // The callback might delete this object, so hang onto a weak ptr to find out. | 810 // The callback might delete this object, so hang onto a weak ptr to find out. |
581 base::WeakPtr<BackgroundSyncManager> manager = weak_ptr_factory_.GetWeakPtr(); | 811 base::WeakPtr<BackgroundSyncManager> manager = weak_ptr_factory_.GetWeakPtr(); |
582 callback.Run(); | 812 callback.Run(); |
583 if (manager) | 813 if (manager) |
584 op_scheduler_.CompleteOperationAndRunNext(); | 814 op_scheduler_.CompleteOperationAndRunNext(); |
585 } | 815 } |
586 | 816 |
587 base::Closure BackgroundSyncManager::MakeEmptyCompletion() { | 817 base::Closure BackgroundSyncManager::MakeEmptyCompletion() { |
| 818 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 819 |
588 return base::Bind(&BackgroundSyncManager::PendingClosure, | 820 return base::Bind(&BackgroundSyncManager::PendingClosure, |
589 weak_ptr_factory_.GetWeakPtr(), | 821 weak_ptr_factory_.GetWeakPtr(), |
590 base::Bind(base::DoNothing)); | 822 base::Bind(base::DoNothing)); |
591 } | 823 } |
592 | 824 |
593 BackgroundSyncManager::StatusAndRegistrationCallback | 825 BackgroundSyncManager::StatusAndRegistrationCallback |
594 BackgroundSyncManager::MakeStatusAndRegistrationCompletion( | 826 BackgroundSyncManager::MakeStatusAndRegistrationCompletion( |
595 const StatusAndRegistrationCallback& callback) { | 827 const StatusAndRegistrationCallback& callback) { |
| 828 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 829 |
596 return base::Bind( | 830 return base::Bind( |
597 &BackgroundSyncManager::PendingStatusAndRegistrationCallback, | 831 &BackgroundSyncManager::PendingStatusAndRegistrationCallback, |
598 weak_ptr_factory_.GetWeakPtr(), callback); | 832 weak_ptr_factory_.GetWeakPtr(), callback); |
599 } | 833 } |
600 | 834 |
601 BackgroundSyncManager::StatusCallback | 835 BackgroundSyncManager::StatusCallback |
602 BackgroundSyncManager::MakeStatusCompletion(const StatusCallback& callback) { | 836 BackgroundSyncManager::MakeStatusCompletion(const StatusCallback& callback) { |
| 837 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 838 |
603 return base::Bind(&BackgroundSyncManager::PendingStatusCallback, | 839 return base::Bind(&BackgroundSyncManager::PendingStatusCallback, |
604 weak_ptr_factory_.GetWeakPtr(), callback); | 840 weak_ptr_factory_.GetWeakPtr(), callback); |
605 } | 841 } |
606 | 842 |
607 } // namespace content | 843 } // namespace content |
OLD | NEW |