| // 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. |
| |
| #ifndef COMPONENTS_SYNC_DRIVER_SYNC_SERVICE_H_ |
| #define COMPONENTS_SYNC_DRIVER_SYNC_SERVICE_H_ |
| |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| #include "base/callback.h" |
| #include "base/location.h" |
| #include "base/macros.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/time/time.h" |
| #include "components/keyed_service/core/keyed_service.h" |
| #include "components/sync/base/enum_set.h" |
| #include "components/sync/base/model_type.h" |
| #include "components/sync/driver/sync_service_observer.h" |
| |
| struct CoreAccountInfo; |
| class GoogleServiceAuthError; |
| class GURL; |
| |
| namespace syncer { |
| |
| class JsController; |
| class ProtocolEventObserver; |
| class SyncCycleSnapshot; |
| struct TypeEntitiesCount; |
| struct SyncTokenStatus; |
| class SyncUserSettings; |
| struct SyncStatus; |
| |
| // UIs that need to prevent Sync startup should hold an instance of this class |
| // until the user has finished modifying sync settings. This is not an inner |
| // class of SyncService to enable forward declarations. |
| class SyncSetupInProgressHandle { |
| public: |
| // UIs should not construct this directly, but instead call |
| // SyncService::GetSetupInProgress(). |
| explicit SyncSetupInProgressHandle(base::OnceClosure on_destroy); |
| |
| ~SyncSetupInProgressHandle(); |
| |
| private: |
| base::OnceClosure on_destroy_; |
| }; |
| |
| // SyncService is the layer between browser subsystems like bookmarks and the |
| // sync engine. Each subsystem is logically thought of as being a sync datatype. |
| // Individual datatypes can, at any point, be in a variety of stages of being |
| // "enabled". Here are some specific terms for concepts used in this class: |
| // |
| // 'Registered' (feature suppression for a datatype) |
| // |
| // When a datatype is registered, the user has the option of syncing it. |
| // The sync opt-in UI will show only registered types; a checkbox should |
| // never be shown for an unregistered type, nor can it ever be synced. |
| // |
| // 'Preferred' (user preferences and opt-out for a datatype) |
| // |
| // This means the user's opt-in or opt-out preference on a per-datatype |
| // basis. The sync service will try to make active exactly these types. |
| // If a user has opted out of syncing a particular datatype, it will |
| // be registered, but not preferred. Also note that not all datatypes can |
| // be directly chosen by the user: e.g. AUTOFILL_PROFILE is implied by |
| // AUTOFILL but can't be selected separately. If AUTOFILL is chosen by the |
| // user, then AUTOFILL_PROFILE will also be considered preferred. See |
| // SyncPrefs::ResolvePrefGroups. |
| // |
| // This state is controlled by SyncUserSettings::SetChosenDataTypes. They |
| // are stored in the preferences system and persist; though if a datatype |
| // is not registered, it cannot be a preferred datatype. |
| // |
| // 'Active' (run-time initialization of sync system for a datatype) |
| // |
| // An active datatype is a preferred datatype that is actively being |
| // synchronized: the syncer has been instructed to querying the server |
| // for this datatype, first-time merges have finished, and there is an |
| // actively installed ChangeProcessor that listens for changes to this |
| // datatype, propagating such changes into and out of the sync engine |
| // as necessary. |
| // |
| // When a datatype is in the process of becoming active, it may be |
| // in some intermediate state. Those finer-grained intermediate states |
| // are differentiated by the DataTypeController state, but not exposed. |
| // |
| // Sync Configuration: |
| // |
| // Sync configuration is accomplished via SyncUserSettings, in particular: |
| // * SetChosenDataTypes(): Set the data types the user wants to sync. |
| // * SetDecryptionPassphrase(): Attempt to decrypt the user's encrypted data |
| // using the passed passphrase. |
| // * SetEncryptionPassphrase(): Re-encrypt the user's data using the passed |
| // passphrase. |
| // |
| // Initial sync setup: |
| // |
| // For privacy reasons, it is usually desirable to avoid syncing any data |
| // types until the user has finished setting up sync. There are two APIs |
| // that control the initial sync download: |
| // |
| // * SyncUserSettings::SetFirstSetupComplete() |
| // * GetSetupInProgressHandle() |
| // |
| // SetFirstSetupComplete() should be called once the user has finished setting |
| // up sync at least once on their account. GetSetupInProgressHandle() should |
| // be called while the user is actively configuring their account. The handle |
| // should be deleted once configuration is complete. |
| // |
| // Once first setup has completed and there are no outstanding |
| // setup-in-progress handles, datatype configuration will begin. |
| class SyncService : public KeyedService { |
| public: |
| // The set of reasons due to which Sync-the-feature can be disabled. Note that |
| // Sync-the-transport might still start up even in the presence of (some) |
| // disable reasons. Meant to be used as a enum set. |
| enum DisableReason { |
| // Sync is disabled via platform-level override (e.g. Android's "MasterSync" |
| // toggle). |
| DISABLE_REASON_PLATFORM_OVERRIDE, |
| DISABLE_REASON_FIRST = DISABLE_REASON_PLATFORM_OVERRIDE, |
| // Sync is disabled by enterprise policy, either browser policy (through |
| // prefs) or account policy received from the Sync server. |
| DISABLE_REASON_ENTERPRISE_POLICY, |
| // Sync can't start because there is no authenticated user. |
| DISABLE_REASON_NOT_SIGNED_IN, |
| // Sync is suppressed by user choice, either via the feature toggle in |
| // Chrome settings (which exists on Android and iOS), a platform-level |
| // toggle (e.g. Android's "ChromeSync" toggle), or a “Reset Sync” operation |
| // from the dashboard. This is also set if there's simply no signed-in user |
| // (in addition to DISABLE_REASON_NOT_SIGNED_IN). |
| DISABLE_REASON_USER_CHOICE, |
| // Sync has encountered an unrecoverable error. It won't attempt to start |
| // again until either the browser is restarted, or the user fully signs out |
| // and back in again. |
| DISABLE_REASON_UNRECOVERABLE_ERROR, |
| DISABLE_REASON_LAST = DISABLE_REASON_UNRECOVERABLE_ERROR, |
| }; |
| |
| using DisableReasonSet = |
| EnumSet<DisableReason, DISABLE_REASON_FIRST, DISABLE_REASON_LAST>; |
| |
| // The overall state of Sync-the-transport, in ascending order of |
| // "activeness". Note that this refers to the transport layer, which may be |
| // active even if Sync-the-feature is turned off. |
| enum class TransportState { |
| // Sync is inactive, e.g. due to enterprise policy, or simply because there |
| // is no authenticated user. |
| DISABLED, |
| // Sync is paused, e.g. because the user signed out on the web, and the |
| // engine is inactive. |
| PAUSED, |
| // Sync's startup was deferred, so that it doesn't slow down browser |
| // startup. Once the deferral time (usually 10s) expires, or something |
| // requests immediate startup, Sync will actually start. |
| START_DEFERRED, |
| // The Sync engine is in the process of initializing. |
| INITIALIZING, |
| // The Sync engine is initialized, but the process of configuring the data |
| // types hasn't been started yet. This usually occurs if the user hasn't |
| // completed the initial Sync setup yet (i.e. IsFirstSetupComplete() is |
| // false), but it can also occur if a (non-initial) Sync setup happens to be |
| // ongoing while the Sync service is starting up. |
| PENDING_DESIRED_CONFIGURATION, |
| // The Sync engine itself is up and running, but the individual data types |
| // are being (re)configured. GetActiveDataTypes() will still be empty. |
| CONFIGURING, |
| // The Sync service is up and running. Note that this *still* doesn't |
| // necessarily mean any particular data is being uploaded, e.g. individual |
| // data types might be disabled or might have failed to start (check |
| // GetActiveDataTypes()). |
| ACTIVE |
| }; |
| |
| ~SyncService() override {} |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // USER SETTINGS |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| // Returns the SyncUserSettings, which encapsulate all the user-configurable |
| // bits for Sync. |
| virtual SyncUserSettings* GetUserSettings() = 0; |
| virtual const SyncUserSettings* GetUserSettings() const = 0; |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // BASIC STATE ACCESS |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| // Returns the set of reasons that are keeping Sync disabled, as a bitmask of |
| // DisableReason enum entries. |
| // Note: This refers to Sync-the-feature. Sync-the-transport may be running |
| // even in the presence of disable reasons. |
| virtual DisableReasonSet GetDisableReasons() const = 0; |
| // Helper that returns whether GetDisableReasons() contains the given |reason| |
| // (possibly among others). |
| bool HasDisableReason(DisableReason reason) const { |
| return GetDisableReasons().Has(reason); |
| } |
| |
| // Returns the overall state of the SyncService transport layer. See the enum |
| // definition for what the individual states mean. |
| // Note: This refers to Sync-the-transport, which may be active even if |
| // Sync-the-feature is disabled by the user, by enterprise policy, etc. |
| // Note: If your question is "Are we actually sending this data to Google?" or |
| // "Am I allowed to send this type of data to Google?", you probably want |
| // syncer::GetUploadToGoogleState instead of this. |
| virtual TransportState GetTransportState() const = 0; |
| |
| // Returns true if the local sync backend server has been enabled through a |
| // command line flag or policy. In this case sync is considered active but any |
| // implied consent for further related services e.g. Suggestions, Web History |
| // etc. is considered not granted. |
| virtual bool IsLocalSyncEnabled() const = 0; |
| |
| // Information about the currently signed in user. |
| virtual CoreAccountInfo GetAuthenticatedAccountInfo() const = 0; |
| // Whether the currently signed in user is the "primary" browser account (see |
| // IdentityManager). If this is false, then IsSyncFeatureEnabled will also be |
| // false, but Sync-the-transport might still run. |
| virtual bool IsAuthenticatedAccountPrimary() const = 0; |
| |
| // Returns whether the SyncService has completed at least one Sync cycle since |
| // starting up (i.e. since browser startup or signin). This can be useful |
| // in combination with GetAuthError(), if you need to know if the user's |
| // refresh token is really valid: Before a Sync cycle has been completed, |
| // Sync hasn't tried using the refresh token, so doesn't know if it's valid. |
| // TODO(crbug.com/831579): If Chrome would persist auth errors, this would not |
| // be necessary. |
| bool HasCompletedSyncCycle() const; |
| |
| // The last authentication error that was encountered by the SyncService. This |
| // error can be either from Chrome's identity system (e.g. while trying to get |
| // an access token), or from the Sync server. It gets cleared when the error |
| // is resolved. |
| virtual GoogleServiceAuthError GetAuthError() const = 0; |
| virtual base::Time GetAuthErrorTime() const = 0; |
| |
| // Returns true if the Chrome client is too old and needs to be updated for |
| // Sync to work. |
| virtual bool RequiresClientUpgrade() const = 0; |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // DERIVED STATE ACCESS |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| // Returns whether all conditions are satisfied for Sync-the-feature to start. |
| // This means that there is a primary account, no disable reasons, and |
| // first-time Sync setup has been completed by the user. |
| // Note: This does not imply that Sync is actually running. Check |
| // IsSyncFeatureActive or GetTransportState to get the current state. |
| bool IsSyncFeatureEnabled() const; |
| |
| // Equivalent to "HasDisableReason(DISABLE_REASON_UNRECOVERABLE_ERROR)". |
| bool HasUnrecoverableError() const; |
| |
| // Equivalent to GetTransportState() returning one of |
| // PENDING_DESIRED_CONFIGURATION, CONFIGURING, or ACTIVE. |
| // Note: This refers to Sync-the-transport, which may be active even if |
| // Sync-the-feature is disabled by the user, by enterprise policy, etc. |
| bool IsEngineInitialized() const; |
| |
| // Returns whether Sync-the-feature can (attempt to) start. This means that |
| // there is a primary account and no disable reasons. It does *not* require |
| // first-time Sync setup to be complete, because that can only happen after |
| // the engine has started. |
| // Note: This refers to Sync-the-feature. Sync-the-transport may be running |
| // even if this is false. |
| bool CanSyncFeatureStart() const; |
| |
| // Returns whether Sync-the-feature is active, which means |
| // GetTransportState() is either CONFIGURING or ACTIVE and |
| // IsSyncFeatureEnabled() is true. |
| // To see which datatypes are actually syncing, see GetActiveDataTypes(). |
| // Note: This refers to Sync-the-feature. Sync-the-transport may be active |
| // even if this is false. |
| bool IsSyncFeatureActive() const; |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // SETUP-IN-PROGRESS HANDLING |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| // Called by the UI to notify the SyncService that UI is visible, so any |
| // changes to Sync settings should *not* take effect immediately (e.g. if the |
| // user accidentally enabled a data type, we should give them a chance to undo |
| // the change before local and remote data are irrevocably merged). |
| // The UI calls this and holds onto the instance for as long as any part of |
| // the Sync setup/configuration UI is visible. |
| virtual std::unique_ptr<SyncSetupInProgressHandle> |
| GetSetupInProgressHandle() = 0; |
| |
| // Whether a Sync setup is currently in progress, i.e. a setup UI is being |
| // shown. |
| virtual bool IsSetupInProgress() const = 0; |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // DATA TYPE STATE |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| // Returns the set of types which are preferred for enabling. This is a |
| // superset of the active types (see GetActiveDataTypes()). This also includes |
| // any forced types. |
| virtual ModelTypeSet GetPreferredDataTypes() const = 0; |
| |
| // Returns the set of currently active data types (those chosen or configured |
| // by the user which have not also encountered a runtime error). |
| // Note that if the Sync engine is in the middle of a configuration, this will |
| // be the empty set. Once the configuration completes the set will be updated. |
| virtual ModelTypeSet GetActiveDataTypes() const = 0; |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // ACTIONS / STATE CHANGE REQUESTS |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| // Stops sync-the-feature and clears all local data. Sync-the-transport may |
| // remain active after calling this. |
| virtual void StopAndClear() = 0; |
| |
| // Controls whether sync is allowed at the platform level. If set to false |
| // sync will be disabled with DISABLE_REASON_PLATFORM_OVERRIDE. |
| virtual void SetSyncAllowedByPlatform(bool allowed) = 0; |
| |
| // Called when a datatype (SyncableService) has a need for sync to start |
| // ASAP, presumably because a local change event has occurred but we're |
| // still in deferred start mode, meaning the SyncableService hasn't been |
| // told to MergeDataAndStartSyncing yet. |
| virtual void OnDataTypeRequestsSyncStartup(ModelType type) = 0; |
| |
| // Triggers a GetUpdates call for the specified |types|, pulling any new data |
| // from the sync server. Used by tests and debug UI (sync-internals). |
| virtual void TriggerRefresh(const ModelTypeSet& types) = 0; |
| |
| // Informs the data type manager that the preconditions for a controller have |
| // changed. If preconditions are NOT met, the datatype will be stopped |
| // according to the metadata clearing policy returned by the controller's |
| // GetPreconditionState(). Otherwise, if preconditions are newly met, |
| // reconfiguration will be triggered so that |type| gets started again. No-op |
| // if the type's state didn't actually change. |
| virtual void DataTypePreconditionChanged(ModelType type) = 0; |
| |
| // Enables/disables invalidations for session sync related datatypes. |
| // The session sync generates a lot of changes, which results in many |
| // invalidations. This can negatively affect the battery life on Android. For |
| // that reason, on Android, the invalidations for sessions should be received |
| // only when user is interested in session sync data, e.g. the history sync |
| // page is opened. |
| virtual void SetInvalidationsForSessionsEnabled(bool enabled) = 0; |
| |
| // Processes trusted vault encryption keys retrieved from the web. Unused and |
| // ignored on platforms where keys are retrieved by other means. |
| // |last_key_version| represents the key version of the last element in |
| // |keys| (unused if empty). |
| virtual void AddTrustedVaultDecryptionKeysFromWeb( |
| const std::string& gaia_id, |
| const std::vector<std::vector<uint8_t>>& keys, |
| int last_key_version) = 0; |
| |
| // Registers a new trusted recovery method that can be used to retrieve |
| // trusted vault encryption keys. |
| virtual void AddTrustedVaultRecoveryMethodFromWeb( |
| const std::string& gaia_id, |
| const std::vector<uint8_t>& public_key, |
| base::OnceClosure callback) = 0; |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // OBSERVERS |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| // Adds/removes an observer. SyncService does not take ownership of the |
| // observer. |
| virtual void AddObserver(SyncServiceObserver* observer) = 0; |
| virtual void RemoveObserver(SyncServiceObserver* observer) = 0; |
| |
| // Returns true if |observer| has already been added as an observer. |
| virtual bool HasObserver(const SyncServiceObserver* observer) const = 0; |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // DETAILED STATE FOR DEBUG UI |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| // Returns the state of the access token and token request, for display in |
| // internals UI. |
| virtual SyncTokenStatus GetSyncTokenStatusForDebugging() const = 0; |
| |
| // Initializes a struct of status indicators with data from the engine. |
| // Returns false if the engine was not available for querying; in that case |
| // the struct will be filled with default data. |
| virtual bool QueryDetailedSyncStatusForDebugging( |
| SyncStatus* result) const = 0; |
| |
| virtual base::Time GetLastSyncedTimeForDebugging() const = 0; |
| |
| // Returns some statistics on the most-recently completed sync cycle. |
| virtual SyncCycleSnapshot GetLastCycleSnapshotForDebugging() const = 0; |
| |
| // Returns a ListValue indicating the status of all registered types. |
| // |
| // The format is: |
| // [ {"name": <name>, "value": <value>, "status": <status> }, ... ] |
| // where <name> is a type's name, <value> is a string providing details for |
| // the type's status, and <status> is one of "error", "warning" or "ok" |
| // depending on the type's current status. |
| // |
| // This function is used by sync_internals_util.cc to help populate the |
| // chrome://sync-internals page. It returns a ListValue rather than a |
| // DictionaryValue in part to make it easier to iterate over its elements when |
| // constructing that page. |
| virtual std::unique_ptr<base::Value> GetTypeStatusMapForDebugging() = 0; |
| |
| // Retrieves the TypeEntitiesCount for all registered data types. |
| virtual void GetEntityCountsForDebugging( |
| base::OnceCallback<void(const std::vector<TypeEntitiesCount>&)> callback) |
| const = 0; |
| |
| virtual const GURL& GetSyncServiceUrlForDebugging() const = 0; |
| |
| virtual std::string GetUnrecoverableErrorMessageForDebugging() const = 0; |
| virtual base::Location GetUnrecoverableErrorLocationForDebugging() const = 0; |
| |
| virtual void AddProtocolEventObserver(ProtocolEventObserver* observer) = 0; |
| virtual void RemoveProtocolEventObserver(ProtocolEventObserver* observer) = 0; |
| |
| virtual base::WeakPtr<JsController> GetJsController() = 0; |
| |
| // Asynchronously fetches base::Value representations of all sync nodes and |
| // returns them to the specified callback on this thread. |
| // |
| // These requests can live a long time and return when you least expect it. |
| // For safety, the callback should be bound to some sort of WeakPtr<> or |
| // scoped_refptr<>. |
| virtual void GetAllNodesForDebugging( |
| base::OnceCallback<void(std::unique_ptr<base::ListValue>)> callback) = 0; |
| |
| protected: |
| SyncService() {} |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(SyncService); |
| }; |
| |
| } // namespace syncer |
| |
| #endif // COMPONENTS_SYNC_DRIVER_SYNC_SERVICE_H_ |