// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/background_sync/background_sync_manager.h"

#include <algorithm>
#include <utility>

#include "base/barrier_closure.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/default_clock.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "content/browser/background_sync/background_sync_metrics.h"
#include "content/browser/background_sync/background_sync_network_observer.h"
#include "content/browser/service_worker/embedded_worker_status.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_storage.h"
#include "content/browser/storage_partition_impl.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/background_sync_controller.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/permission_controller.h"
#include "content/public/browser/permission_type.h"
#include "third_party/blink/public/common/service_worker/service_worker_type_converters.h"
#include "third_party/blink/public/mojom/service_worker/service_worker.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"

#if defined(OS_ANDROID)
#include "content/browser/android/background_sync_network_observer_android.h"
#endif

using blink::mojom::BackgroundSyncType;
using blink::mojom::PermissionStatus;
using SyncAndNotificationPermissions =
    std::pair<PermissionStatus, PermissionStatus>;

namespace content {

// TODO(crbug.com/932591): Use blink::mojom::BackgroundSyncError
// directly and eliminate these checks.
#define COMPILE_ASSERT_MATCHING_ENUM(mojo_name, manager_name) \
  static_assert(static_cast<int>(blink::mojo_name) ==         \
                    static_cast<int>(content::manager_name),  \
                "mojo and manager enums must match")

COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::NONE,
                             BACKGROUND_SYNC_STATUS_OK);
COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::STORAGE,
                             BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::NOT_FOUND,
                             BACKGROUND_SYNC_STATUS_NOT_FOUND);
COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::NO_SERVICE_WORKER,
                             BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER);
COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::NOT_ALLOWED,
                             BACKGROUND_SYNC_STATUS_NOT_ALLOWED);
COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::PERMISSION_DENIED,
                             BACKGROUND_SYNC_STATUS_PERMISSION_DENIED);
COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::MAX,
                             BACKGROUND_SYNC_STATUS_PERMISSION_DENIED);

namespace {

// The only allowed value of min_interval for one shot Background Sync
// registrations.
constexpr int kMinIntervalForOneShotSync = -1;

// The key used to index the background sync data in ServiceWorkerStorage.
const char kBackgroundSyncUserDataKey[] = "BackgroundSyncUserData";

void RecordFailureAndPostError(
    BackgroundSyncStatus status,
    BackgroundSyncManager::StatusAndRegistrationCallback callback) {
  BackgroundSyncMetrics::CountRegisterFailure(status);

  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::BindOnce(std::move(callback), status, nullptr));
}

// Returns nullptr if the browser context cannot be accessed for any reason.
BrowserContext* GetBrowserContextOnUIThread(
    scoped_refptr<ServiceWorkerContextWrapper> service_worker_context) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (!service_worker_context)
    return nullptr;
  StoragePartitionImpl* storage_partition_impl =
      service_worker_context->storage_partition();
  if (!storage_partition_impl)  // may be null in tests
    return nullptr;

  return storage_partition_impl->browser_context();
}

// Returns nullptr if the controller cannot be accessed for any reason.
BackgroundSyncController* GetBackgroundSyncControllerOnUIThread(
    scoped_refptr<ServiceWorkerContextWrapper> service_worker_context) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  BrowserContext* browser_context =
      GetBrowserContextOnUIThread(std::move(service_worker_context));
  if (!browser_context)
    return nullptr;

  return browser_context->GetBackgroundSyncController();
}

SyncAndNotificationPermissions GetBackgroundSyncPermissionOnUIThread(
    scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
    const url::Origin& origin,
    BackgroundSyncType sync_type) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  BrowserContext* browser_context =
      GetBrowserContextOnUIThread(std::move(service_worker_context));
  if (!browser_context)
    return {PermissionStatus::DENIED, PermissionStatus::DENIED};

  PermissionController* permission_controller =
      BrowserContext::GetPermissionController(browser_context);
  DCHECK(permission_controller);

  // The requesting origin always matches the embedding origin.
  GURL origin_url = origin.GetURL();
  auto sync_permission = permission_controller->GetPermissionStatus(
      sync_type == BackgroundSyncType::ONE_SHOT
          ? PermissionType::BACKGROUND_SYNC
          : PermissionType::PERIODIC_BACKGROUND_SYNC,
      origin_url, origin_url);
  auto notification_permission = permission_controller->GetPermissionStatus(
      PermissionType::NOTIFICATIONS, origin_url, origin_url);
  return {sync_permission, notification_permission};
}

void NotifyBackgroundSyncRegisteredOnUIThread(
    scoped_refptr<ServiceWorkerContextWrapper> sw_context_wrapper,
    const url::Origin& origin,
    bool can_fire,
    bool is_reregistered) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  BackgroundSyncController* background_sync_controller =
      GetBackgroundSyncControllerOnUIThread(std::move(sw_context_wrapper));

  if (!background_sync_controller)
    return;

  background_sync_controller->NotifyBackgroundSyncRegistered(origin, can_fire,
                                                             is_reregistered);
}

void NotifyBackgroundSyncCompletedOnUIThread(
    scoped_refptr<ServiceWorkerContextWrapper> sw_context_wrapper,
    const url::Origin& origin,
    blink::ServiceWorkerStatusCode status_code,
    int num_attempts,
    int max_attempts) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  BackgroundSyncController* background_sync_controller =
      GetBackgroundSyncControllerOnUIThread(std::move(sw_context_wrapper));

  if (!background_sync_controller)
    return;

  background_sync_controller->NotifyBackgroundSyncCompleted(
      origin, status_code, num_attempts, max_attempts);
}

void RunInBackgroundOnUIThread(
    scoped_refptr<ServiceWorkerContextWrapper> sw_context_wrapper) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  BackgroundSyncController* background_sync_controller =
      GetBackgroundSyncControllerOnUIThread(sw_context_wrapper);
  if (background_sync_controller) {
    background_sync_controller->RunInBackground();
  }
}

std::unique_ptr<BackgroundSyncParameters> GetControllerParameters(
    scoped_refptr<ServiceWorkerContextWrapper> sw_context_wrapper,
    std::unique_ptr<BackgroundSyncParameters> parameters) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  BackgroundSyncController* background_sync_controller =
      GetBackgroundSyncControllerOnUIThread(sw_context_wrapper);

  if (!background_sync_controller) {
    // If there is no controller then BackgroundSync can't run in the
    // background, disable it.
    parameters->disable = true;
    return parameters;
  }

  background_sync_controller->GetParameterOverrides(parameters.get());
  return parameters;
}

base::TimeDelta GetNextEventDelay(
    scoped_refptr<ServiceWorkerContextWrapper> sw_context_wrapper,
    const BackgroundSyncRegistration& registration,
    const url::Origin& origin,
    std::unique_ptr<BackgroundSyncParameters> parameters) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  BackgroundSyncController* background_sync_controller =
      GetBackgroundSyncControllerOnUIThread(sw_context_wrapper);

  if (!background_sync_controller)
    return base::TimeDelta::Max();

  return background_sync_controller->GetNextEventDelay(
      origin, registration.options()->min_interval, registration.num_attempts(),
      registration.sync_type(), parameters.get());
}

void OnSyncEventFinished(scoped_refptr<ServiceWorkerVersion> active_version,
                         int request_id,
                         ServiceWorkerVersion::StatusCallback callback,
                         blink::mojom::ServiceWorkerEventStatus status) {
  if (!active_version->FinishRequest(
          request_id,
          status == blink::mojom::ServiceWorkerEventStatus::COMPLETED)) {
    return;
  }
  std::move(callback).Run(
      mojo::ConvertTo<blink::ServiceWorkerStatusCode>(status));
}

