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