#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;
}
class StorageKey;
}
namespace content {
class BackgroundSyncNetworkObserver;
class ServiceWorkerContextWrapper;
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,
DevToolsBackgroundServicesContextImpl& devtools_context);
BackgroundSyncManager(const BackgroundSyncManager&) = delete;
BackgroundSyncManager& operator=(const BackgroundSyncManager&) = delete;
~BackgroundSyncManager() override;
void Register(int64_t sw_registration_id,
int render_process_host_id,
blink::mojom::SyncRegistrationOptions options,
StatusAndRegistrationCallback callback);
void UnregisterPeriodicSync(int64_t sw_registration_id,
const std::string& tag,
StatusCallback callback);
void DidResolveRegistration(
blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info);
void GetOneShotSyncRegistrations(int64_t sw_registration_id,
StatusAndRegistrationsCallback callback);
void GetPeriodicSyncRegistrations(int64_t sw_registration_id,
StatusAndRegistrationsCallback callback);
void UnregisterPeriodicSyncForOrigin(const url::Origin& origin);
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);
}
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);
void EmulateServiceWorkerOffline(int64_t service_worker_id, bool is_offline);
virtual void FireReadyEvents(
blink::mojom::BackgroundSyncType sync_type,
bool reschedule,
base::OnceClosure callback,
std::unique_ptr<BackgroundSyncEventKeepAlive> keepalive = nullptr);
virtual base::TimeDelta GetSoonestWakeupDelta(
blink::mojom::BackgroundSyncType sync_type,
base::Time last_browser_wakeup_time);
base::TimeDelta MaybeApplyBrowserWakeupCountLimit(
base::TimeDelta wakeup_delta,
base::Time last_browser_wakeup_time);
base::TimeDelta GetSmallestPeriodicSyncEventDelayForOrigin(
const url::Origin& origin,
const std::string& tag_to_skip) const;
void RevivePeriodicSyncRegistrations(url::Origin origin);
const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context() {
return service_worker_context_;
}
protected:
BackgroundSyncManager(
scoped_refptr<ServiceWorkerContextWrapper> context,
DevToolsBackgroundServicesContextImpl& devtools_context);
void Init();
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;
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);
BackgroundSyncRegistration* LookupActiveRegistration(
const blink::mojom::BackgroundSyncRegistrationInfo& registration_info);
void StoreRegistrations(int64_t sw_registration_id,
ServiceWorkerRegistry::StatusCallback callback);
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);
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);
void DidResolveRegistrationImpl(
blink::mojom::BackgroundSyncRegistrationInfoPtr registration_info);
void ResolveRegistrationDidCreateKeepAlive(
std::unique_ptr<BackgroundSyncEventKeepAlive> keepalive);
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);
void ScheduleDelayedProcessingOfRegistrations(
blink::mojom::BackgroundSyncType sync_type);
void CancelDelayedProcessingOfRegistrations(
blink::mojom::BackgroundSyncType sync_type);
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);
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);
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);
void OnRegistrationDeletedImpl(int64_t sw_registration_id,
base::OnceClosure callback);
void OnStorageWipedImpl(base::OnceClosure callback);
void OnNetworkChanged();
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);
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);
int GetNumFiringRegistrations(blink::mojom::BackgroundSyncType sync_type);
void UpdateNumFiringRegistrationsBy(
blink::mojom::BackgroundSyncType sync_type,
int to_add);
bool AllRegistrationsWaitingToBeResolved() const;
bool AllConditionsExceptConnectivitySatisfied(
const BackgroundSyncRegistration& registration,
int64_t service_worker_id);
bool CanFireAnyRegistrationUponConnectivity(
blink::mojom::BackgroundSyncType sync_type);
bool& delayed_processing_scheduled(
blink::mojom::BackgroundSyncType sync_type);
void ScheduleOrCancelDelayedProcessing(
blink::mojom::BackgroundSyncType sync_type);
std::map<int64_t, BackgroundSyncRegistrations> active_registrations_;
BackgroundSyncOpScheduler op_scheduler_;
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
std::unique_ptr<BackgroundSyncProxy> proxy_;
raw_ptr<DevToolsBackgroundServicesContextImpl> devtools_context_;
std::unique_ptr<BackgroundSyncParameters> parameters_;
bool disabled_;
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};
};
}
#endif