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

#ifndef CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_MANAGER_H_
#define CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_MANAGER_H_

#include <stddef.h>
#include <stdint.h>

#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "base/cancelable_callback.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/time/clock.h"
#include "base/time/time.h"
#include "content/browser/background_sync/background_sync.pb.h"
#include "content/browser/background_sync/background_sync_op_scheduler.h"
#include "content/browser/background_sync/background_sync_proxy.h"
#include "content/browser/background_sync/background_sync_status.h"
#include "content/browser/devtools/devtools_background_services_context_impl.h"
#include "content/browser/service_worker/service_worker_context_core_observer.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_registry.h"
#include "content/common/content_export.h"
#include "content/public/browser/background_sync_controller.h"
#include "content/public/browser/background_sync_parameters.h"
#include "content/public/browser/background_sync_registration.h"
#include "content/public/browser/browser_thread.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/mojom/background_sync/background_sync.mojom.h"
#include "third_party/blink/public/mojom/permissions/permission_status.mojom.h"
#include "url/gurl.h"
#include "url/origin.h"

namespace blink {
namespace mojom {
enum class PermissionStatus;
}  // namespace mojom
class StorageKey;
}  // namespace blink

namespace content {

class BackgroundSyncNetworkObserver;
class ServiceWorkerContextWrapper;

// BackgroundSyncManager manages and stores the set of background sync
// registrations across all registered service workers for a profile.
// Registrations are stored along with their associated Service Worker
// registration in ServiceWorkerStorage. If the ServiceWorker is unregistered,
// the sync registrations are removed. This class runs on the UI thread.
// The asynchronous methods are executed sequentially.
class CONTENT_EXPORT BackgroundSyncManager
    : public ServiceWorkerContextCoreObserver {
 public:
  using BoolCallback = base::OnceCallback<void(bool)>;
  using StatusCallback = base::OnceCallback<void(BackgroundSyncStatus)>;
  using StatusAndRegistrationCallback =
      base::OnceCallback<void(BackgroundSyncStatus,
                              std::unique_ptr<BackgroundSyncRegistration>)>;
  using StatusAndRegistrationsCallback = base::OnceCallback<void(
      BackgroundSyncStatus,
      std::vector<std::unique_ptr<BackgroundSyncRegistration>>)>;
  using BackgroundSyncEventKeepAlive =
      BackgroundSyncController::BackgroundSyncEventKeepAlive;

  static std::unique_ptr<BackgroundSyncManager> Create(
      scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
      scoped_refptr<DevToolsBackgroundServicesContextImpl> devtools_context);

  BackgroundSyncManager(const BackgroundSyncManager&) = delete;
  BackgroundSyncManager& operator=(const BackgroundSyncManager&) = delete;

  ~BackgroundSyncManager() override;

  // Stores the given background sync registration and adds it to the scheduling
  // queue. It will overwrite an existing registration with the same tag unless
  // they're identical (save for the id). Calls |callback| with
  // BACKGROUND_SYNC_STATUS_OK and the accepted registration on success.
  // The accepted registration will have a unique id. It may also have altered
  // parameters if the user or UA chose different parameters than those
  // supplied.
  void Register(int64_t sw_registration_id,
                int render_process_host_id,
                blink::mojom::SyncRegistrationOptions options,
                StatusAndRegistrationCallback callback);

  // Removes the Periodic Background Sync registration identified by |tag| for
  // the service worker identified by |sw_registration_id|. Calls |callback|
  // with BACKGROUND_SYNC_STATUS_OK on success.
  void UnregisterPeriodicSync(int64_t sw_registration_id,
                              const std::string& tag,
                              StatusCallback callback);

  // Called after the client has resolved its registration promise. At this
  // point it's safe to fire any pending registrations.
  void DidResolveRegistration(
      blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info);

  // Finds the one-shot Background Sync registrations associated with
  // |sw_registration_id|. Calls |callback| with BACKGROUND_SYNC_STATUS_OK on
  // success.
  void GetOneShotSyncRegistrations(int64_t sw_registration_id,
                                   StatusAndRegistrationsCallback callback);

  // Finds the periodic Background Sync registrations associated with
  // |sw_registration_id|. Calls |callback| with BACKGROUND_SYNC_STATUS_OK on
  // success.
  void GetPeriodicSyncRegistrations(int64_t sw_registration_id,
                                    StatusAndRegistrationsCallback callback);

  // Goes through the list of active Periodic Background Sync registrations and
  // unregisters any origins that no longer have the required permission.
  void UnregisterPeriodicSyncForOrigin(const url::Origin& origin);

  // ServiceWorkerContextCoreObserver overrides.
  void OnRegistrationDeleted(int64_t sw_registration_id,
                             const GURL& pattern,
                             const blink::StorageKey& key) override;
  void OnStorageWiped() override;

  BackgroundSyncNetworkObserver* GetNetworkObserverForTesting() {
    return network_observer_.get();
  }

  void set_clock(base::Clock* clock) {
    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
    clock_ = clock;
  }

  void set_proxy_for_testing(std::unique_ptr<BackgroundSyncProxy> proxy) {
    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
    proxy_ = std::move(proxy);
  }

  // Called from DevTools
  void EmulateDispatchSyncEvent(
      const std::string& tag,
      scoped_refptr<ServiceWorkerVersion> active_version,
      bool last_chance,
      ServiceWorkerVersion::StatusCallback callback);
  void EmulateDispatchPeriodicSyncEvent(
      const std::string& tag,
      scoped_refptr<ServiceWorkerVersion> active_version,
      ServiceWorkerVersion::StatusCallback callback);

  // Called from DevTools to toggle service worker "offline" status
  void EmulateServiceWorkerOffline(int64_t service_worker_id, bool is_offline);

  // Scans the list of available events and fires those of type |sync_type| that
  // are ready to fire. For those that can't yet be fired, wakeup alarms are
  // set. Once all of this is done, invokes |callback|.
  virtual void FireReadyEvents(
      blink::mojom::BackgroundSyncType sync_type,
      bool reschedule,
      base::OnceClosure callback,
      std::unique_ptr<BackgroundSyncEventKeepAlive> keepalive = nullptr);

  // Gets the soonest delta after which the browser should be woken up to send
  // a Background Sync event. If set to max, the browser won't be woken up.
  // Only registrations of type |sync_type| are considered.
  // Browsers can have a hard limit on how often to wake themselves up to
  // process Periodic Background Sync registrations. We apply this limit if
  // |last_browser_wakeup_time| is not null.
  // This limit is only applied when calculating the soonest wake up delta to
  // wake up Chrome. It's not applied when calculating the time after which a
  // delayed task should be run to process Background Sync registrations.
  virtual base::TimeDelta GetSoonestWakeupDelta(
      blink::mojom::BackgroundSyncType sync_type,
      base::Time last_browser_wakeup_time);

  // Browsers can have a hard limit on how often to wake themselves up to
  // process Periodic Background Sync registrations. If the browser can't be
  // woken up after |wakeup_delta| to do so, returns an updated delta after
  // which it's safe to wake the browser. This limit doesn't apply to retries.
  base::TimeDelta MaybeApplyBrowserWakeupCountLimit(
      base::TimeDelta wakeup_delta,
      base::Time last_browser_wakeup_time);

  // Finds all periodicsync registrations for the |origin|, and returns the time
  // till the soonest scheduled periodicsync event for this origin, skipping
  // over the registration with tag |tag_to_skip|. If there's
  // none, it returns base::TimeDelta::Max(). If the soonest such event is
  // scheduled to be fired in the past, returns base::TimeDelta().
  base::TimeDelta GetSmallestPeriodicSyncEventDelayForOrigin(
      const url::Origin& origin,
      const std::string& tag_to_skip) const;

  // Revive any pending periodic Background Sync registrations for |origin|.
  void RevivePeriodicSyncRegistrations(url::Origin origin);

  const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context() {
    return service_worker_context_;
  }

 protected:
  BackgroundSyncManager(
      scoped_refptr<ServiceWorkerContextWrapper> context,
      scoped_refptr<DevToolsBackgroundServicesContextImpl> devtools_context);

  // Init must be called before any public member function. Only call it once.
  void Init();

  // The following methods are virtual for testing.
  virtual void StoreDataInBackend(
      int64_t sw_registration_id,
      const url::Origin& origin,
      const std::string& backend_key,
      const std::string& data,
      ServiceWorkerRegistry::StatusCallback callback);
  virtual void GetDataFromBackend(
      const std::string& backend_key,
      ServiceWorkerRegistry::GetUserDataForAllRegistrationsCallback callback);
  virtual void DispatchSyncEvent(
      const std::string& tag,
      scoped_refptr<ServiceWorkerVersion> active_version,
      bool last_chance,
      ServiceWorkerVersion::StatusCallback callback);
  virtual void DispatchPeriodicSyncEvent(
      const std::string& tag,
      scoped_refptr<ServiceWorkerVersion> active_version,
      ServiceWorkerVersion::StatusCallback callback);
  virtual void HasMainFrameWindowClient(const blink::StorageKey& key,
                                        BoolCallback callback);

 private:
  friend class TestBackgroundSyncManager;
  friend class BackgroundSyncManagerTest;

  struct BackgroundSyncRegistrations {
    using RegistrationMap =
        std::map<std::pair<std::string, blink::mojom::BackgroundSyncType>,
                 BackgroundSyncRegistration>;

    BackgroundSyncRegistrations();
    BackgroundSyncRegistrations(const BackgroundSyncRegistrations& other);
    ~BackgroundSyncRegistrations();

    RegistrationMap registration_map;
    url::Origin origin;
  };

  static const size_t kMaxTagLength = 10240;

  // Disable the manager. Already queued operations will abort once they start
  // to run (in their impl methods). Future operations will not queue.
  // The list of active registrations is cleared and the backend is also cleared
  // (if it's still functioning). The manager will reenable itself once it
  // receives the OnStorageWiped message or on browser restart.
  void DisableAndClearManager(base::OnceClosure callback);
  void DisableAndClearDidGetRegistrations(
      base::OnceClosure callback,
      const std::vector<std::pair<int64_t, std::string>>& user_data,
      blink::ServiceWorkerStatusCode status);
  void DisableAndClearManagerClearedOne(base::OnceClosure barrier_closure,
                                        blink::ServiceWorkerStatusCode status);

  // Returns the existing registration or nullptr if it cannot be found.
  BackgroundSyncRegistration* LookupActiveRegistration(
      const blink::mojom::BackgroundSyncRegistrationInfo& registration_info);

  // Write all registrations for a given |sw_registration_id| to persistent
  // storage.
  void StoreRegistrations(int64_t sw_registration_id,
                          ServiceWorkerRegistry::StatusCallback callback);

  // Removes the active registration if it is in the map.
  void RemoveActiveRegistration(
      const blink::mojom::BackgroundSyncRegistrationInfo& registration_info);

  void AddOrUpdateActiveRegistration(
      int64_t sw_registration_id,
      const url::Origin& origin,
      const BackgroundSyncRegistration& sync_registration);

  void InitImpl(base::OnceClosure callback);
  void InitDidGetControllerParameters(
      base::OnceClosure callback,
      std::unique_ptr<BackgroundSyncParameters> parameters);
  void InitDidGetDataFromBackend(
      base::OnceClosure callback,
      const std::vector<std::pair<int64_t, std::string>>& user_data,
      blink::ServiceWorkerStatusCode status);

  void GetRegistrations(blink::mojom::BackgroundSyncType sync_type,
                        int64_t sw_registration_id,
                        StatusAndRegistrationsCallback callback);

  // Register callbacks
  void RegisterCheckIfHasMainFrame(
      int64_t sw_registration_id,
      int render_process_host_id,
      blink::mojom::SyncRegistrationOptions options,
      StatusAndRegistrationCallback callback);
  void RegisterDidCheckIfMainFrame(
      int64_t sw_registration_id,
      int render_process_host_id,
      blink::mojom::SyncRegistrationOptions options,
      StatusAndRegistrationCallback callback,
      bool has_main_frame_client);
  void RegisterImpl(int64_t sw_registration_id,
                    int render_process_host_id,
                    blink::mojom::SyncRegistrationOptions options,
                    StatusAndRegistrationCallback callback);
  void RegisterDidAskForPermission(
      int64_t sw_registration_id,
      blink::mojom::SyncRegistrationOptions options,
      StatusAndRegistrationCallback callback,
      std::pair<blink::mojom::PermissionStatus, blink::mojom::PermissionStatus>
          permission_statuses);
  void RegisterDidGetDelay(int64_t sw_registration_id,
                           BackgroundSyncRegistration new_registration,
                           StatusAndRegistrationCallback callback,
                           base::TimeDelta delay);
  void RegisterDidStore(int64_t sw_registration_id,
                        const BackgroundSyncRegistration& new_registration,
                        StatusAndRegistrationCallback callback,
                        blink::ServiceWorkerStatusCode status);
  void UnregisterPeriodicSyncImpl(int64_t sw_registration_id,
                                  const std::string& tag,
                                  StatusCallback callback);
  void UnregisterPeriodicSyncDidStore(StatusCallback callback,
                                      blink::ServiceWorkerStatusCode status);

  // DidResolveRegistration callbacks
  void DidResolveRegistrationImpl(
      blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info);
  void ResolveRegistrationDidCreateKeepAlive(
      std::unique_ptr<BackgroundSyncEventKeepAlive> keepalive);

  // GetRegistrations callbacks
  void GetRegistrationsImpl(blink::mojom::BackgroundSyncType sync_type,
                            int64_t sw_registration_id,
                            StatusAndRegistrationsCallback callback);

  bool AreOptionConditionsMet();
  bool IsRegistrationReadyToFire(const BackgroundSyncRegistration& registration,
                                 int64_t service_worker_id);

  // Determines if the browser needs to be able to run in the background (e.g.,
  // to run a pending registration or verify that a firing registration
  // completed). If background processing is required it calls out to
  // BackgroundSyncProxy to enable it.
  // Assumes that all registrations in the pending state are not currently ready
  // to fire. Therefore this should not be called directly and should only be
  // called by FireReadyEvents.
  void ScheduleDelayedProcessingOfRegistrations(
      blink::mojom::BackgroundSyncType sync_type);

  // Cancels waking up of the browser to process (Periodic) BackgroundSync
  // registrations.
  void CancelDelayedProcessingOfRegistrations(
      blink::mojom::BackgroundSyncType sync_type);

  // Fires ready events for |sync_type|.
  // |reschedule| is true when it's ok to schedule background processing from
  // this method, false otherwise.
  // |scheduler_id| is an id unique to the |op_scheduler_| task. It's passed to
  // correctly mark this operation as finished with the |op_scheduler_| and run
  // the next operation scheduled.
  // |keepalive| is used to keep the browser alive until the first attempt to
  // fire a sync event has been made.
  void FireReadyEventsImpl(
      blink::mojom::BackgroundSyncType sync_type,
      bool reschedule,
      base::OnceClosure callback,
      std::unique_ptr<BackgroundSyncEventKeepAlive> keepalive);

  void 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);
  void FireReadyEventsAllEventsFiring(
      blink::mojom::BackgroundSyncType sync_type,
      bool reschedule,
      base::OnceClosure callback);