void DidStartWorkerForSyncEvent(
    base::OnceCallback<void(ServiceWorkerVersion::StatusCallback)> task,
    ServiceWorkerVersion::StatusCallback callback,
    blink::ServiceWorkerStatusCode start_worker_status) {
  if (start_worker_status != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(start_worker_status);
    return;
  }
  std::move(task).Run(std::move(callback));
}

BackgroundSyncType GetBackgroundSyncType(
    const blink::mojom::SyncRegistrationOptions& options) {
  return options.min_interval == -1 ? BackgroundSyncType::ONE_SHOT
                                    : BackgroundSyncType::PERIODIC;
}

std::string GetEventStatusString(blink::ServiceWorkerStatusCode status_code) {
  // The |status_code| is derived from blink::mojom::ServiceWorkerEventStatus.
  switch (status_code) {
    case blink::ServiceWorkerStatusCode::kOk:
      return "succeeded";
    case blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected:
      return "waitUntil rejected";
    case blink::ServiceWorkerStatusCode::kErrorAbort:
      return "aborted";
    case blink::ServiceWorkerStatusCode::kErrorTimeout:
      return "timeout";
    default:
      NOTREACHED();
      return "unknown error";
  }
}

// This prevents the browser process from shutting down when the last browser
// window is closed and there are one-shot Background Sync events ready to fire.
std::unique_ptr<BackgroundSyncController::BackgroundSyncEventKeepAlive>
CreateBackgroundSyncEventKeepAliveOnUIThread(
    scoped_refptr<ServiceWorkerContextWrapper> sw_context_wrapper,
    const blink::mojom::BackgroundSyncRegistrationInfo& registration_info) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  BackgroundSyncController* controller =
      GetBackgroundSyncControllerOnUIThread(sw_context_wrapper);
  if (!controller ||
      registration_info.sync_type != BackgroundSyncType::ONE_SHOT) {
    return nullptr;
  }

  return controller->CreateBackgroundSyncEventKeepAlive();
}

}  // namespace

BackgroundSyncManager::BackgroundSyncRegistrations::
    BackgroundSyncRegistrations() = default;

BackgroundSyncManager::BackgroundSyncRegistrations::BackgroundSyncRegistrations(
    const BackgroundSyncRegistrations& other) = default;

BackgroundSyncManager::BackgroundSyncRegistrations::
    ~BackgroundSyncRegistrations() = default;

// static
std::unique_ptr<BackgroundSyncManager> BackgroundSyncManager::Create(
    scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
    scoped_refptr<DevToolsBackgroundServicesContextImpl> devtools_context) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  BackgroundSyncManager* sync_manager = new BackgroundSyncManager(
      std::move(service_worker_context), std::move(devtools_context));
  sync_manager->Init();
  return base::WrapUnique(sync_manager);
}

BackgroundSyncManager::~BackgroundSyncManager() {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  service_worker_context_->RemoveObserver(this);
}

void BackgroundSyncManager::Register(
    int64_t sw_registration_id,
    blink::mojom::SyncRegistrationOptions options,
    StatusAndRegistrationCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (disabled_) {
    RecordFailureAndPostError(BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
                              std::move(callback));
    return;
  }

  DCHECK(options.min_interval >= 0 ||
         options.min_interval == kMinIntervalForOneShotSync);

  if (GetBackgroundSyncType(options) == BackgroundSyncType::ONE_SHOT) {
    op_scheduler_.ScheduleOperation(
        CacheStorageSchedulerOp::kBackgroundSync,
        base::BindOnce(
            &BackgroundSyncManager::RegisterCheckIfHasMainFrame,
            weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
            std::move(options),
            op_scheduler_.WrapCallbackToRunNext(std::move(callback))));
  } else {
    // Periodic Background Sync events already have a pre-defined cadence which
    // the user agent decides. Don't block registration if there's no top level
    // frame at the time of registration.
    op_scheduler_.ScheduleOperation(
        CacheStorageSchedulerOp::kBackgroundSync,
        base::BindOnce(
            &BackgroundSyncManager::RegisterImpl,
            weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
            std::move(options),
            op_scheduler_.WrapCallbackToRunNext(std::move(callback))));
  }
}

void BackgroundSyncManager::UnregisterPeriodicSync(
    int64_t sw_registration_id,
    const std::string& tag,
    BackgroundSyncManager::StatusCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (disabled_) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::BindOnce(std::move(callback),
                                  BACKGROUND_SYNC_STATUS_STORAGE_ERROR));
    return;
  }

  op_scheduler_.ScheduleOperation(
      CacheStorageSchedulerOp::kBackgroundSync,
      base::BindOnce(&BackgroundSyncManager::UnregisterPeriodicSyncImpl,
                     weak_ptr_factory_.GetWeakPtr(), sw_registration_id, tag,
                     op_scheduler_.WrapCallbackToRunNext(std::move(callback))));
}

void BackgroundSyncManager::DidResolveRegistration(
    blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (disabled_)
    return;
  op_scheduler_.ScheduleOperation(
      CacheStorageSchedulerOp::kBackgroundSync,
      base::BindOnce(&BackgroundSyncManager::DidResolveRegistrationImpl,
                     weak_ptr_factory_.GetWeakPtr(),
                     std::move(registration_info)));
}

void BackgroundSyncManager::GetOneShotSyncRegistrations(
    int64_t sw_registration_id,
    StatusAndRegistrationsCallback callback) {
  GetRegistrations(BackgroundSyncType::ONE_SHOT, sw_registration_id,
                   std::move(callback));
}

void BackgroundSyncManager::GetPeriodicSyncRegistrations(
    int64_t sw_registration_id,
    StatusAndRegistrationsCallback callback) {
  GetRegistrations(BackgroundSyncType::PERIODIC, sw_registration_id,
                   std::move(callback));
}

void BackgroundSyncManager::GetRegistrations(
    BackgroundSyncType sync_type,
    int64_t sw_registration_id,
    StatusAndRegistrationsCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (disabled_) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE,
        base::BindOnce(
            std::move(callback), BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
            std::vector<std::unique_ptr<BackgroundSyncRegistration>>()));
    return;
  }

  op_scheduler_.ScheduleOperation(
      CacheStorageSchedulerOp::kBackgroundSync,
      base::BindOnce(&BackgroundSyncManager::GetRegistrationsImpl,
                     weak_ptr_factory_.GetWeakPtr(), sync_type,
                     sw_registration_id,
                     op_scheduler_.WrapCallbackToRunNext(std::move(callback))));
}

void BackgroundSyncManager::OnRegistrationDeleted(int64_t sw_registration_id,
                                                  const GURL& pattern) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  // Operations already in the queue will either fail when they write to storage
  // or return stale results based on registrations loaded in memory. This is
  // inconsequential since the service worker is gone.
  op_scheduler_.ScheduleOperation(
      CacheStorageSchedulerOp::kBackgroundSync,
      base::BindOnce(&BackgroundSyncManager::OnRegistrationDeletedImpl,
                     weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
                     MakeEmptyCompletion()));
}

void BackgroundSyncManager::OnStorageWiped() {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  // Operations already in the queue will either fail when they write to storage
  // or return stale results based on registrations loaded in memory. This is
  // inconsequential since the service workers are gone.
  op_scheduler_.ScheduleOperation(
      CacheStorageSchedulerOp::kBackgroundSync,
      base::BindOnce(&BackgroundSyncManager::OnStorageWipedImpl,
                     weak_ptr_factory_.GetWeakPtr(), MakeEmptyCompletion()));
}

void BackgroundSyncManager::SetMaxSyncAttemptsForTesting(int max_attempts) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  op_scheduler_.ScheduleOperation(
      CacheStorageSchedulerOp::kBackgroundSync,
      base::BindOnce(&BackgroundSyncManager::SetMaxSyncAttemptsImpl,
                     weak_ptr_factory_.GetWeakPtr(), max_attempts,
                     MakeEmptyCompletion()));
}

