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