  // Called when a sync event has completed.
  void EventComplete(
      scoped_refptr<ServiceWorkerRegistration> service_worker_registration,
      blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info,
      std::unique_ptr<BackgroundSyncEventKeepAlive> keepalive,
      base::OnceClosure callback,
      blink::ServiceWorkerStatusCode status_code);
  void EventCompleteImpl(
      blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info,
      std::unique_ptr<BackgroundSyncEventKeepAlive> keepalive,
      blink::ServiceWorkerStatusCode status_code,
      const url::Origin& origin,
      base::OnceClosure callback);
  void EventCompleteDidGetDelay(
      blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info,
      blink::ServiceWorkerStatusCode status_code,
      const url::Origin& origin,
      base::OnceClosure callback,
      base::TimeDelta delay);
  void EventCompleteDidStore(blink::mojom::BackgroundSyncType sync_type,
                             int64_t service_worker_id,
                             base::OnceClosure callback,
                             blink::ServiceWorkerStatusCode status_code);

  // Called when all sync events have completed.
  static void OnAllSyncEventsCompleted(
      blink::mojom::BackgroundSyncType sync_type,
      const base::TimeTicks& start_time,
      bool from_wakeup_task,
      int number_of_batched_sync_events,
      base::OnceClosure callback);