void BackgroundSyncManager::EmulateDispatchSyncEvent(
    const std::string& tag,
    scoped_refptr<ServiceWorkerVersion> active_version,
    bool last_chance,
    ServiceWorkerVersion::StatusCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  blink::ServiceWorkerStatusCode code = CanEmulateSyncEvent(active_version);
  if (code != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(code);
    return;
  }

  DispatchSyncEvent(tag, std::move(active_version), last_chance,
                    std::move(callback));
}

void BackgroundSyncManager::EmulateServiceWorkerOffline(
    int64_t service_worker_id,
    bool is_offline) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  // Multiple DevTools sessions may want to set the same SW offline, which
  // is supposed to disable the background sync. For consistency with the
  // network stack, SW remains offline until all DevTools sessions disable
  // the offline mode.
  emulated_offline_sw_[service_worker_id] += is_offline ? 1 : -1;
  if (emulated_offline_sw_[service_worker_id] > 0)
    return;
  emulated_offline_sw_.erase(service_worker_id);
  FireReadyEvents(BackgroundSyncType::ONE_SHOT, MakeEmptyCompletion());
}

BackgroundSyncManager::BackgroundSyncManager(
    scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
    scoped_refptr<DevToolsBackgroundServicesContextImpl> devtools_context)
    : op_scheduler_(CacheStorageSchedulerClient::kBackgroundSync,
                    base::ThreadTaskRunnerHandle::Get()),
      service_worker_context_(std::move(service_worker_context)),
      devtools_context_(std::move(devtools_context)),
      parameters_(std::make_unique<BackgroundSyncParameters>()),
      disabled_(false),
      num_firing_registrations_(0),
      clock_(base::DefaultClock::GetInstance()),
      weak_ptr_factory_(this) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  DCHECK(devtools_context_);

  service_worker_context_->AddObserver(this);

#if defined(OS_ANDROID)
  network_observer_ = std::make_unique<BackgroundSyncNetworkObserverAndroid>(
      base::BindRepeating(&BackgroundSyncManager::OnNetworkChanged,
                          weak_ptr_factory_.GetWeakPtr()));
#else
  network_observer_ = std::make_unique<BackgroundSyncNetworkObserver>(
      base::BindRepeating(&BackgroundSyncManager::OnNetworkChanged,
                          weak_ptr_factory_.GetWeakPtr()));
#endif
}

void BackgroundSyncManager::Init() {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  DCHECK(!op_scheduler_.ScheduledOperations());
  DCHECK(!disabled_);

  op_scheduler_.ScheduleOperation(
      CacheStorageSchedulerOp::kBackgroundSync,
      base::BindOnce(&BackgroundSyncManager::InitImpl,
                     weak_ptr_factory_.GetWeakPtr(), MakeEmptyCompletion()));
}

void BackgroundSyncManager::InitImpl(base::OnceClosure callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (disabled_) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
                                                  std::move(callback));
    return;
  }

  base::PostTaskWithTraitsAndReplyWithResult(
      FROM_HERE, {BrowserThread::UI},
      base::BindOnce(&GetControllerParameters, service_worker_context_,
                     std::make_unique<BackgroundSyncParameters>(*parameters_)),
      base::BindOnce(&BackgroundSyncManager::InitDidGetControllerParameters,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void BackgroundSyncManager::InitDidGetControllerParameters(
    base::OnceClosure callback,
    std::unique_ptr<BackgroundSyncParameters> updated_parameters) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  parameters_ = std::move(updated_parameters);
  if (parameters_->disable) {
    disabled_ = true;
    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
                                                  std::move(callback));
    return;
  }

  GetDataFromBackend(
      kBackgroundSyncUserDataKey,
      base::BindOnce(&BackgroundSyncManager::InitDidGetDataFromBackend,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void BackgroundSyncManager::InitDidGetDataFromBackend(
    base::OnceClosure callback,
    const std::vector<std::pair<int64_t, std::string>>& user_data,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (status != blink::ServiceWorkerStatusCode::kOk &&
      status != blink::ServiceWorkerStatusCode::kErrorNotFound) {
    DisableAndClearManager(std::move(callback));
    return;
  }

  for (const std::pair<int64_t, std::string>& data : user_data) {
    BackgroundSyncRegistrationsProto registrations_proto;
    if (registrations_proto.ParseFromString(data.second)) {
      BackgroundSyncRegistrations* registrations =
          &active_registrations_[data.first];
      registrations->origin =
          url::Origin::Create(GURL(registrations_proto.origin()));

      for (const auto& registration_proto :
           registrations_proto.registration()) {
        BackgroundSyncType sync_type =
            registration_proto.has_periodic_sync_options()
                ? BackgroundSyncType::PERIODIC
                : BackgroundSyncType::ONE_SHOT;
        BackgroundSyncRegistration* registration =
            &registrations
                 ->registration_map[{registration_proto.tag(), sync_type}];

        blink::mojom::SyncRegistrationOptions* options =
            registration->options();
        options->tag = registration_proto.tag();
        if (sync_type == BackgroundSyncType::PERIODIC) {
          options->min_interval =
              registration_proto.periodic_sync_options().min_interval();
          if (options->min_interval < 0) {
            DisableAndClearManager(std::move(callback));
            return;
          }
        } else {
          options->min_interval = kMinIntervalForOneShotSync;
        }

        registration->set_num_attempts(registration_proto.num_attempts());
        registration->set_delay_until(
            base::Time::FromInternalValue(registration_proto.delay_until()));
        registration->set_resolved();
        if (registration_proto.has_max_attempts())
          registration->set_max_attempts(registration_proto.max_attempts());
        else
          registration->set_max_attempts(parameters_->max_sync_attempts);
      }
    }
  }

  FireReadyEvents(BackgroundSyncType::ONE_SHOT, MakeEmptyCompletion());
  FireReadyEvents(BackgroundSyncType::PERIODIC, MakeEmptyCompletion());
  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(callback));
}

void BackgroundSyncManager::RegisterCheckIfHasMainFrame(
    int64_t sw_registration_id,
    blink::mojom::SyncRegistrationOptions options,
    StatusAndRegistrationCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  ServiceWorkerRegistration* sw_registration =
      service_worker_context_->GetLiveRegistration(sw_registration_id);
  if (!sw_registration || !sw_registration->active_version()) {
    RecordFailureAndPostError(BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER,
                              std::move(callback));
    return;
  }

  HasMainFrameProviderHost(
      url::Origin::Create(sw_registration->scope().GetOrigin()),
      base::BindOnce(&BackgroundSyncManager::RegisterDidCheckIfMainFrame,
                     weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
                     std::move(options), std::move(callback)));
}

void BackgroundSyncManager::RegisterDidCheckIfMainFrame(
    int64_t sw_registration_id,
    blink::mojom::SyncRegistrationOptions options,
    StatusAndRegistrationCallback callback,
    bool has_main_frame_client) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (!has_main_frame_client) {
    RecordFailureAndPostError(BACKGROUND_SYNC_STATUS_NOT_ALLOWED,
                              std::move(callback));
    return;
  }
  RegisterImpl(sw_registration_id, std::move(options), std::move(callback));
}

void BackgroundSyncManager::RegisterImpl(
    int64_t sw_registration_id,
    blink::mojom::SyncRegistrationOptions options,
    StatusAndRegistrationCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (disabled_) {
    RecordFailureAndPostError(BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
                              std::move(callback));
    return;
  }

  if (options.tag.length() > kMaxTagLength) {
    RecordFailureAndPostError(BACKGROUND_SYNC_STATUS_NOT_ALLOWED,
                              std::move(callback));
    return;
  }

  ServiceWorkerRegistration* sw_registration =
      service_worker_context_->GetLiveRegistration(sw_registration_id);
  if (!sw_registration || !sw_registration->active_version()) {
    RecordFailureAndPostError(BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER,
                              std::move(callback));
    return;
  }

  BackgroundSyncType sync_type = GetBackgroundSyncType(options);
  base::PostTaskWithTraitsAndReplyWithResult(
      FROM_HERE, {BrowserThread::UI},
      base::BindOnce(
          &GetBackgroundSyncPermissionOnUIThread, service_worker_context_,
          url::Origin::Create(sw_registration->scope().GetOrigin()), sync_type),
      base::BindOnce(&BackgroundSyncManager::RegisterDidAskForPermission,
                     weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
                     std::move(options), std::move(callback)));
}

void BackgroundSyncManager::RegisterDidAskForPermission(
    int64_t sw_registration_id,
    blink::mojom::SyncRegistrationOptions options,
    StatusAndRegistrationCallback callback,
    SyncAndNotificationPermissions permission_statuses) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (permission_statuses.first == PermissionStatus::DENIED) {
    RecordFailureAndPostError(BACKGROUND_SYNC_STATUS_PERMISSION_DENIED,
                              std::move(callback));
    return;
  }
  DCHECK_EQ(permission_statuses.first, PermissionStatus::GRANTED);

  ServiceWorkerRegistration* sw_registration =
      service_worker_context_->GetLiveRegistration(sw_registration_id);
  if (!sw_registration || !sw_registration->active_version()) {
    // The service worker was shut down in the interim.
    RecordFailureAndPostError(BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER,
                              std::move(callback));
    return;
  }

  BackgroundSyncRegistration* existing_registration =
      LookupActiveRegistration(blink::mojom::BackgroundSyncRegistrationInfo(
          sw_registration_id, options.tag, GetBackgroundSyncType(options)));

  url::Origin origin =
      url::Origin::Create(sw_registration->scope().GetOrigin());

  // TODO(crbug.com/925297): Record Periodic Sync metrics.
  if (GetBackgroundSyncType(options) ==
      blink::mojom::BackgroundSyncType::ONE_SHOT) {
    bool is_reregistered =
        existing_registration && existing_registration->IsFiring();
    base::PostTaskWithTraits(
        FROM_HERE, {BrowserThread::UI},
        base::BindOnce(
            &NotifyBackgroundSyncRegisteredOnUIThread, service_worker_context_,
            origin, /* can_fire= */ AreOptionConditionsMet(), is_reregistered));
  }

  if (existing_registration) {
    DCHECK_EQ(existing_registration->options()->tag, options.tag);
    if (existing_registration->options()->Equals(options)) {
      BackgroundSyncMetrics::RegistrationCouldFire registration_could_fire =
          AreOptionConditionsMet()
              ? BackgroundSyncMetrics::REGISTRATION_COULD_FIRE
              : BackgroundSyncMetrics::REGISTRATION_COULD_NOT_FIRE;
      BackgroundSyncMetrics::CountRegisterSuccess(
          registration_could_fire,
          BackgroundSyncMetrics::REGISTRATION_IS_DUPLICATE);

      if (existing_registration->IsFiring()) {
        existing_registration->set_sync_state(
            blink::mojom::BackgroundSyncState::REREGISTERED_WHILE_FIRING);
      }

      base::ThreadTaskRunnerHandle::Get()->PostTask(
          FROM_HERE,
          base::BindOnce(std::move(callback), BACKGROUND_SYNC_STATUS_OK,
                         std::make_unique<BackgroundSyncRegistration>(
                             *existing_registration)));
      return;
    }
  }

  BackgroundSyncRegistration registration;

  *registration.options() = std::move(options);

  // TODO(crbug.com/963487): This section below is really confusing. Add a
  // comment explaining what's going on here, or annotate permission_statuses.
  registration.set_max_attempts(
      permission_statuses.second == PermissionStatus::GRANTED
          ? parameters_->max_sync_attempts_with_notification_permission
          : parameters_->max_sync_attempts);

  if (registration.sync_type() == BackgroundSyncType::PERIODIC) {
    base::PostTaskWithTraitsAndReplyWithResult(
        FROM_HERE, {BrowserThread::UI},
        base::BindOnce(
            &GetNextEventDelay, service_worker_context_, registration, origin,
            std::make_unique<BackgroundSyncParameters>(*parameters_)),
        base::BindOnce(&BackgroundSyncManager::RegisterDidGetDelay,
                       weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
                       registration, std::move(callback)));
    return;
  }

  RegisterDidGetDelay(sw_registration_id, registration, std::move(callback),
                      base::TimeDelta());
}

