| // Copyright 2012 The Chromium Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef COMPONENTS_SYNC_ENGINE_CYCLE_SYNC_CYCLE_H_ | |
| #define COMPONENTS_SYNC_ENGINE_CYCLE_SYNC_CYCLE_H_ | |
| #include <map> | |
| #include <memory> | |
| #include <optional> | |
| #include <set> | |
| #include <utility> | |
| #include "base/memory/raw_ptr.h" | |
| #include "base/time/time.h" | |
| #include "components/signin/public/identity_manager/access_token_info.h" | |
| #include "components/sync/base/data_type.h" | |
| #include "components/sync/engine/cycle/status_controller.h" | |
| #include "components/sync/engine/cycle/sync_cycle_context.h" | |
| #include "components/sync/engine/cycle/sync_cycle_snapshot.h" | |
| #include "components/sync/engine/sync_cycle_event.h" | |
| #include "components/sync/engine/sync_protocol_error.h" | |
| namespace syncer { | |
| class ProtocolEvent; | |
| // A class representing an attempt to synchronize the local syncable data | |
| // store with a sync server. A SyncCycle instance is passed as a stateful | |
| // bundle throughout the sync cycle. The SyncCycle is not reused across | |
| // sync cycles; each cycle starts with a new one. | |
| class SyncCycle { | |
| public: | |
| // The Delegate services events that occur during the cycle requiring an | |
| // explicit (and cycle-global) action, as opposed to events that are simply | |
| // recorded in per-cycle state. | |
| class Delegate { | |
| public: | |
| // The client was throttled and should cease-and-desist syncing activity | |
| // until the specified time. | |
| virtual void OnThrottled(const base::TimeDelta& throttle_duration) = 0; | |
| // Some of the client's types were throttled. | |
| virtual void OnTypesThrottled(DataTypeSet types, | |
| const base::TimeDelta& throttle_duration) = 0; | |
| // Some of the client's types were backed off. | |
| virtual void OnTypesBackedOff(DataTypeSet types) = 0; | |
| // Silenced intervals can be out of phase with individual cycles, so the | |
| // delegate is the only thing that can give an authoritative answer for | |
| // "is syncing silenced right now". This shouldn't be necessary very often | |
| // as the delegate ensures no cycle is started if syncing is silenced. | |
| // ** Note ** This will return true if silencing commenced during this | |
| // cycle and the interval has not yet elapsed, but the contract here is | |
| // solely based on absolute time values. So, this cannot be used to infer | |
| // that any given cycle _instance_ is silenced. An example of reasonable | |
| // use is for UI reporting. | |
| virtual bool IsAnyThrottleOrBackoff() = 0; | |
| // The client has been instructed to change its poll interval. | |
| virtual void OnReceivedPollIntervalUpdate( | |
| const base::TimeDelta& new_interval) = 0; | |
| // The client has been instructed to change a nudge delay. | |
| virtual void OnReceivedCustomNudgeDelays( | |
| const std::map<DataType, base::TimeDelta>& nudge_delays) = 0; | |
| // Called for the syncer to respond to the error sent by the server. | |
| virtual void OnSyncProtocolError( | |
| const SyncProtocolError& sync_protocol_error) = 0; | |
| // Called when server requests a migration. | |
| virtual void OnReceivedMigrationRequest(DataTypeSet types) = 0; | |
| // Called when server wants to change the parameters for commit quotas of | |
| // data types that can receive commits via extension APIs. Empty optional | |
| // means using the client-side defaults. | |
| virtual void OnReceivedQuotaParamsForExtensionTypes( | |
| std::optional<int> max_tokens, | |
| std::optional<base::TimeDelta> refill_interval, | |
| std::optional<base::TimeDelta> depleted_quota_nudge_delay) = 0; | |
| protected: | |
| virtual ~Delegate() = default; | |
| }; | |
| SyncCycle(SyncCycleContext* context, | |
| Delegate* delegate, | |
| signin::AccessTokenInfo access_token_info); | |
| SyncCycle(const SyncCycle&) = delete; | |
| SyncCycle& operator=(const SyncCycle&) = delete; | |
| ~SyncCycle(); | |
| // Builds a thread-safe and read-only copy of the current cycle state. | |
| SyncCycleSnapshot TakeSnapshot() const; | |
| SyncCycleSnapshot TakeSnapshotWithOrigin( | |
| sync_pb::SyncEnums::GetUpdatesOrigin get_updates_origin) const; | |
| // Builds and sends a snapshot to the cycle context's listeners. | |
| void SendSyncCycleEndEventNotification( | |
| sync_pb::SyncEnums::GetUpdatesOrigin get_updates_origin); | |
| void SendEventNotification(SyncCycleEvent::EventCause cause); | |
| void SendProtocolEvent(const ProtocolEvent& event); | |
| // TODO(akalin): Split this into context() and mutable_context(). | |
| SyncCycleContext* context() const { return context_; } | |
| Delegate* delegate() const { return delegate_; } | |
| const StatusController& status_controller() const { | |
| return *status_controller_.get(); | |
| } | |
| StatusController* mutable_status_controller() { | |
| return status_controller_.get(); | |
| } | |
| const signin::AccessTokenInfo& access_token_info() const { | |
| return access_token_info_; | |
| } | |
| private: | |
| // The context for this cycle, guaranteed to outlive `this`. | |
| const raw_ptr<SyncCycleContext, DanglingUntriaged> context_; | |
| // The delegate for this cycle, must never be null. | |
| const raw_ptr<Delegate> delegate_; | |
| // The access token info for this cycle. | |
| const signin::AccessTokenInfo access_token_info_; | |
| // Our controller for various status and error counters. | |
| std::unique_ptr<StatusController> status_controller_; | |
| }; | |
| } // namespace syncer | |
| #endif // COMPONENTS_SYNC_ENGINE_CYCLE_SYNC_CYCLE_H_ |