chromium/components/sync/protocol/sync.proto

// 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 java_multiple_files = true;
option java_package = "org.chromium.components.sync.protocol";

option optimize_for = LITE_RUNTIME;

package sync_pb;

import "components/sync/protocol/client_commands.proto";
import "components/sync/protocol/client_debug_info.proto";
import "components/sync/protocol/data_type_progress_marker.proto";
import "components/sync/protocol/get_updates_caller_info.proto";
import "components/sync/protocol/password_sharing_invitation_specifics.proto";
import "components/sync/protocol/sync_entity.proto";
import "components/sync/protocol/sync_enums.proto";
import "components/sync/protocol/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/40833583): 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];
  // LINT.IfChange(SyncClientToServerMessageContents)
  enum Contents {
    COMMIT = 1;
    GET_UPDATES = 2;
    DEPRECATED_3 = 3;
    DEPRECATED_4 = 4;
    CLEAR_SERVER_DATA = 5;
  }
  // LINT.ThenChange(/tools/metrics/histograms/metadata/sync/enums.xml:SyncClientToServerMessageContents)

  // 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/40751358): 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;
}