tree: bf59e1f84399bb8aaf543e28f09431d920931a0c [path history] [tgz]
  1. android/
  2. base/
  3. engine/
  4. invalidations/
  5. model/
  6. nigori/
  7. protocol/
  8. service/
  9. test/
  10. bootstrap_new_data_type.sh
  11. BUILD.gn
  12. COMMON_METADATA
  13. DEPS
  14. DIR_METADATA
  15. OWNERS
  16. PRESUBMIT.py
  17. PRESUBMIT_test.py
  18. README.md
components/sync/README.md

Chromium Sync Architecture Overview

Chromium Sync is a system designed to synchronize user data (bookmarks, passwords, history, etc.) across multiple devices. It follows a layered architecture to separate high-level service logic, low-level sync protocol management, and individual data type models. This document describes the high-level architecture.

Additional (more specific/detailed) docs are in docs/website/site/developers/design-documents/sync/. You can also visit them via chromium.org.

1. High-Level Architecture

The system is primarily divided into four parts:

A. Service (components/sync/service/)

This is the main public entry point for the rest of Chromium. It runs on the UI thread.

  • SyncService / SyncServiceImpl: The central facade. It manages the overall sync lifecycle (initialization, startup, shutdown) and high-level state.
  • SyncUserSettings: Manages user preferences, such as which data types are enabled and encryption settings.
  • DataTypeController: Responsible for managing the state of a single data type (e.g., Bookmarks). It handles the transition between states like loading the model, connecting to the engine, and stopping. Data types may implement a subclass of this to customize the behavior.

Some important private/internal classes:

  • DataTypeManager: Coordinates the starting and stopping of various data types.
  • SyncAuthManager: Handles Gaia authentication and access tokens.
  • SyncServiceCrypto: Manages encryption state and interacts with the “Nigori” (sync encryption) subsystem.

B. Engine (components/sync/engine/)

The engine performs the actual communication with the Sync server. It runs on a dedicated Sync thread.

  • SyncEngine / SyncEngineImpl: The main interface to the engine. Note that this lives on the UI thread; SyncEngineBackend is the corresponding Sync-thread class.
  • SyncScheduler: Orchestrates when sync cycles should run (based on polling, nudges from local changes, or invalidations from the server).
  • DataTypeWorker: Responsible for the communication with the sync server, including batching, encryption, etc. Instantiated per data type.
  • Syncer: The core logic that executes sync cycles (downloading updates via GetUpdates and uploading changes via Commit).

C. Model (components/sync/model/)

This layer provides the bridge between sync and the individual features / data types (e.g., the Bookmark model). It includes the main APIs that individual features must integrate with in order to Sync (e.g. main data flow). It runs on the model sequence (often a backend/database sequence, but it can also be the UI thread in some cases).

  • DataTypeSyncBridge: An abstract interface that data type owners must implement. It handles merging local and remote data, and receiving and applying remote updates. It is responsible for storing its own sync metadata.
  • SyncableService: A deprecated predecessor to DataTypeSyncBridge. Several data types still use it, but it must not be used for any new data types. Unlike DataTypeSyncBridge, it does not manage its own metadata directly; instead, it is wrapped in a SyncableServiceBasedBridge which uses DataTypeStore (LevelDB) for persistence. Historically, this metadata was managed by a central SQLite database called the “Directory”, which has since been removed.
  • DataTypeLocalChangeProcessor: Used by the bridge to report local changes to sync.
  • DataTypeStore: Offers a simple storage system (LevelDB-based) for features that don't have or need a specific storage system.

D. Protocol (components/sync/protocol/)

  • Contains the Protocol Buffer (.proto) definitions used for communication between the client and the server. sync.proto is the main entry point, with various *_specifics.proto files defining the schema for each data type.

2. Key Data Concepts

  • Entities: The basic unit of sync data (e.g., a single bookmark).
  • Specifics: The type-specific payload of an entity (e.g., the URL and title of a bookmark).
  • Metadata: Information sync needs to track the state of an entity (versions, timestamps, client tags).
  • Client Tag: A unique, stable identifier for an entity across all devices.
  • Nigori: The protocol used for encryption of sync data.

3. Core Workflows

Startup Sequence

  1. SyncServiceImpl::Initialize() is called during browser startup.
  2. SyncAuthManager fetches an OAuth2 access token.
  3. SyncServiceImpl creates the SyncEngine.
  4. DataTypeManager begins a “configuration” cycle, determining which types should start.
  5. Each DataTypeController connects its DataTypeSyncBridge (model) to a DataTypeWorker (engine).

Local Change (Commit)

  1. The user modifies data (e.g., saves a password).
  2. The DataTypeSyncBridge calls processor()->Put().
  3. The DataTypeWorker is notified and “nudges” the SyncScheduler.
  4. The Syncer performs a Commit request, sending the new data to the server.

Remote Change (Update)

  1. The server sends an invalidation (via FCM) or a poll interval elapses.
  2. The Syncer performs a GetUpdates request.
  3. New data is received by the DataTypeWorker and forwarded to the DataTypeSyncBridge.
  4. The bridge merges the remote changes into the local data model via ApplyIncrementalSyncChanges().

4. Sync Modes

  • Sync-the-feature: The classic mode where the user opts in to “Sync everything”. It merges local and account data.
  • Sync-the-transport: The modern mode where sync runs automatically upon sign-in for certain types, keeping local and account data strictly separate.

5. Threading Model

Chromium Sync operates across multiple threads to ensure the UI remains responsive and to isolate complex sync logic.

A. UI Thread

  • Components: SyncService, DataTypeManager, SyncAuthManager, DataTypeController, SyncEngine.
  • Role: Handles interaction with the rest of the browser, manages high-level state, and orchestrates the startup/shutdown of data types.

B. Sync Thread (Sequenced Task Runner)

  • Components: SyncEngineBackend, Syncer, SyncScheduler, DataTypeWorker.
  • Role: Performs all network communication, handles the sync protocol, and manages the sync cycle.
  • Implementation: This is typically a SequencedTaskRunner created via the base::ThreadPool (managed by SyncEngineFactoryImpl).

C. Model Thread(s)

  • Components: DataTypeSyncBridge, DataTypeLocalChangeProcessor, and the actual data models (e.g., BookmarkModel).
  • Role: Processes local changes and applies remote updates to the local data storage.
  • Implementation: The thread depends on the specific data type. Some types (like Bookmarks) run on the UI thread, while others (like Passwords) run on a dedicated background thread.
  • Communication: The ProxyDataTypeControllerDelegate is used to hop from the UI thread to the model thread when they are different.

Thread Communication Map

  • UI -> Sync: SyncEngineImpl (on UI thread) posts tasks to SyncEngineBackend (on Sync thread).
  • Sync -> UI: SyncEngineBackend uses a WeakPtr to SyncEngineImpl to post notifications (like OnEngineInitialized) back to the UI thread.
  • Model -> Sync: DataTypeLocalChangeProcessor (on Model thread) communicates with DataTypeWorker (on Sync thread).
  • Sync -> Model: DataTypeWorker posts tasks to DataTypeProcessor (which lives on the Model thread).