void BackgroundSyncManager::RegisterDidGetDelay(
    int64_t sw_registration_id,
    BackgroundSyncRegistration registration,
    StatusAndRegistrationCallback callback,
    base::TimeDelta delay) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  // For one-shot registrations, we let the delay_until be in the past, so that
  // an event is fired at the soonest opportune moment.
  if (registration.sync_type() == BackgroundSyncType::PERIODIC) {
    registration.set_delay_until(clock_->Now() + delay);
  }

  ServiceWorkerRegistration* sw_registration =
      service_worker_context_->GetLiveRegistration(sw_registration_id);
  if (!sw_registration || !sw_registration->active_version()) {
    // The service worker was shut down in the interim.
    RecordFailureAndPostError(BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER,
                              std::move(callback));
    return;
  }

  AddOrUpdateActiveRegistration(
      sw_registration_id,
      url::Origin::Create(sw_registration->scope().GetOrigin()), registration);

  StoreRegistrations(
      sw_registration_id,
      base::BindOnce(&BackgroundSyncManager::RegisterDidStore,
                     weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
                     registration, std::move(callback)));
}

void BackgroundSyncManager::UnregisterPeriodicSyncImpl(
    int64_t sw_registration_id,
    const std::string& tag,
    BackgroundSyncManager::StatusCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  auto registration_info = blink::mojom::BackgroundSyncRegistrationInfo(
      sw_registration_id, tag, BackgroundSyncType::PERIODIC);

  if (!LookupActiveRegistration(registration_info)) {
    // It's okay to not find a matching tag.
    UnregisterPeriodicSyncDidStore(std::move(callback),
                                   blink::ServiceWorkerStatusCode::kOk);
    return;
  }

  RemoveActiveRegistration(std::move(registration_info));
  StoreRegistrations(
      sw_registration_id,
      base::BindOnce(&BackgroundSyncManager::UnregisterPeriodicSyncDidStore,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void BackgroundSyncManager::UnregisterPeriodicSyncDidStore(
    BackgroundSyncManager::StatusCallback callback,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (status != blink::ServiceWorkerStatusCode::kOk) {
    BackgroundSyncMetrics::CountUnregisterPeriodicSync(
        BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
    DisableAndClearManager(base::BindOnce(
        std::move(callback), BACKGROUND_SYNC_STATUS_STORAGE_ERROR));
    return;
  }

  BackgroundSyncMetrics::CountUnregisterPeriodicSync(BACKGROUND_SYNC_STATUS_OK);
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE,
      base::BindOnce(std::move(callback), BACKGROUND_SYNC_STATUS_OK));
}

void BackgroundSyncManager::DisableAndClearManager(base::OnceClosure callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (disabled_) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
                                                  std::move(callback));
    return;
  }

  disabled_ = true;

  active_registrations_.clear();

  // Delete all backend entries. The memory representation of registered syncs
  // may be out of sync with storage (e.g., due to corruption detection on
  // loading from storage), so reload the registrations from storage again.
  GetDataFromBackend(
      kBackgroundSyncUserDataKey,
      base::BindOnce(&BackgroundSyncManager::DisableAndClearDidGetRegistrations,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void BackgroundSyncManager::DisableAndClearDidGetRegistrations(
    base::OnceClosure callback,
    const std::vector<std::pair<int64_t, std::string>>& user_data,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (status != blink::ServiceWorkerStatusCode::kOk || user_data.empty()) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
                                                  std::move(callback));
    return;
  }

  base::RepeatingClosure barrier_closure =
      base::BarrierClosure(user_data.size(), std::move(callback));

  for (const auto& sw_id_and_regs : user_data) {
    service_worker_context_->ClearRegistrationUserData(
        sw_id_and_regs.first, {kBackgroundSyncUserDataKey},
        base::BindOnce(&BackgroundSyncManager::DisableAndClearManagerClearedOne,
                       weak_ptr_factory_.GetWeakPtr(), barrier_closure));
  }
}

void BackgroundSyncManager::DisableAndClearManagerClearedOne(
    base::OnceClosure barrier_closure,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  // The status doesn't matter at this point, there is nothing else to be done.
  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
                                                std::move(barrier_closure));
}

BackgroundSyncRegistration* BackgroundSyncManager::LookupActiveRegistration(
    const blink::mojom::BackgroundSyncRegistrationInfo& registration_info) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  auto it = active_registrations_.find(
      registration_info.service_worker_registration_id);
  if (it == active_registrations_.end())
    return nullptr;

  BackgroundSyncRegistrations& registrations = it->second;
  DCHECK(!registrations.origin.opaque());

  auto key_and_registration_iter = registrations.registration_map.find(
      {registration_info.tag, registration_info.sync_type});
  if (key_and_registration_iter == registrations.registration_map.end())
    return nullptr;

  return &key_and_registration_iter->second;
}