  // OnRegistrationDeleted callbacks
  void OnRegistrationDeletedImpl(int64_t sw_registration_id,
                                 base::OnceClosure callback);

  // OnStorageWiped callbacks
  void OnStorageWipedImpl(base::OnceClosure callback);

  void OnNetworkChanged();

  // Whether an event should be logged for debuggability, for |sync_type|.
  bool ShouldLogToDevTools(blink::mojom::BackgroundSyncType sync_type);

  void ReviveOriginImpl(url::Origin origin, base::OnceClosure callback);
  void ReviveDidGetNextEventDelay(int64_t service_worker_registration_id,
                                  BackgroundSyncRegistration registration,
                                  base::OnceClosure done_closure,
                                  base::TimeDelta delay);
  void ReviveDidStoreRegistration(int64_t service_worker_registration_id,
                                  base::OnceClosure done_closure,
                                  blink::ServiceWorkerStatusCode status);
  void DidReceiveDelaysForSuspendedRegistrations(base::OnceClosure callback);

  // Helper methods to unregister Periodic Background Sync registrations
  // associated with |origin|.
  void UnregisterForOriginImpl(const url::Origin& origin,
                               base::OnceClosure callback);
  void UnregisterForOriginDidStore(
      int64_t service_worker_registration_id_to_remove,
      base::OnceClosure done_closure,
      blink::ServiceWorkerStatusCode status);
  void UnregisterForOriginScheduleDelayedProcessing(base::OnceClosure callback);

