Home | History | Annotate | Download | only in protocol
      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 
      5 // Keep this file in sync with the .proto files in this directory.
      6 
      7 #include "sync/protocol/proto_value_conversions.h"
      8 
      9 #include <string>
     10 
     11 #include "base/base64.h"
     12 #include "base/basictypes.h"
     13 #include "base/logging.h"
     14 #include "base/strings/string_number_conversions.h"
     15 #include "base/values.h"
     16 #include "sync/internal_api/public/base/unique_position.h"
     17 #include "sync/protocol/app_notification_specifics.pb.h"
     18 #include "sync/protocol/app_setting_specifics.pb.h"
     19 #include "sync/protocol/app_specifics.pb.h"
     20 #include "sync/protocol/autofill_specifics.pb.h"
     21 #include "sync/protocol/bookmark_specifics.pb.h"
     22 #include "sync/protocol/dictionary_specifics.pb.h"
     23 #include "sync/protocol/encryption.pb.h"
     24 #include "sync/protocol/experiments_specifics.pb.h"
     25 #include "sync/protocol/extension_setting_specifics.pb.h"
     26 #include "sync/protocol/extension_specifics.pb.h"
     27 #include "sync/protocol/favicon_image_specifics.pb.h"
     28 #include "sync/protocol/favicon_tracking_specifics.pb.h"
     29 #include "sync/protocol/history_delete_directive_specifics.pb.h"
     30 #include "sync/protocol/nigori_specifics.pb.h"
     31 #include "sync/protocol/password_specifics.pb.h"
     32 #include "sync/protocol/preference_specifics.pb.h"
     33 #include "sync/protocol/priority_preference_specifics.pb.h"
     34 #include "sync/protocol/proto_enum_conversions.h"
     35 #include "sync/protocol/search_engine_specifics.pb.h"
     36 #include "sync/protocol/session_specifics.pb.h"
     37 #include "sync/protocol/sync.pb.h"
     38 #include "sync/protocol/synced_notification_specifics.pb.h"
     39 #include "sync/protocol/theme_specifics.pb.h"
     40 #include "sync/protocol/typed_url_specifics.pb.h"
     41 #include "sync/protocol/unique_position.pb.h"
     42 
     43 namespace syncer {
     44 
     45 namespace {
     46 
     47 // Basic Type -> Value functions.
     48 
     49 base::StringValue* MakeInt64Value(int64 x) {
     50   return new base::StringValue(base::Int64ToString(x));
     51 }
     52 
     53 // TODO(akalin): Perhaps make JSONWriter support BinaryValue and use
     54 // that instead of a StringValue.
     55 base::StringValue* MakeBytesValue(const std::string& bytes) {
     56   std::string bytes_base64;
     57   if (!base::Base64Encode(bytes, &bytes_base64)) {
     58     NOTREACHED();
     59   }
     60   return new base::StringValue(bytes_base64);
     61 }
     62 
     63 base::StringValue* MakeStringValue(const std::string& str) {
     64   return new base::StringValue(str);
     65 }
     66 
     67 // T is the enum type.
     68 template <class T>
     69 base::StringValue* MakeEnumValue(T t, const char* (*converter_fn)(T)) {
     70   return new base::StringValue(converter_fn(t));
     71 }
     72 
     73 // T is the field type, F is either RepeatedField or RepeatedPtrField,
     74 // and V is a subclass of Value.
     75 template <class T, class F, class V>
     76 base::ListValue* MakeRepeatedValue(const F& fields, V* (*converter_fn)(T)) {
     77   base::ListValue* list = new base::ListValue();
     78   for (typename F::const_iterator it = fields.begin(); it != fields.end();
     79        ++it) {
     80     list->Append(converter_fn(*it));
     81   }
     82   return list;
     83 }
     84 
     85 }  // namespace
     86 
     87 // Helper macros to reduce the amount of boilerplate.
     88 
     89 #define SET(field, fn) \
     90   if (proto.has_##field()) { \
     91     value->Set(#field, fn(proto.field())); \
     92   }
     93 #define SET_REP(field, fn) \
     94   value->Set(#field, MakeRepeatedValue(proto.field(), fn))
     95 #define SET_ENUM(field, fn) \
     96   value->Set(#field, MakeEnumValue(proto.field(), fn))
     97 
     98 #define SET_BOOL(field) SET(field, new base::FundamentalValue)
     99 #define SET_BYTES(field) SET(field, MakeBytesValue)
    100 #define SET_INT32(field) SET(field, MakeInt64Value)
    101 #define SET_INT32_REP(field) SET_REP(field, MakeInt64Value)
    102 #define SET_INT64(field) SET(field, MakeInt64Value)
    103 #define SET_INT64_REP(field) SET_REP(field, MakeInt64Value)
    104 #define SET_STR(field) SET(field, new base::StringValue)
    105 #define SET_STR_REP(field) \
    106   value->Set(#field, \
    107              MakeRepeatedValue<const std::string&, \
    108                                google::protobuf::RepeatedPtrField< \
    109                                    std::string >, \
    110                                base::StringValue>(proto.field(), \
    111                                             MakeStringValue))
    112 #define SET_EXPERIMENT_ENABLED_FIELD(field)          \
    113   do {                                               \
    114     if (proto.has_##field() &&                       \
    115         proto.field().has_enabled()) {               \
    116       value->Set(#field,                             \
    117                  new base::FundamentalValue(         \
    118                      proto.field().enabled()));      \
    119     }                                                \
    120   } while (0)
    121 
    122 #define SET_FIELD(field, fn)                         \
    123   do {                                               \
    124     if (specifics.has_##field()) {                   \
    125       value->Set(#field, fn(specifics.field()));     \
    126     }                                                \
    127   } while (0)
    128 
    129 // If you add another macro, don't forget to add an #undef at the end
    130 // of this file, too.
    131 
    132 base::DictionaryValue* EncryptedDataToValue(
    133     const sync_pb::EncryptedData& proto) {
    134   base::DictionaryValue* value = new base::DictionaryValue();
    135   SET_STR(key_name);
    136   // TODO(akalin): Shouldn't blob be of type bytes instead of string?
    137   SET_BYTES(blob);
    138   return value;
    139 }
    140 
    141 base::DictionaryValue* AppSettingsToValue(
    142     const sync_pb::AppNotificationSettings& proto) {
    143   base::DictionaryValue* value = new base::DictionaryValue();
    144   SET_BOOL(initial_setup_done);
    145   SET_BOOL(disabled);
    146   SET_STR(oauth_client_id);
    147   return value;
    148 }
    149 
    150 base::DictionaryValue* SessionHeaderToValue(
    151     const sync_pb::SessionHeader& proto) {
    152   base::DictionaryValue* value = new base::DictionaryValue();
    153   SET_REP(window, SessionWindowToValue);
    154   SET_STR(client_name);
    155   SET_ENUM(device_type, GetDeviceTypeString);
    156   return value;
    157 }
    158 
    159 base::DictionaryValue* SessionTabToValue(const sync_pb::SessionTab& proto) {
    160   base::DictionaryValue* value = new base::DictionaryValue();
    161   SET_INT32(tab_id);
    162   SET_INT32(window_id);
    163   SET_INT32(tab_visual_index);
    164   SET_INT32(current_navigation_index);
    165   SET_BOOL(pinned);
    166   SET_STR(extension_app_id);
    167   SET_REP(navigation, TabNavigationToValue);
    168   SET_BYTES(favicon);
    169   SET_ENUM(favicon_type, GetFaviconTypeString);
    170   SET_STR(favicon_source);
    171   return value;
    172 }
    173 
    174 base::DictionaryValue* SessionWindowToValue(
    175     const sync_pb::SessionWindow& proto) {
    176   base::DictionaryValue* value = new base::DictionaryValue();
    177   SET_INT32(window_id);
    178   SET_INT32(selected_tab_index);
    179   SET_INT32_REP(tab);
    180   SET_ENUM(browser_type, GetBrowserTypeString);
    181   return value;
    182 }
    183 
    184 base::DictionaryValue* TabNavigationToValue(
    185     const sync_pb::TabNavigation& proto) {
    186   base::DictionaryValue* value = new base::DictionaryValue();
    187   SET_STR(virtual_url);
    188   SET_STR(referrer);
    189   SET_STR(title);
    190   SET_STR(state);
    191   SET_ENUM(page_transition, GetPageTransitionString);
    192   SET_ENUM(redirect_type, GetPageTransitionRedirectTypeString);
    193   SET_INT32(unique_id);
    194   SET_INT64(timestamp_msec);
    195   SET_BOOL(navigation_forward_back);
    196   SET_BOOL(navigation_from_address_bar);
    197   SET_BOOL(navigation_home_page);
    198   SET_BOOL(navigation_chain_start);
    199   SET_BOOL(navigation_chain_end);
    200   SET_INT64(global_id);
    201   SET_STR(search_terms);
    202   SET_STR(favicon_url);
    203   SET_ENUM(blocked_state, GetBlockedStateString);
    204   SET_STR_REP(content_pack_categories);
    205   return value;
    206 }
    207 
    208 base::DictionaryValue* PasswordSpecificsDataToValue(
    209     const sync_pb::PasswordSpecificsData& proto) {
    210   base::DictionaryValue* value = new base::DictionaryValue();
    211   SET_INT32(scheme);
    212   SET_STR(signon_realm);
    213   SET_STR(origin);
    214   SET_STR(action);
    215   SET_STR(username_element);
    216   SET_STR(username_value);
    217   SET_STR(password_element);
    218   value->SetString("password_value", "<redacted>");
    219   SET_BOOL(ssl_valid);
    220   SET_BOOL(preferred);
    221   SET_INT64(date_created);
    222   SET_BOOL(blacklisted);
    223   return value;
    224 }
    225 
    226 base::DictionaryValue* GlobalIdDirectiveToValue(
    227     const sync_pb::GlobalIdDirective& proto) {
    228   base::DictionaryValue* value = new base::DictionaryValue();
    229   SET_INT64_REP(global_id);
    230   SET_INT64(start_time_usec);
    231   SET_INT64(end_time_usec);
    232   return value;
    233 }
    234 
    235 base::DictionaryValue* TimeRangeDirectiveToValue(
    236     const sync_pb::TimeRangeDirective& proto) {
    237   base::DictionaryValue* value = new base::DictionaryValue();
    238   SET_INT64(start_time_usec);
    239   SET_INT64(end_time_usec);
    240   return value;
    241 }
    242 
    243 base::DictionaryValue* SimpleCollapsedLayoutToValue(
    244     const sync_pb::SimpleCollapsedLayout& proto) {
    245   base::DictionaryValue* value = new base::DictionaryValue();
    246   SET_STR(heading);
    247   SET_STR(description);
    248   return value;
    249 }
    250 
    251 base::DictionaryValue* CollapsedInfoToValue(
    252     const sync_pb::CollapsedInfo& proto) {
    253   base::DictionaryValue* value = new base::DictionaryValue();
    254   SET(simple_collapsed_layout, SimpleCollapsedLayoutToValue);
    255   return value;
    256 }
    257 
    258 base::DictionaryValue* RenderInfoToValue(
    259     const sync_pb::SyncedNotificationRenderInfo& proto) {
    260   base::DictionaryValue* value = new base::DictionaryValue();
    261   SET(collapsed_info, CollapsedInfoToValue);
    262   return value;
    263 }
    264 
    265 base::DictionaryValue* CoalescedNotificationToValue(
    266     const sync_pb::CoalescedSyncedNotification& proto) {
    267   base::DictionaryValue* value = new base::DictionaryValue();
    268   SET_STR(key);
    269   SET_INT32(read_state);
    270   SET(render_info, RenderInfoToValue);
    271   return value;
    272 }
    273 
    274 base::DictionaryValue* AppNotificationToValue(
    275     const sync_pb::AppNotification& proto) {
    276   base::DictionaryValue* value = new base::DictionaryValue();
    277   SET_STR(guid);
    278   SET_STR(app_id);
    279   SET_INT64(creation_timestamp_ms);
    280   SET_STR(title);
    281   SET_STR(body_text);
    282   SET_STR(link_url);
    283   SET_STR(link_text);
    284   return value;
    285 }
    286 
    287 base::DictionaryValue* AppSettingSpecificsToValue(
    288     const sync_pb::AppSettingSpecifics& proto) {
    289   base::DictionaryValue* value = new base::DictionaryValue();
    290   SET(extension_setting, ExtensionSettingSpecificsToValue);
    291   return value;
    292 }
    293 
    294 base::DictionaryValue* AppSpecificsToValue(
    295     const sync_pb::AppSpecifics& proto) {
    296   base::DictionaryValue* value = new base::DictionaryValue();
    297   SET(extension, ExtensionSpecificsToValue);
    298   SET(notification_settings, AppSettingsToValue);
    299   SET_STR(app_launch_ordinal);
    300   SET_STR(page_ordinal);
    301 
    302   return value;
    303 }
    304 
    305 base::DictionaryValue* AutofillSpecificsToValue(
    306     const sync_pb::AutofillSpecifics& proto) {
    307   base::DictionaryValue* value = new base::DictionaryValue();
    308   SET_STR(name);
    309   SET_STR(value);
    310   SET_INT64_REP(usage_timestamp);
    311   SET(profile, AutofillProfileSpecificsToValue);
    312   return value;
    313 }
    314 
    315 base::DictionaryValue* AutofillProfileSpecificsToValue(
    316     const sync_pb::AutofillProfileSpecifics& proto) {
    317   base::DictionaryValue* value = new base::DictionaryValue();
    318   SET_STR(guid);
    319   SET_STR(origin);
    320 
    321   SET_STR_REP(name_first);
    322   SET_STR_REP(name_middle);
    323   SET_STR_REP(name_last);
    324   SET_STR_REP(email_address);
    325   SET_STR(company_name);
    326 
    327   SET_STR(address_home_line1);
    328   SET_STR(address_home_line2);
    329   SET_STR(address_home_city);
    330   SET_STR(address_home_state);
    331   SET_STR(address_home_zip);
    332   SET_STR(address_home_country);
    333 
    334   SET_STR_REP(phone_home_whole_number);
    335   return value;
    336 }
    337 
    338 base::DictionaryValue* BookmarkSpecificsToValue(
    339     const sync_pb::BookmarkSpecifics& proto) {
    340   base::DictionaryValue* value = new base::DictionaryValue();
    341   SET_STR(url);
    342   SET_BYTES(favicon);
    343   SET_STR(title);
    344   SET_INT64(creation_time_us);
    345   SET_STR(icon_url);
    346   return value;
    347 }
    348 
    349 base::DictionaryValue* DeviceInfoSpecificsToValue(
    350     const sync_pb::DeviceInfoSpecifics& proto) {
    351   base::DictionaryValue* value = new base::DictionaryValue();
    352   SET_STR(cache_guid);
    353   SET_STR(client_name);
    354   SET_ENUM(device_type, GetDeviceTypeString);
    355   SET_STR(sync_user_agent);
    356   SET_STR(chrome_version);
    357   return value;
    358 }
    359 
    360 base::DictionaryValue* DictionarySpecificsToValue(
    361     const sync_pb::DictionarySpecifics& proto) {
    362   base::DictionaryValue* value = new base::DictionaryValue();
    363   SET_STR(word);
    364   return value;
    365 }
    366 
    367 namespace {
    368 
    369 base::DictionaryValue* FaviconSyncFlagsToValue(
    370     const sync_pb::FaviconSyncFlags& proto) {
    371   base::DictionaryValue* value = new base::DictionaryValue();
    372   SET_BOOL(enabled);
    373   SET_INT32(favicon_sync_limit);
    374   return value;
    375 }
    376 
    377 }  // namespace
    378 
    379 base::DictionaryValue* ExperimentsSpecificsToValue(
    380     const sync_pb::ExperimentsSpecifics& proto) {
    381   base::DictionaryValue* value = new base::DictionaryValue();
    382   SET_EXPERIMENT_ENABLED_FIELD(keystore_encryption);
    383   SET_EXPERIMENT_ENABLED_FIELD(history_delete_directives);
    384   SET_EXPERIMENT_ENABLED_FIELD(autofill_culling);
    385   SET_EXPERIMENT_ENABLED_FIELD(pre_commit_update_avoidance);
    386   if (proto.has_favicon_sync())
    387     SET(favicon_sync, FaviconSyncFlagsToValue);
    388   return value;
    389 }
    390 
    391 base::DictionaryValue* ExtensionSettingSpecificsToValue(
    392     const sync_pb::ExtensionSettingSpecifics& proto) {
    393   base::DictionaryValue* value = new base::DictionaryValue();
    394   SET_STR(extension_id);
    395   SET_STR(key);
    396   SET_STR(value);
    397   return value;
    398 }
    399 
    400 base::DictionaryValue* ExtensionSpecificsToValue(
    401     const sync_pb::ExtensionSpecifics& proto) {
    402   base::DictionaryValue* value = new base::DictionaryValue();
    403   SET_STR(id);
    404   SET_STR(version);
    405   SET_STR(update_url);
    406   SET_BOOL(enabled);
    407   SET_BOOL(incognito_enabled);
    408   SET_STR(name);
    409   return value;
    410 }
    411 
    412 namespace {
    413 base::DictionaryValue* FaviconDataToValue(
    414     const sync_pb::FaviconData& proto) {
    415   base::DictionaryValue* value = new base::DictionaryValue();
    416   SET_BYTES(favicon);
    417   SET_INT32(width);
    418   SET_INT32(height);
    419   return value;
    420 }
    421 }  // namespace
    422 
    423 base::DictionaryValue* FaviconImageSpecificsToValue(
    424     const sync_pb::FaviconImageSpecifics& proto) {
    425   base::DictionaryValue* value = new base::DictionaryValue();
    426   SET_STR(favicon_url);
    427   SET(favicon_web, FaviconDataToValue);
    428   SET(favicon_web_32, FaviconDataToValue);
    429   SET(favicon_touch_64, FaviconDataToValue);
    430   SET(favicon_touch_precomposed_64, FaviconDataToValue);
    431   return value;
    432 }
    433 
    434 base::DictionaryValue* FaviconTrackingSpecificsToValue(
    435     const sync_pb::FaviconTrackingSpecifics& proto) {
    436   base::DictionaryValue* value = new base::DictionaryValue();
    437   SET_STR(favicon_url);
    438   SET_INT64(last_visit_time_ms)
    439   SET_BOOL(is_bookmarked);
    440   return value;
    441 }
    442 
    443 base::DictionaryValue* HistoryDeleteDirectiveSpecificsToValue(
    444     const sync_pb::HistoryDeleteDirectiveSpecifics& proto) {
    445   base::DictionaryValue* value = new base::DictionaryValue();
    446   SET(global_id_directive, GlobalIdDirectiveToValue);
    447   SET(time_range_directive, TimeRangeDirectiveToValue);
    448   return value;
    449 }
    450 
    451 base::DictionaryValue* ManagedUserSettingSpecificsToValue(
    452     const sync_pb::ManagedUserSettingSpecifics& proto) {
    453   base::DictionaryValue* value = new base::DictionaryValue();
    454   SET_STR(name);
    455   SET_STR(value);
    456   return value;
    457 }
    458 
    459 base::DictionaryValue* ManagedUserSpecificsToValue(
    460     const sync_pb::ManagedUserSpecifics& proto) {
    461   base::DictionaryValue* value = new base::DictionaryValue();
    462   SET_STR(id);
    463   SET_STR(name);
    464   SET_BOOL(acknowledged);
    465   return value;
    466 }
    467 
    468 base::DictionaryValue* NigoriSpecificsToValue(
    469     const sync_pb::NigoriSpecifics& proto) {
    470   base::DictionaryValue* value = new base::DictionaryValue();
    471   SET(encryption_keybag, EncryptedDataToValue);
    472   SET_BOOL(keybag_is_frozen);
    473   SET_BOOL(encrypt_bookmarks);
    474   SET_BOOL(encrypt_preferences);
    475   SET_BOOL(encrypt_autofill_profile);
    476   SET_BOOL(encrypt_autofill);
    477   SET_BOOL(encrypt_themes);
    478   SET_BOOL(encrypt_typed_urls);
    479   SET_BOOL(encrypt_extension_settings);
    480   SET_BOOL(encrypt_extensions);
    481   SET_BOOL(encrypt_sessions);
    482   SET_BOOL(encrypt_app_settings);
    483   SET_BOOL(encrypt_apps);
    484   SET_BOOL(encrypt_search_engines);
    485   SET_BOOL(encrypt_dictionary);
    486   SET_BOOL(encrypt_everything);
    487   SET_BOOL(sync_tab_favicons);
    488   SET_ENUM(passphrase_type, PassphraseTypeString);
    489   SET(keystore_decryptor_token, EncryptedDataToValue);
    490   SET_INT64(keystore_migration_time);
    491   SET_INT64(custom_passphrase_time);
    492   return value;
    493 }
    494 
    495 base::DictionaryValue* PasswordSpecificsToValue(
    496     const sync_pb::PasswordSpecifics& proto) {
    497   base::DictionaryValue* value = new base::DictionaryValue();
    498   SET(encrypted, EncryptedDataToValue);
    499   return value;
    500 }
    501 
    502 base::DictionaryValue* PreferenceSpecificsToValue(
    503     const sync_pb::PreferenceSpecifics& proto) {
    504   base::DictionaryValue* value = new base::DictionaryValue();
    505   SET_STR(name);
    506   SET_STR(value);
    507   return value;
    508 }
    509 
    510 base::DictionaryValue* PriorityPreferenceSpecificsToValue(
    511     const sync_pb::PriorityPreferenceSpecifics& specifics) {
    512   base::DictionaryValue* value = new base::DictionaryValue();
    513   SET_FIELD(preference, PreferenceSpecificsToValue);
    514   return value;
    515 }
    516 
    517 base::DictionaryValue* SyncedNotificationSpecificsToValue(
    518     const sync_pb::SyncedNotificationSpecifics& proto) {
    519   // There is a lot of data, for now just use heading, description, key, and
    520   // the read state.
    521   // TODO(petewil): Eventually add more data here.
    522   base::DictionaryValue* value = new base::DictionaryValue();
    523   SET(coalesced_notification, CoalescedNotificationToValue);
    524   return value;
    525 }
    526 
    527 base::DictionaryValue* SearchEngineSpecificsToValue(
    528     const sync_pb::SearchEngineSpecifics& proto) {
    529   base::DictionaryValue* value = new base::DictionaryValue();
    530   SET_STR(short_name);
    531   SET_STR(keyword);
    532   SET_STR(favicon_url);
    533   SET_STR(url);
    534   SET_BOOL(safe_for_autoreplace);
    535   SET_STR(originating_url);
    536   SET_INT64(date_created);
    537   SET_STR(input_encodings);
    538   SET_BOOL(show_in_default_list);
    539   SET_STR(suggestions_url);
    540   SET_INT32(prepopulate_id);
    541   SET_BOOL(autogenerate_keyword);
    542   SET_STR(instant_url);
    543   SET_INT64(last_modified);
    544   SET_STR(sync_guid);
    545   SET_STR_REP(alternate_urls);
    546   SET_STR(search_terms_replacement_key);
    547   SET_STR(image_url);
    548   SET_STR(search_url_post_params);
    549   SET_STR(suggestions_url_post_params);
    550   SET_STR(instant_url_post_params);
    551   SET_STR(image_url_post_params);
    552   return value;
    553 }
    554 
    555 base::DictionaryValue* SessionSpecificsToValue(
    556     const sync_pb::SessionSpecifics& proto) {
    557   base::DictionaryValue* value = new base::DictionaryValue();
    558   SET_STR(session_tag);
    559   SET(header, SessionHeaderToValue);
    560   SET(tab, SessionTabToValue);
    561   SET_INT32(tab_node_id);
    562   return value;
    563 }
    564 
    565 base::DictionaryValue* ThemeSpecificsToValue(
    566     const sync_pb::ThemeSpecifics& proto) {
    567   base::DictionaryValue* value = new base::DictionaryValue();
    568   SET_BOOL(use_custom_theme);
    569   SET_BOOL(use_system_theme_by_default);
    570   SET_STR(custom_theme_name);
    571   SET_STR(custom_theme_id);
    572   SET_STR(custom_theme_update_url);
    573   return value;
    574 }
    575 
    576 base::DictionaryValue* TypedUrlSpecificsToValue(
    577     const sync_pb::TypedUrlSpecifics& proto) {
    578   base::DictionaryValue* value = new base::DictionaryValue();
    579   SET_STR(url);
    580   SET_STR(title);
    581   SET_BOOL(hidden);
    582   SET_INT64_REP(visits);
    583   SET_INT32_REP(visit_transitions);
    584   return value;
    585 }
    586 
    587 base::DictionaryValue* EntitySpecificsToValue(
    588     const sync_pb::EntitySpecifics& specifics) {
    589   base::DictionaryValue* value = new base::DictionaryValue();
    590   SET_FIELD(app, AppSpecificsToValue);
    591   SET_FIELD(app_notification, AppNotificationToValue);
    592   SET_FIELD(app_setting, AppSettingSpecificsToValue);
    593   SET_FIELD(autofill, AutofillSpecificsToValue);
    594   SET_FIELD(autofill_profile, AutofillProfileSpecificsToValue);
    595   SET_FIELD(bookmark, BookmarkSpecificsToValue);
    596   SET_FIELD(device_info, DeviceInfoSpecificsToValue);
    597   SET_FIELD(dictionary, DictionarySpecificsToValue);
    598   SET_FIELD(experiments, ExperimentsSpecificsToValue);
    599   SET_FIELD(extension, ExtensionSpecificsToValue);
    600   SET_FIELD(extension_setting, ExtensionSettingSpecificsToValue);
    601   SET_FIELD(favicon_image, FaviconImageSpecificsToValue);
    602   SET_FIELD(favicon_tracking, FaviconTrackingSpecificsToValue);
    603   SET_FIELD(history_delete_directive, HistoryDeleteDirectiveSpecificsToValue);
    604   SET_FIELD(managed_user_setting, ManagedUserSettingSpecificsToValue);
    605   SET_FIELD(managed_user, ManagedUserSpecificsToValue);
    606   SET_FIELD(nigori, NigoriSpecificsToValue);
    607   SET_FIELD(password, PasswordSpecificsToValue);
    608   SET_FIELD(preference, PreferenceSpecificsToValue);
    609   SET_FIELD(priority_preference, PriorityPreferenceSpecificsToValue);
    610   SET_FIELD(search_engine, SearchEngineSpecificsToValue);
    611   SET_FIELD(session, SessionSpecificsToValue);
    612   SET_FIELD(synced_notification, SyncedNotificationSpecificsToValue);
    613   SET_FIELD(theme, ThemeSpecificsToValue);
    614   SET_FIELD(typed_url, TypedUrlSpecificsToValue);
    615   return value;
    616 }
    617 
    618 namespace {
    619 
    620 base::StringValue* UniquePositionToStringValue(
    621     const sync_pb::UniquePosition& proto) {
    622   UniquePosition pos = UniquePosition::FromProto(proto);
    623   return new base::StringValue(pos.ToDebugString());
    624 }
    625 
    626 base::DictionaryValue* SyncEntityToValue(const sync_pb::SyncEntity& proto,
    627                                          bool include_specifics) {
    628   base::DictionaryValue* value = new base::DictionaryValue();
    629   SET_STR(id_string);
    630   SET_STR(parent_id_string);
    631   SET_STR(old_parent_id);
    632   SET_INT64(version);
    633   SET_INT64(mtime);
    634   SET_INT64(ctime);
    635   SET_STR(name);
    636   SET_STR(non_unique_name);
    637   SET_INT64(sync_timestamp);
    638   SET_STR(server_defined_unique_tag);
    639   SET_INT64(position_in_parent);
    640   SET(unique_position, UniquePositionToStringValue);
    641   SET_STR(insert_after_item_id);
    642   SET_BOOL(deleted);
    643   SET_STR(originator_cache_guid);
    644   SET_STR(originator_client_item_id);
    645   if (include_specifics)
    646     SET(specifics, EntitySpecificsToValue);
    647   SET_BOOL(folder);
    648   SET_STR(client_defined_unique_tag);
    649   return value;
    650 }
    651 
    652 base::ListValue* SyncEntitiesToValue(
    653     const ::google::protobuf::RepeatedPtrField<sync_pb::SyncEntity>& entities,
    654     bool include_specifics) {
    655   base::ListValue* list = new base::ListValue();
    656   ::google::protobuf::RepeatedPtrField<sync_pb::SyncEntity>::const_iterator it;
    657   for (it = entities.begin(); it != entities.end(); ++it) {
    658     list->Append(SyncEntityToValue(*it, include_specifics));
    659   }
    660 
    661   return list;
    662 }
    663 
    664 base::DictionaryValue* ChromiumExtensionActivityToValue(
    665     const sync_pb::ChromiumExtensionsActivity& proto) {
    666   base::DictionaryValue* value = new base::DictionaryValue();
    667   SET_STR(extension_id);
    668   SET_INT32(bookmark_writes_since_last_commit);
    669   return value;
    670 }
    671 
    672 base::DictionaryValue* CommitMessageToValue(
    673     const sync_pb::CommitMessage& proto,
    674     bool include_specifics) {
    675   base::DictionaryValue* value = new base::DictionaryValue();
    676   value->Set("entries",
    677              SyncEntitiesToValue(proto.entries(), include_specifics));
    678   SET_STR(cache_guid);
    679   SET_REP(extensions_activity, ChromiumExtensionActivityToValue);
    680   SET(config_params, ClientConfigParamsToValue);
    681   return value;
    682 }
    683 
    684 base::DictionaryValue* GetUpdateTriggersToValue(
    685     const sync_pb::GetUpdateTriggers& proto) {
    686   base::DictionaryValue* value = new base::DictionaryValue();
    687   SET_STR_REP(notification_hint);
    688   SET_BOOL(client_dropped_hints);
    689   SET_BOOL(invalidations_out_of_sync);
    690   SET_INT64(local_modification_nudges);
    691   SET_INT64(datatype_refresh_nudges);
    692   return value;
    693 }
    694 
    695 base::DictionaryValue* DataTypeProgressMarkerToValue(
    696     const sync_pb::DataTypeProgressMarker& proto) {
    697   base::DictionaryValue* value = new base::DictionaryValue();
    698   SET_INT32(data_type_id);
    699   SET_BYTES(token);
    700   SET_INT64(timestamp_token_for_migration);
    701   SET_STR(notification_hint);
    702   SET(get_update_triggers, GetUpdateTriggersToValue);
    703   return value;
    704 }
    705 
    706 base::DictionaryValue* GetUpdatesCallerInfoToValue(
    707     const sync_pb::GetUpdatesCallerInfo& proto) {
    708   base::DictionaryValue* value = new base::DictionaryValue();
    709   SET_ENUM(source, GetUpdatesSourceString);
    710   SET_BOOL(notifications_enabled);
    711   return value;
    712 }
    713 
    714 base::DictionaryValue* GetUpdatesMessageToValue(
    715     const sync_pb::GetUpdatesMessage& proto) {
    716   base::DictionaryValue* value = new base::DictionaryValue();
    717   SET(caller_info, GetUpdatesCallerInfoToValue);
    718   SET_BOOL(fetch_folders);
    719   SET_INT32(batch_size);
    720   SET_REP(from_progress_marker, DataTypeProgressMarkerToValue);
    721   SET_BOOL(streaming);
    722   SET_BOOL(need_encryption_key);
    723   SET_BOOL(create_mobile_bookmarks_folder);
    724   SET_ENUM(get_updates_origin, GetUpdatesOriginString);
    725   return value;
    726 }
    727 
    728 base::DictionaryValue* ClientStatusToValue(const sync_pb::ClientStatus& proto) {
    729   base::DictionaryValue* value = new base::DictionaryValue();
    730   SET_BOOL(hierarchy_conflict_detected);
    731   return value;
    732 }
    733 
    734 base::DictionaryValue* EntryResponseToValue(
    735     const sync_pb::CommitResponse::EntryResponse& proto) {
    736   base::DictionaryValue* value = new base::DictionaryValue();
    737   SET_ENUM(response_type, GetResponseTypeString);
    738   SET_STR(id_string);
    739   SET_STR(parent_id_string);
    740   SET_INT64(position_in_parent);
    741   SET_INT64(version);
    742   SET_STR(name);
    743   SET_STR(error_message);
    744   SET_INT64(mtime);
    745   return value;
    746 }
    747 
    748 base::DictionaryValue* CommitResponseToValue(
    749     const sync_pb::CommitResponse& proto) {
    750   base::DictionaryValue* value = new base::DictionaryValue();
    751   SET_REP(entryresponse, EntryResponseToValue);
    752   return value;
    753 }
    754 
    755 base::DictionaryValue* GetUpdatesResponseToValue(
    756     const sync_pb::GetUpdatesResponse& proto,
    757     bool include_specifics) {
    758   base::DictionaryValue* value = new base::DictionaryValue();
    759   value->Set("entries",
    760              SyncEntitiesToValue(proto.entries(), include_specifics));
    761   SET_INT64(changes_remaining);
    762   SET_REP(new_progress_marker, DataTypeProgressMarkerToValue);
    763   return value;
    764 }
    765 
    766 base::DictionaryValue* ClientCommandToValue(
    767     const sync_pb::ClientCommand& proto) {
    768   base::DictionaryValue* value = new base::DictionaryValue();
    769   SET_INT32(set_sync_poll_interval);
    770   SET_INT32(set_sync_long_poll_interval);
    771   SET_INT32(max_commit_batch_size);
    772   SET_INT32(sessions_commit_delay_seconds);
    773   SET_INT32(throttle_delay_seconds);
    774   SET_INT32(client_invalidation_hint_buffer_size);
    775   return value;
    776 }
    777 
    778 base::DictionaryValue* ErrorToValue(
    779     const sync_pb::ClientToServerResponse::Error& proto) {
    780   base::DictionaryValue* value = new base::DictionaryValue();
    781   SET_ENUM(error_type, GetErrorTypeString);
    782   SET_STR(error_description);
    783   SET_STR(url);
    784   SET_ENUM(action, GetActionString);
    785   return value;
    786 }
    787 
    788 }  // namespace
    789 
    790 base::DictionaryValue* ClientToServerResponseToValue(
    791     const sync_pb::ClientToServerResponse& proto,
    792     bool include_specifics) {
    793   base::DictionaryValue* value = new base::DictionaryValue();
    794   SET(commit, CommitResponseToValue);
    795   if (proto.has_get_updates()) {
    796     value->Set("get_updates", GetUpdatesResponseToValue(proto.get_updates(),
    797                                                         include_specifics));
    798   }
    799 
    800   SET(error, ErrorToValue);
    801   SET_ENUM(error_code, GetErrorTypeString);
    802   SET_STR(error_message);
    803   SET_STR(store_birthday);
    804   SET(client_command, ClientCommandToValue);
    805   SET_INT32_REP(migrated_data_type_id);
    806   return value;
    807 }
    808 
    809 base::DictionaryValue* ClientToServerMessageToValue(
    810     const sync_pb::ClientToServerMessage& proto,
    811     bool include_specifics) {
    812   base::DictionaryValue* value = new base::DictionaryValue();
    813   SET_STR(share);
    814   SET_INT32(protocol_version);
    815   if (proto.has_commit()) {
    816     value->Set("commit",
    817                CommitMessageToValue(proto.commit(), include_specifics));
    818   }
    819 
    820   SET(get_updates, GetUpdatesMessageToValue);
    821   SET_STR(store_birthday);
    822   SET_BOOL(sync_problem_detected);
    823   SET(debug_info, DebugInfoToValue);
    824   SET(client_status, ClientStatusToValue);
    825   return value;
    826 }
    827 
    828 base::DictionaryValue* DatatypeAssociationStatsToValue(
    829     const sync_pb::DatatypeAssociationStats& proto) {
    830   base::DictionaryValue* value = new base::DictionaryValue();
    831   SET_INT32(data_type_id);
    832   SET_INT32(num_local_items_before_association);
    833   SET_INT32(num_sync_items_before_association);
    834   SET_INT32(num_local_items_after_association);
    835   SET_INT32(num_sync_items_after_association);
    836   SET_INT32(num_local_items_added);
    837   SET_INT32(num_local_items_deleted);
    838   SET_INT32(num_local_items_modified);
    839   SET_INT32(num_sync_items_added);
    840   SET_INT32(num_sync_items_deleted);
    841   SET_INT32(num_sync_items_modified);
    842   SET_INT64(local_version_pre_association);
    843   SET_INT64(sync_version_pre_association)
    844   SET_BOOL(had_error);
    845   SET_INT64(download_wait_time_us);
    846   SET_INT64(download_time_us);
    847   SET_INT64(association_wait_time_for_high_priority_us);
    848   SET_INT64(association_wait_time_for_same_priority_us);
    849   return value;
    850 }
    851 
    852 base::DictionaryValue* DebugEventInfoToValue(
    853     const sync_pb::DebugEventInfo& proto) {
    854   base::DictionaryValue* value = new base::DictionaryValue();
    855   SET_ENUM(singleton_event, SingletonEventTypeString);
    856   SET(sync_cycle_completed_event_info, SyncCycleCompletedEventInfoToValue);
    857   SET_INT32(nudging_datatype);
    858   SET_INT32_REP(datatypes_notified_from_server);
    859   SET(datatype_association_stats, DatatypeAssociationStatsToValue);
    860   return value;
    861 }
    862 
    863 base::DictionaryValue* DebugInfoToValue(const sync_pb::DebugInfo& proto) {
    864   base::DictionaryValue* value = new base::DictionaryValue();
    865   SET_REP(events, DebugEventInfoToValue);
    866   SET_BOOL(cryptographer_ready);
    867   SET_BOOL(cryptographer_has_pending_keys);
    868   SET_BOOL(events_dropped);
    869   return value;
    870 }
    871 
    872 base::DictionaryValue* SyncCycleCompletedEventInfoToValue(
    873     const sync_pb::SyncCycleCompletedEventInfo& proto) {
    874   base::DictionaryValue* value = new base::DictionaryValue();
    875   SET_INT32(num_encryption_conflicts);
    876   SET_INT32(num_hierarchy_conflicts);
    877   SET_INT32(num_server_conflicts);
    878   SET_INT32(num_updates_downloaded);
    879   SET_INT32(num_reflected_updates_downloaded);
    880   SET(caller_info, GetUpdatesCallerInfoToValue);
    881   return value;
    882 }
    883 
    884 base::DictionaryValue* ClientConfigParamsToValue(
    885     const sync_pb::ClientConfigParams& proto) {
    886   base::DictionaryValue* value = new base::DictionaryValue();
    887   SET_INT32_REP(enabled_type_ids);
    888   SET_BOOL(tabs_datatype_enabled);
    889   return value;
    890 }
    891 
    892 #undef SET
    893 #undef SET_REP
    894 
    895 #undef SET_BOOL
    896 #undef SET_BYTES
    897 #undef SET_INT32
    898 #undef SET_INT64
    899 #undef SET_INT64_REP
    900 #undef SET_STR
    901 #undef SET_STR_REP
    902 
    903 #undef SET_FIELD
    904 
    905 }  // namespace syncer
    906