diff --git a/.gitignore b/.gitignore
index c3179e3..7aa78e2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,4 +14,5 @@ pyhindsight/static/web_modules/
.claude/
hindsight-temp/
data-sets/
-/temp_outputs/
\ No newline at end of file
+/temp_outputs/
+/test-fixtures/
diff --git a/pyhindsight/lib/components/download/database/proto/download_entry.proto b/pyhindsight/lib/components/download/database/proto/download_entry.proto
new file mode 100644
index 0000000..aa0c1b0
--- /dev/null
+++ b/pyhindsight/lib/components/download/database/proto/download_entry.proto
@@ -0,0 +1,110 @@
+// Copyright 2017 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package download_pb;
+
+import "components/download/database/proto/download_source.proto";
+
+message HttpRequestHeader {
+ optional string key = 1;
+ optional string value = 2;
+}
+
+// Slice information for parallel downloading.
+message ReceivedSlice {
+ optional int64 offset = 1;
+ optional int64 received_bytes = 2;
+ optional bool finished = 3;
+}
+
+// Stores various in-progress metadata related to a download.
+message DownloadEntry {
+ optional string guid = 1;
+ optional string request_origin = 2;
+ optional DownloadSource download_source = 3;
+ optional int64 ukm_download_id = 4;
+ optional int64 bytes_wasted = 5;
+ optional bool fetch_error_body = 6;
+ repeated HttpRequestHeader request_headers = 7;
+}
+
+// Contains a list of entries.
+message DownloadEntries {
+ repeated DownloadEntry entries = 1;
+}
+
+// Information for ukm reporting
+message UkmInfo {
+ optional DownloadSource download_source = 1;
+ optional int64 ukm_download_id = 2;
+}
+
+// Information about when to start the download, used by download later feature.
+// Deprecated.
+message DownloadSchedule {
+ optional int64 start_time = 1;
+}
+
+// Information about an in progress download.
+message InProgressInfo {
+ repeated string url_chain = 1;
+ optional string referrer_url = 2;
+ optional string site_url = 3; // deprecated
+ optional string tab_url = 4;
+ optional string tab_referrer_url = 5;
+ optional bool fetch_error_body = 6;
+ repeated HttpRequestHeader request_headers = 7;
+ optional string etag = 8;
+ optional string last_modified = 9;
+ optional int64 total_bytes = 10;
+ optional string mime_type = 11;
+ optional string original_mime_type = 12;
+ optional bytes current_path = 13; // Serialized pickles to support string16
+ optional bytes target_path = 14; // Serialized pickles to support string16
+ optional int64 received_bytes = 15;
+ optional int64 start_time = 16;
+ optional int64 end_time = 17;
+ repeated ReceivedSlice received_slices = 18;
+ optional bytes hash = 19; // Hindsight: upstream declares this `string` but it holds the
+ // raw binary SHA-256; `bytes` lets us extract/hex it cleanly.
+ optional bool transient = 20;
+ optional int32 state = 21;
+ optional int32 danger_type = 22;
+ optional int32 interrupt_reason = 23;
+ optional bool paused = 24;
+ optional bool metered = 25;
+ optional int64 bytes_wasted = 26;
+ optional int32 auto_resume_count = 27;
+ optional DownloadSchedule download_schedule = 28; // // Deprecated.
+ // Removing DownloadItemRerouteInfo since FileSystem Connector will not
+ // be released, implementation deleted.
+ reserved 29;
+ optional int32 credentials_mode = 30; // network::mojom::CredentialsMode
+ optional int64 range_request_from = 31;
+ optional int64 range_request_to = 32;
+ optional bytes serialized_embedder_download_data = 33; // Hindsight: upstream `string`,
+ // but holds a serialized content.proto.EmbedderDownloadData;
+ // `bytes` lets us FromString it cleanly.
+ reserved 34;
+ optional bool fetched_via_service_worker = 35;
+}
+
+// Stores various metadata related to a download.
+// WIP and will replace DownloadEntry.
+message DownloadInfo {
+ optional string guid = 1;
+ optional int32 id = 2;
+ optional UkmInfo ukm_info = 3;
+ optional InProgressInfo in_progress_info = 4;
+}
+
+// In progress database entry for download information.
+message DownloadDBEntry {
+ // Add field for offline page download.
+ oneof entry { DownloadInfo download_info = 1; }
+}
diff --git a/pyhindsight/lib/components/download/database/proto/download_source.proto b/pyhindsight/lib/components/download/database/proto/download_source.proto
new file mode 100644
index 0000000..43a8f1c
--- /dev/null
+++ b/pyhindsight/lib/components/download/database/proto/download_source.proto
@@ -0,0 +1,27 @@
+// Copyright 2017 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package download_pb;
+
+// This should stay in sync with the download::DownloadSource enum in
+// components/download/public/common/download_source.h.
+enum DownloadSource {
+ UNKNOWN = 0;
+ NAVIGATION = 1;
+ DRAG_AND_DROP = 2;
+ FROM_RENDERER = 3;
+ EXTENSION_API = 4;
+ EXTENSION_INSTALLER = 5;
+ INTERNAL_API = 6;
+ WEB_CONTENTS_API = 7;
+ OFFLINE_PAGE = 8;
+ CONTEXT_MENU = 9;
+ RETRY = 10;
+ RETRY_FROM_BUBBLE = 11;
+ TOOLBAR_MENU = 12;
+}
diff --git a/pyhindsight/lib/components/performance_manager/persistence/site_data/site_data.proto b/pyhindsight/lib/components/performance_manager/persistence/site_data/site_data.proto
new file mode 100644
index 0000000..0c4e604
--- /dev/null
+++ b/pyhindsight/lib/components/performance_manager/persistence/site_data/site_data.proto
@@ -0,0 +1,49 @@
+// Copyright 2019 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+// Contains the information that we want to track about a given site feature.
+// Next Id: 3
+message SiteDataFeatureProto {
+ // The cumulative observation time for this feature in seconds, set to 0 once
+ // this feature has been observed.
+ optional int64 observation_duration = 1;
+ // The time at which this feature has been used (set to 0 if it hasn't been
+ // used), in seconds since epoch.
+ optional int64 use_timestamp = 2;
+}
+
+// Contains decaying average performance measurement estimates.
+// Next Id: 4
+message SiteDataPerformanceMeasurement {
+ // A decaying average of the CPU usage measurements. Units: microseconds.
+ optional float avg_cpu_usage_us = 1;
+ // A decaying average of the process footprint measurements. Units: kilobytes.
+ optional float avg_footprint_kb = 2;
+ // A decaying average of the duration from navigation commit to "loaded".
+ // Units: microseconds.
+ optional float avg_load_duration_us = 3;
+};
+
+// Defines the data that we want to track about a given site.
+// Next Id: 7
+message SiteDataProto {
+ // The last time this site has been in the loaded state, in seconds since
+ // epoch.
+ optional uint32 last_loaded = 1;
+
+ // List of features that we're tracking.
+ optional SiteDataFeatureProto updates_favicon_in_background = 2;
+ optional SiteDataFeatureProto updates_title_in_background = 3;
+ optional SiteDataFeatureProto uses_audio_in_background = 4;
+ optional SiteDataFeatureProto deprecated_uses_notifications_in_background = 5;
+
+ // Load time performance measurement estimates. This maintains a decaying
+ // average of the resource usage of a page until shortly after it becomes
+ // idle.
+ optional SiteDataPerformanceMeasurement load_time_estimates = 6;
+}
\ No newline at end of file
diff --git a/pyhindsight/lib/components/services/storage/service_worker/service_worker_database.proto b/pyhindsight/lib/components/services/storage/service_worker/service_worker_database.proto
new file mode 100644
index 0000000..42499c8
--- /dev/null
+++ b/pyhindsight/lib/components/services/storage/service_worker/service_worker_database.proto
@@ -0,0 +1,304 @@
+// Copyright 2014 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package storage;
+
+message ServiceWorkerOriginTrialFeature {
+ required string name = 1;
+ repeated string tokens = 2;
+}
+
+message ServiceWorkerOriginTrialInfo {
+ repeated ServiceWorkerOriginTrialFeature features = 1;
+}
+
+message ServiceWorkerNavigationPreloadState {
+ required bool enabled = 1;
+ optional string header = 2;
+}
+
+// NEXT ID TO USE: 27
+message ServiceWorkerRegistrationData {
+ enum ServiceWorkerScriptType {
+ CLASSIC = 0;
+ MODULE = 1;
+ }
+ enum ServiceWorkerUpdateViaCacheType {
+ IMPORTS = 0;
+ ALL = 1;
+ NONE = 2;
+ }
+ enum CrossOriginEmbedderPolicyValue {
+ NONE_OR_NOT_EXISTENT = 0;
+ REQUIRE_CORP = 1;
+ CREDENTIALLESS = 2;
+ }
+ enum AncestorFrameType {
+ NORMAL_FRAME = 0;
+ FENCED_FRAME = 1;
+ }
+ enum FetchHandlerSkippableType {
+ reserved 0; // Deprecated UNKNOWN_FETCH_HANDLER.
+ NOT_SKIPPABLE = 1;
+ SKIPPABLE_EMPTY_FETCH_HANDLER = 2;
+ }
+ enum ReferrerPolicyValue {
+ ALWAYS = 0;
+ DEFAULT = 1;
+ NO_REFERRER_WHEN_DOWNGRADE = 2;
+ NEVER = 3;
+ ORIGIN = 4;
+ ORIGIN_WHEN_CROSS_ORIGIN = 5;
+ STRICT_ORIGIN_WHEN_CROSS_ORIGIN = 6;
+ SAME_ORIGIN = 7;
+ STRICT_ORIGIN = 8;
+ }
+
+ // https://wicg.github.io/local-network-access/
+ enum IPAddressSpace {
+ UNKNOWN = 0;
+ LOOPBACK = 1;
+ LOCAL = 2;
+ PUBLIC = 3;
+ }
+
+ message PolicyContainerPolicies {
+ optional ReferrerPolicyValue referrer_policy = 1 [default = DEFAULT];
+ optional int32 sandbox_flags = 2 [default = 0];
+ optional IPAddressSpace ip_address_space = 3 [default = UNKNOWN];
+ // TODO(crbug.com/4016869): add content security policies
+ }
+
+ message RouterRules {
+ message RuleV1 {
+ message Condition {
+ // Structure representing a URLPattern as described in:
+ // https://wicg.github.io/urlpattern/.
+ message URLPattern {
+ message Part {
+ enum Modifier {
+ kNone = 0;
+ kOptional = 1;
+ kZeroOrMore = 2;
+ kOneOrMore = 3;
+ }
+ // Represents a fixed string part of a URLPattern as described in:
+ // https://wicg.github.io/urlpattern/#part-type-fixed-text
+ message FixedPattern {
+ optional string value = 1;
+ }
+ // Represents either a segment wildcard part or a full wildcard
+ // part of a URLPattern as described in:
+ // https://wicg.github.io/urlpattern/#parts
+ message WildcardPattern {
+ optional string name = 1;
+ optional string prefix = 2;
+ optional string value = 3;
+ optional string suffix = 4;
+ }
+ optional Modifier modifier = 1;
+ oneof pattern {
+ FixedPattern fixed = 2;
+ // Note that kRegex PartType is not implemented because we do not
+ // execute regexp in the browser process for security concerns.
+ // (but reserve 3 for regex just in case).
+ WildcardPattern segment_wildcard = 4;
+ WildcardPattern full_wildcard = 5;
+ }
+ }
+ message Options {
+ optional bool ignore_case = 1 [default = false];
+ }
+
+ repeated Part legacy_pathname = 1;
+
+ repeated Part protocol = 3;
+ repeated Part username = 4;
+ repeated Part password = 5;
+ repeated Part hostname = 2;
+ repeated Part port = 6;
+ repeated Part pathname = 7;
+ repeated Part search = 8;
+ repeated Part hash = 9;
+
+ optional Options options = 10;
+ }
+ message Request {
+ optional string method = 1;
+ // RequestMode in services/network/public/mojom/fetch_api.mojom
+ enum Mode {
+ kSameOriginMode = 0;
+ kNoCorsMode = 1;
+ kCorsMode = 2;
+ kCorsWithForcedPreflightMode = 3;
+ kNavigateMode = 4;
+ }
+ optional Mode mode = 2;
+ // RequestDestination in services/network/public/mojom/fetch_api.mojom
+ enum Destination {
+ kEmptyDestination = 0;
+ kAudioDestination = 1;
+ kAudioWorkletDestination = 2;
+ kDocumentDestination = 3;
+ kEmbedDestination = 4;
+ kFontDestination = 5;
+ kFrameDestination = 6;
+ kIframeDestination = 7;
+ kImageDestination = 8;
+ kManifestDestination = 9;
+ kObjectDestination = 10;
+ kPaintWorkletDestination = 11;
+ kReportDestination = 12;
+ kScriptDestination = 13;
+ kServiceWorkerDestination = 14;
+ kSharedWorkerDestination = 15;
+ kStyleDestination = 16;
+ kTrackDestination = 17;
+ kVideoDestination = 18;
+ kWebBundleDestination = 19;
+ kWorkerDestination = 20;
+ kXsltDestination = 21;
+ kFencedframeDestination = 22;
+ kWebIdentityDestination = 23;
+ kDictionaryDestination = 24;
+ kSpeculationRulesDestination = 25;
+ kJsonDestination = 26;
+ kSharedStorageWorkletDestination = 27;
+ kEmailVerificationDestination = 28;
+ }
+ optional Destination destination = 3;
+ }
+ message RunningStatus {
+ enum Status {
+ kRunning = 0;
+ kNotRunning = 1;
+ }
+ optional Status status = 1;
+ }
+ // TODO(crbug.com/4028565): Remove and replace this to `condition`
+ message ConditionObject {
+ repeated Condition conditions = 1;
+ }
+ message OrCondition {
+ repeated ConditionObject objects = 1;
+ }
+ message NotCondition {
+ required ConditionObject object = 1;
+ }
+ // TODO(crbug.com/4028565): Make this a `message` to fit WebIDL
+ oneof condition {
+ // Used for representing URLPattern.
+ URLPattern url_pattern = 1;
+ // Used for representing Request.
+ Request request = 2;
+ // Used for representing running status.
+ RunningStatus running_status = 3;
+ // Used for representing 'or' condition.
+ // The `_condition` suffix is to avoid conflicts with keywords in C++
+ OrCondition or_condition = 4;
+ // Used for representing 'not' condition.
+ // The `_condition` suffix is to avoid conflicts with keywords in C++
+ NotCondition not_condition = 5;
+ }
+ }
+ message Source {
+ message NetworkSource {}
+ message RaceNetworkAndFetchEventSource {
+ reserved 1; // Deprecated
+ reserved "target"; // Deprecated
+ }
+ message FetchEventSource {}
+ message CacheSource {
+ optional string cache_name = 1;
+ }
+ message RaceNetworkAndCacheSource {
+ required CacheSource cache_source = 1;
+ }
+ oneof source {
+ NetworkSource network_source = 1;
+ RaceNetworkAndFetchEventSource race_network_and_fetch_event_source =
+ 2;
+ FetchEventSource fetch_event_source = 3;
+ CacheSource cache_source = 4;
+ RaceNetworkAndCacheSource race_network_and_cache_source = 5;
+ }
+ }
+ repeated Condition condition = 1;
+ repeated Source source = 2;
+ }
+
+ required int32 version = 1;
+ repeated RuleV1 v1 = 2;
+ }
+
+ required int64 registration_id = 1;
+ required string scope_url = 2;
+ required string script_url = 3;
+
+ // Versions are first stored once they successfully install and become the
+ // waiting version. Then they are updated when they transition to the active
+ // version.
+ required int64 version_id = 4;
+
+ required bool is_active = 5;
+ required bool has_fetch_handler = 6;
+ optional FetchHandlerSkippableType fetch_handler_skippable_type = 22;
+
+ // Serialized by Time::FromDeltaSinceWindowsEpoch().
+ required int64 last_update_check_time = 7;
+
+ optional uint64 resources_total_size_bytes = 8;
+
+ // repeated string foreign_fetch_scope = 9; // obsolete
+ // repeated string foreign_fetch_origin = 10; // obsolete
+
+ // If the registration data was created by old Chrome (< M56),
+ // |origin_trial_tokens| is not set. In this case, we have to start the
+ // Service Worker and load the main script resource in ServiceWorkerStorage
+ // to check the HTTP header.
+ optional ServiceWorkerOriginTrialInfo origin_trial_tokens = 11;
+
+ optional ServiceWorkerNavigationPreloadState navigation_preload_state = 12;
+
+ // The set of features that the worker used up until the time installation
+ // completed. The values must be from blink::UseCounter::Feature enum.
+ repeated uint32 used_features = 13;
+
+ optional ServiceWorkerUpdateViaCacheType update_via_cache = 14
+ [default = IMPORTS];
+ optional ServiceWorkerScriptType script_type = 15 [default = CLASSIC];
+
+ // The time when the browser received the service worker main script,
+ // serialized by Time::ToDeltaSinceWindowsEpoch().
+ optional int64 script_response_time = 16;
+
+ optional CrossOriginEmbedderPolicyValue cross_origin_embedder_policy_value =
+ 17 [default = NONE_OR_NOT_EXISTENT];
+ optional string cross_origin_embedder_policy_reporting_endpoint = 18;
+ optional CrossOriginEmbedderPolicyValue
+ cross_origin_embedder_policy_report_only_value = 19
+ [default = NONE_OR_NOT_EXISTENT];
+ optional string cross_origin_embedder_policy_report_only_reporting_endpoint =
+ 20;
+ optional AncestorFrameType ancestor_frame_type = 21 [default = NORMAL_FRAME];
+
+ optional PolicyContainerPolicies policy_container_policies = 23;
+
+ optional RouterRules router_rules = 24;
+
+ optional bool has_hid_event_handlers = 25;
+
+ optional bool has_usb_event_handlers = 26;
+}
+
+message ServiceWorkerResourceRecord {
+ required int64 resource_id = 1;
+ required string url = 2;
+ optional uint64 size_bytes = 3;
+ optional string sha256_checksum = 4;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/BUILD.gn b/pyhindsight/lib/components/sync/protocol/BUILD.gn
new file mode 100644
index 0000000..50219ae
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/BUILD.gn
@@ -0,0 +1,83 @@
+# Copyright 2014 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/protobuf/proto_library.gni")
+import("protocol_sources.gni")
+
+proto_library("protocol") {
+ proto_in_dir = "//"
+ sources = sync_protocol_sources
+ extra_configs = [ "//build/config/compiler:wexit_time_destructors" ]
+}
+
+# TODO(crbug.com/41449994): It seems some code implicitly depends on "util" due to
+# it being listed in public_deps of upper directories (even though it doesn't
+# fit the definition of public_deps). Consider using a group() to expose this
+# together with the "protocol" target and simplify things.
+static_library("util") {
+ sources = [
+ "collaboration_metadata.cc",
+ "collaboration_metadata.h",
+ "data_type_state_helper.cc",
+ "data_type_state_helper.h",
+ "entity_data.cc",
+ "entity_data.h",
+ "proto_enum_conversions.cc",
+ "proto_enum_conversions.h",
+ "proto_memory_estimations.cc",
+ "proto_memory_estimations.h",
+ "proto_value_conversions.cc",
+ "proto_value_conversions.h",
+ "proto_visitors.h",
+ ]
+
+ public_deps = [
+ "//base",
+ "//components/sync/base",
+ "//google_apis",
+ ]
+}
+
+if (is_android) {
+ import("//build/config/android/rules.gni")
+
+ proto_java_library("protocol_java") {
+ proto_path = "//"
+ sources = sync_protocol_sources
+ }
+}
+
+action("prepare_full_proto") {
+ script = "prepare_full_proto.py"
+
+ inputs = [
+ "sync_collaboration_attribution.proto",
+ "shared_tab_group_data_specifics.proto",
+ "unique_position.proto",
+ ]
+
+ outputs = [
+ "$target_gen_dir/sync_collaboration_attribution_full_proto.proto",
+ "$target_gen_dir/shared_tab_group_data_specifics_full_proto.proto",
+ "$target_gen_dir/unique_position_full_proto.proto",
+ ]
+
+ args = [ rebase_path(target_gen_dir, root_build_dir) ]
+
+ foreach(f, inputs) {
+ args += [ rebase_path(f, root_build_dir) ]
+ }
+}
+
+proto_library("full_proto") {
+ testonly = true
+ proto_in_dir = root_gen_dir
+ proto_out_dir = "."
+ sources = get_target_outputs(":prepare_full_proto")
+
+ proto_deps = [ ":prepare_full_proto" ]
+
+ use_protobuf_full = true
+ import_dirs = [ "//third_party/protobuf/src" ]
+}
diff --git a/pyhindsight/lib/components/sync/protocol/DEPS b/pyhindsight/lib/components/sync/protocol/DEPS
new file mode 100644
index 0000000..eae6436
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+ "+components/sync/base",
+ "+google/protobuf/descriptor.h" # for unit tests.
+]
diff --git a/pyhindsight/lib/components/sync/protocol/README.md b/pyhindsight/lib/components/sync/protocol/README.md
new file mode 100644
index 0000000..0425ed5
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/README.md
@@ -0,0 +1,33 @@
+Sync Protocol Style
+===================
+
+General guidelines:
+* Follow the [Protocol Buffers Style Guide](https://developers.google.com/protocol-buffers/docs/style)
+* Follow the [Proto Do's and Don'ts](http://go/protodosdonts) (sorry, Googlers only).
+* Maintain local consistency.
+* Use proto2 syntax.
+
+Some specific guidelines on top of the general ones above, or just things that often come up:
+* Avoid using "explicit version numbers" in your protobuf; instead, have your code test for the existence of a field to determine what to do. Protobufs were written precisely to avoid version-specific logic, and testing for fields is more robust.
+* Enum entries should be in ALL_CAPS (different from C++!), and for new code, the first entry should be a `FOO_UNSPECIFIED = 0` one.
+* Timestamp fields must specify their epoch and unit in a suffix, in this format: `_[unix|windows]_epoch_[seconds|millis|micros|nanos]`, e.g `creation_time_unix_epoch_millis`.
+ * Many existing fields do not follow this format, and specify epoch/unit in a comment instead. Follow the format for all new fields, though!
+* Similarly, duration fields must specify their unit as `_[minutes|seconds|millis|...]`.
+* Proto changes also require corresponding changes in [proto_visitors.h](https://source.chromium.org/chromium/chromium/src/+/main:components/sync/protocol/proto_visitors.h) and (where appropriate) in [proto_enum_conversions.h/cc](https://source.chromium.org/chromium/chromium/src/+/main:components/sync/protocol/proto_enum_conversions.cc).
+* Backwards compatibility: In general, all changes must be fully backwards-compatible - consider that a single user might be running different versions of the browser simultaneously! Also note that Sync supports clients up to a few years old, so deprecating/removing an existing field is typically a multi-year process.
+ * As one special case, **renaming** a field **within a specifics message** is generally safe (unless there are special server-side integrations that depend on the name). However, **never** rename fields anywhere outside of specifics.
+ * Avoid repurposing existing fields. Instead, add a new field for the new data and deprecate the old field. Also consider adding code to migrate the old field to the new field.
+* Adding fields:
+ * Any new fields in a proto are unrecognized by older clients. Thus, any such change faces an inherent risk of leading to data loss for a multi-client Sync user when an older client commits. It is recommended for the data type to follow [Protection against data override by old Sync clients][forward-compatibility] for forward-compatibility.
+* Deprecating fields:
+ * If the field **is** still accessed: Mark it as `[deprecated = true]`. This is the common case, since the browser typically needs to continue supporting the old field for backwards compatibility reasons.
+ * If the field **is not** accessed anymore (i.e. no non-ancient clients depend on the field being populated anymore, all migration code has been retired, etc): Remove the field, and add `reserved` entries for both its name and its tag number.
+ * **Note**: If your data type is using the [Protection against data override by old Sync clients][forward-compatibility], then even fields that aren't accessed anymore should **not** be removed from the proto definition, since they should still be treated as supported for the purpose of trimming. (Otherwise, the removed fields would forever be carried forward in the data.)
+
+* Deprecating enum values: This is particularly tricky, especially if the default value is not a `FOO_UNSPECIFIED` one (see above). A common pattern is prepending `DEPRECATED_` to the entry name.
+
+For reviewers:
+* Be extra careful with protocol changes, especially consider backward and forward compatibility.
+* In doubt, loop in a second reviewer from the Sync team.
+
+[forward-compatibility]: https://www.chromium.org/developers/design-documents/sync/old-sync-clients-data-override-protection/
diff --git a/pyhindsight/lib/components/sync/protocol/app_list_specifics.proto b/pyhindsight/lib/components/sync/protocol/app_list_specifics.proto
new file mode 100644
index 0000000..375b99c
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/app_list_specifics.proto
@@ -0,0 +1,90 @@
+// Copyright 2013 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 datatype extension for the app list (aka app launcher).
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+// Properties of app list objects.
+message AppListSpecifics {
+ // Unique identifier for the item:
+ // * TYPE_FOLDER: Folder id (generated)
+ // * TYPE_APP: App Id
+ optional string item_id = 1;
+
+ // What type of item this is.
+ enum AppListItemType {
+ // An app, whether a web app, Android app, etc.
+ //
+ // For bookmark apps (URL shortcuts), additional information such as their
+ // URLs are kept in the AppSpecifics.bookmark_app_foobar fields.
+ TYPE_APP = 1;
+ // A request to remove any matching default installed apps.
+ TYPE_REMOVE_DEFAULT_APP = 2;
+ // A folder containing entries whose `parent_id` matches `item_id`.
+ TYPE_FOLDER = 3;
+ // Obsolete type, intended for URL shortcuts, that was never implemented.
+ TYPE_OBSOLETE_URL = 4;
+ // A "page break" item (Indicate creation of a new page in app list).
+ TYPE_PAGE_BREAK = 5;
+ }
+ optional AppListItemType item_type = 2;
+
+ // Item name (FOLDER).
+ optional string item_name = 3;
+
+ // Id of the parent (folder) item.
+ optional string parent_id = 4;
+
+ // Marked OBSOLETE because this is unused for the app list.
+ // Which page this item will appear on in the app list.
+ optional string OBSOLETE_page_ordinal = 5 [deprecated = true];
+
+ // Where on a page this item will appear.
+ optional string item_ordinal = 6;
+
+ // Where on a shelf this item will appear.
+ optional string item_pin_ordinal = 7;
+
+ // The color groups used for grouping together icons by colors.
+ enum ColorGroup {
+ COLOR_EMPTY = 0;
+ COLOR_WHITE = 1;
+ COLOR_RED = 2;
+ COLOR_ORANGE = 3;
+ COLOR_YELLOW = 4;
+ COLOR_GREEN = 5;
+ COLOR_BLUE = 6;
+ COLOR_MAGENTA = 7;
+ COLOR_BLACK = 8;
+ }
+
+ message IconColor {
+ // The item icon's background color.
+ optional ColorGroup background_color = 1;
+
+ // The item icon's hue.
+ optional int32 hue = 2;
+ }
+ optional IconColor item_color = 8;
+
+ // This field previously stored the is_user_pinned value, which has been
+ // removed.
+ reserved 9;
+
+ // Identifier for the app package of the item. Package Ids are stable and
+ // globally unique across app platforms, whereas App Id stored in item_id is
+ // not.
+ optional string promise_package_id = 10;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/app_setting_specifics.proto b/pyhindsight/lib/components/sync/protocol/app_setting_specifics.proto
new file mode 100644
index 0000000..8e9d93a
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/app_setting_specifics.proto
@@ -0,0 +1,26 @@
+// 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 datatype extension for an app setting.
+// This is the same as for an extension setting, but uses a separate datatype
+// in order to control syncability separately.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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/extension_setting_specifics.proto";
+
+// Properties of app setting sync objects; just an extension setting.
+message AppSettingSpecifics {
+ optional ExtensionSettingSpecifics extension_setting = 1;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/app_specifics.proto b/pyhindsight/lib/components/sync/protocol/app_specifics.proto
new file mode 100644
index 0000000..4ab12d0
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/app_specifics.proto
@@ -0,0 +1,101 @@
+// 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 datatype extension for apps.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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/extension_specifics.proto";
+
+// Settings related to push notifications for apps.
+message AppNotificationSettings {
+ // DEPRECATED: Use oauth_client_id below.
+ // Whether or not the user has setup notifications at least once.
+ // The value for this field will start out false and will be set
+ // to true when the user accepts receiving notifications for the
+ // first time and then it will always remain true.
+ optional bool initial_setup_done = 1 [deprecated = true];
+
+ // Whether or not the user has disabled notifications.
+ optional bool disabled = 2;
+
+ // OAuth2 client id to which the user granted the notification permission.
+ // This field will start out empty.
+ // It will be set when the user accepts receiving notifications.
+ // This field is used when the user revokes the notifications permission.
+ // Note that it is never cleared after it was set once. Hence, the presence
+ // of this field can be used to determine if the user has setup notifications
+ // at least once for the given app.
+ optional string oauth_client_id = 3;
+}
+
+// Information about a linked app icon.
+message LinkedAppIconInfo {
+ // The URL of the app icon.
+ optional string url = 1;
+
+ // The size of the app icon in DIPs.
+ optional uint32 size = 2;
+}
+
+// Properties of app sync objects.
+//
+// For now, an app is just an extension. We keep the two data types
+// separate for future-proofing purposes.
+message AppSpecifics {
+ // Extension data.
+ optional ExtensionSpecifics extension = 1;
+
+ // Notification settings.
+ optional AppNotificationSettings notification_settings = 2;
+
+ // This controls where on a page this application icon will appear.
+ optional string app_launch_ordinal = 3;
+
+ // This specifics which page the application icon will appear on in the NTP.
+ // This values only provide the order within the application pages, not within
+ // all of the panels in the NTP.
+ optional string page_ordinal = 4;
+
+ // The possible launch types for an app.
+ // This enum should be kept in sync with extensions::LaunchType.
+ enum LaunchType {
+ PINNED = 0;
+ REGULAR = 1;
+ FULLSCREEN = 2;
+ WINDOW = 3;
+ }
+
+ // This describes how the extension should be launched.
+ optional LaunchType launch_type = 5;
+
+ // DEPRECATED. See https://crbug.com/1233303.
+ optional string bookmark_app_url = 6 [deprecated = true];
+
+ // DEPRECATED. See https://crbug.com/1233303.
+ optional string bookmark_app_description = 7 [deprecated = true];
+
+ // DEPRECATED. See https://crbug.com/1233303.
+ optional string bookmark_app_icon_color = 8 [deprecated = true];
+
+ // This is information about linked icons (that is, icons that are downloaded
+ // from outside the app's bundle of files.
+ repeated LinkedAppIconInfo linked_app_icons = 9;
+
+ // DEPRECATED. See https://crbug.com/1233303.
+ optional string bookmark_app_scope = 10 [deprecated = true];
+
+ // DEPRECATED. See https://crbug.com/1233303.
+ optional uint32 bookmark_app_theme_color = 11 [deprecated = true];
+}
diff --git a/pyhindsight/lib/components/sync/protocol/arc_package_specifics.proto b/pyhindsight/lib/components/sync/protocol/arc_package_specifics.proto
new file mode 100644
index 0000000..6720158
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/arc_package_specifics.proto
@@ -0,0 +1,30 @@
+// Copyright 2016 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 datatype extension for ARC pakcages.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+// Properties of arc package objects.
+message ArcPackageSpecifics {
+ // Unique identifier for the item:
+ // Android package name.
+ optional string package_name = 1;
+ // Android package version.
+ optional int32 package_version = 2;
+ // Last Android id generated when Android side backups data.
+ optional int64 last_backup_android_id = 3;
+ // Last time internal value that Android side backups data.
+ optional int64 last_backup_time = 4;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/autofill_offer_specifics.proto b/pyhindsight/lib/components/sync/protocol/autofill_offer_specifics.proto
new file mode 100644
index 0000000..c92e98d
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/autofill_offer_specifics.proto
@@ -0,0 +1,108 @@
+// Copyright 2020 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+// Properties of Autofill wallet offer related objects.
+
+// Next tag: 11
+message AutofillOfferSpecifics {
+ // The id for this offer data. Will be used as the client tag.
+ optional int64 id = 1;
+
+ // The link leading to the offer details page on Gpay app. Will be populated
+ // on Android only.
+ optional string offer_details_url = 2;
+
+ // Merchant domain and merchant app package name refers to the merchant this
+ // offer is applied to.
+ repeated string merchant_domain = 3;
+ repeated string merchant_app_package = 4;
+
+ // The expiry of this offer. Will be represented in the form of unix epoch
+ // time in seconds. Once the offer is expired it will not be shown in the
+ // client.
+ optional int64 offer_expiry_date = 5;
+
+ // Proto containing data specific to a card-linked offer.
+ message CardLinkedOfferData {
+ reserved 1, 2;
+
+ // The server id of the card to which the offer is linked.
+ repeated int64 instrument_id = 3;
+ }
+
+ // Proto containing data specific to a promo code offer.
+ message PromoCodeOfferData {
+ // The actual promo code which can be applied at checkout.
+ optional string promo_code = 1;
+ }
+
+ // The unique offer data for different offer types.
+ oneof type_specific_offer_data {
+ CardLinkedOfferData card_linked_offer_data = 6;
+ PromoCodeOfferData promo_code_offer_data = 9;
+ }
+
+ // Strings to be shown in client UI, based on the offer type and details.
+ message DisplayStrings {
+ // A message translated in the user's GPay app locale, explaining the value
+ // of the offer. For example, a promo code offer might display
+ // "$5 off on shoes, up to $50."
+ optional string value_prop_text = 1;
+
+ // A message translated in the user's GPay app locale and shown on mobile as
+ // a link, prompting the user to click it to learn more about the offer.
+ // Generally, "See details".
+ optional string see_details_text_mobile = 2;
+
+ // A message translated in the user's GPay app locale and shown on desktop
+ // (not as a link), informing the user that exclusions and restrictions may
+ // apply to the value prop text. Generally, "Terms apply."
+ optional string see_details_text_desktop = 3;
+
+ // A message translated in the user's GPay app locale and shown on mobile,
+ // instructing them on how to redeem the offer. For example, a promo code
+ // offer might display "Tap the promo code field at checkout to autofill
+ // it."
+ optional string usage_instructions_text_mobile = 4;
+
+ // A message translated in the user's GPay app locale and shown on desktop,
+ // instructing them on how to redeem the offer. For example, a promo code
+ // offer might display "Click the promo code field at checkout to autofill
+ // it."
+ optional string usage_instructions_text_desktop = 5;
+ }
+ optional DisplayStrings display_strings = 10;
+
+ // This value will be shown in the offer text template as "XXX% cashback".
+ // Percentage has a range of (0, 100].
+ message PercentageReward {
+ // The string contains a number and a percent sign.
+ optional string percentage = 1;
+ }
+
+ // This value will be shown in the offer text template as "XXX$ off".
+ message FixedAmountReward {
+ // The string contains a number and a currency sign.
+ optional string amount = 1;
+ }
+
+ // The reward type of the offer. Will be used to generate the display text in
+ // the UI. Each type has its own client side text template.
+ oneof reward_type {
+ PercentageReward percentage_reward = 7;
+ FixedAmountReward fixed_amount_reward = 8;
+ }
+}
diff --git a/pyhindsight/lib/components/sync/protocol/autofill_specifics.proto b/pyhindsight/lib/components/sync/protocol/autofill_specifics.proto
new file mode 100644
index 0000000..2b298f1
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/autofill_specifics.proto
@@ -0,0 +1,839 @@
+// 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 datatype extension for autofill.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+// Properties of autofill sync objects.
+
+// An AutofillProfile.
+message AutofillProfileSpecifics {
+ // Represents the validation status of value stored in the AutofillProfile.
+ enum VerificationStatus {
+ // No verification status assigned.
+ VERIFICATION_STATUS_UNSPECIFIED = 0;
+ // The value token was parsed from a parent token.
+ // For example, the first name was derived by splitting a full name into
+ // its components.
+ PARSED = 1;
+ // Value was built from its subcomponents.
+ // For example, the full name was built from the first, middle and last
+ // name.
+ FORMATTED = 2;
+ // The value was observed in a form transmission.
+ // For example, the user filled a form that contained at NAME_FULL field.
+ // The value of NAME_FULL will be stored as OBSERVED.
+ OBSERVED = 3;
+ // The user used the autofill settings to verify and store this token.
+ // This is currently only applicable to the full name, since users cannot
+ // edit individual components of their name.
+ USER_VERIFIED = 4;
+ // The token was parsed remotely.
+ SERVER_PARSED = 5;
+ }
+
+ optional string guid = 15;
+ // Starting from M115, Autofill ignores the origin and doesn't distinguish
+ // between verified (meaning `deprecated_origin == kSettingsOrigin`) and
+ // unverified profiles anymore. However, clients prior to this milestone only
+ // accept updates to verified profiles through Sync if the remote profile is
+ // verified as well. For this reason, M115 clients and above always set the
+ // origin to kSettingsOrigin.
+ // TODO(crbug.com/40266694): Remove in a few milestones.
+ optional string deprecated_origin = 16;
+ optional int64 use_count = 22;
+
+ // The time_t value of the last time this profile was used. This
+ // value makes sense wrt base::Time::To/FromTimeT, which measures
+ // from the Windows epoch.
+ optional int64 use_date = 23;
+
+ // A label intended to be chosen by the user. This was however never
+ // implemented and is currently unused.
+ optional string profile_label = 62;
+
+ // Contact info name fields.
+ repeated string name_first = 2;
+ repeated string name_middle = 3;
+ repeated string name_last = 4;
+
+ // A name_last consists of a prefix and a core (e.g., "van" and "Gogh" in
+ // "van Gogh"). Used for more granular name representation of last names
+ // with prefixes.
+ repeated string name_last_prefix = 99;
+ repeated string name_last_core = 100;
+
+ // Sometimes the last name is composed of two names as it is common for
+ // Hispanic/Latinx names. In the unstructured representation of the last name,
+ // there may be even a conjunction between the first and the second last
+ // name. For example, the more-complete version of Pablo Picasso's surname is
+ // "Ruiz y Picasso" containing a first last name, a conjunction (the y) and a
+ // second last name.
+ repeated string name_last_first = 27;
+ repeated string name_last_conjunction = 28;
+ repeated string name_last_second = 29;
+ repeated string name_full = 21;
+
+ reserved 60;
+ reserved "name_full_with_honorific";
+
+ // Contact info alternative name fields (e.g. phonetic names in Japan).
+ optional string alternative_full_name = 93;
+ optional string alternative_given_name = 94;
+ optional string alternative_family_name = 95;
+
+ // Validation status records for name fields.
+ reserved 30;
+ reserved "name_honorific_status";
+ repeated VerificationStatus name_first_status = 31;
+ repeated VerificationStatus name_middle_status = 32;
+ repeated VerificationStatus name_last_status = 33;
+ repeated VerificationStatus name_last_prefix_status = 101;
+ repeated VerificationStatus name_last_core_status = 102;
+ repeated VerificationStatus name_last_first_status = 34;
+ repeated VerificationStatus name_last_conjunction_status = 35;
+ repeated VerificationStatus name_last_second_status = 36;
+ repeated VerificationStatus name_full_status = 37;
+ reserved 61;
+ reserved "name_full_with_honorific_status";
+
+ // Validation status records for alternative name fields.
+ optional VerificationStatus alternative_full_name_status = 96;
+ optional VerificationStatus alternative_given_name_status = 97;
+ optional VerificationStatus alternative_family_name_status = 98;
+
+ // Contact info additional fields.
+ repeated string email_address = 5;
+ optional string company_name = 6;
+
+ // Address field.
+ // The address_home_line1/2 fields are deprecated and
+ // address_home_street_address should be used instead by
+ // joining address_home_line1/2 with a newline ("\n").
+ // Full deprecation can not be achieved before all sync profiles have been
+ // updated with a M86+ client.
+ // TODO(crbug.com/40142711): Remove usages of address_home_line1/2 and mark
+ // field as deprecated.
+ optional string address_home_line1 = 7;
+ optional string address_home_line2 = 8;
+ optional string address_home_city = 9;
+ optional string address_home_state = 10;
+ optional string address_home_zip = 11;
+ optional string address_home_country = 12;
+ optional string address_home_admin_level_2 = 71;
+
+ // Additional address fields for i18n.
+ optional string address_home_street_address = 17;
+ optional string address_home_sorting_code = 18;
+ optional string address_home_dependent_locality = 19;
+ optional string address_home_language_code = 20;
+ optional string address_home_thoroughfare_name = 38;
+ optional string address_home_thoroughfare_number = 39;
+ optional string address_home_street_location = 73;
+ optional string address_home_subpremise_name = 42;
+ // All the information related to the apartment. Normally a combination of the
+ // apartment type (address_home_apt_type) and number (address_home_apt_num).
+ // E.g. "Apt 5".
+ optional string address_home_apt = 85;
+ // The raw number (or identifier) of an apartment (e.g. "5") but without a
+ // prefix. The value "apt 5" would correspond to the address_home_apt.
+ optional string address_home_apt_num = 56;
+ // Information describing the type of apartment (e.g. Apt, Apartamento, Sala,
+ // Departamento).
+ optional string address_home_apt_type = 87;
+ optional string address_home_floor = 57;
+ optional string address_home_landmark = 67;
+ // The type indicates that the address is at the intersection between two
+ // streets. This is a common way of writing addresses in Mexico.
+ optional string address_home_between_streets = 69;
+ // The meaning of the field is similar to address_home_between_streets. The
+ // type should be used for "Entre calle 1" in MX addresses which also
+ // contain the "Entre calle 2" field.
+ optional string address_home_between_streets_1 = 77;
+ // The meaning of the field is similar to address_home_between_streets. The
+ // type should be used for "Entre calle 2" in MX addresses which also
+ // contain the "Entre calle 1" field.
+ optional string address_home_between_streets_2 = 79;
+ optional string address_home_overflow = 75;
+ // Combination of types address_home_between_streets or address_home_landmark.
+ // Note that some address forms require the combination of both in a single
+ // field as opposed to each one separately.
+ optional string address_home_between_streets_or_landmark = 81;
+ // Combination of types address_home_overflow and address_home_landmark.
+ // Note that some address forms require the combination of both in a single
+ // field as opposed to each one separately.
+ optional string address_home_overflow_and_landmark = 83;
+ // Combination of types address_home_street_location and
+ // address_home_dependent_locality. Note that some address forms require the
+ // combination of both in a single field as opposed to each one separately.
+ optional string address_home_street_location_and_locality = 89;
+ // Combination of types address_home_thoroughfare_number and
+ // address_home_apt. Note that some address forms require the combination of
+ // both in a single field as opposed to each one separately.
+ optional string address_home_thoroughfare_number_and_apt = 91;
+ // Sometimes address_home_zip consists of two parts.
+ // For example, address_home_zip = 12345-6789,
+ // prefix = 12345, suffix = 6789.
+ optional string address_home_zip_prefix = 103;
+ optional string address_home_zip_suffix = 104;
+
+ // Validation status records for address fields.
+ optional VerificationStatus address_home_city_status = 43;
+ optional VerificationStatus address_home_state_status = 44;
+ optional VerificationStatus address_home_zip_status = 45;
+ optional VerificationStatus address_home_country_status = 46;
+ optional VerificationStatus address_home_landmark_status = 68;
+ optional VerificationStatus address_home_between_streets_status = 70;
+ optional VerificationStatus address_home_between_streets_1_status = 78;
+ optional VerificationStatus address_home_between_streets_2_status = 80;
+ optional VerificationStatus address_home_admin_level_2_status = 72;
+ optional VerificationStatus address_home_overflow_status = 76;
+ optional VerificationStatus address_home_between_streets_or_landmark_status =
+ 82;
+ optional VerificationStatus address_home_overflow_and_landmark_status = 84;
+ optional VerificationStatus address_home_street_location_and_locality_status =
+ 90;
+ optional VerificationStatus address_home_thoroughfare_number_and_apt_status =
+ 92;
+ optional VerificationStatus address_home_street_address_status = 47;
+ optional VerificationStatus address_home_sorting_code_status = 48;
+ optional VerificationStatus address_home_dependent_locality_status = 49;
+ optional VerificationStatus address_home_language_code_status = 50;
+ optional VerificationStatus address_home_thoroughfare_name_status = 51;
+ optional VerificationStatus address_home_thoroughfare_number_status = 52;
+ optional VerificationStatus address_home_street_location_status = 74;
+ optional VerificationStatus address_home_subpremise_name_status = 55;
+ optional VerificationStatus address_home_apt_status = 86;
+ optional VerificationStatus address_home_apt_num_status = 58;
+ optional VerificationStatus address_home_apt_type_status = 88;
+ optional VerificationStatus address_home_floor_status = 59;
+ optional VerificationStatus address_home_zip_prefix_status = 105;
+ optional VerificationStatus address_home_zip_suffix_status = 106;
+
+ // Phone.
+ repeated string phone_home_whole_number = 13;
+
+ reserved 63;
+ reserved "disallow_settings_visible_updates";
+
+ // Removed in M123.
+ reserved 64;
+ reserved "birthdate_day";
+ reserved 65;
+ reserved "birthdate_month";
+ reserved 66;
+ reserved "birthdate_year";
+
+ // Deprecated.
+ optional string deprecated_label = 1 [deprecated = true];
+ optional string phone_fax_whole_number = 14 [deprecated = true];
+ // The following validity-related fields have only been used in combination
+ // with an experimental features that are disabled for all clients and have
+ // been removed in M100.
+ optional int64 validity_state_bitfield = 24 [deprecated = true];
+ optional bool is_client_validity_states_updated = 25 [deprecated = true];
+ // Removed in M118.
+ reserved 40;
+ reserved "address_home_dependent_thoroughfare_name";
+ reserved 41;
+ reserved "address_home_premise_name";
+ reserved 53;
+ reserved "address_home_dependent_thoroughfare_name_status";
+ reserved 54;
+ reserved "address_home_premise_name_status";
+ // Removed in M122.
+ reserved 26;
+ reserved "name_honorific";
+}
+
+message AutofillSpecifics {
+ // If any of these 3 fields are present, then all 3 should be, and it implies
+ // that this entity represents a classic autofill object. In this case,
+ // none of the autofill++ objects below should be present.
+ optional string name = 1;
+ optional string value = 2;
+ repeated int64 usage_timestamp = 3;
+
+ // An autofill++ profile object. If present, indicates this entity
+ // represents an AutofillProfile exclusively, and no other fields (such as
+ // name/value or credit_card) should be present.
+ optional AutofillProfileSpecifics profile = 4;
+
+ reserved 5;
+ reserved "encrypted_credit_card";
+ reserved 6;
+ reserved "credit_card";
+}
+
+// TODO(crbug.com/40105930): Deprecated, remove this once dependent change is
+// done. Use WalletCreditCardCloudTokenData instead.
+message CloudTokenData {
+ // Last 4-5 digits of the Cloud Primary Account Number (CPAN).
+ optional string suffix = 1;
+
+ // CPAN Month number 1-12.
+ optional int32 exp_month = 2;
+
+ // CPAN Four-digit year (e.g. 2017).
+ optional int32 exp_year = 3;
+
+ // URL of the card art to be displayed for CPAN.
+ optional string art_fife_url = 4;
+
+ // Opaque identifier for the cloud token associated with the payment
+ // instrument.
+ optional string instrument_token = 5;
+}
+
+// Next id: 8
+message CardBenefit {
+ // The unique identifier of the benefit. Generated originally in Chrome Sync
+ // server.
+ optional string benefit_id = 7;
+
+ // The benefit description (Engligh only currently) to be shown in the UI.
+ optional string benefit_description = 1;
+
+ // When the benefit should be displayed, in UTC time.
+ optional int64 start_time_unix_epoch_milliseconds = 2;
+ optional int64 end_time_unix_epoch_milliseconds = 3;
+
+ // Proto containing data specific to a flat rate benefit. Empty as flat rate
+ // benefits don't have unique fields. The actual benefit (e.g. "2% cash back")
+ // is already included in the `benefit_description`.
+ message FlatRateBenefit {}
+
+ // For category benefits, represents the category of purchases that the
+ // benefit can be applied to.
+ enum CategoryBenefitType {
+ CATEGORY_BENEFIT_TYPE_UNKNOWN = 0;
+ SUBSCRIPTION = 1;
+ FLIGHTS = 2;
+ DINING = 3;
+ ENTERTAINMENT = 4;
+ STREAMING = 5;
+ GROCERY_STORES = 6;
+ AIR_MILES_PARTNER = 7;
+ ALCOHOL_STORES = 8;
+ DRUGSTORES = 9;
+ OFFICE_SUPPLIES = 10;
+ RECURRING_BILLS = 11;
+ TRANSIT = 12;
+ TRAVEL = 13;
+ WHOLESALE_CLUBS = 14;
+ }
+
+ // Proto containing data specific to a category benefit.
+ message CategoryBenefit {
+ // The type of category purchases the benefit is eligible on.
+ optional CategoryBenefitType category_benefit_type = 1;
+ }
+
+ // Proto containing data specific to a merchant benefit.
+ message MerchantBenefit {
+ // The merchant domain that the benefit is eligible on.
+ // Example: https://www.acme.com
+ repeated string merchant_domain = 1;
+ }
+
+ // Proto data representing the actual data of the credit card benefit,
+ // depending on the benefit type.
+ oneof DomainSpecificBenefit {
+ FlatRateBenefit flat_rate_benefit = 4;
+ CategoryBenefit category_benefit = 5;
+ MerchantBenefit merchant_benefit = 6;
+ }
+}
+
+message CardIssuer {
+ enum Issuer {
+ ISSUER_UNKNOWN = 0;
+ // Card where the issuer is Google.
+ GOOGLE = 1;
+ // Card where the issuer is external.
+ EXTERNAL_ISSUER = 2;
+ }
+ optional Issuer issuer = 1;
+
+ // Uniquely identifies the issuer of the card. This field is required when
+ // Issuer is EXTERNAL_ISSUER.
+ // Example: capitalone, amex.
+ optional string issuer_id = 2;
+}
+
+message WalletMaskedCreditCard {
+ reserved 9, 14;
+ reserved "card_class";
+
+ enum WalletCardStatus {
+ VALID = 0;
+ EXPIRED = 1;
+ }
+
+ enum WalletCardType {
+ UNKNOWN = 0;
+ AMEX = 1;
+ DISCOVER = 2;
+ JCB = 3;
+ MAESTRO = 4;
+ MASTER_CARD = 5;
+ SOLO = 6;
+ SWITCH = 7;
+ VISA = 8;
+ UNIONPAY = 9;
+ ELO = 10;
+ VERVE = 11;
+ }
+
+ enum VirtualCardEnrollmentState {
+ UNSPECIFIED = 0;
+ UNENROLLED = 1 [deprecated = true];
+ ENROLLED = 2;
+ UNENROLLED_AND_NOT_ELIGIBLE = 3;
+ UNENROLLED_AND_ELIGIBLE = 4;
+ }
+
+ enum VirtualCardEnrollmentType {
+ TYPE_UNSPECIFIED = 0;
+ ISSUER = 1;
+ NETWORK = 2;
+ }
+
+ enum CardInfoRetrievalEnrollmentState {
+ RETRIEVAL_UNSPECIFIED = 0;
+ RETRIEVAL_ENROLLED = 1;
+ RETRIEVAL_UNENROLLED_AND_NOT_ELIGIBLE = 2;
+ RETRIEVAL_UNENROLLED_AND_ELIGIBLE = 3;
+ }
+
+ enum CardBenefitSource {
+ SOURCE_UNKNOWN = 0;
+ SOURCE_AMEX = 1;
+ SOURCE_BMO = 2;
+ SOURCE_CURINOS = 3;
+ }
+
+ enum CardCreationSource {
+ CREATION_SOURCE_UNSPECIFIED = 0;
+ CREATION_SOURCE_CHROME_PAYMENTS = 1;
+ CREATION_SOURCE_NON_CHROME_PAYMENTS = 2;
+ }
+
+ // Server-generated unique ID string. This is opaque to the client.
+ // This is the legacy version of `instrument_id`.
+ optional string id = 1;
+
+ // What the server thinks of this card.
+ optional WalletCardStatus status = 2;
+
+ optional string name_on_card = 3;
+
+ optional WalletCardType type = 4;
+
+ // Last 4 digits of the credit card number.
+ optional string last_four = 5;
+
+ // Month number 1-12.
+ optional int32 exp_month = 6;
+
+ // Four-digit year (e.g. 2017).
+ optional int32 exp_year = 7;
+
+ // The WalletPostalAddress.id of the billing address.
+ optional string billing_address_id = 8;
+
+ // Issuing Bank name which is internationalized (e.g. "Chase", "工商银行")
+ optional string bank_name = 10;
+
+ // TODO(crbug.com/40105930): Deprecated, remove this once dependent change is
+ // done.
+ // Use WalletCreditCardCloudTokenData instead. This field will be set if
+ // a cloud token is available for the instrument.
+ optional CloudTokenData cloud_token_data = 11;
+
+ // The card's nickname, if it exists.
+ optional string nickname = 12;
+
+ // Issuer of the card.
+ optional CardIssuer card_issuer = 13;
+
+ // Server-generated unique ID. This is opaque to the client.
+ // `id` is the legacy version of this.
+ optional int64 instrument_id = 15;
+
+ // The state of virtual card enrollment.
+ optional VirtualCardEnrollmentState virtual_card_enrollment_state = 16;
+
+ // The URL for the client to fetch the card art image.
+ optional string card_art_url = 17;
+
+ // The product description for the card. Used to be shown in the UI.
+ optional string product_description = 18;
+
+ // The type of virtual card enrollment. kTypeUnspecified indicates that the
+ // card is unenrolled.
+ optional VirtualCardEnrollmentType virtual_card_enrollment_type = 19;
+
+ // The benefits (e.g. points or discounts) associated with purchases made
+ // with the card.
+ repeated CardBenefit card_benefit = 20;
+
+ // Separate link from the card issuer which provides additional context or
+ // terms and conditions regarding the credit card product and its benefits.
+ optional string product_terms_url = 21;
+
+ // The state of enrollement for runtime card info retrieval. Enrollment in
+ // 'CardInfoRetrieval' will enable runtime retrieval of card information from
+ // card issuer including card number, expiry and CVC.
+ optional CardInfoRetrievalEnrollmentState
+ card_info_retrieval_enrollment_state = 22;
+
+ // The source of the card's benefits. eg: Curinos. Each card can only have one
+ // single benefit source, even if there are multiple benefits.
+ optional CardBenefitSource card_benefit_source = 23;
+
+ // The source of the card creation, indicating whether the card was added
+ // through a Chrome-related service, or through an external service (which
+ // includes Android Autofill).
+ optional CardCreationSource card_creation_source = 24;
+}
+
+// Unused by the client since M121.
+// TODO(crbug.com/40273491): Some server-side code still relies on this message.
+// To keep the protos in sync, it is kept until that code is cleaned up.
+// Different than an AutofillProfile because this represents some known address
+// on the server that is pulled down rather than synced between Chromes.
+message WalletPostalAddress {
+ optional string id = 1;
+
+ optional string recipient_name = 12;
+ optional string company_name = 2;
+
+ // This is the street address, of which there may be multiple lines. This
+ // corresponds to "address_home_line[1|2] in the AutofillProfileSpecifics
+ // message above. In some locales there may be more than two lines.
+ repeated string street_address = 3;
+
+ // Also known as "administrative area". This is normally the state or
+ // province in most countries.
+ optional string address_1 = 4;
+
+ // Also known as "locality". In the US this is the city.
+ optional string address_2 = 5;
+
+ // A sub-classification beneath the city, e.g. an inner-city district or
+ // suburb. Also known as "dependent_locality"
+ optional string address_3 = 6;
+
+ // Used in certain countries. Also known as "sub_dependent_locality".
+ optional string address_4 = 7;
+
+ optional string postal_code = 8;
+
+ // Similar to the zipcode column, but used for businesses or organizations
+ // that might not be geographically contiguous. The canonical example is
+ // CEDEX in France.
+ optional string sorting_code = 9;
+
+ optional string country_code = 10;
+ optional string language_code = 11;
+
+ // Phone number. The format is unspecified and will be explicitly ignored.
+ optional string phone_number = 13;
+}
+
+// Contains information about a Payments Customer.
+message PaymentsCustomerData {
+ // The billable customer ID associated with the account.
+ optional string id = 1;
+}
+
+// Contains information about the cloud token data of server credit cards.
+message WalletCreditCardCloudTokenData {
+ // Server-generated ID string for the card this cloud token data is related
+ // to. This should match the id in WalletMaskedCreditCard for to fetch the
+ // corresponding actual card data. Note this is not unique across all cloud
+ // token data, which means one card can have multiple sets of cloud token data
+ // with the same masked_card_id.
+ optional string masked_card_id = 1;
+
+ // Last 4-5 digits of the Cloud Primary Account Number (CPAN).
+ optional string suffix = 2;
+
+ // CPAN Month number 1-12.
+ optional int32 exp_month = 3;
+
+ // CPAN Four-digit year (e.g. 2017).
+ optional int32 exp_year = 4;
+
+ // URL of the card art to be displayed for CPAN.
+ optional string art_fife_url = 5;
+
+ // Opaque identifier for the cloud token.
+ optional string instrument_token = 6;
+}
+
+// Contains information of payment instruments that can be used by the user.
+message PaymentInstrument {
+ // Opaque identifier for the account stored in Payments Platform.
+ // This will be used to initiate the payment.
+ optional int64 instrument_id = 1;
+
+ // Supported payment infrastructures (rail) that allow users to send money
+ // between the payer and the payee. https://en.wikipedia.org/wiki/Payment_rail
+ enum SupportedRail {
+ SUPPORTED_RAIL_UNKNOWN = 0;
+ // Payment rails for Brazil Open Banking.
+ PIX = 1;
+ // International Bank Account Numbers.
+ IBAN = 2;
+ // This rail can be used for making payments to push payment targets
+ // represented as payment hyperlinks that are supported by the instrument
+ // issuer. The hyperlink will be specified in the href attribute within a
+ // tag in the DOM representing the payment page.
+ // More details on payment links can be found at
+ // https://github.com/aneeshali/paymentlink/blob/main/docs/explainer.md.
+ PAYMENT_HYPERLINK = 3;
+ // This rail is used for making payments via card numbers. Example use case:
+ // Credit/Debit cards, BuyNowPayLater (BNPL), eWallet Fronting cards etc.
+ CARD_NUMBER = 4;
+ }
+ // The supported rails for which a payment can be made for the given account.
+ // For example, Pix is the open-banking rail in Brazil, UPI is the
+ // open-banking rail in India.
+ repeated SupportedRail supported_rails = 2;
+
+ // The URL for the image to be displayed when showing the account to the
+ // user.
+ optional string display_icon_url = 3;
+
+ // Nickname for the instrument.
+ optional string nickname = 4;
+
+ // The backing source for the applicable rails.
+ oneof instrument_details {
+ BankAccountDetails bank_account = 5;
+ WalletMaskedIban iban = 6;
+ EwalletDetails ewallet_details = 7;
+ BnplIssuerDetails bnpl_issuer_details = 9;
+ }
+
+ optional DeviceDetails device_details = 8;
+
+ enum ActionRequired {
+ ACTION_REQUIRED_UNKNOWN = 0;
+ // The user needs to accept the relevant ToS to make the instrument usable.
+ ACCEPT_TOS = 1;
+ }
+
+ // The action to take to update the instrument.
+ repeated ActionRequired action_required = 10;
+}
+
+// Details for user's linked and unlinked Buy Now Pay Later issuers.
+message BnplIssuerDetails {
+ // Unique identifier for the BNPL partner. Example: 'affirm'.
+ optional string issuer_id = 1;
+ // Eligible price range that the BNPL issuer supports.
+ repeated EligiblePriceRange eligible_price_range = 2;
+}
+
+// Details for payment instruments that the user is eligible to create an
+// instrument with.
+message PaymentInstrumentCreationOption {
+ // Identifier for the payment instrument creation option.
+ optional string id = 1;
+
+ oneof creation_option {
+ BnplCreationOption buy_now_pay_later_option = 2;
+ }
+}
+
+// Buy Now Pay Later details that the user is eligible to create an instrument
+// from.
+message BnplCreationOption {
+ // Unique identifier for the BNPL partner. Example: 'affirm'.
+ optional string issuer_id = 1;
+ // Eligible price range that the BNPL issuer supports.
+ repeated EligiblePriceRange eligible_price_range = 2;
+}
+
+// Details the eligible price range that a BNPL issuer supports. Server
+// should set min and max price and ensure that they are both for the same
+// currency.
+message EligiblePriceRange {
+ // Currency of the price range. This field contains a three-letter currency
+ // code.
+ optional string currency = 1;
+ // Min and max eligible price in micros of currency, i.e. one millionths of
+ // the base unit (dollars, not cents for example). e.g. $1.05 == 1050000
+ // micros.
+ optional int64 min_price_in_micros = 2;
+ optional int64 max_price_in_micros = 3;
+}
+
+// Contains information of server IBAN (International Bank Account Number).
+message WalletMaskedIban {
+ // Opaque identifier for the account stored in Payments Platform.
+ optional string instrument_id = 1;
+
+ // Prefix of the full IBAN value, if available.
+ optional string prefix = 2;
+
+ // Suffix of the full IBAN value, if available.
+ optional string suffix = 3;
+
+ // Length of the full IBAN value, if available.
+ optional int32 length = 4;
+
+ // Nickname for the IBAN, if available.
+ optional string nickname = 5;
+}
+
+// Details of a bank account required to show it in the payment instrument
+// selector.
+message BankAccountDetails {
+ // The name of the bank where the user has an account.
+ optional string bank_name = 1;
+
+ // The last four digits of the account number to help the user identify their
+ // account.
+ optional string account_number_suffix = 2;
+
+ enum AccountType {
+ ACCOUNT_TYPE_UNSPECIFIED = 0;
+ CHECKING = 1;
+ SAVINGS = 2;
+ CURRENT = 3;
+ SALARY = 4;
+ TRANSACTING_ACCOUNT = 5;
+ }
+ // The type of bank account.
+ optional AccountType account_type = 3;
+}
+
+// Details of an eWallet account required to show it in the payment instrument
+// selector.
+message EwalletDetails {
+ // Name of the ewallet provider.
+ optional string ewallet_name = 1;
+
+ // Display name of the ewallet account.
+ optional string account_display_name = 2;
+
+ // Payment hyperlinks will be embedded in payment web pages. Chrome will match
+ // the payment link against the list of payment link URI regexes below. If
+ // there is a match, the payment flow will be initiated via the Payments
+ // Server. The regex matching approach makes it possible to launch new payment
+ // methods without requiring any client side changes. More details on payment
+ // links can be found at
+ // https://github.com/aneeshali/paymentlink/blob/main/docs/explainer.md.
+ repeated string supported_payment_link_uris = 3;
+}
+
+// This field captures all of the information related to the instrument-device
+// combo that is required for the payment flows.
+message DeviceDetails {
+ // Whether the device is enrolled in FIDO for this instrument. Depending on
+ // the FIDO state, the Chrome client will show a different UI for the
+ // user. For an unbound device, there will be some user-education content and
+ // the user will be asked to complete FIDO binding. For an already-bound
+ // device, the user will see a more simplified UI.
+ optional bool is_fido_enrolled = 1;
+}
+
+message AutofillWalletSpecifics {
+ enum WalletInfoType {
+ UNKNOWN = 0;
+ MASKED_CREDIT_CARD = 1;
+ // POSTAL_ADDRESS is unused by the client since M121.
+ POSTAL_ADDRESS = 2;
+ CUSTOMER_DATA = 3;
+ CREDIT_CARD_CLOUD_TOKEN_DATA = 4;
+ PAYMENT_INSTRUMENT = 5;
+ MASKED_IBAN = 6 [deprecated = true];
+ PAYMENT_INSTRUMENT_CREATION_OPTION = 7;
+ }
+
+ optional WalletInfoType type = 1;
+
+ // This field exists if and only if the "type" field equals to
+ // MASKED_CREDIT_CARD.
+ optional WalletMaskedCreditCard masked_card = 2;
+
+ // Unused by the client since M121.
+ // This field exists if and only if the `type` equals POSTAL_ADDRESS.
+ // TODO(crbug.com/40273491): Some server-side code still relies on this field.
+ // To keep the protos in sync, it is kept until that code is cleaned up.
+ optional WalletPostalAddress address = 3;
+
+ // This field exists if and only if the "type" field equals to CUSTOMER_DATA.
+ optional PaymentsCustomerData customer_data = 4;
+
+ // This field exists if and only if the "type" field equals to
+ // CREDIT_CARD_CLOUD_TOKEN_DATA.
+ optional WalletCreditCardCloudTokenData cloud_token_data = 5;
+
+ // This field exists if and only if the "type" field equals to
+ // PAYMENT_INSTRUMENT.
+ optional PaymentInstrument payment_instrument = 6;
+
+ // This field exists if and only if the `type` field equals to
+ // MASKED_IBAN.
+ optional WalletMaskedIban masked_iban = 7 [deprecated = true];
+
+ // This field exists if and only if the "type" field equals to
+ // PAYMENT_INSTRUMENT_CREATION_OPTION.
+ optional PaymentInstrumentCreationOption payment_instrument_creation_option =
+ 8;
+}
+
+// Wallet card usage information that can be synced.
+message WalletMetadataSpecifics {
+ enum Type {
+ UNKNOWN = 0;
+ CARD = 1;
+ // Unused by the client since M121.
+ // TODO(crbug.com/40273491): Some server-side code still relies on this.
+ // To keep the protos in sync, it is kept until that code is cleaned up.
+ ADDRESS = 2;
+ IBAN = 3;
+ }
+
+ // The type of the Wallet metadata.
+ optional Type type = 1;
+
+ // Base64 encoding of the unique ID string of the corresponding
+ // AutofillMetadata.
+ // For Wallet cards, this value is WalletMaskedCreditCard::id.
+ // For Wallet IBANs, this value is WalletMaskedIban::instrument_id.
+ optional string id = 2;
+
+ // The number of times that this Wallet card or address was used.
+ optional int64 use_count = 3;
+
+ // The last use date of this Wallet card or address. Measured in microseconds
+ // since the Windows epoch (1601).
+ optional int64 use_date = 4;
+
+ // The id of the profile/address that represents the billing address of this
+ // Wallet card.
+ optional string card_billing_address_id = 5;
+
+ // Unused by the client since M121.
+ // TODO(crbug.com/40273491): Some server-side code still relies on this field.
+ // To keep the protos in sync, it is kept until that code is cleaned up.
+ optional bool address_has_converted = 6;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/autofill_valuable_setting_specifics.proto b/pyhindsight/lib/components/sync/protocol/autofill_valuable_setting_specifics.proto
new file mode 100644
index 0000000..ae6a49b
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/autofill_valuable_setting_specifics.proto
@@ -0,0 +1,28 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+// Used to sync settings for `AUTOFILL_VALUABLE`. Since these settings originate
+// from the user's Wallet account settings, they are not reusing standard
+// syncable prefs.
+message AutofillValuableSettingSpecifics {
+ optional string name = 1;
+ // The value of the setting. Which variant is set depends on the setting.
+ oneof Value {
+ bool bool_value = 2;
+ string string_value = 3;
+ int64 int_value = 4;
+ }
+}
diff --git a/pyhindsight/lib/components/sync/protocol/autofill_valuable_specifics.proto b/pyhindsight/lib/components/sync/protocol/autofill_valuable_specifics.proto
new file mode 100644
index 0000000..1126227
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/autofill_valuable_specifics.proto
@@ -0,0 +1,121 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+// This is a copy of google.protobuf.Any.
+message Any {
+ // A URL/resource name that uniquely identifies the type of the serialized
+ // protocol buffer message.
+ optional string type_url = 1;
+
+ // Must be a valid serialized protocol buffer of the above specified type.
+ optional bytes value = 2;
+}
+
+// Represents a loyalty card from Google Wallet.
+message LoyaltyCard {
+ // The merchant name e.g. "Deutsche Bahn".
+ optional string merchant_name = 1;
+
+ // The program name e.g. "BahnBonus".
+ optional string program_name = 2;
+
+ // The logo URL.
+ optional string program_logo = 3;
+
+ // The loyalty card text code.
+ optional string loyalty_card_number = 4;
+
+ // Merchant domains associated to the loyalty card.
+ repeated string merchant_domains = 5;
+}
+
+// Represents a vehicle registration from Google Wallet.
+message VehicleRegistration {
+ // The vehicle make e.g. "Ford".
+ optional string vehicle_make = 1;
+
+ // The vehicle model e.g. "Fiesta".
+ optional string vehicle_model = 2;
+
+ // The year when model was first made e.g. "2018".
+ optional string vehicle_year = 3;
+
+ // The Vehicle Identification Number (VIN).
+ optional string vehicle_identification_number = 4;
+
+ // The license plate number.
+ optional string vehicle_license_plate = 5;
+
+ // The region that issued the license plate.
+ optional string license_plate_region = 6;
+
+ // The country that issued the license plate, normalized to ISO 3166-1
+ // alpha-2.
+ optional string license_plate_country = 7;
+
+ // The owner of the vehicle as it appears on their vehicle registration
+ // documents.
+ optional string owner_name = 8;
+}
+
+// Represents a flight reservation from Google Wallet.
+message FlightReservation {
+ // The flight number.
+ optional string flight_number = 1;
+
+ // The flight ticket number.
+ optional string flight_ticket_number = 2;
+
+ // The flight confirmation code (normally ~6 digits made of alphanumeric
+ // characters).
+ optional string flight_confirmation_code = 3;
+
+ // The passenger's full name.
+ optional string passenger_name = 4;
+
+ // The departure airport in IATA format e.g AMS for Amsterdam Schiphol.
+ optional string departure_airport = 5;
+
+ // The arrival airport in IATA format e.g LHR for London Heathrow.
+ optional string arrival_airport = 6;
+
+ // The departure date. This is a server-provided timestamp in microseconds.
+ optional int64 departure_date_unix_epoch_micros = 7;
+
+ // The arrival date. This is a server-provided timestamp with units in
+ // microseconds.
+ optional int64 arrival_date_unix_epoch_micros = 8;
+}
+
+// Valuables coming from Google Wallet.
+message AutofillValuableSpecifics {
+ // The valuable id.
+ optional string id = 1;
+
+ // True if the pass is editable by external clients.
+ optional bool is_editable = 6;
+
+ oneof valuable_data {
+ LoyaltyCard loyalty_card = 2;
+ VehicleRegistration vehicle_registration = 3;
+ FlightReservation flight_reservation = 5;
+ // add other valuable types here.
+ }
+
+ // Contains information that is used by Chrome and needs to be persisted
+ // across clients.
+ optional Any serialized_chrome_valuables_metadata = 4;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/autofill_wallet_credential_specifics.proto b/pyhindsight/lib/components/sync/protocol/autofill_wallet_credential_specifics.proto
new file mode 100644
index 0000000..d3dcd94
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/autofill_wallet_credential_specifics.proto
@@ -0,0 +1,27 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+// Autofill wallet data which stores the relevant card credential data.
+message AutofillWalletCredentialSpecifics {
+ // A server-generated unique ID for the instrument/card.
+ optional string instrument_id = 1;
+
+ // A 3 or 4 digit card verification code.
+ optional string cvc = 2;
+
+ // The timestamp of the last update. Used to determine data freshness.
+ optional int64 last_updated_time_unix_epoch_millis = 3;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/autofill_wallet_usage_specifics.proto b/pyhindsight/lib/components/sync/protocol/autofill_wallet_usage_specifics.proto
new file mode 100644
index 0000000..6d81241
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/autofill_wallet_usage_specifics.proto
@@ -0,0 +1,43 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+// Autofill usage data related objects which contains usage data of a payment
+// method related to a specific merchant.
+
+message AutofillWalletUsageSpecifics {
+ // A unique ID identifying this item. Used as the client tag.
+ optional string guid = 1;
+
+ // The type of usage data this entity is associated with.
+ oneof usage_data_type {
+ VirtualCardUsageData virtual_card_usage_data = 2;
+ }
+
+ message VirtualCardUsageData {
+ // The instrument id of the actual card that the virtual card is related to.
+ optional int64 instrument_id = 1;
+
+ // The last four of the virtual card number. This is tied to the usage
+ // data because the virtual card number may vary depending on merchants.
+ optional string virtual_card_last_four = 2;
+
+ // The url of the merchant where the virtual card is used.
+ optional string merchant_url = 3;
+
+ // The merchant the usage data is related to on the Android platform.
+ optional string merchant_app_package = 4;
+ }
+}
diff --git a/pyhindsight/lib/components/sync/protocol/bookmark_model_metadata.proto b/pyhindsight/lib/components/sync/protocol/bookmark_model_metadata.proto
new file mode 100644
index 0000000..524b00c
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/bookmark_model_metadata.proto
@@ -0,0 +1,79 @@
+// Copyright 2018 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+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/data_type_state.proto";
+import "components/sync/protocol/entity_metadata.proto";
+
+// Corresponds to a single bookmark id/metadata pair.
+message BookmarkMetadata {
+ // Bookmark local id.
+ optional int64 id = 1;
+
+ // Bookmarks sync metadata.
+ optional EntityMetadata metadata = 2;
+}
+
+// Sync proto to carry the sync metadata for the bookmarks model. It is used for
+// persisting and loading sync metadata from disk.
+message BookmarkModelMetadata {
+ // Bookmark global metadata.
+ optional DataTypeState data_type_state = 1;
+
+ // A set of all bookmarks metadata.
+ repeated BookmarkMetadata bookmarks_metadata = 2;
+
+ reserved 3;
+
+ reserved 4;
+
+ reserved 5;
+
+ // Indicates whether the reupload of bookmarks has been triggered such that
+ // they include fields like `type`, `unique_position` and `parent_guid`, which
+ // means that their sequence number has been increased (independently of
+ // whether the commit has succeeded or even started).
+ // TODO(crbug.com/40780588): remove this code when most of bookmarks are
+ // reuploaded.
+ optional bool bookmarks_hierarchy_fields_reuploaded = 6;
+
+ // Number of remote updates that were ignored because the parent folder could
+ // not be determined since sync (bookmark sync) started (since initial sync,
+ // including initial sync itself). Note that this excludes updates
+ // representing changes (moves) to existing/tracked bookmarks (i.e. the parent
+ // folder used to be known, but the new one specified in the update isn't).
+ //
+ // Only a minority of users should have a non-zero value, due to a) corrupt
+ // data, reasons unknown; or b) permanent folders that were unsupported at the
+ // time the update was received (either for the permanent folder itself or for
+ // descendants). The absence of this field should be interpreted as 'unknown',
+ // which roughly means the counter wasn't supported by the browser -M77 or
+ // below- at the time sync was enabled (it also means, it will remain
+ // 'unknown' until initial sync is exercised, e.g. sync disabled and
+ // reenabled).
+ optional int64 num_ignored_updates_due_to_missing_parent = 7;
+
+ // See field above. Among such ignored updates, this field tracks which was
+ // the highest server version. This may be useful -in the future- to get a
+ // sense of "time" (or, since versions are opaque to the client, at least a
+ // notion of ordering with respect to other updates). The absence of this
+ // field should be interpreted as 'unknown' and does not distinguish the
+ // case between a) no updates ignored; and b) field wasn't supported at the
+ // time the last update was ignored. To distinguish between these two, the
+ // field above can be used.
+ optional int64 max_version_among_ignored_updates_due_to_missing_parent = 8;
+
+ // Indicates whether the count of remote updates during the latest initial
+ // merge exceeded the bookmark limit. This field is mutually exclusive to all
+ // the other fields and is managed completely by the processor.
+ optional bool last_initial_merge_remote_updates_exceeded_limit = 9;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/bookmark_specifics.proto b/pyhindsight/lib/components/sync/protocol/bookmark_specifics.proto
new file mode 100644
index 0000000..07df6a5
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/bookmark_specifics.proto
@@ -0,0 +1,95 @@
+// 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 datatype extension for bookmarks.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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/unique_position.proto";
+
+// Corresponds to a single meta info key/value pair for a bookmark node.
+message MetaInfo {
+ optional string key = 1;
+ optional string value = 2;
+}
+
+// Properties of bookmark sync objects.
+message BookmarkSpecifics {
+ // URL of the bookmarked page (unset for folders).
+ optional string url = 1;
+ // PNG-encoded content of the favicon image (in practice 16x16, as determined
+ // by `kFaviconSize`). Empty if the bookmark has no favicon (which includes
+ // bookmark folders).
+ optional bytes favicon = 2;
+ // Contains legacy title which is truncated and may contain escaped symbols.
+ optional string legacy_canonicalized_title = 3;
+ // Corresponds to BookmarkNode::date_added() represented as microseconds since
+ // the Windows epoch.
+ optional int64 creation_time_us = 4;
+ // The URL of the favicon image encoded in field `favicon`. Note that there
+ // are various cases where this URL may be missing (field unset or empty) even
+ // if the `favicon` field (image content) is populated:
+ // 1. WebUI pages such as "chrome://bookmarks/" are missing a favicon URL but
+ // they have a favicon.
+ // 2. Data generated by ancient clients (prior to M25) may not contain the
+ // favicon URL.
+ // 3. If the favicon URL is too large (determined by `kMaxFaviconUrlSize`) it
+ // may be omitted by clients to avoid running into the max-entity-size
+ // limit. Most notably, this includes URLs prefixed with the data: scheme
+ // that may encode the image content itself in the URL.
+ optional string icon_url = 5;
+ repeated MetaInfo meta_info = 6;
+ reserved 7;
+ reserved 8;
+ reserved 9;
+ // Introduced in M81, it represents a globally unique and immutable ID.
+ //
+ // If present, it must be the same as originator_client_item_id in lowercase,
+ // unless originator client item ID is not a valid GUID. In such cases (which
+ // is the case for bookmarks created before 2015), this GUID must match the
+ // value inferred from the combination of originator cache GUID and
+ // originator client item ID, see InferGuidForLegacyBookmark().
+ //
+ // If not present, the value can be safely inferred using the very same
+ // methods listed above.
+ optional string guid = 10;
+ // Contains full title as is. `legacy_canonicalized_title` is a prefix of
+ // `full_title` with escaped symbols.
+ optional string full_title = 11;
+ reserved 12;
+ reserved 13;
+ // Introduced in M94, represents the GUID (field `guid`) of the parent.
+ optional string parent_guid = 14;
+
+ // Introduced in M94, determines whether this entity represents a bookmark
+ // folder. This field is redundant to the similar field in SyncEntity. If this
+ // field in specifics is set, it takes precedence over the one in SyncEntity.
+ enum Type {
+ // `UNSPECIFIED` is relevant only for the case where the field is not set.
+ // M94 and above should not use this value.
+ UNSPECIFIED = 0;
+ URL = 1;
+ FOLDER = 2;
+ }
+ optional Type type = 15;
+
+ // Introduced in M94, determines ordering among siblings. This field is
+ // redundant to the similar field in SyncEntity. If this field in specifics is
+ // set, it takes precedence over the one in SyncEntity.
+ optional UniquePosition unique_position = 16;
+
+ // Introduced in M106, corresponds to BookmarkNode::date_last_used()
+ // represented as microseconds since the Windows epoch.
+ optional int64 last_used_time_us = 17;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/client_commands.proto b/pyhindsight/lib/components/sync/protocol/client_commands.proto
new file mode 100644
index 0000000..f685619
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/client_commands.proto
@@ -0,0 +1,55 @@
+// 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}.
+
+syntax = "proto2";
+
+option java_multiple_files = true;
+option java_package = "org.chromium.components.sync.protocol";
+
+option optimize_for = LITE_RUNTIME;
+
+package sync_pb;
+
+message CustomNudgeDelay {
+ optional int32 datatype_id = 1; // Datatype id.
+ optional int32 delay_ms = 2; // Delay in milliseconds.
+}
+
+message ClientCommand {
+ // Time to wait before sending any requests to the server.
+ optional int32 set_sync_poll_interval = 1; // in seconds
+ // This has been deprecated since M75.
+ optional int32 set_sync_long_poll_interval = 2 [deprecated = true];
+
+ optional int32 max_commit_batch_size = 3;
+
+ // Number of seconds to delay before the throttled client should retry.
+ optional int32 throttle_delay_seconds = 5;
+
+ // This has been deprecated since M109.
+ optional int32 client_invalidation_hint_buffer_size = 6 [deprecated = true];
+
+ // A dictionary of custom nudge delays.
+ repeated CustomNudgeDelay custom_nudge_delays = 8;
+
+ // Configuration for commit quota of extension-related data types.
+ // The maximum count of tokens (=initial at browser startup) and the
+ // interval for refilling one more token if not at maximum.
+ optional int32 extension_types_max_tokens = 9;
+ optional int32 extension_types_refill_interval_seconds = 10;
+
+ // Extended nudge delay for data types with depleted quota.
+ optional int32 extension_types_depleted_quota_nudge_delay_seconds = 11;
+
+ reserved 4;
+ reserved "sessions_commit_delay_seconds";
+
+ reserved 7;
+ reserved "gu_retry_delay_seconds";
+}
diff --git a/pyhindsight/lib/components/sync/protocol/client_debug_info.proto b/pyhindsight/lib/components/sync/protocol/client_debug_info.proto
new file mode 100644
index 0000000..8f4cb43
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/client_debug_info.proto
@@ -0,0 +1,92 @@
+// 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 debug info clients can send to the sync server.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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/get_updates_caller_info.proto";
+import "components/sync/protocol/sync_enums.proto";
+
+// Per-type hint information.
+message TypeHint {
+ // The data type this hint applied to.
+ optional int32 data_type_id = 1;
+
+ // Whether or not a valid hint is provided.
+ optional bool has_valid_hint = 2;
+}
+
+// The additional info here is from the StatusController. They get sent when
+// the event SYNC_CYCLE_COMPLETED is sent.
+message SyncCycleCompletedEventInfo {
+ reserved 1;
+ reserved "syncer_stuck";
+ reserved 2;
+ reserved "num_blocking_conflicts";
+ reserved 3;
+ reserved "num_non_blocking_conflicts";
+
+ // These new conflict counters replace the ones above.
+ // TODO(crbug.com/40833583): Deprecated in M103.
+ optional int32 num_encryption_conflicts = 4 [deprecated = true];
+ optional int32 num_hierarchy_conflicts = 5 [deprecated = true];
+ optional int32 num_simple_conflicts = 6; // No longer sent since M24.
+ optional int32 num_server_conflicts = 7;
+
+ // Counts to track the effective usefulness of our GetUpdate requests.
+ optional int32 num_updates_downloaded = 8;
+ // TODO(crbug.com/40833583): Deprecated in M103.
+ optional int32 num_reflected_updates_downloaded = 9 [deprecated = true];
+
+ // `caller_info` was mostly replaced by `get_updates_origin`; now it only
+ // contains the `notifications_enabled` flag.
+ optional GetUpdatesCallerInfo caller_info = 10;
+
+ // Deprecated in M67.
+ reserved 11;
+ reserved "source_info";
+
+ optional SyncEnums.GetUpdatesOrigin get_updates_origin = 12;
+}
+
+message DebugEventInfo {
+ // Each of the following fields correspond to different kinds of events. as
+ // a result, only one is set during any single DebugEventInfo.
+ // A singleton event. See enum definition.
+ optional SyncEnums.SingletonDebugEventType singleton_event = 1;
+ // A sync cycle completed.
+ optional SyncCycleCompletedEventInfo sync_cycle_completed_event_info = 2;
+ // A datatype triggered a nudge.
+ optional int32 nudging_datatype = 3;
+ // A notification triggered a nudge.
+ repeated int32 datatypes_notified_from_server = 4;
+
+ reserved "datatype_association_stats";
+ reserved 5;
+}
+
+message DebugInfo {
+ repeated DebugEventInfo events = 1;
+
+ // Whether cryptographer is ready to encrypt and decrypt data.
+ optional bool cryptographer_ready = 2;
+
+ // Cryptographer has pending keys which indicates the correct passphrase
+ // has not been provided yet.
+ optional bool cryptographer_has_pending_keys = 3;
+
+ // Indicates client has dropped some events to save bandwidth.
+ optional bool events_dropped = 4;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/collaboration_group_metadata.proto b/pyhindsight/lib/components/sync/protocol/collaboration_group_metadata.proto
new file mode 100644
index 0000000..3734095
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/collaboration_group_metadata.proto
@@ -0,0 +1,23 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+
+option java_multiple_files = true;
+option java_package = "org.chromium.components.sync.protocol";
+
+option optimize_for = LITE_RUNTIME;
+
+package sync_pb;
+
+// This proto contains metadata about the specific collaboration. Each
+// CollaborationGroupMetadata should be mapped to a specific CollaborationGroup,
+// though the mapping happens outside of Chrome Sync.
+message CollaborationGroupMetadata {
+ // The current version of a collaboration group. This is used for ensuring
+ // that old and new clients can enable or disable functionality based on:
+ // (1) The value of this field.
+ // (2) What that specific version of Chrome supports.
+ optional int64 version = 1;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/collaboration_group_specifics.proto b/pyhindsight/lib/components/sync/protocol/collaboration_group_specifics.proto
new file mode 100644
index 0000000..3bbf035
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/collaboration_group_specifics.proto
@@ -0,0 +1,30 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+// Special sync datatype to notify client about People Group changes.
+message CollaborationGroupSpecifics {
+ // Unique identifier for a collaboration group, also known as `group_id` or
+ // `group_name`.
+ optional string collaboration_id = 1;
+
+ // Indicates staleness of the collaboration group, used to determine whether
+ // client should refresh cached group. Server-side derived from group event
+ // `changed_at`.
+ optional int64 changed_at_timestamp_millis_since_unix_epoch = 2;
+
+ // An opaque token, that is used to optimize ReadGroup(s) RPCs.
+ optional string consistency_token = 3;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/collaboration_metadata.cc b/pyhindsight/lib/components/sync/protocol/collaboration_metadata.cc
new file mode 100644
index 0000000..9a3979b
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/collaboration_metadata.cc
@@ -0,0 +1,111 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/sync/protocol/collaboration_metadata.h"
+
+#include
+#include
+#include
+
+#include "base/trace_event/memory_usage_estimator.h"
+#include "components/sync/protocol/entity_metadata.pb.h"
+#include "components/sync/protocol/sync_entity.pb.h"
+#include "google_apis/gaia/gaia_id.h"
+
+namespace syncer {
+
+CollaborationMetadata::CollaborationMetadata(
+ const CollaborationMetadata& other) = default;
+CollaborationMetadata& CollaborationMetadata::operator=(
+ const CollaborationMetadata& other) = default;
+CollaborationMetadata::CollaborationMetadata(CollaborationMetadata&& other) =
+ default;
+CollaborationMetadata& CollaborationMetadata::operator=(
+ CollaborationMetadata&& other) = default;
+CollaborationMetadata::~CollaborationMetadata() = default;
+
+// static
+CollaborationMetadata CollaborationMetadata::FromRemoteProto(
+ const sync_pb::SyncEntity::CollaborationMetadata& remote_proto) {
+ return CollaborationMetadata(
+ /*created_by=*/GaiaId(
+ remote_proto.creation_attribution().obfuscated_gaia_id()),
+ /*last_updated_by=*/
+ GaiaId(remote_proto.last_update_attribution().obfuscated_gaia_id()),
+ CollaborationId(remote_proto.collaboration_id()));
+}
+
+// static
+CollaborationMetadata CollaborationMetadata::FromLocalProto(
+ const sync_pb::EntityMetadata::CollaborationMetadata& local_proto) {
+ return CollaborationMetadata(
+ /*created_by=*/GaiaId(
+ local_proto.creation_attribution().obfuscated_gaia_id()),
+ /*last_updated_by=*/
+ GaiaId(local_proto.last_update_attribution().obfuscated_gaia_id()),
+ CollaborationId(local_proto.collaboration_id()));
+}
+
+// static
+CollaborationMetadata CollaborationMetadata::ForLocalChange(
+ const GaiaId& changed_by,
+ const CollaborationId& collaboration_id) {
+ return CollaborationMetadata(
+ /*created_by=*/changed_by,
+ /*last_updated_by=*/changed_by, collaboration_id);
+}
+
+sync_pb::SyncEntity::CollaborationMetadata
+CollaborationMetadata::ToRemoteProto() const {
+ sync_pb::SyncEntity::CollaborationMetadata remote_proto;
+ if (!created_by_.empty()) {
+ remote_proto.mutable_creation_attribution()->set_obfuscated_gaia_id(
+ created_by_.ToString());
+ }
+ if (!last_updated_by_.empty()) {
+ remote_proto.mutable_last_update_attribution()->set_obfuscated_gaia_id(
+ last_updated_by_.ToString());
+ }
+ remote_proto.set_collaboration_id(collaboration_id_.value());
+ return remote_proto;
+}
+
+sync_pb::EntityMetadata::CollaborationMetadata
+CollaborationMetadata::ToLocalProto() const {
+ sync_pb::EntityMetadata::CollaborationMetadata local_proto;
+ if (!created_by_.empty()) {
+ local_proto.mutable_creation_attribution()->set_obfuscated_gaia_id(
+ created_by_.ToString());
+ }
+ if (!last_updated_by_.empty()) {
+ local_proto.mutable_last_update_attribution()->set_obfuscated_gaia_id(
+ last_updated_by_.ToString());
+ }
+ local_proto.set_collaboration_id(collaboration_id_.value());
+ return local_proto;
+}
+
+size_t CollaborationMetadata::EstimateMemoryUsage() const {
+ using base::trace_event::EstimateMemoryUsage;
+ return EstimateMemoryUsage(created_by_.ToString()) +
+ EstimateMemoryUsage(last_updated_by_.ToString()) +
+ EstimateMemoryUsage(collaboration_id_.value());
+}
+
+CollaborationMetadata::CollaborationMetadata(GaiaId created_by,
+ GaiaId last_updated_by,
+ CollaborationId collaboration_id)
+ : created_by_(std::move(created_by)),
+ last_updated_by_(std::move(last_updated_by)),
+ collaboration_id_(std::move(collaboration_id)) {}
+
+void PrintTo(const CollaborationMetadata& collaboration_metadata,
+ std::ostream* os) {
+ *os << "{ collaboration_id: '"
+ << collaboration_metadata.collaboration_id().value() << "', created_by: '"
+ << collaboration_metadata.created_by() << "', last_updated_by: '"
+ << collaboration_metadata.last_updated_by() << "'}";
+}
+
+} // namespace syncer
diff --git a/pyhindsight/lib/components/sync/protocol/collaboration_metadata.h b/pyhindsight/lib/components/sync/protocol/collaboration_metadata.h
new file mode 100644
index 0000000..f34908e
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/collaboration_metadata.h
@@ -0,0 +1,69 @@
+// Copyright 2024 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_PROTOCOL_COLLABORATION_METADATA_H_
+#define COMPONENTS_SYNC_PROTOCOL_COLLABORATION_METADATA_H_
+
+#include
+#include
+
+#include "components/sync/base/collaboration_id.h"
+#include "components/sync/protocol/entity_metadata.pb.h"
+#include "components/sync/protocol/sync_entity.pb.h"
+#include "google_apis/gaia/gaia_id.h"
+
+namespace syncer {
+
+// Metadata associated with a shared Sync entity.
+class CollaborationMetadata {
+ public:
+ CollaborationMetadata(const CollaborationMetadata& other);
+ CollaborationMetadata& operator=(const CollaborationMetadata& other);
+ CollaborationMetadata(CollaborationMetadata&& other);
+ CollaborationMetadata& operator=(CollaborationMetadata&& other);
+ ~CollaborationMetadata();
+
+ static CollaborationMetadata FromRemoteProto(
+ const sync_pb::SyncEntity::CollaborationMetadata& remote_metadata);
+ static CollaborationMetadata FromLocalProto(
+ const sync_pb::EntityMetadata::CollaborationMetadata& local_metadata);
+
+ // Creates a CollaborationMetadata for a local change (either creation or
+ // update). For a new entity, `changed_by` will be used for both `created_by`
+ // and `last_updated_by`.
+ static CollaborationMetadata ForLocalChange(
+ const GaiaId& changed_by,
+ const CollaborationId& collaboration_id);
+
+ // The account that created the entity (may be empty).
+ const GaiaId& created_by() const { return created_by_; }
+
+ // The account that last updated the entity (may be empty).
+ const GaiaId& last_updated_by() const { return last_updated_by_; }
+
+ // The collaboration ID of the entity.
+ const CollaborationId& collaboration_id() const { return collaboration_id_; }
+
+ sync_pb::SyncEntity::CollaborationMetadata ToRemoteProto() const;
+ sync_pb::EntityMetadata::CollaborationMetadata ToLocalProto() const;
+
+ size_t EstimateMemoryUsage() const;
+
+ private:
+ CollaborationMetadata(GaiaId created_by,
+ GaiaId last_updated_by,
+ CollaborationId collaboration_id);
+
+ GaiaId created_by_;
+ GaiaId last_updated_by_;
+ CollaborationId collaboration_id_;
+};
+
+// gMock printer helper.
+void PrintTo(const CollaborationMetadata& collaboration_metadata,
+ std::ostream* os);
+
+} // namespace syncer
+
+#endif // COMPONENTS_SYNC_PROTOCOL_COLLABORATION_METADATA_H_
diff --git a/pyhindsight/lib/components/sync/protocol/collaboration_metadata_unittest.cc b/pyhindsight/lib/components/sync/protocol/collaboration_metadata_unittest.cc
new file mode 100644
index 0000000..b2f9d39
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/collaboration_metadata_unittest.cc
@@ -0,0 +1,68 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/sync/protocol/collaboration_metadata.h"
+
+#include "base/test/protobuf_matchers.h"
+#include "components/sync/protocol/entity_metadata.pb.h"
+
+namespace syncer {
+namespace {
+
+using base::test::EqualsProto;
+
+constexpr char kCollaborationId[] = "collaboration";
+constexpr char kCreatorId[] = "creator_id";
+constexpr char kUpdaterId[] = "updater_id";
+
+TEST(CollaborationMetadataTest, SerializeAndDeserializeLocalProto) {
+ sync_pb::EntityMetadata::CollaborationMetadata local_proto;
+ local_proto.set_collaboration_id(kCollaborationId);
+ local_proto.mutable_creation_attribution()->set_obfuscated_gaia_id(
+ kCreatorId);
+ local_proto.mutable_last_update_attribution()->set_obfuscated_gaia_id(
+ kUpdaterId);
+ EXPECT_THAT(CollaborationMetadata::FromLocalProto(local_proto).ToLocalProto(),
+ EqualsProto(local_proto));
+}
+
+TEST(CollaborationMetadataTest, SerializeAndDeserializeRemoteProto) {
+ sync_pb::SyncEntity::CollaborationMetadata remote_proto;
+ remote_proto.set_collaboration_id(kCollaborationId);
+ remote_proto.mutable_creation_attribution()->set_obfuscated_gaia_id(
+ kCreatorId);
+ remote_proto.mutable_last_update_attribution()->set_obfuscated_gaia_id(
+ kUpdaterId);
+ EXPECT_THAT(
+ CollaborationMetadata::FromRemoteProto(remote_proto).ToRemoteProto(),
+ EqualsProto(remote_proto));
+}
+
+TEST(CollaborationMetadataTest, SerializeLocalChangeToProtos) {
+ // Creator and updater are the same for the local change.
+ sync_pb::EntityMetadata::CollaborationMetadata expected_local_proto;
+ expected_local_proto.set_collaboration_id(kCollaborationId);
+ expected_local_proto.mutable_creation_attribution()->set_obfuscated_gaia_id(
+ kCreatorId);
+ expected_local_proto.mutable_last_update_attribution()
+ ->set_obfuscated_gaia_id(kCreatorId);
+
+ sync_pb::SyncEntity::CollaborationMetadata expected_remote_proto;
+ expected_remote_proto.set_collaboration_id(kCollaborationId);
+ expected_remote_proto.mutable_creation_attribution()->set_obfuscated_gaia_id(
+ kCreatorId);
+ expected_remote_proto.mutable_last_update_attribution()
+ ->set_obfuscated_gaia_id(kCreatorId);
+
+ CollaborationMetadata collaboration_metadata =
+ CollaborationMetadata::ForLocalChange(GaiaId(kCreatorId),
+ CollaborationId(kCollaborationId));
+ EXPECT_THAT(collaboration_metadata.ToLocalProto(),
+ EqualsProto(expected_local_proto));
+ EXPECT_THAT(collaboration_metadata.ToRemoteProto(),
+ EqualsProto(expected_remote_proto));
+}
+
+} // namespace
+} // namespace syncer
diff --git a/pyhindsight/lib/components/sync/protocol/contact_info_specifics.proto b/pyhindsight/lib/components/sync/protocol/contact_info_specifics.proto
new file mode 100644
index 0000000..153db0d
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/contact_info_specifics.proto
@@ -0,0 +1,258 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+message ContactInfoSpecifics {
+ // Used to distinguish whether the address is the dedicated Home or Work
+ // address of the user's account.
+ // This translates into `AutofillProfile::RecordType::kAccount*`.
+ enum AddressType {
+ REGULAR = 0;
+ HOME = 1;
+ WORK = 2;
+ }
+
+ // Represents the validation status of a stored value.
+ enum VerificationStatus {
+ // No verification status assigned.
+ VERIFICATION_STATUS_UNSPECIFIED = 0;
+ // The value token was parsed from a parent token.
+ // For example, the first name was derived by splitting a full name into
+ // its components.
+ PARSED = 1;
+ // Value was built from its subcomponents.
+ // For example, the full name was built from the first, middle and last
+ // name.
+ FORMATTED = 2;
+ // The value was observed in a form transmission.
+ // For example, the user filled a form that contained at NAME_FULL field.
+ // The value of NAME_FULL will be stored as OBSERVED.
+ OBSERVED = 3;
+ // The user used the settings UI to verify and store this token.
+ // This is currently only applicable to the full name, since users cannot
+ // edit individual components of their name.
+ USER_VERIFIED = 4;
+ // The token was parsed remotely.
+ SERVER_PARSED = 5;
+ }
+
+ message Observation {
+ // An `autofill::ProfileTokenQuality::ObservationType`. Represented as a
+ // uint32 to retain future enum values (since this is proto2).
+ // The `ObservationType`'s underlying type is uint8_t, but this is not
+ // supported by protos. Since the uint32 Proto type uses variable-length
+ // encoding, uint32 has a similar size as a single element byte[].
+ optional uint32 type = 1;
+ // The `autofill::ProfileTokenQuality::FormSignatureHash` has type uint8_t.
+ // Like for `type`, this should have the (non-existing) data type uint8.
+ optional uint32 form_hash = 2;
+ }
+
+ // Metadata that is attached to every token type.
+ message TokenMetadata {
+ optional VerificationStatus status = 1;
+ repeated Observation observations = 2;
+ // Stores a hash of the token value that this metadata is associated with.
+ // This is used by Autofill to detect changes of the token value by external
+ // integrators.
+ optional uint32 value_hash = 3;
+ }
+
+ // A token with a string interpretation of the value.
+ message StringToken {
+ optional string value = 1;
+ optional TokenMetadata metadata = 2;
+ }
+
+ // A globally unique, immutable UUID represented in lowercase.
+ optional string guid = 1;
+ reserved 2;
+ reserved "source";
+ optional AddressType address_type = 56 [default = REGULAR];
+
+ // The number of time this profile has been used.
+ optional int64 use_count = 3;
+
+ // The last times this profile was used. use_date.. is the last use date of
+ // the profile, use_date2.. the second last use date, etc. If a profile hasn't
+ // been used at least that many times, the field is unset.
+ optional int64 use_date_unix_epoch_seconds = 4;
+ optional int64 use_date2_unix_epoch_seconds = 54;
+ optional int64 use_date3_unix_epoch_seconds = 55;
+
+ // The last time the profile was modified.
+ optional int64 date_modified_unix_epoch_seconds = 37;
+
+ // The BCP 47 language code used to format the address for display.
+ optional string language_code = 38;
+
+ // A label intended to be chosen by the user. This was however never
+ // implemented and is currently unused.
+ optional string profile_label = 5;
+
+ // Tracks the application that initially created the profile. The integer
+ // represents a value in the server-side enum `BillableService`. A value of
+ // 70073 represents Chrome (enum value BILLABLE_SERVICE_CHROME_PAYMENTS).
+ optional int32 initial_creator_id = 39;
+ // Tracks the application that applied the last modification to the
+ // non-metadata content of the profile. It represents a value in the same
+ // `BillableService` enum.
+ // All StringTokens, and the `profile_label` are considered non-metadata.
+ optional int32 last_modifier_id = 40;
+
+ // Used to hide account addresses in Chrome.
+ // Chrome will set this value to true if the address should be filtered out
+ // on the server side and not passed to Chrome again.
+ // If Chrome set this value to false or if the value is not set, the address
+ // will be passed to Chrome.
+ optional bool invisible_in_autofill = 62;
+
+ // Contact info name fields.
+ optional StringToken name_first = 7;
+ optional StringToken name_middle = 8;
+ optional StringToken name_last = 9;
+
+ // Prefix of the last name, e.g., "von" in "von Neumann".
+ optional StringToken name_last_prefix = 60;
+
+ // Core of the last name, excluding prefixes.
+ optional StringToken name_last_core = 61;
+
+ // Sometimes the last name is composed of two names as it is common for
+ // Hispanic/Latinx names. In the unstructured representation of the last name,
+ // there may be even a conjunction between the first and the second last
+ // name. For example, the more-complete version of Pablo Picasso's surname is
+ // "Ruiz y Picasso" containing a first last name, a conjunction (the y) and a
+ // second last name.
+ optional StringToken name_last_first = 10;
+ optional StringToken name_last_conjunction = 11;
+ optional StringToken name_last_second = 12;
+ optional StringToken name_full = 13;
+
+ reserved 14;
+ reserved "name_full_with_honorific";
+
+ // Contact info alternative name fields (e.g. phonetic names in Japan).
+ optional StringToken alternative_full_name = 57;
+ optional StringToken alternative_given_name = 58;
+ optional StringToken alternative_family_name = 59;
+
+ // Contact info additional fields.
+ optional StringToken email_address = 15;
+ optional StringToken company_name = 16;
+
+ // Address fields: These are user-provided values with no particular
+ // guarantees about their format.
+ optional StringToken address_city = 17;
+ optional StringToken address_state = 18;
+ optional StringToken address_zip = 19;
+ optional StringToken address_country = 20;
+ optional StringToken address_admin_level_2 = 43;
+
+ // Additional address fields for i18n.
+ // Includes all of the lines of a street address, including newlines, e.g.
+ // 123 Main Street,
+ // Apt. #42
+ optional StringToken address_street_address = 21;
+ // A sorting code is similar to a postal code. However, whereas a postal code
+ // normally refers to a single geographical location, a sorting code often
+ // does not. Instead, a sorting code is assigned to an organization, which
+ // might be geographically distributed. The most prominent example of a
+ // sorting code system is CEDEX in France.
+ optional StringToken address_sorting_code = 22;
+ // A dependent locality is a subunit of a locality, where a "locality" is
+ // roughly equivalent to a city. Examples of dependent localities include
+ // inner-city districts and suburbs.
+ optional StringToken address_dependent_locality = 23;
+ reserved 24;
+ reserved "address_language_code";
+ // The street name of the address, without a house number.
+ optional StringToken address_thoroughfare_name = 25;
+ // The house number, which may be alphanumeric.
+ optional StringToken address_thoroughfare_number = 26;
+ // Deprecated in M118.
+ reserved 27;
+ reserved "address_dependent_thoroughfare_name";
+ reserved 28;
+ reserved "address_thoroughfare_and_dependent_thoroughfare_name";
+ reserved 29;
+ reserved "address_premise_name";
+ // Contains the floor, staircase or apartment number within a building.
+ optional StringToken address_subpremise_name = 30;
+ // All the information related to the apartment. Normally a combination of the
+ // apartment type (address_apt_type) and number (address_apt_num).
+ // E.g. "Apt 5".
+ optional StringToken address_apt = 50;
+ // The apartment number within a building.
+ optional StringToken address_apt_num = 31;
+ // Information describing the type of apartment (e.g. Apt, Apartamento, Sala,
+ // Departamento).
+ optional StringToken address_apt_type = 51;
+ // The floor number within a building.
+ optional StringToken address_floor = 32;
+ // Contains both the street and house number.
+ optional StringToken address_street_location = 44;
+
+ optional StringToken address_landmark = 41;
+ optional StringToken address_overflow = 45;
+ // Indicates that the address is at the intersection between two streets.
+ // It is normally a combination of between_streets_1 and _2. This is a common
+ // way of writing addresses in Mexico.
+ optional StringToken address_between_streets = 42;
+ // The meaning of the field is similar to address_between_streets. The
+ // type should be used for "Entre calle 1" in MX addresses which also
+ // contain the "Entre calle 2" field.
+ optional StringToken address_between_streets_1 = 46;
+ // The meaning of the field is similar to address_between_streets. The
+ // type should be used for "Entre calle 2" in MX addresses which also
+ // contain the "Entre calle 1" field.
+ optional StringToken address_between_streets_2 = 47;
+ // Combination of types address_between_streets or address_landmark. Note that
+ // some address forms require the combination of both in a single field as
+ // opposed to each one separately.
+ optional StringToken address_between_streets_or_landmark = 48;
+ // Combination of types address_overflow and address_landmark. Note that some
+ // address forms require the combination of both in a single field as opposed
+ // to each one separately.
+ optional StringToken address_overflow_and_landmark = 49;
+ // Combination of types address_street_location and
+ // address_dependent_locality. Note that some address forms require the
+ // combination of both in a single field as opposed to each one separately.
+ optional StringToken address_street_location_and_locality = 52;
+ // Combination of types address_thoroughfare_number and address_apt. Note that
+ // some address forms require the combination of both in a single field as
+ // opposed to each one separately.
+ optional StringToken address_thoroughfare_number_and_apt = 53;
+ // Prefix of the zip code, e.g., "12345" in "12345-6789".
+ optional StringToken address_zip_prefix = 63;
+ // Part of the zip code, excluding prefix and separator.
+ // For example, "6789" in "12345-6789".
+ optional StringToken address_zip_suffix = 64;
+
+ // Phone.
+ optional StringToken phone_home_whole_number = 33;
+
+ // Removed in M123.
+ reserved 34;
+ reserved "birthdate_day";
+ reserved 35;
+ reserved "birthdate_month";
+ reserved 36;
+ reserved "birthdate_year";
+
+ // Removed in M122.
+ reserved 6;
+ reserved "name_honorific";
+}
diff --git a/pyhindsight/lib/components/sync/protocol/cookie_specifics.proto b/pyhindsight/lib/components/sync/protocol/cookie_specifics.proto
new file mode 100644
index 0000000..502a60f
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/cookie_specifics.proto
@@ -0,0 +1,92 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+
+option java_multiple_files = true;
+option java_package = "org.chromium.components.sync.protocol";
+
+option optimize_for = LITE_RUNTIME;
+
+package sync_pb;
+
+// This proto represents a single cookie. Except for `unique_key` all
+// fields should be the same as in `net::CanonicalCookie`.
+message CookieSpecifics {
+ // To be used as a Sync client tag, corresponds to `StrictlyUniqueCookieKey`.
+ // `StrictlyUniqueCookieKey` contains selected members of
+ // `net::CanonicalCoookie` which we already save in specifics, but we save the
+ // key separately to be resilient against future changes to
+ // `StrictlyUniqueCookieKey`. By reading it from this field (instead of
+ // computing it from other data in specifics) we make sure that the client tag
+ // will be stable across different Chrome versions. It also leaves the option
+ // to check if the key saved in a given entity is aligned with the current
+ // definition of `StrictlyUniqueCookieKey`. If it is not, client can choose to
+ // ignore that entity, or implement any other special handling. The string
+ // saved here is expected to be computed by concatenating serialized values
+ // from the `StrictlyUniqueCookieKey` for the corresponding cookie.
+ optional string unique_key = 1;
+
+ optional string name = 2;
+ optional string value = 3;
+ optional string domain = 4;
+ optional string path = 5;
+
+ optional int64 creation_time_windows_epoch_micros = 6;
+ optional int64 expiry_time_windows_epoch_micros = 7;
+ optional int64 last_access_time_windows_epoch_micros = 8;
+ optional int64 last_update_time_windows_epoch_micros = 9;
+
+ optional bool secure = 10;
+ optional bool httponly = 11;
+
+ // The numbering is different compared to the `net::CookieSameSite` enum since
+ // the style guide asks to use UNSPECIFIED for the zero value enum
+ // (https://protobuf.dev/programming-guides/style/#enums).
+ enum CookieSameSite {
+ UNSPECIFIED = 0;
+ NO_RESTRICTION = 1;
+ LAX_MODE = 2;
+ STRICT_MODE = 3;
+ }
+
+ optional CookieSameSite site_restrictions = 12;
+
+ // The numbering is different compared to the `net::CookiePriority` enum since
+ // the style guide asks to use UNSPECIFIED for the zero value enum
+ // (https://protobuf.dev/programming-guides/style/#enums).
+ enum CookiePriority {
+ UNSPECIFIED_PRIORITY = 0;
+ LOW = 1;
+ MEDIUM = 2;
+ HIGH = 3;
+ }
+
+ optional CookiePriority priority = 13;
+
+ enum CookieSourceScheme {
+ UNSET = 0;
+ NON_SECURE = 1;
+ SECURE = 2;
+ };
+
+ optional CookieSourceScheme source_scheme = 14;
+
+ message SerializedCookiePartitionKey {
+ optional string top_level_site = 1;
+ optional bool has_cross_site_ancestor = 2;
+ }
+
+ optional SerializedCookiePartitionKey partition_key = 15;
+ optional int32 source_port = 16;
+
+ enum CookieSourceType {
+ UNKNOWN = 0;
+ HTTP = 1;
+ SCRIPT = 2;
+ OTHER = 3;
+ };
+
+ optional CookieSourceType source_type = 17;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/data_type_progress_marker.proto b/pyhindsight/lib/components/sync/protocol/data_type_progress_marker.proto
new file mode 100644
index 0000000..bd7cba5
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/data_type_progress_marker.proto
@@ -0,0 +1,183 @@
+// Copyright 2021 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+
+option java_multiple_files = true;
+option java_package = "org.chromium.components.sync.protocol";
+
+option optimize_for = LITE_RUNTIME;
+
+package sync_pb;
+
+message DataTypeProgressMarker {
+ // An integer identifying the data type whose progress is tracked by this
+ // marker. The legitimate values of this field correspond to the protobuf
+ // field numbers of all EntitySpecifics fields supported by the server.
+ // These values are externally declared in per-datatype .proto files.
+ optional int32 data_type_id = 1;
+
+ // An opaque-to-the-client sequence of bytes that the server may interpret
+ // as an indicator of the client's knowledge state. If this is empty or
+ // omitted by the client, it indicates that the client is initiating a
+ // a first-time sync of this datatype. Otherwise, clients must supply a
+ // value previously returned by the server in an earlier GetUpdatesResponse.
+ // These values are not comparable or generable on the client.
+ //
+ // The opaque semantics of this field are to afford server implementations
+ // some flexibility in implementing progress tracking. For instance,
+ // a server implementation built on top of a distributed storage service --
+ // or multiple heterogenous such services -- might need to supply a vector
+ // of totally ordered monotonic update timestamps, rather than a single
+ // monotonically increasing value. Other optimizations may also be
+ // possible if the server is allowed to embed arbitrary information in
+ // the progress token.
+ //
+ // Server implementations should keep the size of these tokens relatively
+ // small, on the order of tens of bytes, and they should remain small
+ // regardless of the number of items synchronized. (A possible bad server
+ // implementation would be for progress_token to contain a list of all the
+ // items ever sent to the client. Servers shouldn't do this.)
+ optional bytes token = 2;
+
+ reserved 3;
+ reserved "timestamp_token_for_migration";
+
+ reserved 4;
+ reserved "notification_hint";
+
+ // This field will be included only in GetUpdates with origin GU_TRIGGER.
+ optional GetUpdateTriggers get_update_triggers = 5;
+
+ // The garbage collection directive for this data type. The client should
+ // purge items locally based on this directive. Since this directive is
+ // designed to be sent from server only, the client should persist it locally
+ // as needed and avoid sending it to the server.
+ optional GarbageCollectionDirective gc_directive = 6;
+}
+
+// A single datatype's sync context. Allows the datatype to pass along
+// datatype specific information with its own server backend.
+message DataTypeContext {
+ // The type this context is associated with.
+ optional int32 data_type_id = 1;
+ // The context for the datatype.
+ optional bytes context = 2;
+ // The version of the context.
+ optional int64 version = 3;
+}
+
+message GarbageCollectionDirective {
+ enum Type {
+ UNKNOWN = 0;
+ VERSION_WATERMARK = 1;
+ DEPRECATED_AGE_WATERMARK = 2 [deprecated = true];
+ DEPRECATED_MAX_ITEM_COUNT = 3 [deprecated = true];
+ }
+
+ // Deprecated in M124. This field is unused because it would be hard to use
+ // `active_collaboration_ids`. The client should rely on the presence of the
+ // corresponding fields instead.
+ optional Type type = 1 [default = UNKNOWN, deprecated = true];
+
+ // This field specifies the watermark for the versions which should get
+ // garbage collected. The client should purge all sync entities when
+ // receiving any value of this. This is a change from previous behavior,
+ // where the client would only be required to purge items older than the
+ // specified watermark.
+ // TODO(crbug.com/41410173): Rename this to make clear that whenever it's set,
+ // the client will delete ALL data, regardless of its value.
+ optional int64 version_watermark = 2;
+
+ reserved 3;
+ reserved "age_watermark_in_days";
+
+ reserved 4;
+ reserved "max_number_of_items";
+
+ // This field contains a list of active collaboration IDs which are available
+ // to the user. The client should stop tracking any shared sync entities with
+ // collaborations which are not in the list. Note that if the list is empty,
+ // an empty `collaboration_gc` is expected to be provided by the server.
+ // Introduced in M124.
+ message CollaborationGarbageCollection {
+ repeated string active_collaboration_ids = 1;
+ }
+ optional CollaborationGarbageCollection collaboration_gc = 5;
+}
+
+// This message communicates additional per-type information related to
+// requests with origin GU_TRIGGER. This message is not relevant when any
+// other origin value is used.
+// Introduced in M29.
+message GetUpdateTriggers {
+ // An opaque-to-the-client string of bytes, received through a notification,
+ // that the server may interpret as a hint about the location of the latest
+ // version of the data for this type.
+ // Introduced in M29.
+ repeated string notification_hint = 1;
+
+ // This flag is set if the client was forced to drop hints because the number
+ // of queued hints exceeded its limit. The oldest hints will be discarded
+ // first. Introduced in M29.
+ optional bool client_dropped_hints = 2;
+
+ // This flag is set when the client suspects that its list of invalidation
+ // hints may be incomplete. This may be the case if:
+ // - The client is syncing for the first time.
+ // - The client has just restarted and it was unable to keep track of
+ // invalidations that were received prior to the restart.
+ // - The client's connection to the invalidation server is currently or
+ // was recently broken.
+ //
+ // It's difficult to provide more details here. This is implemented by
+ // setting the flag to false whenever anything that might adversely affect
+ // notifications happens (eg. a crash, restart on a platform that doesn't
+ // support invalidation ack-tracking, transient invalidation error) and is
+ // unset only after we've experienced one successful sync cycle while
+ // notifications were enabled.
+ //
+ // This flag was introduced in M29.
+ optional bool invalidations_out_of_sync = 3;
+
+ // This counts the number of times the syncer has been asked to commit
+ // changes for this type since the last successful sync cycle. The number of
+ // nudges may not be related to the actual number of items modified. It
+ // often correlates with the number of user actions, but that's not always
+ // the case.
+ // Introduced in M29.
+ optional int64 local_modification_nudges = 4;
+
+ // This counts the number of times the syncer has been explicitly asked to
+ // fetch updates for this type since the last successful sync cycle. These
+ // explicit refresh requests should be relatively rare on most platforms, and
+ // associated with user actions. For example, at the time of this writing
+ // the most common (only?) source of refresh requests is when a user opens
+ // the new tab page on a platform that does not support sessions
+ // invalidations.
+ // Introduced in M29.
+ optional int64 datatype_refresh_nudges = 5;
+
+ // This flag is set if the invalidation server reports that it may have
+ // dropped some invalidations at some point. Introduced in M33.
+ optional bool server_dropped_hints = 6;
+
+ // This flag is set if this GetUpdate request is due at least in part due
+ // to the fact that this type has not finished initial sync yet, and the
+ // client would like to initialize itself with the server data.
+ //
+ // Only some types support performing an initial sync as part of a normal
+ // GetUpdate request. Many types must be in configure mode when fetching
+ // initial sync data.
+ //
+ // Introduced in M38.
+ optional bool initial_sync_in_progress = 7;
+
+ // This flag is set if this GetUpdate request is due to client receiving
+ // conflict response from server, so client needs to sync and then resolve
+ // conflict locally, and then commit again.
+ //
+ // Introduced in M42.
+ optional bool sync_for_resolve_conflict_in_progress = 8;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/data_type_state.proto b/pyhindsight/lib/components/sync/protocol/data_type_state.proto
new file mode 100644
index 0000000..7dcd3f6
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/data_type_state.proto
@@ -0,0 +1,94 @@
+// Copyright 2016 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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/data_type_progress_marker.proto";
+
+// Sync proto to store data type global metadata in data type storage.
+message DataTypeState {
+ enum InitialSyncState {
+ // Default value, typically used when there is no metadata (e.g. because
+ // Sync is disabled).
+ INITIAL_SYNC_STATE_UNSPECIFIED = 0;
+
+ // Note: Value "1" is reserved, in case we ever want to introduce an
+ // INITIAL_SYNC_STARTED state.
+
+ // Indicates that syncing has started and some, but not all updates from the
+ // initial download/sync have been delivered. This is only used for data
+ // types in ApplyUpdatesImmediatelyTypes().
+ INITIAL_SYNC_PARTIALLY_DONE = 2;
+
+ // Indicates that the initial sync (download + merge) has been completed.
+ INITIAL_SYNC_DONE = 3;
+
+ // Indicates that no initial sync is necessary, used for CommitOnlyTypes().
+ INITIAL_SYNC_UNNECESSARY = 4;
+ }
+
+ // The latest progress markers received from the server.
+ optional DataTypeProgressMarker progress_marker = 1;
+
+ // A data type context. Sent to the server in every commit or update
+ // request. May be updated by either responses from the server or requests
+ // made on the model thread. The interpretation of this value may be
+ // data-type specific. Many data types ignore it.
+ optional DataTypeContext type_context = 2;
+
+ // This value is set if this type's data should be encrypted on the server.
+ // If this key changes, the client will need to re-commit all of its local
+ // data to the server using the new encryption key.
+ optional string encryption_key_name = 3;
+
+ // Indicates the status of "initial sync", i.e. whether the first download
+ // cycle and initial merge are complete.
+ optional InitialSyncState initial_sync_state = 9;
+
+ // A GUID that identifies the committing sync client. It's persisted within
+ // the sync metadata and should be used to check the integrity of the
+ // metadata. Mismatches with the guid of the running client indicates invalid
+ // persisted sync metadata, because cache_guid is reset when sync is disabled,
+ // and disabling sync is supposed to clear sync metadata.
+ optional string cache_guid = 5;
+
+ // Syncing account obfuscated Gaia ID, representing the user.
+ optional string authenticated_obfuscated_gaia_id = 6;
+
+ message Invalidation {
+ // Opaque field, which has to be provided as part of resulting GetUpdates
+ // back to the server.
+ optional bytes hint = 1;
+
+ // Version of invalidation, used to order incoming invalidations.
+ optional int64 version = 2;
+ }
+
+ // The latest unprocessed invalidations received from the server.
+ // All incoming invalidations are stored in this message and persist until
+ // they are used in GetUpdate() message.
+ repeated Invalidation invalidations = 7;
+
+ // This is relevant for the passwords datatype. This indicates that the
+ // initial sync flow (downling all passwords from the server) has been run at
+ // least once after the password notes features is enabled. It is used to
+ // enforce redownload of passwords upon upgrading the browser to a version
+ // that supports password notes if necessary. It is false by default and set
+ // to true upon downloading passwords to make sure this download is executed
+ // only once.
+ optional bool notes_enabled_before_initial_sync_for_passwords = 8;
+
+ reserved 4;
+ reserved "initial_sync_done";
+}
diff --git a/pyhindsight/lib/components/sync/protocol/data_type_state_helper.cc b/pyhindsight/lib/components/sync/protocol/data_type_state_helper.cc
new file mode 100644
index 0000000..fdfb1fe
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/data_type_state_helper.cc
@@ -0,0 +1,34 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/sync/protocol/data_type_state_helper.h"
+
+#include "components/sync/protocol/data_type_state.pb.h"
+
+namespace syncer {
+
+bool IsInitialSyncDone(sync_pb::DataTypeState::InitialSyncState state) {
+ switch (state) {
+ case sync_pb::DataTypeState_InitialSyncState_INITIAL_SYNC_STATE_UNSPECIFIED:
+ case sync_pb::DataTypeState_InitialSyncState_INITIAL_SYNC_PARTIALLY_DONE:
+ return false;
+ case sync_pb::DataTypeState_InitialSyncState_INITIAL_SYNC_DONE:
+ case sync_pb::DataTypeState_InitialSyncState_INITIAL_SYNC_UNNECESSARY:
+ return true;
+ }
+}
+
+bool IsInitialSyncAtLeastPartiallyDone(
+ sync_pb::DataTypeState::InitialSyncState state) {
+ switch (state) {
+ case sync_pb::DataTypeState_InitialSyncState_INITIAL_SYNC_STATE_UNSPECIFIED:
+ return false;
+ case sync_pb::DataTypeState_InitialSyncState_INITIAL_SYNC_PARTIALLY_DONE:
+ case sync_pb::DataTypeState_InitialSyncState_INITIAL_SYNC_DONE:
+ case sync_pb::DataTypeState_InitialSyncState_INITIAL_SYNC_UNNECESSARY:
+ return true;
+ }
+}
+
+} // namespace syncer
diff --git a/pyhindsight/lib/components/sync/protocol/data_type_state_helper.h b/pyhindsight/lib/components/sync/protocol/data_type_state_helper.h
new file mode 100644
index 0000000..91b243a
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/data_type_state_helper.h
@@ -0,0 +1,23 @@
+// Copyright 2023 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_PROTOCOL_DATA_TYPE_STATE_HELPER_H_
+#define COMPONENTS_SYNC_PROTOCOL_DATA_TYPE_STATE_HELPER_H_
+
+#include "components/sync/base/data_type.h"
+
+namespace sync_pb {
+enum DataTypeState_InitialSyncState : int;
+} // namespace sync_pb
+
+namespace syncer {
+
+bool IsInitialSyncDone(sync_pb::DataTypeState_InitialSyncState state);
+
+bool IsInitialSyncAtLeastPartiallyDone(
+ sync_pb::DataTypeState_InitialSyncState state);
+
+} // namespace syncer
+
+#endif // COMPONENTS_SYNC_PROTOCOL_DATA_TYPE_STATE_HELPER_H_
diff --git a/pyhindsight/lib/components/sync/protocol/data_type_store_schema_descriptor.proto b/pyhindsight/lib/components/sync/protocol/data_type_store_schema_descriptor.proto
new file mode 100644
index 0000000..f1d203b
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/data_type_store_schema_descriptor.proto
@@ -0,0 +1,22 @@
+// Copyright 2016 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Protocol messages used to record the state of the data type store for USS.
+// At the time of writing, the data type store uses leveldb, a schemaless
+// key-value store. This means that the database's schema is mostly implicit.
+// This descriptor isn't intended to fully describe the schema, just keep track
+// of which major changes have been applied.
+
+syntax = "proto2";
+
+option java_multiple_files = true;
+option java_package = "org.chromium.components.sync.protocol";
+
+option optimize_for = LITE_RUNTIME;
+
+package sync_pb;
+
+message DataTypeStoreSchemaDescriptor {
+ optional int64 version_number = 1;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/deletion_origin.proto b/pyhindsight/lib/components/sync/protocol/deletion_origin.proto
new file mode 100644
index 0000000..e8d3737
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/deletion_origin.proto
@@ -0,0 +1,60 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Protobuf representation of the DeletionOrigin class.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+// Represents a fingerprint-like token that identifies, or may help identity,
+// which piece of functionality is responsible for issuing a deletion that
+// propagates via Sync. It is sent to the Sync server as part of deletion
+// requests, as a safeguard to investigate and mitigate user reports or even
+// large-scale incidents.
+message DeletionOrigin {
+ // Populated by chromium-based browsers with the version that originally
+ // created the deletion. This will often be the same as the version that
+ // uploaded (committed) the deletion, but in rare cases the latter could be
+ // greater (i.e. the browser was updated in between).
+ optional string chromium_version = 1;
+
+ // Populated by Android Google Play Services with the version of the APK
+ // identifying the version that originally created the deletion. This should
+ // not be populated for DeletionOrigin instances that go through Google Play
+ // Services but were actually first triggered in chromium.
+ optional string google_play_services_apk_version_name = 2;
+
+ // Hash of the filename in the source code where the deletion originated. The
+ // precise hashing function is unspecified and may change over time. It may
+ // only be assumed that the hashing function is the same for a given version
+ // of the client (see fields above). Hashing is used instead of including the
+ // actual name to reduce the size of this message.
+ optional fixed32 file_name_hash = 3;
+
+ // Line of code where the deletion originated.
+ optional int32 file_line_number = 4;
+
+ // Human-readable and extra optional version of `file_name_hash`. Since the
+ // file name can be long and includes the full path, this string is very
+ // likely truncated (and hence not guaranteed to be unique). Truncation will
+ // remove the beginning of the string rather than the end of it.
+ optional string file_name_possibly_truncated = 5;
+
+ // Arbitrary but unique tag defined in the source code, when other means
+ // like the file name and line number aren't possible or desirable. This
+ // string isn't meant to be too long (recommended limit of 30 characters) and
+ // is subject to truncation any time. If truncation is used, it will remove
+ // the beginning of the string rather than the end of it. This field must not
+ // contain personally-identifiable information.
+ optional string unique_source_tag_no_pii_possibly_truncated = 6;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/device_info_specifics.proto b/pyhindsight/lib/components/sync/protocol/device_info_specifics.proto
new file mode 100644
index 0000000..5a2113a
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/device_info_specifics.proto
@@ -0,0 +1,226 @@
+// 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 datatype extension for nigori keys.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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/sync_enums.proto";
+
+// Information about a device that is running a sync-enabled Chrome browser. We
+// are mapping the per-client cache guid to more specific information about the
+// device.
+message DeviceInfoSpecifics {
+ // The cache_guid created to identify a sync client on this device.
+ optional string cache_guid = 1;
+
+ // A non-unique but human readable name to describe this client.
+ optional string client_name = 2;
+
+ // The platform of the device.
+ // Deprecated in M110, but still populated for backwards compatibility.
+ // Replaced by os_type + device_form_factor.
+ optional SyncEnums.DeviceType device_type = 3 [deprecated = true];
+
+ // The UserAgent used when contacting the Chrome Sync server.
+ // Only present when talking to the HTTP server.
+ optional string sync_user_agent = 4;
+
+ // The Chrome instance's version. Updated (if necessary) on every startup.
+ // DEPRECATED in M92. Still populated for backward compatibility.
+ optional string chrome_version = 5 [deprecated = true];
+
+ // Last time when pre-sync data on the device was saved. The device can be
+ // restored to state back to this time. In millisecond since UNIX epoch.
+ // DEPRECATED in M50.
+ optional int64 deprecated_backup_timestamp = 6 [deprecated = true];
+
+ // Device_id that is stable until user signs out. This device_id is used for
+ // annotating login scoped refresh token. Present only for Chrome Clients.
+ optional string signin_scoped_device_id = 7;
+
+ // This field is updated to be the current time periodically, and is also set
+ // to the current time whenever another field changes. By examining the
+ // difference between this field and the current time, it should be possible
+ // to reason about the inactivity of any device that was syncing at one time.
+ optional int64 last_updated_timestamp = 8;
+
+ // Device info fields that are specific to a feature. This is information that
+ // can not be derived from the other fields in the proto and are not general
+ // enough to be used by another feature.
+ optional FeatureSpecificFields feature_fields = 9;
+
+ // Device specific information for Sharing feature.
+ optional SharingSpecificFields sharing_fields = 10;
+
+ // Model of device.
+ optional string model = 11;
+
+ // Name of device manufacturer.
+ optional string manufacturer = 12;
+
+ // The interval in minutes with which `last_updated_timestamp` is updated to
+ // the sync servers if online and while sync is actively running (e.g.
+ // excludes backgrounded apps on Android). Introduced in M81. The legacy
+ // default was 1 day.
+ optional int32 pulse_interval_in_minutes = 13;
+
+ // Device specific information for Sync invalidations.
+ optional InvalidationSpecificFields invalidation_fields = 14;
+
+ // Information for contacting this device in order to perform security key
+ // operations.
+ optional PhoneAsASecurityKeySpecificFields paask_fields = 15;
+
+ // Unique hardware identifier string which details the HW combination of
+ // a ChromeOS device. This field will be empty on other OS devices.
+ optional string full_hardware_class = 16;
+
+ // Version information to pin-point which client implementation this is.
+ oneof client_version_info {
+ ChromeVersionInfo chrome_version_info = 17;
+ GooglePlayServicesVersionInfo google_play_services_version_info = 18;
+ }
+
+ // The OS type the device.
+ optional SyncEnums.OsType os_type = 19;
+
+ // The form factor of the device.
+ optional SyncEnums.DeviceFormFactor device_form_factor = 20;
+}
+
+// Feature specific information about the device that is running a sync-enabled
+// Chrome browser. Adding to this proto is discouraged and should only be added
+// when the information can not be derived more generally.
+message FeatureSpecificFields {
+ // Tracks whether the SendTabToSelf feature is enabled on the device. For this
+ // to be true, two things must be true: (1) The receiving side of the feature
+ // must be enabled on the device (2) The user has enabled sync for this
+ // feature.
+ optional bool send_tab_to_self_receiving_enabled = 1;
+
+ // Tracks which type of Send Tab To Self message(s) can be sent to the
+ // receiving device.
+ // If not set, the in-app message type will be assumed.
+ optional SyncEnums.SendTabReceivingType send_tab_to_self_receiving_type = 2;
+
+ // Tracks the last time this device signed-in with the Auto Sign-Out
+ // feature enabled. As of 09/2025, this feature is only supported on ChromeOS.
+ optional int64 auto_sign_out_last_signin_timestamp_windows_epoch_micros = 3;
+}
+
+// Device specific information for Sharing feature. Used to send end-to-end
+// encrypted message through FCM or unencrypted message through Chime to other
+// devices.
+message SharingSpecificFields {
+ reserved 1, 2, 3;
+ reserved "vapid_fcm_token", "vapid_p256dh", "vapid_auth_secret";
+
+ // Enum defining available Sharing features.
+ enum EnabledFeatures {
+ reserved 5;
+ reserved "PEER_CONNECTION";
+ reserved 1;
+ reserved "CLICK_TO_CALL_VAPID";
+ reserved 2;
+ reserved "SHARED_CLIPBOARD_VAPID";
+
+ UNKNOWN = 0;
+ SMS_FETCHER = 3;
+ REMOTE_COPY = 4;
+ DISCOVERY = 6;
+ // Supports Click to Call via sender ID.
+ CLICK_TO_CALL_V2 = 7;
+ // Supports Shared Clipboard via sender ID.
+ SHARED_CLIPBOARD_V2 = 8;
+ // Supports optimization guide push notification.
+ OPTIMIZATION_GUIDE_PUSH_NOTIFICATION = 9;
+ }
+
+ // A list of enabled Sharing features.
+ repeated EnabledFeatures enabled_features = 4;
+
+ // Deprecated. Use sender_id_fcm_token_v2 for new clients.
+ optional string sender_id_fcm_token_deprecated = 5 [deprecated = true];
+
+ // Deprecated. Use sender_id_p256dh_v2 for new clients.
+ optional bytes sender_id_p256dh_deprecated = 6 [deprecated = true];
+
+ // Deprecated. Use sender_id_auth_secret_v2 for new clients.
+ optional bytes sender_id_auth_secret_deprecated = 7 [deprecated = true];
+
+ // FCM registration token of device subscribed using Sharing sender ID.
+ optional string sender_id_fcm_token_v2 = 8;
+
+ // Public key for message encryption [RFC8291] using Sharing sender ID.
+ optional bytes sender_id_p256dh_v2 = 9;
+
+ // Auth secret for message encryption [RFC8291] using Sharing sender ID.
+ optional bytes sender_id_auth_secret_v2 = 10;
+
+ // Identifier used to send notifications to a specific device in Chime. Added
+ // in M128.
+ optional string chime_representative_target_id = 11;
+}
+
+// Device specific information telling how to send invalidations to this device.
+message InvalidationSpecificFields {
+ // FCM registration token of device (using Sync sender ID).
+ optional string instance_id_token = 1;
+
+ // This device wants to receive only invalidations which are related to these
+ // types. The legitimate values of this field correspond to the protobuf field
+ // numbers of all EntitySpecifics fields supported by the server (see
+ // components/sync/protocol/sync.proto).
+ repeated int32 interested_data_type_ids = 2;
+}
+
+message PhoneAsASecurityKeySpecificFields {
+ // The encoded tunnel server in the same format as in the BLE advert. See
+ // device::cablev2::tunnelserver::DecodeDomain. (Actually a uint16 but
+ // proto doesn't have that as a type.)
+ optional uint32 tunnel_server_domain = 1;
+
+ // An FCM token that can be presented to the tunnel server to contact this
+ // device.
+ optional bytes contact_id = 2;
+
+ // A shared secret key, used to enable communication across devices via
+ // unauthenticated channels. Knowledge of this secret acts as proof that the
+ // remote end is authorized to talk to the device publishing this secret.
+ optional bytes secret = 3;
+
+ // An id that identifies `secret`. This, and `secret`, will be rotated and
+ // the ID allows this device to know which `secret` the counterparty is
+ // using.
+ optional fixed32 id = 4;
+
+ // A P-256, X9.62-encoded public key for this device. Specific to the Chrome
+ // instance.
+ optional bytes peer_public_key_x962 = 5;
+
+ // The credential ID for use when signing into accounts.google.com. This
+ // credential ID isn't published as a WebauthnCredentialSpecifics, unlike
+ // other passkeys, because it's auto-generated.
+ optional bytes google_credential_id = 6;
+}
+
+message ChromeVersionInfo {
+ // Version number as per https://www.chromium.org/developers/version-numbers.
+ optional string version_number = 1;
+}
+
+message GooglePlayServicesVersionInfo {
+ optional string apk_version_name = 1;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/dictionary_specifics.proto b/pyhindsight/lib/components/sync/protocol/dictionary_specifics.proto
new file mode 100644
index 0000000..f670576
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/dictionary_specifics.proto
@@ -0,0 +1,23 @@
+// 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 datatype extension for the dictionary.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+// Properties of Dictionary objects.
+message DictionarySpecifics {
+ // A spelling which when typed is treated as a correctly spelled word.
+ optional string word = 1;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/encryption.proto b/pyhindsight/lib/components/sync/protocol/encryption.proto
new file mode 100644
index 0000000..2c7457b
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/encryption.proto
@@ -0,0 +1,34 @@
+// 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.
+//
+// Common sync protocol for encrypted data.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+// Encrypted sync data consists of two parts: a key name and a blob. Key name is
+// the name of the key that was used to encrypt blob and blob is encrypted data
+// itself.
+//
+// The reason we need to keep track of the key name is that a sync user can
+// change their passphrase (and thus their encryption key) at any time. When
+// that happens, we make a best effort to reencrypt all nodes with the new
+// passphrase, but since we don't have transactions on the server-side, we
+// cannot guarantee that every node will be reencrypted. As a workaround, we
+// keep track of all keys, assign each key a name (by using that key to encrypt
+// a well known string) and keep track of which key was used to encrypt each
+// node.
+message EncryptedData {
+ optional string key_name = 1;
+ optional string blob = 2; // base64-encoded.
+}
diff --git a/pyhindsight/lib/components/sync/protocol/entity_data.cc b/pyhindsight/lib/components/sync/protocol/entity_data.cc
new file mode 100644
index 0000000..17a258e
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/entity_data.cc
@@ -0,0 +1,101 @@
+// Copyright 2015 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/sync/protocol/entity_data.h"
+
+#include
+#include
+#include
+#include
+
+#include "base/json/json_writer.h"
+#include "base/trace_event/memory_usage_estimator.h"
+#include "base/values.h"
+#include "components/sync/base/time.h"
+#include "components/sync/protocol/proto_memory_estimations.h"
+#include "components/sync/protocol/proto_value_conversions.h"
+
+namespace syncer {
+
+EntityData::EntityData() = default;
+
+EntityData::EntityData(EntityData&& other) = default;
+
+EntityData::~EntityData() = default;
+
+EntityData& EntityData::operator=(EntityData&& other) = default;
+
+base::Value::Dict EntityData::ToDictionaryValue() const {
+ // This is used when debugging at sync-internals page. The code in
+ // sync_node_browser.js is expecting certain fields names. e.g. CTIME, MTIME,
+ // and IS_DIR.
+ base::Value::Dict value =
+ base::Value::Dict()
+ .Set("SPECIFICS", EntitySpecificsToValue(specifics))
+ .Set("ID", id)
+ .Set("CLIENT_TAG_HASH", client_tag_hash.value())
+ .Set("ORIGINATOR_CACHE_GUID", originator_cache_guid)
+ .Set("ORIGINATOR_CLIENT_ITEM_ID", originator_client_item_id)
+ .Set("SERVER_DEFINED_UNIQUE_TAG", server_defined_unique_tag)
+ // The string "NON_UNIQUE_NAME" is used in sync-internals to identify
+ // the node title.
+ .Set("NON_UNIQUE_NAME", name)
+ .Set("NAME", name)
+ // The string "PARENT_ID" is used in sync-internals to build the node
+ // tree.
+ .Set("PARENT_ID", legacy_parent_id)
+ .Set("CTIME", GetTimeDebugString(creation_time))
+ .Set("MTIME", GetTimeDebugString(modification_time))
+ .Set("RECIPIENT_PUBLIC_KEY",
+ CrossUserSharingPublicKeyToValue(recipient_public_key));
+ if (collaboration_metadata.has_value()) {
+ value.Set("COLLABORATION_ID",
+ collaboration_metadata->collaboration_id().value());
+ value.Set("CREATED_BY", collaboration_metadata->created_by().ToString());
+ value.Set("LAST_UPDATED_BY",
+ collaboration_metadata->last_updated_by().ToString());
+ }
+ return value;
+}
+
+size_t EntityData::EstimateMemoryUsage() const {
+ using base::trace_event::EstimateMemoryUsage;
+ size_t memory_usage = 0;
+ memory_usage += EstimateMemoryUsage(id);
+ memory_usage += EstimateMemoryUsage(client_tag_hash);
+ memory_usage += EstimateMemoryUsage(originator_cache_guid);
+ memory_usage += EstimateMemoryUsage(originator_client_item_id);
+ memory_usage += EstimateMemoryUsage(server_defined_unique_tag);
+ memory_usage += EstimateMemoryUsage(name);
+ memory_usage += EstimateMemoryUsage(specifics);
+ memory_usage += EstimateMemoryUsage(legacy_parent_id);
+ memory_usage += EstimateMemoryUsage(recipient_public_key);
+ if (collaboration_metadata.has_value()) {
+ memory_usage += EstimateMemoryUsage(collaboration_metadata.value());
+ }
+ if (deletion_origin.has_value()) {
+ memory_usage += EstimateMemoryUsage(*deletion_origin);
+ }
+ return memory_usage;
+}
+
+void PrintTo(const EntityData& entity_data, std::ostream* os) {
+ std::string specifics;
+ base::JSONWriter::WriteWithOptions(
+ syncer::EntitySpecificsToValue(entity_data.specifics),
+ base::JSONWriter::OPTIONS_PRETTY_PRINT, &specifics);
+ *os << "{ id: '" << entity_data.id << "', client_tag_hash: '"
+ << entity_data.client_tag_hash << "', originator_cache_guid: '"
+ << entity_data.originator_cache_guid << "', originator_client_item_id: '"
+ << entity_data.originator_client_item_id
+ << "', server_defined_unique_tag: '"
+ << entity_data.server_defined_unique_tag << "', specifics: " << specifics;
+ if (entity_data.collaboration_metadata.has_value()) {
+ *os << ", collaboration_metadata: ";
+ PrintTo(entity_data.collaboration_metadata.value(), os);
+ }
+ *os << "}";
+}
+
+} // namespace syncer
diff --git a/pyhindsight/lib/components/sync/protocol/entity_data.h b/pyhindsight/lib/components/sync/protocol/entity_data.h
new file mode 100644
index 0000000..c0159ef
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/entity_data.h
@@ -0,0 +1,114 @@
+// Copyright 2015 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_PROTOCOL_ENTITY_DATA_H_
+#define COMPONENTS_SYNC_PROTOCOL_ENTITY_DATA_H_
+
+#include
+#include
+#include
+
+#include "base/time/time.h"
+#include "base/values.h"
+#include "components/sync/base/client_tag_hash.h"
+#include "components/sync/protocol/deletion_origin.pb.h"
+#include "components/sync/protocol/entity_specifics.pb.h"
+#include "components/sync/protocol/collaboration_metadata.h"
+
+namespace syncer {
+
+// A light-weight container for sync entity data which represents either
+// local data created on the local model side or remote data created on
+// DataTypeWorker.
+// EntityData is supposed to be wrapped and passed by reference.
+struct EntityData {
+ public:
+ EntityData();
+
+ EntityData& operator=(const EntityData&) = delete;
+
+ EntityData(EntityData&&);
+ EntityData& operator=(EntityData&&);
+
+ ~EntityData();
+
+ // Typically this is a server assigned sync ID, although for a local change
+ // that represents a new entity this field might be either empty or contain
+ // a temporary client sync ID.
+ std::string id;
+
+ // A hash based on the client tag and data type.
+ // Used for various map lookups. Should always be available for all data types
+ // except bookmarks (for bookmarks it depends on the version of the client
+ // that originally created the bookmark).
+ ClientTagHash client_tag_hash;
+
+ // A GUID that identifies the the sync client who initially committed this
+ // entity. It's relevant only for bookmarks. See the definition in sync.proto
+ // for more details.
+ std::string originator_cache_guid;
+
+ // The local item id of this entry from the client that initially committed
+ // this entity. It's relevant only for bookmarks. See the definition in
+ // sync.proto for more details.
+ std::string originator_client_item_id;
+
+ // This tag identifies this item as being a uniquely instanced item. An item
+ // can't have both a client_tag_hash and a
+ // server_defined_unique_tag. Sent to the server as
+ // SyncEntity::server_defined_unique_tag.
+ std::string server_defined_unique_tag;
+
+ // Entity name, used mostly for Debug purposes.
+ std::string name;
+
+ // Data type specific sync data.
+ sync_pb::EntitySpecifics specifics;
+
+ // Entity creation and modification timestamps.
+ base::Time creation_time;
+ base::Time modification_time;
+
+ // Server-provided sync ID of the parent entity, used for legacy bookmarks
+ // only. Unused for modern data created or reuploaded by M94 or above, which
+ // relies exclusively on the parent's GUID in BookmarkSpecifics.
+ // WARNING: Avoid references to this field outside
+ // components/sync_bookmarks/parent_guid_preprocessing.cc.
+ std::string legacy_parent_id;
+
+ // Recipient's Public Key used for cross-user sharing data types. Used for
+ // only outgoing password sharing invitations (created locally).
+ sync_pb::CrossUserSharingPublicKey recipient_public_key;
+
+ // Indicate whether bookmark's `unique_position` was missing in the original
+ // specifics during GetUpdates. If the `unique_position` in specifics was
+ // evaluated by AdaptUniquePositionForBookmark(), this field will be set to
+ // true. Relevant only for bookmarks.
+ bool is_bookmark_unique_position_in_specifics_preprocessed = false;
+
+ // Collaboration metadata for the entity. Present only for shared entities.
+ std::optional collaboration_metadata;
+
+ // True if EntityData represents deleted entity; otherwise false.
+ // Note that EntityData would be considered to represent a deletion if its
+ // specifics hasn't been set.
+ bool is_deleted() const { return specifics.ByteSizeLong() == 0; }
+
+ // Optionally populated for outgoing deletions. See corresponding field in
+ // SyncEntity for details.
+ std::optional deletion_origin;
+
+ // Dumps all info into a base::Value::Dict and returns it.
+ base::Value::Dict ToDictionaryValue() const;
+
+ // Returns the estimate of dynamically allocated memory in bytes.
+ size_t EstimateMemoryUsage() const;
+};
+
+// gMock printer helper.
+void PrintTo(const EntityData& entity_data, std::ostream* os);
+
+} // namespace syncer
+
+#endif // COMPONENTS_SYNC_PROTOCOL_ENTITY_DATA_H_
diff --git a/pyhindsight/lib/components/sync/protocol/entity_data_unittest.cc b/pyhindsight/lib/components/sync/protocol/entity_data_unittest.cc
new file mode 100644
index 0000000..f138944
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/entity_data_unittest.cc
@@ -0,0 +1,27 @@
+// Copyright 2015 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/sync/protocol/entity_data.h"
+
+#include "components/sync/base/data_type.h"
+#include "components/sync/base/unique_position.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace syncer {
+
+class EntityDataTest : public testing::Test {
+ protected:
+ EntityDataTest() = default;
+ ~EntityDataTest() override = default;
+};
+
+TEST_F(EntityDataTest, IsDeleted) {
+ EntityData data;
+ EXPECT_TRUE(data.is_deleted());
+
+ AddDefaultFieldValue(BOOKMARKS, &data.specifics);
+ EXPECT_FALSE(data.is_deleted());
+}
+
+} // namespace syncer
diff --git a/pyhindsight/lib/components/sync/protocol/entity_metadata.proto b/pyhindsight/lib/components/sync/protocol/entity_metadata.proto
new file mode 100644
index 0000000..9a3e496
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/entity_metadata.proto
@@ -0,0 +1,117 @@
+// Copyright 2015 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_conversions.{h, cc}.
+
+syntax = "proto2";
+
+package sync_pb;
+
+import "components/sync/protocol/deletion_origin.proto";
+import "components/sync/protocol/entity_specifics.proto";
+import "components/sync/protocol/unique_position.proto";
+
+option java_multiple_files = true;
+option java_package = "org.chromium.components.sync.protocol";
+option optimize_for = LITE_RUNTIME;
+
+// Sync proto to store entity metadata in data type storage.
+message EntityMetadata {
+ // A hash based on the client tag and data type.
+ // Used for various map lookups. Should always be available.
+ // Sent to the server as SyncEntity::client_tag_hash.
+ optional string client_tag_hash = 1;
+
+ // The entity's server-assigned ID.
+ //
+ // Prior to the item's first commit, we leave this value as an empty string.
+ // The initial ID for a newly created item has to meet certain uniqueness
+ // requirements, and we handle those on the sync thread.
+ optional string server_id = 2;
+
+ // Whether or not the entity is deleted.
+ optional bool is_deleted = 3;
+
+ // A version number used to track in-progress commits. Each local change
+ // increments this number.
+ optional int64 sequence_number = 4;
+
+ // The sequence number of the last item known to be successfully committed.
+ optional int64 acked_sequence_number = 5;
+
+ // The server version on which this item is based.
+ //
+ // If there are no local changes, this is the version of the entity as we see
+ // it here.
+ //
+ // If there are local changes, this is the version of the entity on which
+ // those changes are based.
+ optional int64 server_version = 6 [default = -1];
+
+ // Entity creation and modification timestamps. Assigned by the client and
+ // synced by the server, though the server usually doesn't bother to inspect
+ // their values. They are encoded as milliseconds since the Unix epoch.
+ optional int64 creation_time = 7;
+ optional int64 modification_time = 8;
+
+ // A hash of the current entity specifics value. Used to detect whether
+ // entity's specifics value has changed without having to keep specifics in
+ // memory.
+ optional string specifics_hash = 9;
+
+ // A hash of the last specifics known by both the client and server. Used to
+ // detect when local commits and remote updates are just for encryption. This
+ // value will be the empty string only in the following cases: the entity is
+ // in sync with the server, has never been synced, or is deleted.
+ optional string base_specifics_hash = 10;
+
+ // Used for positioning entities among their siblings. Relevant only for data
+ // types that support positions (e.g bookmarks). Refer to its definition in
+ // unique_position.proto for more information about its internal
+ // representation.
+ optional UniquePosition unique_position = 11;
+
+ // Used only for bookmarks. It's analogous to `specifics_hash` but it
+ // exclusively hashes the content of the favicon image, as represented in
+ // proto field BookmarkSpecifics.favicon, using base::PersistentHash().
+ optional fixed32 bookmark_favicon_hash = 12;
+
+ // Last specifics known by both the client and server. Used during commits to
+ // the server in order to prevent data loss caused by older clients dealing
+ // with unknown proto fields (fields that were introduced later). Datatypes
+ // (DataTypeSyncBridge) may implement logic to trim down (or fully clear)
+ // this proto prior to caching, to avoid the memory and I/O overhead of
+ // dealing with an extra copy of the data. Introduced in M101.
+ optional EntitySpecifics possibly_trimmed_base_specifics = 13;
+
+ // If the entity is deleted, this field will record the chromium version
+ // (e.g. 117.0.5875.1) that originated the deletion. Introduced in M117.
+ optional string deleted_by_version = 14;
+
+ // Metadata used for shared data types. Must not be present for regular data
+ // types.
+ // Introduced in M124.
+ message CollaborationMetadata {
+ message Attribution {
+ // Obfuscated Gaia ID of the user.
+ optional string obfuscated_gaia_id = 1;
+ }
+
+ // Collaboration ID which the current entity belongs to.
+ optional string collaboration_id = 1;
+
+ // Information about when the specifics was created.
+ optional Attribution creation_attribution = 2;
+
+ // Information about when the specifics was last updated.
+ optional Attribution last_update_attribution = 3;
+ }
+ optional CollaborationMetadata collaboration = 15;
+
+ // Optionally present for committed deletions (but may remain unset if the
+ // origin is unspecified), it represents which piece of code triggered a
+ // deletion. Introduced in M126.
+ optional DeletionOrigin deletion_origin = 16;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/entity_specifics.proto b/pyhindsight/lib/components/sync/protocol/entity_specifics.proto
new file mode 100644
index 0000000..70bc6fd
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/entity_specifics.proto
@@ -0,0 +1,199 @@
+// Copyright 2021 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+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/encryption.proto";
+import "components/sync/protocol/app_list_specifics.proto";
+import "components/sync/protocol/app_setting_specifics.proto";
+import "components/sync/protocol/app_specifics.proto";
+import "components/sync/protocol/arc_package_specifics.proto";
+import "components/sync/protocol/autofill_specifics.proto";
+import "components/sync/protocol/autofill_offer_specifics.proto";
+import "components/sync/protocol/autofill_valuable_specifics.proto";
+import "components/sync/protocol/autofill_valuable_setting_specifics.proto";
+import "components/sync/protocol/autofill_wallet_credential_specifics.proto";
+import "components/sync/protocol/autofill_wallet_usage_specifics.proto";
+import "components/sync/protocol/bookmark_specifics.proto";
+import "components/sync/protocol/collaboration_group_specifics.proto";
+import "components/sync/protocol/product_comparison_specifics.proto";
+import "components/sync/protocol/contact_info_specifics.proto";
+import "components/sync/protocol/cookie_specifics.proto";
+import "components/sync/protocol/device_info_specifics.proto";
+import "components/sync/protocol/dictionary_specifics.proto";
+import "components/sync/protocol/extension_setting_specifics.proto";
+import "components/sync/protocol/extension_specifics.proto";
+import "components/sync/protocol/history_delete_directive_specifics.proto";
+import "components/sync/protocol/history_specifics.proto";
+import "components/sync/protocol/managed_user_setting_specifics.proto";
+import "components/sync/protocol/managed_user_shared_setting_specifics.proto";
+import "components/sync/protocol/nigori_specifics.proto";
+import "components/sync/protocol/os_preference_specifics.proto";
+import "components/sync/protocol/os_priority_preference_specifics.proto";
+import "components/sync/protocol/password_sharing_invitation_specifics.proto";
+import "components/sync/protocol/password_specifics.proto";
+import "components/sync/protocol/plus_address_setting_specifics.proto";
+import "components/sync/protocol/plus_address_specifics.proto";
+import "components/sync/protocol/preference_specifics.proto";
+import "components/sync/protocol/printer_specifics.proto";
+import "components/sync/protocol/printers_authorization_server_specifics.proto";
+import "components/sync/protocol/priority_preference_specifics.proto";
+import "components/sync/protocol/reading_list_specifics.proto";
+import "components/sync/protocol/saved_tab_group_specifics.proto";
+import "components/sync/protocol/search_engine_specifics.proto";
+import "components/sync/protocol/security_event_specifics.proto";
+import "components/sync/protocol/send_tab_to_self_specifics.proto";
+import "components/sync/protocol/session_specifics.proto";
+import "components/sync/protocol/shared_comment_specifics.proto";
+import "components/sync/protocol/shared_tab_group_data_specifics.proto";
+import "components/sync/protocol/sharing_message_specifics.proto";
+import "components/sync/protocol/theme_specifics.proto";
+import "components/sync/protocol/typed_url_specifics.proto";
+import "components/sync/protocol/user_consent_specifics.proto";
+import "components/sync/protocol/user_event_specifics.proto";
+import "components/sync/protocol/web_apk_specifics.proto";
+import "components/sync/protocol/web_app_specifics.proto";
+import "components/sync/protocol/webauthn_credential_specifics.proto";
+import "components/sync/protocol/wifi_configuration_specifics.proto";
+import "components/sync/protocol/workspace_desk_specifics.proto";
+import "components/sync/protocol/shared_tab_group_account_data_specifics.proto";
+
+message EntitySpecifics {
+ // If a datatype is encrypted, this field will contain the encrypted
+ // original EntitySpecifics. The extension for the datatype will continue
+ // to exist, but contain only the default values.
+ // Note that currently passwords employ their own legacy encryption scheme and
+ // do not use this field.
+ optional EncryptedData encrypted = 1;
+
+ // To add new datatype-specific fields to the protocol, extend
+ // EntitySpecifics. First, pick a non-colliding tag number by
+ // picking a Cr-Commit-Position of one of your past commits
+ // to src.chromium.org. Then, in a different protocol buffer
+ // definition, define your message type, and add an optional field
+ // to the list below using the unique tag value you selected.
+ //
+ // optional MyDatatypeSpecifics my_datatype = 32222;
+ //
+ // where:
+ // - 32222 is the non-colliding tag number you picked earlier.
+ // - MyDatatypeSpecifics is the type (probably a message type defined
+ // in your new .proto file) that you want to associate with each
+ // object of the new datatype.
+ // - my_datatype is the field identifier you'll use to access the
+ // datatype specifics from the code.
+ //
+ // Server implementations are obligated to preserve the contents of
+ // EntitySpecifics when it contains unrecognized fields. In this
+ // way, it is possible to add new datatype fields without having
+ // to update the server.
+ //
+ // Note: The tag selection process is based on legacy versions of the
+ // protocol which used protobuf extensions. We have kept the process
+ // consistent as the old values cannot change. The 5+ digit nature of the
+ // tags also makes them recognizable (individually and collectively) from
+ // noise in logs and debugging contexts, and creating a divergent subset of
+ // tags would only make things a bit more confusing.
+
+ oneof specifics_variant {
+ AutofillSpecifics autofill = 31729;
+ BookmarkSpecifics bookmark = 32904;
+ PreferenceSpecifics preference = 37702;
+ ThemeSpecifics theme = 41210;
+ PasswordSpecifics password = 45873;
+ NigoriSpecifics nigori = 47745;
+ ExtensionSpecifics extension = 48119;
+ AppSpecifics app = 48364;
+ SessionSpecifics session = 50119;
+ AutofillProfileSpecifics autofill_profile = 63951;
+ SearchEngineSpecifics search_engine = 88610;
+ ExtensionSettingSpecifics extension_setting = 96159;
+ AppSettingSpecifics app_setting = 103656;
+ HistoryDeleteDirectiveSpecifics history_delete_directive = 150251;
+ DeviceInfoSpecifics device_info = 154522;
+ PriorityPreferenceSpecifics priority_preference = 163425;
+ DictionarySpecifics dictionary = 170540;
+ ManagedUserSettingSpecifics managed_user_setting = 186662;
+ AppListSpecifics app_list = 229170;
+ AutofillWalletSpecifics autofill_wallet = 306270;
+ WalletMetadataSpecifics wallet_metadata = 330441;
+ ArcPackageSpecifics arc_package = 340906;
+ PrinterSpecifics printer = 410745;
+ ReadingListSpecifics reading_list = 411028;
+ UserEventSpecifics user_event = 455206;
+ UserConsentSpecifics user_consent = 556014;
+ SendTabToSelfSpecifics send_tab_to_self = 601980;
+ SecurityEventSpecifics security_event = 600372;
+ WebApkSpecifics web_apk = 1117170;
+ WebAppSpecifics web_app = 673225;
+ WifiConfigurationSpecifics wifi_configuration = 662827;
+ OsPreferenceSpecifics os_preference = 702141;
+ OsPriorityPreferenceSpecifics os_priority_preference = 703915;
+ SharingMessageSpecifics sharing_message = 728866;
+ AutofillOfferSpecifics autofill_offer = 774329;
+ WorkspaceDeskSpecifics workspace_desk = 874841;
+ WebauthnCredentialSpecifics webauthn_credential = 895275;
+ HistorySpecifics history = 963985;
+ PrintersAuthorizationServerSpecifics printers_authorization_server = 974304;
+ SavedTabGroupSpecifics saved_tab_group = 1004874;
+ AutofillWalletUsageSpecifics autofill_wallet_usage = 1033580;
+ ContactInfoSpecifics contact_info = 1034378;
+ IncomingPasswordSharingInvitationSpecifics
+ incoming_password_sharing_invitation = 1141935;
+ OutgoingPasswordSharingInvitationSpecifics
+ outgoing_password_sharing_invitation = 1142081;
+ AutofillWalletCredentialSpecifics autofill_wallet_credential = 1164238;
+ SharedTabGroupDataSpecifics shared_tab_group_data = 1239418;
+ CollaborationGroupSpecifics collaboration_group = 1259076;
+ ProductComparisonSpecifics product_comparison = 1329438;
+ PlusAddressSpecifics plus_address = 1267844;
+ CookieSpecifics cookie = 1281100;
+ PlusAddressSettingSpecifics plus_address_setting = 1303742;
+ AutofillValuableSpecifics autofill_valuable = 1419865;
+ SharedTabGroupAccountDataSpecifics shared_tab_group_account_data = 1429255;
+ SharedCommentSpecifics shared_comment = 1484017;
+ AutofillValuableSettingSpecifics autofill_valuable_setting = 1438954;
+ // When adding a new type, follow the docs below and keep this comment as
+ // the last entry.
+ // https://www.chromium.org/developers/design-documents/sync/integration-checklist/
+
+ // No-longer-supported data types, in various stages of removal.
+ // TODO(crbug.com/40881888): Eventually, these should all become "reserved"
+ // fields, or at least use "EmptySpecifics". But some of them are still
+ // needed by the server, e.g. to support older clients.
+ EmptySpecifics app_notification = 45184 [deprecated = true];
+ EmptySpecifics synced_notification = 153108 [deprecated = true];
+ EmptySpecifics synced_notification_app_info = 235816 [deprecated = true];
+ EmptySpecifics managed_user = 194582 [deprecated = true];
+ ManagedUserSharedSettingSpecifics managed_user_shared_setting = 202026
+ [deprecated = true];
+ EmptySpecifics managed_user_allowlist = 306060 [deprecated = true];
+ TypedUrlSpecifics typed_url = 40781 [deprecated = true];
+ }
+ reserved 161496;
+ reserved "experiments";
+ reserved 181534;
+ reserved "favicon_tracking";
+ reserved 182019;
+ reserved "favicon_image";
+ reserved 218175;
+ reserved "wifi_credential";
+ reserved 223759;
+ reserved "article";
+ reserved 545005;
+ reserved "mountain_share";
+ reserved 1026052;
+ reserved "segmentation";
+ reserved 1073150;
+ reserved "power_bookmark";
+}
+
+message EmptySpecifics {}
diff --git a/pyhindsight/lib/components/sync/protocol/extension_setting_specifics.proto b/pyhindsight/lib/components/sync/protocol/extension_setting_specifics.proto
new file mode 100644
index 0000000..d6c4958
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/extension_setting_specifics.proto
@@ -0,0 +1,29 @@
+// 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 datatype extension for an extension setting.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+// Properties of extension setting sync objects.
+message ExtensionSettingSpecifics {
+ // Id of the extension the setting is for.
+ optional string extension_id = 1;
+
+ // Setting key.
+ optional string key = 2;
+
+ // Setting value serialized as JSON.
+ optional string value = 3;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/extension_specifics.proto b/pyhindsight/lib/components/sync/protocol/extension_specifics.proto
new file mode 100644
index 0000000..e72c9d7
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/extension_specifics.proto
@@ -0,0 +1,64 @@
+// 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 datatype extension for extensions.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+// Properties of extension sync objects.
+//
+// Merge policy: the settings for the higher version number win; in
+// the case of a tie, server wins.
+message ExtensionSpecifics {
+ // Globally unique id for this extension.
+ optional string id = 1;
+ // The known installed version.
+ optional string version = 2;
+
+ // Auto-update URL to use for this extension. May be blank, in
+ // which case the default one (i.e., the one for the Chrome
+ // Extensions Gallery) is used.
+ optional string update_url = 3;
+ // Whether or not this extension is enabled.
+ // TODO(crbug.com/40554334): Deprecate this field. Enabled state can be
+ // determined from the disable reasons set.
+ optional bool enabled = 4;
+ // Whether or not this extension is enabled in incognito mode.
+ optional bool incognito_enabled = 5;
+
+ // DEPRECATED. See https://crbug.com/1233303.
+ optional string name = 6 [deprecated = true];
+
+ // Whether this extension was installed remotely, and hasn't been approved by
+ // a user in chrome yet.
+ optional bool remote_install = 7;
+
+ // DEPRECATED. See https://crbug.com/1014183.
+ optional bool installed_by_custodian = 8 [deprecated = true];
+
+ // DEPRECATED. See https://crbug.com/839681.
+ optional bool all_urls_enabled = 9 [deprecated = true];
+
+ // Bitmask of the set of reasons why the extension is disabled (see
+ // extensions::disable_reason::DisableReason). Only relevant when enabled ==
+ // false. Note that old clients (?[\]^`{|}'. The space
+// character is encoded as '%20'.
+
+// A simple example of PasswordSpecificsData, as created by Chrome for a web
+// form that the user submitted. E.g. federated credentials or credentials for
+// Android apps may have different fields set.
+// PasswordSpecificsData {
+// action: "https://example.com/",
+// avatar_url: "",
+// blacklisted: false,
+// date_created: 13305119271948046,
+// date_last_used: 13305119270102691,
+// date_password_modified_windows_epoch_micros: 13305119271949070,
+// display_name: "",
+// federation_url: "",
+// notes: {},
+// origin: "https://rsolomakhin.github.io/autofill/",
+// password_element: "password",
+// password_issues: {},
+// password_value: "pwd",
+// scheme: 0,
+// signon_realm: "https://rsolomakhin.github.io/",
+// times_used: 0,
+// type: 0,
+// username_element: "username",
+// username_value: "Superman"
+// }
+
+// All the strings are encoded with UTF-8. URLs are encoded in Punycode.
+message PasswordIssues {
+ message PasswordIssue {
+ // Timestamp set by a client detecting the issue for the first time.
+ // Number of microseconds since Windows epoch (1601).
+ // This can be unset even if is_muted is set in a few cases in
+ // storage (for a time mutes were written without setting this
+ // field - fixed starting 2021-11-10).
+ optional uint64 date_first_detection_windows_epoch_micros = 1;
+
+ // Whether the issue was muted by user.
+ optional bool is_muted = 2;
+
+ // Whether the backend should notify the user about this issue.
+ // Set to true if the user hasn't already seen a client notification for
+ // this issue (e.g. a leak detection prompt in Chrome). The backend sending
+ // notifications does not reset this field. All other sources can write this
+ // in both `PasswordSpecificsData` and `PasswordSpecificsMetadata` and do
+ // so.
+ optional bool trigger_notification_from_backend_on_detection = 3;
+ }
+ optional PasswordIssue leaked_password_issue = 1;
+ optional PasswordIssue reused_password_issue = 2;
+ optional PasswordIssue weak_password_issue = 3;
+ optional PasswordIssue phished_password_issue = 4;
+}
+
+message PasswordSpecificsData {
+ // The different types of the saved credential.
+ enum Scheme {
+ // SCHEME_HTML, the credential represents either a parsed HTML form, or an
+ // android credential or a password saved through Credential Management API
+ // (https://w3c.github.io/webappsec/specs/credentialmanagement/).
+ SCHEME_HTML = 0;
+ // SCHEME_BASIC, basic access http authentication.
+ SCHEME_BASIC = 1;
+ // SCHEME_DIGEST, digest access authentication.
+ SCHEME_DIGEST = 2;
+ // SCHEME_OTHER, another proxy access authentication.
+ SCHEME_OTHER = 3;
+ // USERNAME_ONLY, partial credentials saved on Android that contain only
+ // username and miss the password.
+ USERNAME_ONLY = 4;
+ }
+ // See the enum above.
+ optional int32 scheme = 1;
+
+ // Signon realm stores information on where the saved password was stored, and
+ // where it's supposed to be filled again.
+ //
+ // It can take various formats depending on the exact circumstances where it
+ // was recorded. Note that the format is *not* guaranteed to be a valid URL or
+ // URI:
+ //
+ // * For parsed web forms and normal passwords saved through Credential
+ // Manager
+ // API: ://[:]/
+ //
+ // where
+ // is one of "http" or "https"
+ // is the host for which the password was stored
+ // is the option port on the host
+ // The signon realm is a valid URL in this case with an empty path.
+ // Examples:
+ // http://www.example.com/
+ // https://127.0.0.1/
+ // http://www.google.com:8080/
+ // http://192.168.1.254/
+ // https://accounts.google.com/
+ //
+ // * For Android apps saved through Autofill with Google:
+ // android://@/
+ // where
+ // is the base64 encoded SHA512 of the app's public
+ // certificate is the app's package name
+ // Examples:
+ // android://kCyQDzpaoAX2gs-1zdGPKNAeICb8LzRFOxa4NCq0jO8c8d_NFS_q-Y35bU3Nq3GmFV2lLurmNvIZa6YPYZwmWg==@com.pinterest/
+ // android://mNUCvTnoWBkzIhSSkVj-uzAdK42YagmCmyUtPoC6JPmYAN3wKpmTdIRsdJtz6pzNBye8XL7nBbEcx-y9CJeo9A==@com.twitter.android.lite/
+ //
+ // * For federated credentials:
+ // federation:///
+ // where
+ // is the host for which the login information was stored
+ // is the host of the federation provider that was
+ // used to sign in
+ // Examples:
+ // federation://www.example.com/accounts.google.com
+ // federation://uk.trustpilot.com/www.facebook.com
+ //
+ // * For proxy auth:
+ // [:]/
+ // where
+ // is the host of the proxy for which the password was
+ // stored
+ // is the port of the proxy
+ // is a string provided by the proxy during authentication.
+ // It can contain spaces.
+ // Examples:
+ // proxy2.eq.edu.au:80/MISldap
+ // proxy.det.nsw.edu.au:8080/NSW Department of Education
+ // 10.47.2.250:3128/Squid Proxy Server CPUT
+ // default.go2https.com:443/(******Get password from vpnso.com/account/
+ // *****)
+ //
+ // * For HTTP basic auth:
+ // ://[:]/
+ // where
+ // is one of "http" or "https"
+ // is the host for which the password was stored
+ // is the option port on the host
+ // is a string provided by the host during authentication.
+ // It can contain spaces.
+ // Examples:
+ // http://192.168.1.1/Broadband Router
+ // http://192.168.0.1/TP-LINK Wireless N Router WR841N
+ // http://192.168.1.1/index.htm
+ // https://www.edge.asic.gov.au/ASIC eBusiness
+ optional string signon_realm = 2;
+
+ // For parsed web forms and Credential Management API:
+ // url-scheme://url-host[:url-port]/path
+ // For Android: "android://@/"
+ // For proxy/HTTP auth: url-scheme://url-host[:url-port]/path
+ optional string origin = 3;
+
+ // Only for web-parsed forms - the action target of the form:
+ // url-scheme://url-host[:url-port]/path
+ optional string action = 4;
+
+ // Only for web-parsed forms - the name of the element containing username.
+ optional string username_element = 5;
+
+ // For all: the username.
+ // For blacklisted forms: .
+ optional string username_value = 6;
+
+ // Only for web-parsed forms - the name of the element containing password.
+ optional string password_element = 7;
+
+ // For all: the password.
+ // For federated logins and blacklisted forms:
+ optional string password_value = 8;
+
+ // Deprecated: http://crbug.com/413020
+ // True if the credential was saved for a HTTPS session with a valid SSL cert.
+ // Ignored for Android apps.
+ optional bool ssl_valid = 9 [deprecated = true];
+
+ // True for the last credential used for logging in on a given site.
+ // Deprecated in M81.
+ optional bool preferred = 10 [deprecated = true];
+
+ // Time when the credential was created. Amount of microseconds since 1601.
+ optional int64 date_created = 11;
+
+ // True, if user chose permanently not to save the credentials for the form.
+ optional bool blacklisted = 12;
+
+ // kFormSubmission(0), user manually filled the username and the password
+ // in the form.
+ // kGenerated(1), the credential was auto generated.
+ // kApi(2), the credential was generated from Credential Management API.
+ // kManuallyAdded(3), user manually created the password credential
+ // via Settings.
+ // kImported(4), the credential was imported using the import flow.
+ // kReceivedViaSharing(5), the credential has been received via the password
+ // sharing feature.
+ optional int32 type = 13;
+
+ // Number of times this login was used for logging in using an HTML form.
+ // Chrome uses this field to distinguish log-in and sign-up forms.
+ optional int32 times_used = 14;
+
+ // A human readable name of the account holder. Set by CredentialManager API
+ // and Android.
+ optional string display_name = 15;
+
+ // A URL of the avatar for the credential. Set by CredentialManager API and
+ // Android.
+ optional string avatar_url = 16;
+
+ // A URL of the IdP used to verify the credential. Set by Credential Manager
+ // API and Android.
+ optional string federation_url = 17;
+
+ // Time when the credential was last used. This covers *successful* logins to
+ // the website, and explicit updates to the password. It does *not* cover if
+ // the password just gets filled but not actually submitted, or if the login
+ // failed (see `date_last_filled_windows_epoch_micros` for that).
+ // Note that password consumers other than Chrome (e.g. Google Play Services)
+ // might not update this at all.
+ // Amount of microseconds since 1601, aka Windows epoch.
+ optional int64 date_last_used = 18;
+
+ // Set if an issue was detected that puts this password at risk. All the
+ // clients are expected to clear the field when the password value is updated.
+ // 'reused' part can be additionally reset when the analysis on the entire
+ // password store is completed.
+ optional PasswordIssues password_issues = 19;
+
+ // Time when the `password_value` was last modified. For new credentials it
+ // should be set to `date_created`. For subsequent updates the timestamp is
+ // changed if and only if the new password value was saved.
+ // Number of microseconds since Windows epoch (1601).
+ optional int64 date_password_modified_windows_epoch_micros = 20;
+
+ message Notes {
+ message Note {
+ // The display name must be unique within the scope of a password.
+ optional string unique_display_name = 1;
+ // The user-defined value of the note.
+ optional string value = 2;
+ // The creation time of the note. Number of microseconds since 1601.
+ optional int64 date_created_windows_epoch_micros = 3;
+ // Whether the value of the note is not displayed in plain text by
+ // default.
+ optional bool hide_by_default = 4;
+ }
+ repeated Note note = 1;
+ }
+ reserved 21;
+ // Set of extra notes that the user attached to the password. The presence of
+ // this field, even with an empty Notes message, becomes the authoritative
+ // value for notes and would disregard whatever `encrypted_notes_backup`
+ // contains.
+ optional Notes notes = 22;
+
+ // For credentials that have been shared by another user, this field captures
+ // the sender email. It's empty for credentials that weren't received via
+ // password sharing feature.
+ optional string sender_email = 23;
+
+ // Similar to `sender_email` but for the sender name.
+ optional string sender_name = 24;
+
+ // The timestamp when the password was received via sharing feature from
+ // another user.
+ optional int64 date_received_windows_epoch_micros = 25;
+
+ // Whether the user has been already notified that they received this password
+ // from another user via the password sharing feature. This is synced to avoid
+ // showing the notification on multiple devices.
+ optional bool sharing_notification_displayed = 26;
+
+ // Similar to `sender_email` but for the url of the sender profile image.
+ optional string sender_profile_image_url = 27;
+
+ // Similar to `date_last_used` but covers when the password was last *filled*
+ // into a form (through autofill or other UI surfaces).
+ optional int64 date_last_filled_windows_epoch_micros = 28;
+}
+
+// Contains the password specifics metadata which simplifies its lookup.
+message PasswordSpecificsMetadata {
+ // The signon realm for the credential. For more details, see the
+ // `signon_realm` field in PasswordSpecificsData.
+ optional string url = 1;
+
+ // True, if user chose permanently not to save the credentials for the form.
+ // Introduced in M82. Copy from PasswordSpecificsData.blacklisted.
+ optional bool blacklisted = 2;
+
+ // Copy from PasswordSpecificsData.date_last_used.
+ // Introduced in M112.
+ optional int64 date_last_used_windows_epoch_micros = 3;
+
+ // Copy from PasswordSpecificsData.password_issues. Introduced in M114.
+ optional PasswordIssues password_issues = 4;
+
+ // Copy from PasswordSpecificsData.type. Introduced in M119.
+ optional int32 type = 13;
+}
+
+// Properties of password sync objects.
+message PasswordSpecifics {
+ // The actual password data. Contains an encrypted PasswordSpecificsData
+ // message.
+ optional EncryptedData encrypted = 1;
+ // An unsynced field for use internally on the client. This field should
+ // never be set in any network-based communications because it contains
+ // unencrypted material.
+ optional PasswordSpecificsData client_only_encrypted_data = 2;
+ // Password related metadata, which is sent to the server side. The field
+ // should never be set for full encryption users. If encryption is enabled,
+ // this field must be cleared.
+ optional PasswordSpecificsMetadata unencrypted_metadata = 3;
+ reserved 4;
+ // An encrypted backup of the notes field inside the PasswordSpecificsData.
+ // The Sync server preserves the contents of this field across commits from
+ // legacy clients that don't set this field. It is the responsibility of Sync
+ // clients to populate the contents of PasswordSpecificsData notes fields
+ // using the contents of this field. This should be deprecated together with
+ // the logic for preserving it on the server when clients without support for
+ // the `notes` field are no longer allowed by the server (below support
+ // version horizon).
+ //
+ // Encryption key considerations:
+ // a) For commits, the client must use the same key for both encrypted blobs.
+ // b) For handling getupdates, the two keys may NOT necessarily match the
+ // encryption key used, as in theory the new blob could be "behind" if key
+ // rotation took place. As of today, it is safe to assume that if
+ // `encrypted` is decryptable by a client, then `encrypted_notes_backup`
+ // must be decryptable too (i.e. the Nigori keybag should include older
+ // versions of the key). But not the other way round.
+ //
+ // If both `encrypted_notes_backup` and the `notes` in `encrypted` are
+ // populated, the one in notes is considered the authoritative value.
+ optional EncryptedData encrypted_notes_backup = 5;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/persisted_entity_data.proto b/pyhindsight/lib/components/sync/protocol/persisted_entity_data.proto
new file mode 100644
index 0000000..1a79925
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/persisted_entity_data.proto
@@ -0,0 +1,26 @@
+// Copyright 2018 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+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/entity_specifics.proto";
+
+// Sync proto to store entity data similar to what the legacy Directory used
+// to store, used to persist data locally and never sent through the wire.
+//
+// Because it's conceptually similar to SyncEntity (actual protocol) and it's
+// unclear how big this'll grow, we've kept compatibility with SyncEntity by
+// using the same field numbers.
+message PersistedEntityData {
+ // See corresponding fields in SyncEntity for details.
+ optional string name = 8;
+ optional EntitySpecifics specifics = 21;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/plus_address_setting_specifics.proto b/pyhindsight/lib/components/sync/protocol/plus_address_setting_specifics.proto
new file mode 100644
index 0000000..e19a847
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/plus_address_setting_specifics.proto
@@ -0,0 +1,27 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+// Used to sync settings for `PLUS_ADDRESS`. Since these settings originate from
+// the user's account, they are not reusing standard syncable prefs.
+message PlusAddressSettingSpecifics {
+ optional string name = 1;
+ // The value of the setting. Which variant is set depends on the setting.
+ oneof Value {
+ bool bool_value = 2;
+ string string_value = 3;
+ int64 int_value = 4;
+ }
+}
diff --git a/pyhindsight/lib/components/sync/protocol/plus_address_specifics.proto b/pyhindsight/lib/components/sync/protocol/plus_address_specifics.proto
new file mode 100644
index 0000000..088dc61
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/plus_address_specifics.proto
@@ -0,0 +1,27 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+message PlusAddressSpecifics {
+ // A stable, unique identifier, generated by the PlusAddress backend.
+ optional string profile_id = 1;
+ // The origin that the `plus_email` is generated for.
+ optional string facet = 2;
+ optional PlusEmail plus_email = 3;
+}
+
+message PlusEmail {
+ optional string email_address = 1;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/power_bookmark_specifics.proto b/pyhindsight/lib/components/sync/protocol/power_bookmark_specifics.proto
new file mode 100644
index 0000000..ac892c3
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/power_bookmark_specifics.proto
@@ -0,0 +1,57 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+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/note_entity.proto";
+
+// Data structure dedicated to each power type.
+// Should keep the field numbers of specifics in sync with the ones in PowerType
+// below.
+message PowerEntity {
+ oneof entity {
+ // Used for notes.
+ NoteEntity note_entity = 2;
+ }
+}
+
+message PowerBookmarkSpecifics {
+ // PowerType is persisted to disk and therefore shouldn't be reoderered or
+ // changed.
+ // Should keep the field numbers of PowerType in sync with the ones in
+ // entity above.
+ enum PowerType {
+ // All powers should have type so this should be unused.
+ POWER_TYPE_UNSPECIFIED = 0;
+ // Used for testing.
+ POWER_TYPE_MOCK = 1;
+ // Used for notes.
+ POWER_TYPE_NOTE = 2;
+ }
+
+ // The primary key for local storage.
+ /* required */ optional string guid = 1;
+
+ // Powers associated with a URL.
+ /* required */ optional string url = 2;
+
+ // Tracks the type of the power.
+ /* required */ optional PowerType power_type = 3;
+
+ // Tracks when this was added.
+ /* required */ optional int64 creation_time_usec = 4;
+
+ // Tracks when this was last modified.
+ /* required */ optional int64 update_time_usec = 5;
+
+ // Power entity.
+ /* required */ optional PowerEntity power_entity = 100;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/preference_specifics.proto b/pyhindsight/lib/components/sync/protocol/preference_specifics.proto
new file mode 100644
index 0000000..98bad40
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/preference_specifics.proto
@@ -0,0 +1,23 @@
+// 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 datatype extension for preferences.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+// Properties of preference sync objects.
+message PreferenceSpecifics {
+ optional string name = 1;
+ optional string value = 2;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/prepare_full_proto.py b/pyhindsight/lib/components/sync/protocol/prepare_full_proto.py
new file mode 100644
index 0000000..ca0d88b
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/prepare_full_proto.py
@@ -0,0 +1,86 @@
+# Copyright 2025 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import re
+import sys
+
+
+def process_proto_file(input_path, output_path, local_import_basenames):
+ """Reads an input .proto file and writes a processed version.
+
+ Transformations:
+ 1. Removes 'option optimize_for = LITE_RUNTIME;'.
+ 2. Uncomments blocks between '// copybara:uncomment_begin/end'.
+ 3. Rewrites any import statement that points to another file being processed
+ in the same batch to use the "_full_proto.proto" suffix.
+ """
+ # Regex to find and capture the path in an import statement.
+ import_regex = re.compile(r'import\s+"([^"]+\.proto)"')
+
+ # Ensure the output directory exists.
+ os.makedirs(os.path.dirname(output_path), exist_ok=True)
+
+ with open(input_path, "r") as f_in, open(output_path, "w") as f_out:
+ in_annotation_block = False
+ for line in f_in:
+ # Rule 1: Remove LITE_RUNTIME option.
+ if "option optimize_for = LITE_RUNTIME;" in line:
+ continue
+
+ # Rule 2: Handle annotation blocks.
+ if "copybara:uncomment_begin" in line:
+ in_annotation_block = True
+ continue
+ if "copybara:uncomment_end" in line:
+ in_annotation_block = False
+ continue
+
+ # If we are in an annotation block, uncomment the line before
+ # further processing.
+ if in_annotation_block:
+ line = re.sub(r"^(\s*)//\s?(.*)$", r"\1\2", line)
+
+ # Rule 3: Rewrite local imports to use the "_full_proto" suffix.
+ match = import_regex.search(line)
+ # Check if this line is an import and if the file it imports is one
+ # of the other files we are processing in this batch.
+ if match and os.path.basename(match.group(1)) in local_import_basenames:
+ original_import_path = match.group(1)
+ new_import_path = original_import_path.replace(
+ ".proto", "_full_proto.proto"
+ )
+ line = f'import "{new_import_path}";\n'
+
+ f_out.write(line)
+
+
+def main():
+ """Main function to handle command-line arguments.
+
+ It now correctly parses the arguments provided by the BUILD.gn action.
+ """
+ if len(sys.argv) < 3:
+ print(
+ "Usage: python3 prepare_full_proto.py "
+ " ..."
+ )
+ sys.exit(1)
+
+ output_dir = sys.argv[1]
+
+ input_paths = sys.argv[2:]
+
+ local_import_basenames = {os.path.basename(p) for p in input_paths}
+
+ for input_path in input_paths:
+ output_basename = os.path.basename(input_path).replace(
+ ".proto", "_full_proto.proto"
+ )
+ output_path = os.path.join(output_dir, output_basename)
+ process_proto_file(input_path, output_path, local_import_basenames)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/pyhindsight/lib/components/sync/protocol/printer_specifics.proto b/pyhindsight/lib/components/sync/protocol/printer_specifics.proto
new file mode 100644
index 0000000..e202605
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/printer_specifics.proto
@@ -0,0 +1,81 @@
+// Copyright 2016 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 datatype extension for printer data.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+// User PPD configuration
+message PrinterPPDReference {
+ // Url for user provided file. Overrides other fields.
+ optional string user_supplied_ppd_url = 1;
+
+ // Retired fields
+ optional string effective_manufacturer = 2 [deprecated = true];
+ optional string effective_model = 3 [deprecated = true];
+
+ // String identifying the type of printer, used to look up a ppd to drive the
+ // printer.
+ optional string effective_make_and_model = 4;
+
+ // True if the printer should be automatically configured, false otherwise.
+ optional bool autoconf = 5 [default = false];
+}
+
+message PrinterSpecifics {
+ // Printer record GUID
+ optional string id = 1;
+
+ // User visible name. Any string.
+ optional string display_name = 2;
+
+ // User visible description. Any string.
+ optional string description = 3;
+
+ // Printer manufacturer. Should be a known manufacturuer.
+ // Deprecated in favor of make_and_model.
+ optional string manufacturer = 4 [deprecated = true];
+
+ // Printer model. Should match a known model for the manufacturer.
+ // Deprecated in favor of make_and_model.
+ optional string model = 5 [deprecated = true];
+
+ // Universal Resource Identifier for the printer on the network. usb:// will
+ // be the scheme for USB printers. Example
+ // ipp://address.example:port/queue/queue/queue.
+ optional string uri = 6;
+
+ // Universally Unique Identifier provided by the printer. Used for unique
+ // identification of printers in a zeroconf environment.
+ optional string uuid = 7;
+
+ // PPDData was deprecated in favor of PPDReference format.
+ optional bytes ppd = 8 [deprecated = true];
+
+ // Structure representing the user's ppd configuration.
+ optional PrinterPPDReference ppd_reference = 9;
+
+ // Timestamp when printer was last updated.
+ optional int64 updated_timestamp = 10;
+
+ // The make and model of the printer in one string. The typical arrangement
+ // for this is ''. This aligns with the typical formatting of
+ // the IPP attribute printer-make-and-model.
+ optional string make_and_model = 11;
+
+ // Universal Resource Identifier for the print server on the network. This
+ // will only be populated if the printer is from a print server. Example
+ // ipp://address.example:port/
+ optional string print_server_uri = 12;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/printers_authorization_server_specifics.proto b/pyhindsight/lib/components/sync/protocol/printers_authorization_server_specifics.proto
new file mode 100644
index 0000000..c73b72e
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/printers_authorization_server_specifics.proto
@@ -0,0 +1,25 @@
+// Copyright 2022 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 datatype extension for printer data.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+// Represents trusted Authorization Server for printers.
+message PrintersAuthorizationServerSpecifics {
+ // Universal Resource Identifier for the authorization server on the network.
+ // The scheme must be https. Example: https://address.example:port/path/path.
+ // This field must be unique and is required.
+ optional string uri = 1;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/priority_preference_specifics.proto b/pyhindsight/lib/components/sync/protocol/priority_preference_specifics.proto
new file mode 100644
index 0000000..d31cda2
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/priority_preference_specifics.proto
@@ -0,0 +1,24 @@
+// 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 datatype extension for priority preferences.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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/preference_specifics.proto";
+
+// Properties of a synced priority preference.
+message PriorityPreferenceSpecifics {
+ optional PreferenceSpecifics preference = 1;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/product_comparison_specifics.proto b/pyhindsight/lib/components/sync/protocol/product_comparison_specifics.proto
new file mode 100644
index 0000000..a4454e0
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/product_comparison_specifics.proto
@@ -0,0 +1,74 @@
+// Copyright 2024 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 datatype extension for compare.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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/unique_position.proto";
+
+// A Product Comparison sync entity, containing sufficient data to enable all
+// data acquisition for rendering the Compare experience.
+message ProductComparisonSpecifics {
+ // The primary key for local storage.
+ optional string uuid = 1;
+
+ // Tracks when this entity was created (milliseconds since epoch).
+ optional int64 creation_time_unix_epoch_millis = 2;
+
+ // Tracks when this entity was last modified (milliseconds since epoch).
+ optional int64 update_time_unix_epoch_millis = 3;
+
+ // The name of the comparison group. Will de deprecated in favor of
+ // ProductComparison#name.
+ optional string name = 4;
+
+ // The list of product URLs that constitute this comparison group. Will be
+ // deprecated in favor of ProductComparisonItem#url.
+ repeated ComparisonData data = 5;
+
+ // For splitting out a Product Comparison into multiple specifics.
+ oneof entity {
+ ProductComparison product_comparison = 6;
+ ProductComparisonItem product_comparison_item = 7;
+ }
+}
+
+message ComparisonData {
+ // The URL of the item in the comparison.
+ optional string url = 1;
+}
+
+// Product Comparison specific - top level data about the product comparison.
+message ProductComparison {
+ // Name of this Product Comparison
+ optional string name = 1;
+}
+
+// Product Comparison Item specific - data about one item in the product
+// comparison.
+message ProductComparisonItem {
+ // Identifier of top level ProductComparison specifics this item belongs to
+ optional string product_comparison_uuid = 1;
+
+ // URL for product comparison.
+ optional string url = 2;
+
+ // Ensures unique ordering among items in a product comparison. This is
+ // necessary because the ProductComparisonItems point to a ProductComparison
+ // and not the opposite, so we need to explicitly define the ordering.
+ optional UniquePosition unique_position = 3;
+
+ // Title for the URL for the product comparison item.
+ optional string title = 4;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/proto_enum_conversions.cc b/pyhindsight/lib/components/sync/protocol/proto_enum_conversions.cc
new file mode 100644
index 0000000..9eae644
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/proto_enum_conversions.cc
@@ -0,0 +1,1092 @@
+// 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.
+
+#include "components/sync/protocol/proto_enum_conversions.h"
+
+#include "base/logging.h"
+#include "base/notreached.h"
+
+namespace syncer {
+
+#define ASSERT_ENUM_BOUNDS(enum_parent, enum_type, enum_min, enum_max) \
+ static_assert(enum_parent::enum_type##_MIN == enum_parent::enum_min, \
+ #enum_type "_MIN should be " #enum_min); \
+ static_assert(enum_parent::enum_type##_MAX == enum_parent::enum_max, \
+ #enum_type "_MAX should be " #enum_max);
+
+#define ENUM_CASE(enum_parent, enum_value) \
+ case enum_parent::enum_value: \
+ return #enum_value
+
+const char* ProtoEnumToString(
+ sync_pb::AppListSpecifics::AppListItemType item_type) {
+ ASSERT_ENUM_BOUNDS(sync_pb::AppListSpecifics, AppListItemType, TYPE_APP,
+ TYPE_PAGE_BREAK);
+ switch (item_type) {
+ ENUM_CASE(sync_pb::AppListSpecifics, TYPE_APP);
+ ENUM_CASE(sync_pb::AppListSpecifics, TYPE_REMOVE_DEFAULT_APP);
+ ENUM_CASE(sync_pb::AppListSpecifics, TYPE_FOLDER);
+ ENUM_CASE(sync_pb::AppListSpecifics, TYPE_OBSOLETE_URL);
+ ENUM_CASE(sync_pb::AppListSpecifics, TYPE_PAGE_BREAK);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(sync_pb::AppSpecifics::LaunchType launch_type) {
+ ASSERT_ENUM_BOUNDS(sync_pb::AppSpecifics, LaunchType, PINNED, WINDOW);
+ switch (launch_type) {
+ ENUM_CASE(sync_pb::AppSpecifics, PINNED);
+ ENUM_CASE(sync_pb::AppSpecifics, REGULAR);
+ ENUM_CASE(sync_pb::AppSpecifics, FULLSCREEN);
+ ENUM_CASE(sync_pb::AppSpecifics, WINDOW);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::AutofillProfileSpecifics::VerificationStatus status) {
+ ASSERT_ENUM_BOUNDS(sync_pb::AutofillProfileSpecifics, VerificationStatus,
+ VERIFICATION_STATUS_UNSPECIFIED, SERVER_PARSED);
+ switch (status) {
+ ENUM_CASE(sync_pb::AutofillProfileSpecifics,
+ VERIFICATION_STATUS_UNSPECIFIED);
+ ENUM_CASE(sync_pb::AutofillProfileSpecifics, PARSED);
+ ENUM_CASE(sync_pb::AutofillProfileSpecifics, FORMATTED);
+ ENUM_CASE(sync_pb::AutofillProfileSpecifics, OBSERVED);
+ ENUM_CASE(sync_pb::AutofillProfileSpecifics, USER_VERIFIED);
+ ENUM_CASE(sync_pb::AutofillProfileSpecifics, SERVER_PARSED);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::AutofillWalletSpecifics::WalletInfoType wallet_info_type) {
+ ASSERT_ENUM_BOUNDS(sync_pb::AutofillWalletSpecifics, WalletInfoType, UNKNOWN,
+ PAYMENT_INSTRUMENT_CREATION_OPTION);
+ switch (wallet_info_type) {
+ ENUM_CASE(sync_pb::AutofillWalletSpecifics, UNKNOWN);
+ ENUM_CASE(sync_pb::AutofillWalletSpecifics, MASKED_CREDIT_CARD);
+ ENUM_CASE(sync_pb::AutofillWalletSpecifics, POSTAL_ADDRESS);
+ ENUM_CASE(sync_pb::AutofillWalletSpecifics, CUSTOMER_DATA);
+ ENUM_CASE(sync_pb::AutofillWalletSpecifics, CREDIT_CARD_CLOUD_TOKEN_DATA);
+ ENUM_CASE(sync_pb::AutofillWalletSpecifics, PAYMENT_INSTRUMENT);
+ ENUM_CASE(sync_pb::AutofillWalletSpecifics, MASKED_IBAN);
+ ENUM_CASE(sync_pb::AutofillWalletSpecifics,
+ PAYMENT_INSTRUMENT_CREATION_OPTION);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::BankAccountDetails::AccountType account_type) {
+ ASSERT_ENUM_BOUNDS(sync_pb::BankAccountDetails, AccountType,
+ ACCOUNT_TYPE_UNSPECIFIED, TRANSACTING_ACCOUNT);
+ switch (account_type) {
+ ENUM_CASE(sync_pb::BankAccountDetails, ACCOUNT_TYPE_UNSPECIFIED);
+ ENUM_CASE(sync_pb::BankAccountDetails, CHECKING);
+ ENUM_CASE(sync_pb::BankAccountDetails, SAVINGS);
+ ENUM_CASE(sync_pb::BankAccountDetails, CURRENT);
+ ENUM_CASE(sync_pb::BankAccountDetails, SALARY);
+ ENUM_CASE(sync_pb::BankAccountDetails, TRANSACTING_ACCOUNT);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(sync_pb::BookmarkSpecifics::Type type) {
+ ASSERT_ENUM_BOUNDS(sync_pb::BookmarkSpecifics, Type, UNSPECIFIED, FOLDER);
+ switch (type) {
+ ENUM_CASE(sync_pb::BookmarkSpecifics, UNSPECIFIED);
+ ENUM_CASE(sync_pb::BookmarkSpecifics, URL);
+ ENUM_CASE(sync_pb::BookmarkSpecifics, FOLDER);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::CommitResponse::ResponseType response_type) {
+ ASSERT_ENUM_BOUNDS(sync_pb::CommitResponse, ResponseType, SUCCESS,
+ TRANSIENT_ERROR);
+ switch (response_type) {
+ ENUM_CASE(sync_pb::CommitResponse, SUCCESS);
+ ENUM_CASE(sync_pb::CommitResponse, CONFLICT);
+ ENUM_CASE(sync_pb::CommitResponse, RETRY);
+ ENUM_CASE(sync_pb::CommitResponse, INVALID_MESSAGE);
+ ENUM_CASE(sync_pb::CommitResponse, OVER_QUOTA);
+ ENUM_CASE(sync_pb::CommitResponse, TRANSIENT_ERROR);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::ContactInfoSpecifics::AddressType address_type) {
+ ASSERT_ENUM_BOUNDS(sync_pb::ContactInfoSpecifics, AddressType, REGULAR, WORK);
+ switch (address_type) {
+ ENUM_CASE(sync_pb::ContactInfoSpecifics, REGULAR);
+ ENUM_CASE(sync_pb::ContactInfoSpecifics, HOME);
+ ENUM_CASE(sync_pb::ContactInfoSpecifics, WORK);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::ContactInfoSpecifics::VerificationStatus verification_status) {
+ ASSERT_ENUM_BOUNDS(sync_pb::ContactInfoSpecifics, VerificationStatus,
+ VERIFICATION_STATUS_UNSPECIFIED, SERVER_PARSED);
+ switch (verification_status) {
+ ENUM_CASE(sync_pb::ContactInfoSpecifics, VERIFICATION_STATUS_UNSPECIFIED);
+ ENUM_CASE(sync_pb::ContactInfoSpecifics, PARSED);
+ ENUM_CASE(sync_pb::ContactInfoSpecifics, FORMATTED);
+ ENUM_CASE(sync_pb::ContactInfoSpecifics, OBSERVED);
+ ENUM_CASE(sync_pb::ContactInfoSpecifics, USER_VERIFIED);
+ ENUM_CASE(sync_pb::ContactInfoSpecifics, SERVER_PARSED);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::TrustedVaultAutoUpgradeExperimentGroup::Type type) {
+ ASSERT_ENUM_BOUNDS(sync_pb::TrustedVaultAutoUpgradeExperimentGroup, Type,
+ TYPE_UNSPECIFIED, VALIDATION);
+
+ switch (type) {
+ ENUM_CASE(sync_pb::TrustedVaultAutoUpgradeExperimentGroup,
+ TYPE_UNSPECIFIED);
+ ENUM_CASE(sync_pb::TrustedVaultAutoUpgradeExperimentGroup, TREATMENT);
+ ENUM_CASE(sync_pb::TrustedVaultAutoUpgradeExperimentGroup, CONTROL);
+ ENUM_CASE(sync_pb::TrustedVaultAutoUpgradeExperimentGroup, VALIDATION);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(sync_pb::NigoriSpecifics::PassphraseType type) {
+ ASSERT_ENUM_BOUNDS(sync_pb::NigoriSpecifics, PassphraseType, UNKNOWN,
+ TRUSTED_VAULT_PASSPHRASE);
+ switch (type) {
+ ENUM_CASE(sync_pb::NigoriSpecifics, UNKNOWN);
+ ENUM_CASE(sync_pb::NigoriSpecifics, IMPLICIT_PASSPHRASE);
+ ENUM_CASE(sync_pb::NigoriSpecifics, KEYSTORE_PASSPHRASE);
+ ENUM_CASE(sync_pb::NigoriSpecifics, FROZEN_IMPLICIT_PASSPHRASE);
+ ENUM_CASE(sync_pb::NigoriSpecifics, CUSTOM_PASSPHRASE);
+ ENUM_CASE(sync_pb::NigoriSpecifics, TRUSTED_VAULT_PASSPHRASE);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::PaymentInstrument::SupportedRail supported_rail) {
+ ASSERT_ENUM_BOUNDS(sync_pb::PaymentInstrument, SupportedRail,
+ SUPPORTED_RAIL_UNKNOWN, CARD_NUMBER);
+ switch (supported_rail) {
+ ENUM_CASE(sync_pb::PaymentInstrument, SUPPORTED_RAIL_UNKNOWN);
+ ENUM_CASE(sync_pb::PaymentInstrument, PIX);
+ ENUM_CASE(sync_pb::PaymentInstrument, IBAN);
+ ENUM_CASE(sync_pb::PaymentInstrument, PAYMENT_HYPERLINK);
+ ENUM_CASE(sync_pb::PaymentInstrument, CARD_NUMBER);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::PaymentInstrument::ActionRequired action_required) {
+ ASSERT_ENUM_BOUNDS(sync_pb::PaymentInstrument, ActionRequired,
+ ACTION_REQUIRED_UNKNOWN, ACCEPT_TOS);
+ switch (action_required) {
+ ENUM_CASE(sync_pb::PaymentInstrument, ACTION_REQUIRED_UNKNOWN);
+ ENUM_CASE(sync_pb::PaymentInstrument, ACCEPT_TOS);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::PowerBookmarkSpecifics::PowerType power_type) {
+ ASSERT_ENUM_BOUNDS(sync_pb::PowerBookmarkSpecifics, PowerType,
+ POWER_TYPE_UNSPECIFIED, POWER_TYPE_NOTE);
+ switch (power_type) {
+ ENUM_CASE(sync_pb::PowerBookmarkSpecifics, POWER_TYPE_UNSPECIFIED);
+ ENUM_CASE(sync_pb::PowerBookmarkSpecifics, POWER_TYPE_MOCK);
+ ENUM_CASE(sync_pb::PowerBookmarkSpecifics, POWER_TYPE_NOTE);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(sync_pb::NoteEntity::TargetType target_type) {
+ ASSERT_ENUM_BOUNDS(sync_pb::NoteEntity, TargetType, TARGET_TYPE_UNSPECIFIED,
+ TARGET_TYPE_PAGE);
+ switch (target_type) {
+ ENUM_CASE(sync_pb::NoteEntity, TARGET_TYPE_UNSPECIFIED);
+ ENUM_CASE(sync_pb::NoteEntity, TARGET_TYPE_PAGE);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::ReadingListSpecifics::ReadingListEntryStatus status) {
+ ASSERT_ENUM_BOUNDS(sync_pb::ReadingListSpecifics, ReadingListEntryStatus,
+ UNREAD, UNSEEN);
+ switch (status) {
+ ENUM_CASE(sync_pb::ReadingListSpecifics, UNREAD);
+ ENUM_CASE(sync_pb::ReadingListSpecifics, READ);
+ ENUM_CASE(sync_pb::ReadingListSpecifics, UNSEEN);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::SavedTabGroup::SavedTabGroupColor color) {
+ ASSERT_ENUM_BOUNDS(sync_pb::SavedTabGroup, SavedTabGroupColor,
+ SAVED_TAB_GROUP_COLOR_UNSPECIFIED,
+ SAVED_TAB_GROUP_COLOR_ORANGE);
+ switch (color) {
+ ENUM_CASE(sync_pb::SavedTabGroup, SAVED_TAB_GROUP_COLOR_UNSPECIFIED);
+ ENUM_CASE(sync_pb::SavedTabGroup, SAVED_TAB_GROUP_COLOR_GREY);
+ ENUM_CASE(sync_pb::SavedTabGroup, SAVED_TAB_GROUP_COLOR_BLUE);
+ ENUM_CASE(sync_pb::SavedTabGroup, SAVED_TAB_GROUP_COLOR_RED);
+ ENUM_CASE(sync_pb::SavedTabGroup, SAVED_TAB_GROUP_COLOR_YELLOW);
+ ENUM_CASE(sync_pb::SavedTabGroup, SAVED_TAB_GROUP_COLOR_GREEN);
+ ENUM_CASE(sync_pb::SavedTabGroup, SAVED_TAB_GROUP_COLOR_PINK);
+ ENUM_CASE(sync_pb::SavedTabGroup, SAVED_TAB_GROUP_COLOR_PURPLE);
+ ENUM_CASE(sync_pb::SavedTabGroup, SAVED_TAB_GROUP_COLOR_CYAN);
+ ENUM_CASE(sync_pb::SavedTabGroup, SAVED_TAB_GROUP_COLOR_ORANGE);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::SearchEngineSpecifics::ActiveStatus is_active) {
+ ASSERT_ENUM_BOUNDS(sync_pb::SearchEngineSpecifics, ActiveStatus,
+ ACTIVE_STATUS_UNSPECIFIED, ACTIVE_STATUS_FALSE);
+ switch (is_active) {
+ ENUM_CASE(sync_pb::SearchEngineSpecifics, ACTIVE_STATUS_UNSPECIFIED);
+ ENUM_CASE(sync_pb::SearchEngineSpecifics, ACTIVE_STATUS_TRUE);
+ ENUM_CASE(sync_pb::SearchEngineSpecifics, ACTIVE_STATUS_FALSE);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(sync_pb::SessionTab::FaviconType favicon_type) {
+ ASSERT_ENUM_BOUNDS(sync_pb::SessionTab, FaviconType, TYPE_WEB_FAVICON,
+ TYPE_WEB_FAVICON);
+ switch (favicon_type) { ENUM_CASE(sync_pb::SessionTab, TYPE_WEB_FAVICON); }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(sync_pb::SharedTabGroup::Color color) {
+ ASSERT_ENUM_BOUNDS(sync_pb::SharedTabGroup, Color, UNSPECIFIED, ORANGE);
+ switch (color) {
+ ENUM_CASE(sync_pb::SharedTabGroup, UNSPECIFIED);
+ ENUM_CASE(sync_pb::SharedTabGroup, GREY);
+ ENUM_CASE(sync_pb::SharedTabGroup, BLUE);
+ ENUM_CASE(sync_pb::SharedTabGroup, RED);
+ ENUM_CASE(sync_pb::SharedTabGroup, YELLOW);
+ ENUM_CASE(sync_pb::SharedTabGroup, GREEN);
+ ENUM_CASE(sync_pb::SharedTabGroup, PINK);
+ ENUM_CASE(sync_pb::SharedTabGroup, PURPLE);
+ ENUM_CASE(sync_pb::SharedTabGroup, CYAN);
+ ENUM_CASE(sync_pb::SharedTabGroup, ORANGE);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(sync_pb::SyncEnums::BrowserType browser_type) {
+ ASSERT_ENUM_BOUNDS(sync_pb::SyncEnums, BrowserType, BROWSER_TYPE_UNKNOWN,
+ TYPE_AUTH_TAB);
+ switch (browser_type) {
+ ENUM_CASE(sync_pb::SyncEnums, BROWSER_TYPE_UNKNOWN);
+ ENUM_CASE(sync_pb::SyncEnums, TYPE_TABBED);
+ ENUM_CASE(sync_pb::SyncEnums, TYPE_POPUP);
+ ENUM_CASE(sync_pb::SyncEnums, TYPE_CUSTOM_TAB);
+ ENUM_CASE(sync_pb::SyncEnums, TYPE_AUTH_TAB);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(sync_pb::SyncEnums::Action action) {
+ ASSERT_ENUM_BOUNDS(sync_pb::SyncEnums, Action, UPGRADE_CLIENT,
+ UNKNOWN_ACTION);
+ switch (action) {
+ ENUM_CASE(sync_pb::SyncEnums, UPGRADE_CLIENT);
+ ENUM_CASE(sync_pb::SyncEnums, UNKNOWN_ACTION);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(sync_pb::SyncEnums::DeviceType device_type) {
+ ASSERT_ENUM_BOUNDS(sync_pb::SyncEnums, DeviceType, TYPE_UNSET, TYPE_TABLET);
+ switch (device_type) {
+ ENUM_CASE(sync_pb::SyncEnums, TYPE_UNSET);
+ ENUM_CASE(sync_pb::SyncEnums, TYPE_WIN);
+ ENUM_CASE(sync_pb::SyncEnums, TYPE_MAC);
+ ENUM_CASE(sync_pb::SyncEnums, TYPE_LINUX);
+ ENUM_CASE(sync_pb::SyncEnums, TYPE_CROS);
+ ENUM_CASE(sync_pb::SyncEnums, TYPE_OTHER);
+ ENUM_CASE(sync_pb::SyncEnums, TYPE_PHONE);
+ ENUM_CASE(sync_pb::SyncEnums, TYPE_TABLET);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(sync_pb::SyncEnums::OsType os_type) {
+ ASSERT_ENUM_BOUNDS(sync_pb::SyncEnums, OsType, OS_TYPE_UNSPECIFIED,
+ OS_TYPE_FUCHSIA);
+ switch (os_type) {
+ ENUM_CASE(sync_pb::SyncEnums, OS_TYPE_UNSPECIFIED);
+ ENUM_CASE(sync_pb::SyncEnums, OS_TYPE_WINDOWS);
+ ENUM_CASE(sync_pb::SyncEnums, OS_TYPE_MAC);
+ ENUM_CASE(sync_pb::SyncEnums, OS_TYPE_LINUX);
+ ENUM_CASE(sync_pb::SyncEnums, OS_TYPE_CHROME_OS_ASH);
+ ENUM_CASE(sync_pb::SyncEnums, OS_TYPE_ANDROID);
+ ENUM_CASE(sync_pb::SyncEnums, OS_TYPE_IOS);
+ ENUM_CASE(sync_pb::SyncEnums, OS_TYPE_CHROME_OS_LACROS);
+ ENUM_CASE(sync_pb::SyncEnums, OS_TYPE_FUCHSIA);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::SyncEnums::DeviceFormFactor device_form_factor) {
+ ASSERT_ENUM_BOUNDS(sync_pb::SyncEnums, DeviceFormFactor,
+ DEVICE_FORM_FACTOR_UNSPECIFIED, DEVICE_FORM_FACTOR_TV);
+ switch (device_form_factor) {
+ ENUM_CASE(sync_pb::SyncEnums, DEVICE_FORM_FACTOR_UNSPECIFIED);
+ ENUM_CASE(sync_pb::SyncEnums, DEVICE_FORM_FACTOR_DESKTOP);
+ ENUM_CASE(sync_pb::SyncEnums, DEVICE_FORM_FACTOR_PHONE);
+ ENUM_CASE(sync_pb::SyncEnums, DEVICE_FORM_FACTOR_TABLET);
+ ENUM_CASE(sync_pb::SyncEnums, DEVICE_FORM_FACTOR_AUTOMOTIVE);
+ ENUM_CASE(sync_pb::SyncEnums, DEVICE_FORM_FACTOR_WEARABLE);
+ ENUM_CASE(sync_pb::SyncEnums, DEVICE_FORM_FACTOR_TV);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(sync_pb::SyncEnums::ErrorType error_type) {
+ ASSERT_ENUM_BOUNDS(sync_pb::SyncEnums, ErrorType, SUCCESS, UNKNOWN);
+ switch (error_type) {
+ ENUM_CASE(sync_pb::SyncEnums, SUCCESS);
+ ENUM_CASE(sync_pb::SyncEnums, NOT_MY_BIRTHDAY);
+ ENUM_CASE(sync_pb::SyncEnums, THROTTLED);
+ ENUM_CASE(sync_pb::SyncEnums, TRANSIENT_ERROR);
+ ENUM_CASE(sync_pb::SyncEnums, MIGRATION_DONE);
+ ENUM_CASE(sync_pb::SyncEnums, DISABLED_BY_ADMIN);
+ ENUM_CASE(sync_pb::SyncEnums, PARTIAL_FAILURE);
+ ENUM_CASE(sync_pb::SyncEnums, CLIENT_DATA_OBSOLETE);
+ ENUM_CASE(sync_pb::SyncEnums, ENCRYPTION_OBSOLETE);
+ ENUM_CASE(sync_pb::SyncEnums, UNKNOWN);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(sync_pb::SyncEnums::GetUpdatesOrigin origin) {
+ ASSERT_ENUM_BOUNDS(sync_pb::SyncEnums, GetUpdatesOrigin, UNKNOWN_ORIGIN,
+ PROGRAMMATIC);
+ switch (origin) {
+ ENUM_CASE(sync_pb::SyncEnums, UNKNOWN_ORIGIN);
+ ENUM_CASE(sync_pb::SyncEnums, PERIODIC);
+ ENUM_CASE(sync_pb::SyncEnums, NEWLY_SUPPORTED_DATATYPE);
+ ENUM_CASE(sync_pb::SyncEnums, MIGRATION);
+ ENUM_CASE(sync_pb::SyncEnums, NEW_CLIENT);
+ ENUM_CASE(sync_pb::SyncEnums, RECONFIGURATION);
+ ENUM_CASE(sync_pb::SyncEnums, GU_TRIGGER);
+ ENUM_CASE(sync_pb::SyncEnums, PROGRAMMATIC);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::SyncEnums::PageTransition page_transition) {
+ ASSERT_ENUM_BOUNDS(sync_pb::SyncEnums, PageTransition, LINK,
+ KEYWORD_GENERATED);
+ switch (page_transition) {
+ ENUM_CASE(sync_pb::SyncEnums, LINK);
+ ENUM_CASE(sync_pb::SyncEnums, TYPED);
+ ENUM_CASE(sync_pb::SyncEnums, AUTO_BOOKMARK);
+ ENUM_CASE(sync_pb::SyncEnums, AUTO_SUBFRAME);
+ ENUM_CASE(sync_pb::SyncEnums, MANUAL_SUBFRAME);
+ ENUM_CASE(sync_pb::SyncEnums, GENERATED);
+ ENUM_CASE(sync_pb::SyncEnums, AUTO_TOPLEVEL);
+ ENUM_CASE(sync_pb::SyncEnums, FORM_SUBMIT);
+ ENUM_CASE(sync_pb::SyncEnums, RELOAD);
+ ENUM_CASE(sync_pb::SyncEnums, KEYWORD);
+ ENUM_CASE(sync_pb::SyncEnums, KEYWORD_GENERATED);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::SyncEnums::PageTransitionRedirectType page_transition_qualifier) {
+ ASSERT_ENUM_BOUNDS(sync_pb::SyncEnums, PageTransitionRedirectType,
+ CLIENT_REDIRECT, SERVER_REDIRECT);
+ switch (page_transition_qualifier) {
+ ENUM_CASE(sync_pb::SyncEnums, CLIENT_REDIRECT);
+ ENUM_CASE(sync_pb::SyncEnums, SERVER_REDIRECT);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::SyncEnums::SendTabReceivingType send_tab_receiving_type) {
+ ASSERT_ENUM_BOUNDS(sync_pb::SyncEnums, SendTabReceivingType,
+ SEND_TAB_RECEIVING_TYPE_CHROME_OR_UNSPECIFIED,
+ SEND_TAB_RECEIVING_TYPE_CHROME_AND_PUSH_NOTIFICATION);
+ switch (send_tab_receiving_type) {
+ ENUM_CASE(sync_pb::SyncEnums,
+ SEND_TAB_RECEIVING_TYPE_CHROME_OR_UNSPECIFIED);
+ ENUM_CASE(sync_pb::SyncEnums,
+ SEND_TAB_RECEIVING_TYPE_CHROME_AND_PUSH_NOTIFICATION);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::SyncEnums::SingletonDebugEventType type) {
+ ASSERT_ENUM_BOUNDS(sync_pb::SyncEnums, SingletonDebugEventType,
+ CONNECTION_STATUS_CHANGE, TRUSTED_VAULT_KEY_ACCEPTED);
+ switch (type) {
+ ENUM_CASE(sync_pb::SyncEnums, CONNECTION_STATUS_CHANGE);
+ ENUM_CASE(sync_pb::SyncEnums, UPDATED_TOKEN);
+ ENUM_CASE(sync_pb::SyncEnums, PASSPHRASE_REQUIRED);
+ ENUM_CASE(sync_pb::SyncEnums, PASSPHRASE_ACCEPTED);
+ ENUM_CASE(sync_pb::SyncEnums, INITIALIZATION_COMPLETE);
+ ENUM_CASE(sync_pb::SyncEnums, STOP_SYNCING_PERMANENTLY);
+ ENUM_CASE(sync_pb::SyncEnums, ACTIONABLE_ERROR);
+ ENUM_CASE(sync_pb::SyncEnums, ENCRYPTED_TYPES_CHANGED);
+ ENUM_CASE(sync_pb::SyncEnums, PASSPHRASE_TYPE_CHANGED);
+ ENUM_CASE(sync_pb::SyncEnums, DEPRECATED_KEYSTORE_TOKEN_UPDATED);
+ ENUM_CASE(sync_pb::SyncEnums, CONFIGURE_COMPLETE);
+ ENUM_CASE(sync_pb::SyncEnums, DEPRECATED_BOOTSTRAP_TOKEN_UPDATED);
+ ENUM_CASE(sync_pb::SyncEnums, TRUSTED_VAULT_KEY_REQUIRED);
+ ENUM_CASE(sync_pb::SyncEnums, TRUSTED_VAULT_KEY_ACCEPTED);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(sync_pb::TabNavigation::BlockedState state) {
+ ASSERT_ENUM_BOUNDS(sync_pb::TabNavigation, BlockedState, STATE_ALLOWED,
+ STATE_BLOCKED);
+ switch (state) {
+ ENUM_CASE(sync_pb::TabNavigation, STATE_ALLOWED);
+ ENUM_CASE(sync_pb::TabNavigation, STATE_BLOCKED);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(sync_pb::SyncEnums::PasswordState state) {
+ ASSERT_ENUM_BOUNDS(sync_pb::SyncEnums, PasswordState, PASSWORD_STATE_UNKNOWN,
+ HAS_PASSWORD_FIELD);
+ switch (state) {
+ ENUM_CASE(sync_pb::SyncEnums, PASSWORD_STATE_UNKNOWN);
+ ENUM_CASE(sync_pb::SyncEnums, NO_PASSWORD_FIELD);
+ ENUM_CASE(sync_pb::SyncEnums, HAS_PASSWORD_FIELD);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(sync_pb::UserConsentTypes::ConsentStatus status) {
+ ASSERT_ENUM_BOUNDS(sync_pb::UserConsentTypes, ConsentStatus,
+ CONSENT_STATUS_UNSPECIFIED, GIVEN);
+ switch (status) {
+ ENUM_CASE(sync_pb::UserConsentTypes, CONSENT_STATUS_UNSPECIFIED);
+ ENUM_CASE(sync_pb::UserConsentTypes, NOT_GIVEN);
+ ENUM_CASE(sync_pb::UserConsentTypes, GIVEN);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::GaiaPasswordReuse::PasswordReuseDetected::SafeBrowsingStatus::
+ ReportingPopulation safe_browsing_reporting_population) {
+ ASSERT_ENUM_BOUNDS(
+ sync_pb::GaiaPasswordReuse::PasswordReuseDetected::SafeBrowsingStatus,
+ ReportingPopulation, REPORTING_POPULATION_UNSPECIFIED,
+ ENHANCED_PROTECTION);
+ switch (safe_browsing_reporting_population) {
+ ENUM_CASE(
+ sync_pb::GaiaPasswordReuse::PasswordReuseDetected::SafeBrowsingStatus,
+ REPORTING_POPULATION_UNSPECIFIED);
+ ENUM_CASE(
+ sync_pb::GaiaPasswordReuse::PasswordReuseDetected::SafeBrowsingStatus,
+ NONE);
+ ENUM_CASE(
+ sync_pb::GaiaPasswordReuse::PasswordReuseDetected::SafeBrowsingStatus,
+ EXTENDED_REPORTING);
+ ENUM_CASE(
+ sync_pb::GaiaPasswordReuse::PasswordReuseDetected::SafeBrowsingStatus,
+ SCOUT);
+ ENUM_CASE(
+ sync_pb::GaiaPasswordReuse::PasswordReuseDetected::SafeBrowsingStatus,
+ ENHANCED_PROTECTION);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::GaiaPasswordReuse::PasswordReuseDialogInteraction::
+ InteractionResult interaction_result) {
+ ASSERT_ENUM_BOUNDS(sync_pb::GaiaPasswordReuse::PasswordReuseDialogInteraction,
+ InteractionResult, UNSPECIFIED,
+ WARNING_ACTION_TAKEN_ON_SETTINGS);
+ switch (interaction_result) {
+ ENUM_CASE(sync_pb::GaiaPasswordReuse::PasswordReuseDialogInteraction,
+ UNSPECIFIED);
+ ENUM_CASE(sync_pb::GaiaPasswordReuse::PasswordReuseDialogInteraction,
+ WARNING_ACTION_TAKEN);
+ ENUM_CASE(sync_pb::GaiaPasswordReuse::PasswordReuseDialogInteraction,
+ WARNING_ACTION_IGNORED);
+ ENUM_CASE(sync_pb::GaiaPasswordReuse::PasswordReuseDialogInteraction,
+ WARNING_UI_IGNORED);
+ ENUM_CASE(sync_pb::GaiaPasswordReuse::PasswordReuseDialogInteraction,
+ WARNING_ACTION_TAKEN_ON_SETTINGS);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::GaiaPasswordReuse::PasswordReuseLookup::LookupResult
+ lookup_result) {
+ ASSERT_ENUM_BOUNDS(sync_pb::GaiaPasswordReuse::PasswordReuseLookup,
+ LookupResult, UNSPECIFIED, TURNED_OFF_BY_POLICY);
+ switch (lookup_result) {
+ ENUM_CASE(sync_pb::GaiaPasswordReuse::PasswordReuseLookup, UNSPECIFIED);
+ ENUM_CASE(sync_pb::GaiaPasswordReuse::PasswordReuseLookup, ALLOWLIST_HIT);
+ ENUM_CASE(sync_pb::GaiaPasswordReuse::PasswordReuseLookup, CACHE_HIT);
+ ENUM_CASE(sync_pb::GaiaPasswordReuse::PasswordReuseLookup, REQUEST_SUCCESS);
+ ENUM_CASE(sync_pb::GaiaPasswordReuse::PasswordReuseLookup, REQUEST_FAILURE);
+ ENUM_CASE(sync_pb::GaiaPasswordReuse::PasswordReuseLookup, URL_UNSUPPORTED);
+ ENUM_CASE(sync_pb::GaiaPasswordReuse::PasswordReuseLookup,
+ ENTERPRISE_ALLOWLIST_HIT);
+ ENUM_CASE(sync_pb::GaiaPasswordReuse::PasswordReuseLookup,
+ TURNED_OFF_BY_POLICY);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::GaiaPasswordReuse::PasswordReuseLookup::ReputationVerdict
+ verdict) {
+ ASSERT_ENUM_BOUNDS(sync_pb::GaiaPasswordReuse::PasswordReuseLookup,
+ ReputationVerdict, VERDICT_UNSPECIFIED, PHISHING);
+ switch (verdict) {
+ ENUM_CASE(sync_pb::GaiaPasswordReuse::PasswordReuseLookup,
+ VERDICT_UNSPECIFIED);
+ ENUM_CASE(sync_pb::GaiaPasswordReuse::PasswordReuseLookup, SAFE);
+ ENUM_CASE(sync_pb::GaiaPasswordReuse::PasswordReuseLookup, LOW_REPUTATION);
+ ENUM_CASE(sync_pb::GaiaPasswordReuse::PasswordReuseLookup, PHISHING);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::UserEventSpecifics::GaiaPasswordCaptured::EventTrigger trigger) {
+ ASSERT_ENUM_BOUNDS(sync_pb::UserEventSpecifics::GaiaPasswordCaptured,
+ EventTrigger, UNSPECIFIED, EXPIRED_28D_TIMER);
+ switch (trigger) {
+ ENUM_CASE(sync_pb::UserEventSpecifics::GaiaPasswordCaptured, UNSPECIFIED);
+ ENUM_CASE(sync_pb::UserEventSpecifics::GaiaPasswordCaptured,
+ USER_LOGGED_IN);
+ ENUM_CASE(sync_pb::UserEventSpecifics::GaiaPasswordCaptured,
+ EXPIRED_28D_TIMER);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::UserEventSpecifics::FlocIdComputed::EventTrigger trigger) {
+ ASSERT_ENUM_BOUNDS(sync_pb::UserEventSpecifics::FlocIdComputed, EventTrigger,
+ UNSPECIFIED, HISTORY_DELETE);
+ switch (trigger) {
+ ENUM_CASE(sync_pb::UserEventSpecifics::FlocIdComputed, UNSPECIFIED);
+ ENUM_CASE(sync_pb::UserEventSpecifics::FlocIdComputed, NEW);
+ ENUM_CASE(sync_pb::UserEventSpecifics::FlocIdComputed, REFRESHED);
+ ENUM_CASE(sync_pb::UserEventSpecifics::FlocIdComputed, HISTORY_DELETE);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::WalletMaskedCreditCard::CardInfoRetrievalEnrollmentState
+ card_info_retrieval_enrollment_state) {
+ ASSERT_ENUM_BOUNDS(sync_pb::WalletMaskedCreditCard,
+ CardInfoRetrievalEnrollmentState, RETRIEVAL_UNSPECIFIED,
+ RETRIEVAL_UNENROLLED_AND_ELIGIBLE);
+ switch (card_info_retrieval_enrollment_state) {
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, RETRIEVAL_UNSPECIFIED);
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, RETRIEVAL_ENROLLED);
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard,
+ RETRIEVAL_UNENROLLED_AND_NOT_ELIGIBLE);
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard,
+ RETRIEVAL_UNENROLLED_AND_ELIGIBLE);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::WalletMaskedCreditCard::CardBenefitSource card_benefit_source) {
+ ASSERT_ENUM_BOUNDS(sync_pb::WalletMaskedCreditCard, CardBenefitSource, SOURCE_UNKNOWN,
+ SOURCE_CURINOS);
+ switch (card_benefit_source) {
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, SOURCE_UNKNOWN);
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, SOURCE_AMEX);
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, SOURCE_BMO);
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, SOURCE_CURINOS);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::WalletMaskedCreditCard::CardCreationSource card_creation_source) {
+ ASSERT_ENUM_BOUNDS(sync_pb::WalletMaskedCreditCard, CardCreationSource,
+ CREATION_SOURCE_UNSPECIFIED,
+ CREATION_SOURCE_NON_CHROME_PAYMENTS);
+ switch (card_creation_source) {
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, CREATION_SOURCE_UNSPECIFIED);
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, CREATION_SOURCE_CHROME_PAYMENTS);
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard,
+ CREATION_SOURCE_NON_CHROME_PAYMENTS);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::WalletMaskedCreditCard::VirtualCardEnrollmentState
+ virtual_card_enrollment_state) {
+ ASSERT_ENUM_BOUNDS(sync_pb::WalletMaskedCreditCard,
+ VirtualCardEnrollmentState, UNSPECIFIED,
+ UNENROLLED_AND_ELIGIBLE);
+ switch (virtual_card_enrollment_state) {
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, UNSPECIFIED);
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, UNENROLLED);
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, ENROLLED);
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, UNENROLLED_AND_NOT_ELIGIBLE);
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, UNENROLLED_AND_ELIGIBLE);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::WalletMaskedCreditCard::VirtualCardEnrollmentType
+ virtual_card_enrollment_type) {
+ ASSERT_ENUM_BOUNDS(sync_pb::WalletMaskedCreditCard, VirtualCardEnrollmentType,
+ TYPE_UNSPECIFIED, NETWORK);
+ switch (virtual_card_enrollment_type) {
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, TYPE_UNSPECIFIED);
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, ISSUER);
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, NETWORK);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::WalletMaskedCreditCard::WalletCardStatus wallet_card_status) {
+ ASSERT_ENUM_BOUNDS(sync_pb::WalletMaskedCreditCard, WalletCardStatus, VALID,
+ EXPIRED);
+ switch (wallet_card_status) {
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, VALID);
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, EXPIRED);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::WalletMaskedCreditCard::WalletCardType wallet_card_type) {
+ ASSERT_ENUM_BOUNDS(sync_pb::WalletMaskedCreditCard, WalletCardType, UNKNOWN,
+ VERVE);
+ switch (wallet_card_type) {
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, UNKNOWN);
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, AMEX);
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, DISCOVER);
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, JCB);
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, MAESTRO);
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, MASTER_CARD);
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, SOLO);
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, SWITCH);
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, VISA);
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, UNIONPAY);
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, ELO);
+ ENUM_CASE(sync_pb::WalletMaskedCreditCard, VERVE);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::CardBenefit::CategoryBenefitType category_benefit_type) {
+ ASSERT_ENUM_BOUNDS(sync_pb::CardBenefit, CategoryBenefitType,
+ CATEGORY_BENEFIT_TYPE_UNKNOWN, WHOLESALE_CLUBS);
+ switch (category_benefit_type) {
+ ENUM_CASE(sync_pb::CardBenefit, CATEGORY_BENEFIT_TYPE_UNKNOWN);
+ ENUM_CASE(sync_pb::CardBenefit, SUBSCRIPTION);
+ ENUM_CASE(sync_pb::CardBenefit, FLIGHTS);
+ ENUM_CASE(sync_pb::CardBenefit, DINING);
+ ENUM_CASE(sync_pb::CardBenefit, ENTERTAINMENT);
+ ENUM_CASE(sync_pb::CardBenefit, STREAMING);
+ ENUM_CASE(sync_pb::CardBenefit, GROCERY_STORES);
+ ENUM_CASE(sync_pb::CardBenefit, AIR_MILES_PARTNER);
+ ENUM_CASE(sync_pb::CardBenefit, ALCOHOL_STORES);
+ ENUM_CASE(sync_pb::CardBenefit, DRUGSTORES);
+ ENUM_CASE(sync_pb::CardBenefit, OFFICE_SUPPLIES);
+ ENUM_CASE(sync_pb::CardBenefit, RECURRING_BILLS);
+ ENUM_CASE(sync_pb::CardBenefit, TRANSIT);
+ ENUM_CASE(sync_pb::CardBenefit, TRAVEL);
+ ENUM_CASE(sync_pb::CardBenefit, WHOLESALE_CLUBS);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(sync_pb::CardIssuer::Issuer issuer) {
+ ASSERT_ENUM_BOUNDS(sync_pb::CardIssuer, Issuer, ISSUER_UNKNOWN,
+ EXTERNAL_ISSUER);
+ switch (issuer) {
+ ENUM_CASE(sync_pb::CardIssuer, ISSUER_UNKNOWN);
+ ENUM_CASE(sync_pb::CardIssuer, GOOGLE);
+ ENUM_CASE(sync_pb::CardIssuer, EXTERNAL_ISSUER);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::WalletMetadataSpecifics::Type wallet_metadata_type) {
+ ASSERT_ENUM_BOUNDS(sync_pb::WalletMetadataSpecifics, Type, UNKNOWN, IBAN);
+ switch (wallet_metadata_type) {
+ ENUM_CASE(sync_pb::WalletMetadataSpecifics, UNKNOWN);
+ ENUM_CASE(sync_pb::WalletMetadataSpecifics, CARD);
+ ENUM_CASE(sync_pb::WalletMetadataSpecifics, ADDRESS);
+ ENUM_CASE(sync_pb::WalletMetadataSpecifics, IBAN);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(sync_pb::WebApkIconInfo::Purpose purpose) {
+ ASSERT_ENUM_BOUNDS(sync_pb::WebApkIconInfo, Purpose, UNSPECIFIED, MONOCHROME);
+ switch (purpose) {
+ ENUM_CASE(sync_pb::WebApkIconInfo, UNSPECIFIED);
+ ENUM_CASE(sync_pb::WebApkIconInfo, ANY);
+ ENUM_CASE(sync_pb::WebApkIconInfo, MASKABLE);
+ ENUM_CASE(sync_pb::WebApkIconInfo, MONOCHROME);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(sync_pb::WebAppIconInfo::Purpose purpose) {
+ ASSERT_ENUM_BOUNDS(sync_pb::WebAppIconInfo, Purpose, UNSPECIFIED, MONOCHROME);
+ switch (purpose) {
+ ENUM_CASE(sync_pb::WebAppIconInfo, UNSPECIFIED);
+ ENUM_CASE(sync_pb::WebAppIconInfo, ANY);
+ ENUM_CASE(sync_pb::WebAppIconInfo, MASKABLE);
+ ENUM_CASE(sync_pb::WebAppIconInfo, MONOCHROME);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::WebAppSpecifics::UserDisplayMode user_display_mode) {
+ ASSERT_ENUM_BOUNDS(sync_pb::WebAppSpecifics, UserDisplayMode, UNSPECIFIED,
+ TABBED);
+ switch (user_display_mode) {
+ ENUM_CASE(sync_pb::WebAppSpecifics, UNSPECIFIED);
+ ENUM_CASE(sync_pb::WebAppSpecifics, BROWSER);
+ ENUM_CASE(sync_pb::WebAppSpecifics, STANDALONE);
+ ENUM_CASE(sync_pb::WebAppSpecifics, TABBED);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::WifiConfigurationSpecifics::SecurityType security_type) {
+ ASSERT_ENUM_BOUNDS(sync_pb::WifiConfigurationSpecifics, SecurityType,
+ SECURITY_TYPE_UNSPECIFIED, SECURITY_TYPE_PSK);
+ switch (security_type) {
+ ENUM_CASE(sync_pb::WifiConfigurationSpecifics, SECURITY_TYPE_UNSPECIFIED);
+ ENUM_CASE(sync_pb::WifiConfigurationSpecifics, SECURITY_TYPE_NONE);
+ ENUM_CASE(sync_pb::WifiConfigurationSpecifics, SECURITY_TYPE_WEP);
+ ENUM_CASE(sync_pb::WifiConfigurationSpecifics, SECURITY_TYPE_PSK);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::WifiConfigurationSpecifics::AutomaticallyConnectOption
+ automatically_connect_option) {
+ ASSERT_ENUM_BOUNDS(
+ sync_pb::WifiConfigurationSpecifics, AutomaticallyConnectOption,
+ AUTOMATICALLY_CONNECT_UNSPECIFIED, AUTOMATICALLY_CONNECT_ENABLED);
+ switch (automatically_connect_option) {
+ ENUM_CASE(sync_pb::WifiConfigurationSpecifics,
+ AUTOMATICALLY_CONNECT_UNSPECIFIED);
+ ENUM_CASE(sync_pb::WifiConfigurationSpecifics,
+ AUTOMATICALLY_CONNECT_DISABLED);
+ ENUM_CASE(sync_pb::WifiConfigurationSpecifics,
+ AUTOMATICALLY_CONNECT_ENABLED);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::WifiConfigurationSpecifics::IsPreferredOption
+ is_preferred_option) {
+ ASSERT_ENUM_BOUNDS(sync_pb::WifiConfigurationSpecifics, IsPreferredOption,
+ IS_PREFERRED_UNSPECIFIED, IS_PREFERRED_ENABLED);
+ switch (is_preferred_option) {
+ ENUM_CASE(sync_pb::WifiConfigurationSpecifics, IS_PREFERRED_UNSPECIFIED);
+ ENUM_CASE(sync_pb::WifiConfigurationSpecifics, IS_PREFERRED_DISABLED);
+ ENUM_CASE(sync_pb::WifiConfigurationSpecifics, IS_PREFERRED_ENABLED);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::WifiConfigurationSpecifics::MeteredOption metered_option) {
+ ASSERT_ENUM_BOUNDS(sync_pb::WifiConfigurationSpecifics, MeteredOption,
+ METERED_OPTION_UNSPECIFIED, METERED_OPTION_AUTO);
+ switch (metered_option) {
+ ENUM_CASE(sync_pb::WifiConfigurationSpecifics, METERED_OPTION_UNSPECIFIED);
+ ENUM_CASE(sync_pb::WifiConfigurationSpecifics, METERED_OPTION_NO);
+ ENUM_CASE(sync_pb::WifiConfigurationSpecifics, METERED_OPTION_YES);
+ ENUM_CASE(sync_pb::WifiConfigurationSpecifics, METERED_OPTION_AUTO);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::WifiConfigurationSpecifics::ProxyConfiguration::ProxyOption
+ proxy_option) {
+ ASSERT_ENUM_BOUNDS(sync_pb::WifiConfigurationSpecifics::ProxyConfiguration,
+ ProxyOption, PROXY_OPTION_UNSPECIFIED,
+ PROXY_OPTION_MANUAL);
+ switch (proxy_option) {
+ ENUM_CASE(sync_pb::WifiConfigurationSpecifics::ProxyConfiguration,
+ PROXY_OPTION_UNSPECIFIED);
+ ENUM_CASE(sync_pb::WifiConfigurationSpecifics::ProxyConfiguration,
+ PROXY_OPTION_DISABLED);
+ ENUM_CASE(sync_pb::WifiConfigurationSpecifics::ProxyConfiguration,
+ PROXY_OPTION_AUTOMATIC);
+ ENUM_CASE(sync_pb::WifiConfigurationSpecifics::ProxyConfiguration,
+ PROXY_OPTION_AUTODISCOVERY);
+ ENUM_CASE(sync_pb::WifiConfigurationSpecifics::ProxyConfiguration,
+ PROXY_OPTION_MANUAL);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::WorkspaceDeskSpecifics::WindowState window_state) {
+ ASSERT_ENUM_BOUNDS(sync_pb::WorkspaceDeskSpecifics, WindowState,
+ UNKNOWN_WINDOW_STATE, FLOATED);
+ switch (window_state) {
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, UNKNOWN_WINDOW_STATE);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, NORMAL);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, MINIMIZED);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, MAXIMIZED);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, FULLSCREEN);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, PRIMARY_SNAPPED);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, SECONDARY_SNAPPED);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, FLOATED);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::WorkspaceDeskSpecifics::LaunchContainer container) {
+ ASSERT_ENUM_BOUNDS(sync_pb::WorkspaceDeskSpecifics, LaunchContainer,
+ LAUNCH_CONTAINER_UNSPECIFIED, LAUNCH_CONTAINER_NONE);
+ switch (container) {
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, LAUNCH_CONTAINER_UNSPECIFIED);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, LAUNCH_CONTAINER_WINDOW);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics,
+ LAUNCH_CONTAINER_PANEL_DEPRECATED);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, LAUNCH_CONTAINER_TAB);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, LAUNCH_CONTAINER_NONE);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::WorkspaceDeskSpecifics::WindowOpenDisposition disposition) {
+ ASSERT_ENUM_BOUNDS(sync_pb::WorkspaceDeskSpecifics, WindowOpenDisposition,
+ UNKNOWN, NEW_PICTURE_IN_PICTURE);
+ switch (disposition) {
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, UNKNOWN);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, CURRENT_TAB);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, SINGLETON_TAB);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, NEW_FOREGROUND_TAB);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, NEW_BACKGROUND_TAB);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, NEW_POPUP);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, NEW_WINDOW);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, SAVE_TO_DISK);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, OFF_THE_RECORD);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, IGNORE_ACTION);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, SWITCH_TO_TAB);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, NEW_PICTURE_IN_PICTURE);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::UserConsentTypes::AssistantActivityControlConsent::SettingType
+ setting_type) {
+ ASSERT_ENUM_BOUNDS(sync_pb::UserConsentTypes::AssistantActivityControlConsent,
+ SettingType, SETTING_TYPE_UNSPECIFIED, DEVICE_APPS);
+ switch (setting_type) {
+ ENUM_CASE(sync_pb::UserConsentTypes::AssistantActivityControlConsent,
+ SETTING_TYPE_UNSPECIFIED);
+ ENUM_CASE(sync_pb::UserConsentTypes::AssistantActivityControlConsent, ALL);
+ ENUM_CASE(sync_pb::UserConsentTypes::AssistantActivityControlConsent,
+ WEB_AND_APP_ACTIVITY);
+ ENUM_CASE(sync_pb::UserConsentTypes::AssistantActivityControlConsent,
+ DEVICE_APPS);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(sync_pb::WorkspaceDeskSpecifics::DeskType type) {
+ ASSERT_ENUM_BOUNDS(sync_pb::WorkspaceDeskSpecifics, DeskType, UNKNOWN_TYPE,
+ FLOATING_WORKSPACE);
+ switch (type) {
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, UNKNOWN_TYPE);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, TEMPLATE);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, SAVE_AND_RECALL);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, FLOATING_WORKSPACE);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::WorkspaceDeskSpecifics::TabGroupColor color) {
+ ASSERT_ENUM_BOUNDS(sync_pb::WorkspaceDeskSpecifics, TabGroupColor,
+ UNKNOWN_COLOR, ORANGE);
+
+ switch (color) {
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, UNKNOWN_COLOR);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, GREY);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, BLUE);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, RED);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, YELLOW);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, GREEN);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, PINK);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, PURPLE);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, CYAN);
+ ENUM_CASE(sync_pb::WorkspaceDeskSpecifics, ORANGE);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(sync_pb::DataTypeState::InitialSyncState state) {
+ ASSERT_ENUM_BOUNDS(sync_pb::DataTypeState, InitialSyncState,
+ INITIAL_SYNC_STATE_UNSPECIFIED, INITIAL_SYNC_UNNECESSARY);
+ switch (state) {
+ ENUM_CASE(sync_pb::DataTypeState, INITIAL_SYNC_STATE_UNSPECIFIED);
+ ENUM_CASE(sync_pb::DataTypeState, INITIAL_SYNC_PARTIALLY_DONE);
+ ENUM_CASE(sync_pb::DataTypeState, INITIAL_SYNC_DONE);
+ ENUM_CASE(sync_pb::DataTypeState, INITIAL_SYNC_UNNECESSARY);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::CookieSpecifics::CookieSameSite site_restrictions) {
+ ASSERT_ENUM_BOUNDS(sync_pb::CookieSpecifics, CookieSameSite, UNSPECIFIED,
+ STRICT_MODE);
+ switch (site_restrictions) {
+ ENUM_CASE(sync_pb::CookieSpecifics, UNSPECIFIED);
+ ENUM_CASE(sync_pb::CookieSpecifics, NO_RESTRICTION);
+ ENUM_CASE(sync_pb::CookieSpecifics, LAX_MODE);
+ ENUM_CASE(sync_pb::CookieSpecifics, STRICT_MODE);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::CookieSpecifics::CookiePriority priority) {
+ ASSERT_ENUM_BOUNDS(sync_pb::CookieSpecifics, CookiePriority,
+ UNSPECIFIED_PRIORITY, HIGH);
+ switch (priority) {
+ ENUM_CASE(sync_pb::CookieSpecifics, UNSPECIFIED_PRIORITY);
+ ENUM_CASE(sync_pb::CookieSpecifics, LOW);
+ ENUM_CASE(sync_pb::CookieSpecifics, MEDIUM);
+ ENUM_CASE(sync_pb::CookieSpecifics, HIGH);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::CookieSpecifics::CookieSourceScheme source_scheme) {
+ ASSERT_ENUM_BOUNDS(sync_pb::CookieSpecifics, CookieSourceScheme, UNSET,
+ SECURE);
+ switch (source_scheme) {
+ ENUM_CASE(sync_pb::CookieSpecifics, UNSET);
+ ENUM_CASE(sync_pb::CookieSpecifics, NON_SECURE);
+ ENUM_CASE(sync_pb::CookieSpecifics, SECURE);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::CookieSpecifics::CookieSourceType source_type) {
+ ASSERT_ENUM_BOUNDS(sync_pb::CookieSpecifics, CookieSourceType, UNKNOWN,
+ OTHER);
+ switch (source_type) {
+ ENUM_CASE(sync_pb::CookieSpecifics, UNKNOWN);
+ ENUM_CASE(sync_pb::CookieSpecifics, HTTP);
+ ENUM_CASE(sync_pb::CookieSpecifics, SCRIPT);
+ ENUM_CASE(sync_pb::CookieSpecifics, OTHER);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::SharingMessageSpecifics::ChannelConfiguration::
+ ChimeChannelConfiguration::ChimeChannelType channel_type) {
+ ASSERT_ENUM_BOUNDS(sync_pb::SharingMessageSpecifics::ChannelConfiguration::
+ ChimeChannelConfiguration,
+ ChimeChannelType, CHANNEL_TYPE_UNSPECIFIED, APPLE_PUSH);
+ switch (channel_type) {
+ ENUM_CASE(sync_pb::SharingMessageSpecifics::ChannelConfiguration::
+ ChimeChannelConfiguration,
+ CHANNEL_TYPE_UNSPECIFIED);
+ ENUM_CASE(sync_pb::SharingMessageSpecifics::ChannelConfiguration::
+ ChimeChannelConfiguration,
+ APPLE_PUSH);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::UserColorTheme::BrowserColorVariant browser_color_variant) {
+ ASSERT_ENUM_BOUNDS(sync_pb::UserColorTheme, BrowserColorVariant,
+ BROWSER_COLOR_VARIANT_UNSPECIFIED, EXPRESSIVE);
+ switch (browser_color_variant) {
+ ENUM_CASE(sync_pb::UserColorTheme, BROWSER_COLOR_VARIANT_UNSPECIFIED);
+ ENUM_CASE(sync_pb::UserColorTheme, SYSTEM);
+ ENUM_CASE(sync_pb::UserColorTheme, TONAL_SPOT);
+ ENUM_CASE(sync_pb::UserColorTheme, NEUTRAL);
+ ENUM_CASE(sync_pb::UserColorTheme, VIBRANT);
+ ENUM_CASE(sync_pb::UserColorTheme, EXPRESSIVE);
+ }
+ NOTREACHED();
+}
+
+const char* ProtoEnumToString(
+ sync_pb::ThemeSpecifics::BrowserColorScheme browser_color_scheme) {
+ ASSERT_ENUM_BOUNDS(sync_pb::ThemeSpecifics, BrowserColorScheme,
+ BROWSER_COLOR_SCHEME_UNSPECIFIED, DARK);
+ switch (browser_color_scheme) {
+ ENUM_CASE(sync_pb::ThemeSpecifics, BROWSER_COLOR_SCHEME_UNSPECIFIED);
+ ENUM_CASE(sync_pb::ThemeSpecifics, SYSTEM);
+ ENUM_CASE(sync_pb::ThemeSpecifics, LIGHT);
+ ENUM_CASE(sync_pb::ThemeSpecifics, DARK);
+ }
+}
+
+const char* ProtoEnumToString(sync_pb::SharedUrlContext::Source source) {
+ ASSERT_ENUM_BOUNDS(sync_pb::SharedUrlContext, Source, SOURCE_UNSPECIFIED,
+ CANONICAL_URL);
+ switch (source) {
+ ENUM_CASE(sync_pb::SharedUrlContext, SOURCE_UNSPECIFIED);
+ ENUM_CASE(sync_pb::SharedUrlContext, OMNIBOX);
+ ENUM_CASE(sync_pb::SharedUrlContext, FROM_SYNC);
+ ENUM_CASE(sync_pb::SharedUrlContext, CANONICAL_URL);
+ }
+}
+
+#undef ASSERT_ENUM_BOUNDS
+#undef ENUM_CASE
+
+} // namespace syncer
diff --git a/pyhindsight/lib/components/sync/protocol/proto_enum_conversions.h b/pyhindsight/lib/components/sync/protocol/proto_enum_conversions.h
new file mode 100644
index 0000000..f20e46d
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/proto_enum_conversions.h
@@ -0,0 +1,255 @@
+// 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_PROTOCOL_PROTO_ENUM_CONVERSIONS_H_
+#define COMPONENTS_SYNC_PROTOCOL_PROTO_ENUM_CONVERSIONS_H_
+
+#include "components/sync/protocol/app_list_specifics.pb.h"
+#include "components/sync/protocol/app_specifics.pb.h"
+#include "components/sync/protocol/autofill_specifics.pb.h"
+#include "components/sync/protocol/contact_info_specifics.pb.h"
+#include "components/sync/protocol/cookie_specifics.pb.h"
+#include "components/sync/protocol/data_type_state.pb.h"
+#include "components/sync/protocol/gaia_password_reuse.pb.h"
+#include "components/sync/protocol/get_updates_caller_info.pb.h"
+#include "components/sync/protocol/nigori_specifics.pb.h"
+#include "components/sync/protocol/note_entity.pb.h"
+#include "components/sync/protocol/power_bookmark_specifics.pb.h"
+#include "components/sync/protocol/proto_value_conversions.h"
+#include "components/sync/protocol/reading_list_specifics.pb.h"
+#include "components/sync/protocol/saved_tab_group_specifics.pb.h"
+#include "components/sync/protocol/session_specifics.pb.h"
+#include "components/sync/protocol/shared_comment_specifics.pb.h"
+#include "components/sync/protocol/shared_tab_group_data_specifics.pb.h"
+#include "components/sync/protocol/sharing_message_specifics.pb.h"
+#include "components/sync/protocol/sync.pb.h"
+#include "components/sync/protocol/sync_enums.pb.h"
+#include "components/sync/protocol/theme_types.pb.h"
+#include "components/sync/protocol/user_consent_types.pb.h"
+#include "components/sync/protocol/user_event_specifics.pb.h"
+#include "components/sync/protocol/web_apk_specifics.pb.h"
+#include "components/sync/protocol/web_app_specifics.pb.h"
+#include "components/sync/protocol/wifi_configuration_specifics.pb.h"
+#include "components/sync/protocol/workspace_desk_specifics.pb.h"
+
+// Keep this file in sync with the .proto files in this directory.
+//
+// Utility functions to get the string equivalent for some sync proto
+// enums.
+
+namespace syncer {
+
+// The returned strings (which don't have to be freed) are in ASCII.
+// The result of passing in an invalid enum value is undefined.
+
+const char* ProtoEnumToString(
+ sync_pb::AppListSpecifics::AppListItemType item_type);
+
+const char* ProtoEnumToString(sync_pb::AppSpecifics::LaunchType launch_type);
+
+const char* ProtoEnumToString(
+ sync_pb::AutofillWalletSpecifics::WalletInfoType wallet_info_type);
+
+const char* ProtoEnumToString(
+ sync_pb::BankAccountDetails::AccountType account_type);
+
+const char* ProtoEnumToString(sync_pb::BookmarkSpecifics::Type type);
+
+const char* ProtoEnumToString(
+ sync_pb::CommitResponse::ResponseType response_type);
+
+const char* ProtoEnumToString(
+ sync_pb::ContactInfoSpecifics::AddressType address_type);
+
+const char* ProtoEnumToString(
+ sync_pb::ContactInfoSpecifics::VerificationStatus verification_status);
+
+const char* ProtoEnumToString(
+ sync_pb::TrustedVaultAutoUpgradeExperimentGroup::Type type);
+
+const char* ProtoEnumToString(sync_pb::NigoriSpecifics::PassphraseType type);
+
+const char* ProtoEnumToString(
+ sync_pb::PaymentInstrument::SupportedRail supported_rail);
+
+const char* ProtoEnumToString(
+ sync_pb::PaymentInstrument::ActionRequired action_required);
+
+const char* ProtoEnumToString(
+ sync_pb::PowerBookmarkSpecifics::PowerType power_type);
+
+const char* ProtoEnumToString(sync_pb::NoteEntity::TargetType target_type);
+
+const char* ProtoEnumToString(
+ sync_pb::ReadingListSpecifics::ReadingListEntryStatus status);
+
+const char* ProtoEnumToString(sync_pb::SavedTabGroup::SavedTabGroupColor color);
+
+const char* ProtoEnumToString(sync_pb::SharedTabGroup::Color color);
+
+const char* ProtoEnumToString(
+ sync_pb::SearchEngineSpecifics::ActiveStatus is_active);
+
+const char* ProtoEnumToString(sync_pb::SessionTab::FaviconType favicon_type);
+
+const char* ProtoEnumToString(sync_pb::SyncEnums::BrowserType browser_type);
+
+const char* ProtoEnumToString(sync_pb::SyncEnums::Action action);
+
+const char* ProtoEnumToString(sync_pb::SyncEnums::DeviceType device_type);
+
+const char* ProtoEnumToString(sync_pb::SyncEnums::OsType os_type);
+
+const char* ProtoEnumToString(
+ sync_pb::SyncEnums::DeviceFormFactor device_form_factor);
+
+const char* ProtoEnumToString(sync_pb::SyncEnums::ErrorType error_type);
+
+const char* ProtoEnumToString(sync_pb::SyncEnums::GetUpdatesOrigin origin);
+
+const char* ProtoEnumToString(
+ sync_pb::SyncEnums::PageTransition page_transition);
+
+const char* ProtoEnumToString(
+ sync_pb::SyncEnums::PageTransitionRedirectType redirect_type);
+
+const char* ProtoEnumToString(
+ sync_pb::SyncEnums::SendTabReceivingType send_tab_receiving_type);
+
+const char* ProtoEnumToString(sync_pb::SyncEnums::SingletonDebugEventType type);
+
+const char* ProtoEnumToString(sync_pb::TabNavigation::BlockedState state);
+
+const char* ProtoEnumToString(sync_pb::SyncEnums::PasswordState state);
+
+const char* ProtoEnumToString(sync_pb::UserConsentTypes::ConsentStatus status);
+
+const char* ProtoEnumToString(
+ sync_pb::GaiaPasswordReuse::PasswordReuseDetected::SafeBrowsingStatus::
+ ReportingPopulation safe_browsing_reporting_population);
+
+const char* ProtoEnumToString(
+ sync_pb::GaiaPasswordReuse::PasswordReuseDialogInteraction::
+ InteractionResult interaction_result);
+
+const char* ProtoEnumToString(
+ sync_pb::GaiaPasswordReuse::PasswordReuseLookup::LookupResult
+ lookup_result);
+
+const char* ProtoEnumToString(
+ sync_pb::GaiaPasswordReuse::PasswordReuseLookup::ReputationVerdict verdict);
+
+const char* ProtoEnumToString(
+ sync_pb::UserEventSpecifics::GaiaPasswordCaptured::EventTrigger trigger);
+
+const char* ProtoEnumToString(
+ sync_pb::UserEventSpecifics::FlocIdComputed::EventTrigger trigger);
+
+const char* ProtoEnumToString(
+ sync_pb::WalletMaskedCreditCard::CardInfoRetrievalEnrollmentState
+ card_info_retrieval_enrollment_state);
+
+const char* ProtoEnumToString(
+ sync_pb::WalletMaskedCreditCard::CardBenefitSource
+ card_benefit_source);
+
+const char* ProtoEnumToString(
+ sync_pb::WalletMaskedCreditCard::CardCreationSource card_creation_source);
+
+const char* ProtoEnumToString(
+ sync_pb::WalletMaskedCreditCard::VirtualCardEnrollmentState
+ virtual_card_enrollment_state);
+
+const char* ProtoEnumToString(
+ sync_pb::WalletMaskedCreditCard::VirtualCardEnrollmentType
+ virtual_card_enrollment_type);
+
+const char* ProtoEnumToString(
+ sync_pb::WalletMaskedCreditCard::WalletCardStatus wallet_card_status);
+
+const char* ProtoEnumToString(
+ sync_pb::WalletMaskedCreditCard::WalletCardType wallet_card_type);
+
+const char* ProtoEnumToString(
+ sync_pb::CardBenefit::CategoryBenefitType category_benefit_type);
+
+const char* ProtoEnumToString(sync_pb::CardIssuer::Issuer issuer);
+
+const char* ProtoEnumToString(
+ sync_pb::WalletMetadataSpecifics::Type wallet_metadata_type);
+
+const char* ProtoEnumToString(sync_pb::WebApkIconInfo::Purpose purpose);
+
+const char* ProtoEnumToString(sync_pb::WebAppIconInfo::Purpose purpose);
+
+const char* ProtoEnumToString(
+ sync_pb::WebAppSpecifics::UserDisplayMode user_display_mode);
+
+const char* ProtoEnumToString(
+ sync_pb::AutofillProfileSpecifics::VerificationStatus status);
+
+const char* ProtoEnumToString(
+ sync_pb::WifiConfigurationSpecifics::SecurityType security_type);
+
+const char* ProtoEnumToString(
+ sync_pb::WifiConfigurationSpecifics::AutomaticallyConnectOption
+ automatically_connect_option);
+
+const char* ProtoEnumToString(
+ sync_pb::WifiConfigurationSpecifics::IsPreferredOption is_preferred_option);
+
+const char* ProtoEnumToString(
+ sync_pb::WifiConfigurationSpecifics::MeteredOption metered_option);
+
+const char* ProtoEnumToString(
+ sync_pb::WifiConfigurationSpecifics::ProxyConfiguration::ProxyOption
+ proxy_option);
+
+const char* ProtoEnumToString(
+ sync_pb::WorkspaceDeskSpecifics::WindowState window_state);
+
+const char* ProtoEnumToString(
+ sync_pb::WorkspaceDeskSpecifics::LaunchContainer container);
+
+const char* ProtoEnumToString(
+ sync_pb::WorkspaceDeskSpecifics::WindowOpenDisposition disposition);
+
+const char* ProtoEnumToString(
+ sync_pb::UserConsentTypes::AssistantActivityControlConsent::SettingType
+ setting_type);
+
+const char* ProtoEnumToString(sync_pb::WorkspaceDeskSpecifics::DeskType type);
+
+const char* ProtoEnumToString(
+ sync_pb::WorkspaceDeskSpecifics::TabGroupColor color);
+
+const char* ProtoEnumToString(sync_pb::DataTypeState::InitialSyncState state);
+
+const char* ProtoEnumToString(
+ sync_pb::CookieSpecifics::CookieSameSite site_restrictions);
+
+const char* ProtoEnumToString(
+ sync_pb::CookieSpecifics::CookiePriority priority);
+
+const char* ProtoEnumToString(
+ sync_pb::CookieSpecifics::CookieSourceScheme source_scheme);
+
+const char* ProtoEnumToString(
+ sync_pb::CookieSpecifics::CookieSourceType source_type);
+
+const char* ProtoEnumToString(
+ sync_pb::SharingMessageSpecifics::ChannelConfiguration::
+ ChimeChannelConfiguration::ChimeChannelType channel_type);
+
+const char* ProtoEnumToString(
+ sync_pb::UserColorTheme::BrowserColorVariant browser_color_variant);
+
+const char* ProtoEnumToString(
+ sync_pb::ThemeSpecifics::BrowserColorScheme browser_color_scheme);
+
+const char* ProtoEnumToString(sync_pb::SharedUrlContext::Source source);
+
+} // namespace syncer
+
+#endif // COMPONENTS_SYNC_PROTOCOL_PROTO_ENUM_CONVERSIONS_H_
diff --git a/pyhindsight/lib/components/sync/protocol/proto_enum_conversions_unittest.cc b/pyhindsight/lib/components/sync/protocol/proto_enum_conversions_unittest.cc
new file mode 100644
index 0000000..854dda8
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/proto_enum_conversions_unittest.cc
@@ -0,0 +1,159 @@
+// 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.
+
+#include "components/sync/protocol/proto_enum_conversions.h"
+
+#include
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace syncer {
+namespace {
+
+// WARNING: Keep this file in sync with the .proto files in this directory.
+
+using ::testing::Not;
+using ::testing::StrEq;
+
+// Iterates through the enum values, checking their string version is non-empty.
+// The T##_IsValid() check is needed because some enums have deprecated values,
+// so they have gaps in their numeric range.
+#define TestEnumStringsNonEmpty(T) \
+ for (int i = T##_MIN; i <= T##_MAX; ++i) { \
+ if (T##_IsValid(i)) { \
+ EXPECT_THAT(ProtoEnumToString(static_cast(i)), Not(StrEq(""))); \
+ } \
+ }
+
+TEST(ProtoEnumConversionsTest, GetAppListItemTypeString) {
+ TestEnumStringsNonEmpty(sync_pb::AppListSpecifics::AppListItemType);
+}
+
+TEST(ProtoEnumConversionsTest, GetBrowserTypeString) {
+ TestEnumStringsNonEmpty(sync_pb::SyncEnums::BrowserType);
+}
+
+TEST(ProtoEnumConversionsTest, GetPageTransitionString) {
+ TestEnumStringsNonEmpty(sync_pb::SyncEnums::PageTransition);
+}
+
+TEST(ProtoEnumConversionsTest, GetPageTransitionQualifierString) {
+ TestEnumStringsNonEmpty(sync_pb::SyncEnums::PageTransitionRedirectType);
+}
+
+TEST(ProtoEnumConversionsTest, GetWifiConfigurationSecurityTypeString) {
+ TestEnumStringsNonEmpty(sync_pb::WifiConfigurationSpecifics::SecurityType);
+}
+
+TEST(ProtoEnumConversionsTest,
+ GetWifiConfigurationAutomaticallyConnectOptionString) {
+ TestEnumStringsNonEmpty(
+ sync_pb::WifiConfigurationSpecifics::AutomaticallyConnectOption);
+}
+
+TEST(ProtoEnumConversionsTest, GetWifiConfigurationIsPreferredOptionString) {
+ TestEnumStringsNonEmpty(
+ sync_pb::WifiConfigurationSpecifics::IsPreferredOption);
+}
+
+TEST(ProtoEnumConversionsTest, GetWifiConfigurationMeteredOptionString) {
+ TestEnumStringsNonEmpty(sync_pb::WifiConfigurationSpecifics::MeteredOption);
+}
+
+TEST(ProtoEnumConversionsTest, GetWifiConfigurationProxyOptionString) {
+ TestEnumStringsNonEmpty(
+ sync_pb::WifiConfigurationSpecifics::ProxyConfiguration::ProxyOption);
+}
+
+TEST(ProtoEnumConversionsTest, GetUpdatesOriginString) {
+ TestEnumStringsNonEmpty(sync_pb::SyncEnums::GetUpdatesOrigin);
+}
+
+TEST(ProtoEnumConversionsTest, GetResponseTypeString) {
+ TestEnumStringsNonEmpty(sync_pb::CommitResponse::ResponseType);
+}
+
+TEST(ProtoEnumConversionsTest, GetErrorTypeString) {
+ TestEnumStringsNonEmpty(sync_pb::SyncEnums::ErrorType);
+}
+
+TEST(ProtoEnumConversionsTest, GetActionString) {
+ TestEnumStringsNonEmpty(sync_pb::SyncEnums::Action);
+}
+
+TEST(ProtoEnumConversionsTest, GetConsentStatusString) {
+ TestEnumStringsNonEmpty(sync_pb::UserConsentTypes::ConsentStatus);
+}
+
+TEST(ProtoEnumConversionsTest, GetVirtualCardEnrollmentTypeString) {
+ TestEnumStringsNonEmpty(
+ sync_pb::WalletMaskedCreditCard::VirtualCardEnrollmentType);
+}
+
+TEST(ProtoEnumConversionsTest, GetSavedTabGroupColorString) {
+ TestEnumStringsNonEmpty(sync_pb::SavedTabGroup::SavedTabGroupColor);
+}
+
+TEST(ProtoEnumConversionsTest, GetSharedTabGroupColorString) {
+ TestEnumStringsNonEmpty(sync_pb::SharedTabGroup::Color);
+}
+
+TEST(ProtoEnumConversionsTest, GetIssuerString) {
+ TestEnumStringsNonEmpty(sync_pb::CardIssuer::Issuer);
+}
+
+TEST(ProtoEnumConversionsTest, GetPowerBookmakrPowerTypeString) {
+ TestEnumStringsNonEmpty(sync_pb::PowerBookmarkSpecifics::PowerType);
+}
+
+TEST(ProtoEnumConversionsTest, GetNoteTargetTypeString) {
+ TestEnumStringsNonEmpty(sync_pb::NoteEntity::TargetType);
+}
+
+TEST(ProtoEnumConversionsTest, GetInitialSyncStateString) {
+ TestEnumStringsNonEmpty(sync_pb::DataTypeState::InitialSyncState);
+}
+
+TEST(ProtoEnumConversionsTest, GetCategoryBenefitTypeString) {
+ TestEnumStringsNonEmpty(sync_pb::CardBenefit::CategoryBenefitType);
+}
+
+TEST(ProtoEnumConversionsTest,
+ GetTrustedVaultAutoUpgradeExperimentGroupTypeString) {
+ TestEnumStringsNonEmpty(
+ sync_pb::TrustedVaultAutoUpgradeExperimentGroup::Type);
+}
+
+TEST(ProtoEnumConversionsTest, GetBrowserColorVariantString) {
+ TestEnumStringsNonEmpty(sync_pb::UserColorTheme::BrowserColorVariant);
+}
+
+TEST(ProtoEnumConversionsTest, GetBrowserColorSchemeString) {
+ TestEnumStringsNonEmpty(sync_pb::ThemeSpecifics::BrowserColorScheme);
+}
+
+TEST(ProtoEnumConversionsTest, GetContactInfoAddressType) {
+ TestEnumStringsNonEmpty(sync_pb::ContactInfoSpecifics::AddressType);
+}
+
+TEST(ProtoEnumConversionsTest, GetCardInfoRetrievalEnrollmentStateString) {
+ TestEnumStringsNonEmpty(
+ sync_pb::WalletMaskedCreditCard::CardInfoRetrievalEnrollmentState);
+}
+
+TEST(ProtoEnumConversionsTest, GetCardBenefitSourceString) {
+ TestEnumStringsNonEmpty(sync_pb::WalletMaskedCreditCard::CardBenefitSource);
+}
+
+TEST(ProtoEnumConversionsTest, GetCardCreationSourceString) {
+ TestEnumStringsNonEmpty(sync_pb::WalletMaskedCreditCard::CardCreationSource);
+}
+
+TEST(ProtoEnumConversionsTest, GetActionRequiredString) {
+ TestEnumStringsNonEmpty(sync_pb::PaymentInstrument::ActionRequired);
+}
+
+} // namespace
+} // namespace syncer
diff --git a/pyhindsight/lib/components/sync/protocol/proto_memory_estimations.cc b/pyhindsight/lib/components/sync/protocol/proto_memory_estimations.cc
new file mode 100644
index 0000000..a9de71e
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/proto_memory_estimations.cc
@@ -0,0 +1,160 @@
+// Copyright 2016 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Keep this file in sync with the .proto files in this directory.
+
+#include "components/sync/protocol/proto_memory_estimations.h"
+
+#include
+#include
+
+#include "base/trace_event/memory_usage_estimator.h"
+#include "components/sync/protocol/data_type_progress_marker.pb.h"
+#include "components/sync/protocol/data_type_state.pb.h"
+#include "components/sync/protocol/entity_metadata.pb.h"
+#include "components/sync/protocol/entity_specifics.pb.h"
+#include "components/sync/protocol/nigori_specifics.pb.h"
+#include "components/sync/protocol/persisted_entity_data.pb.h"
+#include "components/sync/protocol/proto_visitors.h"
+#include "components/sync/protocol/sync_entity.pb.h"
+#include "components/sync/protocol/unique_position.pb.h"
+
+namespace {
+
+// This class is a VisitProtoFields()-compatible visitor that estimates
+// proto's memory usage:
+//
+// MemoryUsageVisitor visitor;
+// VisitProtoFields(visitor, proto);
+// size_t memory_usage = visitor.memory_usage();
+//
+class MemoryUsageVisitor {
+ public:
+ MemoryUsageVisitor() = default;
+
+ size_t memory_usage() const { return memory_usage_; }
+
+ template
+ void VisitBytes(const P& parent_proto,
+ const char* field_name,
+ const std::string& field) {
+ // Delegate to Visit(..., const std::string&) below.
+ Visit(parent_proto, field_name, field);
+ }
+
+ template
+ void VisitBytes(
+ const P& parent_proto,
+ const char* field_name,
+ const google::protobuf::RepeatedPtrField& fields) {
+ // Delegate to Visit(..., const std::string&) below.
+ Visit(parent_proto, field_name, fields);
+ }
+
+ template
+ void VisitSecret(const P& parent_proto,
+ const char* field_name,
+ const std::string& field) {
+ // Delegate to Visit(..., const std::string&) below.
+ Visit(parent_proto, field_name, field);
+ }
+
+ template
+ void VisitEnum(const P&, const char* field_name, E field) {}
+
+ // Types derived from MessageLite (i.e. protos)
+ template
+ requires(std::derived_from)
+ void Visit(const P&, const char* field_name, const F& field) {
+ using base::trace_event::EstimateMemoryUsage;
+ // All object fields are dynamically allocated.
+ memory_usage_ += sizeof(F) + EstimateMemoryUsage(field);
+ }
+
+ // Arithmetic types
+ template
+ requires(std::is_arithmetic_v)
+ void Visit(const P&, const char* field_name, const F& field) {
+ // Arithmetic fields (integers, floats & bool) don't allocate.
+ }
+
+ // std::string
+ template
+ void Visit(const P&, const char* field_name, const std::string& field) {
+ using base::trace_event::EstimateMemoryUsage;
+ // All strings are of type ArenaStringPtr, which essentially
+ // is std::string*.
+ memory_usage_ += sizeof(std::string) + EstimateMemoryUsage(field);
+ }
+
+ // RepeatedPtrField
+ template
+ void Visit(const P&,
+ const char* field_name,
+ const google::protobuf::RepeatedPtrField& fields) {
+ using base::trace_event::EstimateMemoryUsage;
+ // Can't use RepeatedPtrField::SpaceUsedExcludingSelf() because it will
+ // end up calling undefined TypeHandler::SpaceUsed() method.
+ memory_usage_ += fields.Capacity() ? sizeof(void*) : 0; // header
+ memory_usage_ += fields.Capacity() * sizeof(void*);
+ for (const auto& field : fields) {
+ memory_usage_ += sizeof(F) + EstimateMemoryUsage(field);
+ }
+ }
+
+ // RepeatedField
+ template
+ requires(std::is_arithmetic_v)
+ void Visit(const P&,
+ const char* field_name,
+ const google::protobuf::RepeatedField& fields) {
+ memory_usage_ += fields.SpaceUsedExcludingSelf();
+ // Arithmetic fields (integers, floats & bool) don't allocate, so no point
+ // in iterating over `fields`.
+ }
+
+ // RepeatedField
+ template
+ void Visit(const P&,
+ const char* field_name,
+ const google::protobuf::RepeatedField& fields) {
+ using base::trace_event::EstimateMemoryUsage;
+ memory_usage_ += fields.SpaceUsedExcludingSelf();
+ for (const auto& field : fields) {
+ memory_usage_ += EstimateMemoryUsage(field);
+ }
+ }
+
+ private:
+ size_t memory_usage_ = 0;
+};
+
+} // namespace
+
+namespace sync_pb {
+
+template
+size_t EstimateMemoryUsage(const P& proto) {
+ MemoryUsageVisitor visitor;
+ syncer::VisitProtoFields(visitor, proto);
+ return visitor.memory_usage();
+}
+
+// Explicit instantiations
+
+#define INSTANTIATE(Proto) \
+ template size_t EstimateMemoryUsage(const Proto&);
+
+INSTANTIATE(CrossUserSharingPublicKey)
+INSTANTIATE(DataTypeContext)
+INSTANTIATE(DataTypeProgressMarker)
+INSTANTIATE(DataTypeState)
+INSTANTIATE(DeletionOrigin)
+INSTANTIATE(EntityMetadata)
+INSTANTIATE(EntitySpecifics)
+INSTANTIATE(PersistedEntityData)
+INSTANTIATE(SyncEntity)
+INSTANTIATE(UniquePosition)
+
+} // namespace sync_pb
diff --git a/pyhindsight/lib/components/sync/protocol/proto_memory_estimations.h b/pyhindsight/lib/components/sync/protocol/proto_memory_estimations.h
new file mode 100644
index 0000000..26d3123
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/proto_memory_estimations.h
@@ -0,0 +1,22 @@
+// Copyright 2016 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_PROTOCOL_PROTO_MEMORY_ESTIMATIONS_H_
+#define COMPONENTS_SYNC_PROTOCOL_PROTO_MEMORY_ESTIMATIONS_H_
+
+#include
+
+namespace sync_pb {
+
+// Estimates memory usage for a proto.
+// Needs to be in sync_pb namespace for ADL to find it (when for example
+// EstimateMemoryUsage() is called on a list of protos).
+// Note: if you get linking errors you need to add explicit instantiation at
+// the end of the implementation file.
+template
+size_t EstimateMemoryUsage(const P& proto);
+
+} // namespace sync_pb
+
+#endif // COMPONENTS_SYNC_PROTOCOL_PROTO_MEMORY_ESTIMATIONS_H_
diff --git a/pyhindsight/lib/components/sync/protocol/proto_value_conversions.cc b/pyhindsight/lib/components/sync/protocol/proto_value_conversions.cc
new file mode 100644
index 0000000..7452bfc
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/proto_value_conversions.cc
@@ -0,0 +1,430 @@
+// 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.
+
+#include "components/sync/protocol/proto_value_conversions.h"
+
+#include
+
+#include
+#include
+
+#include "base/base64.h"
+#include "base/memory/raw_ptr.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
+#include "base/values.h"
+#include "components/sync/base/unique_position.h"
+#include "components/sync/protocol/app_list_specifics.pb.h"
+#include "components/sync/protocol/app_setting_specifics.pb.h"
+#include "components/sync/protocol/app_specifics.pb.h"
+#include "components/sync/protocol/arc_package_specifics.pb.h"
+#include "components/sync/protocol/autofill_offer_specifics.pb.h"
+#include "components/sync/protocol/autofill_specifics.pb.h"
+#include "components/sync/protocol/bookmark_specifics.pb.h"
+#include "components/sync/protocol/collaboration_group_specifics.pb.h"
+#include "components/sync/protocol/contact_info_specifics.pb.h"
+#include "components/sync/protocol/cookie_specifics.pb.h"
+#include "components/sync/protocol/data_type_progress_marker.pb.h"
+#include "components/sync/protocol/dictionary_specifics.pb.h"
+#include "components/sync/protocol/entity_specifics.pb.h"
+#include "components/sync/protocol/extension_setting_specifics.pb.h"
+#include "components/sync/protocol/extension_specifics.pb.h"
+#include "components/sync/protocol/history_delete_directive_specifics.pb.h"
+#include "components/sync/protocol/history_specifics.pb.h"
+#include "components/sync/protocol/nigori_specifics.pb.h"
+#include "components/sync/protocol/os_preference_specifics.pb.h"
+#include "components/sync/protocol/os_priority_preference_specifics.pb.h"
+#include "components/sync/protocol/password_sharing_invitation_specifics.pb.h"
+#include "components/sync/protocol/password_specifics.pb.h"
+#include "components/sync/protocol/plus_address_setting_specifics.pb.h"
+#include "components/sync/protocol/plus_address_specifics.pb.h"
+#include "components/sync/protocol/preference_specifics.pb.h"
+#include "components/sync/protocol/printer_specifics.pb.h"
+#include "components/sync/protocol/printers_authorization_server_specifics.pb.h"
+#include "components/sync/protocol/priority_preference_specifics.pb.h"
+#include "components/sync/protocol/product_comparison_specifics.pb.h"
+#include "components/sync/protocol/proto_visitors.h"
+#include "components/sync/protocol/reading_list_specifics.pb.h"
+#include "components/sync/protocol/saved_tab_group_specifics.pb.h"
+#include "components/sync/protocol/search_engine_specifics.pb.h"
+#include "components/sync/protocol/send_tab_to_self_specifics.pb.h"
+#include "components/sync/protocol/session_specifics.pb.h"
+#include "components/sync/protocol/shared_comment_specifics.pb.h"
+#include "components/sync/protocol/sharing_message_specifics.pb.h"
+#include "components/sync/protocol/sync.pb.h"
+#include "components/sync/protocol/sync_entity.pb.h"
+#include "components/sync/protocol/theme_specifics.pb.h"
+#include "components/sync/protocol/typed_url_specifics.pb.h"
+#include "components/sync/protocol/user_consent_specifics.pb.h"
+#include "components/sync/protocol/user_event_specifics.pb.h"
+#include "components/sync/protocol/web_apk_specifics.pb.h"
+#include "components/sync/protocol/web_app_specifics.pb.h"
+#include "components/sync/protocol/webauthn_credential_specifics.pb.h"
+#include "components/sync/protocol/workspace_desk_specifics.pb.h"
+
+namespace syncer {
+
+namespace {
+
+// ToValueVisitor is a VisitProtoFields()-compatible visitor that serializes
+// protos to base::Value. To serialize a proto you call ToValue() method:
+//
+// ToValueVisitor visitor;
+// auto value = visitor.ToValue(proto);
+//
+// By default all fields visited by VisitProtoFields() are serialized, but
+// there are several ways to customize that on per-field / per-proto basis:
+//
+// 1. If you want to change how fields of a particular proto type are
+// serialized, customize Visit() method:
+//
+// template
+// void Visit(const P& parent_proto,
+// const char* field_name, const F& field);
+//
+// By default Visit() serializes `field` and sets it to `value_` under
+// `field_name` name. Default implementation is accessible via VisitImpl().
+//
+// For example here is how you would serialize only GreenProto::content
+// for all GreenProto fields:
+//
+// template
+// void Visit(const P& parent_proto,
+// const char* field_name, const sync_pb::GreenProto& field) {
+// if (field.has_content()) {
+// value_->Set(field_name, field.content());
+// }
+// }
+//
+// You can further fine-tune this method by specifying parent proto. For
+// example let's say we don't want to serialize fields of type GreenProto
+// that are contained in RedProto:
+//
+// void Visit(const sync_pb::RedProto& parent_proto,
+// const char* field_name, const sync_pb::GreenProto& field) {}
+//
+// Note: Visit() method only called to serialize fields, and doesn't
+// affect top level protos. I.e. ToValueVisitor().ToValue(GreenProto)
+// won't call methods above.
+//
+// 2. If you want to change how proto itself is serialized, you need to
+// customize ToValue() method:
+//
+// template
+// base::Value ToValue(const P& proto) const;
+//
+// By default ToValue() creates new instance of ToValueVisitor, calls
+// VisitProtoFields(visitor, `proto`) and returns visitor's `value_`.
+// Default implementation is accessible via ToValueDictImpl().
+//
+// For example let's say you want to clobber a sensitive field:
+//
+// base::Value ToValue(const sync_pb::GreenProto& proto) const {
+// base::Value::Dict value = ToValueDictImpl(proto);
+// value.Set("secret", "");
+// return base::Value(value);
+// }
+//
+// ToValue() doesn't have to return a dictionary though. It might
+// be more appropriate to serialize GreenProto into a string instead:
+//
+// base::Value ToValue(const sync_pb::GreenProto& proto) const {
+// return base::Value(proto.content());
+// }
+//
+class ToValueVisitor {
+ public:
+ explicit ToValueVisitor(const ProtoValueConversionOptions& options =
+ ProtoValueConversionOptions(),
+ base::Value::Dict* value = nullptr)
+ : options_(options), value_(value) {}
+
+ template
+ void VisitBytes(const P& parent_proto,
+ const char* field_name,
+ const std::string& field) {
+ value_->Set(field_name,
+ base::Base64Encode(base::as_bytes(base::span(field))));
+ }
+
+ template
+ void VisitBytes(
+ const P& parent_proto,
+ const char* field_name,
+ const google::protobuf::RepeatedPtrField& repeated_field) {
+ if (!repeated_field.empty()) {
+ base::Value::List list;
+ for (const auto& field : repeated_field) {
+ list.Append(base::Base64Encode(base::as_byte_span(field)));
+ }
+ value_->Set(field_name, std::move(list));
+ }
+ }
+
+ template
+ void VisitSecret(const P& parent_proto,
+ const char* field_name,
+ const std::string& field) {
+ value_->Set(field_name,
+ base::StringPrintf("<%zu-byte secret>", field.size()));
+ }
+
+ template
+ void VisitEnum(const P& parent_proto, const char* field_name, E field) {
+ value_->Set(field_name, ProtoEnumToString(field));
+ }
+
+ template
+ void Visit(const P& parent_proto,
+ const char* field_name,
+ const google::protobuf::RepeatedPtrField& repeated_field) {
+ if (!repeated_field.empty()) {
+ base::Value::List list;
+ for (const auto& field : repeated_field) {
+ list.Append(ToValue(field));
+ }
+ value_->Set(field_name, std::move(list));
+ }
+ }
+
+ template
+ void Visit(const P& parent_proto,
+ const char* field_name,
+ const google::protobuf::RepeatedField& repeated_field) {
+ if (!repeated_field.empty()) {
+ base::Value::List list;
+ for (const auto& field : repeated_field) {
+ list.Append(ToValue(field));
+ }
+ value_->Set(field_name, std::move(list));
+ }
+ }
+
+ template
+ void Visit(const P& parent_proto, const char* field_name, const F& field) {
+ VisitImpl(parent_proto, field_name, field);
+ }
+
+ template
+ base::Value ToValue(const P& proto) const {
+ return base::Value(ToValueDictImpl(proto));
+ }
+
+ // Customizations
+
+ // EntitySpecifics
+ template
+ void Visit(const P& parent_proto,
+ const char* field_name,
+ const sync_pb::EntitySpecifics& field) {
+ if (options_.include_specifics) {
+ VisitImpl(parent_proto, field_name, field);
+ }
+ }
+
+ // GetUpdateTriggers.
+ base::Value ToValue(const sync_pb::GetUpdateTriggers& proto) const {
+ base::Value::Dict dict = ToValueDictImpl(proto);
+ if (!options_.include_full_get_update_triggers) {
+ if (!proto.client_dropped_hints()) {
+ dict.Remove("client_dropped_hints");
+ }
+ if (!proto.invalidations_out_of_sync()) {
+ dict.Remove("invalidations_out_of_sync");
+ }
+ if (proto.local_modification_nudges() == 0) {
+ dict.Remove("local_modification_nudges");
+ }
+ if (proto.datatype_refresh_nudges() == 0) {
+ dict.Remove("datatype_refresh_nudges");
+ }
+ if (!proto.server_dropped_hints()) {
+ dict.Remove("server_dropped_hints");
+ }
+ if (!proto.initial_sync_in_progress()) {
+ dict.Remove("initial_sync_in_progress");
+ }
+ if (!proto.sync_for_resolve_conflict_in_progress()) {
+ dict.Remove("sync_for_resolve_conflict_in_progress");
+ }
+ }
+ return base::Value(std::move(dict));
+ }
+
+ // AutofillWalletSpecifics
+ base::Value ToValue(const sync_pb::AutofillWalletSpecifics& proto) const {
+ base::Value::Dict dict = ToValueDictImpl(proto);
+ // TODO(crbug.com/40252694): consider whether the VISIT_SECRET macro in
+ // proto_visitors.h could replace this.
+ if (proto.type() != sync_pb::AutofillWalletSpecifics::POSTAL_ADDRESS) {
+ dict.Remove("address");
+ }
+ if (proto.type() != sync_pb::AutofillWalletSpecifics::MASKED_CREDIT_CARD) {
+ dict.Remove("masked_card");
+ }
+ if (proto.type() != sync_pb::AutofillWalletSpecifics::CUSTOMER_DATA) {
+ dict.Remove("customer_data");
+ }
+ if (proto.type() !=
+ sync_pb::AutofillWalletSpecifics::CREDIT_CARD_CLOUD_TOKEN_DATA) {
+ dict.Remove("cloud_token_data");
+ }
+ if (proto.type() != sync_pb::AutofillWalletSpecifics::PAYMENT_INSTRUMENT) {
+ dict.Remove("payment_instrument");
+ }
+ return base::Value(std::move(dict));
+ }
+
+ // UniquePosition
+ base::Value ToValue(const sync_pb::UniquePosition& proto) const {
+ UniquePosition pos = UniquePosition::FromProto(proto);
+ return base::Value(pos.ToDebugString());
+ }
+
+ private:
+ template
+ base::Value::Dict ToValueDictImpl(const P& proto) const {
+ base::Value::Dict dict;
+ ToValueVisitor visitor(options_, &dict);
+ VisitProtoFields(visitor, proto);
+ return dict;
+ }
+
+ base::Value ToValue(const std::string& value) const {
+ return base::Value(value);
+ }
+
+ base::Value ToValue(int64_t value) const {
+ return base::Value(base::NumberToString(value));
+ }
+ base::Value ToValue(uint64_t value) const {
+ return base::Value(base::NumberToString(value));
+ }
+ base::Value ToValue(uint32_t value) const {
+ return base::Value(base::NumberToString(value));
+ }
+ base::Value ToValue(int32_t value) const {
+ return base::Value(base::NumberToString(value));
+ }
+
+ base::Value ToValue(bool value) const { return base::Value(value); }
+ base::Value ToValue(float value) const { return base::Value(value); }
+ base::Value ToValue(double value) const { return base::Value(value); }
+
+ // Needs to be here to see all ToValue() overloads above.
+ template
+ void VisitImpl(P&, const char* field_name, const F& field) {
+ value_->Set(field_name, ToValue(field));
+ }
+
+ const ProtoValueConversionOptions options_;
+ const raw_ptr value_;
+};
+
+} // namespace
+
+#define IMPLEMENT_PROTO_TO_VALUE(Proto) \
+ base::Value Proto##ToValue(const sync_pb::Proto& proto) { \
+ return ToValueVisitor().ToValue(proto); \
+ }
+
+#define IMPLEMENT_PROTO_TO_VALUE_WITH_OPTIONS(Proto) \
+ base::Value Proto##ToValue(const sync_pb::Proto& proto, \
+ const ProtoValueConversionOptions& options) { \
+ return ToValueVisitor(options).ToValue(proto); \
+ }
+
+IMPLEMENT_PROTO_TO_VALUE(AppListSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(AppSettingSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(AppSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(ArcPackageSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(AutofillOfferSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(AutofillProfileSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(AutofillSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(AutofillWalletCredentialSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(AutofillWalletSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(AutofillWalletUsageSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(BankAccountDetails)
+IMPLEMENT_PROTO_TO_VALUE(BookmarkSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(ClientConfigParams)
+IMPLEMENT_PROTO_TO_VALUE(CollaborationGroupSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(ContactInfoSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(CookieSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(CrossUserSharingPublicKey)
+IMPLEMENT_PROTO_TO_VALUE(DebugEventInfo)
+IMPLEMENT_PROTO_TO_VALUE(DebugInfo)
+IMPLEMENT_PROTO_TO_VALUE(DeviceDetails)
+IMPLEMENT_PROTO_TO_VALUE(DeviceInfoSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(DictionarySpecifics)
+IMPLEMENT_PROTO_TO_VALUE(EncryptedData)
+IMPLEMENT_PROTO_TO_VALUE(EntityMetadata)
+IMPLEMENT_PROTO_TO_VALUE(EntitySpecifics)
+IMPLEMENT_PROTO_TO_VALUE(EwalletDetails)
+IMPLEMENT_PROTO_TO_VALUE(ExtensionSettingSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(ExtensionSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(GlobalIdDirective)
+IMPLEMENT_PROTO_TO_VALUE(HistoryDeleteDirectiveSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(HistorySpecifics)
+IMPLEMENT_PROTO_TO_VALUE(IncomingPasswordSharingInvitationSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(LinkedAppIconInfo)
+IMPLEMENT_PROTO_TO_VALUE(ManagedUserSettingSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(NavigationRedirect)
+IMPLEMENT_PROTO_TO_VALUE(NigoriSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(OsPreferenceSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(OsPriorityPreferenceSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(OutgoingPasswordSharingInvitationSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(PasswordSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(PasswordSpecificsData)
+IMPLEMENT_PROTO_TO_VALUE(PasswordSpecificsData_Notes)
+IMPLEMENT_PROTO_TO_VALUE(PasswordSpecificsData_Notes_Note)
+IMPLEMENT_PROTO_TO_VALUE(PaymentInstrument)
+IMPLEMENT_PROTO_TO_VALUE(PaymentsCustomerData)
+IMPLEMENT_PROTO_TO_VALUE(PlusAddressSettingSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(PlusAddressSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(PowerBookmarkSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(PreferenceSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(PrinterPPDReference)
+IMPLEMENT_PROTO_TO_VALUE(PrinterSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(PrintersAuthorizationServerSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(PriorityPreferenceSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(ProductComparisonSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(ReadingListSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(SavedTabGroupSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(SearchEngineSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(SecurityEventSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(SendTabToSelfPush)
+IMPLEMENT_PROTO_TO_VALUE(SendTabToSelfSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(SessionHeader)
+IMPLEMENT_PROTO_TO_VALUE(SessionSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(SessionTab)
+IMPLEMENT_PROTO_TO_VALUE(SessionWindow)
+IMPLEMENT_PROTO_TO_VALUE(SharedCommentSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(SharingMessageSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(SyncCycleCompletedEventInfo)
+IMPLEMENT_PROTO_TO_VALUE(TabNavigation)
+IMPLEMENT_PROTO_TO_VALUE(ThemeSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(TimeRangeDirective)
+IMPLEMENT_PROTO_TO_VALUE(TypedUrlSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(UnencryptedSharingMessage)
+IMPLEMENT_PROTO_TO_VALUE(UrlDirective)
+IMPLEMENT_PROTO_TO_VALUE(UserConsentSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(UserEventSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(WalletCreditCardCloudTokenData)
+IMPLEMENT_PROTO_TO_VALUE(WalletMaskedCreditCard)
+IMPLEMENT_PROTO_TO_VALUE(WalletMetadataSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(WalletPostalAddress)
+IMPLEMENT_PROTO_TO_VALUE(WebApkSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(WebAppSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(WebauthnCredentialSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(WifiConfigurationSpecifics)
+IMPLEMENT_PROTO_TO_VALUE(WorkspaceDeskSpecifics)
+
+IMPLEMENT_PROTO_TO_VALUE_WITH_OPTIONS(ClientToServerMessage)
+IMPLEMENT_PROTO_TO_VALUE_WITH_OPTIONS(ClientToServerResponse)
+IMPLEMENT_PROTO_TO_VALUE_WITH_OPTIONS(SyncEntity)
+
+#undef IMPLEMENT_PROTO_TO_VALUE
+#undef IMPLEMENT_PROTO_TO_VALUE_WITH_OPTIONS
+
+} // namespace syncer
diff --git a/pyhindsight/lib/components/sync/protocol/proto_value_conversions.h b/pyhindsight/lib/components/sync/protocol/proto_value_conversions.h
new file mode 100644
index 0000000..cdc362b
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/proto_value_conversions.h
@@ -0,0 +1,360 @@
+// 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_PROTOCOL_PROTO_VALUE_CONVERSIONS_H_
+#define COMPONENTS_SYNC_PROTOCOL_PROTO_VALUE_CONVERSIONS_H_
+
+namespace base {
+class Value;
+}
+
+namespace sync_pb {
+class AppListSpecifics;
+class AppSettingSpecifics;
+class AppSpecifics;
+class ArcPackageSpecifics;
+class AutofillProfileSpecifics;
+class AutofillSpecifics;
+class AutofillOfferSpecifics;
+class AutofillWalletCredentialSpecifics;
+class AutofillWalletSpecifics;
+class AutofillWalletUsageSpecifics;
+class BankAccountDetails;
+class BookmarkSpecifics;
+class ClientConfigParams;
+class ClientToServerMessage;
+class ClientToServerResponse;
+class CollaborationGroupSpecifics;
+class ContactInfoSpecifics;
+class CookieSpecifics;
+class CrossUserSharingPublicKey;
+class DebugEventInfo;
+class DebugInfo;
+class DeviceDetails;
+class DeviceInfoSpecifics;
+class DictionarySpecifics;
+class EncryptedData;
+class EntityMetadata;
+class EntitySpecifics;
+class EwalletDetails;
+class ExtensionSettingSpecifics;
+class ExtensionSpecifics;
+class HistoryDeleteDirectiveSpecifics;
+class HistorySpecifics;
+class IncomingPasswordSharingInvitationSpecifics;
+class LinkedAppIconInfo;
+class ManagedUserSettingSpecifics;
+class NavigationRedirect;
+class NigoriSpecifics;
+class OsPreferenceSpecifics;
+class OsPriorityPreferenceSpecifics;
+class OutgoingPasswordSharingInvitationSpecifics;
+class PasswordSpecifics;
+class PasswordSpecificsData;
+class PaymentInstrument;
+class PaymentsCustomerData;
+class PlusAddressSettingSpecifics;
+class PlusAddressSpecifics;
+class PowerBookmarkSpecifics;
+class PreferenceSpecifics;
+class PrinterPPDReference;
+class PrinterSpecifics;
+class PrintersAuthorizationServerSpecifics;
+class PriorityPreferenceSpecifics;
+class ProductComparisonSpecifics;
+class ReadingListSpecifics;
+class SavedTabGroupSpecifics;
+class SearchEngineSpecifics;
+class SecurityEventSpecifics;
+class SendTabToSelfPush;
+class SendTabToSelfSpecifics;
+class SessionHeader;
+class SessionSpecifics;
+class SessionTab;
+class SessionWindow;
+class SharingMessageSpecifics;
+class SyncCycleCompletedEventInfo;
+class SyncEntity;
+class TabNavigation;
+class ThemeSpecifics;
+class TimeRangeDirective;
+class TypedUrlSpecifics;
+class UnencryptedSharingMessage;
+class UrlDirective;
+class UserConsentSpecifics;
+class UserEventSpecifics;
+class WalletCreditCardCloudTokenData;
+class WalletMaskedCreditCard;
+class WalletMetadataSpecifics;
+class WalletPostalAddress;
+class WebApkSpecifics;
+class WebAppSpecifics;
+class WebauthnCredentialSpecifics;
+class WifiConfigurationSpecifics;
+class WorkspaceDeskSpecifics;
+} // namespace sync_pb
+
+// Keep this file in sync with the .proto files in this directory.
+//
+// Utility functions to convert sync protocol buffers to dictionaries.
+// Each protocol field is mapped to a key of the same name. Repeated
+// fields are mapped to array values and sub-messages are mapped to
+// sub-dictionary values.
+
+namespace syncer {
+
+base::Value AppListSpecificsToValue(const sync_pb::AppListSpecifics& proto);
+
+base::Value AppSettingSpecificsToValue(
+ const sync_pb::AppSettingSpecifics& app_setting_specifics);
+
+base::Value AppSpecificsToValue(const sync_pb::AppSpecifics& app_specifics);
+
+base::Value ArcPackageSpecificsToValue(
+ const sync_pb::ArcPackageSpecifics& proto);
+
+base::Value AutofillOfferSpecificsToValue(
+ const sync_pb::AutofillOfferSpecifics& autofill_offer_specifics);
+
+base::Value AutofillProfileSpecificsToValue(
+ const sync_pb::AutofillProfileSpecifics& autofill_profile_specifics);
+
+base::Value AutofillSpecificsToValue(
+ const sync_pb::AutofillSpecifics& autofill_specifics);
+
+base::Value AutofillWalletCredentialSpecificsToValue(
+ const sync_pb::AutofillWalletCredentialSpecifics&
+ autofill_wallet_credential_specifics);
+
+base::Value AutofillWalletSpecificsToValue(
+ const sync_pb::AutofillWalletSpecifics& autofill_wallet_specifics);
+
+base::Value AutofillWalletUsageSpecificsToValue(
+ const sync_pb::AutofillWalletUsageSpecifics&
+ autofill_wallet_usage_specifics);
+
+base::Value BankAccountDetailsToValue(
+ const sync_pb::BankAccountDetails& bank_account_details);
+
+base::Value BookmarkSpecificsToValue(
+ const sync_pb::BookmarkSpecifics& bookmark_specifics);
+
+base::Value ClientConfigParamsToValue(const sync_pb::ClientConfigParams& proto);
+
+base::Value CollaborationGroupSpecificsToValue(
+ const sync_pb::CollaborationGroupSpecifics& proto);
+
+base::Value ContactInfoSpecificsToValue(
+ const sync_pb::ContactInfoSpecifics& proto);
+
+base::Value CookieSpecificsToValue(const sync_pb::CookieSpecifics& proto);
+
+base::Value DebugEventInfoToValue(const sync_pb::DebugEventInfo& proto);
+
+base::Value DebugInfoToValue(const sync_pb::DebugInfo& proto);
+
+base::Value DeviceDetailsToValue(const sync_pb::DeviceDetails& device_details);
+
+base::Value DeviceInfoSpecificsToValue(
+ const sync_pb::DeviceInfoSpecifics& device_info_specifics);
+
+base::Value DictionarySpecificsToValue(
+ const sync_pb::DictionarySpecifics& dictionary_specifics);
+
+base::Value EncryptedDataToValue(const sync_pb::EncryptedData& encrypted_data);
+
+base::Value EntityMetadataToValue(const sync_pb::EntityMetadata& metadata);
+
+base::Value EntitySpecificsToValue(const sync_pb::EntitySpecifics& specifics);
+
+base::Value EwalletDetailsToValue(
+ const sync_pb::EwalletDetails& ewallet_details);
+
+base::Value ExtensionSettingSpecificsToValue(
+ const sync_pb::ExtensionSettingSpecifics& extension_setting_specifics);
+
+base::Value ExtensionSpecificsToValue(
+ const sync_pb::ExtensionSpecifics& extension_specifics);
+
+base::Value HistoryDeleteDirectiveSpecificsToValue(
+ const sync_pb::HistoryDeleteDirectiveSpecifics&
+ history_delete_directive_specifics);
+
+base::Value HistorySpecificsToValue(
+ const sync_pb::HistorySpecifics& history_specifics);
+
+base::Value IncomingPasswordSharingInvitationSpecificsToValue(
+ const sync_pb::IncomingPasswordSharingInvitationSpecifics& specifics);
+
+base::Value LinkedAppIconInfoToValue(
+ const sync_pb::LinkedAppIconInfo& linked_app_icon_info);
+
+base::Value ManagedUserSettingSpecificsToValue(
+ const sync_pb::ManagedUserSettingSpecifics& managed_user_setting_specifics);
+
+base::Value NavigationRedirectToValue(
+ const sync_pb::NavigationRedirect& navigation_redirect);
+
+base::Value NigoriSpecificsToValue(
+ const sync_pb::NigoriSpecifics& nigori_specifics);
+
+base::Value OsPreferenceSpecificsToValue(
+ const sync_pb::OsPreferenceSpecifics& specifics);
+
+base::Value OsPriorityPreferenceSpecificsToValue(
+ const sync_pb::OsPriorityPreferenceSpecifics& specifics);
+
+base::Value OutgoingPasswordSharingInvitationSpecificsToValue(
+ const sync_pb::OutgoingPasswordSharingInvitationSpecifics& specifics);
+
+base::Value PasswordSpecificsToValue(
+ const sync_pb::PasswordSpecifics& password_specifics);
+
+base::Value PasswordSpecificsDataToValue(
+ const sync_pb::PasswordSpecificsData& password_specifics_data);
+
+base::Value PaymentInstrumentToValue(
+ const sync_pb::PaymentInstrument& payment_instrument);
+
+base::Value PaymentsCustomerDataToValue(
+ const sync_pb::PaymentsCustomerData& payments_customer_data);
+
+base::Value PlusAddressSettingSpecificsToValue(
+ const sync_pb::PlusAddressSettingSpecifics& plus_address_setting_specifics);
+
+base::Value PlusAddressSpecificsToValue(
+ const sync_pb::PlusAddressSpecifics& plus_address_specifics);
+
+base::Value PowerBookmarkSpecificsToValue(
+ const sync_pb::PowerBookmarkSpecifics& power_bookmark_specifics);
+
+base::Value PreferenceSpecificsToValue(
+ const sync_pb::PreferenceSpecifics& password_specifics);
+
+base::Value PrinterPPDReferenceToValue(
+ const sync_pb::PrinterPPDReference& proto);
+
+base::Value PrinterSpecificsToValue(
+ const sync_pb::PrinterSpecifics& printer_specifics);
+
+base::Value PrintersAuthorizationServerSpecificsToValue(
+ const sync_pb::PrintersAuthorizationServerSpecifics&
+ printers_authorization_server_specifics);
+
+base::Value PriorityPreferenceSpecificsToValue(
+ const sync_pb::PriorityPreferenceSpecifics& proto);
+
+base::Value ProductComparisonSpecificsToValue(
+ const sync_pb::ProductComparisonSpecifics& product_comparison_specifics);
+
+base::Value CrossUserSharingPublicKeyToValue(
+ const sync_pb::CrossUserSharingPublicKey& proto);
+
+base::Value ReadingListSpecificsToValue(
+ const sync_pb::ReadingListSpecifics& proto);
+
+base::Value SavedTabGroupSpecificsToValue(
+ const sync_pb::SavedTabGroupSpecifics& saved_tab_group_specifics);
+
+base::Value SearchEngineSpecificsToValue(
+ const sync_pb::SearchEngineSpecifics& search_engine_specifics);
+
+base::Value SendTabToSelfPushToValue(
+ const sync_pb::SendTabToSelfPush& send_tab_push);
+
+base::Value SendTabToSelfSpecificsToValue(
+ const sync_pb::SendTabToSelfSpecifics& send_tab_specifics);
+
+base::Value SecurityEventSpecificsToValue(
+ const sync_pb::SecurityEventSpecifics& security_event_specifics);
+
+base::Value SessionHeaderToValue(const sync_pb::SessionHeader& session_header);
+
+base::Value SessionSpecificsToValue(
+ const sync_pb::SessionSpecifics& session_specifics);
+
+base::Value SessionTabToValue(const sync_pb::SessionTab& session_tab);
+
+base::Value SessionWindowToValue(const sync_pb::SessionWindow& session_window);
+
+base::Value SharingMessageSpecificsToValue(
+ const sync_pb::SharingMessageSpecifics& sharing_message_specifics);
+
+base::Value SyncCycleCompletedEventInfoToValue(
+ const sync_pb::SyncCycleCompletedEventInfo& proto);
+
+base::Value TabNavigationToValue(const sync_pb::TabNavigation& tab_navigation);
+
+base::Value ThemeSpecificsToValue(
+ const sync_pb::ThemeSpecifics& theme_specifics);
+
+base::Value TimeRangeDirectiveToValue(
+ const sync_pb::TimeRangeDirective& time_range_directive);
+
+base::Value TypedUrlSpecificsToValue(
+ const sync_pb::TypedUrlSpecifics& typed_url_specifics);
+
+base::Value UnencryptedSharingMessageToValue(
+ const sync_pb::UnencryptedSharingMessage& proto);
+
+base::Value UrlDirectiveToValue(
+ const sync_pb::UrlDirective& time_range_directive);
+
+base::Value UserConsentSpecificsToValue(
+ const sync_pb::UserConsentSpecifics& user_consent_specifics);
+
+base::Value UserEventSpecificsToValue(
+ const sync_pb::UserEventSpecifics& user_event_specifics);
+
+base::Value WalletCreditCardCloudTokenDataToValue(
+ const sync_pb::WalletCreditCardCloudTokenData& cloud_token_data);
+
+base::Value WalletMaskedCreditCardToValue(
+ const sync_pb::WalletMaskedCreditCard& wallet_masked_card);
+
+base::Value WalletMetadataSpecificsToValue(
+ const sync_pb::WalletMetadataSpecifics& wallet_metadata_specifics);
+
+base::Value WalletPostalAddressToValue(
+ const sync_pb::WalletPostalAddress& wallet_postal_address);
+
+base::Value WebApkSpecificsToValue(
+ const sync_pb::WebApkSpecifics& web_apk_specifics);
+
+base::Value WebAppSpecificsToValue(
+ const sync_pb::WebAppSpecifics& web_app_specifics);
+
+base::Value WebAuthnCredentialSpecificsToValue(
+ const sync_pb::WebauthnCredentialSpecifics& webauthn_credential_specifics);
+
+base::Value WifiConfigurationSpecificsToValue(
+ const sync_pb::WifiConfigurationSpecifics& wifi_configuration_specifics);
+
+base::Value WorkspaceDeskSpecificsToValue(
+ const sync_pb::WorkspaceDeskSpecifics& workspace_desk_specifics);
+
+// ToValue functions that allow omitting specifics and other fields.
+
+struct ProtoValueConversionOptions {
+ // Whether to include specifics.
+ bool include_specifics = true;
+
+ // Whether to include default values which are set in GetUpdateTriggers.
+ bool include_full_get_update_triggers = true;
+};
+
+base::Value ClientToServerMessageToValue(
+ const sync_pb::ClientToServerMessage& proto,
+ const ProtoValueConversionOptions& options);
+
+base::Value ClientToServerResponseToValue(
+ const sync_pb::ClientToServerResponse& proto,
+ const ProtoValueConversionOptions& options);
+
+base::Value SyncEntityToValue(const sync_pb::SyncEntity& entity,
+ const ProtoValueConversionOptions& options);
+
+} // namespace syncer
+
+#endif // COMPONENTS_SYNC_PROTOCOL_PROTO_VALUE_CONVERSIONS_H_
diff --git a/pyhindsight/lib/components/sync/protocol/proto_value_conversions_unittest.cc b/pyhindsight/lib/components/sync/protocol/proto_value_conversions_unittest.cc
new file mode 100644
index 0000000..3333391
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/proto_value_conversions_unittest.cc
@@ -0,0 +1,397 @@
+// 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.
+
+#include "components/sync/protocol/proto_value_conversions.h"
+
+#include
+#include
+#include
+
+#include "base/strings/string_number_conversions.h"
+#include "base/time/time.h"
+#include "base/values.h"
+#include "components/sync/base/data_type.h"
+#include "components/sync/base/unique_position.h"
+#include "components/sync/protocol/app_setting_specifics.pb.h"
+#include "components/sync/protocol/app_specifics.pb.h"
+#include "components/sync/protocol/autofill_specifics.pb.h"
+#include "components/sync/protocol/bookmark_specifics.pb.h"
+#include "components/sync/protocol/collaboration_group_specifics.pb.h"
+#include "components/sync/protocol/contact_info_specifics.pb.h"
+#include "components/sync/protocol/cookie_specifics.pb.h"
+#include "components/sync/protocol/data_type_progress_marker.pb.h"
+#include "components/sync/protocol/device_info_specifics.pb.h"
+#include "components/sync/protocol/encryption.pb.h"
+#include "components/sync/protocol/entity_specifics.pb.h"
+#include "components/sync/protocol/extension_setting_specifics.pb.h"
+#include "components/sync/protocol/extension_specifics.pb.h"
+#include "components/sync/protocol/managed_user_setting_specifics.pb.h"
+#include "components/sync/protocol/nigori_specifics.pb.h"
+#include "components/sync/protocol/os_preference_specifics.pb.h"
+#include "components/sync/protocol/os_priority_preference_specifics.pb.h"
+#include "components/sync/protocol/password_specifics.pb.h"
+#include "components/sync/protocol/preference_specifics.pb.h"
+#include "components/sync/protocol/priority_preference_specifics.pb.h"
+#include "components/sync/protocol/product_comparison_specifics.pb.h"
+#include "components/sync/protocol/search_engine_specifics.pb.h"
+#include "components/sync/protocol/session_specifics.pb.h"
+#include "components/sync/protocol/sharing_message_specifics.pb.h"
+#include "components/sync/protocol/sync.pb.h"
+#include "components/sync/protocol/sync_entity.pb.h"
+#include "components/sync/protocol/theme_specifics.pb.h"
+#include "components/sync/protocol/typed_url_specifics.pb.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace syncer {
+namespace {
+
+using testing::Not;
+
+// Keep this file in sync with the .proto files in this directory.
+
+#define DEFINE_SPECIFICS_TO_VALUE_TEST(Key) \
+ TEST(ProtoValueConversionsTest, Proto_##Key##_SpecificsToValue) { \
+ sync_pb::EntitySpecifics specifics; \
+ specifics.mutable_##Key(); \
+ base::Value value = EntitySpecificsToValue(specifics); \
+ ASSERT_TRUE(value.is_dict()); \
+ EXPECT_EQ(1u, value.GetDict().size()); \
+ }
+
+// We'd also like to check if we changed any field in our messages. However,
+// that's hard to do: sizeof could work, but it's platform-dependent.
+// default_instance().ByteSizeLong() won't change for most changes, since most
+// of our fields are optional. So we just settle for comments in the proto
+// files.
+
+DEFINE_SPECIFICS_TO_VALUE_TEST(encrypted)
+
+static_assert(56 == syncer::GetNumDataTypes(),
+ "When adding a new field, add a DEFINE_SPECIFICS_TO_VALUE_TEST "
+ "for your field below, and optionally a test for the specific "
+ "conversions.");
+
+DEFINE_SPECIFICS_TO_VALUE_TEST(app)
+DEFINE_SPECIFICS_TO_VALUE_TEST(app_list)
+DEFINE_SPECIFICS_TO_VALUE_TEST(app_setting)
+DEFINE_SPECIFICS_TO_VALUE_TEST(arc_package)
+DEFINE_SPECIFICS_TO_VALUE_TEST(autofill)
+DEFINE_SPECIFICS_TO_VALUE_TEST(autofill_offer)
+DEFINE_SPECIFICS_TO_VALUE_TEST(autofill_profile)
+DEFINE_SPECIFICS_TO_VALUE_TEST(autofill_wallet)
+DEFINE_SPECIFICS_TO_VALUE_TEST(autofill_wallet_credential)
+DEFINE_SPECIFICS_TO_VALUE_TEST(autofill_wallet_usage)
+DEFINE_SPECIFICS_TO_VALUE_TEST(bookmark)
+DEFINE_SPECIFICS_TO_VALUE_TEST(collaboration_group)
+DEFINE_SPECIFICS_TO_VALUE_TEST(contact_info)
+DEFINE_SPECIFICS_TO_VALUE_TEST(cookie)
+DEFINE_SPECIFICS_TO_VALUE_TEST(device_info)
+DEFINE_SPECIFICS_TO_VALUE_TEST(dictionary)
+DEFINE_SPECIFICS_TO_VALUE_TEST(extension)
+DEFINE_SPECIFICS_TO_VALUE_TEST(extension_setting)
+DEFINE_SPECIFICS_TO_VALUE_TEST(history)
+DEFINE_SPECIFICS_TO_VALUE_TEST(history_delete_directive)
+DEFINE_SPECIFICS_TO_VALUE_TEST(incoming_password_sharing_invitation)
+DEFINE_SPECIFICS_TO_VALUE_TEST(managed_user_setting)
+DEFINE_SPECIFICS_TO_VALUE_TEST(nigori)
+DEFINE_SPECIFICS_TO_VALUE_TEST(os_preference)
+DEFINE_SPECIFICS_TO_VALUE_TEST(os_priority_preference)
+DEFINE_SPECIFICS_TO_VALUE_TEST(outgoing_password_sharing_invitation)
+DEFINE_SPECIFICS_TO_VALUE_TEST(password)
+DEFINE_SPECIFICS_TO_VALUE_TEST(plus_address)
+DEFINE_SPECIFICS_TO_VALUE_TEST(plus_address_setting)
+DEFINE_SPECIFICS_TO_VALUE_TEST(preference)
+DEFINE_SPECIFICS_TO_VALUE_TEST(printer)
+DEFINE_SPECIFICS_TO_VALUE_TEST(printers_authorization_server)
+DEFINE_SPECIFICS_TO_VALUE_TEST(priority_preference)
+DEFINE_SPECIFICS_TO_VALUE_TEST(product_comparison)
+DEFINE_SPECIFICS_TO_VALUE_TEST(reading_list)
+DEFINE_SPECIFICS_TO_VALUE_TEST(saved_tab_group)
+DEFINE_SPECIFICS_TO_VALUE_TEST(search_engine)
+DEFINE_SPECIFICS_TO_VALUE_TEST(security_event)
+DEFINE_SPECIFICS_TO_VALUE_TEST(send_tab_to_self)
+DEFINE_SPECIFICS_TO_VALUE_TEST(session)
+DEFINE_SPECIFICS_TO_VALUE_TEST(shared_tab_group_data)
+DEFINE_SPECIFICS_TO_VALUE_TEST(sharing_message)
+DEFINE_SPECIFICS_TO_VALUE_TEST(theme)
+DEFINE_SPECIFICS_TO_VALUE_TEST(typed_url)
+DEFINE_SPECIFICS_TO_VALUE_TEST(user_consent)
+DEFINE_SPECIFICS_TO_VALUE_TEST(user_event)
+DEFINE_SPECIFICS_TO_VALUE_TEST(wallet_metadata)
+DEFINE_SPECIFICS_TO_VALUE_TEST(web_apk)
+DEFINE_SPECIFICS_TO_VALUE_TEST(web_app)
+DEFINE_SPECIFICS_TO_VALUE_TEST(webauthn_credential)
+DEFINE_SPECIFICS_TO_VALUE_TEST(wifi_configuration)
+DEFINE_SPECIFICS_TO_VALUE_TEST(workspace_desk)
+DEFINE_SPECIFICS_TO_VALUE_TEST(autofill_valuable)
+DEFINE_SPECIFICS_TO_VALUE_TEST(autofill_valuable_setting)
+DEFINE_SPECIFICS_TO_VALUE_TEST(shared_tab_group_account_data)
+DEFINE_SPECIFICS_TO_VALUE_TEST(shared_comment)
+
+TEST(ProtoValueConversionsTest, AutofillWalletSpecificsToValue) {
+ sync_pb::AutofillWalletSpecifics specifics;
+ specifics.mutable_masked_card()->set_name_on_card("Igloo");
+ specifics.mutable_address()->set_recipient_name("John");
+ specifics.mutable_customer_data()->set_id("123456");
+ specifics.mutable_cloud_token_data()->set_masked_card_id("1111");
+
+ specifics.set_type(sync_pb::AutofillWalletSpecifics::UNKNOWN);
+ base::Value::Dict value =
+ AutofillWalletSpecificsToValue(specifics).TakeDict();
+ EXPECT_FALSE(value.contains("masked_card"));
+ EXPECT_FALSE(value.contains("address"));
+ EXPECT_FALSE(value.contains("customer_data"));
+ EXPECT_FALSE(value.contains("cloud_token_data"));
+
+ specifics.set_type(sync_pb::AutofillWalletSpecifics::MASKED_CREDIT_CARD);
+ value = AutofillWalletSpecificsToValue(specifics).TakeDict();
+ EXPECT_TRUE(value.contains("masked_card"));
+ EXPECT_FALSE(value.contains("address"));
+ EXPECT_FALSE(value.contains("customer_data"));
+ EXPECT_FALSE(value.contains("cloud_token_data"));
+
+ specifics.set_type(sync_pb::AutofillWalletSpecifics::POSTAL_ADDRESS);
+ value = AutofillWalletSpecificsToValue(specifics).TakeDict();
+ EXPECT_FALSE(value.contains("masked_card"));
+ EXPECT_TRUE(value.contains("address"));
+ EXPECT_FALSE(value.contains("customer_data"));
+ EXPECT_FALSE(value.contains("cloud_token_data"));
+
+ specifics.set_type(sync_pb::AutofillWalletSpecifics::CUSTOMER_DATA);
+ value = AutofillWalletSpecificsToValue(specifics).TakeDict();
+ EXPECT_FALSE(value.contains("masked_card"));
+ EXPECT_FALSE(value.contains("address"));
+ EXPECT_TRUE(value.contains("customer_data"));
+ EXPECT_FALSE(value.contains("cloud_token_data"));
+
+ specifics.set_type(
+ sync_pb::AutofillWalletSpecifics::CREDIT_CARD_CLOUD_TOKEN_DATA);
+ value = AutofillWalletSpecificsToValue(specifics).TakeDict();
+ EXPECT_FALSE(value.contains("masked_card"));
+ EXPECT_FALSE(value.contains("address"));
+ EXPECT_FALSE(value.contains("customer_data"));
+ EXPECT_TRUE(value.contains("cloud_token_data"));
+}
+
+TEST(ProtoValueConversionsTest, BookmarkSpecificsData) {
+ const base::Time creation_time(base::Time::Now());
+ const std::string icon_url = "http://www.google.com/favicon.ico";
+ sync_pb::BookmarkSpecifics specifics;
+ specifics.set_creation_time_us(creation_time.ToInternalValue());
+ specifics.set_icon_url(icon_url);
+ sync_pb::MetaInfo* meta_1 = specifics.add_meta_info();
+ meta_1->set_key("key1");
+ meta_1->set_value("value1");
+ sync_pb::MetaInfo* meta_2 = specifics.add_meta_info();
+ meta_2->set_key("key2");
+ meta_2->set_value("value2");
+
+ base::Value::Dict value = BookmarkSpecificsToValue(specifics).TakeDict();
+ EXPECT_FALSE(value.empty());
+ const std::string* encoded_time = value.FindString("creation_time_us");
+ EXPECT_TRUE(encoded_time);
+ EXPECT_EQ(base::NumberToString(creation_time.ToInternalValue()),
+ *encoded_time);
+ const std::string* encoded_icon_url = value.FindString("icon_url");
+ EXPECT_TRUE(encoded_icon_url);
+ EXPECT_EQ(icon_url, *encoded_icon_url);
+
+ const base::Value::List* meta_info_list = value.FindList("meta_info");
+
+ EXPECT_EQ(2u, meta_info_list->size());
+ std::string meta_key;
+ std::string meta_value;
+ const auto& meta_info_value = (*meta_info_list)[0].GetDict();
+ ASSERT_TRUE((*meta_info_list)[0].is_dict());
+ EXPECT_STREQ("key1", meta_info_value.FindString("key")->c_str());
+ EXPECT_STREQ("value1", meta_info_value.FindString("value")->c_str());
+ const auto& meta_info_value_1 = (*meta_info_list)[1].GetDict();
+ ASSERT_TRUE((*meta_info_list)[1].is_dict());
+ EXPECT_STREQ("key2", meta_info_value_1.FindString("key")->c_str());
+ EXPECT_STREQ("value2", meta_info_value_1.FindString("value")->c_str());
+}
+
+TEST(ProtoValueConversionsTest, UniquePositionToValue) {
+ sync_pb::SyncEntity entity;
+ entity.mutable_unique_position()->set_custom_compressed_v1("test");
+
+ base::Value::Dict value =
+ SyncEntityToValue(entity, {.include_specifics = false}).TakeDict();
+ const std::string* unique_position = value.FindString("unique_position");
+ EXPECT_TRUE(unique_position);
+
+ std::string expected_unique_position =
+ UniquePosition::FromProto(entity.unique_position()).ToDebugString();
+ EXPECT_EQ(expected_unique_position, *unique_position);
+}
+
+TEST(ProtoValueConversionsTest, SyncEntityToValueIncludeSpecifics) {
+ sync_pb::SyncEntity entity;
+ entity.mutable_specifics();
+
+ base::Value::Dict value =
+ SyncEntityToValue(entity, {.include_specifics = true}).TakeDict();
+ EXPECT_TRUE(value.FindDict("specifics"));
+
+ value = SyncEntityToValue(entity, {.include_specifics = false}).TakeDict();
+ EXPECT_FALSE(value.FindDict("specifics"));
+}
+
+namespace {
+// Returns whether the given value has specifics under the entries in the given
+// path.
+bool ValueHasSpecifics(const base::Value::Dict& value,
+ const std::string& path) {
+ const base::Value::List* entities_list = value.FindListByDottedPath(path);
+ if (!entities_list) {
+ return false;
+ }
+
+ const base::Value& entry_dictionary_value = (*entities_list)[0];
+ if (!entry_dictionary_value.is_dict()) {
+ return false;
+ }
+
+ const base::Value::Dict& entry_dictionary = entry_dictionary_value.GetDict();
+ return entry_dictionary.FindDict("specifics") != nullptr;
+}
+
+MATCHER(ValueHasNonEmptyGetUpdateTriggers, "") {
+ const base::Value::Dict& value_dict = arg;
+
+ const base::Value::List* entities_list =
+ value_dict.FindListByDottedPath("get_updates.from_progress_marker");
+ if (!entities_list) {
+ *result_listener << "no from_progress_marker list";
+ return false;
+ }
+
+ const base::Value& entry_dictionary_value = entities_list->front();
+ if (!entry_dictionary_value.is_dict()) {
+ *result_listener << "from_progress_marker does not contain a dictionary";
+ return false;
+ }
+
+ const base::Value::Dict& entry_dictionary = entry_dictionary_value.GetDict();
+ const base::Value::Dict* get_update_triggers_dictionary =
+ entry_dictionary.FindDict("get_update_triggers");
+ if (!get_update_triggers_dictionary) {
+ *result_listener << "no get_update_triggers dictionary";
+ return false;
+ }
+
+ return !get_update_triggers_dictionary->empty();
+}
+} // namespace
+
+// Create a ClientToServerMessage with an EntitySpecifics. Converting it to
+// a value should respect the `include_specifics` flag.
+TEST(ProtoValueConversionsTest, ClientToServerMessageToValue) {
+ sync_pb::ClientToServerMessage message;
+ sync_pb::CommitMessage* commit_message = message.mutable_commit();
+ sync_pb::SyncEntity* entity = commit_message->add_entries();
+ entity->mutable_specifics();
+
+ base::Value::Dict value_with_specifics =
+ ClientToServerMessageToValue(message, {.include_specifics = true})
+ .TakeDict();
+ EXPECT_FALSE(value_with_specifics.empty());
+ EXPECT_TRUE(ValueHasSpecifics(value_with_specifics, "commit.entries"));
+
+ base::Value::Dict value_without_specifics =
+ ClientToServerMessageToValue(message, {.include_specifics = false})
+ .TakeDict();
+ EXPECT_FALSE(value_without_specifics.empty());
+ EXPECT_FALSE(ValueHasSpecifics(value_without_specifics, "commit.entries"));
+}
+
+TEST(ProtoValueConversionsTest, ClientToServerMessageToValueGUTriggers) {
+ sync_pb::ClientToServerMessage message;
+ sync_pb::GetUpdateTriggers* get_update_triggers =
+ message.mutable_get_updates()
+ ->add_from_progress_marker()
+ ->mutable_get_update_triggers();
+ get_update_triggers->set_client_dropped_hints(false);
+ get_update_triggers->set_server_dropped_hints(false);
+ get_update_triggers->set_datatype_refresh_nudges(0);
+ get_update_triggers->set_local_modification_nudges(0);
+ get_update_triggers->set_initial_sync_in_progress(false);
+ get_update_triggers->set_sync_for_resolve_conflict_in_progress(false);
+
+ base::Value::Dict value_with_full_gu_triggers =
+ ClientToServerMessageToValue(message,
+ {.include_full_get_update_triggers = true})
+ .TakeDict();
+ EXPECT_FALSE(value_with_full_gu_triggers.empty());
+ EXPECT_THAT(value_with_full_gu_triggers, ValueHasNonEmptyGetUpdateTriggers());
+
+ base::Value::Dict value_without_full_gu_triggers =
+ ClientToServerMessageToValue(message,
+ {.include_full_get_update_triggers = false})
+ .TakeDict();
+ EXPECT_FALSE(value_without_full_gu_triggers.empty());
+ EXPECT_THAT(value_without_full_gu_triggers,
+ Not(ValueHasNonEmptyGetUpdateTriggers()));
+}
+
+// Create a ClientToServerResponse with an EntitySpecifics. Converting it to
+// a value should respect the `include_specifics` flag.
+TEST(ProtoValueConversionsTest, ClientToServerResponseToValue) {
+ sync_pb::ClientToServerResponse message;
+ sync_pb::GetUpdatesResponse* response = message.mutable_get_updates();
+ sync_pb::SyncEntity* entity = response->add_entries();
+ entity->mutable_specifics();
+
+ base::Value::Dict value_with_specifics =
+ ClientToServerResponseToValue(message, {.include_specifics = true})
+ .TakeDict();
+ EXPECT_FALSE(value_with_specifics.empty());
+ EXPECT_TRUE(ValueHasSpecifics(value_with_specifics, "get_updates.entries"));
+
+ base::Value::Dict value_without_specifics =
+ ClientToServerResponseToValue(message, {.include_specifics = false})
+ .TakeDict();
+ EXPECT_FALSE(value_without_specifics.empty());
+ EXPECT_FALSE(
+ ValueHasSpecifics(value_without_specifics, "get_updates.entries"));
+}
+
+TEST(ProtoValueConversionsTest, CompareSpecificsData) {
+ sync_pb::ProductComparisonSpecifics specifics;
+ specifics.set_uuid("my_uuid");
+ specifics.set_creation_time_unix_epoch_millis(1708532099);
+ specifics.set_update_time_unix_epoch_millis(1708642103);
+ specifics.set_name("my_name");
+ specifics.add_data();
+ specifics.mutable_data(0)->set_url("https://www.foo.com");
+ specifics.add_data();
+ specifics.mutable_data(1)->set_url("https://www.bar.com");
+
+ base::Value::Dict value =
+ ProductComparisonSpecificsToValue(specifics).TakeDict();
+ EXPECT_FALSE(value.empty());
+ EXPECT_TRUE(value.FindString("uuid"));
+ EXPECT_STREQ("my_uuid", value.FindString("uuid")->c_str());
+ EXPECT_TRUE(value.FindString("creation_time_unix_epoch_millis"));
+ EXPECT_STREQ("1708532099",
+ value.FindString("creation_time_unix_epoch_millis")->c_str());
+ EXPECT_TRUE(value.FindString("update_time_unix_epoch_millis"));
+ EXPECT_STREQ("1708642103",
+ value.FindString("update_time_unix_epoch_millis")->c_str());
+ EXPECT_TRUE(value.FindString("name"));
+ EXPECT_STREQ("my_name", value.FindString("name")->c_str());
+ const base::Value::List* data_list = value.FindList("data");
+ EXPECT_TRUE(data_list);
+ EXPECT_EQ(2u, data_list->size());
+ EXPECT_TRUE((*data_list)[0].GetDict().FindString("url"));
+ EXPECT_STREQ("https://www.foo.com",
+ (*data_list)[0].GetDict().FindString("url")->c_str());
+ EXPECT_TRUE((*data_list)[1].GetDict().FindString("url"));
+ EXPECT_STREQ("https://www.bar.com",
+ (*data_list)[1].GetDict().FindString("url")->c_str());
+}
+
+} // namespace
+} // namespace syncer
diff --git a/pyhindsight/lib/components/sync/protocol/proto_visitors.h b/pyhindsight/lib/components/sync/protocol/proto_visitors.h
new file mode 100644
index 0000000..cf0615c
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/proto_visitors.h
@@ -0,0 +1,2154 @@
+// Copyright 2016 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_PROTOCOL_PROTO_VISITORS_H_
+#define COMPONENTS_SYNC_PROTOCOL_PROTO_VISITORS_H_
+
+#include "components/sync/base/data_type.h"
+#include "components/sync/protocol/app_list_specifics.pb.h"
+#include "components/sync/protocol/app_setting_specifics.pb.h"
+#include "components/sync/protocol/app_specifics.pb.h"
+#include "components/sync/protocol/arc_package_specifics.pb.h"
+#include "components/sync/protocol/autofill_offer_specifics.pb.h"
+#include "components/sync/protocol/autofill_specifics.pb.h"
+#include "components/sync/protocol/autofill_valuable_specifics.pb.h"
+#include "components/sync/protocol/autofill_wallet_credential_specifics.pb.h"
+#include "components/sync/protocol/autofill_wallet_usage_specifics.pb.h"
+#include "components/sync/protocol/bookmark_specifics.pb.h"
+#include "components/sync/protocol/collaboration_group_specifics.pb.h"
+#include "components/sync/protocol/contact_info_specifics.pb.h"
+#include "components/sync/protocol/cookie_specifics.pb.h"
+#include "components/sync/protocol/data_type_progress_marker.pb.h"
+#include "components/sync/protocol/data_type_state.pb.h"
+#include "components/sync/protocol/deletion_origin.pb.h"
+#include "components/sync/protocol/dictionary_specifics.pb.h"
+#include "components/sync/protocol/encryption.pb.h"
+#include "components/sync/protocol/entity_metadata.pb.h"
+#include "components/sync/protocol/entity_specifics.pb.h"
+#include "components/sync/protocol/extension_setting_specifics.pb.h"
+#include "components/sync/protocol/extension_specifics.pb.h"
+#include "components/sync/protocol/history_delete_directive_specifics.pb.h"
+#include "components/sync/protocol/history_specifics.pb.h"
+#include "components/sync/protocol/nigori_local_data.pb.h"
+#include "components/sync/protocol/nigori_specifics.pb.h"
+#include "components/sync/protocol/note_entity.pb.h"
+#include "components/sync/protocol/os_preference_specifics.pb.h"
+#include "components/sync/protocol/os_priority_preference_specifics.pb.h"
+#include "components/sync/protocol/password_sharing_invitation_specifics.pb.h"
+#include "components/sync/protocol/password_specifics.pb.h"
+#include "components/sync/protocol/persisted_entity_data.pb.h"
+#include "components/sync/protocol/plus_address_setting_specifics.pb.h"
+#include "components/sync/protocol/plus_address_specifics.pb.h"
+#include "components/sync/protocol/power_bookmark_specifics.pb.h"
+#include "components/sync/protocol/preference_specifics.pb.h"
+#include "components/sync/protocol/printer_specifics.pb.h"
+#include "components/sync/protocol/printers_authorization_server_specifics.pb.h"
+#include "components/sync/protocol/priority_preference_specifics.pb.h"
+#include "components/sync/protocol/product_comparison_specifics.pb.h"
+#include "components/sync/protocol/proto_enum_conversions.h"
+#include "components/sync/protocol/proto_value_conversions.h"
+#include "components/sync/protocol/reading_list_specifics.pb.h"
+#include "components/sync/protocol/saved_tab_group_specifics.pb.h"
+#include "components/sync/protocol/search_engine_specifics.pb.h"
+#include "components/sync/protocol/send_tab_to_self_specifics.pb.h"
+#include "components/sync/protocol/session_specifics.pb.h"
+#include "components/sync/protocol/shared_comment_specifics.pb.h"
+#include "components/sync/protocol/shared_tab_group_data_specifics.pb.h"
+#include "components/sync/protocol/sharing_message_specifics.pb.h"
+#include "components/sync/protocol/sync.pb.h"
+#include "components/sync/protocol/sync_entity.pb.h"
+#include "components/sync/protocol/sync_invalidations_payload.pb.h"
+#include "components/sync/protocol/tab_group_attribution_metadata.pb.h"
+#include "components/sync/protocol/theme_specifics.pb.h"
+#include "components/sync/protocol/theme_specifics_ios.pb.h"
+#include "components/sync/protocol/theme_types.pb.h"
+#include "components/sync/protocol/typed_url_specifics.pb.h"
+#include "components/sync/protocol/unencrypted_sharing_message.pb.h"
+#include "components/sync/protocol/unique_position.pb.h"
+#include "components/sync/protocol/user_consent_specifics.pb.h"
+#include "components/sync/protocol/user_event_specifics.pb.h"
+#include "components/sync/protocol/web_apk_specifics.pb.h"
+#include "components/sync/protocol/web_app_specifics.pb.h"
+#include "components/sync/protocol/webauthn_credential_specifics.pb.h"
+#include "components/sync/protocol/workspace_desk_specifics.pb.h"
+
+// This file implements VisitProtoFields() functions for sync protos.
+//
+// VisitProtoFields(visitor, proto) calls `visitor` for each field in
+// `proto`. When called, `visitor` gets passed `proto`, field name and
+// field value.
+//
+// VisitProtoFields() used to implement two distinctive features:
+// 1. Serialization into base::Value::Dict
+// 2. Proto memory usage estimation
+//
+// To achieve that it's very important for VisitProtoFields() to be free
+// of any logic. It must just call visitor for each field in a proto.
+//
+// Logic (like clobbering sensitive fields) must be implemented in visitors.
+// For example see how ToValueVisitor (from proto_value_conversions.cc)
+// implements various customizations.
+
+#define VISIT_(Kind, field) \
+ if (proto.has_##field()) \
+ visitor.Visit##Kind(proto, #field, proto.field())
+
+// Generic version, calls visitor.Visit(). Handles almost everything except
+// for special cases below.
+#define VISIT(field) VISIT_(, field)
+
+// 'bytes' protobuf type maps to std::string, and is indistinguishable
+// from 'string' type. To solve that 'bytes' fields are special cased to
+// call visitor.VisitBytes().
+#define VISIT_BYTES(field) VISIT_(Bytes, field)
+
+// We could use template magic (std::is_enum) to handle enums, but that would
+// complicate visitors, and besides we already have special case for 'bytes',
+// so just add one more special case. Calls visitor.VisitEnum().
+#define VISIT_ENUM(field) VISIT_(Enum, field)
+
+// Repeated fields are always present, so there are no 'has_' methods.
+// This macro unconditionally calls visitor.Visit().
+#define VISIT_REP(field) visitor.Visit(proto, #field, proto.field());
+
+// Repeated fields are always present, so there are no 'has_' methods.
+// This macro unconditionally calls visitor.VisitBytes().
+#define VISIT_REP_BYTES(field) visitor.VisitBytes(proto, #field, proto.field());
+
+// Values that are secrets do not have their contents reported in debugging
+// output, only their lengths, but are still counted for things like memory
+// estimation.
+#define VISIT_SECRET(field) VISIT_(Secret, field)
+
+#define VISIT_PROTO_FIELDS(proto) \
+ template \
+ void VisitProtoFields(V& visitor, proto)
+
+namespace syncer {
+
+VISIT_PROTO_FIELDS(const sync_pb::AppListSpecifics& proto) {
+ VISIT(item_id);
+ VISIT_ENUM(item_type);
+ VISIT(item_name);
+ VISIT(parent_id);
+ VISIT(item_ordinal);
+ VISIT(item_pin_ordinal);
+ VISIT(promise_package_id);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::AppNotificationSettings& proto) {
+ VISIT(initial_setup_done);
+ VISIT(disabled);
+ VISIT(oauth_client_id);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::AppSettingSpecifics& proto) {
+ VISIT(extension_setting);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::AppSpecifics& proto) {
+ VISIT(extension);
+ VISIT(notification_settings);
+ VISIT(app_launch_ordinal);
+ VISIT(page_ordinal);
+ VISIT_ENUM(launch_type);
+ VISIT_REP(linked_app_icons);
+ VISIT(bookmark_app_url);
+ VISIT(bookmark_app_description);
+ VISIT(bookmark_app_icon_color);
+ VISIT(bookmark_app_scope);
+ VISIT(bookmark_app_theme_color);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::ArcPackageSpecifics& proto) {
+ VISIT(package_name);
+ VISIT(package_version);
+ VISIT(last_backup_android_id);
+ VISIT(last_backup_time);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::AutofillOfferSpecifics& proto) {
+ VISIT(id);
+ VISIT(offer_details_url);
+ VISIT_REP(merchant_domain);
+ VISIT_REP(merchant_app_package);
+ VISIT(offer_expiry_date);
+ VISIT(card_linked_offer_data);
+ VISIT(promo_code_offer_data);
+ VISIT(display_strings);
+ VISIT(percentage_reward);
+ VISIT(fixed_amount_reward);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::AutofillOfferSpecifics::CardLinkedOfferData& proto) {
+ VISIT_REP(instrument_id);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::AutofillOfferSpecifics::PromoCodeOfferData& proto) {
+ VISIT(promo_code);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::AutofillOfferSpecifics::DisplayStrings& proto) {
+ VISIT(value_prop_text);
+ VISIT(see_details_text_mobile);
+ VISIT(see_details_text_desktop);
+ VISIT(usage_instructions_text_mobile);
+ VISIT(usage_instructions_text_desktop);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::AutofillOfferSpecifics::PercentageReward& proto) {
+ VISIT(percentage);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::AutofillOfferSpecifics::FixedAmountReward& proto) {
+ VISIT(amount);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::AutofillProfileSpecifics& proto) {
+ VISIT(guid);
+ VISIT(deprecated_origin);
+ VISIT(use_count);
+ VISIT(use_date);
+ VISIT(profile_label);
+ VISIT_REP(name_first);
+ VISIT_REP(name_middle);
+ VISIT_REP(name_last_prefix);
+ VISIT_REP(name_last_core);
+ VISIT_REP(name_last_first);
+ VISIT_REP(name_last_conjunction);
+ VISIT_REP(name_last_second);
+ VISIT_REP(name_last);
+ VISIT_REP(name_full);
+
+ VISIT_REP(name_first_status);
+ VISIT_REP(name_middle_status);
+ VISIT_REP(name_last_prefix_status);
+ VISIT_REP(name_last_core_status);
+ VISIT_REP(name_last_first_status);
+ VISIT_REP(name_last_conjunction_status);
+ VISIT_REP(name_last_second_status);
+ VISIT_REP(name_last_status);
+ VISIT_REP(name_full_status);
+
+ VISIT(alternative_full_name);
+ VISIT(alternative_given_name);
+ VISIT(alternative_family_name);
+
+ VISIT_ENUM(alternative_full_name_status);
+ VISIT_ENUM(alternative_given_name_status);
+ VISIT_ENUM(alternative_family_name_status);
+
+ VISIT_REP(email_address);
+ VISIT(company_name);
+
+ VISIT(address_home_line1);
+ VISIT(address_home_line2);
+ VISIT(address_home_city);
+ VISIT(address_home_state);
+ VISIT(address_home_zip);
+ VISIT(address_home_zip_prefix);
+ VISIT(address_home_zip_suffix);
+ VISIT(address_home_country);
+ VISIT(address_home_landmark);
+ VISIT(address_home_overflow);
+ VISIT(address_home_between_streets);
+ VISIT(address_home_between_streets_1);
+ VISIT(address_home_between_streets_2);
+ VISIT(address_home_between_streets_or_landmark);
+ VISIT(address_home_overflow_and_landmark);
+ VISIT(address_home_admin_level_2);
+ VISIT(address_home_street_address);
+ VISIT(address_home_sorting_code);
+ VISIT(address_home_dependent_locality);
+ VISIT(address_home_thoroughfare_name);
+ VISIT(address_home_thoroughfare_number);
+ VISIT(address_home_subpremise_name);
+ VISIT(address_home_apt);
+ VISIT(address_home_apt_num);
+ VISIT(address_home_apt_type);
+ VISIT(address_home_street_location_and_locality);
+ VISIT(address_home_thoroughfare_number_and_apt);
+
+ VISIT_ENUM(address_home_city_status);
+ VISIT_ENUM(address_home_state_status);
+ VISIT_ENUM(address_home_zip_status);
+ VISIT_ENUM(address_home_zip_prefix_status);
+ VISIT_ENUM(address_home_zip_suffix_status);
+ VISIT_ENUM(address_home_country_status);
+ VISIT_ENUM(address_home_landmark_status);
+ VISIT_ENUM(address_home_overflow_status);
+ VISIT_ENUM(address_home_between_streets_status);
+ VISIT_ENUM(address_home_between_streets_1_status);
+ VISIT_ENUM(address_home_between_streets_2_status);
+ VISIT_ENUM(address_home_between_streets_or_landmark_status);
+ VISIT_ENUM(address_home_overflow_and_landmark_status);
+ VISIT_ENUM(address_home_admin_level_2_status);
+ VISIT_ENUM(address_home_street_address_status);
+ VISIT_ENUM(address_home_sorting_code_status);
+ VISIT_ENUM(address_home_dependent_locality_status);
+ VISIT_ENUM(address_home_thoroughfare_name_status);
+ VISIT_ENUM(address_home_thoroughfare_number_status);
+ VISIT_ENUM(address_home_subpremise_name_status);
+ VISIT_ENUM(address_home_apt_status);
+ VISIT_ENUM(address_home_apt_num_status);
+ VISIT_ENUM(address_home_apt_type_status);
+ VISIT_ENUM(address_home_street_location_and_locality_status);
+ VISIT_ENUM(address_home_thoroughfare_number_and_apt_status);
+
+ VISIT(address_home_language_code);
+ VISIT_REP(phone_home_whole_number);
+ VISIT(validity_state_bitfield);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::AutofillSpecifics& proto) {
+ VISIT(name);
+ VISIT(value);
+ VISIT_REP(usage_timestamp);
+ VISIT(profile);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::AutofillWalletCredentialSpecifics& proto) {
+ VISIT(instrument_id);
+ VISIT_SECRET(cvc);
+ VISIT(last_updated_time_unix_epoch_millis);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::AutofillWalletUsageSpecifics& proto) {
+ VISIT(guid);
+ VISIT(virtual_card_usage_data);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::AutofillWalletUsageSpecifics::VirtualCardUsageData& proto) {
+ VISIT(instrument_id);
+ VISIT(virtual_card_last_four);
+ VISIT(merchant_url);
+ VISIT(merchant_app_package);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::AutofillWalletSpecifics& proto) {
+ VISIT_ENUM(type);
+ VISIT(masked_card);
+ VISIT(address);
+ VISIT(customer_data);
+ VISIT(cloud_token_data);
+ VISIT(payment_instrument);
+ VISIT(payment_instrument_creation_option);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::BnplCreationOption& proto) {
+ VISIT(issuer_id);
+ VISIT_REP(eligible_price_range);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::BnplIssuerDetails& proto) {
+ VISIT(issuer_id);
+ VISIT_REP(eligible_price_range);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::BookmarkSpecifics& proto) {
+ VISIT(url);
+ VISIT_BYTES(favicon);
+ VISIT(guid);
+ VISIT(legacy_canonicalized_title);
+ VISIT(creation_time_us);
+ VISIT(icon_url);
+ VISIT_REP(meta_info);
+ VISIT(full_title);
+ VISIT(parent_guid);
+ VISIT_ENUM(type);
+ VISIT(unique_position);
+ VISIT(last_used_time_us);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::ChromiumExtensionsActivity& proto) {
+ VISIT(extension_id);
+ VISIT(bookmark_writes_since_last_commit);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::CollaborationGroupSpecifics& proto) {
+ VISIT(collaboration_id);
+ VISIT(changed_at_timestamp_millis_since_unix_epoch);
+ VISIT(consistency_token);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::ComparisonData& proto) {
+ VISIT(url);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::ProductComparison& proto) {
+ VISIT(name);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::ProductComparisonItem& proto) {
+ VISIT(product_comparison_uuid);
+ VISIT(url);
+ VISIT(unique_position);
+ VISIT(title);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::ProductComparisonSpecifics& proto) {
+ VISIT(uuid);
+ VISIT(creation_time_unix_epoch_millis);
+ VISIT(update_time_unix_epoch_millis);
+ VISIT(name);
+ VISIT_REP(data);
+ VISIT(product_comparison);
+ VISIT(product_comparison_item);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::ContactInfoSpecifics& proto) {
+ VISIT(guid);
+ VISIT_ENUM(address_type);
+ VISIT(use_count);
+ VISIT(use_date_unix_epoch_seconds);
+ VISIT(use_date2_unix_epoch_seconds);
+ VISIT(use_date3_unix_epoch_seconds);
+ VISIT(date_modified_unix_epoch_seconds);
+ VISIT(language_code);
+ VISIT(profile_label);
+ VISIT(initial_creator_id);
+ VISIT(last_modifier_id);
+ VISIT(name_first);
+ VISIT(name_middle);
+ VISIT(name_last);
+ VISIT(name_last_prefix);
+ VISIT(name_last_core);
+ VISIT(name_last_first);
+ VISIT(name_last_conjunction);
+ VISIT(name_last_second);
+ VISIT(name_full);
+ VISIT(alternative_full_name);
+ VISIT(alternative_given_name);
+ VISIT(alternative_family_name);
+ VISIT(email_address);
+ VISIT(company_name);
+ VISIT(address_city);
+ VISIT(address_state);
+ VISIT(address_zip);
+ VISIT(address_zip_prefix);
+ VISIT(address_zip_suffix);
+ VISIT(address_country);
+ VISIT(address_street_address);
+ VISIT(address_sorting_code);
+ VISIT(address_dependent_locality);
+ VISIT(address_thoroughfare_name);
+ VISIT(address_thoroughfare_number);
+ VISIT(address_subpremise_name);
+ VISIT(address_apt);
+ VISIT(address_apt_num);
+ VISIT(address_apt_type);
+ VISIT(address_floor);
+ VISIT(address_landmark);
+ VISIT(address_between_streets);
+ VISIT(address_admin_level_2);
+ VISIT(phone_home_whole_number);
+ VISIT(address_street_location);
+ VISIT(address_overflow);
+ VISIT(address_between_streets_1);
+ VISIT(address_between_streets_2);
+ VISIT(address_between_streets_or_landmark);
+ VISIT(address_overflow_and_landmark);
+ VISIT(address_street_location_and_locality);
+ VISIT(address_thoroughfare_number_and_apt);
+ VISIT(invisible_in_autofill);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::ContactInfoSpecifics::Observation& proto) {
+ VISIT(type);
+ VISIT(form_hash);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::ContactInfoSpecifics::TokenMetadata& proto) {
+ VISIT_ENUM(status);
+ VISIT_REP(observations);
+ VISIT(value_hash);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::ContactInfoSpecifics::StringToken& proto) {
+ VISIT(value);
+ VISIT(metadata);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::CookieSpecifics& proto) {
+ VISIT(unique_key);
+ VISIT(name);
+ VISIT(value);
+ VISIT(domain);
+ VISIT(path);
+ VISIT(creation_time_windows_epoch_micros);
+ VISIT(expiry_time_windows_epoch_micros);
+ VISIT(last_access_time_windows_epoch_micros);
+ VISIT(last_update_time_windows_epoch_micros);
+ VISIT(secure);
+ VISIT(httponly);
+ VISIT_ENUM(site_restrictions);
+ VISIT_ENUM(priority);
+ VISIT_ENUM(source_scheme);
+ VISIT(partition_key);
+ VISIT(source_port);
+ VISIT_ENUM(source_type);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::CookieSpecifics::SerializedCookiePartitionKey& proto) {
+ VISIT(top_level_site);
+ VISIT(has_cross_site_ancestor);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::CustomNudgeDelay& proto) {
+ VISIT(datatype_id);
+ VISIT(delay_ms);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::ClientCommand& proto) {
+ VISIT(set_sync_poll_interval);
+ VISIT(max_commit_batch_size);
+ VISIT(throttle_delay_seconds);
+ VISIT(client_invalidation_hint_buffer_size);
+ VISIT_REP(custom_nudge_delays);
+ VISIT(extension_types_max_tokens);
+ VISIT(extension_types_refill_interval_seconds);
+ VISIT(extension_types_depleted_quota_nudge_delay_seconds);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::ClientConfigParams& proto) {
+ VISIT_REP(enabled_type_ids);
+ VISIT(tabs_datatype_enabled);
+ VISIT(cookie_jar_mismatch);
+ VISIT(single_client);
+ VISIT_REP(devices_fcm_registration_tokens);
+ VISIT(single_client_with_standalone_invalidations);
+ VISIT_REP(fcm_registration_tokens_for_interested_clients);
+ VISIT(single_client_with_old_invalidations);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::ClientStatus& proto) {
+ VISIT(hierarchy_conflict_detected);
+ VISIT(is_sync_feature_enabled);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::ClientToServerMessage& proto) {
+ VISIT(share);
+ VISIT(protocol_version);
+ VISIT(commit);
+ VISIT(get_updates);
+ VISIT(store_birthday);
+ VISIT(debug_info);
+ VISIT(client_status);
+ VISIT(invalidator_client_id);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::ClientToServerResponse& proto) {
+ VISIT(commit);
+ VISIT(get_updates);
+ VISIT(error);
+ VISIT_ENUM(error_code);
+ VISIT(error_message);
+ VISIT(store_birthday);
+ VISIT(client_command);
+ VISIT_REP(migrated_data_type_id);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::ClientToServerResponse::Error& proto) {
+ VISIT_ENUM(error_type);
+ VISIT(error_description);
+ VISIT_ENUM(action);
+ VISIT_REP(error_data_type_ids);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::CommitMessage& proto) {
+ VISIT_REP(entries);
+ VISIT(cache_guid);
+ VISIT_REP(extensions_activity);
+ VISIT(config_params);
+ VISIT_REP(client_contexts);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::CommitResponse& proto) {
+ VISIT_REP(entryresponse);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::CommitResponse::EntryResponse& proto) {
+ VISIT_ENUM(response_type);
+ VISIT(id_string);
+ VISIT(version);
+ VISIT(error_message);
+ VISIT(mtime);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::DataTypeContext& proto) {
+ VISIT(data_type_id);
+ VISIT(context);
+ VISIT(version);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::DataTypeProgressMarker& proto) {
+ VISIT(data_type_id);
+ VISIT_BYTES(token);
+ VISIT(get_update_triggers);
+ VISIT(gc_directive);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::GarbageCollectionDirective& proto) {
+ VISIT(version_watermark);
+ VISIT(collaboration_gc);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::GarbageCollectionDirective::CollaborationGarbageCollection&
+ proto) {
+ VISIT_REP(active_collaboration_ids);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::DebugEventInfo& proto) {
+ VISIT_ENUM(singleton_event);
+ VISIT(sync_cycle_completed_event_info);
+ VISIT(nudging_datatype);
+ VISIT_REP(datatypes_notified_from_server);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::DebugInfo& proto) {
+ VISIT_REP(events);
+ VISIT(cryptographer_ready);
+ VISIT(cryptographer_has_pending_keys);
+ VISIT(events_dropped);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::DeletionOrigin& proto) {
+ VISIT(chromium_version);
+ VISIT(google_play_services_apk_version_name);
+ VISIT(file_name_hash);
+ VISIT(file_line_number);
+ VISIT(file_name_possibly_truncated);
+ VISIT(unique_source_tag_no_pii_possibly_truncated);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::DeviceInfoSpecifics& proto) {
+ VISIT(cache_guid);
+ VISIT(client_name);
+ VISIT_ENUM(device_type);
+ VISIT(sync_user_agent);
+ VISIT(chrome_version);
+ VISIT(signin_scoped_device_id);
+ VISIT(model);
+ VISIT(manufacturer);
+ VISIT(last_updated_timestamp);
+ VISIT(feature_fields);
+ VISIT(sharing_fields);
+ VISIT(invalidation_fields);
+ VISIT(paask_fields);
+ VISIT(full_hardware_class);
+ VISIT(chrome_version_info);
+ VISIT(google_play_services_version_info);
+ VISIT_ENUM(os_type);
+ VISIT_ENUM(device_form_factor);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::EligiblePriceRange& proto) {
+ VISIT(currency);
+ VISIT(min_price_in_micros);
+ VISIT(max_price_in_micros);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::FeatureSpecificFields& proto) {
+ VISIT(send_tab_to_self_receiving_enabled);
+ VISIT_ENUM(send_tab_to_self_receiving_type);
+ VISIT(auto_sign_out_last_signin_timestamp_windows_epoch_micros);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::SharingSpecificFields& proto) {
+ VISIT_REP(enabled_features);
+ VISIT(sender_id_fcm_token_v2);
+ VISIT_BYTES(sender_id_p256dh_v2);
+ VISIT_BYTES(sender_id_auth_secret_v2);
+ VISIT(chime_representative_target_id);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::PhoneAsASecurityKeySpecificFields& proto) {
+ VISIT(tunnel_server_domain);
+ VISIT_BYTES(contact_id);
+ VISIT(id);
+ VISIT_BYTES(peer_public_key_x962);
+ VISIT_BYTES(google_credential_id);
+ // `secret` is deliberately omitted to avoid including sensitive information
+ // in debugging output, which might be included in bug reports etc.
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::ChromeVersionInfo& proto) {
+ VISIT(version_number);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::GooglePlayServicesVersionInfo& proto) {
+ VISIT(apk_version_name);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::DictionarySpecifics& proto) {
+ VISIT(word);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::EncryptedData& proto) {
+ VISIT(key_name);
+ VISIT_BYTES(blob);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::EntityMetadata& proto) {
+ VISIT(client_tag_hash);
+ VISIT(server_id);
+ VISIT(is_deleted);
+ VISIT(sequence_number);
+ VISIT(acked_sequence_number);
+ VISIT(server_version);
+ VISIT(creation_time);
+ VISIT(modification_time);
+ VISIT(specifics_hash);
+ VISIT(base_specifics_hash);
+ VISIT(possibly_trimmed_base_specifics);
+ VISIT(deleted_by_version);
+ VISIT(collaboration);
+ VISIT(deletion_origin);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::EntityMetadata::CollaborationMetadata& proto) {
+ VISIT(collaboration_id);
+ VISIT(creation_attribution);
+ VISIT(last_update_attribution);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::EntityMetadata::CollaborationMetadata::Attribution& proto) {
+ VISIT(obfuscated_gaia_id);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::EntitySpecifics& proto) {
+ static_assert(56 == GetNumDataTypes(),
+ "When adding a new protocol type, you will likely need to add "
+ "it here as well.");
+ VISIT(encrypted);
+ VISIT(app);
+ VISIT(app_list);
+ VISIT(app_setting);
+ VISIT(arc_package);
+ VISIT(autofill);
+ VISIT(autofill_offer);
+ VISIT(autofill_profile);
+ VISIT(autofill_valuable);
+ VISIT(autofill_valuable_setting);
+ VISIT(autofill_wallet);
+ VISIT(autofill_wallet_credential);
+ VISIT(autofill_wallet_usage);
+ VISIT(bookmark);
+ VISIT(collaboration_group);
+ VISIT(contact_info);
+ VISIT(cookie);
+ VISIT(device_info);
+ VISIT(dictionary);
+ VISIT(extension);
+ VISIT(extension_setting);
+ VISIT(history);
+ VISIT(history_delete_directive);
+ VISIT(incoming_password_sharing_invitation);
+ VISIT(managed_user_setting);
+ VISIT(nigori);
+ VISIT(os_preference);
+ VISIT(os_priority_preference);
+ VISIT(outgoing_password_sharing_invitation);
+ VISIT(password);
+ VISIT(plus_address);
+ VISIT(plus_address_setting);
+ VISIT(preference);
+ VISIT(printer);
+ VISIT(printers_authorization_server);
+ VISIT(priority_preference);
+ VISIT(product_comparison);
+ VISIT(reading_list);
+ VISIT(saved_tab_group);
+ VISIT(search_engine);
+ VISIT(security_event);
+ VISIT(send_tab_to_self);
+ VISIT(session);
+ VISIT(shared_comment);
+ VISIT(shared_tab_group_account_data);
+ VISIT(shared_tab_group_data);
+ VISIT(sharing_message);
+ VISIT(theme);
+ VISIT(typed_url);
+ VISIT(user_consent);
+ VISIT(user_event);
+ VISIT(wallet_metadata);
+ VISIT(web_apk);
+ VISIT(web_app);
+ VISIT(webauthn_credential);
+ VISIT(wifi_configuration);
+ VISIT(workspace_desk);
+ VISIT(webauthn_credential);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::ExtensionSettingSpecifics& proto) {
+ VISIT(extension_id);
+ VISIT(key);
+ VISIT(value);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::ExtensionSpecifics& proto) {
+ VISIT(id);
+ VISIT(version);
+ VISIT(update_url);
+ VISIT(enabled);
+ VISIT(incognito_enabled);
+ VISIT(remote_install);
+ VISIT(all_urls_enabled);
+ VISIT(disable_reasons);
+ VISIT_REP(disable_reasons_list);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::GetUpdateTriggers& proto) {
+ VISIT_REP(notification_hint);
+ VISIT(client_dropped_hints);
+ VISIT(invalidations_out_of_sync);
+ VISIT(local_modification_nudges);
+ VISIT(datatype_refresh_nudges);
+ VISIT(server_dropped_hints);
+ VISIT(initial_sync_in_progress);
+ VISIT(sync_for_resolve_conflict_in_progress);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::GetUpdatesCallerInfo& proto) {
+ VISIT(notifications_enabled);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::GetUpdatesMessage& proto) {
+ VISIT(caller_info);
+ VISIT(fetch_folders);
+ VISIT_REP(from_progress_marker);
+ VISIT(streaming);
+ VISIT(need_encryption_key);
+ VISIT_ENUM(get_updates_origin);
+ VISIT(is_retry);
+ VISIT_REP(client_contexts);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::GetUpdatesResponse& proto) {
+ VISIT_REP(entries)
+ VISIT(changes_remaining);
+ VISIT_REP(new_progress_marker);
+ VISIT_REP(context_mutations);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::GlobalIdDirective& proto) {
+ VISIT_REP(global_id);
+ VISIT(start_time_usec);
+ VISIT(end_time_usec);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::HistoryDeleteDirectiveSpecifics& proto) {
+ VISIT(global_id_directive);
+ VISIT(time_range_directive);
+ VISIT(url_directive);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::IncomingPasswordSharingInvitationSpecifics& proto) {
+ VISIT(guid);
+ VISIT(sender_info);
+ VISIT_BYTES(encrypted_password_sharing_invitation_data);
+ VISIT(client_only_unencrypted_data);
+ VISIT(recipient_key_version);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::InvalidationSpecificFields& proto) {
+ VISIT(instance_id_token);
+ VISIT_REP(interested_data_type_ids);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::LinkedAppIconInfo& proto) {
+ VISIT(url);
+ VISIT(size);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::ManagedUserSettingSpecifics& proto) {
+ VISIT(name);
+ VISIT(value);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::MetaInfo& proto) {
+ VISIT(key);
+ VISIT(value);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::DataTypeState& proto) {
+ VISIT(progress_marker);
+ VISIT(type_context);
+ VISIT(encryption_key_name);
+ VISIT_ENUM(initial_sync_state);
+ VISIT(cache_guid);
+ VISIT(authenticated_obfuscated_gaia_id);
+ VISIT_REP(invalidations);
+ VISIT(notes_enabled_before_initial_sync_for_passwords);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::DataTypeState::Invalidation& proto) {
+ VISIT(hint);
+ VISIT(version);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::NavigationRedirect& proto) {
+ VISIT(url);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::ReplacedNavigation& proto) {
+ VISIT(first_committed_url);
+ VISIT(first_timestamp_msec);
+ VISIT_ENUM(first_page_transition);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::CryptographerData& proto) {
+ VISIT(key_bag);
+ VISIT(default_key_name);
+ VISIT(cross_user_sharing_keys);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::CrossUserSharingKeys& proto) {
+ VISIT_REP(private_key);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::CustomPassphraseKeyDerivationParams& proto) {
+ VISIT(custom_passphrase_key_derivation_method);
+ VISIT(custom_passphrase_key_derivation_salt);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::NigoriModel& proto) {
+ VISIT(cryptographer_data);
+ VISIT(current_keystore_key_name);
+ VISIT(pending_keys);
+ VISIT(passphrase_type);
+ VISIT(keystore_migration_time);
+ VISIT(custom_passphrase_time);
+ VISIT(custom_passphrase_key_derivation_params);
+ VISIT(encrypt_everything);
+ VISIT_REP(encrypted_types_specifics_field_number);
+ VISIT_REP(keystore_key);
+ VISIT(pending_keystore_decryptor_token);
+ VISIT(last_default_trusted_vault_key_name);
+ VISIT(trusted_vault_debug_info);
+ VISIT(cross_user_sharing_public_key);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::NigoriLocalData& proto) {
+ VISIT(data_type_state);
+ VISIT(entity_metadata);
+ VISIT(nigori_model);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::CrossUserSharingPublicKey& proto) {
+ VISIT(version);
+ VISIT_BYTES(x25519_public_key);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::CrossUserSharingPrivateKey& proto) {
+ VISIT(version);
+ VISIT(x25519_private_key);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::NigoriSpecifics& proto) {
+ VISIT(encryption_keybag);
+ VISIT(keybag_is_frozen);
+ VISIT(encrypt_everything);
+ VISIT(server_only_was_missing_keystore_migration_time);
+ VISIT(sync_tab_favicons);
+ VISIT(passphrase_type);
+ VISIT(keystore_decryptor_token);
+ VISIT(keystore_migration_time);
+ VISIT(custom_passphrase_time);
+ VISIT(custom_passphrase_key_derivation_method);
+ VISIT(custom_passphrase_key_derivation_salt);
+ VISIT(trusted_vault_debug_info);
+ VISIT(cross_user_sharing_public_key);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::WebauthnCredentialSpecifics& proto) {
+ VISIT_BYTES(sync_id);
+ VISIT_BYTES(credential_id);
+ VISIT(rp_id);
+ VISIT_BYTES(user_id);
+ VISIT_REP_BYTES(newly_shadowed_credential_ids);
+ VISIT(creation_time);
+ VISIT(user_name);
+ VISIT(user_display_name);
+ VISIT(third_party_payments_support);
+ VISIT(last_used_time_windows_epoch_micros);
+ VISIT(key_version);
+ VISIT(device_authorization_key_version);
+ VISIT_SECRET(private_key);
+ VISIT_SECRET(encrypted);
+ VISIT_SECRET(security_domain_encrypted);
+ VISIT(edited_by_user);
+ VISIT(hidden);
+ VISIT(hidden_time);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::HistorySpecifics::PageTransition& proto) {
+ VISIT_ENUM(core_transition);
+ VISIT(blocked);
+ VISIT(forward_back);
+ VISIT(from_address_bar);
+ VISIT(home_page);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::HistorySpecifics::RedirectEntry& proto) {
+ VISIT(originator_visit_id);
+ VISIT(url);
+ VISIT(title);
+ VISIT(hidden);
+ VISIT_ENUM(redirect_type);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::HistorySpecifics::Category& proto) {
+ VISIT(id);
+ VISIT(weight);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::HistorySpecifics& proto) {
+ VISIT(visit_time_windows_epoch_micros);
+ VISIT(originator_cache_guid);
+ VISIT_REP(redirect_entries);
+ VISIT(redirect_chain_start_incomplete);
+ VISIT(redirect_chain_end_incomplete);
+ VISIT(redirect_chain_middle_trimmed);
+ VISIT(page_transition);
+ VISIT(originator_referring_visit_id);
+ VISIT(originator_opener_visit_id);
+ VISIT(originator_cluster_id);
+ VISIT(visit_duration_micros);
+ VISIT_ENUM(browser_type);
+ VISIT(window_id);
+ VISIT(tab_id);
+ VISIT(task_id);
+ VISIT(root_task_id);
+ VISIT(parent_task_id);
+ VISIT(http_response_code);
+ VISIT(page_language);
+ VISIT_ENUM(password_state);
+ VISIT(favicon_url);
+ VISIT(referrer_url);
+ VISIT(has_url_keyed_image);
+ VISIT_REP(categories);
+ VISIT_REP(related_searches);
+ VISIT(app_id);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::TrustedVaultAutoUpgradeExperimentGroup& proto) {
+ VISIT(cohort);
+ VISIT_ENUM(type);
+ VISIT(type_index);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::NigoriSpecifics::TrustedVaultDebugInfo& proto) {
+ VISIT(migration_time);
+ VISIT(key_version);
+ VISIT(auto_upgrade_experiment_group);
+ VISIT(auto_upgrade_experiment_group_modification_time_unix_epoch_millis);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::OsPreferenceSpecifics& proto) {
+ VISIT(preference);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::OsPriorityPreferenceSpecifics& proto) {
+ VISIT(preference);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::OutgoingPasswordSharingInvitationSpecifics& proto) {
+ VISIT(guid);
+ VISIT(recipient_user_id);
+ VISIT_BYTES(encrypted_password_sharing_invitation_data);
+ VISIT(client_only_unencrypted_data);
+ VISIT(recipient_key_version);
+ VISIT(sender_key_version);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::PasswordSharingInvitationData& proto) {
+ VISIT(password_group_data);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::PasswordSharingInvitationData::PasswordGroupData& proto) {
+ VISIT(username_value);
+ VISIT(password_value);
+ VISIT_REP(element_data);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::PasswordSharingInvitationData::PasswordGroupElementData&
+ proto) {
+ VISIT(scheme);
+ VISIT(signon_realm);
+ VISIT(origin);
+ VISIT(username_element);
+ VISIT(password_element);
+ VISIT(display_name);
+ VISIT(avatar_url);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::PasswordSpecifics& proto) {
+ VISIT(encrypted);
+ VISIT(unencrypted_metadata);
+ VISIT(client_only_encrypted_data);
+ VISIT(encrypted_notes_backup);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::PasswordSpecificsData& proto) {
+ VISIT(scheme);
+ VISIT(signon_realm);
+ VISIT(origin);
+ VISIT(action);
+ VISIT(username_element);
+ VISIT(username_value);
+ VISIT(password_element);
+ VISIT(password_value);
+ VISIT(preferred);
+ VISIT(date_created);
+ VISIT(blacklisted);
+ VISIT(type);
+ VISIT(times_used);
+ VISIT(display_name);
+ VISIT(avatar_url);
+ VISIT(federation_url);
+ VISIT(date_last_used);
+ VISIT(password_issues);
+ VISIT(date_password_modified_windows_epoch_micros);
+ VISIT(notes);
+ VISIT(sender_email);
+ VISIT(sender_name);
+ VISIT(date_received_windows_epoch_micros);
+ VISIT(sharing_notification_displayed);
+ VISIT(sender_profile_image_url);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::PasswordIssues& proto) {
+ VISIT(leaked_password_issue);
+ VISIT(reused_password_issue);
+ VISIT(weak_password_issue);
+ VISIT(phished_password_issue);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::PasswordIssues_PasswordIssue& proto) {
+ VISIT(date_first_detection_windows_epoch_micros);
+ VISIT(is_muted);
+ VISIT(trigger_notification_from_backend_on_detection);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::PasswordSpecificsData_Notes& proto) {
+ VISIT_REP(note);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::PasswordSpecificsData_Notes_Note& proto) {
+ VISIT(unique_display_name);
+ VISIT(value);
+ VISIT(date_created_windows_epoch_micros);
+ VISIT(hide_by_default);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::PasswordSpecificsMetadata& proto) {
+ VISIT(url);
+ VISIT(blacklisted);
+ VISIT(date_last_used_windows_epoch_micros);
+ VISIT(password_issues);
+ VISIT(type);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::PowerBookmarkSpecifics& proto) {
+ VISIT(guid);
+ VISIT(url);
+ VISIT_ENUM(power_type);
+ VISIT(creation_time_usec);
+ VISIT(update_time_usec);
+ VISIT(power_entity);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::PowerEntity& proto) {
+ VISIT(note_entity);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::NoteEntity& proto) {
+ VISIT(plain_text);
+ VISIT(rich_text);
+ VISIT_ENUM(target_type);
+ VISIT(current_note_version);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::PersistedEntityData& proto) {
+ VISIT(name);
+ VISIT(specifics);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::PlusAddressSettingSpecifics& proto) {
+ VISIT(name);
+ VISIT(bool_value);
+ VISIT(string_value);
+ VISIT(int_value);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::PlusAddressSpecifics& proto) {
+ VISIT(profile_id);
+ VISIT(facet);
+ VISIT(plus_email);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::PlusEmail& proto) {
+ VISIT(email_address);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::PreferenceSpecifics& proto) {
+ VISIT(name);
+ VISIT(value);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::PrinterPPDReference& proto) {
+ VISIT(user_supplied_ppd_url);
+ VISIT(effective_make_and_model);
+ VISIT(autoconf);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::PrinterSpecifics& proto) {
+ VISIT(id);
+ VISIT(display_name);
+ VISIT(description);
+ VISIT(manufacturer);
+ VISIT(model);
+ VISIT(uri);
+ VISIT(uuid);
+ VISIT(ppd_reference);
+ VISIT(make_and_model);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::PrintersAuthorizationServerSpecifics& proto) {
+ VISIT(uri);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::PriorityPreferenceSpecifics& proto) {
+ VISIT(preference);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::ReadingListSpecifics& proto) {
+ VISIT(entry_id);
+ VISIT(title);
+ VISIT(url);
+ VISIT(creation_time_us);
+ VISIT(update_time_us);
+ VISIT_ENUM(status);
+ VISIT(first_read_time_us);
+ VISIT(update_title_time_us);
+ VISIT(estimated_read_time_seconds);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::SavedTabGroupSpecifics& proto) {
+ VISIT(guid);
+ VISIT(creation_time_windows_epoch_micros);
+ VISIT(update_time_windows_epoch_micros);
+ VISIT(group);
+ VISIT(tab);
+ VISIT(attribution_metadata);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::SavedTabGroup& proto) {
+ VISIT(position);
+ VISIT(title);
+ VISIT_ENUM(color);
+ VISIT(pinned_position);
+ VISIT(bookmark_node_id);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::SavedTabGroupTab& proto) {
+ VISIT(position);
+ VISIT(group_guid);
+ VISIT(url);
+ VISIT(title);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::AttributionMetadata& proto) {
+ VISIT(created);
+ VISIT(updated);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::AttributionMetadata::Attribution& proto) {
+ VISIT(device_info);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::AttributionMetadata::Attribution::AttributionDeviceInfo&
+ proto) {
+ VISIT(cache_guid);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::SearchEngineSpecifics& proto) {
+ VISIT(short_name);
+ VISIT(keyword);
+ VISIT(favicon_url);
+ VISIT(url);
+ VISIT(safe_for_autoreplace);
+ VISIT(originating_url);
+ VISIT(date_created);
+ VISIT(input_encodings);
+ VISIT(suggestions_url);
+ VISIT(prepopulate_id);
+ VISIT(autogenerate_keyword);
+ VISIT(last_modified);
+ VISIT(sync_guid);
+ VISIT_REP(alternate_urls);
+ VISIT(image_url);
+ VISIT(search_url_post_params);
+ VISIT(suggestions_url_post_params);
+ VISIT(image_url_post_params);
+ VISIT(new_tab_url);
+ VISIT_ENUM(is_active);
+ VISIT(starter_pack_id);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::SendTabToSelfPush& proto) {
+ VISIT(title);
+ VISIT(text);
+ VISIT_REP(icon);
+ VISIT(favicon);
+ VISIT(destination_url);
+ VISIT(placeholder_title);
+ VISIT(placeholder_body);
+ VISIT(entry_unique_guid);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::SendTabToSelfPush::Image& proto) {
+ VISIT(url);
+ VISIT(alt_text);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::SendTabToSelfSpecifics& proto) {
+ VISIT(guid);
+ VISIT(title);
+ VISIT(url);
+ VISIT(shared_time_usec);
+ VISIT(device_name);
+ VISIT(target_device_sync_cache_guid);
+ VISIT(opened);
+ VISIT(notification_dismissed);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::SessionHeader& proto) {
+ VISIT(session_start_time_unix_epoch_millis);
+ VISIT_REP(window);
+ VISIT(client_name);
+ VISIT_ENUM(device_type);
+ VISIT_ENUM(device_form_factor);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::SessionSpecifics& proto) {
+ VISIT(session_tag);
+ VISIT(header);
+ VISIT(tab);
+ VISIT(tab_node_id);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::SessionTab& proto) {
+ VISIT(tab_id);
+ VISIT(window_id);
+ VISIT(tab_visual_index);
+ VISIT(current_navigation_index);
+ VISIT(pinned);
+ VISIT(extension_app_id);
+ VISIT_REP(navigation);
+ VISIT_BYTES(favicon);
+ VISIT_ENUM(favicon_type);
+ VISIT(favicon_source);
+ VISIT_REP(variation_id);
+ VISIT_ENUM(browser_type);
+ VISIT(last_active_time_unix_epoch_millis);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::SessionWindow& proto) {
+ VISIT(window_id);
+ VISIT(selected_tab_index);
+ VISIT_REP(tab);
+ VISIT_ENUM(browser_type);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::SharedTabGroup& proto) {
+ VISIT(title);
+ VISIT_ENUM(color);
+ VISIT(originating_tab_group_guid);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::SharedTab& proto) {
+ VISIT(url);
+ VISIT(title);
+ VISIT(shared_tab_group_guid);
+ VISIT(unique_position);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::SharedTabGroupDataSpecifics& proto) {
+ VISIT(guid);
+ VISIT(tab_group);
+ VISIT(tab);
+ VISIT(update_time_windows_epoch_micros);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::SharingMessageSpecifics& proto) {
+ VISIT(message_id);
+ VISIT(channel_configuration);
+ VISIT_BYTES(payload);
+ VISIT(unencrypted_payload);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::SharingMessageSpecifics::
+ ChannelConfiguration::FCMChannelConfiguration& proto) {
+ VISIT(token);
+ VISIT(ttl);
+ VISIT(priority);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::SharingMessageSpecifics::
+ ChannelConfiguration::ChimeChannelConfiguration& proto) {
+ VISIT_BYTES(device_token);
+ VISIT_ENUM(channel_type);
+ VISIT(type_id);
+ VISIT(representative_target_id);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::SharingMessageSpecifics::ChannelConfiguration& proto) {
+ VISIT(fcm);
+ VISIT_BYTES(server);
+ VISIT(chime);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::SyncCycleCompletedEventInfo& proto) {
+ VISIT(num_encryption_conflicts);
+ VISIT(num_hierarchy_conflicts);
+ VISIT(num_server_conflicts);
+ VISIT(num_updates_downloaded);
+ VISIT(num_reflected_updates_downloaded);
+ VISIT(caller_info);
+ VISIT_ENUM(get_updates_origin);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::SyncEntity& proto) {
+ VISIT(id_string);
+ VISIT(parent_id_string);
+ VISIT(version);
+ VISIT(mtime);
+ VISIT(ctime);
+ VISIT(name);
+ VISIT(non_unique_name);
+ VISIT(server_defined_unique_tag);
+ VISIT(unique_position);
+ VISIT(deleted);
+ VISIT(originator_cache_guid);
+ VISIT(originator_client_item_id);
+ VISIT(specifics);
+ VISIT(folder);
+ VISIT(client_tag_hash);
+ VISIT(collaboration);
+ VISIT(deletion_origin);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::SyncEntity::CollaborationMetadata& proto) {
+ VISIT(collaboration_id);
+ VISIT(creation_attribution);
+ VISIT(last_update_attribution);
+ VISIT_REP(per_field_attributions);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::SyncEntity::CollaborationMetadata::Attribution& proto) {
+ VISIT(obfuscated_gaia_id);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::SyncEntity::CollaborationMetadata::PerFieldAttribution&
+ proto) {
+ VISIT(attribution_name);
+ VISIT(last_update_obfuscated_gaia_id);
+ VISIT(mtime);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::SyncInvalidationsPayload& proto) {
+ VISIT_REP(data_type_invalidations);
+ VISIT_BYTES(hint);
+ VISIT(version);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::SyncInvalidationsPayload::DataTypeInvalidation& proto) {
+ VISIT(data_type_id);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::SecurityEventSpecifics& proto) {
+ VISIT(gaia_password_reuse_event);
+ VISIT(event_time_usec);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::GaiaPasswordReuse& proto) {
+ VISIT(reuse_detected);
+ VISIT(reuse_lookup);
+ VISIT(dialog_interaction);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::GaiaPasswordReuse::PasswordReuseDetected& proto) {
+ VISIT(status);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::GaiaPasswordReuse::PasswordReuseDetected::SafeBrowsingStatus&
+ proto) {
+ VISIT(enabled);
+ VISIT_ENUM(safe_browsing_reporting_population);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::GaiaPasswordReuse::PasswordReuseDialogInteraction& proto) {
+ VISIT_ENUM(interaction_result);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::GaiaPasswordReuse::PasswordReuseLookup& proto) {
+ VISIT_ENUM(lookup_result);
+ VISIT_ENUM(verdict);
+ VISIT(verdict_token);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::UserDisplayInfo& proto) {
+ VISIT(email);
+ VISIT(display_name);
+ VISIT(profile_image_url);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::UserInfo& proto) {
+ VISIT(user_id);
+ VISIT(user_display_info);
+ VISIT(cross_user_sharing_public_key);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::UserEventSpecifics::GaiaPasswordCaptured& proto) {
+ VISIT_ENUM(event_trigger);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::UserEventSpecifics::FlocIdComputed& proto) {
+ VISIT(floc_id);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::TabNavigation& proto) {
+ VISIT(virtual_url);
+ VISIT(referrer);
+ VISIT(title);
+ VISIT_ENUM(page_transition);
+ VISIT_ENUM(redirect_type);
+ VISIT(unique_id);
+ VISIT(timestamp_msec);
+ VISIT(navigation_forward_back);
+ VISIT(navigation_from_address_bar);
+ VISIT(navigation_home_page);
+ VISIT(global_id);
+ VISIT(favicon_url);
+ VISIT_ENUM(blocked_state);
+ VISIT(http_status_code);
+ VISIT(obsolete_referrer_policy);
+ VISIT(is_restored);
+ VISIT_REP(navigation_redirect);
+ VISIT(last_navigation_redirect_url);
+ VISIT(correct_referrer_policy);
+ VISIT(page_language);
+ VISIT_ENUM(password_state);
+ VISIT(task_id);
+ VISIT_REP(ancestor_task_id);
+ VISIT(replaced_navigation);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::ThemeSpecifics& proto) {
+ VISIT(use_custom_theme);
+ VISIT(use_system_theme_by_default);
+ VISIT(custom_theme_name);
+ VISIT(custom_theme_id);
+ VISIT(custom_theme_update_url);
+ VISIT(autogenerated_color_theme);
+ VISIT(user_color_theme);
+ VISIT(grayscale_theme_enabled);
+ VISIT_ENUM(browser_color_scheme);
+ VISIT(ntp_background);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::ThemeSpecifics::AutogeneratedColorTheme& proto) {
+ VISIT(color);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::ThemeSpecificsIos& proto) {
+ VISIT(user_color_theme);
+ VISIT(ntp_background);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::UserColorTheme& proto) {
+ VISIT(color);
+ VISIT_ENUM(browser_color_variant);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::ThemeSpecifics::Empty& proto) {}
+
+VISIT_PROTO_FIELDS(const sync_pb::NtpCustomBackground& proto) {
+ VISIT(url);
+ VISIT(attribution_line_1);
+ VISIT(attribution_line_2);
+ VISIT(attribution_action_url);
+ VISIT(collection_id);
+ VISIT(resume_token);
+ VISIT(refresh_timestamp_unix_epoch_seconds);
+ VISIT(main_color);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::TimeRangeDirective& proto) {
+ VISIT(start_time_usec);
+ VISIT(end_time_usec);
+ VISIT(app_id);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::UrlDirective& proto) {
+ VISIT(url);
+ VISIT(end_time_usec);
+ VISIT(app_id);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::TypeHint& proto) {
+ VISIT(data_type_id);
+ VISIT(has_valid_hint);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::TypedUrlSpecifics& proto) {
+ VISIT(url);
+ VISIT(title);
+ VISIT(hidden);
+ VISIT_REP(visits);
+ VISIT_REP(visit_transitions);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::UnencryptedSharingMessage& proto) {
+ VISIT(sender_guid);
+ VISIT(sender_device_name);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::UniquePosition& proto) {
+ VISIT_BYTES(value);
+ VISIT_BYTES(compressed_value);
+ VISIT(uncompressed_length);
+ VISIT_BYTES(custom_compressed_v1);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::UserConsentSpecifics& proto) {
+ VISIT(locale);
+ VISIT(client_consent_time_usec);
+ VISIT(obfuscated_gaia_id);
+ VISIT(sync_consent);
+ VISIT(arc_backup_and_restore_consent);
+ VISIT(arc_location_service_consent);
+ VISIT(arc_play_terms_of_service_consent);
+ VISIT(assistant_activity_control_consent);
+ VISIT(account_passwords_consent);
+ VISIT(recorder_speaker_label_consent);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::UserConsentTypes::ArcBackupAndRestoreConsent& proto) {
+ VISIT_REP(description_grd_ids);
+ VISIT_ENUM(status);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::UserConsentTypes::ArcGoogleLocationServiceConsent& proto) {
+ VISIT_REP(description_grd_ids);
+ VISIT_ENUM(status);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::UserConsentTypes::ArcPlayTermsOfServiceConsent& proto) {
+ VISIT(play_terms_of_service_text_length);
+ VISIT(play_terms_of_service_hash);
+ VISIT(confirmation_grd_id);
+ VISIT_ENUM(status);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::UserConsentTypes::AssistantActivityControlConsent& proto) {
+ VISIT(ui_audit_key);
+ VISIT_ENUM(status);
+ VISIT_ENUM(setting_type);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::UserConsentTypes::SyncConsent& proto) {
+ VISIT_REP(description_grd_ids);
+ VISIT(confirmation_grd_id);
+ VISIT_ENUM(status);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::UserConsentTypes::UnifiedConsent& proto) {
+ VISIT_REP(description_grd_ids);
+ VISIT(confirmation_grd_id);
+ VISIT_ENUM(status);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::UserConsentTypes::AccountPasswordsConsent& proto) {
+ VISIT_REP(description_grd_ids);
+ VISIT(confirmation_grd_id);
+ VISIT_ENUM(status);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::UserConsentTypes::RecorderSpeakerLabelConsent& proto) {
+ VISIT_REP(description_grd_ids);
+ VISIT(confirmation_grd_id);
+ VISIT_ENUM(status);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::UserEventSpecifics& proto) {
+ VISIT(event_time_usec);
+ VISIT(navigation_id);
+ VISIT(session_id);
+ VISIT(test_event);
+ VISIT(gaia_password_reuse_event);
+ VISIT(gaia_password_captured_event);
+ VISIT(floc_id_computed_event);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::UserEventSpecifics::Test& proto) {}
+
+VISIT_PROTO_FIELDS(const sync_pb::CloudTokenData& proto) {
+ VISIT(suffix);
+ VISIT(exp_month);
+ VISIT(exp_year);
+ VISIT(art_fife_url);
+ VISIT(instrument_token);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::PaymentInstrument& proto) {
+ VISIT_REP(supported_rails);
+ VISIT(display_icon_url);
+ VISIT(instrument_id);
+ VISIT(bank_account);
+ VISIT(nickname);
+ VISIT(iban);
+ VISIT(ewallet_details);
+ VISIT(device_details);
+ VISIT(bnpl_issuer_details);
+ VISIT_REP(action_required);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::PaymentInstrumentCreationOption& proto) {
+ VISIT(id);
+ VISIT(buy_now_pay_later_option);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::BankAccountDetails& proto) {
+ VISIT(bank_name);
+ VISIT(account_number_suffix);
+ VISIT_ENUM(account_type);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::EwalletDetails& proto) {
+ VISIT(ewallet_name);
+ VISIT(account_display_name);
+ VISIT_REP(supported_payment_link_uris);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::DeviceDetails& proto) {
+ VISIT(is_fido_enrolled);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::CardBenefit& proto) {
+ VISIT(benefit_id);
+ VISIT(benefit_description);
+ VISIT(start_time_unix_epoch_milliseconds);
+ VISIT(end_time_unix_epoch_milliseconds);
+ VISIT(flat_rate_benefit);
+ VISIT(category_benefit);
+ VISIT(merchant_benefit);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::CardBenefit_FlatRateBenefit& proto) {}
+
+VISIT_PROTO_FIELDS(const sync_pb::CardBenefit_CategoryBenefit& proto) {
+ VISIT_ENUM(category_benefit_type);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::CardBenefit_MerchantBenefit& proto) {
+ VISIT_REP(merchant_domain);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::CardIssuer& proto) {
+ VISIT_ENUM(issuer);
+ VISIT(issuer_id);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::WalletMaskedCreditCard& proto) {
+ VISIT(id);
+ VISIT_ENUM(status);
+ VISIT(name_on_card);
+ VISIT_ENUM(type);
+ VISIT(last_four);
+ VISIT(exp_month);
+ VISIT(exp_year);
+ VISIT(billing_address_id);
+ VISIT(bank_name);
+ VISIT(nickname);
+ VISIT(card_issuer);
+ VISIT(instrument_id);
+ VISIT_ENUM(virtual_card_enrollment_state);
+ VISIT(card_art_url);
+ VISIT(product_description);
+ VISIT_ENUM(virtual_card_enrollment_type);
+ VISIT_REP(card_benefit);
+ VISIT(product_terms_url);
+ VISIT_ENUM(card_info_retrieval_enrollment_state);
+ VISIT_ENUM(card_benefit_source);
+ VISIT_ENUM(card_creation_source);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::WalletMetadataSpecifics& proto) {
+ VISIT_ENUM(type);
+ VISIT(id);
+ VISIT(use_count);
+ VISIT(use_date);
+ VISIT(card_billing_address_id);
+ VISIT(address_has_converted);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::WalletPostalAddress& proto) {
+ VISIT(id);
+ VISIT(recipient_name);
+ VISIT(company_name);
+ VISIT_REP(street_address);
+ VISIT(address_1);
+ VISIT(address_2);
+ VISIT(address_3);
+ VISIT(address_4);
+ VISIT(postal_code);
+ VISIT(sorting_code);
+ VISIT(country_code);
+ VISIT(phone_number);
+ VISIT(language_code);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::PaymentsCustomerData& proto) {
+ VISIT(id);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::WalletCreditCardCloudTokenData& proto) {
+ VISIT(masked_card_id);
+ VISIT(suffix);
+ VISIT(exp_month);
+ VISIT(exp_year);
+ VISIT(art_fife_url);
+ VISIT(instrument_token);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::WalletMaskedIban& proto) {
+ VISIT(instrument_id);
+ VISIT(prefix);
+ VISIT(suffix);
+ VISIT(length);
+ VISIT(nickname);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::WebApkIconInfo& proto) {
+ VISIT(size_in_px);
+ VISIT(url);
+ VISIT_ENUM(purpose);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::WebApkSpecifics& proto) {
+ VISIT(manifest_id);
+ VISIT(start_url);
+ VISIT(name);
+ VISIT(theme_color);
+ VISIT(scope);
+ VISIT_REP(icon_infos);
+ VISIT(last_used_time_windows_epoch_micros);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::WebAppIconInfo& proto) {
+ VISIT(size_in_px);
+ VISIT(url);
+ VISIT_ENUM(purpose);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::WebAppSpecifics& proto) {
+ VISIT(start_url);
+ VISIT(name);
+ VISIT_ENUM(user_display_mode_default);
+ VISIT(theme_color);
+ VISIT(scope);
+ VISIT_REP(icon_infos);
+ VISIT(user_page_ordinal);
+ VISIT(user_launch_ordinal);
+ VISIT(relative_manifest_id);
+ VISIT_ENUM(user_display_mode_cros);
+ VISIT_REP(trusted_icons);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::WifiConfigurationSpecifics::
+ ProxyConfiguration::ManualProxyConfiguration& proto) {
+ VISIT(http_proxy_url);
+ VISIT(http_proxy_port);
+ VISIT(secure_http_proxy_url);
+ VISIT(secure_http_proxy_port);
+ VISIT(socks_host_url);
+ VISIT(socks_host_port);
+ VISIT_REP(excluded_domains);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::WifiConfigurationSpecifics::ProxyConfiguration& proto) {
+ VISIT_ENUM(proxy_option);
+ VISIT(autoconfiguration_url);
+ VISIT(manual_proxy_configuration);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::WifiConfigurationSpecifics& proto) {
+ VISIT_BYTES(hex_ssid);
+ VISIT_ENUM(security_type);
+ VISIT_BYTES(passphrase);
+ VISIT_ENUM(automatically_connect);
+ VISIT_ENUM(is_preferred);
+ VISIT(proxy_configuration);
+ VISIT_REP(custom_dns);
+ VISIT(last_connected_timestamp);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::WorkspaceDeskSpecifics& proto) {
+ VISIT(uuid);
+ VISIT(name);
+ VISIT(created_time_windows_epoch_micros);
+ VISIT(updated_time_windows_epoch_micros);
+ VISIT(desk);
+ VISIT_ENUM(desk_type);
+ VISIT(client_cache_guid);
+ VISIT_ENUM(device_form_factor);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::WorkspaceDeskSpecifics::App& proto) {
+ VISIT(window_bound);
+ VISIT_ENUM(window_state);
+ VISIT(z_index);
+ VISIT(app);
+ VISIT(window_id);
+ VISIT(display_id);
+ VISIT_ENUM(pre_minimized_window_state);
+ VISIT(snap_percentage);
+ VISIT_ENUM(container);
+ VISIT_ENUM(disposition);
+ VISIT(app_name);
+ VISIT(title);
+ VISIT(override_url);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::WorkspaceDeskSpecifics::AppOneOf& proto) {
+ VISIT(browser_app_window);
+ VISIT(chrome_app);
+ VISIT(progress_web_app);
+ VISIT(arc_app);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::WorkspaceDeskSpecifics::BrowserAppWindow& proto) {
+ VISIT_REP(tabs);
+ VISIT(active_tab_index);
+ VISIT(show_as_app);
+ VISIT_REP(tab_groups);
+ VISIT(first_non_pinned_tab_index);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::WorkspaceDeskSpecifics::BrowserAppWindow::BrowserAppTab&
+ proto) {
+ VISIT(url);
+ VISIT(title);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::WorkspaceDeskSpecifics::ChromeApp& proto) {
+ VISIT(app_id);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::WorkspaceDeskSpecifics::Desk& proto) {
+ VISIT_REP(apps);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::WorkspaceDeskSpecifics::ProgressiveWebApp& proto) {
+ VISIT(app_id);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::WorkspaceDeskSpecifics::WindowBound& proto) {
+ VISIT(top);
+ VISIT(left);
+ VISIT(width);
+ VISIT(height);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::WorkspaceDeskSpecifics::ArcApp& proto) {
+ VISIT(app_id);
+ VISIT(minimum_size);
+ VISIT(maximum_size);
+ VISIT(bounds_in_root);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::WorkspaceDeskSpecifics::ArcApp::WindowSize& proto) {
+ VISIT(width);
+ VISIT(height);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::WorkspaceDeskSpecifics::BrowserAppWindow::TabGroup& proto) {
+ VISIT(first_index);
+ VISIT(last_index);
+ VISIT(title);
+ VISIT_ENUM(color);
+ VISIT(is_collapsed);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::Any& proto) {
+ VISIT_REP(type_url);
+ VISIT_REP(value);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::AutofillValuableSpecifics& proto) {
+ VISIT(id);
+ VISIT(is_editable);
+ VISIT(loyalty_card);
+ VISIT(vehicle_registration);
+ VISIT(flight_reservation);
+ VISIT(serialized_chrome_valuables_metadata);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::LoyaltyCard& proto) {
+ VISIT(merchant_name);
+ VISIT(program_name);
+ VISIT(program_logo);
+ VISIT(loyalty_card_number);
+ VISIT_REP(merchant_domains);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::VehicleRegistration& proto) {
+ VISIT(vehicle_make);
+ VISIT(vehicle_model);
+ VISIT(vehicle_year);
+ VISIT(vehicle_identification_number);
+ VISIT(vehicle_license_plate);
+ VISIT(license_plate_region);
+ VISIT(license_plate_country);
+ VISIT(owner_name);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::FlightReservation& proto) {
+ VISIT(flight_number);
+ VISIT(flight_ticket_number);
+ VISIT(flight_confirmation_code);
+ VISIT(passenger_name);
+ VISIT(departure_airport);
+ VISIT(arrival_airport);
+ VISIT(departure_date_unix_epoch_micros);
+ VISIT(arrival_date_unix_epoch_micros);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::AutofillValuableSettingSpecifics& proto) {
+ VISIT(name);
+ VISIT(bool_value);
+ VISIT(string_value);
+ VISIT(int_value);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::SharedTabDetails& proto) {
+ VISIT(shared_tab_group_guid);
+ VISIT(last_seen_timestamp_windows_epoch);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::SharedTabGroupDetails& proto) {
+ VISIT(pinned_position);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::SharedTabGroupAccountDataSpecifics& proto) {
+ VISIT(guid);
+ VISIT(collaboration_id);
+ VISIT(shared_tab_details);
+ VISIT(shared_tab_group_details);
+ VISIT(update_time_windows_epoch_micros);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::CommentData::Attribution::CommentTarget::FragmentLink&
+ proto) {
+ VISIT(fragment);
+ VISIT(text_preview);
+}
+
+VISIT_PROTO_FIELDS(
+ const sync_pb::CommentData::Attribution::CommentTarget& proto) {
+ VISIT(shared_url_context_uuid);
+ VISIT(link_fragment);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::CommentData::Attribution::InReplyTo& proto) {
+ VISIT(parent_id);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::CommentData::Attribution& proto) {
+ VISIT(top_level);
+ VISIT(parent);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::CommentData::OrderKey& proto) {
+ VISIT(device_guid);
+ VISIT(local_sequence);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::CommentData& proto) {
+ VISIT(text);
+ VISIT(attribution);
+ VISIT(order_key);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::SharedUrlContext::UrlRepresentation& proto) {
+ VISIT_ENUM(source);
+ VISIT(value);
+ VISIT(version);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::SharedUrlContext& proto) {
+ VISIT_REP(representations);
+ VISIT(title);
+}
+
+VISIT_PROTO_FIELDS(const sync_pb::SharedCommentSpecifics& proto) {
+ VISIT(uuid);
+ VISIT(context_id);
+ VISIT(proto_version);
+ VISIT(comment);
+ VISIT(shared_url_context);
+}
+
+} // namespace syncer
+
+#undef VISIT_
+#undef VISIT_BYTES
+#undef VISIT_ENUM
+#undef VISIT
+#undef VISIT_REP
+
+#endif // COMPONENTS_SYNC_PROTOCOL_PROTO_VISITORS_H_
diff --git a/pyhindsight/lib/components/sync/protocol/protocol_sources.gni b/pyhindsight/lib/components/sync/protocol/protocol_sources.gni
new file mode 100644
index 0000000..004c087
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/protocol_sources.gni
@@ -0,0 +1,90 @@
+# Copyright 2015 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_sources = [
+ "app_list_specifics.proto",
+ "app_setting_specifics.proto",
+ "app_specifics.proto",
+ "arc_package_specifics.proto",
+ "autofill_offer_specifics.proto",
+ "autofill_specifics.proto",
+ "autofill_valuable_setting_specifics.proto",
+ "autofill_valuable_specifics.proto",
+ "autofill_wallet_credential_specifics.proto",
+ "autofill_wallet_usage_specifics.proto",
+ "bookmark_model_metadata.proto",
+ "bookmark_specifics.proto",
+ "client_commands.proto",
+ "client_debug_info.proto",
+ "collaboration_group_metadata.proto",
+ "collaboration_group_specifics.proto",
+ "contact_info_specifics.proto",
+ "cookie_specifics.proto",
+ "data_type_progress_marker.proto",
+ "data_type_state.proto",
+ "data_type_store_schema_descriptor.proto",
+ "deletion_origin.proto",
+ "device_info_specifics.proto",
+ "dictionary_specifics.proto",
+ "encryption.proto",
+ "entity_metadata.proto",
+ "entity_specifics.proto",
+ "extension_setting_specifics.proto",
+ "extension_specifics.proto",
+ "gaia_password_reuse.proto",
+ "get_updates_caller_info.proto",
+ "history_delete_directive_specifics.proto",
+ "history_specifics.proto",
+ "history_status.proto",
+ "loopback_server.proto",
+ "managed_user_setting_specifics.proto",
+ "managed_user_shared_setting_specifics.proto",
+ "nigori_local_data.proto",
+ "nigori_specifics.proto",
+ "note_entity.proto",
+ "os_preference_specifics.proto",
+ "os_priority_preference_specifics.proto",
+ "password_sharing_invitation_specifics.proto",
+ "password_sharing_recipients.proto",
+ "password_specifics.proto",
+ "persisted_entity_data.proto",
+ "plus_address_setting_specifics.proto",
+ "plus_address_specifics.proto",
+ "power_bookmark_specifics.proto",
+ "preference_specifics.proto",
+ "printer_specifics.proto",
+ "printers_authorization_server_specifics.proto",
+ "priority_preference_specifics.proto",
+ "product_comparison_specifics.proto",
+ "reading_list_specifics.proto",
+ "saved_tab_group_specifics.proto",
+ "search_engine_specifics.proto",
+ "security_event_specifics.proto",
+ "send_tab_to_self_specifics.proto",
+ "session_specifics.proto",
+ "shared_comment_specifics.proto",
+ "shared_tab_group_account_data_specifics.proto",
+ "shared_tab_group_data_specifics.proto",
+ "sharing_message_specifics.proto",
+ "sync.proto",
+ "sync_entity.proto",
+ "sync_enums.proto",
+ "sync_invalidations_payload.proto",
+ "tab_group_attribution_metadata.proto",
+ "test.proto",
+ "theme_specifics.proto",
+ "theme_specifics_ios.proto",
+ "theme_types.proto",
+ "typed_url_specifics.proto",
+ "unencrypted_sharing_message.proto",
+ "unique_position.proto",
+ "user_consent_specifics.proto",
+ "user_consent_types.proto",
+ "user_event_specifics.proto",
+ "web_apk_specifics.proto",
+ "web_app_specifics.proto",
+ "webauthn_credential_specifics.proto",
+ "wifi_configuration_specifics.proto",
+ "workspace_desk_specifics.proto",
+]
diff --git a/pyhindsight/lib/components/sync/protocol/reading_list_specifics.proto b/pyhindsight/lib/components/sync/protocol/reading_list_specifics.proto
new file mode 100644
index 0000000..5728871
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/reading_list_specifics.proto
@@ -0,0 +1,46 @@
+// Copyright 2016 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 datatype extension for the reading list items.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+// Sync Reading list entry. This proto contains the fields synced for a reading
+// list entry. It must be kept synced with the reading_list.ReadingListLocal
+// protobuf.
+message ReadingListSpecifics {
+ // entry_id and url must be equal.
+ optional string entry_id = 1;
+ optional string title = 2;
+ optional string url = 3;
+
+ // The timestamps are microseconds since the unix epoch.
+ // TODO(crbug.com/353449026): Consider renaming the fields to use the
+ // preferred naming scheme, i.e. `_unix_epoch_micros`.
+ optional int64 creation_time_us = 4;
+ optional int64 update_time_us = 5;
+ optional int64 first_read_time_us = 7;
+ optional int64 update_title_time_us = 8;
+
+ optional int32 estimated_read_time_seconds = 9;
+
+ enum ReadingListEntryStatus {
+ UNREAD = 0;
+ READ = 1;
+ UNSEEN = 2;
+ }
+
+ // If the field is not present, it defaults to UNSEEN.
+ optional ReadingListEntryStatus status = 6;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/saved_tab_group_specifics.proto b/pyhindsight/lib/components/sync/protocol/saved_tab_group_specifics.proto
new file mode 100644
index 0000000..862e664
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/saved_tab_group_specifics.proto
@@ -0,0 +1,109 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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/tab_group_attribution_metadata.proto";
+
+// LINT.IfChange(SavedTabGroupSpecifics)
+// Sync protocol datatype extension for saved tab groups. Saved Tab Groups are
+// tab groups which can be recalled between browser sessions, and if sync is
+// turned on, cross device. A saved tab group contains tabs which are stored as
+// a SavedTabGroupSpecifics separately (SavedTabGroupTab). This is due to
+// limitations from the sync service on the size of an individual sync entity.
+message SavedTabGroup {
+ // These colors map to tab_groups::TabGroupColorId. They DO NOT match the enum
+ // integer values due to "kGrey" being in the "Unspecified" field.
+ enum SavedTabGroupColor {
+ SAVED_TAB_GROUP_COLOR_UNSPECIFIED = 0;
+ SAVED_TAB_GROUP_COLOR_GREY = 1;
+ SAVED_TAB_GROUP_COLOR_BLUE = 2;
+ SAVED_TAB_GROUP_COLOR_RED = 3;
+ SAVED_TAB_GROUP_COLOR_YELLOW = 4;
+ SAVED_TAB_GROUP_COLOR_GREEN = 5;
+ SAVED_TAB_GROUP_COLOR_PINK = 6;
+ SAVED_TAB_GROUP_COLOR_PURPLE = 7;
+ SAVED_TAB_GROUP_COLOR_CYAN = 8;
+ SAVED_TAB_GROUP_COLOR_ORANGE = 9;
+ }
+
+ // The position of the SavedTabGroup in any visual display. This also
+ // represents the index in the SavedTabGroupModel of the group. This field
+ // will be deprecated and replaced by the pinned_position field in tab group
+ // V2.
+ optional int64 position = 1;
+
+ // The displayed title of the group, shown on the tab group and the saved tab
+ // group button.
+ optional string title = 2;
+
+ // The color of the group, mapped to tab_groups::TabGroupColorId.
+ optional SavedTabGroupColor color = 3;
+
+ // Position of the pinned tab group in bookmark bar on Desktop. This will
+ // replace the position field in Tab Group V2.
+ optional int64 pinned_position = 4;
+
+ reserved 5;
+
+ // The guid of a bookmark node. This is used for associating a bookmark
+ // folder with a tab group by bookmarks tab group conversion.
+ optional string bookmark_node_id = 6;
+}
+
+// Sync protocol datatype extension for saved tab group tabs. SavedTabGroupTab
+// are the sync representation of a tab in a saved tab group. they are stored as
+// separate entities due to size limitations of sync entities.
+message SavedTabGroupTab {
+ // An id that links the saved tab group tab to it's saved tab group.
+ optional string group_guid = 1;
+
+ // The position in the Tab Strip the tab is located relative to the start of
+ // the tab group. This is also the index in the saved_tabs_ vector in the
+ // SavedTabGroup in the SavedTabGroupModel, which is updated by the
+ // TabStripModel.
+ optional int64 position = 2;
+
+ // Tab Data used for constructing the tab.
+ optional string url = 3;
+
+ // The displayed title of the tab, shown on the saved tab group button's
+ // context menu.
+ optional string title = 4;
+}
+
+message SavedTabGroupSpecifics {
+ // An id that refers to the sync saved tab group object.
+ optional string guid = 1;
+
+ // Timestamps for CRUD operations.
+ optional int64 creation_time_windows_epoch_micros = 2;
+ optional int64 update_time_windows_epoch_micros = 3;
+
+ oneof entity {
+ SavedTabGroup group = 4;
+ SavedTabGroupTab tab = 5;
+ }
+
+ // Attribution metadata about the associated tab group or tab.
+ optional AttributionMetadata attribution_metadata = 6;
+
+ // A mechanism to identify the client version that wrote this specifics.
+ // Designed to aid business logic when reading newly added fields that
+ // didn't exist in older clients.
+ // The client version must be incremented whenever a new field is added to the
+ // specifics.
+ optional int32 version = 7;
+}
+// LINT.ThenChange(//components/saved_tab_groups/internal/saved_tab_group_sync_bridge.cc:TrimAllSupportedFieldsFromRemoteSpecifics)
diff --git a/pyhindsight/lib/components/sync/protocol/search_engine_specifics.proto b/pyhindsight/lib/components/sync/protocol/search_engine_specifics.proto
new file mode 100644
index 0000000..aff67cc
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/search_engine_specifics.proto
@@ -0,0 +1,96 @@
+// 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 datatype extension for custom search engines.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_conversions.{h, cc}.
+
+// Fields that are not used anymore should be marked [deprecated = true].
+
+syntax = "proto2";
+
+option java_multiple_files = true;
+option java_package = "org.chromium.components.sync.protocol";
+
+option optimize_for = LITE_RUNTIME;
+
+package sync_pb;
+
+// Properties of custom search engine sync objects.
+message SearchEngineSpecifics {
+ // The description of the search engine.
+ optional string short_name = 1;
+ // The search engine keyword for omnibox access.
+ optional string keyword = 2;
+ // A URL to the favicon to show in the search engines options page.
+ optional string favicon_url = 3;
+ // The actual parameterized search engine query URL.
+ optional string url = 4;
+ // A flag signifying whether it is safe to automatically modify this search
+ // engine entry or not.
+ optional bool safe_for_autoreplace = 5;
+ // The URL to the OSD file this search engine entry came from.
+ optional string originating_url = 6;
+ // The date this search engine entry was created. A UTC timestamp with units
+ // in microseconds.
+ optional int64 date_created = 7;
+ // A list of supported input encodings.
+ optional string input_encodings = 8;
+ // Obsolete field. This used to represent whether or not this entry is shown
+ // in the list of default search engines.
+ optional bool deprecated_show_in_default_list = 9 [deprecated = true];
+ // The parameterized URL that provides suggestions as the user types.
+ optional string suggestions_url = 10;
+ // The ID associated with the prepopulate data this search engine comes from.
+ // Set to zero if it was not prepopulated.
+ optional int32 prepopulate_id = 11;
+ // DEPRECATED: Whether to autogenerate a keyword for the search engine or not.
+ // Do not write to this field in the future. We preserve this for now so we
+ // can read the field in order to migrate existing data that sets this bit.
+ optional bool autogenerate_keyword = 12 [deprecated = true];
+ // ID 13 reserved - previously used by `logo_id`, now deprecated.
+ optional string instant_url = 15 [deprecated = true];
+ // ID 16 reserved - previously used by `id`, now deprecated.
+ // The last time this entry was modified by a user. A UTC timestamp with units
+ // in microseconds.
+ optional int64 last_modified = 17;
+ // The primary identifier of this search engine entry for Sync.
+ optional string sync_guid = 18;
+ // A list of URL patterns that can be used, in addition to `url`, to extract
+ // search terms from a URL.
+ repeated string alternate_urls = 19;
+ optional string search_terms_replacement_key = 20 [deprecated = true];
+ // The parameterized URL that provides image results according to the image
+ // content or image URL provided by user.
+ optional string image_url = 21;
+
+ // The following post_params are comma-separated lists used to specify the
+ // post parameters for the corresponding search URL.
+ optional string search_url_post_params = 22;
+ optional string suggestions_url_post_params = 23;
+ optional string instant_url_post_params = 24 [deprecated = true];
+ optional string image_url_post_params = 25;
+
+ // The parameterized URL for a search provider specified new tab page.
+ optional string new_tab_url = 26;
+
+ enum ActiveStatus {
+ // The default state when a SE is auto-added. Unspecified SE are inactive.
+ ACTIVE_STATUS_UNSPECIFIED = 0;
+ // The SE is active and can be triggered via the omnibox.
+ ACTIVE_STATUS_TRUE = 1;
+ // The SE has been manually set to inactive by the user.
+ ACTIVE_STATUS_FALSE = 2;
+ }
+ // Whether a search engine is 'active' and can be triggered via the omnibox by
+ // typing in the relevant keyword.
+ optional ActiveStatus is_active = 27;
+ // The ID associated with the starter pack engine. This is set to 0 if not a
+ // starter pack engine.
+ optional int32 starter_pack_id = 28;
+
+ reserved 14;
+ reserved "created_by_policy";
+}
diff --git a/pyhindsight/lib/components/sync/protocol/security_event_specifics.proto b/pyhindsight/lib/components/sync/protocol/security_event_specifics.proto
new file mode 100644
index 0000000..f29ab7e
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/security_event_specifics.proto
@@ -0,0 +1,27 @@
+// Copyright 2019 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 datatype extension for security events.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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/gaia_password_reuse.proto";
+
+message SecurityEventSpecifics {
+ // The specific security event to record.
+ oneof event { GaiaPasswordReuse gaia_password_reuse_event = 1; }
+
+ // Time of event, as measured by client in microseconds since Windows epoch.
+ optional int64 event_time_usec = 2;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/send_tab_to_self_specifics.proto b/pyhindsight/lib/components/sync/protocol/send_tab_to_self_specifics.proto
new file mode 100644
index 0000000..d0026b6
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/send_tab_to_self_specifics.proto
@@ -0,0 +1,45 @@
+// Copyright 2018 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 datatype extension for the reading list items.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+// Send Tab To Self list entry. This proto contains the fields synced to send
+// a url across devices.
+message SendTabToSelfSpecifics {
+ // A random unique identifier for each shared tab.
+ // Required.
+ optional string guid = 5;
+ // The name of the tab being shared.
+ optional string title = 1;
+ // The URL of the tab being shared.
+ // Required.
+ optional string url = 2;
+ // The time the tab was shared as measured by the client in microseconds since
+ // the windows epoch.
+ optional int64 shared_time_usec = 3;
+ // A non-unique but human readable name to describe this client, used in UI.
+ optional string device_name = 4;
+ // The stable Device_id of the device that this tab was shared with.
+ // Required.
+ optional string target_device_sync_cache_guid = 7;
+ // A boolean to designate if the shared tab been opened on the target device.
+ optional bool opened = 8;
+ // Whether the notification for this proto been dismissed.
+ optional bool notification_dismissed = 9;
+
+ reserved "navigation_time_usec";
+ reserved 6;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/session_specifics.proto b/pyhindsight/lib/components/sync/protocol/session_specifics.proto
new file mode 100644
index 0000000..ac693b9
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/session_specifics.proto
@@ -0,0 +1,202 @@
+// 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 datatype extension for sessions.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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/sync_enums.proto";
+
+message SessionSpecifics {
+ // Unique id for the client. M89 and higher use sync's cache GUID (client ID)
+ // to populate this tag for *new* sessions.
+ optional string session_tag = 1;
+ optional SessionHeader header = 2;
+ optional SessionTab tab = 3;
+
+ // The local tab id used by sync. Unique across all nodes for that client.
+ optional int32 tab_node_id = 4 [default = -1];
+}
+
+// Properties of session sync objects.
+message SessionHeader {
+ // The timestamp when this session was started, i.e. when the user signed in
+ // or turned on the sessions data type. Introduced in M130, and not populated
+ // for sessions created/started before that milestone.
+ optional int64 session_start_time_unix_epoch_millis = 6;
+ // Each session is composed of windows.
+ repeated SessionWindow window = 2;
+ // A non-unique but human-readable name to describe this client.
+ optional string client_name = 3;
+ // The form factor of device.
+ optional SyncEnums.DeviceFormFactor device_form_factor = 5;
+
+ // The type of device.
+ // Mandatory until M115. Replaced by device_form_factor afterwards, but still
+ // populated for backward compatibility.
+ optional SyncEnums.DeviceType device_type = 4 [deprecated = true];
+}
+
+message SessionWindow {
+ // Unique (to the owner) id for this window.
+ optional int32 window_id = 1;
+ // Index of the selected tab in tabs; -1 if no tab is selected.
+ optional int32 selected_tab_index = 2 [default = -1];
+ // Type of the window.
+ optional SyncEnums.BrowserType browser_type = 3 [default = TYPE_TABBED];
+ // The tabs that compose a window (correspond to tab id's).
+ repeated int32 tab = 4;
+}
+
+message SessionTab {
+ // Unique (to the owner) id for this tab.
+ optional int32 tab_id = 1 [default = -1];
+ // The unique id for the window this tab belongs to.
+ optional int32 window_id = 2;
+ // Visual index of the tab within its window. There may be gaps in these
+ // values.
+ optional int32 tab_visual_index = 3 [default = -1];
+ // Identifies the index of the current navigation in navigations. For
+ // example, if this is 2 it means the current navigation is navigations[2].
+ optional int32 current_navigation_index = 4 [default = -1];
+ // True if the tab is pinned.
+ optional bool pinned = 5 [default = false];
+ // If non-empty, this tab is an app tab and this is the id of the extension.
+ optional string extension_app_id = 6;
+ // Tabs are navigated, and the navigation data is here.
+ repeated TabNavigation navigation = 7;
+
+ optional SyncEnums.BrowserType browser_type = 13;
+
+ // Timestamp for when this tab was last activated.
+ // Corresponds to WebContents::GetLastActiveTime().
+ optional int64 last_active_time_unix_epoch_millis = 14;
+
+ // The favicon for the current url the tab is displaying. Either empty
+ // or a valid PNG encoded favicon.
+ optional bytes favicon = 8 [deprecated = true];
+ // The type of favicon. For now only normal web favicons are supported.
+ enum FaviconType { TYPE_WEB_FAVICON = 1; }
+ optional FaviconType favicon_type = 9 [deprecated = true];
+ // The url of the actual favicon (as opposed to the page using the favicon).
+ optional string favicon_source = 11 [deprecated = true];
+ // Ids of the currently assigned variations which should be sent to sync.
+ repeated uint64 variation_id = 12 [deprecated = true];
+}
+
+message TabNavigation {
+ // The page's URL as displayed to the user (which can be the actual page URL
+ // or a virtual override). It can be empty or, in rare cases, an unsyncable
+ // URL, so it is the receiver's responsibility to implement additional
+ // filtering before displaying these URLs or tabs in the UI.
+ optional string virtual_url = 2;
+ // The referring URL, which can be empty.
+ optional string referrer = 3;
+ // The title of the page.
+ optional string title = 4;
+ // The core transition type.
+ optional SyncEnums.PageTransition page_transition = 6 [default = LINK];
+ // If this transition was triggered by a redirect, the redirect type.
+ optional SyncEnums.PageTransitionRedirectType redirect_type = 7;
+ // The unique navigation id (within this client).
+ optional int32 unique_id = 8;
+ // Timestamp for when this navigation last occurred (in client time).
+ // If the user goes back/forward in history the timestamp may refresh.
+ optional int64 timestamp_msec = 9;
+ // User used the Forward or Back button to navigate among browsing history.
+ optional bool navigation_forward_back = 10;
+ // User used the address bar to trigger this navigation.
+ optional bool navigation_from_address_bar = 11;
+ // User is navigating to the home page.
+ optional bool navigation_home_page = 12;
+ // The id for this navigation, which is globally unique with high
+ // probability.
+ optional int64 global_id = 15;
+ // The favicon url associated with this page.
+ optional string favicon_url = 17;
+
+ // The status code from the last navigation.
+ optional int32 http_status_code = 20;
+
+ // Correct referrer policy. Valid enums are defined in
+ // third_party/WebKit/public/platform/WebReferrerPolicy.h.
+ optional int32 correct_referrer_policy = 25 [default = 1];
+
+ // Whether the Password Manager saw a password field on the page.
+ optional SyncEnums.PasswordState password_state = 26;
+
+ // The start/end of a redirect chain. Deprecated in M108 because they were
+ // always set to false in practice, and don't make sense in the first place -
+ // this message corresponds to a complete chain.
+ optional bool navigation_chain_start = 13 [deprecated = true];
+ optional bool navigation_chain_end = 14 [deprecated = true];
+ // Search terms extracted from the URL. Deprecated in M64.
+ optional string search_terms = 16 [deprecated = true];
+ enum BlockedState {
+ STATE_ALLOWED = 1;
+ STATE_BLOCKED = 2;
+ }
+ // Whether access to the URL was allowed or blocked. Deprecated in M121
+ // because it was unused.
+ optional BlockedState blocked_state = 18
+ [deprecated = true, default = STATE_ALLOWED];
+ // Referrer policy. Old, broken value. Deprecated in M61.
+ optional int32 obsolete_referrer_policy = 21 [deprecated = true];
+ // True if created from restored navigation entry that hasn't been loaded.
+ // Deprecated in M121 because it was unused.
+ optional bool is_restored = 22 [deprecated = true];
+ // The chain of redirections for this navigation, from the original URL
+ // through the last URL that redirected. Deprecated in M121 because it was
+ // unused.
+ repeated NavigationRedirect navigation_redirect = 23 [deprecated = true];
+ // The last URL traversed when different from the virtual_url. Deprecated in
+ // M121 because it was unused.
+ optional string last_navigation_redirect_url = 24 [deprecated = true];
+ // The id for the task associated with this navigation, which is globally
+ // unique with high probability. Deprecated in M121 because it was unused.
+ optional int64 task_id = 27 [deprecated = true];
+ // Task ids of all ancestor navigations, which can be from other tabs, from
+ // root to parent. Deprecated in M121 because it was unused.
+ repeated int64 ancestor_task_id = 28 [deprecated = true];
+ // When a history entry is replaced (e.g. history.replaceState()), this
+ // contained some information about the entry prior to being replaced.
+ // Deprecated in M121 because it was unused.
+ optional ReplacedNavigation replaced_navigation = 29 [deprecated = true];
+ // The page language as determined by its textual content. An ISO 639 language
+ // code (two letters, except for Chinese where a localization is necessary).
+ // Deprecated in M121 because it was unused.
+ optional string page_language = 30 [deprecated = true];
+
+ reserved 1;
+ reserved "index";
+ reserved 5;
+ reserved "state";
+ reserved 19;
+ reserved "content_pack_categories";
+}
+
+// Navigation information for a single redirection within a single navigation.
+message NavigationRedirect {
+ // A URL that redirected while navigating to the virtual_url.
+ optional string url = 1;
+}
+
+// Subset of TabNavigation fields representing a navigation that was later
+// replaced in history (e.g. history.replaceState()), which allows tracking
+// information about the original navigation prior to the first replacement.
+message ReplacedNavigation {
+ optional string first_committed_url = 1;
+ optional int64 first_timestamp_msec = 2;
+ optional SyncEnums.PageTransition first_page_transition = 3;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/shared_comment_specifics.proto b/pyhindsight/lib/components/sync/protocol/shared_comment_specifics.proto
new file mode 100644
index 0000000..e524a40
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/shared_comment_specifics.proto
@@ -0,0 +1,141 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+// Represents the context of a URL shared within a group, including its various
+// representations and metadata.
+message SharedUrlContext {
+ enum Source {
+ // The source is not specified.
+ SOURCE_UNSPECIFIED = 0;
+ // The current URL shown in the Omnibox.
+ OMNIBOX = 1;
+ // The URL we received or sent through Chrome Sync.
+ FROM_SYNC = 2;
+ // The Canonical URL the client identified.
+ CANONICAL_URL = 3;
+ }
+
+ // A specific representation of a URL from a particular source.
+ message UrlRepresentation {
+ // Where this URL representation was received from.
+ optional Source source = 1;
+ // The URL, hash, or other unique identifier for this representation.
+ optional string value = 2;
+ // An optional version string to differentiate representations over time.
+ optional string version = 3;
+ }
+
+ // A list of all known representations for this URL. This allows different
+ // clients to find a common representation for identifying the page.
+ repeated UrlRepresentation representations = 1;
+
+ // The title of the web page this SharedUrlContext refers to.
+ optional string title = 2;
+}
+
+// Contains all the data for a user-authored comment, including its
+// content, sorting key, and attribution.
+message CommentData {
+ // The user-authored comment string, which may contain rich text.
+ optional string text = 1;
+
+ // Describes what a comment is about, such as a reply to another comment or a
+ // new comment on a specific target.
+ message Attribution {
+ // Identifies the target of a top-level comment.
+ message CommentTarget {
+ // The UUID of the `SharedUrlContext` specifics this comment is attached
+ // to.
+ optional string shared_url_context_uuid = 1;
+
+ // A link to a specific text fragment within the page (i.e., a "deep
+ // link").
+ message FragmentLink {
+ // The fragment part of the link, i.e. the #:~:text=... part of the
+ // link.
+ optional string fragment = 1;
+ // A string representation of the selected text to be used in previews.
+ optional string text_preview = 2;
+ }
+ // An optional link to a text fragment within the page.
+ optional FragmentLink link_fragment = 2;
+ }
+
+ // Identifies the parent comment this comment is a reply to.
+ message InReplyTo {
+ // The UUID of the parent comment.
+ optional string parent_id = 1;
+ }
+
+ // Defines whether the comment is a new thread or a reply.
+ oneof kind {
+ // The target if this is a new top-level comment.
+ CommentTarget top_level = 1;
+ // Metadata about the parent comment if this is a reply.
+ InReplyTo parent = 2;
+ }
+ }
+
+ // The attribution data for this comment, indicating what it refers to.
+ optional Attribution attribution = 2;
+
+ // Defines a key used for deterministically sorting comments in a distributed
+ // system. This ensures that all clients render comments in the same stable
+ // order, regardless of network timing or processing order. This is intended
+ // to be used together with the creation time of an entity to provide a
+ // strictly monotonically increasing ordering.
+ message OrderKey {
+ // A unique identifier for the device or client that authored the comment
+ // (e.g., a GUID). This serves as the main tie-breaker for comments with
+ // identical timestamps.
+ optional string device_guid = 1;
+
+ // A strictly monotonically increasing sequence number generated by the
+ // source device. Any sequence number is guaranteed to not be reused for the
+ // same source device. This provides a final, definitive ordering for
+ // comments created by the same source, even if they arrive out of order.
+ optional int64 local_sequence = 2;
+ }
+ // A key for deterministically sorting entities.
+ optional OrderKey order_key = 3;
+}
+
+// Represents a single entity in the commenting system, which can be either a
+// user comment or a URL context object. This is the top-level message for a
+// single comment-related sync entity.
+message SharedCommentSpecifics {
+ // A unique identifier (UUID) for this entity.
+ optional string uuid = 1;
+
+ // A stable, permanent identifier for the collaboration context this entity
+ // belongs to. It serves as a permanent foreign key to group related data
+ // types (e.g., comments, tab groups) that belong to the same logical
+ // collaboration. This ID never changes, even if the underlying entity is
+ // shared or unshared, thus preventing data from being orphaned.
+ optional string context_id = 2;
+
+ // The highest SharedCommentSpecifics version supported by the client that
+ // wrote this entity.
+ optional int64 proto_version = 3;
+
+ // The main payload of this entity.
+ oneof entity {
+ // The content of a user-authored comment.
+ CommentData comment = 4;
+ // The context for a URL being commented on.
+ SharedUrlContext shared_url_context = 5;
+ }
+}
diff --git a/pyhindsight/lib/components/sync/protocol/shared_tab_group_account_data_specifics.proto b/pyhindsight/lib/components/sync/protocol/shared_tab_group_account_data_specifics.proto
new file mode 100644
index 0000000..ce0dcba
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/shared_tab_group_account_data_specifics.proto
@@ -0,0 +1,61 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+// Account-local metadata for shared tab groups.
+// LINT.IfChange(SharedTabGroupAccountDataSpecifics)
+message SharedTabGroupAccountDataSpecifics {
+ // The guid of this entity.
+ // This could be the SharedTab guid (see SharedTabGroupDataSpecifics)
+ // or the SharedTabGroup guid.
+ optional string guid = 1;
+
+ // The collaboration group.
+ optional string collaboration_id = 2;
+
+ // Entities that contains information for a tab or a tab group.
+ oneof entity {
+ SharedTabDetails shared_tab_details = 3;
+ SharedTabGroupDetails shared_tab_group_details = 4;
+ }
+
+ // Timestamp when the message is updated.
+ optional int64 update_time_windows_epoch_micros = 5;
+
+ // A mechanism to identify the client version that wrote this specifics.
+ // Designed to aid business logic when reading newly added fields that
+ // didn't exist in older clients.
+ // The client version must be incremented whenever a new field is added to the
+ // specifics.
+ optional int32 version = 6;
+}
+
+// Stores account-specific metadata about a shared tab.
+message SharedTabDetails {
+ // The GUID of the SharedTabGroup this is a member of. This is the same
+ // as that from SharedTab in SharedTabGroupDataSpecifics.
+ optional string shared_tab_group_guid = 1;
+
+ // Last time this tab was focused.
+ optional int64 last_seen_timestamp_windows_epoch = 2;
+}
+
+message SharedTabGroupDetails {
+ // Position of the pinned tab group in bookmark bar on Desktop.
+ // This is equivalent to and compared against the pinned_position
+ // of message SavedTabGroup in saved_tab_group_specifics.proto.
+ optional int64 pinned_position = 1;
+}
+// LINT.ThenChange(//components/saved_tab_groups/internal/shared_tab_group_account_data_sync_bridge.cc:TrimSpecifics)
diff --git a/pyhindsight/lib/components/sync/protocol/shared_tab_group_data_specifics.proto b/pyhindsight/lib/components/sync/protocol/shared_tab_group_data_specifics.proto
new file mode 100644
index 0000000..22012ba
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/shared_tab_group_data_specifics.proto
@@ -0,0 +1,118 @@
+// Copyright 2024 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 datatype extension for shared tab groups and tabs.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+// copybara:uncomment_begin(google-only)
+// import "components/sync/protocol/sync_collaboration_attribution.proto";
+// copybara:uncomment_end
+
+import "components/sync/protocol/unique_position.proto";
+
+// LINT.IfChange(SharedTabGroupDataSpecifics)
+// IMPORTANT: please update
+// shared_tab_group_data_specifics_full_proto_unittest.cc if you change any
+// sync_collaboration_attribution FieldOptions.
+message SharedTabGroupDataSpecifics {
+ // Unique identifier for this entity.
+ optional string guid = 1;
+
+ oneof entity {
+ SharedTabGroup tab_group = 3;
+ SharedTab tab = 4;
+ }
+
+ optional int64 update_time_windows_epoch_micros = 5;
+
+ // A mechanism to identify the client version that wrote this specifics.
+ // Designed to aid business logic when reading newly added fields that
+ // didn't exist in older clients.
+ // The client version must be incremented whenever a new field is added to the
+ // specifics.
+ optional int32 version = 6;
+
+ reserved 2;
+}
+
+message SharedTabGroup {
+ // The displayed title of the group, shown on the tab group.
+ optional string title = 1
+ // copybara:uncomment_begin(google-only)
+ // [(sync_collaboration_attribution) = {
+ // attribution_type: LAST_MODIFIED_BY_USER
+ // name: "tab_group_title"
+ // }]
+ // copybara:uncomment_end
+ ;
+
+ // These colors map to tab_groups::TabGroupColorId. They DO NOT match the enum
+ // integer values due to "kGrey" being in the "Unspecified" field.
+ enum Color {
+ UNSPECIFIED = 0;
+ GREY = 1;
+ BLUE = 2;
+ RED = 3;
+ YELLOW = 4;
+ GREEN = 5;
+ PINK = 6;
+ PURPLE = 7;
+ CYAN = 8;
+ ORANGE = 9;
+ }
+ // The color of the tab group, mapped to tab_groups::TabGroupColorId.
+ optional Color color = 2
+ // copybara:uncomment_begin(google-only)
+ // [(sync_collaboration_attribution) = {
+ // attribution_type: LAST_MODIFIED_BY_USER
+ // name: "tab_group_color"
+ // }]
+ // copybara:uncomment_end
+ ;
+
+ // Saved tab group GUID from which this shared tab group was created.
+ optional string originating_tab_group_guid = 3;
+}
+
+message SharedTab {
+ // The URL of the page.
+ optional string url = 1
+ // copybara:uncomment_begin(google-only)
+ // [(sync_collaboration_attribution) = {
+ // attribution_type: LAST_MODIFIED_BY_USER
+ // name: "tab_url"
+ // }]
+ // copybara:uncomment_end
+ ;
+
+ // The title of the page.
+ optional string title = 2
+ // copybara:uncomment_begin(google-only)
+ // [(sync_collaboration_attribution) = {
+ // attribution_type: LAST_MODIFIED_BY_USER
+ // name: "tab_title"
+ // }]
+ // copybara:uncomment_end
+ ;
+
+ // The GUID of the SharedTabGroup this is a member of.
+ optional string shared_tab_group_guid = 4;
+ // The UniquePosition within a SharedTabGroup.
+ optional UniquePosition unique_position = 5;
+
+ reserved 3;
+ reserved "favicon_url";
+}
+// LINT.ThenChange(//components/saved_tab_groups/internal/shared_tab_group_data_sync_bridge.cc:TrimAllSupportedFieldsFromRemoteSpecifics)
diff --git a/pyhindsight/lib/components/sync/protocol/shared_tab_group_data_specifics_full_proto_unittest.cc b/pyhindsight/lib/components/sync/protocol/shared_tab_group_data_specifics_full_proto_unittest.cc
new file mode 100644
index 0000000..00144cf
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/shared_tab_group_data_specifics_full_proto_unittest.cc
@@ -0,0 +1,93 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/sync/protocol/shared_tab_group_data_specifics_full_proto.pb.h"
+#include "components/sync/protocol/sync_collaboration_attribution_full_proto.pb.h"
+#include "google/protobuf/descriptor.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using sync_pb::SharedTab;
+using sync_pb::SharedTabGroup;
+using sync_pb::SharedTabGroupDataSpecifics;
+using sync_pb::sync_collaboration_attribution;
+using sync_pb::SyncCollaborationAttribution;
+
+namespace {
+// Test annotations in uncommented full proto buffer.
+TEST(SharedTabGroupDataSpecificsFullProtoTest,
+ ShouldReflectAndReadCustomAnnotations) {
+ const google::protobuf::Descriptor* group_descriptor =
+ SharedTabGroup::descriptor();
+ ASSERT_TRUE(group_descriptor);
+
+ // Verify the 'title' field annotation.
+ const google::protobuf::FieldDescriptor* group_title_field =
+ group_descriptor->FindFieldByName("title");
+ ASSERT_TRUE(group_title_field);
+
+ const google::protobuf::FieldOptions& group_title_options =
+ group_title_field->options();
+ EXPECT_TRUE(group_title_options.HasExtension(sync_collaboration_attribution));
+
+ const SyncCollaborationAttribution& group_title_annotation =
+ group_title_options.GetExtension(sync_collaboration_attribution);
+
+ EXPECT_EQ(group_title_annotation.attribution_type(),
+ SyncCollaborationAttribution::LAST_MODIFIED_BY_USER);
+ EXPECT_EQ(group_title_annotation.name(), "tab_group_title");
+
+ // Verify the 'color' field annotation.
+ const google::protobuf::FieldDescriptor* group_color_field =
+ group_descriptor->FindFieldByName("color");
+ ASSERT_TRUE(group_color_field);
+
+ const google::protobuf::FieldOptions& group_color_options =
+ group_color_field->options();
+ EXPECT_TRUE(group_color_options.HasExtension(sync_collaboration_attribution));
+
+ const SyncCollaborationAttribution& group_color_annotation =
+ group_color_options.GetExtension(sync_collaboration_attribution);
+
+ EXPECT_EQ(group_color_annotation.attribution_type(),
+ SyncCollaborationAttribution::LAST_MODIFIED_BY_USER);
+ EXPECT_EQ(group_color_annotation.name(), "tab_group_color");
+
+ // Test annotations on SharedTab message
+ const google::protobuf::Descriptor* tab_descriptor = SharedTab::descriptor();
+ ASSERT_TRUE(tab_descriptor);
+
+ // Verify the 'url' field annotation.
+ const google::protobuf::FieldDescriptor* tab_url_field =
+ tab_descriptor->FindFieldByName("url");
+ ASSERT_TRUE(tab_url_field);
+
+ const google::protobuf::FieldOptions& tab_url_options =
+ tab_url_field->options();
+ EXPECT_TRUE(tab_url_options.HasExtension(sync_collaboration_attribution));
+
+ const SyncCollaborationAttribution& tab_url_annotation =
+ tab_url_options.GetExtension(sync_collaboration_attribution);
+
+ EXPECT_EQ(tab_url_annotation.attribution_type(),
+ SyncCollaborationAttribution::LAST_MODIFIED_BY_USER);
+ EXPECT_EQ(tab_url_annotation.name(), "tab_url");
+
+ // Verify the 'title' field annotation for tab.
+ const google::protobuf::FieldDescriptor* tab_title_field =
+ tab_descriptor->FindFieldByName("title");
+ ASSERT_TRUE(tab_title_field);
+
+ const google::protobuf::FieldOptions& tab_title_options =
+ tab_title_field->options();
+ EXPECT_TRUE(tab_title_options.HasExtension(sync_collaboration_attribution));
+
+ const SyncCollaborationAttribution& tab_title_annotation =
+ tab_title_options.GetExtension(sync_collaboration_attribution);
+
+ EXPECT_EQ(tab_title_annotation.attribution_type(),
+ SyncCollaborationAttribution::LAST_MODIFIED_BY_USER);
+ EXPECT_EQ(tab_title_annotation.name(), "tab_title");
+}
+
+} // namespace
diff --git a/pyhindsight/lib/components/sync/protocol/sharing_message_specifics.proto b/pyhindsight/lib/components/sync/protocol/sharing_message_specifics.proto
new file mode 100644
index 0000000..37e8189
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/sharing_message_specifics.proto
@@ -0,0 +1,122 @@
+// Copyright 2020 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 datatype extension for sharing message.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_conversions.{h, cc}.
+
+syntax = "proto2";
+
+option java_multiple_files = true;
+option java_package = "org.chromium.components.sync.protocol";
+
+option optimize_for = LITE_RUNTIME;
+
+import "components/sync/protocol/unencrypted_sharing_message.proto";
+
+package sync_pb;
+
+message SharingMessageSpecifics {
+ // Unique identifier of message.
+ optional string message_id = 1;
+
+ message ChannelConfiguration {
+ message FCMChannelConfiguration {
+ // FCM registration token of target device.
+ optional string token = 1;
+
+ // Time to live for a FCM message (in seconds) - if specified, the message
+ // will expire based on the TTL.
+ optional int32 ttl = 2;
+
+ // Priority level of a FCM message. 5 = normal, 10 = high.
+ optional int32 priority = 3;
+ }
+
+ message ChimeChannelConfiguration {
+ // The channels supported for delivery in the notifications pipeline.
+ // Numbering should be kept in sync with
+ // google3/notifications/backend/proto/common/channel_types.proto.
+ enum ChimeChannelType {
+ CHANNEL_TYPE_UNSPECIFIED = 0;
+ // This uses the AppleSelection for selecting targets.
+ APPLE_PUSH = 2;
+ }
+ // The device registration token. For iOS, this should be the
+ // Apple device token.
+ optional bytes device_token = 1;
+
+ // Channel for delivery.
+ optional ChimeChannelType channel_type = 2;
+
+ // Identifies the type of this notification within Chime.
+ // The value of this field must correspond to a previously
+ // configured type for the "chrome_chime" client id at
+ // google3/googledata/notifications/config/clients/chrome_chime.
+ optional string type_id = 3;
+
+ // RTID provided by Chime after user is registered. Required if message
+ // should target specific device, otherwise optional.
+ optional string representative_target_id = 4;
+ }
+
+ oneof channel_configuration {
+ // FCM channel configuration. Message will be delivered as a FCM message.
+ FCMChannelConfiguration fcm = 1;
+
+ // Opaque server channel configuration. Message will be delivered through
+ // server channel.
+ bytes server = 2;
+
+ // Chime channel configuration. Message will be delivered through Chime.
+ ChimeChannelConfiguration chime = 3;
+ }
+ }
+
+ optional ChannelConfiguration channel_configuration = 2;
+
+ // Payload encrypted using the target user keys according to WebPush
+ // encryption scheme. The payload has to be a valid
+ // components/sharing_message/proto/sharing_message.proto serialized using
+ // SerializeToString.
+ optional bytes payload = 3;
+
+ // Payload NOT encrypted. For encrypted payloads, use payload field.
+ optional UnencryptedSharingMessage unencrypted_payload = 4;
+}
+
+// Used for the server to return fine grained commit errors back to the client.
+message SharingMessageCommitError {
+ // This enum is used in histograms. Entries should not be renumbered and
+ // numeric values should never be reused. Also remember to update in
+ // tools/metrics/histograms/enums.xml SyncSharingMessageCommitErrorCode enum.
+ // LINT.IfChange(SyncSharingMessageCommitErrorCode)
+ enum ErrorCode {
+ NONE = 0;
+ INVALID_ARGUMENT = 1;
+ NOT_FOUND = 2;
+ INTERNAL = 3;
+ UNAVAILABLE = 4;
+ RESOURCE_EXHAUSTED = 5;
+ UNAUTHENTICATED = 6;
+ PERMISSION_DENIED = 7;
+
+ // Client-specific error codes.
+ SYNC_TURNED_OFF = 8;
+ SYNC_NETWORK_ERROR = 9;
+ // Deprecated UMA bucket, prior to splitting between SYNC_SERVER_ERROR and
+ // SYNC_AUTH_ERROR.
+ DEPRECATED_SYNC_SERVER_OR_AUTH_ERROR = 10;
+ // Message wasn't committed before timeout.
+ SYNC_TIMEOUT = 11;
+ // Error code for server error or unparsable server response.
+ SYNC_SERVER_ERROR = 12;
+ // Auth error when communicating with the server.
+ SYNC_AUTH_ERROR = 13;
+ }
+ // LINT.ThenChange(/tools/metrics/histograms/metadata/sync/enums.xml:SyncSharingMessageCommitErrorCode)
+
+ optional ErrorCode error_code = 1;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/sync.proto b/pyhindsight/lib/components/sync/protocol/sync.proto
new file mode 100644
index 0000000..f3f519f
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/sync.proto
@@ -0,0 +1,512 @@
+// 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 version of this item -- a monotonically increasing value that is
+ // maintained by the server. See equivalent field in SyncEntity.
+ // If the returned version is smaller than the version the client already
+ // knew, the client will ignore the response, which means the item will
+ // still be considered to require a commit.
+ 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. Note that this message is handled even when coming
+// from the legacy client (i.e. for which the server would reject
+// GetUpdates/Commit messages), that means breaking server-side changes need to
+// be handled carefully.
+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;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/sync_collaboration_attribution.proto b/pyhindsight/lib/components/sync/protocol/sync_collaboration_attribution.proto
new file mode 100644
index 0000000..c8b25ea
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/sync_collaboration_attribution.proto
@@ -0,0 +1,54 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+
+option java_multiple_files = true;
+option java_package = "org.chromium.components.sync.protocol";
+
+package sync_pb;
+
+import "google/protobuf/descriptor.proto";
+
+// Configuration for per-field attribution in collaborative Sync data types.
+// Attaching this as an option to a field within a Sync entity's proto
+// definition (e.g., in a SharedTab or SharedTabGroup) enables the tracking of
+// metadata related to cross-user collaboration, such as which user last
+// modified that specific field.
+message SyncCollaborationAttribution {
+ enum AttributionType {
+ // Default value. No attribution tracking for this field.
+ NONE = 0;
+ // Track the user who last modified this field.
+ LAST_MODIFIED_BY_USER = 1;
+ }
+
+ // Specifies the type of attribution to be applied to the annotated field.
+ optional AttributionType attribution_type = 1;
+
+ // A stable identifier for the annotated field, used to distinguish it from
+ // other fields within the same Chrome Sync data type message that also
+ // have attribution annotations. This identifier is used to associate
+ // attribution information (like the last modifier) with this specific field
+ // of the Sync Entity.
+ //
+ // This name is also used in the metadata of SyncEntity that are sent to
+ // clients, such that the client code key to find the related attribution
+ // data.
+ //
+ // Because of this, the name MUST be unique across all fields annotated with
+ // `sync_collaboration_attribution` within a single EntitySpecifics. For
+ // example, all `name` values within `SharedTabGroupData` must be distinct.
+ //
+ // Recommended format: `lower_snake_case`.
+ // Examples: "tab_group_title", "tab_url", "tab_group_color".
+ optional string name = 2;
+}
+
+extend google.protobuf.FieldOptions {
+ // IMPORTANT: the extension number needs to be declared. See
+ // go/extension-declaration-reserved-numbers for more information.
+ optional SyncCollaborationAttribution sync_collaboration_attribution =
+ 535801565;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/sync_entity.proto b/pyhindsight/lib/components/sync/protocol/sync_entity.proto
new file mode 100644
index 0000000..64e2c9e
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/sync_entity.proto
@@ -0,0 +1,281 @@
+// Copyright 2021 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+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/deletion_origin.proto";
+import "components/sync/protocol/entity_specifics.proto";
+import "components/sync/protocol/unique_position.proto";
+
+message SyncEntity {
+ // This item's identifier. In a commit of a new item, this will be a
+ // client-generated ID. If the commit succeeds, the server will generate
+ // a globally unique ID and return it to the committing client in the
+ // CommitResponse.EntryResponse. In the context of a GetUpdatesResponse,
+ // `id_string` is always the server generated ID. The original
+ // client-generated ID is preserved in the `originator_client_id` field.
+ // Present in both GetUpdatesResponse and CommitMessage.
+ // Prior to M123, this field was empty for commit-only types.
+ optional string id_string = 1;
+
+ // An id referencing this item's parent in the hierarchy. In a
+ // CommitMessage, it is accepted for this to be a client-generated temporary
+ // ID if there was a new created item with that ID appearing earlier
+ // in the message. In all other situations, it is a server ID.
+ // Present in both GetUpdatesResponse and CommitMessage.
+ //
+ // Starting with M99, this field is optional and used for legacy bookmarks
+ // only:
+ // 1. When processing GetUpdatesResponse, it is unused for modern data created
+ // or reuploaded by M94 or above, which populates the parent's GUID in
+ // BookmarkSpecifics (which is sufficient).
+ // 2. When issuing CommitMessage, the field is populated for compatibility
+ // with clients before M99.
+ optional string parent_id_string = 2;
+
+ reserved 3;
+ reserved "old_parent_id";
+
+ // The version of this item -- a monotonically increasing value that is
+ // maintained by the server (or more precisely, the storage backend). It is
+ // typically a timestamp, in microseconds since the Unix epoch, of the last
+ // backend write. Present in both CommitMessage (set by the client) and
+ // GetUpdatesResponse (set by the server), and there's also an equivalent
+ // field in CommitResponse.
+ //
+ // In a CommitMessage, `version` is set to zero for newly-created items. For
+ // updates to existing items, it is set by the client to the last version the
+ // client knew about when sending the commit. If this version does not match
+ // the latest version on the server, the commit *may* fail for that item with
+ // a result code of CONFLICT. However, this is not guaranteed, and in
+ // practice is not implemented for most data types.
+ //
+ // In a GetUpdatesResponse, `version` is always positive and identifies the
+ // revision of the item stored in the server backend. If the returned version
+ // is smaller than the version the client already knew, the client will ignore
+ // the response.
+ //
+ // WARNING: This field used to be required before M60. Any client before this
+ // will fail to deserialize if this field is missing.
+ optional int64 version = 4;
+
+ // Last modification time, in milliseconds since Unix epoch.
+ // Present in both GetUpdatesResponse and CommitMessage.
+ optional int64 mtime = 5;
+
+ // Creation time, in milliseconds since Unix epoch.
+ // Present in both GetUpdatesResponse and CommitMessage.
+ optional int64 ctime = 6;
+
+ // The name of this item.
+ // Historical note:
+ // Since November 2010, this value is no different from non_unique_name.
+ // Before then, server implementations would maintain a unique-within-parent
+ // value separate from its base, "non-unique" value. Clients had not
+ // depended on the uniqueness of the property since November 2009; it was
+ // removed from Chromium by http://codereview.chromium.org/371029 .
+ // Present in both GetUpdatesResponse and CommitMessage.
+ // WARNING: This field used to be required before M60. Any client before this
+ // will fail to deserialize if this field is missing.
+ optional string name = 7;
+
+ // The name of this item. Same as `name`.
+ // `non_unique_name` should take precedence over the `name` value if both
+ // are supplied. For efficiency, clients and servers should avoid setting
+ // this redundant value.
+ // Present in both GetUpdatesResponse and CommitMessage.
+ optional string non_unique_name = 8;
+
+ reserved 9;
+ reserved "sync_timestamp";
+
+ // If present, this tag identifies this item as being a uniquely
+ // instanced item. The server ensures that there is never more
+ // than one entity in a user's store with the same tag value.
+ // This value is used to identify and find e.g. the "Bookmark Bar" folder
+ // without relying on a particular ID or name.
+ //
+ // This variant of the tag is created by the server, so clients can't create
+ // an item with a tag using this field.
+ //
+ // Use client_tag_hash if you want to create one from the client.
+ //
+ // An item can't have both a client_tag_hash and
+ // a server_defined_unique_tag.
+ //
+ // Present only in GetUpdatesResponse.
+ optional string server_defined_unique_tag = 10;
+
+ reserved 11;
+ reserved "BookmarkData";
+ reserved 12;
+ reserved "bookmark_folder";
+ reserved 13;
+ reserved "bookmark_url";
+ reserved 14;
+ reserved "bookmark_favicon";
+
+ // Ancient fields, predecessors for `unique_position`, deprecated with M26 and
+ // still supported to deal with old incoming data. See field `unique_position`
+ // for details as well as the data-upgrading implementation in
+ // GetUniquePositionFromSyncEntity().
+ optional int64 position_in_parent = 15 [deprecated = true];
+ optional string insert_after_item_id = 16 [deprecated = true];
+
+ reserved 17;
+ reserved "extended_attributes";
+
+ // If true, indicates that this item has been (or should be) deleted.
+ // Present in both GetUpdatesResponse and CommitMessage.
+ optional bool deleted = 18 [default = false];
+
+ // A unique ID that identifies the the sync client who initially committed
+ // this entity. This value corresponds to `cache_guid` in CommitMessage.
+ // This field, along with `originator_client_item_id`, can be used to
+ // reunite the original with its official committed version in the case
+ // where a client does not receive or process the commit response for
+ // some reason.
+ //
+ // Present only in GetUpdatesResponse.
+ //
+ // This field is also used in determining the unique identifier used in
+ // bookmarks' unique_position field.
+ optional string originator_cache_guid = 19;
+
+ // Item ID as generated by the client that initially created this entity. Used
+ // exclusively for bookmarks (other datatypes use client_tag_hash).
+ // There are three generation of bookmarks that have populated this field
+ // differently, depending on which version of the browser created the
+ // bookmark:
+ // 1. For bookmarks created before M44 (2015), the field got populated with an
+ // ID that is locally unique, but not globally unique (usually a negative
+ // number).
+ // 2. For bookmarks created between M45 and M51, both inclusive, the field got
+ // populated with a globally unique GUID in uppercase form.
+ // 3. For bookmarks created with M52 or above, the field gets populated with
+ // a globally unique GUID in lowercase form.
+ //
+ // Present only in GetUpdatesResponse.
+ optional string originator_client_item_id = 20;
+
+ // Extensible container for datatype-specific data.
+ // This became available in version 23 of the protocol.
+ optional EntitySpecifics specifics = 21;
+
+ // Indicate whether this is a folder or not. Available in version 23+.
+ optional bool folder = 22 [default = false];
+
+ // A client defined unique hash for this entity.
+ // Analogous to server_defined_unique_tag, but allows the client to determine
+ // an immutable attribute of the entity in hashed form that makes it unique
+ // per user (i.e. at most one entity may exist per client tag hash).
+ //
+ // This value must be of the form base64(SHA1(client_tag)) where the
+ // client_tag is a value derived from the contents of an entity in a
+ // type-specific way. Since the hashed contents of the client_tag are exposed
+ // to the server via this field, take care when defining it that there is
+ // enough entropy to mask any secrets that the server shouldn't learn.
+ //
+ // The difference between server_defined_unique_tag and
+ // client_tag_hash is the creator of the entity. Server defined
+ // tags are entities created by the server at account creation,
+ // while client defined tags are entities created by the client at any time.
+ //
+ // During GetUpdates, a sync entity update will come back with ONE of:
+ // a) Originator item and cache id - for bookmarks created using old versions
+ // of the browser (latest M93, before https://crrev.com/c/2945119).
+ // b) Server tag - If server committed the item as unique
+ // c) Client tag - If client committed the item as unique
+ //
+ // May be present in CommitMessages for the initial creation of an entity.
+ // If present in Commit updates for the entity, it will be ignored.
+ //
+ // May be returned in GetUpdatesMessage and sent up in CommitMessage.
+ optional string client_tag_hash = 23;
+
+ // Field 23 was previously named client_defined_unique_tag, avoid reuse.
+ reserved "client_defined_unique_tag";
+
+ reserved 24;
+ reserved "ordinal_in_parent";
+
+ // Introduced in M26, represents ordering among entities, in practice used for
+ // bookmarks only. Clients should not assume it is always populated in
+ // GetUpdatesMessage due to the following caveats:
+ // 1. Tombstones and permanent folders do not populate it (ordering is
+ // irrelevant).
+ // 2. It may remain unset by future versions of the client, as long as the
+ // field with the same name is populated inside BookmarkSpecifics. M94 and
+ // above populate both for backward compatibility reasons, but when support
+ // for M93 is retired, modern clients at the time may stop populating this
+ // field.
+ // 3. Very old data (last committed by M25 or below, before the field was
+ // introduced) does not include this field, and in that case the legacy
+ // fields `position_in_parent` or `insert_after_item_id` must be honored
+ // instead.
+ //
+ // May be returned in GetUpdatesMessage and sent up in CommitMessage.
+ optional UniquePosition unique_position = 25;
+
+ // This used to be a list of sync attachment IDs, but it was never launched
+ // and the code has been removed as of M66.
+ reserved 26;
+ reserved "attachment_id";
+
+ // Metadata used for shared data types. Must not be present for regular data
+ // types.
+ // Introduced in M124.
+ message CollaborationMetadata {
+ // Attribution metadata for this whole SyncEntity.
+ message Attribution {
+ // Obfuscated Gaia ID of the user.
+ optional string obfuscated_gaia_id = 1;
+ }
+
+ // Per field attribution metadata (e.g, tab_group_color, tab_group_name.)
+ // Introduced in M141.
+ message PerFieldAttribution {
+ // Name of the attribution that uniquely identifies the changed field
+ // (e.g. tab_group_title). These should have the same values as those
+ // provided through the proto FieldOptions. See
+ // `SharedTabGroupDataSpecifics` for examples.
+ optional string attribution_name = 1;
+
+ // Obfuscated Gaia ID of the user that last modified this.
+ optional string last_update_obfuscated_gaia_id = 2;
+
+ // Last modification time of the specific attribution, in milliseconds
+ // since Unix epoch.
+ optional int64 mtime = 3;
+ }
+
+ // Collaboration ID which the current entity belongs to.
+ optional string collaboration_id = 1;
+
+ // Information about when the specifics was created.
+ optional Attribution creation_attribution = 2;
+
+ // Information about when the specifics was last updated.
+ optional Attribution last_update_attribution = 3;
+
+ repeated PerFieldAttribution per_field_attributions = 4;
+ }
+
+ optional CollaborationMetadata collaboration = 27;
+
+ // Optionally present in CommitMessage for committed deletions (but may remain
+ // unset if the origin is unspecified), it represents which piece of code
+ // triggered a deletion. It is a debug-only field with no compatibility
+ // guarantees, subject to change over time. The main purpose is to help with
+ // investigating and mitigating user reports or incidents that cause data
+ // deletion. Introduced in M126.
+ optional DeletionOrigin deletion_origin = 28;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/sync_enums.proto b/pyhindsight/lib/components/sync/protocol/sync_enums.proto
new file mode 100644
index 0000000..746dcf9
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/sync_enums.proto
@@ -0,0 +1,242 @@
+// 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 enums in this file, update
+// proto_enum_conversions.{h, cc}.
+// If you deprecate enum or enum values, mark any corresponding entry in
+// tools/metrics/histograms/enums.xml as .
+
+syntax = "proto2";
+
+option java_multiple_files = true;
+option java_package = "org.chromium.components.sync.protocol";
+
+option optimize_for = LITE_RUNTIME;
+
+package sync_pb;
+
+message SyncEnums {
+ // These events are sent by the DebugInfo class for singleton events.
+ enum SingletonDebugEventType {
+ // Connection status change. Note this gets generated even during a
+ // successful connection.
+ CONNECTION_STATUS_CHANGE = 1;
+ // Client received an updated token.
+ UPDATED_TOKEN = 2;
+ // Cryptographer needs passphrase.
+ PASSPHRASE_REQUIRED = 3;
+ // Passphrase was accepted by cryptographer.
+ PASSPHRASE_ACCEPTED = 4;
+ // Sync Initialization is complete.
+ INITIALIZATION_COMPLETE = 5;
+ // Server sent stop syncing permanently. This event should never be seen by
+ // the server in the absence of bugs.
+ STOP_SYNCING_PERMANENTLY = 6;
+ // Client has finished encrypting all data.
+ // DEPRECATED_ENCRYPTION_COMPLETE = 7;
+ // Client received an actionable error.
+ ACTIONABLE_ERROR = 8;
+ // Set of encrypted types has changed.
+ ENCRYPTED_TYPES_CHANGED = 9;
+ // The encryption passphrase state changed.
+ PASSPHRASE_TYPE_CHANGED = 10;
+ // A new keystore encryption token was persisted. Deprecated 11/2021.
+ DEPRECATED_KEYSTORE_TOKEN_UPDATED = 11;
+ // The datatype manager has finished an at least partially successful
+ // configuration and is once again syncing with the server.
+ CONFIGURE_COMPLETE = 12;
+ // A new cryptographer bootstrap token was generated.
+ DEPRECATED_BOOTSTRAP_TOKEN_UPDATED = 13;
+ // Cryptographer needs trusted vault decryption keys.
+ TRUSTED_VAULT_KEY_REQUIRED = 14;
+ // Cryptographer no longer needs trusted vault decryption keys.
+ TRUSTED_VAULT_KEY_ACCEPTED = 15;
+ }
+
+ // See ui/base/page_transition_types.h for detailed information on the
+ // values of PageTransition and PageTransitionRedirectType below.
+
+ // Types of transitions between pages.
+ enum PageTransition {
+ LINK = 0;
+ TYPED = 1;
+ AUTO_BOOKMARK = 2;
+ AUTO_SUBFRAME = 3;
+ MANUAL_SUBFRAME = 4;
+ GENERATED = 5;
+ AUTO_TOPLEVEL = 6;
+ FORM_SUBMIT = 7;
+ RELOAD = 8;
+ KEYWORD = 9;
+ KEYWORD_GENERATED = 10;
+ // The below two were mistakenly added but never properly used. They are
+ // actually transition qualifiers, and are set independently of other
+ // qualifiers and of the main transitions. See session_specifics.proto for
+ // the list of synced transition qualifiers.
+ // DEPRECATED_CHAIN_START = 12;
+ // DEPRECATED_CHAIN_END = 13;
+ }
+
+ // Types of redirects that triggered a transition.
+ enum PageTransitionRedirectType {
+ CLIENT_REDIRECT = 1;
+ SERVER_REDIRECT = 2;
+ }
+
+ enum ErrorType {
+ SUCCESS = 0;
+ // DEPRECATED_ACCESS_DENIED = 1;
+ // Returned when the server and client disagree on the store birthday. This
+ // should be interpreted as all local sync metadata requiring cleanup,
+ // obviously including the locally-cached store birthday.
+ NOT_MY_BIRTHDAY = 2;
+ // Returned when the store has exceeded the allowed bandwidth utilization.
+ THROTTLED = 3;
+ // DEPRECATED_AUTH_EXPIRED = 4;
+ // DEPRECATED_USER_NOT_ACTIVATED = 5;
+ // DEPRECATED_AUTH_INVALID = 6;
+ // DEPRECATED_CLEAR_PENDING = 7;
+ // A transient error occurred (e.g. a backend timeout). The client should
+ // try again later.
+ TRANSIENT_ERROR = 8;
+ // A server-side migration has taken place for one or more data types. The
+ // client should clear the cache for these data types only and then re-sync
+ // with a server.
+ MIGRATION_DONE = 9;
+ // An administrator disabled sync for this domain.
+ DISABLED_BY_ADMIN = 10;
+ // Deprecated in M50.
+ // DEPRECATED_USER_ROLLBACK = 11;
+ // Returned when the client wants to update several data types, but some of
+ // them failed (e.g. throttled).
+ PARTIAL_FAILURE = 12;
+ // Returned when the server detects that this client's sync metadata is
+ // obsolete. The client should reset local sync metadata and restart
+ // syncing.
+ CLIENT_DATA_OBSOLETE = 13;
+ // Returned when the server detects that the encryption state (Nigori,
+ // keystore keys) has been reset/overridden, which means the local
+ // Nigori-related state is obsolete and should be cleared.
+ // Introduced in M84.
+ ENCRYPTION_OBSOLETE = 14;
+ // Unknown value. This should never be explicitly used; it is the default
+ // value when an out-of-date client parses a value it doesn't recognize.
+ UNKNOWN = 100;
+ }
+
+ enum Action {
+ UPGRADE_CLIENT = 0; // Upgrade the client to latest version.
+ // DEPRECATED_CLEAR_USER_DATA_AND_RESYNC = 1;
+ // DEPRECATED_ENABLE_SYNC_ON_ACCOUNT = 2;
+ // DEPRECATED_STOP_AND_RESTART_SYNC = 3;
+ // DEPRECATED_DISABLE_SYNC_ON_CLIENT = 4;
+ UNKNOWN_ACTION = 5; // This is the default.
+ }
+
+ // New enums to describe the device type were introduced; OsType and
+ // FormFactor. Deprecated 12/2022.
+ // TODO(crbug.com/40882073): Remove deprecated values from DeviceType enum.
+ enum DeviceType {
+ TYPE_UNSET = 0 [deprecated = true];
+ TYPE_WIN = 1 [deprecated = true];
+ TYPE_MAC = 2 [deprecated = true];
+ TYPE_LINUX = 3 [deprecated = true];
+ TYPE_CROS = 4 [deprecated = true];
+ TYPE_OTHER = 5 [deprecated = true];
+ TYPE_PHONE = 6 [deprecated = true];
+ TYPE_TABLET = 7 [deprecated = true];
+ }
+
+ // Types of device OS.
+ enum OsType {
+ OS_TYPE_UNSPECIFIED = 0;
+ OS_TYPE_WINDOWS = 1;
+ OS_TYPE_MAC = 2;
+ OS_TYPE_LINUX = 3;
+ OS_TYPE_CHROME_OS_ASH = 4;
+ OS_TYPE_ANDROID = 5;
+ OS_TYPE_IOS = 6;
+ OS_TYPE_CHROME_OS_LACROS = 7;
+ OS_TYPE_FUCHSIA = 8;
+ }
+
+ // Types of device form factors.
+ enum DeviceFormFactor {
+ DEVICE_FORM_FACTOR_UNSPECIFIED = 0;
+ DEVICE_FORM_FACTOR_DESKTOP = 1;
+ DEVICE_FORM_FACTOR_PHONE = 2;
+ DEVICE_FORM_FACTOR_TABLET = 3;
+ DEVICE_FORM_FACTOR_AUTOMOTIVE = 4;
+ DEVICE_FORM_FACTOR_WEARABLE = 5;
+ DEVICE_FORM_FACTOR_TV = 6;
+ }
+
+ // Types of browsers; used for history-related data types.
+ enum BrowserType {
+ BROWSER_TYPE_UNKNOWN = 0;
+ TYPE_TABBED = 1; // A normal tabbed window.
+ TYPE_POPUP = 2; // A popup window.
+ TYPE_CUSTOM_TAB = 3; // A custom tab within an app.
+ TYPE_AUTH_TAB = 4; // A auth-dedicated custom tab within an app.
+ }
+
+ // The "password state" is the presence/absence of a password field on a
+ // website; used for history-related data types.
+ enum PasswordState {
+ PASSWORD_STATE_UNKNOWN = 0;
+ NO_PASSWORD_FIELD = 1;
+ HAS_PASSWORD_FIELD = 2;
+ }
+
+ // This is the successor to GetUpdatesSource. It merges the "normal mode"
+ // values (LOCAL, NOTIFICATION and DATATYPE_REFRESH), which were never really
+ // mutually exclusive to being with, into the GU_TRIGGER value. It also
+ // drops support for some old values that are not supported by newer clients.
+ //
+ // Mind the gaps: Some values are intentionally unused because we want to
+ // keep the values in sync with GetUpdatesSource as much as possible. Please
+ // don't add any values < 12 unless there's a good reason for it.
+ //
+ // Introduced in M28.
+ // LINT.IfChange(SyncGetUpdatesOrigin)
+ enum GetUpdatesOrigin {
+ UNKNOWN_ORIGIN = 0; // The source was not set by the caller.
+ PERIODIC = 4; // The source of the update was periodic polling.
+ NEWLY_SUPPORTED_DATATYPE = 7; // The client is in configuration mode
+ // because it's syncing all datatypes, and
+ // support for a new datatype was recently
+ // released via a software auto-update.
+ MIGRATION = 8; // The client is in configuration mode because a
+ // MIGRATION_DONE error previously returned by the
+ // server necessitated resynchronization.
+ NEW_CLIENT = 9; // The client is in configuration mode because the
+ // user enabled sync for the first time. Not to be
+ // confused with FIRST_UPDATE.
+ RECONFIGURATION = 10; // The client is in configuration mode because the
+ // user opted to sync a different set of datatypes.
+ GU_TRIGGER = 12; // The client is in 'normal' mode. It may have several
+ // reasons for requesting an update. See the per-type
+ // GetUpdateTriggers message for more details.
+ // DEPRECATED_RETRY = 13;
+ PROGRAMMATIC = 14; // A GU to programmatically enable/disable a
+ // datatype, often due to error handling.
+
+ reserved 13;
+ reserved "RETRY";
+ }
+ // LINT.ThenChange(/tools/metrics/histograms/metadata/sync/enums.xml:SyncGetUpdatesOrigin)
+
+ // Type of message sent to the receiving device for the send tab to self
+ // feature.
+ enum SendTabReceivingType {
+ // Send tab notification can be received as an in-app message. This is the
+ // default value.
+ SEND_TAB_RECEIVING_TYPE_CHROME_OR_UNSPECIFIED = 0;
+ // Send tab notification can be received as a push notification and/or
+ // in-app message.
+ SEND_TAB_RECEIVING_TYPE_CHROME_AND_PUSH_NOTIFICATION = 1;
+ }
+}
diff --git a/pyhindsight/lib/components/sync/protocol/sync_invalidations_payload.proto b/pyhindsight/lib/components/sync/protocol/sync_invalidations_payload.proto
new file mode 100644
index 0000000..b108dd6
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/sync_invalidations_payload.proto
@@ -0,0 +1,37 @@
+// Copyright 2020 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+// The payload coming from the server for all invalidated data types.
+message SyncInvalidationsPayload {
+ message DataTypeInvalidation {
+ // The legitimate values of this field correspond to the protobuf field
+ // numbers of all EntitySpecifics fields supported by the server (see
+ // components/sync/protocol/sync.proto).
+ optional int32 data_type_id = 1;
+ }
+
+ // This field contains information about each data type which needs to be
+ // updated. Note that it may contain data types which current client is not
+ // interested in.
+ repeated DataTypeInvalidation data_type_invalidations = 1;
+
+ // Opaque field, which has to be provided as part of resulting GetUpdates
+ // back to the server.
+ optional bytes hint = 2;
+
+ // Version of invalidation, used to order incoming invalidations.
+ optional int64 version = 3;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/tab_group_attribution_metadata.proto b/pyhindsight/lib/components/sync/protocol/tab_group_attribution_metadata.proto
new file mode 100644
index 0000000..73966b3
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/tab_group_attribution_metadata.proto
@@ -0,0 +1,42 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+// Stores information about the creation and modification of a tab group or tab.
+message AttributionMetadata {
+ // Details about a single attribution event (creation or modification).
+ message Attribution {
+ // Information about the device where the attribution event occurred.
+ message AttributionDeviceInfo {
+ // The unique identifier for the device in the sync system.
+ optional string cache_guid = 1;
+ }
+
+ // Information about the device.
+ optional AttributionDeviceInfo device_info = 1;
+ }
+
+ // Identifier for device that refers to the device that created the group.
+ // Should only be set on creation, and should not be edited if the value is
+ // missing.
+
+ // Information about when the specifics was created.
+ // The cache guid should only be set on creation and not be edited if the
+ // value is missing.
+ optional Attribution created = 1;
+
+ // Information about when the specifics was last updated.
+ optional Attribution updated = 2;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/test.proto b/pyhindsight/lib/components/sync/protocol/test.proto
new file mode 100644
index 0000000..c416a51
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/test.proto
@@ -0,0 +1,23 @@
+// 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.
+//
+// Protocol messages used only for testing.
+
+syntax = "proto2";
+
+option java_multiple_files = true;
+option java_package = "org.chromium.components.sync.protocol";
+
+option optimize_for = LITE_RUNTIME;
+
+package sync_pb;
+
+message UnknownFieldsTestA {
+ required bool foo = 1;
+}
+
+message UnknownFieldsTestB {
+ required bool foo = 1;
+ required bool bar = 2;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/theme_specifics.proto b/pyhindsight/lib/components/sync/protocol/theme_specifics.proto
new file mode 100644
index 0000000..ff4aa41
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/theme_specifics.proto
@@ -0,0 +1,67 @@
+// 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 datatype extension for themes.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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/theme_types.proto";
+
+// Properties of theme sync objects.
+message ThemeSpecifics {
+ // Set iff a theme extension exists, in which case, all custom_ fields should
+ // be present. This is false for all other theme types (for example,
+ // autogenerated or user color theme). If not set, all custom_* fields
+ // should be omitted.
+ optional bool use_custom_theme = 1;
+
+ // This field is only relevant on platforms that have a distinction between
+ // the system theme and the default theme, but other platforms must be careful
+ // to pass through the value of this flag.
+ //
+ // If true, we use the system theme by default (i.e., when we don't use a
+ // custom theme) for platforms that make a distinction between the default
+ // theme and the system theme. Has no effect if use_custom_theme is true.
+ optional bool use_system_theme_by_default = 2;
+
+ // Extension specific fields. Ignored unless `use_custom_theme` is true.
+ optional string custom_theme_name = 3;
+ optional string custom_theme_id = 4;
+ optional string custom_theme_update_url = 5;
+
+ message AutogeneratedColorTheme {
+ // SkColor used to autogenerate theme.
+ optional uint32 color = 1;
+ }
+
+ message Empty {}
+
+ // The browser-built color theme can be either be autogenerated,
+ // user-selected, or grayscale.
+ oneof color {
+ AutogeneratedColorTheme autogenerated_color_theme = 6;
+ UserColorTheme user_color_theme = 7;
+ Empty grayscale_theme_enabled = 8;
+ }
+
+ enum BrowserColorScheme {
+ BROWSER_COLOR_SCHEME_UNSPECIFIED = 0;
+ SYSTEM = 1;
+ LIGHT = 2;
+ DARK = 3;
+ }
+ optional BrowserColorScheme browser_color_scheme = 9;
+
+ optional NtpCustomBackground ntp_background = 10;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/theme_specifics_ios.proto b/pyhindsight/lib/components/sync/protocol/theme_specifics_ios.proto
new file mode 100644
index 0000000..32f865b
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/theme_specifics_ios.proto
@@ -0,0 +1,26 @@
+// Copyright 2025 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 datatype extension for themes on iOS.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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/theme_types.proto";
+
+// Properties of theme sync objects for iOS themes.
+message ThemeSpecificsIos {
+ optional UserColorTheme user_color_theme = 1;
+
+ optional NtpCustomBackground ntp_background = 2;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/theme_types.proto b/pyhindsight/lib/components/sync/protocol/theme_types.proto
new file mode 100644
index 0000000..0141cd7
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/theme_types.proto
@@ -0,0 +1,50 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Helper sync types for theme syncing.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+message UserColorTheme {
+ enum BrowserColorVariant {
+ BROWSER_COLOR_VARIANT_UNSPECIFIED = 0;
+ SYSTEM = 1;
+ TONAL_SPOT = 2;
+ NEUTRAL = 3;
+ VIBRANT = 4;
+ EXPRESSIVE = 5;
+ }
+ optional uint32 color = 1;
+ optional BrowserColorVariant browser_color_variant = 2;
+}
+
+// Custom NTP background info.
+message NtpCustomBackground {
+ // Background image url.
+ optional string url = 1;
+ // Attribution strings for the image.
+ optional string attribution_line_1 = 2;
+ optional string attribution_line_2 = 3;
+ // Url to learn more info about the image.
+ optional string attribution_action_url = 4;
+ // Id of the collection being used.
+ optional string collection_id = 5;
+ // Token to get the next image from collection and avoid duplicates.
+ optional string resume_token = 6;
+ // Timestamp after which the next image should be fetched from the
+ // collection.
+ optional int64 refresh_timestamp_unix_epoch_seconds = 7;
+ // Main color of the image.
+ optional uint32 main_color = 8;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/typed_url_specifics.proto b/pyhindsight/lib/components/sync/protocol/typed_url_specifics.proto
new file mode 100644
index 0000000..537afbc
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/typed_url_specifics.proto
@@ -0,0 +1,40 @@
+// 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 datatype extension for typed urls.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+// Properties of typed_url sync objects - fields correspond to similarly named
+// fields in history::URLRow.
+message TypedUrlSpecifics {
+ // Actual URL that was typed.
+ optional string url = 1;
+ // Title of the page corresponding to this URL.
+ optional string title = 2;
+ // True if the URL should NOT be used for auto-complete.
+ optional bool hidden = 4;
+ // Timestamps for all visits to this URL.
+ repeated int64 visits = 7 [packed = true];
+ // The PageTransition::Type for each of the visits in the `visit` array. Both
+ // arrays must be the same length.
+ repeated int32 visit_transitions = 8 [packed = true];
+
+ reserved 3;
+ reserved "typed_count";
+ reserved 5;
+ reserved "visit";
+ reserved 6;
+ reserved "visited_count";
+}
diff --git a/pyhindsight/lib/components/sync/protocol/unencrypted_sharing_message.proto b/pyhindsight/lib/components/sync/protocol/unencrypted_sharing_message.proto
new file mode 100644
index 0000000..310eaac
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/unencrypted_sharing_message.proto
@@ -0,0 +1,71 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+
+option java_multiple_files = true;
+option java_package = "org.chromium.components.sync.protocol";
+
+package sync_pb;
+
+// Required in Chrome.
+option optimize_for = LITE_RUNTIME;
+
+// Message for sending between devices in Sharing. Messages defined here should
+// be set to the unencrypted_payload field of SharingMessageSpecifics.
+message UnencryptedSharingMessage {
+ // Identifier of sender.
+ optional string sender_guid = 1;
+
+ // Payload of the message, contains one of the messages below.
+ oneof payload {
+ SendTabToSelfPush send_tab_message = 2;
+ }
+
+ // The name of the device sending this message.
+ optional string sender_device_name = 3;
+}
+
+message SendTabToSelfPush {
+ // Required. Notification title text to display.
+ optional string title = 1;
+
+ // Required. Actual body text to display.
+ optional string text = 2;
+
+ message Image {
+ // Required. URL of this image resource. FIFE hosted URLs are preferred.
+ optional string url = 1;
+
+ // Optional. Alternate text to display if the image cannot be found and for
+ // accessibility reasons.
+ optional string alt_text = 2;
+ }
+
+ // Optional. An icon to be displayed alongside the notification, or a series
+ // of icons to be put in a collage. If no icon is specified, the frontend
+ // will display a generic icon image.
+ repeated Image icon = 3;
+
+ // Optional. A small app icon to display in certain notification views. This
+ // field can be omitted in favor of using a favicon specified in the
+ // chrome_chime client config. If this field is omitted and the client config
+ // favicon is unspecified, no icon is displayed.
+ optional Image favicon = 4;
+
+ // Required. A URL that will be visited when clicking on this notification.
+ optional string destination_url = 5;
+
+ // Placeholder title. Will be used if payload is not properly assembled on
+ // receiving device. Will not get encrypted by Chime.
+ optional string placeholder_title = 6;
+
+ // Placeholder body. Will be used if payload is not properly assembled on
+ // receiving device. Will not get encrypted by Chime.
+ optional string placeholder_body = 7;
+
+ // Unique identifier of the associated SendTabToSelfEntry. Will be used to
+ // dismiss the entry upon push notification interaction.
+ optional string entry_unique_guid = 8;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/unique_position.proto b/pyhindsight/lib/components/sync/protocol/unique_position.proto
new file mode 100644
index 0000000..361cde0
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/unique_position.proto
@@ -0,0 +1,82 @@
+// 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.
+//
+// Protobuf representation of the UniquePosition class.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+// A UniquePosition is a string of bytes.
+//
+// Unique positions are unique per-item, since they are guaranteed to end with a
+// fixed-length suffix that is unique per-item. The position string may not end
+// with a '\0' byte.
+//
+// Prior to the suffix is a series of arbitrary bytes of arbitrary length.
+// Items under the same parent are positioned relative to each other by a
+// lexicographic comparison of their UniquePosition values.
+message UniquePosition {
+ // History:
+ //
+ // Unique positions were first introduced in M28. This change was rolled out
+ // in such a way that it would try to maintain backwards compatibilty with
+ // clients that understood only the old int64-based positions.
+ //
+ // At first, clients supported only the 'value' field. This version never
+ // made it to stable. We later added support for the 'compressed_value'
+ // field, and clients would populate either one or the other.
+ //
+ // In M30, we added the custom_compressed_v1 representation. This
+ // representation was better than the previous implementations in almost every
+ // way. However, we could not use it right away, since older clients would
+ // not understand it. We decided to write both the old-style ('value' or
+ // 'custom_compressed') representation and the 'custom_compressed_v1'
+ // repersentations to every protobuf during the transition period. Protobufs
+ // written during this transition period would be readable by clients who
+ // understand at least one of the two formats.
+ //
+ // In M33, we dropped support for writing the backwards-compatibility fields.
+ // Protobufs written by this version or later are not be intelligible by
+ // clients with version M29 or older. Those clients will end up making use of
+ // the old int64 position fallback mechanism.
+
+ // The uncompressed string of bytes representing the position.
+ //
+ // Deprecated. See history note above.
+ optional bytes value = 1 [deprecated = true];
+
+ // The client may choose to write a compressed position to this field instead
+ // of populating the 'value' above. If it chooses to use compression, the
+ // 'value' field above must be empty. The position value will be compressed
+ // with gzip and stored in the compressed_value field. The position's
+ // uncompressed length must be specified and written to the
+ // uncompressed_length field.
+ //
+ // Deprecated. See history note above.
+ optional bytes compressed_value = 2 [deprecated = true];
+ optional uint64 uncompressed_length = 3 [deprecated = true];
+
+ // This encoding uses compression scheme designed especially for unique
+ // positions. It has the property that X < Y precisely when Compressed(X) <
+ // Compressed(Y), which is very useful when the most common operation is to
+ // compare these positions against each other. Their values may remain
+ // compressed in memory.
+ //
+ // The compression scheme is implemented and documented in
+ // sync/core_impl/base/unique_position.cc.
+ //
+ // As of M30, this is the preferred encoding. Newer clients may continue to
+ // populate the 'value' and 'compressed_value' fields to ensure backwards
+ // compatibility, but they will always try to read from this field first.
+ optional bytes custom_compressed_v1 = 4;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/user_consent_specifics.proto b/pyhindsight/lib/components/sync/protocol/user_consent_specifics.proto
new file mode 100644
index 0000000..91e3c92
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/user_consent_specifics.proto
@@ -0,0 +1,115 @@
+// Copyright 2018 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 datatype extension for user consents.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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/user_consent_types.proto";
+
+// Next id: 18
+message UserConsentSpecifics {
+ // ===========================================================================
+ // Fields common to all Chrome User Consents.
+ // ===========================================================================
+
+ // The UI language Chrome is using, represented as the IETF language tag
+ // defined in BCP 47. The region subtag is not included when it adds no
+ // distinguishing information to the language tag (e.g. both "en-US"
+ // and "fr" are correct here).
+ optional string locale = 4;
+
+ // The local time on the client when the user consent was recorded. The time
+ // as measured by client is given in microseconds since Windows epoch. This
+ // is needed since user consent recording may happen when a client is
+ // offline.
+ optional int64 client_consent_time_usec = 12;
+
+ // ===========================================================================
+ // The specific consent type. Add new User Consent types to
+ // user_consent_types.proto.
+ // ===========================================================================
+
+ oneof consent {
+ UserConsentTypes.SyncConsent sync_consent = 7;
+
+ UserConsentTypes.ArcBackupAndRestoreConsent arc_backup_and_restore_consent =
+ 8;
+
+ UserConsentTypes.ArcGoogleLocationServiceConsent
+ arc_location_service_consent = 9;
+
+ UserConsentTypes.ArcPlayTermsOfServiceConsent
+ arc_play_terms_of_service_consent = 10;
+
+ UserConsentTypes.UnifiedConsent unified_consent = 13 [deprecated = true];
+
+ UserConsentTypes.AssistantActivityControlConsent
+ assistant_activity_control_consent = 14 [deprecated = true];
+
+ UserConsentTypes.AccountPasswordsConsent account_passwords_consent = 15
+ [deprecated = true];
+
+ UserConsentTypes.RecorderSpeakerLabelConsent
+ recorder_speaker_label_consent = 17;
+ }
+ reserved "arc_metrics_and_usage_consent";
+ reserved 11;
+ reserved "autofill_assistant_consent";
+ reserved 16;
+
+ // ===========================================================================
+ // Client only fields.
+ // ===========================================================================
+ // TODO(markusheintz): Refactor the code so that these fields can be moved out
+ // of this message.
+
+ // The obfuscated Gaia ID of the user who gave the consent. This field is used
+ // by UserEventService to distinguish consents from different users,
+ // as UserConsent does not get deleted when a user signs out. However,
+ // it should be cleared before being sent over the wire, as the UserEvent
+ // is sent over an authenticated channel, so this information would be
+ // redundant.
+ //
+ // For semantics and usage of the `obfuscated_gaia_id` in the signin codebase,
+ // see IdentityManager::GetPrimaryAccountInfo() or GaiaId.
+ optional string obfuscated_gaia_id = 6;
+
+ // ===========================================================================
+ // Deprecated fields. Please do not use them!
+ // They have to remain in the proto because the server must continue
+ // supporting legacy consent formats like this.
+ // ===========================================================================
+
+ // Which feature does the consent apply to?
+ enum Feature {
+ FEATURE_UNSPECIFIED = 0;
+ CHROME_SYNC = 1;
+ PLAY_STORE = 2;
+ BACKUP_AND_RESTORE = 3;
+ GOOGLE_LOCATION_SERVICE = 4;
+ CHROME_UNIFIED_CONSENT = 5;
+ // TODO(markusheintz): ASSISTANT_ACTIVITY_CONTROL was only added for
+ // compatibility with the Feature enum in UserEventSpecifics.UserConsent.
+ // Delete this value once the value is deleted from the other proto.
+ ASSISTANT_ACTIVITY_CONTROL = 6;
+ }
+ optional Feature feature = 1 [deprecated = true];
+ // Ids of the strings of the consent text presented to the user.
+ repeated int32 description_grd_ids = 2 [deprecated = true];
+ // Id of the string of the UI element the user clicked when consenting.
+ optional int32 confirmation_grd_id = 3 [deprecated = true];
+ // Was the consent for `feature` given or not given (denied/revoked)?
+ optional UserConsentTypes.ConsentStatus status = 5 [deprecated = true];
+}
diff --git a/pyhindsight/lib/components/sync/protocol/user_consent_types.proto b/pyhindsight/lib/components/sync/protocol/user_consent_types.proto
new file mode 100644
index 0000000..315b2e0
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/user_consent_types.proto
@@ -0,0 +1,188 @@
+// Copyright 2018 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Various user consent types used when reporting consent.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+message UserConsentTypes {
+ // The status of a particular User Consent. The status describes the state
+ // of the consent as it is: given, not_given.
+ enum ConsentStatus {
+ // The status is unspecified e.g. because the user was not asked to
+ // consent yet or an error happened or the decision was delayed.
+ CONSENT_STATUS_UNSPECIFIED = 0;
+ // The consent is not given. This means the user either revoked the
+ // consent or did not grant it in the first place.
+ NOT_GIVEN = 1;
+ // The consent is given. This means the user did grant the consent.
+ GIVEN = 2;
+ }
+
+ // ===========================================================================
+ // Keep sorted alphabetically.
+ // Don't forget to update proto_visitors.h and potentially
+ // proto_enum_conversions.{h, cc}. Never TBR proto changes, because they need
+ // to be manually imported on the Sync server.
+ // ===========================================================================
+
+ // The user consent for the ARC Backup And Restore feature. The consent
+ // status is determined by the corresponding setting on the ARC setup dialog.
+ message ArcBackupAndRestoreConsent {
+ // Ids of the strings of the setting text presented to the user.
+ repeated int32 description_grd_ids = 1;
+
+ // Id of the string of the UI element the user clicked when consenting.
+ optional int32 confirmation_grd_id = 2;
+
+ optional ConsentStatus status = 3;
+ }
+
+ // The user consent for the Google Location Service. The consent status is
+ // determined by the corresponding setting on the ARC setup dialog.
+ message ArcGoogleLocationServiceConsent {
+ // Ids of the strings of the setting text presented to the user.
+ repeated int32 description_grd_ids = 1;
+
+ // Id of the string of the UI element the user clicked when consenting.
+ optional int32 confirmation_grd_id = 2;
+
+ optional ConsentStatus status = 3;
+ }
+
+ // The user consent for the Play terms of service is determined by the user
+ // action on the ARC setup dialog that presents the Play Terms of Service.
+ message ArcPlayTermsOfServiceConsent {
+ // The length of the UTF-8 encoded string of the Play Terms of Service
+ // text. The length is given in number of bytes.
+ optional int32 play_terms_of_service_text_length = 1;
+
+ // The SHA1 hash of UTF-8 encoded string of the Play Terms of Service
+ // displayed to the user.
+ optional bytes play_terms_of_service_hash = 2;
+
+ // GRD Ids of the strings on the consent UI that was shown to the user.
+ repeated int32 description_grd_ids = 5;
+
+ // Id of the string of the UI element the user clicked when consenting.
+ optional int32 confirmation_grd_id = 3;
+
+ // The status of the Play Terms of Service consent. This specifies whether
+ // the consent was given or not given/revoked.
+ optional ConsentStatus status = 4;
+
+ // Enum describing different user flow during which the ARC Play Terms of
+ // service consent can be recorded.
+ enum ConsentFlow {
+ // The ARC setup flow on a CROS device.
+ SETUP = 1;
+ // The user flow for changing the ARC setting on a CROS device.
+ SETTING_CHANGE = 2;
+ }
+ // The user flow during which the consent was recorded. This is necessary in
+ // order to create the correct UI context and Event for the backend.
+ optional ConsentFlow consent_flow = 6;
+ }
+
+ // The User Consent for Chrome Sync is determined by the user action on the
+ // corresponding Sync Consent dialog.
+ message SyncConsent {
+ // Ids of the strings of the sync consent text presented to the user.
+ repeated int32 description_grd_ids = 1;
+
+ // Id of the string of the UI element the user clicked in order to confirm
+ // and close the sync consent dialog.
+ optional int32 confirmation_grd_id = 2;
+
+ // The status of the sync consent. This specifies whether the consent was
+ // given or not given/revoked.
+ optional ConsentStatus status = 3;
+ }
+
+ // The unified User Consent for Chrome is determined by the user action on the
+ // corresponding Chrome Consent dialog.
+ message UnifiedConsent {
+ // Ids of the strings of the unified Chrome consent text presented to the
+ // user.
+ repeated int32 description_grd_ids = 1;
+
+ // Id of the string of the UI element the user clicked in order to confirm
+ // and close the unified Chrome consent dialog.
+ optional int32 confirmation_grd_id = 2;
+
+ // The status of the unified Chrome consent. This specifies whether the
+ // consent was given or not given/revoked.
+ optional ConsentStatus status = 3;
+ }
+
+ // The User Consent for Assistant activity control is determined by the user
+ // action on the Assistant opt-in flow.
+ message AssistantActivityControlConsent {
+ // An opaque token to for ui auditing, which strengthens the audit trail.
+ optional bytes ui_audit_key = 1;
+
+ // The status of the Assistant activity control consent. This specifies
+ // whether the consent was given or not given.
+ optional ConsentStatus status = 2;
+
+ // Enum denoting different Assistant activity control setting type.
+ enum SettingType {
+ // Legacy clients (< M93) did not set a SettingType; for those,
+ // UNSPECIFIED should be interpreted as ALL. Newer clients should always
+ // set it explicitly.
+ SETTING_TYPE_UNSPECIFIED = 0;
+ // All Settings.
+ ALL = 1;
+ WEB_AND_APP_ACTIVITY = 2;
+ DEVICE_APPS = 3;
+ }
+
+ // The activity control setting which the consent was given or not given to.
+ // Clients before M93 did not set this field. Such consents should be
+ // treated as applying to ALL.
+ optional SettingType setting_type = 3;
+ }
+
+ // The User Consent for downloading and using passwords stored in the user's
+ // Google Account. Determined during the opt-in flow for the feature.
+ message AccountPasswordsConsent {
+ // Ids of the strings of the consent text presented to the user.
+ repeated int32 description_grd_ids = 1;
+
+ // Id of the string of the UI element the user clicked in order to confirm
+ // the consent dialog.
+ optional int32 confirmation_grd_id = 2;
+
+ // The status of the consent. This specifies whether the consent was given
+ // or not given/revoked.
+ optional ConsentStatus status = 3;
+ }
+
+ // The User Consent for enabling or disabling speaker label feature in
+ // Recorder app.
+ message RecorderSpeakerLabelConsent {
+ // Ids of the strings of the Recorder speaker label consent text presented
+ // to the user.
+ repeated int32 description_grd_ids = 1;
+
+ // Id of the string of the UI element the user clicked in order to give or
+ // not give the consent and close the Recorder speaker label consent
+ // dialog.
+ optional int32 confirmation_grd_id = 2;
+
+ // The status of the Recorder speaker label consent. This specifies whether
+ // the consent was given or not given/revoked.
+ optional ConsentStatus status = 3;
+ }
+}
diff --git a/pyhindsight/lib/components/sync/protocol/user_event_specifics.proto b/pyhindsight/lib/components/sync/protocol/user_event_specifics.proto
new file mode 100644
index 0000000..8032cb4
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/user_event_specifics.proto
@@ -0,0 +1,140 @@
+// Copyright 2017 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 datatype extension for user events.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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/gaia_password_reuse.proto";
+
+message UserEventSpecifics {
+ // Time of event, as measured by client in microseconds since Windows epoch.
+ optional int64 event_time_usec = 1;
+
+ // The `global_id` field of the associated navigation, if there is one.
+ optional int64 navigation_id = 2;
+
+ // On startup we generate a new random id to identify which FieldTrialEvents
+ // other events belonged to.
+ optional fixed64 session_id = 3;
+
+ // 4-7 reserved for future scalars.
+
+ // Used for testing and debugging EventLog system.
+ message Test {}
+
+ // Language detection output.
+ message LanguageDetection {
+ option deprecated = true;
+
+ message Language {
+ // ISO 639 language code will be used.
+ optional string language_code = 1;
+ // Whether the detected language is reliable, note this is determined by
+ // the CLD3.
+ optional bool is_reliable = 2;
+ }
+ // Top n languages. Typically we just log the top language, but for page
+ // that we're not confident about, we may log up to 3 top languages in
+ // descending order.
+ repeated Language detected_languages = 1;
+ // Adopted language code is the code of final determined language.
+ // It will be stored only if it's different from the first detected
+ // language.
+ optional string adopted_language_code = 2;
+ }
+
+ // User translated a page or interacted with translate suggestion.
+ message Translation {
+ option deprecated = true;
+
+ // Source language of the translation.
+ optional string from_language_code = 1;
+ // Target language of the translation.
+ optional string to_language_code = 2;
+ enum Interaction {
+ UNKNOWN = 0;
+ ACCEPT = 1;
+ DECLINE = 2;
+ // This happens when user scroll or click outside the UI without
+ // translation.
+ IGNORED = 3;
+ // This happens when user choose to close the translation window without
+ // translation.
+ DISMISSED = 4;
+ // User manually entered either language.
+ // In this case, from_language_code and to_language_code will be user
+ // chosen values.
+ MANUAL = 5;
+ // User choose to revert the translation, in this case, from_language_code
+ // and to_language_code will be previous chosen values.
+ TRANSLATION_REVERTED = 6;
+ // Automatically triggered translation.
+ // User sets always translate in user settings.
+ AUTO_TRANSLATION_BY_PREF = 7;
+ // User navigated through a click from a translated page.
+ AUTO_TRANSLATION_BY_LINK = 8;
+ // Failed to initialize the translate script, this can happen for iOS due
+ // to CSPs.
+ INITIALIZATION_ERROR = 9;
+ }
+ optional Interaction interaction = 3;
+ }
+
+ // Logged when the user logs into Google, and at least once per 28d.
+ message GaiaPasswordCaptured {
+ enum EventTrigger {
+ UNSPECIFIED = 0;
+ // Event added because user logged in.
+ USER_LOGGED_IN = 1;
+ // Event added because 28d timer fired.
+ EXPIRED_28D_TIMER = 2;
+ }
+ optional EventTrigger event_trigger = 1;
+ }
+
+ message FlocIdComputed {
+ enum EventTrigger {
+ UNSPECIFIED = 0;
+ // Event added because the floc id is computed for the 1st floc session.
+ NEW = 1;
+ // Event added because the floc id is re-computed due to a long period of
+ // time has passed since the last computation.
+ REFRESHED = 2;
+ // Event added because the floc id is re-computed due to history deletion.
+ HISTORY_DELETE = 3;
+ }
+ reserved 1;
+ reserved "event_trigger";
+
+ // If not set, it means that the floc is disabled.
+ optional uint64 floc_id = 2;
+ }
+
+ oneof event {
+ Test test_event = 8;
+ LanguageDetection language_detection_event = 10 [deprecated = true];
+ Translation translation_event = 11 [deprecated = true];
+ // Happens when a user types their Google account password on another site.
+ GaiaPasswordReuse gaia_password_reuse_event = 104;
+ GaiaPasswordCaptured gaia_password_captured_event = 15;
+ FlocIdComputed floc_id_computed_event = 16;
+ }
+
+ reserved "field_trial_event";
+ reserved 9;
+
+ reserved "user_consent";
+ reserved 12;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/web_apk_specifics.proto b/pyhindsight/lib/components/sync/protocol/web_apk_specifics.proto
new file mode 100644
index 0000000..3537487
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/web_apk_specifics.proto
@@ -0,0 +1,50 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// If you change or add any fields in this file, update
+// components/sync/protocol/proto_visitors.h and potentially
+// components/sync/protocol/proto_enum_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;
+
+// Sync & local data: Information about web app icon.
+message WebApkIconInfo {
+ enum Purpose {
+ UNSPECIFIED = 0;
+ // Suitable for any purpose.
+ ANY = 1;
+ // Designed for masking.
+ MASKABLE = 2;
+ // Suitable for monochrome purposes.
+ MONOCHROME = 3;
+ }
+
+ // The size of the square app icon, in raw pixels.
+ optional int32 size_in_px = 1;
+ // The URL of the app icon.
+ optional string url = 2;
+ // The purpose or context in which the icon should be used.
+ optional Purpose purpose = 3;
+}
+
+// WebApk data.
+message WebApkSpecifics {
+ optional string manifest_id = 1;
+ optional string start_url = 2;
+ optional string name = 3;
+ optional uint32 theme_color = 4;
+ optional string scope = 5;
+ repeated WebApkIconInfo icon_infos = 6;
+
+ // Time when this WebApk was last used or installed.
+ // Number of microseconds since 1601, aka Windows epoch.
+ optional int64 last_used_time_windows_epoch_micros = 7;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/web_app_specifics.proto b/pyhindsight/lib/components/sync/protocol/web_app_specifics.proto
new file mode 100644
index 0000000..211721d
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/web_app_specifics.proto
@@ -0,0 +1,103 @@
+// Copyright 2019 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// If you change or add any fields in this file, update
+// components/sync/protocol/proto_visitors.h and potentially
+// components/sync/protocol/proto_enum_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;
+
+// Sync & local data: Information about web app icon.
+message WebAppIconInfo {
+ enum Purpose {
+ UNSPECIFIED = 0;
+ // Suitable for any purpose.
+ ANY = 1;
+ // Designed for masking.
+ MASKABLE = 2;
+ // Suitable for monochrome purposes.
+ MONOCHROME = 3;
+ }
+
+ // The size of the square app icon, in raw pixels.
+ optional int32 size_in_px = 1;
+ // The URL of the app icon.
+ optional string url = 2;
+ // The purpose or context in which the icon should be used.
+ optional Purpose purpose = 3;
+}
+
+// WebApp data. This is a synced part of
+// chrome/browser/web_applications/proto/web_app.proto data.
+// Note: Pre-M125 clients will incorrectly drop any unrecognized new fields
+// added to the proto. Handling should be added to ApplySyncDataToApp in
+// web_app_sync_bridge.cc if new fields need to be preserved.
+message WebAppSpecifics {
+ // This enum should be a subset of the DisplayMode enum in
+ // chrome/browser/web_applications/proto/web_app.proto and
+ // third_party/blink/public/mojom/manifest/display_mode.mojom
+ enum UserDisplayMode {
+ UNSPECIFIED = 0;
+ BROWSER = 1;
+ // MINIMAL_UI is never serialized.
+ STANDALONE = 3;
+ // FULLSCREEN is never serialized.
+ // WINDOW_CONTROLS_OVERLAY is never serialized.
+ TABBED = 6;
+ // BORDERLESS is never serialized.
+ // PICTURE_IN_PICTURE is never serialized.
+ }
+
+ optional string start_url = 1;
+ optional string name = 2;
+
+ // User-selected display setting, which may be used if no platform-specific
+ // setting is available (eg. on Windows, Mac, and Linux). If absent,
+ // user_display_mode_cros may be used as fallback (if populated). On pre-M122
+ // devices this field is used by all platforms (ie. ChromeOS, Windows, Mac,
+ // Linux) and always replaces any locally-stored value, with
+ // absent/unspecified falling back to standalone.
+ optional UserDisplayMode user_display_mode_default = 3;
+ reserved "user_display_mode_non_cros";
+ reserved "user_display_mode";
+
+ optional uint32 theme_color = 4;
+ optional string scope = 5;
+ repeated WebAppIconInfo icon_infos = 6;
+
+ // Used to store the page number that the app is displayed on in
+ // chrome://apps.
+ optional string user_page_ordinal = 7;
+ // Used to store the in-page ranking for ordering apps in its given
+ // `user_page_ordinal` page.
+ optional string user_launch_ordinal = 8;
+
+ // Used to store id specified in the manifest. This is a path that is relative
+ // to the start_url, similar to how the id field is parsed in
+ // https://www.w3.org/TR/appmanifest/#id-member, except this field does not
+ // include a scheme or origin. This is only the path after the origin,
+ // excluding the first "/".
+ // Note: If this field is not set, then the manifest_id is generated using the
+ // start_url in GenerateManifestIdFromStartUrlOnly. This is different than if
+ // this is set to "", which means the manifest_id will be set to the origin of
+ // the start_url.
+ optional string relative_manifest_id = 9;
+
+ // User-selected display setting for ChromeOS.
+ // If absent, user_display_mode_default may be used as fallback (if
+ // populated).
+ // Introduced in M122.
+ optional UserDisplayMode user_display_mode_cros = 10;
+
+ // Contains the metadata for the trusted icons to be shown on security
+ // sensitive surfaces by the web app.
+ repeated WebAppIconInfo trusted_icons = 11;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/webauthn_credential_specifics.proto b/pyhindsight/lib/components/sync/protocol/webauthn_credential_specifics.proto
new file mode 100644
index 0000000..24ae1ab
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/webauthn_credential_specifics.proto
@@ -0,0 +1,199 @@
+// Copyright 2021 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+// WebauthnCredentialSpecifics is an entity that backs a WebAuthn
+// PublicKeyCredential. Since it contains the authenticator’s view of this
+// object, it has a private key rather than a public key.
+// (https://www.w3.org/TR/webauthn-2/#iface-pkcredential).
+//
+// Names of fields are taken from WebAuthn where possible. E.g.
+// user.displayName in WebAuthn becomes user_display_name here.
+//
+// All fields are immutable after creation except for user_name and
+// user_display_name, which may be updated by a user.
+message WebauthnCredentialSpecifics {
+ // Sync's ID for this entity (sometimes called the client unique tag), 16
+ // random bytes. This value is used within Sync to identify this entity. The
+ // credential ID is not used because the (hashed) sync_id is exposed to the
+ // Sync server, and we don’t want Google to be able to map a credential ID to
+ // an account. Password entities construct this value from the concatenation
+ // of many fields and depend on the fact that the server only sees a hash of
+ // it. But the only high-entropy secret here is the private key, which will
+ // have different encryption in the future, and private keys are not the sort
+ // of data to copy into other fields. Therefore this independent value is
+ // provided to form the client's ID.
+ optional bytes sync_id = 1;
+
+ // The credential ID, 16 random bytes. This is a value surfaced in
+ // the WebAuthn API (https://www.w3.org/TR/webauthn-2/#credential-id).
+ optional bytes credential_id = 2;
+
+ // An RP ID is a WebAuthn concept:
+ // https://www.w3.org/TR/webauthn-2/#rp-id. It’s usually a domain name,
+ // although in non-Web contexts it can be a URL with a non-Web scheme.
+ optional string rp_id = 3;
+
+ // The user ID, which is also called a “user handle” in WebAuthn
+ // (https://www.w3.org/TR/webauthn-2/#user-handle), is an RP-specific
+ // identifier that is up to 64-bytes long. An authenticator conceptually only
+ // stores a single credential for a given (rp_id, user_id) pair, but there
+ // may be several credentials in Sync. They are prioritised using
+ // newly_shadowed_credential_ids and creation_time. See below.
+ //
+ // (We wish to be able to retain several entities for a single (rp_id,
+ // user_id) pair because there’s an edge case where we may wish to revert to
+ // an older entry and thus need to keep the older entry around in Sync. The
+ // revert could happen on a different device too.)
+ optional bytes user_id = 4;
+
+ // The id of credentials with the same (rp_id, user_id) that were
+ // shadowed by the creation of this entity.
+ //
+ // A credential is shadowed if one or more other credentials (from the same
+ // account, and with the same (rp_id, user_id)) include its credential_id in
+ // their list of shadowed IDs. Shadowed credentials are ignored when finding
+ // a credential to sign with. If there is more than one candidate remaining
+ // after filtering shadowed credentials then the most recently created (based
+ // on creation_time) is used.
+ //
+ // The reason for all this is that sites can replace a credential by creating
+ // another one with the same (rp_id, user_id) pair. However, we don't
+ // immediately know whether the WebAuthn response reached the website's
+ // server. Consider a user with a poor internet connection. Javascript in the
+ // site's origin triggers a credential creation that “overwrites” an existing
+ // credential, but the Javascript is unable to send the new public key to the
+ // website's server. The user is now locked out: the old credential has been
+ // over-written but the website's server doesn't know about the new one.
+ //
+ // Thus we wish to keep “overwritten” credentials around for a while to allow
+ // for some sort of recovery. In the simple case, a new credential shadows
+ // the single, previous old credential. We could depend on creation_time, but
+ // client clocks aren't always accurate, thus this field.
+ //
+ // In complicated cases two devices might race to replace a credential, in
+ // which case (after mutual syncing) two candidate credentials exist for the
+ // same (rp_id, user_id) pair because neither shadows the other. In this case
+ // we pick the newest based on `creation_time` but it's quite possible that
+ // some recovery will be needed because the website's server thinks the other
+ // one is correct.
+ //
+ // A generation counter isn't used because a single device might replace a
+ // series of credentials as it tries to update the website's server. But that
+ // doesn't mean that it should dominate a different device that replaced it
+ // only once, but later.
+ repeated bytes newly_shadowed_credential_ids = 5;
+
+ // The local time on the device when this credential was created. Given in
+ // milliseconds since the UNIX epoch. This is used to break ties between
+ // credentials. See newly_shadowed_credential_ids.
+ optional int64 creation_time = 6;
+
+ // The human-readable account identifier. Usually an email address. This is
+ // mutable.
+ // https://www.w3.org/TR/webauthn-2/#dom-publickeycredentialentity-name
+ optional string user_name = 7;
+
+ // The human-readable name. Usually a legal name. This is mutable.
+ // https://www.w3.org/TR/webauthn-2/#dom-publickeycredentialuserentity-displayname.
+ optional string user_display_name = 8;
+
+ // Reserving obsolete field.
+ reserved 10;
+
+ // Credentials may optionally be enabled for Secure Payment Confirmation[1] on
+ // third-party sites. This is opt-in at creation time.
+ //
+ // [1] https://www.w3.org/TR/secure-payment-confirmation/
+ optional bool third_party_payments_support = 11;
+
+ // Time when this passkey was last successfully asserted. Number of
+ // microseconds since 1601, aka Windows epoch. This mirrors the
+ // `date_last_used` field in PasswordSpecificsData.
+ optional int64 last_used_time_windows_epoch_micros = 13;
+
+ message Encrypted {
+ // The bytes of the private key, in PKCS#8 format.
+ optional bytes private_key = 1;
+
+ // The secret for implementing the hmac-secret extension
+ // https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-errata-20220621.html#sctn-hmac-secret-extension
+ optional bytes hmac_secret = 2;
+
+ // The contents of the credential's credBlob.
+ // https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-errata-20220621.html#sctn-credBlob-extension
+ optional bytes cred_blob = 3;
+
+ // The contents of the credential's largeBlob value(*). Unlike with security
+ // keys, largeBlob data is not stored in a single lump for all credentials,
+ // but as per-credential data. This data is presented to the authenticator
+ // over CTAP and thus has already had the required DEFLATE compression
+ // applied by the remote platform. The uncompressed size of this data is in
+ // the next field.
+ //
+ // (*) "large" with respect to embedded devices. Maximum length is 2KiB for
+ // Google Password Manager.
+ //
+ // https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-errata-20220621.html#authenticatorLargeBlobs
+ optional bytes large_blob = 4;
+
+ // The claimed uncompressed size of the DEFLATE-compressed data in
+ // `large_blob`. This corresponds to the `origSize` field from the spec:
+ // https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-errata-20220621.html#large-blob
+ optional uint64 large_blob_uncompressed_size = 5;
+ }
+
+ message SecurityDomainEncrypted {
+ // A serialized `Encrypted` message, encrypted with the device authorization
+ // key (see `device_authorization_key_version` for the key version).
+ optional bytes device_authorization_encrypted = 1;
+ }
+
+ // The "version" (sometimes called the epoch) of the key that `encrypted_data`
+ // is encrypted with. This allows trial decryption to be avoided when present.
+ optional int32 key_version = 14;
+
+ // The key version of the device authorization key that
+ // `device_authorization_encrypted` in `SecurityDomainEncrypted` is encrypted
+ // with.
+ optional int32 device_authorization_key_version = 18;
+
+ oneof encrypted_data {
+ // The bytes of the private key, encrypted with a feature-specific security
+ // domain.
+ bytes private_key = 9;
+
+ // A serialized, `Encrypted` message, encrypted with a feature-specific
+ // security domain.
+ bytes encrypted = 12;
+
+ // A serialized `SecurityDomainEncrypted` message, encrypted with a
+ // feature-specific security domain key.
+ bytes security_domain_encrypted = 19;
+ }
+
+ // `edited_by_user` is set to `true` the first time a user manually changes
+ // the credential's `user_name` or `user_display_name`.
+ optional bool edited_by_user = 15;
+
+ // `hidden` is set to `true` if the credential should not be shown on
+ // authentication surfaces, e.g. because a site marked it as obsolete.
+ optional bool hidden = 16;
+
+ // The local time on the device when this credential was hidden. Given in
+ // milliseconds since the UNIX epoch. This is used to permanently delete
+ // credentials after they've been hidden for a while.
+ optional int64 hidden_time = 17;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/wifi_configuration_specifics.proto b/pyhindsight/lib/components/sync/protocol/wifi_configuration_specifics.proto
new file mode 100644
index 0000000..911d7c1
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/wifi_configuration_specifics.proto
@@ -0,0 +1,92 @@
+// Copyright 2019 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 datatype extension for Wi-Fi configuration items.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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;
+
+message WifiConfigurationSpecifics {
+ // SSID encoded to hex, letters should be upper case and 0x prefix should be
+ // omitted. For example, ssid "network" would be provided as "6E6574776F726B".
+ optional bytes hex_ssid = 1;
+ enum SecurityType {
+ SECURITY_TYPE_UNSPECIFIED = 0;
+ SECURITY_TYPE_NONE = 1;
+ SECURITY_TYPE_WEP = 2;
+ SECURITY_TYPE_PSK = 3; // WPA-PSK or RSN-PSK
+ }
+ optional SecurityType security_type = 2;
+ // The passphrase can be ASCII, UTF-8, or a string of hex digits.
+ optional bytes passphrase = 3;
+ enum AutomaticallyConnectOption {
+ AUTOMATICALLY_CONNECT_UNSPECIFIED = 0;
+ AUTOMATICALLY_CONNECT_DISABLED = 1;
+ AUTOMATICALLY_CONNECT_ENABLED = 2;
+ }
+ optional AutomaticallyConnectOption automatically_connect = 4;
+ enum IsPreferredOption {
+ IS_PREFERRED_UNSPECIFIED = 0;
+ IS_PREFERRED_DISABLED = 1;
+ IS_PREFERRED_ENABLED = 2;
+ }
+ optional IsPreferredOption is_preferred = 5;
+ enum MeteredOption {
+ METERED_OPTION_UNSPECIFIED = 0;
+ METERED_OPTION_NO = 1;
+ METERED_OPTION_YES = 2;
+ // Allows the device to use heuristics to determine if network is metered.
+ METERED_OPTION_AUTO = 3;
+ }
+ optional MeteredOption metered = 6;
+ message ProxyConfiguration {
+ enum ProxyOption {
+ PROXY_OPTION_UNSPECIFIED = 0;
+ PROXY_OPTION_DISABLED = 1;
+ // Use a Proxy Auto-config(PAC) Url, set in proxy_url
+ PROXY_OPTION_AUTOMATIC = 2;
+ // Uses Web Proxy Auto-Discovery Protocol (WPAD) to discover the proxy
+ // settings using DHCP/DNS.
+ PROXY_OPTION_AUTODISCOVERY = 3;
+ // User sets details in manual_proxy_configuration.
+ PROXY_OPTION_MANUAL = 4;
+ }
+ optional ProxyOption proxy_option = 1;
+ // Only set if PROXY_OPTION_AUTOMATIC.
+ optional string autoconfiguration_url = 2;
+ message ManualProxyConfiguration {
+ optional string http_proxy_url = 1;
+ optional int32 http_proxy_port = 2;
+ optional string secure_http_proxy_url = 3;
+ optional int32 secure_http_proxy_port = 4;
+ optional string socks_host_url = 5;
+ optional int32 socks_host_port = 6;
+ repeated string excluded_domains = 7;
+ }
+ // Only set if PROXY_OPTION_MANUAL.
+ optional ManualProxyConfiguration manual_proxy_configuration = 3;
+ }
+ optional ProxyConfiguration proxy_configuration = 7;
+ enum DnsOption {
+ DNS_OPTION_UNSPECIFIED = 0;
+ DNS_OPTION_DEFAULT_DHCP = 1;
+ DNS_OPTION_CUSTOM = 2;
+ }
+ optional DnsOption dns_option = 10;
+ // List of DNS servers to be used when set to DNS_OPTION_CUSTOM. Up to 4.
+ repeated string custom_dns = 8;
+ // The last time this configuration was connected to before being synced. It
+ // will only be updated when the configuration is changed. This is represented
+ // with the UNIX timestamp, ms since epoch.
+ optional int64 last_connected_timestamp = 9;
+}
diff --git a/pyhindsight/lib/components/sync/protocol/workspace_desk_specifics.proto b/pyhindsight/lib/components/sync/protocol/workspace_desk_specifics.proto
new file mode 100644
index 0000000..4f7cd39
--- /dev/null
+++ b/pyhindsight/lib/components/sync/protocol/workspace_desk_specifics.proto
@@ -0,0 +1,309 @@
+// Copyright 2021 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 datatype extension for desks on Chrome OS.
+
+// If you change or add any fields in this file, update proto_visitors.h and
+// potentially proto_enum_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/sync_enums.proto";
+
+// A workspace desk entry. This proto contains the fields synced to represent
+// a saved desk in user's workspace.
+message WorkspaceDeskSpecifics {
+ reserved "created_time_usec";
+
+ // A random unique identifier for each desk.
+ // Required.
+ optional string uuid = 1;
+ // The name of the desk being saved.
+ optional string name = 2;
+ // The time this snapshot of desk was created.
+ optional int64 created_time_windows_epoch_micros = 3;
+
+ // The time this snapshot of desk was updated.
+ optional int64 updated_time_windows_epoch_micros = 5;
+
+ optional Desk desk = 4;
+
+ // The type of a desk.
+ optional DeskType desk_type = 6;
+
+ // The cache guid of the syncing client. Used to identify a unique device
+ // that's syncing data.
+ optional string client_cache_guid = 7;
+
+ // The form factor of the device.
+ optional SyncEnums.DeviceFormFactor device_form_factor = 8;
+
+ // The list of Coral tab and app entities.
+ optional CoralTabAppEntities coral_tab_app_entities = 9;
+
+ // Represent a snapshot of the information on a desk.
+ message Desk {
+ // The apps in this template.
+ repeated App apps = 1;
+ }
+
+ // A Launchable app in template.
+ message App {
+ // The on-display location of this window.
+ optional WindowBound window_bound = 1;
+ optional WindowState window_state = 2;
+ // The z-index of this app relative to other apps in this template.
+ // App with larger z-index appears in front of app with smaller z-index.
+ optional int32 z_index = 3;
+
+ optional AppOneOf app = 4;
+
+ // window_id used to instantiate proto as a restore_data object. The
+ // restore_data object in question can be found at:
+ // //components/app_restore/restore_data.h
+ optional int32 window_id = 5;
+
+ // Display ID this app is on.
+ optional int64 display_id = 6;
+
+ // State of a window before it was minimized. Empty/unset for non-minimized
+ // windows.
+ optional WindowState pre_minimized_window_state = 7;
+
+ // Container this app was launched from. Empty/unset for Arc apps.
+ optional LaunchContainer container = 8;
+
+ // Window open disposition, defines how a window opens. Empty/unset for Arc
+ // apps.
+ optional WindowOpenDisposition disposition = 9;
+
+ // Name of the app which is used by the browser to determine whether to
+ // launch an app as an app or a tab. Does not contain a human readable name
+ // but contains the app ID and a prefix.
+ optional string app_name = 10;
+
+ // Human readable title of the app.
+ optional string title = 11;
+
+ // This is used to determine the size of a snapped window is in clamshell
+ // mode. Empty/unset for non-snapped windows. This should be a value between
+ // 0 and 100.
+ optional int32 snap_percentage = 12;
+
+ // The override URL can be specified by apps to override the default URL at
+ // launch.
+ optional string override_url = 13;
+ }
+
+ message AppOneOf {
+ oneof app {
+ BrowserAppWindow browser_app_window = 1;
+ ChromeApp chrome_app = 2;
+ ProgressiveWebApp progress_web_app = 3;
+ ArcApp arc_app = 4;
+ }
+ }
+
+ // A Chrome or Lacros Browser app window.
+ message BrowserAppWindow {
+ message BrowserAppTab {
+ // The last committed URL of the main frame of the tab.
+ optional string url = 1;
+ // The title of the tab.
+ optional string title = 2;
+ }
+
+ // Structure representing a tab group associated with this window.
+ message TabGroup {
+ // Zero-based index within the browser app tabs of the first tab in the
+ // group.
+ optional int32 first_index = 1;
+
+ // Zero-based Index wotjom the browser app tabs of the last tab in the
+ // group.
+ optional int32 last_index = 2;
+
+ // User readable title of the tab group.
+ optional string title = 3;
+
+ // Color associated with this tab group.
+ optional TabGroupColor color = 4;
+
+ // Indicates whether the tab group is collapsed.
+ optional bool is_collapsed = 5;
+ }
+
+ // The tabs in this browser window.
+ repeated BrowserAppTab tabs = 1;
+
+ // The index of the currently active tab.
+ optional int32 active_tab_index = 2;
+
+ // Indicates whether to show as a dedicated app window.
+ optional bool show_as_app = 3;
+
+ // Tab groups associated with this window.
+ repeated TabGroup tab_groups = 4;
+
+ // The index of the first non-pinned tab.
+ optional int32 first_non_pinned_tab_index = 5;
+ }
+
+ // A Chrome App window.
+ message ChromeApp {
+ // The Chrome App's App ID.
+ optional string app_id = 1;
+
+ reserved 2;
+ }
+
+ // A PWA window.
+ message ProgressiveWebApp {
+ // The PWA's App ID.
+ optional string app_id = 1;
+
+ reserved 2;
+ }
+
+ // An Arc App window.
+ message ArcApp {
+ // The Arc App's ID.
+ optional string app_id = 1;
+
+ // Arc window information. This maps
+ // to ArcExtraInfo in a WindowInfo struct.
+ optional WindowSize minimum_size = 2;
+ optional WindowSize maximum_size = 3;
+
+ reserved 4;
+
+ optional WindowBound bounds_in_root = 5;
+
+ // maps to gfx::Size. Width of the window, including the frame,
+ // in pixels.
+ message WindowSize {
+ optional int32 width = 1;
+ optional int32 height = 2;
+ }
+ }
+
+ message WindowBound {
+ // The offset of the window from the top edge of the screen in pixels.
+ optional int32 top = 1;
+ // The offset of the window from the left edge of the screen in pixels.
+ optional int32 left = 2;
+ // The width of the window, including the frame, in pixels.
+ optional int32 width = 3;
+ // The height of the window, including the frame, in pixels.
+ optional int32 height = 4;
+ }
+
+ // Enumeration for the container an app was launched from as used by
+ // (components/services/app_services/public/mojom/types.mojom:490).
+ enum LaunchContainer {
+ LAUNCH_CONTAINER_UNSPECIFIED = 0;
+ LAUNCH_CONTAINER_WINDOW = 1;
+ LAUNCH_CONTAINER_PANEL_DEPRECATED = 2;
+ LAUNCH_CONTAINER_TAB = 3;
+ LAUNCH_CONTAINER_NONE = 4;
+ }
+
+ // The state of a generic window.
+ enum WindowState {
+ UNKNOWN_WINDOW_STATE = 0;
+ // Normal window state (not minimized, maximized, or fullscreen).
+ NORMAL = 1;
+ // Minimized window state.
+ MINIMIZED = 2;
+ // Maximized window state.
+ MAXIMIZED = 3;
+ // Fullscreen window state.
+ FULLSCREEN = 4;
+ // Snapped to primary half of the screen. Primary half is on the left in
+ // landscape screen orientation and top in portrait screen orientation.
+ PRIMARY_SNAPPED = 5;
+ // Snapped to secondary half of the screen. Secondary half is on the right
+ // in landscape screen orientation and bottom in portrait screen
+ // orientation.
+ SECONDARY_SNAPPED = 6;
+ // Floated window state.
+ FLOATED = 7;
+ }
+
+ // Enumeration for how a window opens. Maps to base::WindowOpenDisposition.
+ // (found in ui/base/window_open_disposition.h:10). Does not include
+ // MAX_VALUE as MAX_VALUE is equivalent to NEW_PICTURE_IN_PICTURE. All
+ // comments are copied verbatim from aforementioned header.
+ enum WindowOpenDisposition {
+ UNKNOWN = 0;
+ CURRENT_TAB = 1;
+ // Indicates that only one tab with the URL shoul exist in the same window.
+ SINGLETON_TAB = 2;
+ NEW_FOREGROUND_TAB = 3;
+ NEW_BACKGROUND_TAB = 4;
+ NEW_POPUP = 5;
+ NEW_WINDOW = 6;
+ SAVE_TO_DISK = 7;
+ OFF_THE_RECORD = 8;
+ IGNORE_ACTION = 9;
+ // Activates an existing tab containing the URL, rather than navigating.
+ // This is similar to SINGLETON_TAB, but searches across all windows
+ // from the current profile and anymity (instead of tjust the current one);
+ // closes the current tab on switching if the current ta was the NTP with
+ // no session history; and behaves like CURRENT_TAB instead of
+ // NEW_FOREGROUND_TAB when no existing tab is found.
+ SWITCH_TO_TAB = 10;
+ // creates a new document picture-in-picture window showing a child WebView.
+ NEW_PICTURE_IN_PICTURE = 11;
+ }
+
+ // Enumerates the type of desk, namely to differentiate desks between desks
+ // saved for desk templates and desks saved for save and recall.
+ enum DeskType {
+ UNKNOWN_TYPE = 0;
+ TEMPLATE = 1;
+ SAVE_AND_RECALL = 2;
+ FLOATING_WORKSPACE = 3;
+ }
+
+ // Enumerates the possible colors that a tab group can have. This mirrors
+ // the enumeration that can be found in
+ // components/tab_groups/tab_group_color.h
+ enum TabGroupColor {
+ UNKNOWN_COLOR = 0;
+ GREY = 1;
+ BLUE = 2;
+ RED = 3;
+ YELLOW = 4;
+ GREEN = 5;
+ PINK = 6;
+ PURPLE = 7;
+ CYAN = 8;
+ ORANGE = 9;
+ }
+
+ // The tab and app entities used by Coral to avoid suggesting groups with a
+ // similar topic.
+ message CoralTabAppEntities {
+ repeated CoralTabEntity tab_entities = 1;
+ repeated CoralAppEntity app_entities = 2;
+ }
+
+ message CoralTabEntity {
+ optional string tab_title = 1;
+ optional string tab_url = 2;
+ }
+
+ message CoralAppEntity {
+ optional string app_name = 1;
+ optional string app_id = 2;
+ }
+}
diff --git a/pyhindsight/lib/content/browser/background_fetch/background_fetch.proto b/pyhindsight/lib/content/browser/background_fetch/background_fetch.proto
new file mode 100644
index 0000000..9baf94a
--- /dev/null
+++ b/pyhindsight/lib/content/browser/background_fetch/background_fetch.proto
@@ -0,0 +1,190 @@
+// Copyright 2017 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package content.proto;
+
+// Stores per-registration (as opposed to per-request) data.
+// https://wicg.github.io/background-fetch/#background-fetch-registration
+//
+// Next Tag: 9
+message BackgroundFetchRegistration {
+ enum BackgroundFetchResult {
+ UNSET = 0; // Default value.
+ FAILURE = 1;
+ SUCCESS = 2;
+ }
+
+ // This should be kept in sync with blink.mojom.BackgroundFetchFailureReason.
+ enum BackgroundFetchFailureReason {
+ NONE = 0; // Default value.
+ CANCELLED_FROM_UI = 1;
+ CANCELLED_BY_DEVELOPER = 2;
+ BAD_STATUS = 3;
+ FETCH_ERROR = 4;
+ SERVICE_WORKER_UNAVAILABLE = 5;
+ QUOTA_EXCEEDED = 6;
+ DOWNLOAD_TOTAL_EXCEEDED = 7;
+ }
+
+ // See definition of |unique_id| in BackgroundFetchRegistrationId.
+ optional string unique_id = 1;
+
+ // See definition of |developer_id| in BackgroundFetchRegistrationId.
+ optional bytes developer_id = 2;
+
+ optional uint64 upload_total = 3;
+ optional uint64 uploaded = 4;
+ optional uint64 download_total = 5;
+ optional uint64 downloaded = 6;
+ optional BackgroundFetchResult result = 7;
+ optional BackgroundFetchFailureReason failure_reason = 8;
+}
+
+// TODO(crbug.com/40245169): Move ImageResource to generic place.
+// Currently also being used within chrome/browser/web_applications
+// https://w3c.github.io/manifest/#dom-imageresource
+//
+// Next Tag: 5
+message ImageResource {
+ optional string src = 1;
+
+ // Next Tag: 3
+ message Size {
+ optional int32 width = 1;
+ optional int32 height = 2;
+ }
+
+ repeated Size sizes = 2;
+ optional bytes type = 3;
+
+ // https://w3c.github.io/manifest/#purpose-member
+ enum Purpose {
+ ANY = 1;
+ MONOCHROME = 2;
+ MASKABLE = 3;
+ }
+
+ // blink::mojom::ManifestImageResource_Purpose enum.
+ repeated Purpose purpose = 4;
+}
+
+// Developer provided options.
+// https://wicg.github.io/background-fetch/#background-fetch-manager
+//
+// Next Tag: 3
+message BackgroundFetchOptions {
+ // The initial title provided by the developer. This can be updated,
+ // and the most recent value is stored in BackgroundFetchUIOptions.
+ optional string title = 1;
+
+ repeated ImageResource icons = 2;
+
+ optional uint64 download_total = 3;
+}
+
+// Keeps track of the version of the persisted data. If a breaking change
+// needs to be made, increment `CURRENT`, and replace it with a descriptive
+// name of the change. Don't directly check against `SV_CURRENT` as it can be
+// changed.
+// For example, if you want to enable a new key format for the SWDB, perform
+// the following steps:
+// 1. Add a new enum value (SV_ENABLE_NEW_KEY_FORMAT) and increment
+// `SV_CURRENT`
+// 2. Migrate the old formats on database load (DatabaseMigrationTask).
+// 3. Add a TODO with a bug to clean this up after 2 milestones or so.
+//
+// Next Value: 3
+enum BackgroundFetchStorageVersion {
+ // There was an error when trying to get the storage version.
+ SV_ERROR = -1;
+ // No storage version was found.
+ SV_UNINITIALIZED = 0;
+
+ // Migrate registered fetches to use the new Cache URL key format, to make
+ // them unique, and allow for duplicate requests in a registration.
+ SV_UNIQUE_CACHE_KEYS = 1;
+
+ // Add new versions here.
+
+ // Must be last.
+ SV_CURRENT = 2;
+}
+
+// Stores information about the background fetch that will be persisted
+// to disk. This information should be everything needed to reconstruct
+// the state of an interrupted background fetch.
+//
+// Next Tag: 8
+message BackgroundFetchMetadata {
+ optional int64 creation_microseconds_since_unix_epoch = 1;
+ optional string origin = 2 [deprecated = true];
+
+ optional BackgroundFetchRegistration registration = 3;
+ optional BackgroundFetchOptions options = 4;
+
+ // Number of fetches initiated by the developer.
+ optional int32 num_fetches = 5;
+
+ // Serialized net::IsolationInfo associated with the Background Fetch.
+ optional string isolation_info = 6;
+
+ // Serialized storage key; this replaces origin
+ optional string storage_key = 7;
+}
+
+// All the updateable options that show up in the UI (e.g. notification).
+//
+// Next Tag: 3
+message BackgroundFetchUIOptions {
+ optional string title = 1;
+
+ // Raw bytes needed to deserialize into a PNG icon. Only used if the icon
+ // has a max resolution of 256x256. This means this is at most ~256KB.
+ optional bytes icon = 2;
+}
+
+// A background fetch request that is still in a pending state.
+//
+// Next Tag: 6
+message BackgroundFetchPendingRequest {
+ optional string unique_id = 1;
+ optional int32 request_index = 2;
+ optional string serialized_request = 3;
+ optional uint64 request_body_size = 5;
+
+ reserved 4;
+}
+
+// A background fetch request in the active state. This means that
+// the DownloadManager started downloading the file.
+//
+// Next Tag: 7
+message BackgroundFetchActiveRequest {
+ optional string unique_id = 1;
+ optional int32 request_index = 2;
+ optional string serialized_request = 3;
+ optional string download_guid = 4;
+ optional uint64 request_body_size = 6;
+
+ reserved 5;
+}
+
+// A background fetch request in the completed state. This means that
+// the DownloadManager returned the download.
+//
+// Next Tag: 7
+message BackgroundFetchCompletedRequest {
+ optional string unique_id = 1;
+ optional int32 request_index = 2;
+ optional string serialized_request = 3;
+ optional string download_guid = 4;
+ optional BackgroundFetchRegistration.BackgroundFetchFailureReason
+ failure_reason = 6;
+
+ reserved 5;
+}
diff --git a/pyhindsight/lib/content/browser/background_sync/background_sync.proto b/pyhindsight/lib/content/browser/background_sync/background_sync.proto
new file mode 100644
index 0000000..ec61e02
--- /dev/null
+++ b/pyhindsight/lib/content/browser/background_sync/background_sync.proto
@@ -0,0 +1,38 @@
+// Copyright 2015 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package content;
+
+enum SyncNetworkState {
+ NETWORK_STATE_ANY = 0;
+ NETWORK_STATE_AVOID_CELLULAR = 1;
+ NETWORK_STATE_ONLINE = 2;
+}
+
+message PeriodicSyncOptions {
+ optional int64 min_interval = 1;
+}
+
+message BackgroundSyncRegistrationProto {
+ // required int64 id = 1;
+ required string tag = 2;
+ // required SyncPeriodicity periodicity = 3;
+ // required int64 min_period = 4;
+ // required SyncNetworkState network_state = 5;
+ // required SyncPowerState power_state = 6;
+ required int32 num_attempts = 7;
+ required int64 delay_until = 8;
+ optional PeriodicSyncOptions periodic_sync_options = 9;
+ optional int32 max_attempts = 10;
+}
+
+message BackgroundSyncRegistrationsProto {
+ repeated BackgroundSyncRegistrationProto registration = 1;
+ // required int64 next_registration_id = 2;
+ required string origin = 3;
+}
\ No newline at end of file
diff --git a/pyhindsight/lib/content/browser/cache_storage/cache_storage.proto b/pyhindsight/lib/content/browser/cache_storage/cache_storage.proto
new file mode 100644
index 0000000..534a534
--- /dev/null
+++ b/pyhindsight/lib/content/browser/cache_storage/cache_storage.proto
@@ -0,0 +1,89 @@
+// Copyright 2014 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package content.proto;
+
+message CacheStorageIndex {
+ // The Cache message represents stored caches, where cache names are
+ // preserved as UTF16 strings to align with WebIDL DOMStrings. This ensures
+ // compatibility with names that may contain invalid characters. While the
+ // `name` field remains for backward compatibility, all new caches will use
+ // `u16string_name` going forward. Older clients that read index files written
+ // with UTF8 cache names will not break due to this approach.
+ message Cache {
+ // Maintained for backward compatibility, but no longer used for new caches.
+ required string name = 1;
+ optional string cache_dir = 2;
+ optional int64 size = 3;
+ optional string padding_key = 4 [deprecated = true];
+ optional int64 padding = 5;
+ optional int32 padding_version = 6;
+ optional bytes u16string_name = 7;
+ }
+ repeated Cache cache = 1;
+ optional string origin = 2 [deprecated = true];
+ optional string storage_key = 3;
+ // Note: The bucket ID is cached here for cases where we need it to
+ // build a Cache Storage directory path when a QuotaManagerProxy
+ // is not available, but otherwise it's safer to lookup the bucket
+ // ID using the storage_key since the value stored here might not
+ // always be reliable (for instance, if a crash occurred between the
+ // time that a bucket was deleted and instances had their index files
+ // deleted on disk).
+ optional int64 bucket_id = 4;
+ optional bool bucket_is_default = 5;
+}
+
+message CacheHeaderMap {
+ required string name = 1;
+ required string value = 2;
+}
+
+message CacheRequest {
+ required string method = 1;
+ repeated CacheHeaderMap headers = 2;
+ optional string fragment = 3;
+ optional bool is_reload_navigation = 4;
+ optional bool is_history_navigation = 5;
+}
+
+message CacheResponse {
+ enum ResponseType {
+ BASIC_TYPE = 0;
+ CORS_TYPE = 1;
+ DEFAULT_TYPE = 2;
+ ERROR_TYPE = 3;
+ OPAQUE_TYPE = 4;
+ OPAQUE_REDIRECT_TYPE = 5;
+ }
+
+ required int32 status_code = 1;
+ required string status_text = 2;
+ required ResponseType response_type = 3;
+ repeated CacheHeaderMap headers = 4;
+ optional string url = 5 [deprecated = true];
+ optional int64 response_time = 6;
+ repeated string cors_exposed_header_names = 7;
+ repeated string url_list = 8;
+ optional bool loaded_with_credentials = 9 [deprecated = true];
+ // Mapped to net::HttpResponseInfo::ConnectionInfo via static casting.
+ optional int32 connection_info = 10;
+ optional string alpn_negotiated_protocol = 11;
+ optional bool was_fetched_via_spdy = 12;
+ optional string mime_type = 13;
+ optional string request_method = 14;
+ optional int64 padding = 15;
+ optional int64 side_data_padding = 16;
+ optional bool request_include_credentials = 17;
+}
+
+message CacheMetadata {
+ required CacheRequest request = 1;
+ required CacheResponse response = 2;
+ optional int64 entry_time = 3;
+}
diff --git a/pyhindsight/lib/content/browser/content_index/content_index.proto b/pyhindsight/lib/content/browser/content_index/content_index.proto
new file mode 100644
index 0000000..4f707cf
--- /dev/null
+++ b/pyhindsight/lib/content/browser/content_index/content_index.proto
@@ -0,0 +1,52 @@
+// Copyright 2019 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package content.proto;
+
+message ContentIconDefinition {
+ optional string src = 1;
+ optional string sizes = 2;
+ optional string type = 3;
+}
+
+// Stores all fields of the developer provided content description.
+message ContentDescription {
+ optional string id = 1;
+ optional string title = 2;
+ optional string description = 3;
+ optional int32 category = 4;
+ repeated ContentIconDefinition icons = 5;
+ optional string launch_url = 6;
+}
+
+// Contains the developer-provided description as well as other metadata that
+// will be useful for ranking content.
+message ContentEntry {
+ optional ContentDescription description = 1;
+
+ // Time from Windows epoch in microseconds.
+ optional int64 timestamp = 2;
+
+ // The complete/resolved URL for the entry. This might differ from
+ // |description.launch_url()| since that field is developer-provided, and
+ // can be an absolute or relative path without the host.
+ optional string launch_url = 3;
+
+ // Whether the ContentIndex entry was created from a top-level context (i.e
+ // not an iframe).
+ optional bool is_top_level_context = 4 [default = true];
+}
+
+// Wrapper to store all the serialized icons.
+message SerializedIcons {
+ // Create a sub-message in case we want to store metadata with the
+ // serialized icon.
+ message SerializedIcon { optional string icon = 1; }
+
+ repeated SerializedIcon icons = 1;
+}
diff --git a/pyhindsight/lib/content/browser/cookie_store/cookie_change_subscriptions.proto b/pyhindsight/lib/content/browser/cookie_store/cookie_change_subscriptions.proto
new file mode 100644
index 0000000..c61da31
--- /dev/null
+++ b/pyhindsight/lib/content/browser/cookie_store/cookie_change_subscriptions.proto
@@ -0,0 +1,27 @@
+// Copyright 2018 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto3";
+
+option optimize_for = LITE_RUNTIME;
+
+package content.proto;
+
+// Proto equivalent of network::mojom::CookieMatchType. Values must match.
+enum CookieMatchType {
+ EQUALS = 0;
+ STARTS_WITH = 1;
+}
+
+// A single cookie change subscription.
+message CookieChangeSubscriptionProto {
+ string url = 1;
+ string name = 2;
+ CookieMatchType match_type = 3;
+}
+
+// All cookie change subscriptions belonging to a service worker registration.
+message CookieChangeSubscriptionsProto {
+ repeated CookieChangeSubscriptionProto subscriptions = 1;
+}
diff --git a/pyhindsight/lib/content/browser/devtools/devtools_background_services.proto b/pyhindsight/lib/content/browser/devtools/devtools_background_services.proto
new file mode 100644
index 0000000..ce4ea26
--- /dev/null
+++ b/pyhindsight/lib/content/browser/devtools/devtools_background_services.proto
@@ -0,0 +1,56 @@
+// Copyright 2019 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package content.devtools.proto;
+
+// The background service we are logging events for.
+// Do not change the tags since these are persisted.
+// Add a corresponding entry in `enums.xml` if a new value is introduced.
+enum BackgroundService {
+ UNKNOWN = 0;
+ TEST_BACKGROUND_SERVICE = 1;
+ BACKGROUND_FETCH = 2;
+ BACKGROUND_SYNC = 3;
+ PUSH_MESSAGING = 4;
+ NOTIFICATIONS = 5;
+ PAYMENT_HANDLER = 6;
+ PERIODIC_BACKGROUND_SYNC = 7;
+
+ // Keep as last, must have the largest tag value.
+ COUNT = 8;
+}
+
+// A proto for storing the background service event with common metadata for
+// all events.
+//
+// Next Tag: 9
+message BackgroundServiceEvent {
+ // Microseconds since windows epoch.
+ optional int64 timestamp = 1;
+
+ // The origin's URL spec.
+ optional string origin = 2;
+
+ optional int64 service_worker_registration_id = 3;
+
+ optional BackgroundService background_service = 4;
+
+ // A descriptive name for the event that is being logged.
+ optional string event_name = 5;
+
+ // The instance this event belongs to. This is for grouping related events.
+ // For example for Background Fetch and Background Sync, this would be the
+ // developer provided ID to create the fetch/sync.
+ optional string instance_id = 6;
+
+ // Additional custom information related to this event.
+ map event_metadata = 7;
+
+ // Storage key the background service belongs to.
+ optional string storage_key = 8;
+}
diff --git a/pyhindsight/lib/content/browser/download/embedder_download_data.proto b/pyhindsight/lib/content/browser/download/embedder_download_data.proto
new file mode 100644
index 0000000..a6f7634
--- /dev/null
+++ b/pyhindsight/lib/content/browser/download/embedder_download_data.proto
@@ -0,0 +1,30 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+
+package content.proto;
+
+// EmbedderDownloadData contains data that is stored in the download history
+// database.
+message EmbedderDownloadData {
+ optional StoragePartitionConfig storage_partition_config = 1;
+}
+
+// StoragePartitionConfig stores data from the content::StoragePartitionConfig
+// class. It enables this data to be serialized for storage in the download
+// history database.
+message StoragePartitionConfig {
+ enum FallbackMode {
+ kNone = 0;
+ kPartitionOnDisk = 1;
+ kPartitionInMemory = 2;
+ }
+
+ required string partition_domain = 1;
+ required string partition_name = 2;
+ required bool in_memory = 3;
+ required FallbackMode fallback_mode = 4;
+}
diff --git a/pyhindsight/lib/content/browser/notifications/notification_database_data.proto b/pyhindsight/lib/content/browser/notifications/notification_database_data.proto
new file mode 100644
index 0000000..c284eed
--- /dev/null
+++ b/pyhindsight/lib/content/browser/notifications/notification_database_data.proto
@@ -0,0 +1,98 @@
+// Copyright 2015 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package content;
+
+// Stores information about a Web Notification. This message is the protocol
+// buffer meant to serialize the content::NotificationDatabaseData structure.
+//
+// Next tag: 17
+message NotificationDatabaseDataProto {
+ enum ClosedReason {
+ USER = 0;
+ DEVELOPER = 1;
+ UNKNOWN = 2;
+ }
+
+ // DEPRECATED: Use |notification_id| instead.
+ optional int64 persistent_notification_id = 1;
+
+ optional string notification_id = 5;
+
+ optional string origin = 2;
+ optional int64 service_worker_registration_id = 3;
+ optional bool replaced_existing_notification = 6;
+ optional int32 num_clicks = 7;
+ optional int32 num_action_button_clicks = 8;
+ optional int64 creation_time_millis = 9;
+ optional int64 time_until_first_click_millis = 10;
+ optional int64 time_until_last_click_millis = 11;
+ optional int64 time_until_close_millis = 12;
+ optional ClosedReason closed_reason = 13;
+
+ // A notification action, corresponds to blink::PlatformNotificationAction.
+ //
+ // Next tag: 6
+ message NotificationAction {
+ // Corresponds to blink::mojom::NotificationActionType.
+ enum Type {
+ BUTTON = 0;
+ TEXT = 1;
+ }
+
+ optional string action = 1;
+ optional string title = 2;
+ optional string icon = 3;
+ optional Type type = 4;
+ optional string placeholder = 5;
+ }
+
+ // Actual data payload of the notification. This message is the protocol
+ // buffer meant to serialize the blink::PlatformNotificationData structure.
+ //
+ // Next tag: 17
+ message NotificationData {
+ enum Direction {
+ LEFT_TO_RIGHT = 0;
+ RIGHT_TO_LEFT = 1;
+ AUTO = 2;
+ }
+
+ optional string title = 1;
+ optional Direction direction = 2;
+ optional string lang = 3;
+ optional string body = 4;
+ optional string tag = 5;
+ optional string image = 15;
+ optional string icon = 6;
+ optional string badge = 14;
+ repeated int32 vibration_pattern = 9 [packed=true];
+ optional int64 timestamp = 12;
+ optional bool renotify = 13;
+ optional bool silent = 7;
+ optional bool require_interaction = 11;
+ optional bytes data = 8;
+ repeated NotificationAction actions = 10;
+ // Stored as offset from the windows epoch in microseconds.
+ optional int64 show_trigger_timestamp = 16;
+ }
+
+ optional NotificationData notification_data = 4;
+
+ // Keeps track if a notification with a |show_trigger_timestamp| has been
+ // displayed already.
+ optional bool has_triggered = 14;
+
+ // Flag for notifications shown by the browser that should not be visible to
+ // the origin when requesting a list of notifications.
+ optional bool is_shown_by_browser = 15;
+
+ // Notification metadata map, where the key is the type of metadata and the
+ // value is any string value of data, such as a serialized dictionary.
+ map serialized_metadata = 16;
+}
diff --git a/pyhindsight/lib/content/browser/payments/payment_app.proto b/pyhindsight/lib/content/browser/payments/payment_app.proto
new file mode 100644
index 0000000..a2939cd
--- /dev/null
+++ b/pyhindsight/lib/content/browser/payments/payment_app.proto
@@ -0,0 +1,59 @@
+// Copyright 2016 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package content;
+
+message StoredPaymentInstrumentKeyInfoProto {
+ optional uint64 insertion_order = 1;
+ optional string key = 2;
+}
+
+message ImageSizeProto {
+ optional uint64 width = 1;
+ optional uint64 height = 2;
+}
+
+message StoredPaymentInstrumentImageObject {
+ optional string src = 1;
+ optional string type = 2;
+ repeated ImageSizeProto sizes = 3;
+}
+
+message StoredPaymentInstrumentProto {
+ optional int64 registration_id = 1;
+ optional string instrument_key = 2;
+ optional string name = 3;
+ optional string method = 4;
+ optional string stringified_capabilities = 5;
+ repeated StoredPaymentInstrumentImageObject icons = 6;
+ optional string decoded_instrument_icon = 7;
+ repeated int32 supported_card_networks = 8;
+}
+
+message StoredRelatedApplicationProto {
+ optional string platform = 1;
+ optional string id = 2;
+}
+
+message SupportedDelegationsProto {
+ optional bool shipping_address = 1;
+ optional bool payer_name = 2;
+ optional bool payer_phone = 3;
+ optional bool payer_email = 4;
+}
+
+message StoredPaymentAppProto {
+ optional int64 registration_id = 1;
+ optional string scope = 2;
+ optional string name = 3;
+ optional string icon = 4;
+ optional bool prefer_related_applications = 5;
+ repeated StoredRelatedApplicationProto related_applications = 6;
+ optional string user_hint = 7;
+ optional SupportedDelegationsProto supported_delegations = 8;
+}