proto_value_conversions.cc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/sync/protocol/proto_value_conversions.h"
  5. #include <stdint.h>
  6. #include <string>
  7. #include <utility>
  8. #include "base/base64.h"
  9. #include "base/memory/raw_ptr.h"
  10. #include "base/strings/string_number_conversions.h"
  11. #include "base/values.h"
  12. #include "components/sync/base/unique_position.h"
  13. #include "components/sync/protocol/app_list_specifics.pb.h"
  14. #include "components/sync/protocol/app_setting_specifics.pb.h"
  15. #include "components/sync/protocol/app_specifics.pb.h"
  16. #include "components/sync/protocol/arc_package_specifics.pb.h"
  17. #include "components/sync/protocol/autofill_offer_specifics.pb.h"
  18. #include "components/sync/protocol/autofill_specifics.pb.h"
  19. #include "components/sync/protocol/bookmark_specifics.pb.h"
  20. #include "components/sync/protocol/contact_info_specifics.pb.h"
  21. #include "components/sync/protocol/data_type_progress_marker.pb.h"
  22. #include "components/sync/protocol/dictionary_specifics.pb.h"
  23. #include "components/sync/protocol/entity_specifics.pb.h"
  24. #include "components/sync/protocol/extension_setting_specifics.pb.h"
  25. #include "components/sync/protocol/extension_specifics.pb.h"
  26. #include "components/sync/protocol/history_delete_directive_specifics.pb.h"
  27. #include "components/sync/protocol/history_specifics.pb.h"
  28. #include "components/sync/protocol/nigori_specifics.pb.h"
  29. #include "components/sync/protocol/os_preference_specifics.pb.h"
  30. #include "components/sync/protocol/os_priority_preference_specifics.pb.h"
  31. #include "components/sync/protocol/password_specifics.pb.h"
  32. #include "components/sync/protocol/preference_specifics.pb.h"
  33. #include "components/sync/protocol/printer_specifics.pb.h"
  34. #include "components/sync/protocol/printers_authorization_server_specifics.pb.h"
  35. #include "components/sync/protocol/priority_preference_specifics.pb.h"
  36. #include "components/sync/protocol/proto_visitors.h"
  37. #include "components/sync/protocol/reading_list_specifics.pb.h"
  38. #include "components/sync/protocol/search_engine_specifics.pb.h"
  39. #include "components/sync/protocol/send_tab_to_self_specifics.pb.h"
  40. #include "components/sync/protocol/session_specifics.pb.h"
  41. #include "components/sync/protocol/sharing_message_specifics.pb.h"
  42. #include "components/sync/protocol/sync.pb.h"
  43. #include "components/sync/protocol/sync_entity.pb.h"
  44. #include "components/sync/protocol/theme_specifics.pb.h"
  45. #include "components/sync/protocol/typed_url_specifics.pb.h"
  46. #include "components/sync/protocol/user_consent_specifics.pb.h"
  47. #include "components/sync/protocol/user_event_specifics.pb.h"
  48. #include "components/sync/protocol/web_app_specifics.pb.h"
  49. #include "components/sync/protocol/webauthn_credential_specifics.pb.h"
  50. #include "components/sync/protocol/workspace_desk_specifics.pb.h"
  51. namespace syncer {
  52. namespace {
  53. // ToValueVisitor is a VisitProtoFields()-compatible visitor that serializes
  54. // protos to base::DictionaryValues. To serialize a proto you call ToValue()
  55. // method:
  56. //
  57. // ToValueVisitor visitor;
  58. // auto value = visitor.ToValue(proto);
  59. //
  60. // By default all fields visited by VisitProtoFields() are serialized, but
  61. // there are several ways to customize that on per-field / per-proto basis:
  62. //
  63. // 1. If you want to change how fields of a particular proto type are
  64. // serialized, customize Visit() method:
  65. //
  66. // template <class P, class F>
  67. // void Visit(const P& parent_proto,
  68. // const char* field_name, const F& field);
  69. //
  70. // By default Visit() serializes |field| and sets it to |value_| under
  71. // |field_name| name. Default implementation is accessible via VisitImpl().
  72. //
  73. // For example here is how you would serialize only GreenProto::content
  74. // for all GreenProto fields:
  75. //
  76. // template <class P>
  77. // void Visit(const P& parent_proto,
  78. // const char* field_name, const sync_pb::GreenProto& field) {
  79. // if (field.has_content()) {
  80. // value_->Set(field_name, field.content());
  81. // }
  82. // }
  83. //
  84. // You can further fine-tune this method by specifying parent proto. For
  85. // example let's say we don't want to serialize fields of type GreenProto
  86. // that are contained in RedProto:
  87. //
  88. // void Visit(const sync_pb::RedProto& parent_proto,
  89. // const char* field_name, const sync_pb::GreenProto& field) {}
  90. //
  91. // Note: Visit() method only called to serialize fields, and doesn't
  92. // affect top level protos. I.e. ToValueVisitor().ToValue(GreenProto)
  93. // won't call methods above.
  94. //
  95. // 2. If you want to change how proto itself is serialized, you need to
  96. // customize ToValue() method:
  97. //
  98. // template <class P>
  99. // std::unique_ptr<base::DictionaryValue> ToValue(const P& proto) const;
  100. //
  101. // By default ToValue() creates new instance of ToValueVisitor, calls
  102. // VisitProtoFields(visitor, |proto|) and returns visitor's |value_|.
  103. // Default implementation is accessible via ToValueImpl().
  104. //
  105. // For example let's say you want to clobber a sensitive field:
  106. //
  107. // std::unique_ptr<base::DictionaryValue> ToValue(
  108. // const sync_pb::GreenProto& proto) const {
  109. // std::unique_ptr<base::DictionaryValue> value = ToValueImpl(proto);
  110. // value->SetStringKey("secret", "<clobbered>");
  111. // return value;
  112. // }
  113. //
  114. // ToValue() doesn't have to return base::DictionaryValue though. It might
  115. // be more appropriate to serialize GreenProto into a string instead:
  116. //
  117. // std::unique_ptr<base::Value> ToValue(
  118. // const sync_pb::GreenProto& proto) const {
  119. // return std::make_unique<base::Value>(proto.content());
  120. // }
  121. //
  122. class ToValueVisitor {
  123. public:
  124. explicit ToValueVisitor(const ProtoValueConversionOptions& options =
  125. ProtoValueConversionOptions(),
  126. base::DictionaryValue* value = nullptr)
  127. : options_(options), value_(value) {}
  128. template <class P>
  129. void VisitBytes(const P& parent_proto,
  130. const char* field_name,
  131. const std::string& field) {
  132. value_->Set(field_name, BytesToValue(field));
  133. }
  134. template <class P, class E>
  135. void VisitEnum(const P& parent_proto, const char* field_name, E field) {
  136. value_->Set(field_name, EnumToValue(field));
  137. }
  138. template <class P, class F>
  139. void Visit(const P& parent_proto,
  140. const char* field_name,
  141. const google::protobuf::RepeatedPtrField<F>& repeated_field) {
  142. if (!repeated_field.empty()) {
  143. std::unique_ptr<base::ListValue> list(new base::ListValue());
  144. for (const auto& field : repeated_field) {
  145. list->Append(base::Value::FromUniquePtrValue(ToValue(field)));
  146. }
  147. value_->Set(field_name, std::move(list));
  148. }
  149. }
  150. template <class P, class F>
  151. void Visit(const P& parent_proto,
  152. const char* field_name,
  153. const google::protobuf::RepeatedField<F>& repeated_field) {
  154. if (!repeated_field.empty()) {
  155. std::unique_ptr<base::ListValue> list(new base::ListValue());
  156. for (const auto& field : repeated_field) {
  157. list->Append(base::Value::FromUniquePtrValue(ToValue(field)));
  158. }
  159. value_->Set(field_name, std::move(list));
  160. }
  161. }
  162. template <class P, class F>
  163. void Visit(const P& parent_proto, const char* field_name, const F& field) {
  164. VisitImpl(parent_proto, field_name, field);
  165. }
  166. template <class P>
  167. std::unique_ptr<base::DictionaryValue> ToValue(const P& proto) const {
  168. return ToValueImpl(proto);
  169. }
  170. // Customizations
  171. // EntitySpecifics
  172. template <class P>
  173. void Visit(const P& parent_proto,
  174. const char* field_name,
  175. const sync_pb::EntitySpecifics& field) {
  176. if (options_.include_specifics) {
  177. VisitImpl(parent_proto, field_name, field);
  178. }
  179. }
  180. // GetUpdateTriggers.
  181. std::unique_ptr<base::DictionaryValue> ToValue(
  182. const sync_pb::GetUpdateTriggers& proto) const {
  183. std::unique_ptr<base::DictionaryValue> value = ToValueImpl(proto);
  184. if (!options_.include_full_get_update_triggers) {
  185. if (!proto.client_dropped_hints()) {
  186. value->RemoveKey("client_dropped_hints");
  187. }
  188. if (!proto.invalidations_out_of_sync()) {
  189. value->RemoveKey("invalidations_out_of_sync");
  190. }
  191. if (proto.local_modification_nudges() == 0) {
  192. value->RemoveKey("local_modification_nudges");
  193. }
  194. if (proto.datatype_refresh_nudges() == 0) {
  195. value->RemoveKey("datatype_refresh_nudges");
  196. }
  197. if (!proto.server_dropped_hints()) {
  198. value->RemoveKey("server_dropped_hints");
  199. }
  200. if (!proto.initial_sync_in_progress()) {
  201. value->RemoveKey("initial_sync_in_progress");
  202. }
  203. if (!proto.sync_for_resolve_conflict_in_progress()) {
  204. value->RemoveKey("sync_for_resolve_conflict_in_progress");
  205. }
  206. }
  207. return value;
  208. }
  209. // AutofillWalletSpecifics
  210. std::unique_ptr<base::DictionaryValue> ToValue(
  211. const sync_pb::AutofillWalletSpecifics& proto) const {
  212. std::unique_ptr<base::DictionaryValue> value = ToValueImpl(proto);
  213. if (proto.type() != sync_pb::AutofillWalletSpecifics::POSTAL_ADDRESS) {
  214. value->RemoveKey("address");
  215. }
  216. if (proto.type() != sync_pb::AutofillWalletSpecifics::MASKED_CREDIT_CARD) {
  217. value->RemoveKey("masked_card");
  218. }
  219. if (proto.type() != sync_pb::AutofillWalletSpecifics::CUSTOMER_DATA) {
  220. value->RemoveKey("customer_data");
  221. }
  222. if (proto.type() !=
  223. sync_pb::AutofillWalletSpecifics::CREDIT_CARD_CLOUD_TOKEN_DATA) {
  224. value->RemoveKey("cloud_token_data");
  225. }
  226. return value;
  227. }
  228. // UniquePosition
  229. std::unique_ptr<base::Value> ToValue(
  230. const sync_pb::UniquePosition& proto) const {
  231. UniquePosition pos = UniquePosition::FromProto(proto);
  232. return std::make_unique<base::Value>(pos.ToDebugString());
  233. }
  234. private:
  235. template <class P>
  236. std::unique_ptr<base::DictionaryValue> ToValueImpl(const P& proto) const {
  237. auto value = std::make_unique<base::DictionaryValue>();
  238. ToValueVisitor visitor(options_, value.get());
  239. VisitProtoFields(visitor, proto);
  240. return value;
  241. }
  242. static std::unique_ptr<base::Value> BytesToValue(const std::string& bytes) {
  243. std::string bytes_base64;
  244. base::Base64Encode(bytes, &bytes_base64);
  245. return std::make_unique<base::Value>(bytes_base64);
  246. }
  247. template <class E>
  248. static std::unique_ptr<base::Value> EnumToValue(E value) {
  249. return std::make_unique<base::Value>(ProtoEnumToString(value));
  250. }
  251. std::unique_ptr<base::Value> ToValue(const std::string& value) const {
  252. return std::make_unique<base::Value>(value);
  253. }
  254. std::unique_ptr<base::Value> ToValue(int64_t value) const {
  255. return std::make_unique<base::Value>(base::NumberToString(value));
  256. }
  257. std::unique_ptr<base::Value> ToValue(uint64_t value) const {
  258. return std::make_unique<base::Value>(base::NumberToString(value));
  259. }
  260. std::unique_ptr<base::Value> ToValue(uint32_t value) const {
  261. return std::make_unique<base::Value>(base::NumberToString(value));
  262. }
  263. std::unique_ptr<base::Value> ToValue(int32_t value) const {
  264. return std::make_unique<base::Value>(base::NumberToString(value));
  265. }
  266. std::unique_ptr<base::Value> ToValue(bool value) const {
  267. return std::make_unique<base::Value>(value);
  268. }
  269. std::unique_ptr<base::Value> ToValue(float value) const {
  270. return std::make_unique<base::Value>(value);
  271. }
  272. std::unique_ptr<base::Value> ToValue(double value) const {
  273. return std::make_unique<base::Value>(value);
  274. }
  275. // Needs to be here to see all ToValue() overloads above.
  276. template <class P, class F>
  277. void VisitImpl(P&, const char* field_name, const F& field) {
  278. value_->Set(field_name, ToValue(field));
  279. }
  280. const ProtoValueConversionOptions options_;
  281. raw_ptr<base::DictionaryValue> value_;
  282. };
  283. } // namespace
  284. #define IMPLEMENT_PROTO_TO_VALUE(Proto) \
  285. std::unique_ptr<base::DictionaryValue> Proto##ToValue( \
  286. const sync_pb::Proto& proto) { \
  287. return ToValueVisitor().ToValue(proto); \
  288. }
  289. #define IMPLEMENT_PROTO_TO_VALUE_WITH_OPTIONS(Proto) \
  290. std::unique_ptr<base::DictionaryValue> Proto##ToValue( \
  291. const sync_pb::Proto& proto, \
  292. const ProtoValueConversionOptions& options) { \
  293. return ToValueVisitor(options).ToValue(proto); \
  294. }
  295. IMPLEMENT_PROTO_TO_VALUE(AppListSpecifics)
  296. IMPLEMENT_PROTO_TO_VALUE(AppSettingSpecifics)
  297. IMPLEMENT_PROTO_TO_VALUE(AppSpecifics)
  298. IMPLEMENT_PROTO_TO_VALUE(ArcPackageSpecifics)
  299. IMPLEMENT_PROTO_TO_VALUE(AutofillOfferSpecifics)
  300. IMPLEMENT_PROTO_TO_VALUE(AutofillProfileSpecifics)
  301. IMPLEMENT_PROTO_TO_VALUE(AutofillSpecifics)
  302. IMPLEMENT_PROTO_TO_VALUE(AutofillWalletSpecifics)
  303. IMPLEMENT_PROTO_TO_VALUE(BookmarkSpecifics)
  304. IMPLEMENT_PROTO_TO_VALUE(ClientConfigParams)
  305. IMPLEMENT_PROTO_TO_VALUE(ContactInfoSpecifics)
  306. IMPLEMENT_PROTO_TO_VALUE(DebugEventInfo)
  307. IMPLEMENT_PROTO_TO_VALUE(DebugInfo)
  308. IMPLEMENT_PROTO_TO_VALUE(DeviceInfoSpecifics)
  309. IMPLEMENT_PROTO_TO_VALUE(DictionarySpecifics)
  310. IMPLEMENT_PROTO_TO_VALUE(EncryptedData)
  311. IMPLEMENT_PROTO_TO_VALUE(EntityMetadata)
  312. IMPLEMENT_PROTO_TO_VALUE(EntitySpecifics)
  313. IMPLEMENT_PROTO_TO_VALUE(ExtensionSettingSpecifics)
  314. IMPLEMENT_PROTO_TO_VALUE(ExtensionSpecifics)
  315. IMPLEMENT_PROTO_TO_VALUE(GlobalIdDirective)
  316. IMPLEMENT_PROTO_TO_VALUE(HistoryDeleteDirectiveSpecifics)
  317. IMPLEMENT_PROTO_TO_VALUE(HistorySpecifics)
  318. IMPLEMENT_PROTO_TO_VALUE(LinkedAppIconInfo)
  319. IMPLEMENT_PROTO_TO_VALUE(ManagedUserSettingSpecifics)
  320. IMPLEMENT_PROTO_TO_VALUE(NavigationRedirect)
  321. IMPLEMENT_PROTO_TO_VALUE(NigoriSpecifics)
  322. IMPLEMENT_PROTO_TO_VALUE(OsPreferenceSpecifics)
  323. IMPLEMENT_PROTO_TO_VALUE(OsPriorityPreferenceSpecifics)
  324. IMPLEMENT_PROTO_TO_VALUE(PasswordSpecifics)
  325. IMPLEMENT_PROTO_TO_VALUE(PasswordSpecificsData)
  326. IMPLEMENT_PROTO_TO_VALUE(PasswordSpecificsData_Notes)
  327. IMPLEMENT_PROTO_TO_VALUE(PasswordSpecificsData_Notes_Note)
  328. IMPLEMENT_PROTO_TO_VALUE(PaymentsCustomerData)
  329. IMPLEMENT_PROTO_TO_VALUE(PreferenceSpecifics)
  330. IMPLEMENT_PROTO_TO_VALUE(PrinterPPDReference)
  331. IMPLEMENT_PROTO_TO_VALUE(PrinterSpecifics)
  332. IMPLEMENT_PROTO_TO_VALUE(PrintersAuthorizationServerSpecifics)
  333. IMPLEMENT_PROTO_TO_VALUE(PriorityPreferenceSpecifics)
  334. IMPLEMENT_PROTO_TO_VALUE(ReadingListSpecifics)
  335. IMPLEMENT_PROTO_TO_VALUE(SearchEngineSpecifics)
  336. IMPLEMENT_PROTO_TO_VALUE(SecurityEventSpecifics)
  337. IMPLEMENT_PROTO_TO_VALUE(SendTabToSelfSpecifics)
  338. IMPLEMENT_PROTO_TO_VALUE(SessionHeader)
  339. IMPLEMENT_PROTO_TO_VALUE(SessionSpecifics)
  340. IMPLEMENT_PROTO_TO_VALUE(SessionTab)
  341. IMPLEMENT_PROTO_TO_VALUE(SessionWindow)
  342. IMPLEMENT_PROTO_TO_VALUE(SharingMessageSpecifics)
  343. IMPLEMENT_PROTO_TO_VALUE(SyncCycleCompletedEventInfo)
  344. IMPLEMENT_PROTO_TO_VALUE(TabNavigation)
  345. IMPLEMENT_PROTO_TO_VALUE(ThemeSpecifics)
  346. IMPLEMENT_PROTO_TO_VALUE(TimeRangeDirective)
  347. IMPLEMENT_PROTO_TO_VALUE(TypedUrlSpecifics)
  348. IMPLEMENT_PROTO_TO_VALUE(UrlDirective)
  349. IMPLEMENT_PROTO_TO_VALUE(UserConsentSpecifics)
  350. IMPLEMENT_PROTO_TO_VALUE(UserEventSpecifics)
  351. IMPLEMENT_PROTO_TO_VALUE(WalletCreditCardCloudTokenData)
  352. IMPLEMENT_PROTO_TO_VALUE(WalletMaskedCreditCard)
  353. IMPLEMENT_PROTO_TO_VALUE(WalletMetadataSpecifics)
  354. IMPLEMENT_PROTO_TO_VALUE(WalletPostalAddress)
  355. IMPLEMENT_PROTO_TO_VALUE(WebAppSpecifics)
  356. IMPLEMENT_PROTO_TO_VALUE(WifiConfigurationSpecifics)
  357. IMPLEMENT_PROTO_TO_VALUE(WorkspaceDeskSpecifics)
  358. IMPLEMENT_PROTO_TO_VALUE_WITH_OPTIONS(ClientToServerMessage)
  359. IMPLEMENT_PROTO_TO_VALUE_WITH_OPTIONS(ClientToServerResponse)
  360. IMPLEMENT_PROTO_TO_VALUE_WITH_OPTIONS(SyncEntity)
  361. #undef IMPLEMENT_PROTO_TO_VALUE
  362. #undef IMPLEMENT_PROTO_TO_VALUE_WITH_OPTIONS
  363. } // namespace syncer