void BackgroundSyncManager::StoreRegistrations(
    int64_t sw_registration_id,
    ServiceWorkerStorage::StatusCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  // Serialize the data.
  const BackgroundSyncRegistrations& registrations =
      active_registrations_[sw_registration_id];
  BackgroundSyncRegistrationsProto registrations_proto;
  registrations_proto.set_origin(registrations.origin.Serialize());

  for (const auto& key_and_registration : registrations.registration_map) {
    const BackgroundSyncRegistration& registration =
        key_and_registration.second;
    BackgroundSyncRegistrationProto* registration_proto =
        registrations_proto.add_registration();
    registration_proto->set_tag(registration.options()->tag);
    if (registration.options()->min_interval >= 0) {
      registration_proto->mutable_periodic_sync_options()->set_min_interval(
          registration.options()->min_interval);
    }
    registration_proto->set_num_attempts(registration.num_attempts());
    registration_proto->set_max_attempts(registration.max_attempts());
    registration_proto->set_delay_until(
        registration.delay_until().ToInternalValue());
  }
  std::string serialized;
  bool success = registrations_proto.SerializeToString(&serialized);
  DCHECK(success);

  StoreDataInBackend(sw_registration_id, registrations.origin,
                     kBackgroundSyncUserDataKey, serialized,
                     std::move(callback));
}

void BackgroundSyncManager::RegisterDidStore(
    int64_t sw_registration_id,
    const BackgroundSyncRegistration& registration,
    StatusAndRegistrationCallback callback,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (status == blink::ServiceWorkerStatusCode::kErrorNotFound) {
    // The service worker registration is gone.
    active_registrations_.erase(sw_registration_id);
    RecordFailureAndPostError(BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
                              std::move(callback));
    return;
  }

  if (status != blink::ServiceWorkerStatusCode::kOk) {
    BackgroundSyncMetrics::CountRegisterFailure(
        BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
    DisableAndClearManager(base::BindOnce(
        std::move(callback), BACKGROUND_SYNC_STATUS_STORAGE_ERROR, nullptr));
    return;
  }

  BackgroundSyncMetrics::RegistrationCouldFire registration_could_fire =
      AreOptionConditionsMet()
          ? BackgroundSyncMetrics::REGISTRATION_COULD_FIRE
          : BackgroundSyncMetrics::REGISTRATION_COULD_NOT_FIRE;
  BackgroundSyncMetrics::CountRegisterSuccess(
      registration_could_fire,
      BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE);

  // TODO(crbug.com/925297): Schedule or update a wake up task for periodic
  // Background Sync registrations.

  // Tell the client that the registration is ready. We won't fire it until the
  // client has resolved the registration event.
  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::BindOnce(std::move(callback), BACKGROUND_SYNC_STATUS_OK,
                                std::make_unique<BackgroundSyncRegistration>(
                                    registration)));
}

void BackgroundSyncManager::DidResolveRegistrationImpl(
    blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  BackgroundSyncRegistration* registration =
      LookupActiveRegistration(*registration_info);
  if (!registration) {
    // There might not be a registration if the client ack's a registration that
    // was a duplicate in the first place and was already firing and finished by
    // the time the client acknowledged the second registration.
    op_scheduler_.CompleteOperationAndRunNext();
    return;
  }

  registration->set_resolved();
  base::PostTaskWithTraitsAndReplyWithResult(
      FROM_HERE, {BrowserThread::UI},
      base::BindOnce(&CreateBackgroundSyncEventKeepAliveOnUIThread,
                     service_worker_context_, std::move(*registration_info)),
      base::BindOnce(
          &BackgroundSyncManager::ResolveRegistrationDidCreateKeepAlive,
          weak_ptr_factory_.GetWeakPtr()));
}

void BackgroundSyncManager::ResolveRegistrationDidCreateKeepAlive(
    std::unique_ptr<BackgroundSyncEventKeepAlive> keepalive) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  FireReadyEvents(BackgroundSyncType::ONE_SHOT, MakeEmptyCompletion(),
                  std::move(keepalive));
  op_scheduler_.CompleteOperationAndRunNext();
}

void BackgroundSyncManager::RemoveActiveRegistration(
    const blink::mojom::BackgroundSyncRegistrationInfo& registration_info) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  DCHECK(LookupActiveRegistration(registration_info));

  BackgroundSyncRegistrations* registrations =
      &active_registrations_[registration_info.service_worker_registration_id];

  registrations->registration_map.erase(
      {registration_info.tag, registration_info.sync_type});
}

void BackgroundSyncManager::AddOrUpdateActiveRegistration(
    int64_t sw_registration_id,
    const url::Origin& origin,
    const BackgroundSyncRegistration& sync_registration) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  BackgroundSyncRegistrations* registrations =
      &active_registrations_[sw_registration_id];
  registrations->origin = origin;

  BackgroundSyncType sync_type = sync_registration.sync_type();
  registrations
      ->registration_map[{sync_registration.options()->tag, sync_type}] =
      sync_registration;

  if (ShouldLogToDevTools(sync_type)) {
    devtools_context_->LogBackgroundServiceEventOnIO(
        sw_registration_id, origin, DevToolsBackgroundService::kBackgroundSync,
        /* event_name= */ "Registered sync",
        /* instance_id= */ sync_registration.options()->tag,
        /* event_metadata= */ {});
  }
}

void BackgroundSyncManager::StoreDataInBackend(
    int64_t sw_registration_id,
    const url::Origin& origin,
    const std::string& backend_key,
    const std::string& data,
    ServiceWorkerStorage::StatusCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  service_worker_context_->StoreRegistrationUserData(
      sw_registration_id, origin.GetURL(), {{backend_key, data}},
      std::move(callback));
}

void BackgroundSyncManager::GetDataFromBackend(
    const std::string& backend_key,
    ServiceWorkerStorage::GetUserDataForAllRegistrationsCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  service_worker_context_->GetUserDataForAllRegistrations(backend_key,
                                                          std::move(callback));
}

