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