#include "components/sync/protocol/proto_value_conversions.h"
#include <stdint.h>
#include <string>
#include <utility>
#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/contact_info_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_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/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/segmentation_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/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_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 {
class ToValueVisitor {
public:
explicit ToValueVisitor(const ProtoValueConversionOptions& options =
ProtoValueConversionOptions(),
base::Value::Dict* value = nullptr)
: options_(options), value_(value) {}
template <class P>
void VisitBytes(const P& parent_proto,
const char* field_name,
const std::string& field) {
value_->Set(field_name,
base::Base64Encode(base::as_bytes(base::make_span(field))));
}
template <class P>
void VisitBytes(
const P& parent_proto,
const char* field_name,
const google::protobuf::RepeatedPtrField<std::string>& repeated_field) {
if (!repeated_field.empty()) {
base::Value::List list;
for (const auto& field : repeated_field) {
list.Append(base::Base64Encode(base::as_bytes(base::make_span(field))));
}
value_->Set(field_name, std::move(list));
}
}
template <class P>
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 <class P, class E>
void VisitEnum(const P& parent_proto, const char* field_name, E field) {
value_->Set(field_name, ProtoEnumToString(field));
}
template <class P, class F>
void Visit(const P& parent_proto,
const char* field_name,
const google::protobuf::RepeatedPtrField<F>& 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 <class P, class F>
void Visit(const P& parent_proto,
const char* field_name,
const google::protobuf::RepeatedField<F>& 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 <class P, class F>
void Visit(const P& parent_proto, const char* field_name, const F& field) {
VisitImpl(parent_proto, field_name, field);
}
template <class P>
base::Value ToValue(const P& proto) const {
return base::Value(ToValueDictImpl(proto));
}
template <class P>
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);
}
}
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));
}
base::Value ToValue(const sync_pb::AutofillWalletSpecifics& proto) const {
base::Value::Dict dict = ToValueDictImpl(proto);
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");
}
return base::Value(std::move(dict));
}
base::Value ToValue(const sync_pb::UniquePosition& proto) const {
UniquePosition pos = UniquePosition::FromProto(proto);
return base::Value(pos.ToDebugString());
}
private:
template <class P>
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); }
template <class P, class F>
void VisitImpl(P&, const char* field_name, const F& field) {
value_->Set(field_name, ToValue(field));
}
const ProtoValueConversionOptions options_;
raw_ptr<base::Value::Dict> value_;
};
}
#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(AutofillWalletSpecifics)
IMPLEMENT_PROTO_TO_VALUE(AutofillWalletUsageSpecifics)
IMPLEMENT_PROTO_TO_VALUE(BookmarkSpecifics)
IMPLEMENT_PROTO_TO_VALUE(ClientConfigParams)
IMPLEMENT_PROTO_TO_VALUE(ContactInfoSpecifics)
IMPLEMENT_PROTO_TO_VALUE(DebugEventInfo)
IMPLEMENT_PROTO_TO_VALUE(DebugInfo)
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(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(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(PasswordSpecifics)
IMPLEMENT_PROTO_TO_VALUE(PasswordSpecificsData)
IMPLEMENT_PROTO_TO_VALUE(PasswordSpecificsData_Notes)
IMPLEMENT_PROTO_TO_VALUE(PasswordSpecificsData_Notes_Note)
IMPLEMENT_PROTO_TO_VALUE(PowerBookmarkSpecifics)
IMPLEMENT_PROTO_TO_VALUE(PaymentsCustomerData)
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(ReadingListSpecifics)
IMPLEMENT_PROTO_TO_VALUE(SavedTabGroupSpecifics)
IMPLEMENT_PROTO_TO_VALUE(SearchEngineSpecifics)
IMPLEMENT_PROTO_TO_VALUE(SecurityEventSpecifics)
IMPLEMENT_PROTO_TO_VALUE(SendTabToSelfSpecifics)
IMPLEMENT_PROTO_TO_VALUE(SegmentationSpecifics)
IMPLEMENT_PROTO_TO_VALUE(SessionHeader)
IMPLEMENT_PROTO_TO_VALUE(SessionSpecifics)
IMPLEMENT_PROTO_TO_VALUE(SessionTab)
IMPLEMENT_PROTO_TO_VALUE(SessionWindow)
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(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(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
}