  base::OnceClosure MakeEmptyCompletion();

  blink::ServiceWorkerStatusCode CanEmulateSyncEvent(
      scoped_refptr<ServiceWorkerVersion> active_version);

  // Read or update |num_firing_registrations_one_shot_| or
  // |num_firing_registrations_periodic_| based on |sync_type|.
  int GetNumFiringRegistrations(blink::mojom::BackgroundSyncType sync_type);
  void UpdateNumFiringRegistrationsBy(
      blink::mojom::BackgroundSyncType sync_type,
      int to_add);

  // Returns true if all registrations are waiting to be resolved.
  // false otherwise.
  bool AllRegistrationsWaitingToBeResolved() const;

  // Returns true if a registration can fire immediately once we have network
  // connectivity.
  bool AllConditionsExceptConnectivitySatisfied(
      const BackgroundSyncRegistration& registration,
      int64_t service_worker_id);

  // Returns true if any registration of |sync_type| can be fired right when we
  // have network connectivity.
  bool CanFireAnyRegistrationUponConnectivity(
      blink::mojom::BackgroundSyncType sync_type);

  // Returns a reference to the bool that notes whether delayed processing for
  // registrations of |sync_type| is currently scheduled.
  bool& delayed_processing_scheduled(
      blink::mojom::BackgroundSyncType sync_type);

