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 <algorithm>
8 #include <utility>
9 
10 #include "base/barrier_closure.h"
11 #include "base/bind.h"
12 #include "base/bind_helpers.h"
13 #include "base/callback_helpers.h"
14 #include "base/location.h"
15 #include "base/memory/ptr_util.h"
16 #include "base/single_thread_task_runner.h"
17 #include "base/task/post_task.h"
18 #include "base/threading/thread_task_runner_handle.h"
19 #include "base/time/default_clock.h"
20 #include "base/time/time.h"
21 #include "build/build_config.h"
22 #include "content/browser/background_sync/background_sync_metrics.h"
23 #include "content/browser/background_sync/background_sync_network_observer.h"
24 #include "content/browser/service_worker/embedded_worker_status.h"
25 #include "content/browser/service_worker/service_worker_context_wrapper.h"
26 #include "content/browser/service_worker/service_worker_storage.h"
27 #include "content/browser/storage_partition_impl.h"
28 #include "content/common/service_worker/service_worker_utils.h"
29 #include "content/public/browser/background_sync_controller.h"
30 #include "content/public/browser/browser_context.h"
31 #include "content/public/browser/browser_task_traits.h"
32 #include "content/public/browser/browser_thread.h"
33 #include "content/public/browser/permission_controller.h"
34 #include "content/public/browser/permission_type.h"
35 #include "third_party/blink/public/common/service_worker/service_worker_type_converters.h"
36 #include "third_party/blink/public/mojom/service_worker/service_worker.mojom.h"
37 #include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
38 #include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
39 
40 #if defined(OS_ANDROID)
41 #include "content/browser/android/background_sync_network_observer_android.h"
42 #include "content/browser/background_sync/background_sync_launcher.h"
43 #endif
44 
45 using blink::mojom::BackgroundSyncType;
46 using blink::mojom::PermissionStatus;
47 using SyncAndNotificationPermissions =
48     std::pair<PermissionStatus, PermissionStatus>;
49 
50 namespace content {
51 
52 // TODO(crbug.com/932591): Use blink::mojom::BackgroundSyncError
53 // directly and eliminate these checks.
54 #define COMPILE_ASSERT_MATCHING_ENUM(mojo_name, manager_name) \
55   static_assert(static_cast<int>(blink::mojo_name) ==         \
56                     static_cast<int>(content::manager_name),  \
57                 "mojo and manager enums must match")
58 
59 COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::NONE,
60                              BACKGROUND_SYNC_STATUS_OK);
61 COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::STORAGE,
62                              BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
63 COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::NOT_FOUND,
64                              BACKGROUND_SYNC_STATUS_NOT_FOUND);
65 COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::NO_SERVICE_WORKER,
66                              BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER);
67 COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::NOT_ALLOWED,
68                              BACKGROUND_SYNC_STATUS_NOT_ALLOWED);
69 COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::PERMISSION_DENIED,
70                              BACKGROUND_SYNC_STATUS_PERMISSION_DENIED);
71 COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::MAX,
72                              BACKGROUND_SYNC_STATUS_PERMISSION_DENIED);
73 
74 namespace {
75 
76 // The only allowed value of min_interval for one shot Background Sync
77 // registrations.
78 constexpr int kMinIntervalForOneShotSync = -1;
79 
80 // The key used to index the background sync data in ServiceWorkerStorage.
81 const char kBackgroundSyncUserDataKey[] = "BackgroundSyncUserData";
82 
RecordFailureAndPostError(BackgroundSyncType sync_type,BackgroundSyncStatus status,BackgroundSyncManager::StatusAndRegistrationCallback callback)83 void RecordFailureAndPostError(
84     BackgroundSyncType sync_type,
85     BackgroundSyncStatus status,
86     BackgroundSyncManager::StatusAndRegistrationCallback callback) {
87   BackgroundSyncMetrics::CountRegisterFailure(sync_type, status);
88 
89   base::ThreadTaskRunnerHandle::Get()->PostTask(
90       FROM_HERE, base::BindOnce(std::move(callback), status, nullptr));
91 }
92 
93 // Returns nullptr if the browser context cannot be accessed for any reason.
GetBrowserContextOnUIThread(scoped_refptr<ServiceWorkerContextWrapper> service_worker_context)94 BrowserContext* GetBrowserContextOnUIThread(
95     scoped_refptr<ServiceWorkerContextWrapper> service_worker_context) {
96   DCHECK_CURRENTLY_ON(BrowserThread::UI);
97 
98   if (!service_worker_context)
99     return nullptr;
100   StoragePartitionImpl* storage_partition_impl =
101       service_worker_context->storage_partition();
102   if (!storage_partition_impl)  // may be null in tests
103     return nullptr;
104 
105   return storage_partition_impl->browser_context();
106 }
107 
108 // Returns nullptr if the controller cannot be accessed for any reason.
GetBackgroundSyncControllerOnUIThread(scoped_refptr<ServiceWorkerContextWrapper> service_worker_context)109 BackgroundSyncController* GetBackgroundSyncControllerOnUIThread(
110     scoped_refptr<ServiceWorkerContextWrapper> service_worker_context) {
111   DCHECK_CURRENTLY_ON(BrowserThread::UI);
112 
113   BrowserContext* browser_context =
114       GetBrowserContextOnUIThread(std::move(service_worker_context));
115   if (!browser_context)
116     return nullptr;
117 
118   return browser_context->GetBackgroundSyncController();
119 }
120 
GetBackgroundSyncPermissionOnUIThread(scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,const url::Origin & origin,BackgroundSyncType sync_type)121 SyncAndNotificationPermissions GetBackgroundSyncPermissionOnUIThread(
122     scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
123     const url::Origin& origin,
124     BackgroundSyncType sync_type) {
125   DCHECK_CURRENTLY_ON(BrowserThread::UI);
126 
127   BrowserContext* browser_context =
128       GetBrowserContextOnUIThread(std::move(service_worker_context));
129   if (!browser_context)
130     return {PermissionStatus::DENIED, PermissionStatus::DENIED};
131 
132   PermissionController* permission_controller =
133       BrowserContext::GetPermissionController(browser_context);
134   DCHECK(permission_controller);
135 
136   // The requesting origin always matches the embedding origin.
137   GURL origin_url = origin.GetURL();
138   auto sync_permission = permission_controller->GetPermissionStatus(
139       sync_type == BackgroundSyncType::ONE_SHOT
140           ? PermissionType::BACKGROUND_SYNC
141           : PermissionType::PERIODIC_BACKGROUND_SYNC,
142       origin_url, origin_url);
143   auto notification_permission = permission_controller->GetPermissionStatus(
144       PermissionType::NOTIFICATIONS, origin_url, origin_url);
145   return {sync_permission, notification_permission};
146 }
147 
NotifyOneShotBackgroundSyncRegisteredOnUIThread(scoped_refptr<ServiceWorkerContextWrapper> sw_context_wrapper,const url::Origin & origin,bool can_fire,bool is_reregistered)148 void NotifyOneShotBackgroundSyncRegisteredOnUIThread(
149     scoped_refptr<ServiceWorkerContextWrapper> sw_context_wrapper,
150     const url::Origin& origin,
151     bool can_fire,
152     bool is_reregistered) {
153   DCHECK_CURRENTLY_ON(BrowserThread::UI);
154 
155   BackgroundSyncController* background_sync_controller =
156       GetBackgroundSyncControllerOnUIThread(std::move(sw_context_wrapper));
157 
158   if (!background_sync_controller)
159     return;
160 
161   background_sync_controller->NotifyOneShotBackgroundSyncRegistered(
162       origin, can_fire, is_reregistered);
163 }
164 
NotifyPeriodicBackgroundSyncRegisteredOnUIThread(scoped_refptr<ServiceWorkerContextWrapper> sw_context_wrapper,const url::Origin & origin,int min_interval,bool is_reregistered)165 void NotifyPeriodicBackgroundSyncRegisteredOnUIThread(
166     scoped_refptr<ServiceWorkerContextWrapper> sw_context_wrapper,
167     const url::Origin& origin,
168     int min_interval,
169     bool is_reregistered) {
170   DCHECK_CURRENTLY_ON(BrowserThread::UI);
171   BackgroundSyncController* background_sync_controller =
172       GetBackgroundSyncControllerOnUIThread(std::move(sw_context_wrapper));
173 
174   if (!background_sync_controller)
175     return;
176 
177   background_sync_controller->NotifyPeriodicBackgroundSyncRegistered(
178       origin, min_interval, is_reregistered);
179 }
180 
NotifyOneShotBackgroundSyncCompletedOnUIThread(scoped_refptr<ServiceWorkerContextWrapper> sw_context_wrapper,const url::Origin & origin,blink::ServiceWorkerStatusCode status_code,int num_attempts,int max_attempts)181 void NotifyOneShotBackgroundSyncCompletedOnUIThread(
182     scoped_refptr<ServiceWorkerContextWrapper> sw_context_wrapper,
183     const url::Origin& origin,
184     blink::ServiceWorkerStatusCode status_code,
185     int num_attempts,
186     int max_attempts) {
187   DCHECK_CURRENTLY_ON(BrowserThread::UI);
188 
189   BackgroundSyncController* background_sync_controller =
190       GetBackgroundSyncControllerOnUIThread(std::move(sw_context_wrapper));
191 
192   if (!background_sync_controller)
193     return;
194 
195   background_sync_controller->NotifyOneShotBackgroundSyncCompleted(
196       origin, status_code, num_attempts, max_attempts);
197 }
198 
NotifyPeriodicBackgroundSyncCompletedOnUIThread(scoped_refptr<ServiceWorkerContextWrapper> sw_context_wrapper,const url::Origin & origin,blink::ServiceWorkerStatusCode status_code,int num_attempts,int max_attempts)199 void NotifyPeriodicBackgroundSyncCompletedOnUIThread(
200     scoped_refptr<ServiceWorkerContextWrapper> sw_context_wrapper,
201     const url::Origin& origin,
202     blink::ServiceWorkerStatusCode status_code,
203     int num_attempts,
204     int max_attempts) {
205   DCHECK_CURRENTLY_ON(BrowserThread::UI);
206 
207   BackgroundSyncController* background_sync_controller =
208       GetBackgroundSyncControllerOnUIThread(std::move(sw_context_wrapper));
209 
210   if (!background_sync_controller)
211     return;
212 
213   background_sync_controller->NotifyPeriodicBackgroundSyncCompleted(
214       origin, status_code, num_attempts, max_attempts);
215 }
216 
GetControllerParameters(scoped_refptr<ServiceWorkerContextWrapper> sw_context_wrapper,std::unique_ptr<BackgroundSyncParameters> parameters)217 std::unique_ptr<BackgroundSyncParameters> GetControllerParameters(
218     scoped_refptr<ServiceWorkerContextWrapper> sw_context_wrapper,
219     std::unique_ptr<BackgroundSyncParameters> parameters) {
220   DCHECK_CURRENTLY_ON(BrowserThread::UI);
221 
222   BackgroundSyncController* background_sync_controller =
223       GetBackgroundSyncControllerOnUIThread(sw_context_wrapper);
224 
225   if (!background_sync_controller) {
226     // If there is no controller then BackgroundSync can't run in the
227     // background, disable it.
228     parameters->disable = true;
229     return parameters;
230   }
231 
232   background_sync_controller->GetParameterOverrides(parameters.get());
233   return parameters;
234 }
235 
GetNextEventDelay(scoped_refptr<ServiceWorkerContextWrapper> sw_context_wrapper,const BackgroundSyncRegistration & registration,std::unique_ptr<BackgroundSyncParameters> parameters,base::TimeDelta time_till_soonest_scheduled_event_for_origin)236 base::TimeDelta GetNextEventDelay(
237     scoped_refptr<ServiceWorkerContextWrapper> sw_context_wrapper,
238     const BackgroundSyncRegistration& registration,
239     std::unique_ptr<BackgroundSyncParameters> parameters,
240     base::TimeDelta time_till_soonest_scheduled_event_for_origin) {
241   DCHECK_CURRENTLY_ON(BrowserThread::UI);
242 
243   BackgroundSyncController* background_sync_controller =
244       GetBackgroundSyncControllerOnUIThread(sw_context_wrapper);
245 
246   if (!background_sync_controller)
247     return base::TimeDelta::Max();
248 
249   return background_sync_controller->GetNextEventDelay(
250       registration, parameters.get(),
251       time_till_soonest_scheduled_event_for_origin);
252 }
253 
OnSyncEventFinished(scoped_refptr<ServiceWorkerVersion> active_version,int request_id,ServiceWorkerVersion::StatusCallback callback,blink::mojom::ServiceWorkerEventStatus status)254 void OnSyncEventFinished(scoped_refptr<ServiceWorkerVersion> active_version,
255                          int request_id,
256                          ServiceWorkerVersion::StatusCallback callback,
257                          blink::mojom::ServiceWorkerEventStatus status) {
258   if (!active_version->FinishRequest(
259           request_id,
260           status == blink::mojom::ServiceWorkerEventStatus::COMPLETED)) {
261     return;
262   }
263   std::move(callback).Run(
264       mojo::ConvertTo<blink::ServiceWorkerStatusCode>(status));
265 }
266 
DidStartWorkerForSyncEvent(base::OnceCallback<void (ServiceWorkerVersion::StatusCallback)> task,ServiceWorkerVersion::StatusCallback callback,blink::ServiceWorkerStatusCode start_worker_status)267 void DidStartWorkerForSyncEvent(
268     base::OnceCallback<void(ServiceWorkerVersion::StatusCallback)> task,
269     ServiceWorkerVersion::StatusCallback callback,
270     blink::ServiceWorkerStatusCode start_worker_status) {
271   if (start_worker_status != blink::ServiceWorkerStatusCode::kOk) {
272     std::move(callback).Run(start_worker_status);
273     return;
274   }
275   std::move(task).Run(std::move(callback));
276 }
277 
GetBackgroundSyncType(const blink::mojom::SyncRegistrationOptions & options)278 BackgroundSyncType GetBackgroundSyncType(
279     const blink::mojom::SyncRegistrationOptions& options) {
280   return options.min_interval == -1 ? BackgroundSyncType::ONE_SHOT
281                                     : BackgroundSyncType::PERIODIC;
282 }
283 
GetSyncEventName(const BackgroundSyncType sync_type)284 std::string GetSyncEventName(const BackgroundSyncType sync_type) {
285   if (sync_type == BackgroundSyncType::ONE_SHOT)
286     return "sync";
287   else
288     return "periodicsync";
289 }
290 
GetDevToolsBackgroundService(BackgroundSyncType sync_type)291 DevToolsBackgroundService GetDevToolsBackgroundService(
292     BackgroundSyncType sync_type) {
293   if (sync_type == BackgroundSyncType::ONE_SHOT)
294     return DevToolsBackgroundService::kBackgroundSync;
295   else
296     return DevToolsBackgroundService::kPeriodicBackgroundSync;
297 }
298 
GetDelayAsString(base::TimeDelta delay)299 std::string GetDelayAsString(base::TimeDelta delay) {
300   if (delay.is_max())
301     return "infinite";
302   return base::NumberToString(delay.InMilliseconds());
303 }
304 
GetEventStatusString(blink::ServiceWorkerStatusCode status_code)305 std::string GetEventStatusString(blink::ServiceWorkerStatusCode status_code) {
306   // The |status_code| is derived from blink::mojom::ServiceWorkerEventStatus.
307   switch (status_code) {
308     case blink::ServiceWorkerStatusCode::kOk:
309       return "succeeded";
310     case blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected:
311       return "waitUntil rejected";
312     case blink::ServiceWorkerStatusCode::kErrorAbort:
313       return "aborted";
314     case blink::ServiceWorkerStatusCode::kErrorTimeout:
315       return "timeout";
316     default:
317       NOTREACHED();
318       return "unknown error";
319   }
320 }
321 
GetNumAttemptsAfterEvent(BackgroundSyncType sync_type,int current_num_attempts,int max_attempts,blink::mojom::BackgroundSyncState sync_state,bool succeeded)322 int GetNumAttemptsAfterEvent(BackgroundSyncType sync_type,
323                              int current_num_attempts,
324                              int max_attempts,
325                              blink::mojom::BackgroundSyncState sync_state,
326                              bool succeeded) {
327   int num_attempts = ++current_num_attempts;
328 
329   if (sync_type == BackgroundSyncType::PERIODIC) {
330     if (succeeded)
331       return 0;
332     if (num_attempts == max_attempts)
333       return 0;
334   }
335 
336   if (sync_state ==
337       blink::mojom::BackgroundSyncState::REREGISTERED_WHILE_FIRING) {
338     return 0;
339   }
340 
341   return num_attempts;
342 }
343 
344 // This prevents the browser process from shutting down when the last browser
345 // window is closed and there are one-shot Background Sync events ready to fire.
346 std::unique_ptr<BackgroundSyncController::BackgroundSyncEventKeepAlive>
CreateBackgroundSyncEventKeepAliveOnUIThread(scoped_refptr<ServiceWorkerContextWrapper> sw_context_wrapper,const blink::mojom::BackgroundSyncRegistrationInfo & registration_info)347 CreateBackgroundSyncEventKeepAliveOnUIThread(
348     scoped_refptr<ServiceWorkerContextWrapper> sw_context_wrapper,
349     const blink::mojom::BackgroundSyncRegistrationInfo& registration_info) {
350   DCHECK_CURRENTLY_ON(BrowserThread::UI);
351 
352   BackgroundSyncController* controller =
353       GetBackgroundSyncControllerOnUIThread(sw_context_wrapper);
354   if (!controller ||
355       registration_info.sync_type != BackgroundSyncType::ONE_SHOT) {
356     return nullptr;
357   }
358 
359   return controller->CreateBackgroundSyncEventKeepAlive();
360 }
361 
362 }  // namespace
363 
364 BackgroundSyncManager::BackgroundSyncRegistrations::
365     BackgroundSyncRegistrations() = default;
366 
367 BackgroundSyncManager::BackgroundSyncRegistrations::BackgroundSyncRegistrations(
368     const BackgroundSyncRegistrations& other) = default;
369 
370 BackgroundSyncManager::BackgroundSyncRegistrations::
371     ~BackgroundSyncRegistrations() = default;
372 
373 // static
Create(scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,scoped_refptr<DevToolsBackgroundServicesContextImpl> devtools_context)374 std::unique_ptr<BackgroundSyncManager> BackgroundSyncManager::Create(
375     scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
376     scoped_refptr<DevToolsBackgroundServicesContextImpl> devtools_context) {
377   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
378 
379   BackgroundSyncManager* sync_manager = new BackgroundSyncManager(
380       std::move(service_worker_context), std::move(devtools_context));
381   sync_manager->Init();
382   return base::WrapUnique(sync_manager);
383 }
384 
~BackgroundSyncManager()385 BackgroundSyncManager::~BackgroundSyncManager() {
386   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
387   service_worker_context_->RemoveObserver(this);
388 }
389 
Register(int64_t sw_registration_id,blink::mojom::SyncRegistrationOptions options,StatusAndRegistrationCallback callback)390 void BackgroundSyncManager::Register(
391     int64_t sw_registration_id,
392     blink::mojom::SyncRegistrationOptions options,
393     StatusAndRegistrationCallback callback) {
394   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
395 
396   if (disabled_) {
397     RecordFailureAndPostError(GetBackgroundSyncType(options),
398                               BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
399                               std::move(callback));
400     return;
401   }
402 
403   DCHECK(options.min_interval >= 0 ||
404          options.min_interval == kMinIntervalForOneShotSync);
405 
406   auto id = op_scheduler_.CreateId();
407   op_scheduler_.ScheduleOperation(
408       id, CacheStorageSchedulerMode::kExclusive,
409       CacheStorageSchedulerOp::kBackgroundSync,
410       CacheStorageSchedulerPriority::kNormal,
411       base::BindOnce(
412           &BackgroundSyncManager::RegisterCheckIfHasMainFrame,
413           weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
414           std::move(options),
415           op_scheduler_.WrapCallbackToRunNext(id, std::move(callback))));
416 }
417 
UnregisterPeriodicSync(int64_t sw_registration_id,const std::string & tag,BackgroundSyncManager::StatusCallback callback)418 void BackgroundSyncManager::UnregisterPeriodicSync(
419     int64_t sw_registration_id,
420     const std::string& tag,
421     BackgroundSyncManager::StatusCallback callback) {
422   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
423 
424   if (disabled_) {
425     base::ThreadTaskRunnerHandle::Get()->PostTask(
426         FROM_HERE, base::BindOnce(std::move(callback),
427                                   BACKGROUND_SYNC_STATUS_STORAGE_ERROR));
428     return;
429   }
430 
431   auto id = op_scheduler_.CreateId();
432   op_scheduler_.ScheduleOperation(
433       id, CacheStorageSchedulerMode::kExclusive,
434       CacheStorageSchedulerOp::kBackgroundSync,
435       CacheStorageSchedulerPriority::kNormal,
436       base::BindOnce(
437           &BackgroundSyncManager::UnregisterPeriodicSyncImpl,
438           weak_ptr_factory_.GetWeakPtr(), sw_registration_id, tag,
439           op_scheduler_.WrapCallbackToRunNext(id, std::move(callback))));
440 }
441 
DidResolveRegistration(blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info)442 void BackgroundSyncManager::DidResolveRegistration(
443     blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info) {
444   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
445 
446   if (disabled_)
447     return;
448   auto id = op_scheduler_.CreateId();
449   op_scheduler_.ScheduleOperation(
450       id, CacheStorageSchedulerMode::kExclusive,
451       CacheStorageSchedulerOp::kBackgroundSync,
452       CacheStorageSchedulerPriority::kNormal,
453       base::BindOnce(&BackgroundSyncManager::DidResolveRegistrationImpl,
454                      weak_ptr_factory_.GetWeakPtr(),
455                      std::move(registration_info), id));
456 }
457 
GetOneShotSyncRegistrations(int64_t sw_registration_id,StatusAndRegistrationsCallback callback)458 void BackgroundSyncManager::GetOneShotSyncRegistrations(
459     int64_t sw_registration_id,
460     StatusAndRegistrationsCallback callback) {
461   GetRegistrations(BackgroundSyncType::ONE_SHOT, sw_registration_id,
462                    std::move(callback));
463 }
464 
GetPeriodicSyncRegistrations(int64_t sw_registration_id,StatusAndRegistrationsCallback callback)465 void BackgroundSyncManager::GetPeriodicSyncRegistrations(
466     int64_t sw_registration_id,
467     StatusAndRegistrationsCallback callback) {
468   GetRegistrations(BackgroundSyncType::PERIODIC, sw_registration_id,
469                    std::move(callback));
470 }
471 
UnregisterPeriodicSyncForOrigin(const url::Origin & origin)472 void BackgroundSyncManager::UnregisterPeriodicSyncForOrigin(
473     const url::Origin& origin) {
474   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
475 
476   auto id = op_scheduler_.CreateId();
477   op_scheduler_.ScheduleOperation(
478       id, CacheStorageSchedulerMode::kExclusive,
479       CacheStorageSchedulerOp::kBackgroundSync,
480       CacheStorageSchedulerPriority::kNormal,
481       base::BindOnce(&BackgroundSyncManager::UnregisterForOriginImpl,
482                      weak_ptr_factory_.GetWeakPtr(), std::move(origin),
483                      MakeEmptyCompletion(id)));
484 }
485 
UnregisterForOriginImpl(const url::Origin & origin,base::OnceClosure callback)486 void BackgroundSyncManager::UnregisterForOriginImpl(
487     const url::Origin& origin,
488     base::OnceClosure callback) {
489   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
490 
491   if (disabled_) {
492     base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
493                                                   std::move(callback));
494     return;
495   }
496 
497   std::vector<int64_t> service_worker_registrations_affected;
498 
499   for (const auto& service_worker_and_registration : active_registrations_) {
500     const auto registrations = service_worker_and_registration.second;
501     if (registrations.origin != origin)
502       continue;
503 
504     service_worker_registrations_affected.emplace_back(
505         service_worker_and_registration.first);
506   }
507 
508   for (auto service_worker_registration_id :
509        service_worker_registrations_affected) {
510     active_registrations_.erase(service_worker_registration_id);
511   }
512 
513   if (service_worker_registrations_affected.empty()) {
514     base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
515                                                   std::move(callback));
516     return;
517   }
518 
519   base::RepeatingClosure barrier_closure = base::BarrierClosure(
520       service_worker_registrations_affected.size(),
521       base::BindOnce(
522           &BackgroundSyncManager::UnregisterForOriginScheduleDelayedProcessing,
523           weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
524 
525   for (int64_t service_worker_registration_id :
526        service_worker_registrations_affected) {
527     StoreRegistrations(
528         service_worker_registration_id,
529         base::BindOnce(&BackgroundSyncManager::UnregisterForOriginDidStore,
530                        weak_ptr_factory_.GetWeakPtr(), barrier_closure));
531   }
532 }
533 
UnregisterForOriginDidStore(base::OnceClosure done_closure,blink::ServiceWorkerStatusCode status)534 void BackgroundSyncManager::UnregisterForOriginDidStore(
535     base::OnceClosure done_closure,
536     blink::ServiceWorkerStatusCode status) {
537   if (status == blink::ServiceWorkerStatusCode::kErrorNotFound) {
538     // The service worker registration is gone.
539     std::move(done_closure).Run();
540     return;
541   }
542 
543   if (status != blink::ServiceWorkerStatusCode::kOk) {
544     DisableAndClearManager(std::move(done_closure));
545     return;
546   }
547 
548   std::move(done_closure).Run();
549 }
550 
UnregisterForOriginScheduleDelayedProcessing(base::OnceClosure callback)551 void BackgroundSyncManager::UnregisterForOriginScheduleDelayedProcessing(
552     base::OnceClosure callback) {
553   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
554   ScheduleOrCancelDelayedProcessing(BackgroundSyncType::PERIODIC);
555   base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(callback));
556 }
557 
GetRegistrations(BackgroundSyncType sync_type,int64_t sw_registration_id,StatusAndRegistrationsCallback callback)558 void BackgroundSyncManager::GetRegistrations(
559     BackgroundSyncType sync_type,
560     int64_t sw_registration_id,
561     StatusAndRegistrationsCallback callback) {
562   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
563 
564   if (disabled_) {
565     base::ThreadTaskRunnerHandle::Get()->PostTask(
566         FROM_HERE,
567         base::BindOnce(
568             std::move(callback), BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
569             std::vector<std::unique_ptr<BackgroundSyncRegistration>>()));
570     return;
571   }
572 
573   auto id = op_scheduler_.CreateId();
574   op_scheduler_.ScheduleOperation(
575       id, CacheStorageSchedulerMode::kExclusive,
576       CacheStorageSchedulerOp::kBackgroundSync,
577       CacheStorageSchedulerPriority::kNormal,
578       base::BindOnce(
579           &BackgroundSyncManager::GetRegistrationsImpl,
580           weak_ptr_factory_.GetWeakPtr(), sync_type, sw_registration_id,
581           op_scheduler_.WrapCallbackToRunNext(id, std::move(callback))));
582 }
583 
OnRegistrationDeleted(int64_t sw_registration_id,const GURL & pattern)584 void BackgroundSyncManager::OnRegistrationDeleted(int64_t sw_registration_id,
585                                                   const GURL& pattern) {
586   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
587 
588   // Operations already in the queue will either fail when they write to storage
589   // or return stale results based on registrations loaded in memory. This is
590   // inconsequential since the service worker is gone.
591   auto id = op_scheduler_.CreateId();
592   op_scheduler_.ScheduleOperation(
593       id, CacheStorageSchedulerMode::kExclusive,
594       CacheStorageSchedulerOp::kBackgroundSync,
595       CacheStorageSchedulerPriority::kNormal,
596       base::BindOnce(&BackgroundSyncManager::OnRegistrationDeletedImpl,
597                      weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
598                      MakeEmptyCompletion(id)));
599 }
600 
OnStorageWiped()601 void BackgroundSyncManager::OnStorageWiped() {
602   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
603 
604   // Operations already in the queue will either fail when they write to storage
605   // or return stale results based on registrations loaded in memory. This is
606   // inconsequential since the service workers are gone.
607   auto id = op_scheduler_.CreateId();
608   op_scheduler_.ScheduleOperation(
609       id, CacheStorageSchedulerMode::kExclusive,
610       CacheStorageSchedulerOp::kBackgroundSync,
611       CacheStorageSchedulerPriority::kNormal,
612       base::BindOnce(&BackgroundSyncManager::OnStorageWipedImpl,
613                      weak_ptr_factory_.GetWeakPtr(), MakeEmptyCompletion(id)));
614 }
615 
EmulateDispatchSyncEvent(const std::string & tag,scoped_refptr<ServiceWorkerVersion> active_version,bool last_chance,ServiceWorkerVersion::StatusCallback callback)616 void BackgroundSyncManager::EmulateDispatchSyncEvent(
617     const std::string& tag,
618     scoped_refptr<ServiceWorkerVersion> active_version,
619     bool last_chance,
620     ServiceWorkerVersion::StatusCallback callback) {
621   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
622   blink::ServiceWorkerStatusCode code = CanEmulateSyncEvent(active_version);
623   if (code != blink::ServiceWorkerStatusCode::kOk) {
624     std::move(callback).Run(code);
625     return;
626   }
627 
628   DispatchSyncEvent(tag, std::move(active_version), last_chance,
629                     std::move(callback));
630 }
631 
EmulateDispatchPeriodicSyncEvent(const std::string & tag,scoped_refptr<ServiceWorkerVersion> active_version,ServiceWorkerVersion::StatusCallback callback)632 void BackgroundSyncManager::EmulateDispatchPeriodicSyncEvent(
633     const std::string& tag,
634     scoped_refptr<ServiceWorkerVersion> active_version,
635     ServiceWorkerVersion::StatusCallback callback) {
636   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
637   blink::ServiceWorkerStatusCode code = CanEmulateSyncEvent(active_version);
638   if (code != blink::ServiceWorkerStatusCode::kOk) {
639     std::move(callback).Run(code);
640     return;
641   }
642 
643   DispatchPeriodicSyncEvent(tag, std::move(active_version),
644                             std::move(callback));
645 }
646 
EmulateServiceWorkerOffline(int64_t service_worker_id,bool is_offline)647 void BackgroundSyncManager::EmulateServiceWorkerOffline(
648     int64_t service_worker_id,
649     bool is_offline) {
650   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
651   // Multiple DevTools sessions may want to set the same SW offline, which
652   // is supposed to disable the background sync. For consistency with the
653   // network stack, SW remains offline until all DevTools sessions disable
654   // the offline mode.
655   emulated_offline_sw_[service_worker_id] += is_offline ? 1 : -1;
656   if (emulated_offline_sw_[service_worker_id] > 0)
657     return;
658   emulated_offline_sw_.erase(service_worker_id);
659   FireReadyEvents(BackgroundSyncType::ONE_SHOT, /* reschedule= */ true,
660                   base::DoNothing::Once());
661 }
662 
BackgroundSyncManager(scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,scoped_refptr<DevToolsBackgroundServicesContextImpl> devtools_context)663 BackgroundSyncManager::BackgroundSyncManager(
664     scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
665     scoped_refptr<DevToolsBackgroundServicesContextImpl> devtools_context)
666     : op_scheduler_(CacheStorageSchedulerClient::kBackgroundSync,
667                     base::ThreadTaskRunnerHandle::Get()),
668       service_worker_context_(std::move(service_worker_context)),
669       proxy_(std::make_unique<BackgroundSyncProxy>(service_worker_context_)),
670       devtools_context_(std::move(devtools_context)),
671       parameters_(std::make_unique<BackgroundSyncParameters>()),
672       disabled_(false),
673       num_firing_registrations_one_shot_(0),
674       num_firing_registrations_periodic_(0),
675       clock_(base::DefaultClock::GetInstance()) {
676   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
677   DCHECK(devtools_context_);
678   DCHECK(service_worker_context_);
679 
680   service_worker_context_->AddObserver(this);
681 
682 #if defined(OS_ANDROID)
683   network_observer_ = std::make_unique<BackgroundSyncNetworkObserverAndroid>(
684       base::BindRepeating(&BackgroundSyncManager::OnNetworkChanged,
685                           weak_ptr_factory_.GetWeakPtr()));
686 #else
687   network_observer_ = std::make_unique<BackgroundSyncNetworkObserver>(
688       base::BindRepeating(&BackgroundSyncManager::OnNetworkChanged,
689                           weak_ptr_factory_.GetWeakPtr()));
690 #endif
691 }
692 
Init()693 void BackgroundSyncManager::Init() {
694   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
695   DCHECK(!op_scheduler_.ScheduledOperations());
696   DCHECK(!disabled_);
697 
698   auto id = op_scheduler_.CreateId();
699   op_scheduler_.ScheduleOperation(
700       id, CacheStorageSchedulerMode::kExclusive,
701       CacheStorageSchedulerOp::kBackgroundSync,
702       CacheStorageSchedulerPriority::kNormal,
703       base::BindOnce(&BackgroundSyncManager::InitImpl,
704                      weak_ptr_factory_.GetWeakPtr(), MakeEmptyCompletion(id)));
705 }
706 
InitImpl(base::OnceClosure callback)707 void BackgroundSyncManager::InitImpl(base::OnceClosure callback) {
708   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
709 
710   if (disabled_) {
711     base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
712                                                   std::move(callback));
713     return;
714   }
715 
716   // TODO(crbug.com/824858): Remove the else branch after the feature is
717   // enabled. Also, try to make a RunOrPostTaskOnThreadAndReplyWithResult()
718   // function so the if/else isn't needed.
719   if (ServiceWorkerContext::IsServiceWorkerOnUIEnabled()) {
720     InitDidGetControllerParameters(
721         std::move(callback),
722         GetControllerParameters(
723             service_worker_context_,
724             std::make_unique<BackgroundSyncParameters>(*parameters_)));
725   } else {
726     base::PostTaskAndReplyWithResult(
727         FROM_HERE, {BrowserThread::UI},
728         base::BindOnce(
729             &GetControllerParameters, service_worker_context_,
730             std::make_unique<BackgroundSyncParameters>(*parameters_)),
731         base::BindOnce(&BackgroundSyncManager::InitDidGetControllerParameters,
732                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
733   }
734 }
735 
InitDidGetControllerParameters(base::OnceClosure callback,std::unique_ptr<BackgroundSyncParameters> updated_parameters)736 void BackgroundSyncManager::InitDidGetControllerParameters(
737     base::OnceClosure callback,
738     std::unique_ptr<BackgroundSyncParameters> updated_parameters) {
739   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
740 
741   parameters_ = std::move(updated_parameters);
742   if (parameters_->disable) {
743     disabled_ = true;
744     base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
745                                                   std::move(callback));
746     return;
747   }
748 
749   network_observer_->Init();
750 
751   GetDataFromBackend(
752       kBackgroundSyncUserDataKey,
753       base::BindOnce(&BackgroundSyncManager::InitDidGetDataFromBackend,
754                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
755 }
756 
InitDidGetDataFromBackend(base::OnceClosure callback,const std::vector<std::pair<int64_t,std::string>> & user_data,blink::ServiceWorkerStatusCode status)757 void BackgroundSyncManager::InitDidGetDataFromBackend(
758     base::OnceClosure callback,
759     const std::vector<std::pair<int64_t, std::string>>& user_data,
760     blink::ServiceWorkerStatusCode status) {
761   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
762 
763   if (status != blink::ServiceWorkerStatusCode::kOk &&
764       status != blink::ServiceWorkerStatusCode::kErrorNotFound) {
765     DisableAndClearManager(std::move(callback));
766     return;
767   }
768 
769   std::set<url::Origin> suspended_periodic_sync_origins;
770   std::set<url::Origin> registered_origins;
771   for (const std::pair<int64_t, std::string>& data : user_data) {
772     BackgroundSyncRegistrationsProto registrations_proto;
773     if (registrations_proto.ParseFromString(data.second)) {
774       BackgroundSyncRegistrations* registrations =
775           &active_registrations_[data.first];
776       registrations->origin =
777           url::Origin::Create(GURL(registrations_proto.origin()));
778 
779       for (const auto& registration_proto :
780            registrations_proto.registration()) {
781         BackgroundSyncType sync_type =
782             registration_proto.has_periodic_sync_options()
783                 ? BackgroundSyncType::PERIODIC
784                 : BackgroundSyncType::ONE_SHOT;
785         BackgroundSyncRegistration* registration =
786             &registrations
787                  ->registration_map[{registration_proto.tag(), sync_type}];
788 
789         blink::mojom::SyncRegistrationOptions* options =
790             registration->options();
791         options->tag = registration_proto.tag();
792         if (sync_type == BackgroundSyncType::PERIODIC) {
793           options->min_interval =
794               registration_proto.periodic_sync_options().min_interval();
795           if (options->min_interval < 0) {
796             DisableAndClearManager(std::move(callback));
797             return;
798           }
799         } else {
800           options->min_interval = kMinIntervalForOneShotSync;
801         }
802 
803         registration->set_num_attempts(registration_proto.num_attempts());
804         registration->set_delay_until(
805             base::Time::FromInternalValue(registration_proto.delay_until()));
806         registration->set_origin(registrations->origin);
807         registered_origins.insert(registration->origin());
808         if (registration->is_suspended()) {
809           suspended_periodic_sync_origins.insert(registration->origin());
810         }
811         registration->set_resolved();
812         if (registration_proto.has_max_attempts())
813           registration->set_max_attempts(registration_proto.max_attempts());
814         else
815           registration->set_max_attempts(parameters_->max_sync_attempts);
816       }
817     }
818   }
819 
820   FireReadyEvents(BackgroundSyncType::ONE_SHOT, /* reschedule= */ true,
821                   base::DoNothing::Once());
822   FireReadyEvents(BackgroundSyncType::PERIODIC, /* reschedule= */ true,
823                   base::DoNothing::Once());
824   proxy_->SendSuspendedPeriodicSyncOrigins(
825       std::move(suspended_periodic_sync_origins));
826   proxy_->SendRegisteredPeriodicSyncOrigins(std::move(registered_origins));
827   base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(callback));
828 }
829 
RegisterCheckIfHasMainFrame(int64_t sw_registration_id,blink::mojom::SyncRegistrationOptions options,StatusAndRegistrationCallback callback)830 void BackgroundSyncManager::RegisterCheckIfHasMainFrame(
831     int64_t sw_registration_id,
832     blink::mojom::SyncRegistrationOptions options,
833     StatusAndRegistrationCallback callback) {
834   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
835 
836   ServiceWorkerRegistration* sw_registration =
837       service_worker_context_->GetLiveRegistration(sw_registration_id);
838   if (!sw_registration || !sw_registration->active_version()) {
839     RecordFailureAndPostError(GetBackgroundSyncType(options),
840                               BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER,
841                               std::move(callback));
842     return;
843   }
844 
845   HasMainFrameWindowClient(
846       url::Origin::Create(sw_registration->scope().GetOrigin()),
847       base::BindOnce(&BackgroundSyncManager::RegisterDidCheckIfMainFrame,
848                      weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
849                      std::move(options), std::move(callback)));
850 }
851 
RegisterDidCheckIfMainFrame(int64_t sw_registration_id,blink::mojom::SyncRegistrationOptions options,StatusAndRegistrationCallback callback,bool has_main_frame_client)852 void BackgroundSyncManager::RegisterDidCheckIfMainFrame(
853     int64_t sw_registration_id,
854     blink::mojom::SyncRegistrationOptions options,
855     StatusAndRegistrationCallback callback,
856     bool has_main_frame_client) {
857   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
858 
859   if (!has_main_frame_client) {
860     RecordFailureAndPostError(GetBackgroundSyncType(options),
861                               BACKGROUND_SYNC_STATUS_NOT_ALLOWED,
862                               std::move(callback));
863     return;
864   }
865   RegisterImpl(sw_registration_id, std::move(options), std::move(callback));
866 }
867 
RegisterImpl(int64_t sw_registration_id,blink::mojom::SyncRegistrationOptions options,StatusAndRegistrationCallback callback)868 void BackgroundSyncManager::RegisterImpl(
869     int64_t sw_registration_id,
870     blink::mojom::SyncRegistrationOptions options,
871     StatusAndRegistrationCallback callback) {
872   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
873 
874   if (disabled_) {
875     RecordFailureAndPostError(GetBackgroundSyncType(options),
876                               BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
877                               std::move(callback));
878     return;
879   }
880 
881   if (options.tag.length() > kMaxTagLength) {
882     RecordFailureAndPostError(GetBackgroundSyncType(options),
883                               BACKGROUND_SYNC_STATUS_NOT_ALLOWED,
884                               std::move(callback));
885     return;
886   }
887 
888   ServiceWorkerRegistration* sw_registration =
889       service_worker_context_->GetLiveRegistration(sw_registration_id);
890   if (!sw_registration || !sw_registration->active_version()) {
891     RecordFailureAndPostError(GetBackgroundSyncType(options),
892                               BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER,
893                               std::move(callback));
894     return;
895   }
896 
897   BackgroundSyncType sync_type = GetBackgroundSyncType(options);
898 
899   if (parameters_->skip_permissions_check_for_testing) {
900     RegisterDidAskForPermission(
901         sw_registration_id, std::move(options), std::move(callback),
902         {PermissionStatus::GRANTED, PermissionStatus::GRANTED});
903     return;
904   }
905 
906   // TODO(crbug.com/824858): Remove the else branch after the feature is
907   // enabled. Also, try to make a RunOrPostTaskOnThreadAndReplyWithResult()
908   // function so the if/else isn't needed.
909   if (ServiceWorkerContext::IsServiceWorkerOnUIEnabled()) {
910     SyncAndNotificationPermissions permission =
911         GetBackgroundSyncPermissionOnUIThread(
912             service_worker_context_,
913             url::Origin::Create(sw_registration->scope().GetOrigin()),
914             sync_type);
915     RegisterDidAskForPermission(sw_registration_id, std::move(options),
916                                 std::move(callback), permission);
917   } else {
918     base::PostTaskAndReplyWithResult(
919         FROM_HERE, {BrowserThread::UI},
920         base::BindOnce(
921             &GetBackgroundSyncPermissionOnUIThread, service_worker_context_,
922             url::Origin::Create(sw_registration->scope().GetOrigin()),
923             sync_type),
924         base::BindOnce(&BackgroundSyncManager::RegisterDidAskForPermission,
925                        weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
926                        std::move(options), std::move(callback)));
927   }
928 }
929 
RegisterDidAskForPermission(int64_t sw_registration_id,blink::mojom::SyncRegistrationOptions options,StatusAndRegistrationCallback callback,SyncAndNotificationPermissions permission_statuses)930 void BackgroundSyncManager::RegisterDidAskForPermission(
931     int64_t sw_registration_id,
932     blink::mojom::SyncRegistrationOptions options,
933     StatusAndRegistrationCallback callback,
934     SyncAndNotificationPermissions permission_statuses) {
935   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
936 
937   if (permission_statuses.first == PermissionStatus::DENIED) {
938     RecordFailureAndPostError(GetBackgroundSyncType(options),
939                               BACKGROUND_SYNC_STATUS_PERMISSION_DENIED,
940                               std::move(callback));
941     return;
942   }
943   DCHECK_EQ(permission_statuses.first, PermissionStatus::GRANTED);
944 
945   ServiceWorkerRegistration* sw_registration =
946       service_worker_context_->GetLiveRegistration(sw_registration_id);
947   if (!sw_registration || !sw_registration->active_version()) {
948     // The service worker was shut down in the interim.
949     RecordFailureAndPostError(GetBackgroundSyncType(options),
950                               BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER,
951                               std::move(callback));
952     return;
953   }
954 
955   BackgroundSyncRegistration* existing_registration =
956       LookupActiveRegistration(blink::mojom::BackgroundSyncRegistrationInfo(
957           sw_registration_id, options.tag, GetBackgroundSyncType(options)));
958 
959   url::Origin origin =
960       url::Origin::Create(sw_registration->scope().GetOrigin());
961 
962   if (GetBackgroundSyncType(options) ==
963       blink::mojom::BackgroundSyncType::ONE_SHOT) {
964     bool is_reregistered =
965         existing_registration && existing_registration->IsFiring();
966     RunOrPostTaskOnThread(
967         FROM_HERE, BrowserThread::UI,
968         base::BindOnce(&NotifyOneShotBackgroundSyncRegisteredOnUIThread,
969                        service_worker_context_, origin,
970                        /* can_fire= */ AreOptionConditionsMet(),
971                        is_reregistered));
972   } else {
973     RunOrPostTaskOnThread(
974         FROM_HERE, BrowserThread::UI,
975         base::BindOnce(
976             &NotifyPeriodicBackgroundSyncRegisteredOnUIThread,
977             service_worker_context_, origin, options.min_interval,
978             /* is_reregistered= */ static_cast<bool>(existing_registration)));
979   }
980 
981   if (existing_registration) {
982     DCHECK_EQ(existing_registration->options()->tag, options.tag);
983     DCHECK_EQ(existing_registration->sync_type(),
984               GetBackgroundSyncType(options));
985 
986     if (existing_registration->options()->Equals(options)) {
987       BackgroundSyncMetrics::RegistrationCouldFire registration_could_fire =
988           AreOptionConditionsMet()
989               ? BackgroundSyncMetrics::REGISTRATION_COULD_FIRE
990               : BackgroundSyncMetrics::REGISTRATION_COULD_NOT_FIRE;
991       BackgroundSyncMetrics::CountRegisterSuccess(
992           existing_registration->sync_type(), options.min_interval,
993           registration_could_fire,
994           BackgroundSyncMetrics::REGISTRATION_IS_DUPLICATE);
995 
996       if (existing_registration->IsFiring()) {
997         existing_registration->set_sync_state(
998             blink::mojom::BackgroundSyncState::REREGISTERED_WHILE_FIRING);
999       }
1000 
1001       base::ThreadTaskRunnerHandle::Get()->PostTask(
1002           FROM_HERE,
1003           base::BindOnce(std::move(callback), BACKGROUND_SYNC_STATUS_OK,
1004                          std::make_unique<BackgroundSyncRegistration>(
1005                              *existing_registration)));
1006       return;
1007     }
1008   }
1009 
1010   BackgroundSyncRegistration registration;
1011 
1012   registration.set_origin(origin);
1013   *registration.options() = std::move(options);
1014 
1015   // TODO(crbug.com/963487): This section below is really confusing. Add a
1016   // comment explaining what's going on here, or annotate permission_statuses.
1017   registration.set_max_attempts(
1018       permission_statuses.second == PermissionStatus::GRANTED
1019           ? parameters_->max_sync_attempts_with_notification_permission
1020           : parameters_->max_sync_attempts);
1021 
1022   // Skip the current registration when getting time till next scheduled
1023   // periodic sync event for the origin. This is because we'll be updating the
1024   // schedule time of this registration soon anyway, so considering its
1025   // schedule time would cause us to calculate incorrect delay.
1026   if (registration.sync_type() == BackgroundSyncType::PERIODIC) {
1027     // TODO(crbug.com/824858): Remove the else branch after the feature is
1028     // enabled. Also, try to make a RunOrPostTaskOnThreadAndReplyWithResult()
1029     // function so the if/else isn't needed.
1030     if (ServiceWorkerContext::IsServiceWorkerOnUIEnabled()) {
1031       base::TimeDelta delay = GetNextEventDelay(
1032           service_worker_context_, registration,
1033           std::make_unique<BackgroundSyncParameters>(*parameters_),
1034           GetSmallestPeriodicSyncEventDelayForOrigin(
1035               origin, registration.options()->tag));
1036       RegisterDidGetDelay(sw_registration_id, registration, std::move(callback),
1037                           delay);
1038     } else {
1039       base::PostTaskAndReplyWithResult(
1040           FROM_HERE, {BrowserThread::UI},
1041           base::BindOnce(
1042               &GetNextEventDelay, service_worker_context_, registration,
1043               std::make_unique<BackgroundSyncParameters>(*parameters_),
1044               GetSmallestPeriodicSyncEventDelayForOrigin(
1045                   origin, registration.options()->tag)),
1046           base::BindOnce(&BackgroundSyncManager::RegisterDidGetDelay,
1047                          weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
1048                          registration, std::move(callback)));
1049     }
1050     return;
1051   }
1052 
1053   RegisterDidGetDelay(sw_registration_id, registration, std::move(callback),
1054                       base::TimeDelta());
1055 }
1056 
RegisterDidGetDelay(int64_t sw_registration_id,BackgroundSyncRegistration registration,StatusAndRegistrationCallback callback,base::TimeDelta delay)1057 void BackgroundSyncManager::RegisterDidGetDelay(
1058     int64_t sw_registration_id,
1059     BackgroundSyncRegistration registration,
1060     StatusAndRegistrationCallback callback,
1061     base::TimeDelta delay) {
1062   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1063 
1064   // We don't fire periodic Background Sync registrations immediately after
1065   // registration, so set delay_until to override its default value.
1066   if (registration.sync_type() == BackgroundSyncType::PERIODIC)
1067     registration.set_delay_until(clock_->Now() + delay);
1068 
1069   ServiceWorkerRegistration* sw_registration =
1070       service_worker_context_->GetLiveRegistration(sw_registration_id);
1071   if (!sw_registration || !sw_registration->active_version()) {
1072     // The service worker was shut down in the interim.
1073     RecordFailureAndPostError(registration.sync_type(),
1074                               BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER,
1075                               std::move(callback));
1076     return;
1077   }
1078 
1079   if (registration.sync_type() == BackgroundSyncType::PERIODIC &&
1080       ShouldLogToDevTools(registration.sync_type())) {
1081     devtools_context_->LogBackgroundServiceEventOnCoreThread(
1082         sw_registration_id, registration.origin(),
1083         DevToolsBackgroundService::kPeriodicBackgroundSync,
1084         /* event_name= */ "Got next event delay",
1085         /* instance_id= */ registration.options()->tag,
1086         {{"Next Attempt Delay (ms)",
1087           GetDelayAsString(registration.delay_until() - clock_->Now())}});
1088   }
1089 
1090   AddOrUpdateActiveRegistration(
1091       sw_registration_id,
1092       url::Origin::Create(sw_registration->scope().GetOrigin()), registration);
1093 
1094   StoreRegistrations(
1095       sw_registration_id,
1096       base::BindOnce(&BackgroundSyncManager::RegisterDidStore,
1097                      weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
1098                      registration, std::move(callback)));
1099 }
1100 
UnregisterPeriodicSyncImpl(int64_t sw_registration_id,const std::string & tag,BackgroundSyncManager::StatusCallback callback)1101 void BackgroundSyncManager::UnregisterPeriodicSyncImpl(
1102     int64_t sw_registration_id,
1103     const std::string& tag,
1104     BackgroundSyncManager::StatusCallback callback) {
1105   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1106 
1107   auto registration_info = blink::mojom::BackgroundSyncRegistrationInfo(
1108       sw_registration_id, tag, BackgroundSyncType::PERIODIC);
1109 
1110   if (!LookupActiveRegistration(registration_info)) {
1111     // It's okay to not find a matching tag.
1112     UnregisterPeriodicSyncDidStore(std::move(callback),
1113                                    blink::ServiceWorkerStatusCode::kOk);
1114     return;
1115   }
1116 
1117   RemoveActiveRegistration(std::move(registration_info));
1118   StoreRegistrations(
1119       sw_registration_id,
1120       base::BindOnce(&BackgroundSyncManager::UnregisterPeriodicSyncDidStore,
1121                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
1122 }
1123 
UnregisterPeriodicSyncDidStore(BackgroundSyncManager::StatusCallback callback,blink::ServiceWorkerStatusCode status)1124 void BackgroundSyncManager::UnregisterPeriodicSyncDidStore(
1125     BackgroundSyncManager::StatusCallback callback,
1126     blink::ServiceWorkerStatusCode status) {
1127   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1128 
1129   if (status != blink::ServiceWorkerStatusCode::kOk) {
1130     BackgroundSyncMetrics::CountUnregisterPeriodicSync(
1131         BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
1132     DisableAndClearManager(base::BindOnce(
1133         std::move(callback), BACKGROUND_SYNC_STATUS_STORAGE_ERROR));
1134     return;
1135   }
1136 
1137   BackgroundSyncMetrics::CountUnregisterPeriodicSync(BACKGROUND_SYNC_STATUS_OK);
1138   ScheduleOrCancelDelayedProcessing(BackgroundSyncType::PERIODIC);
1139   base::ThreadTaskRunnerHandle::Get()->PostTask(
1140       FROM_HERE,
1141       base::BindOnce(std::move(callback), BACKGROUND_SYNC_STATUS_OK));
1142 }
1143 
DisableAndClearManager(base::OnceClosure callback)1144 void BackgroundSyncManager::DisableAndClearManager(base::OnceClosure callback) {
1145   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1146 
1147   if (disabled_) {
1148     base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1149                                                   std::move(callback));
1150     return;
1151   }
1152 
1153   disabled_ = true;
1154 
1155   active_registrations_.clear();
1156 
1157   // Delete all backend entries. The memory representation of registered syncs
1158   // may be out of sync with storage (e.g., due to corruption detection on
1159   // loading from storage), so reload the registrations from storage again.
1160   GetDataFromBackend(
1161       kBackgroundSyncUserDataKey,
1162       base::BindOnce(&BackgroundSyncManager::DisableAndClearDidGetRegistrations,
1163                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
1164 }
1165 
DisableAndClearDidGetRegistrations(base::OnceClosure callback,const std::vector<std::pair<int64_t,std::string>> & user_data,blink::ServiceWorkerStatusCode status)1166 void BackgroundSyncManager::DisableAndClearDidGetRegistrations(
1167     base::OnceClosure callback,
1168     const std::vector<std::pair<int64_t, std::string>>& user_data,
1169     blink::ServiceWorkerStatusCode status) {
1170   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1171 
1172   if (status != blink::ServiceWorkerStatusCode::kOk || user_data.empty()) {
1173     base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1174                                                   std::move(callback));
1175     return;
1176   }
1177 
1178   base::RepeatingClosure barrier_closure =
1179       base::BarrierClosure(user_data.size(), std::move(callback));
1180 
1181   for (const auto& sw_id_and_regs : user_data) {
1182     service_worker_context_->ClearRegistrationUserData(
1183         sw_id_and_regs.first, {kBackgroundSyncUserDataKey},
1184         base::BindOnce(&BackgroundSyncManager::DisableAndClearManagerClearedOne,
1185                        weak_ptr_factory_.GetWeakPtr(), barrier_closure));
1186   }
1187 }
1188 
DisableAndClearManagerClearedOne(base::OnceClosure barrier_closure,blink::ServiceWorkerStatusCode status)1189 void BackgroundSyncManager::DisableAndClearManagerClearedOne(
1190     base::OnceClosure barrier_closure,
1191     blink::ServiceWorkerStatusCode status) {
1192   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1193 
1194   // The status doesn't matter at this point, there is nothing else to be done.
1195   base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1196                                                 std::move(barrier_closure));
1197 }
1198 
LookupActiveRegistration(const blink::mojom::BackgroundSyncRegistrationInfo & registration_info)1199 BackgroundSyncRegistration* BackgroundSyncManager::LookupActiveRegistration(
1200     const blink::mojom::BackgroundSyncRegistrationInfo& registration_info) {
1201   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1202 
1203   auto it = active_registrations_.find(
1204       registration_info.service_worker_registration_id);
1205   if (it == active_registrations_.end())
1206     return nullptr;
1207 
1208   BackgroundSyncRegistrations& registrations = it->second;
1209   DCHECK(!registrations.origin.opaque());
1210 
1211   auto key_and_registration_iter = registrations.registration_map.find(
1212       {registration_info.tag, registration_info.sync_type});
1213   if (key_and_registration_iter == registrations.registration_map.end())
1214     return nullptr;
1215 
1216   return &key_and_registration_iter->second;
1217 }
1218 
StoreRegistrations(int64_t sw_registration_id,ServiceWorkerRegistry::StatusCallback callback)1219 void BackgroundSyncManager::StoreRegistrations(
1220     int64_t sw_registration_id,
1221     ServiceWorkerRegistry::StatusCallback callback) {
1222   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1223 
1224   // Serialize the data.
1225   const BackgroundSyncRegistrations& registrations =
1226       active_registrations_[sw_registration_id];
1227   BackgroundSyncRegistrationsProto registrations_proto;
1228   registrations_proto.set_origin(registrations.origin.Serialize());
1229 
1230   for (const auto& key_and_registration : registrations.registration_map) {
1231     const BackgroundSyncRegistration& registration =
1232         key_and_registration.second;
1233     BackgroundSyncRegistrationProto* registration_proto =
1234         registrations_proto.add_registration();
1235     registration_proto->set_tag(registration.options()->tag);
1236     if (registration.options()->min_interval >= 0) {
1237       registration_proto->mutable_periodic_sync_options()->set_min_interval(
1238           registration.options()->min_interval);
1239     }
1240     registration_proto->set_num_attempts(registration.num_attempts());
1241     registration_proto->set_max_attempts(registration.max_attempts());
1242     registration_proto->set_delay_until(
1243         registration.delay_until().ToInternalValue());
1244   }
1245   std::string serialized;
1246   bool success = registrations_proto.SerializeToString(&serialized);
1247   DCHECK(success);
1248 
1249   StoreDataInBackend(sw_registration_id, registrations.origin,
1250                      kBackgroundSyncUserDataKey, serialized,
1251                      std::move(callback));
1252 }
1253 
RegisterDidStore(int64_t sw_registration_id,const BackgroundSyncRegistration & registration,StatusAndRegistrationCallback callback,blink::ServiceWorkerStatusCode status)1254 void BackgroundSyncManager::RegisterDidStore(
1255     int64_t sw_registration_id,
1256     const BackgroundSyncRegistration& registration,
1257     StatusAndRegistrationCallback callback,
1258     blink::ServiceWorkerStatusCode status) {
1259   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1260 
1261   if (status == blink::ServiceWorkerStatusCode::kErrorNotFound) {
1262     // The service worker registration is gone.
1263     active_registrations_.erase(sw_registration_id);
1264     RecordFailureAndPostError(registration.sync_type(),
1265                               BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
1266                               std::move(callback));
1267     return;
1268   }
1269 
1270   if (status != blink::ServiceWorkerStatusCode::kOk) {
1271     BackgroundSyncMetrics::CountRegisterFailure(
1272         registration.sync_type(), BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
1273     DisableAndClearManager(base::BindOnce(
1274         std::move(callback), BACKGROUND_SYNC_STATUS_STORAGE_ERROR, nullptr));
1275     return;
1276   }
1277 
1278   // Update controller of this new origin.
1279   if (registration.sync_type() == BackgroundSyncType::PERIODIC)
1280     proxy_->AddToTrackedOrigins(registration.origin());
1281 
1282   BackgroundSyncMetrics::RegistrationCouldFire registration_could_fire =
1283       AreOptionConditionsMet()
1284           ? BackgroundSyncMetrics::REGISTRATION_COULD_FIRE
1285           : BackgroundSyncMetrics::REGISTRATION_COULD_NOT_FIRE;
1286   BackgroundSyncMetrics::CountRegisterSuccess(
1287       registration.sync_type(), registration.options()->min_interval,
1288       registration_could_fire,
1289       BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE);
1290 
1291   ScheduleOrCancelDelayedProcessing(BackgroundSyncType::PERIODIC);
1292 
1293   // Tell the client that the registration is ready. We won't fire it until the
1294   // client has resolved the registration event.
1295   base::ThreadTaskRunnerHandle::Get()->PostTask(
1296       FROM_HERE, base::BindOnce(std::move(callback), BACKGROUND_SYNC_STATUS_OK,
1297                                 std::make_unique<BackgroundSyncRegistration>(
1298                                     registration)));
1299 }
1300 
DidResolveRegistrationImpl(blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info,CacheStorageSchedulerId id)1301 void BackgroundSyncManager::DidResolveRegistrationImpl(
1302     blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info,
1303     CacheStorageSchedulerId id) {
1304   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1305 
1306   BackgroundSyncRegistration* registration =
1307       LookupActiveRegistration(*registration_info);
1308   if (!registration) {
1309     // There might not be a registration if the client ack's a registration that
1310     // was a duplicate in the first place and was already firing and finished by
1311     // the time the client acknowledged the second registration.
1312     op_scheduler_.CompleteOperationAndRunNext(id);
1313     return;
1314   }
1315 
1316   registration->set_resolved();
1317 
1318   // TODO(crbug.com/824858): Remove the else branch after the feature is
1319   // enabled. Also, try to make a RunOrPostTaskOnThreadAndReplyWithResult()
1320   // function so the if/else isn't needed.
1321   if (ServiceWorkerContext::IsServiceWorkerOnUIEnabled()) {
1322     ResolveRegistrationDidCreateKeepAlive(
1323         id, CreateBackgroundSyncEventKeepAliveOnUIThread(
1324                 service_worker_context_, std::move(*registration_info)));
1325   } else {
1326     base::PostTaskAndReplyWithResult(
1327         FROM_HERE, {BrowserThread::UI},
1328         base::BindOnce(&CreateBackgroundSyncEventKeepAliveOnUIThread,
1329                        service_worker_context_, std::move(*registration_info)),
1330         base::BindOnce(
1331             &BackgroundSyncManager::ResolveRegistrationDidCreateKeepAlive,
1332             weak_ptr_factory_.GetWeakPtr(), id));
1333   }
1334 }
1335 
ResolveRegistrationDidCreateKeepAlive(CacheStorageSchedulerId id,std::unique_ptr<BackgroundSyncEventKeepAlive> keepalive)1336 void BackgroundSyncManager::ResolveRegistrationDidCreateKeepAlive(
1337     CacheStorageSchedulerId id,
1338     std::unique_ptr<BackgroundSyncEventKeepAlive> keepalive) {
1339   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1340 
1341   FireReadyEvents(BackgroundSyncType::ONE_SHOT, /* reschedule= */ true,
1342                   base::DoNothing::Once(), std::move(keepalive));
1343   op_scheduler_.CompleteOperationAndRunNext(id);
1344 }
1345 
RemoveActiveRegistration(const blink::mojom::BackgroundSyncRegistrationInfo & registration_info)1346 void BackgroundSyncManager::RemoveActiveRegistration(
1347     const blink::mojom::BackgroundSyncRegistrationInfo& registration_info) {
1348   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1349   DCHECK(LookupActiveRegistration(registration_info));
1350 
1351   BackgroundSyncRegistrations* registrations =
1352       &active_registrations_[registration_info.service_worker_registration_id];
1353   const url::Origin& origin = registrations->origin;
1354 
1355   registrations->registration_map.erase(
1356       {registration_info.tag, registration_info.sync_type});
1357 
1358   // Update controller's list of registered origin if necessary.
1359   if (registrations->registration_map.empty())
1360     proxy_->RemoveFromTrackedOrigins(origin);
1361   else {
1362     bool no_more_periodic_sync_registrations = true;
1363     for (auto& key_and_registration : registrations->registration_map) {
1364       if (key_and_registration.second.sync_type() ==
1365           BackgroundSyncType::PERIODIC) {
1366         no_more_periodic_sync_registrations = false;
1367         break;
1368       }
1369     }
1370     if (no_more_periodic_sync_registrations)
1371       proxy_->RemoveFromTrackedOrigins(origin);
1372   }
1373 
1374   if (registration_info.sync_type == BackgroundSyncType::PERIODIC &&
1375       ShouldLogToDevTools(registration_info.sync_type)) {
1376     devtools_context_->LogBackgroundServiceEventOnCoreThread(
1377         registration_info.service_worker_registration_id, origin,
1378         DevToolsBackgroundService::kPeriodicBackgroundSync,
1379         /* event_name= */ "Unregistered periodicsync",
1380         /* instance_id= */ registration_info.tag,
1381         /* event_metadata= */ {});
1382   }
1383 }
1384 
AddOrUpdateActiveRegistration(int64_t sw_registration_id,const url::Origin & origin,const BackgroundSyncRegistration & sync_registration)1385 void BackgroundSyncManager::AddOrUpdateActiveRegistration(
1386     int64_t sw_registration_id,
1387     const url::Origin& origin,
1388     const BackgroundSyncRegistration& sync_registration) {
1389   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1390 
1391   BackgroundSyncRegistrations* registrations =
1392       &active_registrations_[sw_registration_id];
1393   registrations->origin = origin;
1394 
1395   BackgroundSyncType sync_type = sync_registration.sync_type();
1396   registrations
1397       ->registration_map[{sync_registration.options()->tag, sync_type}] =
1398       sync_registration;
1399 
1400   if (ShouldLogToDevTools(sync_registration.sync_type())) {
1401     std::map<std::string, std::string> event_metadata;
1402     if (sync_registration.sync_type() == BackgroundSyncType::PERIODIC) {
1403       event_metadata["minInterval"] =
1404           base::NumberToString(sync_registration.options()->min_interval);
1405     }
1406     devtools_context_->LogBackgroundServiceEventOnCoreThread(
1407         sw_registration_id, origin, GetDevToolsBackgroundService(sync_type),
1408         /* event_name= */ "Registered " + GetSyncEventName(sync_type),
1409         /* instance_id= */ sync_registration.options()->tag, event_metadata);
1410   }
1411 }
1412 
StoreDataInBackend(int64_t sw_registration_id,const url::Origin & origin,const std::string & backend_key,const std::string & data,ServiceWorkerRegistry::StatusCallback callback)1413 void BackgroundSyncManager::StoreDataInBackend(
1414     int64_t sw_registration_id,
1415     const url::Origin& origin,
1416     const std::string& backend_key,
1417     const std::string& data,
1418     ServiceWorkerRegistry::StatusCallback callback) {
1419   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1420 
1421   service_worker_context_->StoreRegistrationUserData(
1422       sw_registration_id, origin.GetURL(), {{backend_key, data}},
1423       std::move(callback));
1424 }
1425 
GetDataFromBackend(const std::string & backend_key,ServiceWorkerRegistry::GetUserDataForAllRegistrationsCallback callback)1426 void BackgroundSyncManager::GetDataFromBackend(
1427     const std::string& backend_key,
1428     ServiceWorkerRegistry::GetUserDataForAllRegistrationsCallback callback) {
1429   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1430 
1431   service_worker_context_->GetUserDataForAllRegistrations(backend_key,
1432                                                           std::move(callback));
1433 }
1434 
DispatchSyncEvent(const std::string & tag,scoped_refptr<ServiceWorkerVersion> active_version,bool last_chance,ServiceWorkerVersion::StatusCallback callback)1435 void BackgroundSyncManager::DispatchSyncEvent(
1436     const std::string& tag,
1437     scoped_refptr<ServiceWorkerVersion> active_version,
1438     bool last_chance,
1439     ServiceWorkerVersion::StatusCallback callback) {
1440   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1441   DCHECK(active_version);
1442 
1443   if (active_version->running_status() != EmbeddedWorkerStatus::RUNNING) {
1444     active_version->RunAfterStartWorker(
1445         ServiceWorkerMetrics::EventType::SYNC,
1446         base::BindOnce(&DidStartWorkerForSyncEvent,
1447                        base::BindOnce(&BackgroundSyncManager::DispatchSyncEvent,
1448                                       weak_ptr_factory_.GetWeakPtr(), tag,
1449                                       active_version, last_chance),
1450                        std::move(callback)));
1451     return;
1452   }
1453 
1454   auto repeating_callback =
1455       base::AdaptCallbackForRepeating(std::move(callback));
1456 
1457   int request_id = active_version->StartRequestWithCustomTimeout(
1458       ServiceWorkerMetrics::EventType::SYNC, repeating_callback,
1459       parameters_->max_sync_event_duration,
1460       ServiceWorkerVersion::CONTINUE_ON_TIMEOUT);
1461 
1462   active_version->endpoint()->DispatchSyncEvent(
1463       tag, last_chance, parameters_->max_sync_event_duration,
1464       base::BindOnce(&OnSyncEventFinished, active_version, request_id,
1465                      std::move(repeating_callback)));
1466 
1467   if (devtools_context_->IsRecording(
1468           DevToolsBackgroundService::kBackgroundSync)) {
1469     devtools_context_->LogBackgroundServiceEventOnCoreThread(
1470         active_version->registration_id(), active_version->script_origin(),
1471         DevToolsBackgroundService::kBackgroundSync,
1472         /* event_name= */ "Dispatched sync event",
1473         /* instance_id= */ tag,
1474         /* event_metadata= */
1475         {{"Last Chance", last_chance ? "Yes" : "No"}});
1476   }
1477 }
1478 
DispatchPeriodicSyncEvent(const std::string & tag,scoped_refptr<ServiceWorkerVersion> active_version,ServiceWorkerVersion::StatusCallback callback)1479 void BackgroundSyncManager::DispatchPeriodicSyncEvent(
1480     const std::string& tag,
1481     scoped_refptr<ServiceWorkerVersion> active_version,
1482     ServiceWorkerVersion::StatusCallback callback) {
1483   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1484   DCHECK(active_version);
1485 
1486   if (active_version->running_status() != EmbeddedWorkerStatus::RUNNING) {
1487     active_version->RunAfterStartWorker(
1488         ServiceWorkerMetrics::EventType::PERIODIC_SYNC,
1489         base::BindOnce(
1490             &DidStartWorkerForSyncEvent,
1491             base::BindOnce(&BackgroundSyncManager::DispatchPeriodicSyncEvent,
1492                            weak_ptr_factory_.GetWeakPtr(), tag, active_version),
1493             std::move(callback)));
1494     return;
1495   }
1496 
1497   auto repeating_callback =
1498       base::AdaptCallbackForRepeating(std::move(callback));
1499 
1500   int request_id = active_version->StartRequestWithCustomTimeout(
1501       ServiceWorkerMetrics::EventType::PERIODIC_SYNC, repeating_callback,
1502       parameters_->max_sync_event_duration,
1503       ServiceWorkerVersion::CONTINUE_ON_TIMEOUT);
1504 
1505   active_version->endpoint()->DispatchPeriodicSyncEvent(
1506       tag, parameters_->max_sync_event_duration,
1507       base::BindOnce(&OnSyncEventFinished, active_version, request_id,
1508                      std::move(repeating_callback)));
1509 
1510   if (devtools_context_->IsRecording(
1511           DevToolsBackgroundService::kPeriodicBackgroundSync)) {
1512     devtools_context_->LogBackgroundServiceEventOnCoreThread(
1513         active_version->registration_id(), active_version->script_origin(),
1514         DevToolsBackgroundService::kPeriodicBackgroundSync,
1515         /* event_name= */ "Dispatched periodicsync event",
1516         /* instance_id= */ tag,
1517         /* event_metadata= */ {});
1518   }
1519 }
1520 
HasMainFrameWindowClient(const url::Origin & origin,BoolCallback callback)1521 void BackgroundSyncManager::HasMainFrameWindowClient(const url::Origin& origin,
1522                                                      BoolCallback callback) {
1523   service_worker_context_->HasMainFrameWindowClient(origin.GetURL(),
1524                                                     std::move(callback));
1525 }
1526 
GetRegistrationsImpl(BackgroundSyncType sync_type,int64_t sw_registration_id,StatusAndRegistrationsCallback callback)1527 void BackgroundSyncManager::GetRegistrationsImpl(
1528     BackgroundSyncType sync_type,
1529     int64_t sw_registration_id,
1530     StatusAndRegistrationsCallback callback) {
1531   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1532 
1533   std::vector<std::unique_ptr<BackgroundSyncRegistration>> out_registrations;
1534 
1535   if (disabled_) {
1536     base::ThreadTaskRunnerHandle::Get()->PostTask(
1537         FROM_HERE, base::BindOnce(std::move(callback),
1538                                   BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
1539                                   std::move(out_registrations)));
1540     return;
1541   }
1542 
1543   auto it = active_registrations_.find(sw_registration_id);
1544 
1545   if (it != active_registrations_.end()) {
1546     const BackgroundSyncRegistrations& registrations = it->second;
1547     for (const auto& key_and_registration : registrations.registration_map) {
1548       const BackgroundSyncRegistration& registration =
1549           key_and_registration.second;
1550       if (registration.sync_type() != sync_type)
1551         continue;
1552       out_registrations.push_back(
1553           std::make_unique<BackgroundSyncRegistration>(registration));
1554     }
1555   }
1556 
1557   base::ThreadTaskRunnerHandle::Get()->PostTask(
1558       FROM_HERE, base::BindOnce(std::move(callback), BACKGROUND_SYNC_STATUS_OK,
1559                                 std::move(out_registrations)));
1560 }
1561 
AreOptionConditionsMet()1562 bool BackgroundSyncManager::AreOptionConditionsMet() {
1563   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1564   return network_observer_->NetworkSufficient();
1565 }
1566 
AllConditionsExceptConnectivitySatisfied(const BackgroundSyncRegistration & registration,int64_t service_worker_id)1567 bool BackgroundSyncManager::AllConditionsExceptConnectivitySatisfied(
1568     const BackgroundSyncRegistration& registration,
1569     int64_t service_worker_id) {
1570   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1571 
1572   // Don't fire the registration if the client hasn't yet resolved its
1573   // registration promise.
1574   if (!registration.resolved() &&
1575       registration.sync_type() == BackgroundSyncType::ONE_SHOT) {
1576     return false;
1577   }
1578 
1579   if (registration.sync_state() != blink::mojom::BackgroundSyncState::PENDING)
1580     return false;
1581 
1582   if (registration.is_suspended())
1583     return false;
1584 
1585   if (base::Contains(emulated_offline_sw_, service_worker_id))
1586     return false;
1587 
1588   return true;
1589 }
1590 
CanFireAnyRegistrationUponConnectivity(BackgroundSyncType sync_type)1591 bool BackgroundSyncManager::CanFireAnyRegistrationUponConnectivity(
1592     BackgroundSyncType sync_type) {
1593   for (const auto& sw_reg_id_and_registrations : active_registrations_) {
1594     int64_t service_worker_registration_id = sw_reg_id_and_registrations.first;
1595     for (const auto& key_and_registration :
1596          sw_reg_id_and_registrations.second.registration_map) {
1597       const BackgroundSyncRegistration& registration =
1598           key_and_registration.second;
1599       if (sync_type != registration.sync_type())
1600         continue;
1601 
1602       if (AllConditionsExceptConnectivitySatisfied(
1603               registration, service_worker_registration_id)) {
1604         return true;
1605       }
1606     }
1607   }
1608   return false;
1609 }
1610 
delayed_processing_scheduled(BackgroundSyncType sync_type)1611 bool& BackgroundSyncManager::delayed_processing_scheduled(
1612     BackgroundSyncType sync_type) {
1613   if (sync_type == BackgroundSyncType::ONE_SHOT)
1614     return delayed_processing_scheduled_one_shot_sync_;
1615   else
1616     return delayed_processing_scheduled_periodic_sync_;
1617 }
1618 
ScheduleOrCancelDelayedProcessing(BackgroundSyncType sync_type)1619 void BackgroundSyncManager::ScheduleOrCancelDelayedProcessing(
1620     BackgroundSyncType sync_type) {
1621   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1622 
1623   bool can_fire_with_connectivity =
1624       CanFireAnyRegistrationUponConnectivity(sync_type);
1625 
1626   if (delayed_processing_scheduled(sync_type) && !can_fire_with_connectivity &&
1627       !GetNumFiringRegistrations(sync_type)) {
1628     CancelDelayedProcessingOfRegistrations(sync_type);
1629     delayed_processing_scheduled(sync_type) = false;
1630   } else if (can_fire_with_connectivity ||
1631              GetNumFiringRegistrations(sync_type)) {
1632     ScheduleDelayedProcessingOfRegistrations(sync_type);
1633     delayed_processing_scheduled(sync_type) = true;
1634   }
1635 }
1636 
IsRegistrationReadyToFire(const BackgroundSyncRegistration & registration,int64_t service_worker_id)1637 bool BackgroundSyncManager::IsRegistrationReadyToFire(
1638     const BackgroundSyncRegistration& registration,
1639     int64_t service_worker_id) {
1640   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1641 
1642   if (clock_->Now() < registration.delay_until())
1643     return false;
1644 
1645   return AllConditionsExceptConnectivitySatisfied(registration,
1646                                                   service_worker_id) &&
1647          AreOptionConditionsMet();
1648 }
1649 
GetNumFiringRegistrations(BackgroundSyncType sync_type)1650 int BackgroundSyncManager::GetNumFiringRegistrations(
1651     BackgroundSyncType sync_type) {
1652   if (sync_type == BackgroundSyncType::ONE_SHOT)
1653     return num_firing_registrations_one_shot_;
1654   return num_firing_registrations_periodic_;
1655 }
1656 
UpdateNumFiringRegistrationsBy(BackgroundSyncType sync_type,int to_add)1657 void BackgroundSyncManager::UpdateNumFiringRegistrationsBy(
1658     BackgroundSyncType sync_type,
1659     int to_add) {
1660   if (sync_type == BackgroundSyncType::ONE_SHOT)
1661     num_firing_registrations_one_shot_ += to_add;
1662   else
1663     num_firing_registrations_periodic_ += to_add;
1664 }
1665 
AllRegistrationsWaitingToBeResolved() const1666 bool BackgroundSyncManager::AllRegistrationsWaitingToBeResolved() const {
1667   for (const auto& active_registration : active_registrations_) {
1668     for (const auto& key_and_registration :
1669          active_registration.second.registration_map) {
1670       const BackgroundSyncRegistration& registration =
1671           key_and_registration.second;
1672       if (registration.resolved())
1673         return false;
1674     }
1675   }
1676   return true;
1677 }
1678 
GetSoonestWakeupDelta(BackgroundSyncType sync_type,base::Time last_browser_wakeup_time)1679 base::TimeDelta BackgroundSyncManager::GetSoonestWakeupDelta(
1680     BackgroundSyncType sync_type,
1681     base::Time last_browser_wakeup_time) {
1682   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1683   base::TimeDelta soonest_wakeup_delta = base::TimeDelta::Max();
1684   bool need_retries = false;
1685   for (const auto& sw_reg_id_and_registrations : active_registrations_) {
1686     for (const auto& key_and_registration :
1687          sw_reg_id_and_registrations.second.registration_map) {
1688       const BackgroundSyncRegistration& registration =
1689           key_and_registration.second;
1690       if (registration.sync_type() != sync_type)
1691         continue;
1692       if (registration.num_attempts() > 0 &&
1693           registration.num_attempts() < registration.max_attempts()) {
1694         need_retries = true;
1695       }
1696       if (registration.sync_state() ==
1697           blink::mojom::BackgroundSyncState::PENDING) {
1698         if (clock_->Now() >= registration.delay_until()) {
1699           soonest_wakeup_delta = base::TimeDelta();
1700           break;
1701         } else {
1702           base::TimeDelta delay_delta =
1703               registration.delay_until() - clock_->Now();
1704           soonest_wakeup_delta = std::min(delay_delta, soonest_wakeup_delta);
1705         }
1706       }
1707     }
1708   }
1709 
1710   // If the browser is closed while firing events, the browser needs a task to
1711   // wake it back up and try again.
1712   if (GetNumFiringRegistrations(sync_type) > 0 &&
1713       soonest_wakeup_delta > parameters_->min_sync_recovery_time) {
1714     soonest_wakeup_delta = parameters_->min_sync_recovery_time;
1715   }
1716 
1717   // If we're still waiting for registrations to be resolved, don't schedule
1718   // a wake up task eagerly.
1719   if (sync_type == BackgroundSyncType::ONE_SHOT &&
1720       AllRegistrationsWaitingToBeResolved() &&
1721       soonest_wakeup_delta < parameters_->min_sync_recovery_time) {
1722     soonest_wakeup_delta = parameters_->min_sync_recovery_time;
1723   }
1724 
1725   // The browser may impose a hard limit on how often it can be woken up to
1726   // process periodic Background Sync registrations. This excludes retries.
1727   if (sync_type == BackgroundSyncType::PERIODIC && !need_retries) {
1728     soonest_wakeup_delta = MaybeApplyBrowserWakeupCountLimit(
1729         soonest_wakeup_delta, last_browser_wakeup_time);
1730   }
1731   return soonest_wakeup_delta;
1732 }
1733 
MaybeApplyBrowserWakeupCountLimit(base::TimeDelta soonest_wakeup_delta,base::Time last_browser_wakeup_time)1734 base::TimeDelta BackgroundSyncManager::MaybeApplyBrowserWakeupCountLimit(
1735     base::TimeDelta soonest_wakeup_delta,
1736     base::Time last_browser_wakeup_time) {
1737   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1738   if (last_browser_wakeup_time.is_null())
1739     return soonest_wakeup_delta;
1740 
1741   base::TimeDelta time_since_last_browser_wakeup =
1742       clock_->Now() - last_browser_wakeup_time;
1743   if (time_since_last_browser_wakeup >=
1744       parameters_->min_periodic_sync_events_interval) {
1745     return soonest_wakeup_delta;
1746   }
1747 
1748   base::TimeDelta time_till_next_allowed_browser_wakeup =
1749       parameters_->min_periodic_sync_events_interval -
1750       time_since_last_browser_wakeup;
1751   return std::max(soonest_wakeup_delta, time_till_next_allowed_browser_wakeup);
1752 }
1753 
1754 base::TimeDelta
GetSmallestPeriodicSyncEventDelayForOrigin(const url::Origin & origin,const std::string & tag_to_skip) const1755 BackgroundSyncManager::GetSmallestPeriodicSyncEventDelayForOrigin(
1756     const url::Origin& origin,
1757     const std::string& tag_to_skip) const {
1758   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1759 
1760   base::Time soonest_wakeup_time = base::Time();
1761   for (const auto& active_registration : active_registrations_) {
1762     if (active_registration.second.origin != origin)
1763       continue;
1764 
1765     const auto& tag_and_registrations =
1766         active_registration.second.registration_map;
1767     for (const auto& tag_and_registration : tag_and_registrations) {
1768       if (/* tag= */ tag_and_registration.first.first == tag_to_skip)
1769         continue;
1770       if (/* sync_type= */ tag_and_registration.first.second !=
1771           BackgroundSyncType::PERIODIC) {
1772         continue;
1773       }
1774       if (tag_and_registration.second.delay_until().is_null())
1775         continue;
1776       if (soonest_wakeup_time.is_null() ||
1777           tag_and_registration.second.delay_until() < soonest_wakeup_time) {
1778         soonest_wakeup_time = tag_and_registration.second.delay_until();
1779       }
1780     }
1781   }
1782 
1783   if (soonest_wakeup_time.is_null())
1784     return base::TimeDelta::Max();
1785 
1786   if (soonest_wakeup_time < clock_->Now())
1787     return base::TimeDelta();
1788 
1789   return soonest_wakeup_time - clock_->Now();
1790 }
1791 
RevivePeriodicSyncRegistrations(url::Origin origin)1792 void BackgroundSyncManager::RevivePeriodicSyncRegistrations(
1793     url::Origin origin) {
1794   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1795 
1796   if (disabled_)
1797     return;
1798 
1799   auto id = op_scheduler_.CreateId();
1800   op_scheduler_.ScheduleOperation(
1801       id, CacheStorageSchedulerMode::kExclusive,
1802       CacheStorageSchedulerOp::kBackgroundSync,
1803       CacheStorageSchedulerPriority::kNormal,
1804       base::BindOnce(&BackgroundSyncManager::ReviveOriginImpl,
1805                      weak_ptr_factory_.GetWeakPtr(), std::move(origin),
1806                      MakeEmptyCompletion(id)));
1807 }
1808 
ReviveOriginImpl(url::Origin origin,base::OnceClosure callback)1809 void BackgroundSyncManager::ReviveOriginImpl(url::Origin origin,
1810                                              base::OnceClosure callback) {
1811   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1812 
1813   if (disabled_) {
1814     base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1815                                                   std::move(callback));
1816     return;
1817   }
1818 
1819   // Create a list of registrations to revive.
1820   std::vector<const BackgroundSyncRegistration*> to_revive;
1821   std::map<const BackgroundSyncRegistration*, int64_t>
1822       service_worker_registration_ids;
1823 
1824   for (const auto& active_registration : active_registrations_) {
1825     int64_t service_worker_registration_id = active_registration.first;
1826     if (active_registration.second.origin != origin)
1827       continue;
1828 
1829     for (const auto& key_and_registration :
1830          active_registration.second.registration_map) {
1831       const BackgroundSyncRegistration* registration =
1832           &key_and_registration.second;
1833       if (!registration->is_suspended())
1834         continue;
1835 
1836       to_revive.push_back(registration);
1837       service_worker_registration_ids[registration] =
1838           service_worker_registration_id;
1839     }
1840   }
1841 
1842   if (to_revive.empty()) {
1843     base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
1844                                                   std::move(callback));
1845     return;
1846   }
1847 
1848   base::RepeatingClosure received_new_delays_closure = base::BarrierClosure(
1849       to_revive.size(),
1850       base::BindOnce(
1851           &BackgroundSyncManager::DidReceiveDelaysForSuspendedRegistrations,
1852           weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
1853 
1854   for (const auto* registration : to_revive) {
1855     // TODO(crbug.com/824858): Remove the else branch after the feature is
1856     // enabled. Also, try to make a RunOrPostTaskOnThreadAndReplyWithResult()
1857     // function so the if/else isn't needed.
1858     if (ServiceWorkerContext::IsServiceWorkerOnUIEnabled()) {
1859       base::TimeDelta delay = GetNextEventDelay(
1860           service_worker_context_, *registration,
1861           std::make_unique<BackgroundSyncParameters>(*parameters_),
1862           GetSmallestPeriodicSyncEventDelayForOrigin(
1863               origin, registration->options()->tag));
1864       ReviveDidGetNextEventDelay(service_worker_registration_ids[registration],
1865                                  *registration, received_new_delays_closure,
1866                                  delay);
1867     } else {
1868       base::PostTaskAndReplyWithResult(
1869           FROM_HERE, {BrowserThread::UI},
1870           base::BindOnce(
1871               &GetNextEventDelay, service_worker_context_, *registration,
1872               std::make_unique<BackgroundSyncParameters>(*parameters_),
1873               GetSmallestPeriodicSyncEventDelayForOrigin(
1874                   origin, registration->options()->tag)),
1875           base::BindOnce(&BackgroundSyncManager::ReviveDidGetNextEventDelay,
1876                          weak_ptr_factory_.GetWeakPtr(),
1877                          service_worker_registration_ids[registration],
1878                          *registration, received_new_delays_closure));
1879     }
1880   }
1881 }
1882 
ReviveDidGetNextEventDelay(int64_t service_worker_registration_id,BackgroundSyncRegistration registration,base::OnceClosure done_closure,base::TimeDelta delay)1883 void BackgroundSyncManager::ReviveDidGetNextEventDelay(
1884     int64_t service_worker_registration_id,
1885     BackgroundSyncRegistration registration,
1886     base::OnceClosure done_closure,
1887     base::TimeDelta delay) {
1888   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1889 
1890   if (delay.is_max()) {
1891     std::move(done_closure).Run();
1892     return;
1893   }
1894 
1895   BackgroundSyncRegistration* active_registration =
1896       LookupActiveRegistration(blink::mojom::BackgroundSyncRegistrationInfo(
1897           service_worker_registration_id, registration.options()->tag,
1898           registration.sync_type()));
1899   if (!active_registration) {
1900     std::move(done_closure).Run();
1901     return;
1902   }
1903 
1904   active_registration->set_delay_until(clock_->Now() + delay);
1905 
1906   StoreRegistrations(
1907       service_worker_registration_id,
1908       base::BindOnce(&BackgroundSyncManager::ReviveDidStoreRegistration,
1909                      weak_ptr_factory_.GetWeakPtr(),
1910                      service_worker_registration_id, std::move(done_closure)));
1911 }
1912 
ReviveDidStoreRegistration(int64_t service_worker_registration_id,base::OnceClosure done_closure,blink::ServiceWorkerStatusCode status)1913 void BackgroundSyncManager::ReviveDidStoreRegistration(
1914     int64_t service_worker_registration_id,
1915     base::OnceClosure done_closure,
1916     blink::ServiceWorkerStatusCode status) {
1917   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1918 
1919   if (status == blink::ServiceWorkerStatusCode::kErrorNotFound) {
1920     // The service worker registration is gone.
1921     active_registrations_.erase(service_worker_registration_id);
1922     std::move(done_closure).Run();
1923   }
1924 
1925   if (status != blink::ServiceWorkerStatusCode::kOk) {
1926     DisableAndClearManager(std::move(done_closure));
1927     return;
1928   }
1929 
1930   std::move(done_closure).Run();
1931 }
1932 
DidReceiveDelaysForSuspendedRegistrations(base::OnceClosure callback)1933 void BackgroundSyncManager::DidReceiveDelaysForSuspendedRegistrations(
1934     base::OnceClosure callback) {
1935   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1936   ScheduleOrCancelDelayedProcessing(BackgroundSyncType::PERIODIC);
1937   base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(callback));
1938 }
1939 
ScheduleDelayedProcessingOfRegistrations(blink::mojom::BackgroundSyncType sync_type)1940 void BackgroundSyncManager::ScheduleDelayedProcessingOfRegistrations(
1941     blink::mojom::BackgroundSyncType sync_type) {
1942   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1943 
1944   auto fire_events_callback = base::BindOnce(
1945       &BackgroundSyncManager::FireReadyEvents, weak_ptr_factory_.GetWeakPtr(),
1946       sync_type, /* reschedule= */ true, base::DoNothing::Once(),
1947       /* keepalive= */ nullptr);
1948 
1949   proxy_->ScheduleDelayedProcessing(
1950       sync_type,
1951       GetSoonestWakeupDelta(sync_type,
1952                             /* last_browser_wakeup_time= */ base::Time()),
1953       std::move(fire_events_callback));
1954 }
1955 
CancelDelayedProcessingOfRegistrations(blink::mojom::BackgroundSyncType sync_type)1956 void BackgroundSyncManager::CancelDelayedProcessingOfRegistrations(
1957     blink::mojom::BackgroundSyncType sync_type) {
1958   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1959 
1960   proxy_->CancelDelayedProcessing(sync_type);
1961 }
1962 
FireReadyEvents(blink::mojom::BackgroundSyncType sync_type,bool reschedule,base::OnceClosure callback,std::unique_ptr<BackgroundSyncEventKeepAlive> keepalive)1963 void BackgroundSyncManager::FireReadyEvents(
1964     blink::mojom::BackgroundSyncType sync_type,
1965     bool reschedule,
1966     base::OnceClosure callback,
1967     std::unique_ptr<BackgroundSyncEventKeepAlive> keepalive) {
1968   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1969 
1970   if (!reschedule) {
1971     // This invocation has come from scheduled processing of registrations.
1972     // Since this delayed processing is one-off, update internal state.
1973     delayed_processing_scheduled(sync_type) = false;
1974   }
1975 
1976   auto id = op_scheduler_.CreateId();
1977   op_scheduler_.ScheduleOperation(
1978       id, CacheStorageSchedulerMode::kExclusive,
1979       CacheStorageSchedulerOp::kBackgroundSync,
1980       CacheStorageSchedulerPriority::kNormal,
1981       base::BindOnce(&BackgroundSyncManager::FireReadyEventsImpl,
1982                      weak_ptr_factory_.GetWeakPtr(), sync_type, reschedule, id,
1983                      std::move(callback), std::move(keepalive)));
1984 }
1985 
FireReadyEventsImpl(blink::mojom::BackgroundSyncType sync_type,bool reschedule,int scheduler_id,base::OnceClosure callback,std::unique_ptr<BackgroundSyncEventKeepAlive> keepalive)1986 void BackgroundSyncManager::FireReadyEventsImpl(
1987     blink::mojom::BackgroundSyncType sync_type,
1988     bool reschedule,
1989     int scheduler_id,
1990     base::OnceClosure callback,
1991     std::unique_ptr<BackgroundSyncEventKeepAlive> keepalive) {
1992   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
1993 
1994   if (disabled_) {
1995     base::ThreadTaskRunnerHandle::Get()->PostTask(
1996         FROM_HERE,
1997         op_scheduler_.WrapCallbackToRunNext(scheduler_id, std::move(callback)));
1998     return;
1999   }
2000 
2001   // Find the registrations that are ready to run.
2002   std::vector<blink::mojom::BackgroundSyncRegistrationInfoPtr> to_fire;
2003 
2004   for (auto& sw_reg_id_and_registrations : active_registrations_) {
2005     const int64_t service_worker_registration_id =
2006         sw_reg_id_and_registrations.first;
2007     for (auto& key_and_registration :
2008          sw_reg_id_and_registrations.second.registration_map) {
2009       BackgroundSyncRegistration* registration = &key_and_registration.second;
2010       if (sync_type != registration->sync_type())
2011         continue;
2012 
2013       if (IsRegistrationReadyToFire(*registration,
2014                                     service_worker_registration_id)) {
2015         to_fire.emplace_back(blink::mojom::BackgroundSyncRegistrationInfo::New(
2016             service_worker_registration_id,
2017             /* tag= */ key_and_registration.first.first,
2018             /* sync_type= */ key_and_registration.first.second));
2019 
2020         // The state change is not saved to persistent storage because
2021         // if the sync event is killed mid-sync then it should return to
2022         // SYNC_STATE_PENDING.
2023         registration->set_sync_state(blink::mojom::BackgroundSyncState::FIRING);
2024       }
2025     }
2026   }
2027 
2028   if (!reschedule) {
2029     // This method has been called from a Chrome wakeup task.
2030     BackgroundSyncMetrics::RecordEventsFiredFromWakeupTask(
2031         sync_type, /* events_fired= */ !to_fire.empty());
2032   }
2033 
2034   if (to_fire.empty()) {
2035     // TODO(crbug.com/996166): Reschedule wakeup after a non-zero delay if
2036     // called from a wakeup task.
2037     if (reschedule)
2038       ScheduleOrCancelDelayedProcessing(sync_type);
2039     base::ThreadTaskRunnerHandle::Get()->PostTask(
2040         FROM_HERE,
2041         op_scheduler_.WrapCallbackToRunNext(scheduler_id, std::move(callback)));
2042     return;
2043   }
2044 
2045   base::TimeTicks start_time = base::TimeTicks::Now();
2046 
2047   // If we've been called from a wake up task, potentially keep the browser
2048   // awake till all events have completed. If not, we only do so until all
2049   // events have been fired.
2050   // To allow the |op_scheduler_| to process other tasks after sync events
2051   // have been fired, mark this task complete after firing events.
2052   base::OnceClosure events_fired_callback, events_completed_callback;
2053   bool keep_browser_awake_till_events_complete =
2054       !reschedule && parameters_->keep_browser_awake_till_events_complete;
2055   if (keep_browser_awake_till_events_complete) {
2056     events_fired_callback = MakeEmptyCompletion(scheduler_id);
2057     events_completed_callback = std::move(callback);
2058   } else {
2059     events_fired_callback =
2060         op_scheduler_.WrapCallbackToRunNext(scheduler_id, std::move(callback));
2061     events_completed_callback = base::DoNothing::Once();
2062   }
2063 
2064   // Fire the sync event of the ready registrations and run
2065   // |events_fired_closure| once they're all done.
2066   base::RepeatingClosure events_fired_barrier_closure = base::BarrierClosure(
2067       to_fire.size(),
2068       base::BindOnce(&BackgroundSyncManager::FireReadyEventsAllEventsFiring,
2069                      weak_ptr_factory_.GetWeakPtr(), sync_type, reschedule,
2070                      std::move(events_fired_callback)));
2071 
2072   // Record the total time taken after all events have run to completion.
2073   base::RepeatingClosure events_completed_barrier_closure =
2074       base::BarrierClosure(
2075           to_fire.size(),
2076           base::BindOnce(&BackgroundSyncManager::OnAllSyncEventsCompleted,
2077                          sync_type, start_time, !reschedule, to_fire.size(),
2078                          std::move(events_completed_callback)));
2079 
2080   for (auto& registration_info : to_fire) {
2081     const BackgroundSyncRegistration* registration =
2082         LookupActiveRegistration(*registration_info);
2083     DCHECK(registration);
2084 
2085     int64_t service_worker_registration_id =
2086         registration_info->service_worker_registration_id;
2087     service_worker_context_->FindReadyRegistrationForId(
2088         service_worker_registration_id,
2089         active_registrations_[service_worker_registration_id].origin.GetURL(),
2090         base::BindOnce(
2091             &BackgroundSyncManager::FireReadyEventsDidFindRegistration,
2092             weak_ptr_factory_.GetWeakPtr(), std::move(registration_info),
2093             std::move(keepalive), events_fired_barrier_closure,
2094             events_completed_barrier_closure));
2095   }
2096 }
2097 
FireReadyEventsDidFindRegistration(blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info,std::unique_ptr<BackgroundSyncEventKeepAlive> keepalive,base::OnceClosure event_fired_callback,base::OnceClosure event_completed_callback,blink::ServiceWorkerStatusCode service_worker_status,scoped_refptr<ServiceWorkerRegistration> service_worker_registration)2098 void BackgroundSyncManager::FireReadyEventsDidFindRegistration(
2099     blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info,
2100     std::unique_ptr<BackgroundSyncEventKeepAlive> keepalive,
2101     base::OnceClosure event_fired_callback,
2102     base::OnceClosure event_completed_callback,
2103     blink::ServiceWorkerStatusCode service_worker_status,
2104     scoped_refptr<ServiceWorkerRegistration> service_worker_registration) {
2105   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
2106 
2107   BackgroundSyncRegistration* registration =
2108       LookupActiveRegistration(*registration_info);
2109 
2110   if (service_worker_status != blink::ServiceWorkerStatusCode::kOk) {
2111     if (registration)
2112       registration->set_sync_state(blink::mojom::BackgroundSyncState::PENDING);
2113     base::ThreadTaskRunnerHandle::Get()->PostTask(
2114         FROM_HERE, std::move(event_fired_callback));
2115     base::ThreadTaskRunnerHandle::Get()->PostTask(
2116         FROM_HERE, std::move(event_completed_callback));
2117     return;
2118   }
2119 
2120   DCHECK_EQ(registration_info->service_worker_registration_id,
2121             service_worker_registration->id());
2122   DCHECK(registration);
2123 
2124   // The connectivity was lost before dispatching the sync event, so there is
2125   // no point in going through with it.
2126   if (!AreOptionConditionsMet()) {
2127     registration->set_sync_state(blink::mojom::BackgroundSyncState::PENDING);
2128     base::ThreadTaskRunnerHandle::Get()->PostTask(
2129         FROM_HERE, std::move(event_fired_callback));
2130     base::ThreadTaskRunnerHandle::Get()->PostTask(
2131         FROM_HERE, std::move(event_completed_callback));
2132     return;
2133   }
2134 
2135   auto sync_type = registration_info->sync_type;
2136   UpdateNumFiringRegistrationsBy(sync_type, 1);
2137 
2138   const bool last_chance =
2139       registration->num_attempts() == registration->max_attempts() - 1;
2140 
2141   HasMainFrameWindowClient(
2142       url::Origin::Create(service_worker_registration->scope().GetOrigin()),
2143       base::BindOnce(&BackgroundSyncMetrics::RecordEventStarted, sync_type));
2144 
2145   if (sync_type == BackgroundSyncType::ONE_SHOT) {
2146     DispatchSyncEvent(
2147         registration->options()->tag,
2148         service_worker_registration->active_version(), last_chance,
2149         base::BindOnce(&BackgroundSyncManager::EventComplete,
2150                        weak_ptr_factory_.GetWeakPtr(),
2151                        service_worker_registration,
2152                        std::move(registration_info), std::move(keepalive),
2153                        std::move(event_completed_callback)));
2154   } else {
2155     DispatchPeriodicSyncEvent(
2156         registration->options()->tag,
2157         service_worker_registration->active_version(),
2158         base::BindOnce(&BackgroundSyncManager::EventComplete,
2159                        weak_ptr_factory_.GetWeakPtr(),
2160                        service_worker_registration,
2161                        std::move(registration_info), std::move(keepalive),
2162                        std::move(event_completed_callback)));
2163   }
2164 
2165   base::ThreadTaskRunnerHandle::Get()->PostTask(
2166       FROM_HERE, std::move(event_fired_callback));
2167 }
2168 
FireReadyEventsAllEventsFiring(BackgroundSyncType sync_type,bool reschedule,base::OnceClosure callback)2169 void BackgroundSyncManager::FireReadyEventsAllEventsFiring(
2170     BackgroundSyncType sync_type,
2171     bool reschedule,
2172     base::OnceClosure callback) {
2173   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
2174 
2175   if (reschedule)
2176     ScheduleOrCancelDelayedProcessing(sync_type);
2177 
2178   base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(callback));
2179 }
2180 
2181 // |service_worker_registration| is just to keep the registration alive
2182 // while the event is firing.
EventComplete(scoped_refptr<ServiceWorkerRegistration> service_worker_registration,blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info,std::unique_ptr<BackgroundSyncEventKeepAlive> keepalive,base::OnceClosure callback,blink::ServiceWorkerStatusCode status_code)2183 void BackgroundSyncManager::EventComplete(
2184     scoped_refptr<ServiceWorkerRegistration> service_worker_registration,
2185     blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info,
2186     std::unique_ptr<BackgroundSyncEventKeepAlive> keepalive,
2187     base::OnceClosure callback,
2188     blink::ServiceWorkerStatusCode status_code) {
2189   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
2190 
2191   if (disabled_) {
2192     base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
2193                                                   std::move(callback));
2194     return;
2195   }
2196 
2197   // The event ran to completion, we should count it, no matter what happens
2198   // from here.
2199   url::Origin origin =
2200       url::Origin::Create(service_worker_registration->scope().GetOrigin());
2201   HasMainFrameWindowClient(
2202       origin,
2203       base::BindOnce(&BackgroundSyncMetrics::RecordEventResult,
2204                      registration_info->sync_type,
2205                      status_code == blink::ServiceWorkerStatusCode::kOk));
2206 
2207   auto id = op_scheduler_.CreateId();
2208   op_scheduler_.ScheduleOperation(
2209       id, CacheStorageSchedulerMode::kExclusive,
2210       CacheStorageSchedulerOp::kBackgroundSync,
2211       CacheStorageSchedulerPriority::kNormal,
2212       base::BindOnce(
2213           &BackgroundSyncManager::EventCompleteImpl,
2214           weak_ptr_factory_.GetWeakPtr(), std::move(registration_info),
2215           std::move(keepalive), status_code, origin,
2216           op_scheduler_.WrapCallbackToRunNext(id, std::move(callback))));
2217 }
2218 
EventCompleteImpl(blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info,std::unique_ptr<BackgroundSyncEventKeepAlive> keepalive,blink::ServiceWorkerStatusCode status_code,const url::Origin & origin,base::OnceClosure callback)2219 void BackgroundSyncManager::EventCompleteImpl(
2220     blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info,
2221     std::unique_ptr<BackgroundSyncEventKeepAlive> keepalive,
2222     blink::ServiceWorkerStatusCode status_code,
2223     const url::Origin& origin,
2224     base::OnceClosure callback) {
2225   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
2226 
2227   if (disabled_) {
2228     base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
2229                                                   std::move(callback));
2230     return;
2231   }
2232 
2233   BackgroundSyncRegistration* registration =
2234       LookupActiveRegistration(*registration_info);
2235   if (!registration) {
2236     base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
2237                                                   std::move(callback));
2238     return;
2239   }
2240   DCHECK_NE(blink::mojom::BackgroundSyncState::PENDING,
2241             registration->sync_state());
2242 
2243   // It's important to update |num_attempts| before we update |delay_until|.
2244   bool succeeded = status_code == blink::ServiceWorkerStatusCode::kOk;
2245   registration->set_num_attempts(GetNumAttemptsAfterEvent(
2246       registration->sync_type(), registration->num_attempts(),
2247       registration->max_attempts(), registration->sync_state(), succeeded));
2248 
2249   // If |delay_until| needs to be updated, get updated delay.
2250   if (registration->sync_type() == BackgroundSyncType::PERIODIC ||
2251       (!succeeded &&
2252        registration->num_attempts() < registration->max_attempts())) {
2253     // TODO(crbug.com/824858): Remove the else branch after the feature is
2254     // enabled. Also, try to make a RunOrPostTaskOnThreadAndReplyWithResult()
2255     // function so the if/else isn't needed.
2256     if (ServiceWorkerContext::IsServiceWorkerOnUIEnabled()) {
2257       base::TimeDelta delay = GetNextEventDelay(
2258           service_worker_context_, *registration,
2259           std::make_unique<BackgroundSyncParameters>(*parameters_),
2260           GetSmallestPeriodicSyncEventDelayForOrigin(
2261               origin, registration->options()->tag));
2262       EventCompleteDidGetDelay(std::move(registration_info), status_code,
2263                                origin, std::move(callback), delay);
2264 
2265     } else {
2266       base::PostTaskAndReplyWithResult(
2267           FROM_HERE, {BrowserThread::UI},
2268           base::BindOnce(
2269               &GetNextEventDelay, service_worker_context_, *registration,
2270               std::make_unique<BackgroundSyncParameters>(*parameters_),
2271               GetSmallestPeriodicSyncEventDelayForOrigin(
2272                   origin, registration->options()->tag)),
2273           base::BindOnce(&BackgroundSyncManager::EventCompleteDidGetDelay,
2274                          weak_ptr_factory_.GetWeakPtr(),
2275                          std::move(registration_info), status_code, origin,
2276                          std::move(callback)));
2277     }
2278     return;
2279   }
2280 
2281   EventCompleteDidGetDelay(std::move(registration_info), status_code, origin,
2282                            std::move(callback), base::TimeDelta::Max());
2283 }
2284 
EventCompleteDidGetDelay(blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info,blink::ServiceWorkerStatusCode status_code,const url::Origin & origin,base::OnceClosure callback,base::TimeDelta delay)2285 void BackgroundSyncManager::EventCompleteDidGetDelay(
2286     blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info,
2287     blink::ServiceWorkerStatusCode status_code,
2288     const url::Origin& origin,
2289     base::OnceClosure callback,
2290     base::TimeDelta delay) {
2291   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
2292 
2293   UpdateNumFiringRegistrationsBy(registration_info->sync_type, -1);
2294 
2295   BackgroundSyncRegistration* registration =
2296       LookupActiveRegistration(*registration_info);
2297   if (!registration) {
2298     base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
2299                                                   std::move(callback));
2300     return;
2301   }
2302 
2303   bool succeeded = status_code == blink::ServiceWorkerStatusCode::kOk;
2304   bool can_retry = registration->num_attempts() < registration->max_attempts();
2305 
2306   bool registration_completed = true;
2307   if (registration->sync_state() ==
2308       blink::mojom::BackgroundSyncState::REREGISTERED_WHILE_FIRING) {
2309     registration->set_sync_state(blink::mojom::BackgroundSyncState::PENDING);
2310     registration->set_num_attempts(0);
2311     registration_completed = false;
2312     if (ShouldLogToDevTools(registration->sync_type())) {
2313       devtools_context_->LogBackgroundServiceEventOnCoreThread(
2314           registration_info->service_worker_registration_id, origin,
2315           GetDevToolsBackgroundService(registration->sync_type()),
2316           /* event_name= */ "Sync event reregistered",
2317           /* instance_id= */ registration_info->tag,
2318           /* event_metadata= */ {});
2319     }
2320   } else if ((!succeeded && can_retry) ||
2321              registration->sync_type() == BackgroundSyncType::PERIODIC) {
2322     registration->set_sync_state(blink::mojom::BackgroundSyncState::PENDING);
2323     registration_completed = false;
2324     registration->set_delay_until(clock_->Now() + delay);
2325 
2326     std::string event_name = GetSyncEventName(registration->sync_type()) +
2327                              (succeeded ? " event completed" : " event failed");
2328     base::TimeDelta display_delay =
2329         registration->sync_type() == BackgroundSyncType::ONE_SHOT
2330             ? delay
2331             : registration->delay_until() - clock_->Now();
2332     std::map<std::string, std::string> event_metadata = {
2333         {"Next Attempt Delay (ms)", GetDelayAsString(display_delay)}};
2334     if (!succeeded) {
2335       event_metadata.emplace("Failure Reason",
2336                              GetEventStatusString(status_code));
2337     }
2338 
2339     if (ShouldLogToDevTools(registration->sync_type())) {
2340       devtools_context_->LogBackgroundServiceEventOnCoreThread(
2341           registration_info->service_worker_registration_id, origin,
2342           GetDevToolsBackgroundService(registration->sync_type()), event_name,
2343           /* instance_id= */ registration_info->tag, event_metadata);
2344     }
2345   }
2346 
2347   if (registration_completed) {
2348     BackgroundSyncMetrics::RecordRegistrationComplete(
2349         succeeded, registration->num_attempts());
2350 
2351     if (ShouldLogToDevTools(registration->sync_type())) {
2352       devtools_context_->LogBackgroundServiceEventOnCoreThread(
2353           registration_info->service_worker_registration_id, origin,
2354           GetDevToolsBackgroundService(registration->sync_type()),
2355           /* event_name= */ "Sync completed",
2356           /* instance_id= */ registration_info->tag,
2357           {{"Status", GetEventStatusString(status_code)}});
2358     }
2359 
2360     if (registration_info->sync_type ==
2361         blink::mojom::BackgroundSyncType::ONE_SHOT) {
2362       RunOrPostTaskOnThread(
2363           FROM_HERE, BrowserThread::UI,
2364           base::BindOnce(&NotifyOneShotBackgroundSyncCompletedOnUIThread,
2365                          service_worker_context_, origin, status_code,
2366                          registration->num_attempts(),
2367                          registration->max_attempts()));
2368     } else {
2369       RunOrPostTaskOnThread(
2370           FROM_HERE, BrowserThread::UI,
2371           base::BindOnce(&NotifyPeriodicBackgroundSyncCompletedOnUIThread,
2372                          service_worker_context_, origin, status_code,
2373                          registration->num_attempts(),
2374                          registration->max_attempts()));
2375     }
2376 
2377     RemoveActiveRegistration(*registration_info);
2378   }
2379 
2380   StoreRegistrations(
2381       registration_info->service_worker_registration_id,
2382       base::BindOnce(&BackgroundSyncManager::EventCompleteDidStore,
2383                      weak_ptr_factory_.GetWeakPtr(),
2384                      registration_info->sync_type,
2385                      registration_info->service_worker_registration_id,
2386                      std::move(callback)));
2387 }
2388 
EventCompleteDidStore(blink::mojom::BackgroundSyncType sync_type,int64_t service_worker_id,base::OnceClosure callback,blink::ServiceWorkerStatusCode status_code)2389 void BackgroundSyncManager::EventCompleteDidStore(
2390     blink::mojom::BackgroundSyncType sync_type,
2391     int64_t service_worker_id,
2392     base::OnceClosure callback,
2393     blink::ServiceWorkerStatusCode status_code) {
2394   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
2395 
2396   if (status_code == blink::ServiceWorkerStatusCode::kErrorNotFound) {
2397     // The registration is gone.
2398     active_registrations_.erase(service_worker_id);
2399     base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
2400                                                   std::move(callback));
2401     return;
2402   }
2403 
2404   if (status_code != blink::ServiceWorkerStatusCode::kOk) {
2405     DisableAndClearManager(std::move(callback));
2406     return;
2407   }
2408 
2409   // Fire any ready events and call RunInBackground if anything is waiting.
2410   FireReadyEvents(sync_type, /* reschedule= */ true, base::DoNothing::Once());
2411 
2412   base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(callback));
2413 }
2414 
2415 // static
OnAllSyncEventsCompleted(BackgroundSyncType sync_type,const base::TimeTicks & start_time,bool from_wakeup_task,int number_of_batched_sync_events,base::OnceClosure callback)2416 void BackgroundSyncManager::OnAllSyncEventsCompleted(
2417     BackgroundSyncType sync_type,
2418     const base::TimeTicks& start_time,
2419     bool from_wakeup_task,
2420     int number_of_batched_sync_events,
2421     base::OnceClosure callback) {
2422   // Record the combined time taken by all sync events.
2423   BackgroundSyncMetrics::RecordBatchSyncEventComplete(
2424       sync_type, base::TimeTicks::Now() - start_time, from_wakeup_task,
2425       number_of_batched_sync_events);
2426   base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(callback));
2427 }
2428 
OnRegistrationDeletedImpl(int64_t sw_registration_id,base::OnceClosure callback)2429 void BackgroundSyncManager::OnRegistrationDeletedImpl(
2430     int64_t sw_registration_id,
2431     base::OnceClosure callback) {
2432   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
2433 
2434   // The backend (ServiceWorkerStorage) will delete the data, so just delete the
2435   // memory representation here.
2436   active_registrations_.erase(sw_registration_id);
2437   base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(callback));
2438 }
2439 
OnStorageWipedImpl(base::OnceClosure callback)2440 void BackgroundSyncManager::OnStorageWipedImpl(base::OnceClosure callback) {
2441   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
2442 
2443   active_registrations_.clear();
2444   disabled_ = false;
2445   InitImpl(std::move(callback));
2446 }
2447 
OnNetworkChanged()2448 void BackgroundSyncManager::OnNetworkChanged() {
2449   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
2450 
2451 #if defined(OS_ANDROID)
2452   if (parameters_->rely_on_android_network_detection)
2453     return;
2454 #endif
2455 
2456   if (!AreOptionConditionsMet())
2457     return;
2458 
2459   FireReadyEvents(BackgroundSyncType::ONE_SHOT, /* reschedule= */ true,
2460                   base::DoNothing::Once());
2461   FireReadyEvents(BackgroundSyncType::PERIODIC, /* reschedule= */ true,
2462                   base::DoNothing::Once());
2463 }
2464 
MakeEmptyCompletion(CacheStorageSchedulerId id)2465 base::OnceClosure BackgroundSyncManager::MakeEmptyCompletion(
2466     CacheStorageSchedulerId id) {
2467   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
2468   return op_scheduler_.WrapCallbackToRunNext(id, base::DoNothing::Once());
2469 }
2470 
CanEmulateSyncEvent(scoped_refptr<ServiceWorkerVersion> active_version)2471 blink::ServiceWorkerStatusCode BackgroundSyncManager::CanEmulateSyncEvent(
2472     scoped_refptr<ServiceWorkerVersion> active_version) {
2473   if (!active_version)
2474     return blink::ServiceWorkerStatusCode::kErrorAbort;
2475   if (!network_observer_->NetworkSufficient())
2476     return blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected;
2477   int64_t registration_id = active_version->registration_id();
2478   if (base::Contains(emulated_offline_sw_, registration_id))
2479     return blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected;
2480   return blink::ServiceWorkerStatusCode::kOk;
2481 }
2482 
ShouldLogToDevTools(BackgroundSyncType sync_type)2483 bool BackgroundSyncManager::ShouldLogToDevTools(BackgroundSyncType sync_type) {
2484   return devtools_context_->IsRecording(
2485       GetDevToolsBackgroundService(sync_type));
2486 }
2487 
2488 }  // namespace content
2489