void BackgroundSyncManager::DispatchSyncEvent(
    const std::string& tag,
    scoped_refptr<ServiceWorkerVersion> active_version,
    bool last_chance,
    ServiceWorkerVersion::StatusCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  DCHECK(active_version);

  if (active_version->running_status() != EmbeddedWorkerStatus::RUNNING) {
    active_version->RunAfterStartWorker(
        ServiceWorkerMetrics::EventType::SYNC,
        base::BindOnce(&DidStartWorkerForSyncEvent,
                       base::BindOnce(&BackgroundSyncManager::DispatchSyncEvent,
                                      weak_ptr_factory_.GetWeakPtr(), tag,
                                      active_version, last_chance),
                       std::move(callback)));
    return;
  }

  auto repeating_callback =
      base::AdaptCallbackForRepeating(std::move(callback));

  int request_id = active_version->StartRequestWithCustomTimeout(
      ServiceWorkerMetrics::EventType::SYNC, repeating_callback,
      parameters_->max_sync_event_duration,
      ServiceWorkerVersion::CONTINUE_ON_TIMEOUT);

  active_version->endpoint()->DispatchSyncEvent(
      tag, last_chance, parameters_->max_sync_event_duration,
      base::BindOnce(&OnSyncEventFinished, active_version, request_id,
                     std::move(repeating_callback)));

  if (devtools_context_->IsRecording(
          DevToolsBackgroundService::kBackgroundSync)) {
    devtools_context_->LogBackgroundServiceEventOnIO(
        active_version->registration_id(), active_version->script_origin(),
        DevToolsBackgroundService::kBackgroundSync,
        /* event_name= */ "Dispatched sync event",
        /* instance_id= */ tag,
        /* event_metadata= */
        {{"Last Chance", last_chance ? "Yes" : "No"}});
  }
}

void BackgroundSyncManager::DispatchPeriodicSyncEvent(
    const std::string& tag,
    scoped_refptr<ServiceWorkerVersion> active_version,
    ServiceWorkerVersion::StatusCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  DCHECK(active_version);

  if (active_version->running_status() != EmbeddedWorkerStatus::RUNNING) {
    active_version->RunAfterStartWorker(
        ServiceWorkerMetrics::EventType::PERIODIC_SYNC,
        base::BindOnce(
            &DidStartWorkerForSyncEvent,
            base::BindOnce(&BackgroundSyncManager::DispatchPeriodicSyncEvent,
                           weak_ptr_factory_.GetWeakPtr(), tag, active_version),
            std::move(callback)));
    return;
  }

  auto repeating_callback =
      base::AdaptCallbackForRepeating(std::move(callback));

  int request_id = active_version->StartRequestWithCustomTimeout(
      ServiceWorkerMetrics::EventType::PERIODIC_SYNC, repeating_callback,
      parameters_->max_sync_event_duration,
      ServiceWorkerVersion::CONTINUE_ON_TIMEOUT);

  active_version->endpoint()->DispatchPeriodicSyncEvent(
      tag, parameters_->max_sync_event_duration,
      base::BindOnce(&OnSyncEventFinished, active_version, request_id,
                     std::move(repeating_callback)));

  // TODO(crbug.com/961238): Record Periodic Sync events for DevTools.
}

void BackgroundSyncManager::ScheduleDelayedTask(base::OnceClosure callback,
                                                base::TimeDelta delay) {
  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
      FROM_HERE, std::move(callback), delay);
}

void BackgroundSyncManager::HasMainFrameProviderHost(const url::Origin& origin,
                                                     BoolCallback callback) {
  service_worker_context_->HasMainFrameProviderHost(origin.GetURL(),
                                                    std::move(callback));
}

void BackgroundSyncManager::GetRegistrationsImpl(
    BackgroundSyncType sync_type,
    int64_t sw_registration_id,
    StatusAndRegistrationsCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  std::vector<std::unique_ptr<BackgroundSyncRegistration>> out_registrations;

  if (disabled_) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::BindOnce(std::move(callback),
                                  BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
                                  std::move(out_registrations)));
    return;
  }

  auto it = active_registrations_.find(sw_registration_id);

  if (it != active_registrations_.end()) {
    const BackgroundSyncRegistrations& registrations = it->second;
    for (const auto& key_and_registration : registrations.registration_map) {
      const BackgroundSyncRegistration& registration =
          key_and_registration.second;
      if (registration.sync_type() != sync_type)
        continue;
      out_registrations.push_back(
          std::make_unique<BackgroundSyncRegistration>(registration));
    }
  }

  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::BindOnce(std::move(callback), BACKGROUND_SYNC_STATUS_OK,
                                std::move(out_registrations)));
}

bool BackgroundSyncManager::AreOptionConditionsMet() {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  return network_observer_->NetworkSufficient();
}

bool BackgroundSyncManager::IsRegistrationReadyToFire(
    const BackgroundSyncRegistration& registration,
    int64_t service_worker_id) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  // Don't fire the registration if the client hasn't yet resolved its
  // registration promise.
  if (!registration.resolved())
    return false;

  if (registration.sync_state() != blink::mojom::BackgroundSyncState::PENDING)
    return false;

  if (clock_->Now() < registration.delay_until())
    return false;

  if (base::Contains(emulated_offline_sw_, service_worker_id))
    return false;

  return AreOptionConditionsMet();
}

base::TimeDelta BackgroundSyncManager::GetSoonestWakeupDelta(
    BackgroundSyncType sync_type) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  base::TimeDelta soonest_wakeup_delta = base::TimeDelta::Max();
  for (const auto& sw_reg_id_and_registrations : active_registrations_) {
    for (const auto& key_and_registration :
         sw_reg_id_and_registrations.second.registration_map) {
      const BackgroundSyncRegistration& registration =
          key_and_registration.second;
      if (registration.sync_type() != sync_type)
        continue;
      if (registration.sync_state() ==
          blink::mojom::BackgroundSyncState::PENDING) {
        if (clock_->Now() >= registration.delay_until()) {
          soonest_wakeup_delta = base::TimeDelta();
          break;
        } else {
          base::TimeDelta delay_delta =
              registration.delay_until() - clock_->Now();
          soonest_wakeup_delta = std::min(delay_delta, soonest_wakeup_delta);
        }
      }
    }
  }

  // If the browser is closed while firing events, the browser needs a task to
  // wake it back up and try again.
  if (sync_type == BackgroundSyncType::ONE_SHOT &&
      num_firing_registrations_ > 0 &&
      soonest_wakeup_delta > parameters_->min_sync_recovery_time) {
    soonest_wakeup_delta = parameters_->min_sync_recovery_time;
  }

  return soonest_wakeup_delta;
}

// TODO(crbug.com/925297): Update to also schedule a wakeup task for Periodic
// Background Sync.
void BackgroundSyncManager::RunInBackgroundIfNecessary() {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  base::TimeDelta soonest_wakeup_delta =
      GetSoonestWakeupDelta(BackgroundSyncType::ONE_SHOT);

  // Try firing again after the wakeup delta.
  if (!soonest_wakeup_delta.is_max() && !soonest_wakeup_delta.is_zero()) {
    delayed_sync_task_.Reset(base::BindOnce(
        &BackgroundSyncManager::FireReadyEvents, weak_ptr_factory_.GetWeakPtr(),
        BackgroundSyncType::ONE_SHOT, MakeEmptyCompletion(),
        /* keepalive= */ nullptr));
    ScheduleDelayedTask(delayed_sync_task_.callback(), soonest_wakeup_delta);
  }

  // In case the browser closes (or to prevent it from closing), call
  // RunInBackground to wake up the browser at the wakeup delta.
  base::PostTaskWithTraits(
      FROM_HERE, {BrowserThread::UI},
      base::BindOnce(RunInBackgroundOnUIThread, service_worker_context_));
}