  // If we should schedule delayed processing, this does so.
  // If we should cancel delayed processing, this does so.
  // Else, this does nothing.
  void ScheduleOrCancelDelayedProcessing(
      blink::mojom::BackgroundSyncType sync_type);

  // Map from service worker registration id to its Background Sync
  // registrations.
  std::map<int64_t, BackgroundSyncRegistrations> active_registrations_;

  BackgroundSyncOpScheduler op_scheduler_;
  scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
  std::unique_ptr<BackgroundSyncProxy> proxy_;

  scoped_refptr<DevToolsBackgroundServicesContextImpl> devtools_context_;
  std::unique_ptr<BackgroundSyncParameters> parameters_;

  // True if the manager is disabled and registrations should fail.
  bool disabled_;

  // The number of registrations currently in the firing state.
  int num_firing_registrations_one_shot_;
  int num_firing_registrations_periodic_;

  bool delayed_processing_scheduled_one_shot_sync_ = false;
  bool delayed_processing_scheduled_periodic_sync_ = false;

  std::unique_ptr<BackgroundSyncNetworkObserver> network_observer_;

  raw_ptr<base::Clock> clock_;

  std::map<int64_t, int> emulated_offline_sw_;

  SEQUENCE_CHECKER(sequence_checker_);

  base::WeakPtrFactory<BackgroundSyncManager> weak_ptr_factory_{this};
};

}  // namespace content

#endif  // CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_MANAGER_H_
