// 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. // // Sync protocol for communication between sync client and server. // If you change or add any fields in this file, update proto_visitors.h and // potentially proto_enum_conversions.{h, cc}. If you add new Specifics proto, // also update proto_value_conversions.{h, cc}. syntax = "proto2"; option go_package = "./sync_pb"; option java_multiple_files = true; option java_package = "org.chromium.components.sync.protocol"; option optimize_for = LITE_RUNTIME; package sync_pb; import "client_commands.proto"; import "client_debug_info.proto"; import "data_type_progress_marker.proto"; import "get_updates_caller_info.proto"; import "password_sharing_invitation_specifics.proto"; import "sync_entity.proto"; import "sync_enums.proto"; import "sharing_message_specifics.proto"; // This message contains diagnostic information used to correlate // commit-related traffic with extensions-related mutations to the // data models in chromium. It plays no functional role in // processing this CommitMessage. message ChromiumExtensionsActivity { // The human-readable ID identifying the extension responsible // for the traffic reported in this ChromiumExtensionsActivity. optional string extension_id = 1; // How many times the extension successfully invoked a write // operation through the bookmarks API since the last CommitMessage. optional uint32 bookmark_writes_since_last_commit = 2; } // Client specific configuration information. message ClientConfigParams { // The set of data types this client has enabled. Note that this does not // include proxy types, as they do not have protocol field numbers and are // placeholder types that implicitly enable protocol types. repeated int32 enabled_type_ids = 1; // Whether the PROXY_TABS proxy datatype is enabled on this client. // Deprecated and not populated anymore since M120. optional bool tabs_datatype_enabled = 2 [deprecated = true]; // Whether the account(s) present in the content area's cookie jar match the // chrome account. If multiple accounts are present in the cookie jar, a // mismatch implies all of them are different from the chrome account. optional bool cookie_jar_mismatch = 3; // Indicates that the client is not aware of any other active clients // interested in the committed data types. This flag shows that it is not // necessary to send invalidations for the committed data. A client is // considered active if it's DeviceInfo has updated recent enough. This flag // does not take into account whether standalone invalidations are enabled (as // opposed to |single_client_with_standalone_invalidations|). However, it's // set depending on interested data types of other devices, e.g. if there are // other devices but they are not interested in SESSION data type, and current // commit request contains only SESSION, it will be set to true. // Introduced in M88. optional bool single_client = 4; // A list of FCM registration tokens which are obtained from other clients. // This list is used by the server to send invalidations to all other clients. // If the list is empty, the server should treat this as "there is no // information about other clients". In practice, this happens by the next // causes: // 1. This is the old client which doesn't set this field. // 2. There are too many active devices and the list would have too many // items. // 3. An empty list could also mean that the current client is the only // client. This case should be covered by the // |single_client_with_standalone_invalidations| field instead (otherwise it // could be mixed up with older clients). The server doesn't have to use this // field and can ignore it. Note that this list does not take into account // interested data types from the other clients. // Introduced in M89. repeated string devices_fcm_registration_tokens = 5; // Similar to |single_client| but takes into account only clients with enabled // sync standalone invalidations. When set to true, there are no other clients // with sync standalone invalidations interested in the committing types and // hence it's not necessary to send out standalone invalidations (it may still // be necessary to send out invalidations using the legacy system, see // |single_client| instead). // Introduced in M105. optional bool single_client_with_standalone_invalidations = 6; // Similar to |devices_fcm_registration_tokens| but takes into account clients // which are subscribed to the data types which are committed in current // commit request. // A list of FCM registration tokens which are obtained from other clients. // This list is used by the server to send invalidations to all other clients. // If the list is empty, the server should treat this as "there is no // information about other clients". In practice, this happens by the next // causes: // 1. This is the old client which doesn't set this field. // 2. There are too many active devices and the list would have too many // items. // 3. An empty list could also mean that the current client is the only // client. This case should be covered by the // |single_client_with_standalone_invalidations| field instead (otherwise it // could be mixed up with older clients). The server doesn't have to use this // field and can ignore it. // Introduced in M105. repeated string fcm_registration_tokens_for_interested_clients = 7; // Similar to |single_client| but takes into account only clients which are // subscribed to old invalidations (i.e. not subscribed to sync standalone // invalidations). When set to true, there are no other clients subscribed to // old invalidations. Note that opposed to |single_client|, this flag does not // always take into account the list of interested data types (because // interested data types were introduced in M89). When the list is empty, a // client is considered to be subscribed to all data types. Note that "single // client" is a bit misleading since this will also be true if there are no // clients with old invalidations at all. // Introduced in M110. optional bool single_client_with_old_invalidations = 8; } message CommitMessage { repeated SyncEntity entries = 1; // A GUID that identifies the committing sync client. This value will be // returned as originator_cache_guid for any new items. optional string cache_guid = 2; repeated ChromiumExtensionsActivity extensions_activity = 3; // The configuration of this client at commit time. Used by the server to // make commit-time decisions about how to process datatypes that might // involve server-side interaction, and e.g require explicit user intent for // syncing a particular data type regardless of whether a commit for that // datatype is currently being sent up. optional ClientConfigParams config_params = 4; // Set of optional per-client datatype contexts. repeated DataTypeContext client_contexts = 5; // This field need to be 256 bytes if set. This attempts to mitigate CRIME // attacks when sync communicate from client to server with compression. So if // compression is used, this need to set a 256 random ASCII bytes. If no // compression, this field should not be set. The server can ignore the // padding. optional string padding = 6; } message GetUpdatesMessage { // Indicates the reason for the GetUpdatesMessage. // This was *mostly* deprecated in M29. GetUpdatesOrigin is the new way to // encode the reason for the GetUpdates request, but some parts of the server // still rely on this field. It also still contains the // "notifications_enabled" flag which needs to be moved elsewhere before this // can be fully removed. See https://crbug.com/510165. optional GetUpdatesCallerInfo caller_info = 2; // Indicates whether related folders should be fetched. optional bool fetch_folders = 3 [default = true]; // Per-datatype progress marker. // // With the exception of certain configuration or initial sync requests, the // client should include one instance of this field for each enabled data // type. repeated DataTypeProgressMarker from_progress_marker = 6; // Indicates whether the response should be sent in chunks. This may be // needed for devices with limited memory resources. If true, the response // will include one or more ClientToServerResponses, with the first one // containing GetUpdatesMetadataResponse, and the remaining ones, if any, // containing GetUpdatesStreamingResponse. These ClientToServerResponses are // delimited by a length prefix, which is encoded as a varint. optional bool streaming = 7 [default = false]; // Whether the client needs the server to provide an encryption key for this // account. // Note: this should typically only be set on the first GetUpdates a client // requests. Clients are expected to persist the encryption key from then on. // The allowed frequency for requesting encryption keys is much lower than // other datatypes, so repeated usage will likely result in throttling. optional bool need_encryption_key = 8 [default = false]; // This value is an updated version of the GetUpdatesCallerInfo's // GetUpdatesSource. It describes the reason for the GetUpdate request. // Introduced in M29. optional SyncEnums.GetUpdatesOrigin get_updates_origin = 9; // Whether this GU also serves as a retry GU. Any GU that happens after // retry timer timeout is a retry GU effectively. optional bool is_retry = 10 [default = false]; // Set of optional per-client datatype contexts. repeated DataTypeContext client_contexts = 11; reserved 1; reserved "from_timestamp"; reserved 4; reserved "requested_types"; reserved 5; reserved "batch_size"; reserved 1000; reserved "create_mobile_bookmarks_folder"; } // Message from a client asking the server to clear its data. This causes the // server to generate a new store birthday, which allows dealing reliably with // in-flight requests (in particular commits) from other clients. message ClearServerDataMessage { // No arguments needed as the store birthday and user identifier are part of // an enclosing message. } // Response to a ClearServerData request. message ClearServerDataResponse { // No result fields necessary. Success/failure is indicated in // ClientToServerResponse. } // The client must preserve, store, and resend the chip bag with // every request. The server depends on the chip bag in order // to precisely choreograph a client-server state machines. // // Because the client stores and sends this data on every request, // the contents of the chip bag should be kept relatively small. // // If the server does not return a chip bag, the client must assume // that there has been no change to the chip bag. The client must // resend the bag of chips it had prior on the next request. // // The client must make the chip bag durable if and only if it // processes the response from the server. message ChipBag { // Server chips are deliberately oqaque, allowing the server // to encapsulate its state machine logic. optional bytes server_chips = 1; } // Information about the syncer's state. message ClientStatus { // Flag to indicate if the client has detected hierarchy conflcits. The flag // is left unset if update application has not been attempted yet. // // The server should attempt to resolve any hierarchy conflicts when this flag // is set. The client may not assume that any particular action will be // taken. There is no guarantee the problem will be addressed in a reasonable // amount of time. // TODO(crbug.com/1315573): Deprecated in M103. optional bool hierarchy_conflict_detected = 1 [deprecated = true]; // Whether the client has full sync (or, sync the feature) enabled or not. optional bool is_sync_feature_enabled = 2; } message ClientToServerMessage { // |share| field is only used on the server for logging and can sometimes // contain empty string. It is still useful for logging username when it can't // be derived from access token in case of auth error. required string share = 1; optional int32 protocol_version = 2 [default = 99]; enum Contents { COMMIT = 1; GET_UPDATES = 2; DEPRECATED_3 = 3; DEPRECATED_4 = 4; CLEAR_SERVER_DATA = 5; } // Each ClientToServerMessage contains one request defined by the // message_contents. Each type has a corresponding message field that will be // present iff the message is of that type. E.g. a commit message will have a // message_contents of COMMIT and its commit field will be present. required Contents message_contents = 3; optional CommitMessage commit = 4; optional GetUpdatesMessage get_updates = 5; reserved 6; reserved "authenticate"; // Opaque server-provided ID representing an "epoch" of the server-side data. // Clients must hand this opaque ID back to the server as part of all requests // within the same sync session (i.e. for all requests to the server except // the very first GetUpdates request). See analogous field // ClientToServerResponse.store_birthday for more details about its lifetime. optional string store_birthday = 7; reserved 8; reserved "sync_problem_detected"; reserved 9; // Client side state information for debugging purpose. // This is only sent on the first getupdates of every sync cycle, // as an optimization to save bandwidth. optional DebugInfo debug_info = 10; // Per-client state for use by the server. Sent with every message sent to the // server. optional ChipBag bag_of_chips = 11; // Google API key. optional string api_key = 12; // Client's self-reported state. // The client should set this on every message sent to the server, though its // member fields may often be unset. optional ClientStatus client_status = 13; // The ID that our invalidation client used to identify itself to the server. // Sending the ID here allows the server to not send notifications of our own // changes to our invalidator. // The field was deprecated in M117 and is no longer populated. optional string invalidator_client_id = 14 [deprecated = true]; // Identifies this ClientToServerMessage as a clear server data request. This // field is present when message_contents is CLEAR_SERVER_DATA. optional ClearServerDataMessage clear_server_data = 15; } message CommitResponse { enum ResponseType { SUCCESS = 1; CONFLICT = 2; // You're out of date; update and check your data // TODO(ncarter): What's the difference between RETRY and TRANSIENT_ERROR? RETRY = 3; // Someone has a conflicting, non-expired session open INVALID_MESSAGE = 4; // What the client sent was invalid, and trying again // won't help. OVER_QUOTA = 5; // This operation would put you, or you are, over quota TRANSIENT_ERROR = 6; // Something went wrong; try again in a bit } repeated group EntryResponse = 1 { required ResponseType response_type = 2; // Sync servers may also return a new ID for an existing item, indicating // a new entry's been created to hold the data the client's sending up. optional string id_string = 3; reserved 4; reserved "parent_id_string"; reserved 5; reserved "position_in_parent"; // The item's current version. optional int64 version = 6; reserved 7; reserved "name"; reserved 8; reserved "non_unique_name"; optional string error_message = 9; // Last modification time (in milliseconds since Unix epoch). Allows the // server to override the client-supplied mtime during a commit operation. // TODO(crbug.com/1182252): Delete this field too. optional int64 mtime = 10 [deprecated = true]; message DatatypeSpecificError { oneof datatype_error { SharingMessageCommitError sharing_message_error = 1; OutgoingPasswordSharingInvitationCommitError outgoing_password_sharing_invitation_error = 2; } } // Datatype specific error (if any). optional DatatypeSpecificError datatype_specific_error = 11; } } message GetUpdatesResponse { // New sync entries that the client should apply. repeated SyncEntity entries = 1; reserved 2; reserved "new_timestamp"; reserved 3; reserved "newest_timestamp"; // Approximate count of changes remaining - use this for UI feedback. // If present and zero, this estimate is firm: the server has no changes // after the current batch. optional int64 changes_remaining = 4; // Opaque, per-datatype timestamp-like tokens. Clients should retain and // persist the values returned in this field, and present them back to the // server to indicate the starting point for future update requests. // // This will be sent only if the client provided |from_progress_marker| // in the update request. // // The server may provide a new progress marker even if this is the end of // the batch, or if there were no new updates on the server; and the client // must save these. If the server does not provide a |new_progress_marker| // value for a particular datatype, when the request provided a // |from_progress_marker| value for that datatype, the client should // interpret this to mean "no change from the previous state" and retain its // previous progress-marker value for that datatype. repeated DataTypeProgressMarker new_progress_marker = 5; // The current encryption keys associated with this account. Will be set if // the GetUpdatesMessage in the request had need_encryption_key == true or // the server has updated the set of encryption keys (e.g. due to a key // rotation). repeated bytes encryption_keys = 6; // Set of optional datatype contexts server mutations. repeated DataTypeContext context_mutations = 7; } message ClientToServerResponse { optional CommitResponse commit = 1; optional GetUpdatesResponse get_updates = 2; reserved 3; reserved "authenticate"; // Up until protocol_version 24, the default was SUCCESS which made it // impossible to add new enum values since older clients would parse any // out-of-range value as SUCCESS. Starting with 25, unless explicitly set, // the error_code will be UNKNOWN so that clients know when they're // out-of-date. Note also that when using protocol_version < 25, // TRANSIENT_ERROR is not supported. Instead, the server sends back a HTTP // 400 error code. This is deprecated now. optional SyncEnums.ErrorType error_code = 4 [default = UNKNOWN]; optional string error_message = 5; // Opaque server-provided ID representing an "epoch" of the server-side data, // referred to as "birthday" or "store birthday". This ID remains fixed until // server-side data gets cleared/reset (e.g. via ClearServerDataMessage), // which clients experience as NOT_MY_BIRTHDAY error, and involves clearing // all local sync metadata including the cached store birthday. // // This mechanism allows the server to implement clear-data/reset // functionality that reliably identifies and deletes sync entities uploaded // before the clear-data/reset event (e.g. via ClearServerDataMessage). // Furthermore, it allows the server to deal reliably with in-flight changes // from other clients upon clear-data event, because all writes issued with an // outdated birthday (which in-flight writes would use) can be detected by the // server. optional string store_birthday = 6; optional ClientCommand client_command = 7; reserved 8; reserved "profiling_data"; reserved 9; reserved 10; reserved "stream_metadata"; reserved 11; reserved "stream_data"; // The data types whose storage has been migrated. Present when the value of // error_code is MIGRATION_DONE. repeated int32 migrated_data_type_id = 12; message Error { optional SyncEnums.ErrorType error_type = 1 [default = UNKNOWN]; optional string error_description = 2; reserved 3; reserved "url"; optional SyncEnums.Action action = 4 [default = UNKNOWN_ACTION]; // Currently meaningful if |error_type| is throttled or partial_failure. // In the throttled case, if this field is absent then the whole client // (all datatypes) is throttled. // In the partial_failure case, this field denotes partial failures. The // client should retry those datatypes with exponential backoff. repeated int32 error_data_type_ids = 5; } optional Error error = 13; // The new per-client state for this client. If set, should be persisted and // sent with any subsequent ClientToServerMessages. optional ChipBag new_bag_of_chips = 14; // Present if this ClientToServerResponse is in response to a ClearServerData // request. optional ClearServerDataResponse clear_server_data = 15; } // A message to notify the server of certain sync events. Idempotent. Send these // to the /event endpoint. message EventRequest { optional SyncDisabledEvent sync_disabled = 1; } message EventResponse {} // A message indicating that the sync engine has been disabled on a client. message SyncDisabledEvent { // The GUID that identifies the sync client. optional string cache_guid = 1; // The store birthday that the client was using before disabling sync. optional string store_birthday = 2; }