void BackgroundSyncManager::FireReadyEvents(
    blink::mojom::BackgroundSyncType sync_type,
    base::OnceClosure callback,
    std::unique_ptr<BackgroundSyncEventKeepAlive> keepalive) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (disabled_)
    return;

  op_scheduler_.ScheduleOperation(
      CacheStorageSchedulerOp::kBackgroundSync,
      base::BindOnce(&BackgroundSyncManager::FireReadyEventsImpl,
                     weak_ptr_factory_.GetWeakPtr(), sync_type,
                     std::move(callback), std::move(keepalive)));
}

void BackgroundSyncManager::FireReadyEventsImpl(
    blink::mojom::BackgroundSyncType sync_type,
    base::OnceClosure callback,
    std::unique_ptr<BackgroundSyncEventKeepAlive> keepalive) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (disabled_) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
                                                  std::move(callback));
    return;
  }

  // Find the registrations that are ready to run.
  // TODO(crbug.com/925297): Periodically re-evaluate suspended Periodic Sync
  // registrations.
  std::vector<blink::mojom::BackgroundSyncRegistrationInfoPtr> to_fire;

  for (auto& sw_reg_id_and_registrations : active_registrations_) {
    const int64_t service_worker_registration_id =
        sw_reg_id_and_registrations.first;
    for (auto& key_and_registration :
         sw_reg_id_and_registrations.second.registration_map) {
      BackgroundSyncRegistration* registration = &key_and_registration.second;
      if (sync_type != registration->sync_type())
        continue;

      if (IsRegistrationReadyToFire(*registration,
                                    service_worker_registration_id)) {
        to_fire.emplace_back(blink::mojom::BackgroundSyncRegistrationInfo::New(
            service_worker_registration_id,
            /* tag= */ key_and_registration.first.first,
            /* sync_type= */ key_and_registration.first.second));

        // The state change is not saved to persistent storage because
        // if the sync event is killed mid-sync then it should return to
        // SYNC_STATE_PENDING.
        registration->set_sync_state(blink::mojom::BackgroundSyncState::FIRING);
      }
    }
  }

  if (to_fire.empty()) {
    RunInBackgroundIfNecessary();
    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
                                                  std::move(callback));
    return;
  }

  base::TimeTicks start_time = base::TimeTicks::Now();

  // Fire the sync event of the ready registrations and run |callback| once
  // they're all done.
  base::RepeatingClosure events_fired_barrier_closure = base::BarrierClosure(
      to_fire.size(),
      base::BindOnce(&BackgroundSyncManager::FireReadyEventsAllEventsFiring,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));

  // Record the total time taken after all events have run to completion.
  base::RepeatingClosure events_completed_barrier_closure =
      base::BarrierClosure(to_fire.size(),
                           base::BindOnce(&OnAllSyncEventsCompleted, start_time,
                                          to_fire.size()));

  for (auto& registration_info : to_fire) {
    const BackgroundSyncRegistration* registration =
        LookupActiveRegistration(*registration_info);
    DCHECK(registration);

    int64_t service_worker_registration_id =
        registration_info->service_worker_registration_id;
    service_worker_context_->FindReadyRegistrationForId(
        service_worker_registration_id,
        active_registrations_[service_worker_registration_id].origin.GetURL(),
        base::BindOnce(
            &BackgroundSyncManager::FireReadyEventsDidFindRegistration,
            weak_ptr_factory_.GetWeakPtr(), std::move(registration_info),
            std::move(keepalive), events_fired_barrier_closure,
            events_completed_barrier_closure));
  }
}

void BackgroundSyncManager::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) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  BackgroundSyncRegistration* registration =
      LookupActiveRegistration(*registration_info);

  if (service_worker_status != blink::ServiceWorkerStatusCode::kOk) {
    if (registration)
      registration->set_sync_state(blink::mojom::BackgroundSyncState::PENDING);
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, std::move(event_fired_callback));
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, std::move(event_completed_callback));
    return;
  }

  DCHECK_EQ(registration_info->service_worker_registration_id,
            service_worker_registration->id());
  DCHECK(registration);

  // The connectivity was lost before dispatching the sync event, so there is
  // no point in going through with it.
  if (!AreOptionConditionsMet()) {
    registration->set_sync_state(blink::mojom::BackgroundSyncState::PENDING);
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, std::move(event_fired_callback));
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, std::move(event_completed_callback));
    return;
  }

  num_firing_registrations_ += 1;

  const bool last_chance =
      registration->num_attempts() == registration->max_attempts() - 1;

  HasMainFrameProviderHost(
      url::Origin::Create(service_worker_registration->scope().GetOrigin()),
      base::BindOnce(&BackgroundSyncMetrics::RecordEventStarted));

  auto sync_type = registration_info->sync_type;
  if (sync_type == BackgroundSyncType::ONE_SHOT) {
    DispatchSyncEvent(
        registration->options()->tag,
        service_worker_registration->active_version(), last_chance,
        base::BindOnce(&BackgroundSyncManager::EventComplete,
                       weak_ptr_factory_.GetWeakPtr(),
                       service_worker_registration,
                       std::move(registration_info), std::move(keepalive),
                       std::move(event_completed_callback)));
  } else {
    DispatchPeriodicSyncEvent(
        registration->options()->tag,
        service_worker_registration->active_version(),
        base::BindOnce(&BackgroundSyncManager::EventComplete,
                       weak_ptr_factory_.GetWeakPtr(),
                       service_worker_registration,
                       std::move(registration_info), std::move(keepalive),
                       std::move(event_completed_callback)));
  }

  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, std::move(event_fired_callback));
}

void BackgroundSyncManager::FireReadyEventsAllEventsFiring(
    base::OnceClosure callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  RunInBackgroundIfNecessary();
  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(callback));
}

// |service_worker_registration| is just to keep the registration alive
// while the event is firing.
void BackgroundSyncManager::EventComplete(
    scoped_refptr<ServiceWorkerRegistration> service_worker_registration,
    blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info,
    std::unique_ptr<BackgroundSyncEventKeepAlive> keepalive,
    base::OnceClosure callback,
    blink::ServiceWorkerStatusCode status_code) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (disabled_) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
                                                  std::move(callback));
    return;
  }

  // The event ran to completion, we should count it, no matter what happens
  // from here.
  url::Origin origin =
      url::Origin::Create(service_worker_registration->scope().GetOrigin());
  HasMainFrameProviderHost(
      origin,
      base::BindOnce(&BackgroundSyncMetrics::RecordEventResult,
                     status_code == blink::ServiceWorkerStatusCode::kOk));

  op_scheduler_.ScheduleOperation(
      CacheStorageSchedulerOp::kBackgroundSync,
      base::BindOnce(&BackgroundSyncManager::EventCompleteImpl,
                     weak_ptr_factory_.GetWeakPtr(),
                     std::move(registration_info), std::move(keepalive),
                     status_code, origin,
                     op_scheduler_.WrapCallbackToRunNext(std::move(callback))));
}

void BackgroundSyncManager::EventCompleteImpl(
    blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info,
    std::unique_ptr<BackgroundSyncEventKeepAlive> keepalive,
    blink::ServiceWorkerStatusCode status_code,
    const url::Origin& origin,
    base::OnceClosure callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (disabled_) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
                                                  std::move(callback));
    return;
  }

  num_firing_registrations_ -= 1;

  BackgroundSyncRegistration* registration =
      LookupActiveRegistration(*registration_info);
  if (!registration) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
                                                  std::move(callback));
    return;
  }
  DCHECK_NE(blink::mojom::BackgroundSyncState::PENDING,
            registration->sync_state());

  // It's important to update |num_attempts| before we update |delay_until|.
  registration->set_num_attempts(registration->num_attempts() + 1);
  if ((registration->sync_type() == BackgroundSyncType::PERIODIC &&
       registration->num_attempts() == registration->max_attempts()) ||
      (registration->sync_state() ==
       blink::mojom::BackgroundSyncState::REREGISTERED_WHILE_FIRING)) {
    registration->set_num_attempts(0);
  }

  // If |delay_until| needs to be updated, get updated delay.
  bool succeeded = status_code == blink::ServiceWorkerStatusCode::kOk;
  if (registration->sync_type() == BackgroundSyncType::PERIODIC ||
      (!succeeded &&
       registration->num_attempts() < registration->max_attempts())) {
    base::PostTaskWithTraitsAndReplyWithResult(
        FROM_HERE, {BrowserThread::UI},
        base::BindOnce(
            &GetNextEventDelay, service_worker_context_, *registration, origin,
            std::make_unique<BackgroundSyncParameters>(*parameters_)),
        base::BindOnce(&BackgroundSyncManager::EventCompleteDidGetDelay,
                       weak_ptr_factory_.GetWeakPtr(),
                       std::move(registration_info), status_code, origin,
                       std::move(callback)));
    return;
  }

  EventCompleteDidGetDelay(std::move(registration_info), status_code, origin,
                           std::move(callback), base::TimeDelta::Max());
}

void BackgroundSyncManager::EventCompleteDidGetDelay(
    blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info,
    blink::ServiceWorkerStatusCode status_code,
    const url::Origin& origin,
    base::OnceClosure callback,
    base::TimeDelta delay) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  BackgroundSyncRegistration* registration =
      LookupActiveRegistration(*registration_info);
  if (!registration) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
                                                  std::move(callback));
    return;
  }

  bool succeeded = status_code == blink::ServiceWorkerStatusCode::kOk;
  bool can_retry = registration->num_attempts() < registration->max_attempts();

  bool registration_completed = true;
  if (registration->sync_state() ==
      blink::mojom::BackgroundSyncState::REREGISTERED_WHILE_FIRING) {
    registration->set_sync_state(blink::mojom::BackgroundSyncState::PENDING);
    registration->set_num_attempts(0);
    registration_completed = false;
    if (ShouldLogToDevTools(registration->sync_type())) {
      devtools_context_->LogBackgroundServiceEventOnIO(
          registration_info->service_worker_registration_id, origin,
          DevToolsBackgroundService::kBackgroundSync,
          /* event_name= */ "Sync event reregistered",
          /* instance_id= */ registration_info->tag,
          /* event_metadata= */ {});
    }
  } else if ((!succeeded && can_retry) ||
             registration->sync_type() == BackgroundSyncType::PERIODIC) {
    registration->set_sync_state(blink::mojom::BackgroundSyncState::PENDING);
    registration_completed = false;
    registration->set_delay_until(clock_->Now() + delay);

    if (ShouldLogToDevTools(registration->sync_type())) {
      std::string delay_ms = delay.is_max()
                                 ? "infinite"
                                 : base::NumberToString(delay.InMilliseconds());
      devtools_context_->LogBackgroundServiceEventOnIO(
          registration_info->service_worker_registration_id, origin,
          DevToolsBackgroundService::kBackgroundSync,
          /* event_name= */ "Sync event failed",
          /* instance_id= */ registration_info->tag,
          {{"Next Attempt Delay (ms)", delay_ms},
           {"Failure Reason", GetEventStatusString(status_code)}});
    }
  }

  if (registration_completed) {
    BackgroundSyncMetrics::RecordRegistrationComplete(
        succeeded, registration->num_attempts());

    if (ShouldLogToDevTools(registration->sync_type())) {
      devtools_context_->LogBackgroundServiceEventOnIO(
          registration_info->service_worker_registration_id, origin,
          DevToolsBackgroundService::kBackgroundSync,
          /* event_name= */ "Sync completed",
          /* instance_id= */ registration_info->tag,
          {{"Status", GetEventStatusString(status_code)}});
    }

    if (registration_info->sync_type ==
        blink::mojom::BackgroundSyncType::ONE_SHOT) {
      base::PostTaskWithTraits(
          FROM_HERE, {BrowserThread::UI},
          base::BindOnce(&NotifyBackgroundSyncCompletedOnUIThread,
                         service_worker_context_, origin, status_code,
                         registration->num_attempts(),
                         registration->max_attempts()));
    }

    RemoveActiveRegistration(*registration_info);
  }

  StoreRegistrations(
      registration_info->service_worker_registration_id,
      base::BindOnce(&BackgroundSyncManager::EventCompleteDidStore,
                     weak_ptr_factory_.GetWeakPtr(),
                     registration_info->service_worker_registration_id,
                     std::move(callback)));
}

void BackgroundSyncManager::EventCompleteDidStore(
    int64_t service_worker_id,
    base::OnceClosure callback,
    blink::ServiceWorkerStatusCode status_code) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (status_code == blink::ServiceWorkerStatusCode::kErrorNotFound) {
    // The registration is gone.
    active_registrations_.erase(service_worker_id);
    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
                                                  std::move(callback));
    return;
  }

  if (status_code != blink::ServiceWorkerStatusCode::kOk) {
    DisableAndClearManager(std::move(callback));
    return;
  }

  // Fire any ready events and call RunInBackground if anything is waiting.
  // We don't need to do this for periodic Background Sync registrations, since
  // once all events have been dispatched, we'll schedule a delayed task to
  // (wake up Chrome and) fire the next set of periodicsync events.
  FireReadyEvents(BackgroundSyncType::ONE_SHOT, MakeEmptyCompletion());

  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(callback));
}

// static
void BackgroundSyncManager::OnAllSyncEventsCompleted(
    const base::TimeTicks& start_time,
    int number_of_batched_sync_events) {
  // Record the combined time taken by all sync events.
  BackgroundSyncMetrics::RecordBatchSyncEventComplete(
      base::TimeTicks::Now() - start_time, number_of_batched_sync_events);
}

void BackgroundSyncManager::OnRegistrationDeletedImpl(
    int64_t sw_registration_id,
    base::OnceClosure callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  // The backend (ServiceWorkerStorage) will delete the data, so just delete the
  // memory representation here.
  active_registrations_.erase(sw_registration_id);
  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(callback));
}

void BackgroundSyncManager::OnStorageWipedImpl(base::OnceClosure callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  active_registrations_.clear();
  disabled_ = false;
  InitImpl(std::move(callback));
}

void BackgroundSyncManager::OnNetworkChanged() {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  FireReadyEvents(BackgroundSyncType::ONE_SHOT, MakeEmptyCompletion());
  FireReadyEvents(BackgroundSyncType::PERIODIC, MakeEmptyCompletion());
}

void BackgroundSyncManager::SetMaxSyncAttemptsImpl(int max_attempts,
                                                   base::OnceClosure callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  parameters_->max_sync_attempts = max_attempts;
  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(callback));
}

base::OnceClosure BackgroundSyncManager::MakeEmptyCompletion() {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  return op_scheduler_.WrapCallbackToRunNext(base::DoNothing::Once());
}

blink::ServiceWorkerStatusCode BackgroundSyncManager::CanEmulateSyncEvent(
    scoped_refptr<ServiceWorkerVersion> active_version) {
  if (!active_version)
    return blink::ServiceWorkerStatusCode::kErrorAbort;
  if (!network_observer_->NetworkSufficient())
    return blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected;
  int64_t registration_id = active_version->registration_id();
  if (base::Contains(emulated_offline_sw_, registration_id))
    return blink::ServiceWorkerStatusCode::kErrorEventWaitUntilRejected;
  return blink::ServiceWorkerStatusCode::kOk;
}

bool BackgroundSyncManager::ShouldLogToDevTools(BackgroundSyncType sync_type) {
  return sync_type == BackgroundSyncType::ONE_SHOT &&
         devtools_context_->IsRecording(
             DevToolsBackgroundService::kBackgroundSync);
}

}  // namespace content
