1// Copyright (c) 2011 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 "chrome/browser/sync/protocol/proto_value_conversions.h"
8
9#include "base/base64.h"
10#include "base/basictypes.h"
11#include "base/logging.h"
12#include "base/string_number_conversions.h"
13#include "base/values.h"
14#include "chrome/browser/sync/protocol/app_specifics.pb.h"
15#include "chrome/browser/sync/protocol/autofill_specifics.pb.h"
16#include "chrome/browser/sync/protocol/bookmark_specifics.pb.h"
17#include "chrome/browser/sync/protocol/encryption.pb.h"
18#include "chrome/browser/sync/protocol/extension_specifics.pb.h"
19#include "chrome/browser/sync/protocol/nigori_specifics.pb.h"
20#include "chrome/browser/sync/protocol/password_specifics.pb.h"
21#include "chrome/browser/sync/protocol/preference_specifics.pb.h"
22#include "chrome/browser/sync/protocol/proto_enum_conversions.h"
23#include "chrome/browser/sync/protocol/session_specifics.pb.h"
24#include "chrome/browser/sync/protocol/sync.pb.h"
25#include "chrome/browser/sync/protocol/theme_specifics.pb.h"
26#include "chrome/browser/sync/protocol/typed_url_specifics.pb.h"
27
28namespace browser_sync {
29
30namespace {
31
32// Basic Type -> Value functions.
33
34StringValue* MakeInt64Value(int64 x) {
35  return Value::CreateStringValue(base::Int64ToString(x));
36}
37
38// TODO(akalin): Perhaps make JSONWriter support BinaryValue and use
39// that instead of a StringValue.
40StringValue* MakeBytesValue(const std::string& bytes) {
41  std::string bytes_base64;
42  if (!base::Base64Encode(bytes, &bytes_base64)) {
43    NOTREACHED();
44  }
45  return Value::CreateStringValue(bytes_base64);
46}
47
48// T is the enum type.
49template <class T>
50StringValue* MakeEnumValue(T t, const char* (*converter_fn)(T)) {
51  return Value::CreateStringValue(converter_fn(t));
52}
53
54// T is the field type, F is either RepeatedField or RepeatedPtrField,
55// and V is a subclass of Value.
56template <class T, class F, class V>
57ListValue* MakeRepeatedValue(const F& fields, V* (*converter_fn)(T)) {
58  ListValue* list = new ListValue();
59  for (typename F::const_iterator it = fields.begin(); it != fields.end();
60       ++it) {
61    list->Append(converter_fn(*it));
62  }
63  return list;
64}
65
66}  // namespace
67
68// Helper macros to reduce the amount of boilerplate.
69
70#define SET(field, fn) value->Set(#field, fn(proto.field()))
71#define SET_REP(field, fn) \
72  value->Set(#field, MakeRepeatedValue(proto.field(), fn))
73#define SET_ENUM(field, fn) \
74  value->Set(#field, MakeEnumValue(proto.field(), fn))
75
76#define SET_BOOL(field) SET(field, Value::CreateBooleanValue)
77#define SET_BYTES(field) SET(field, MakeBytesValue)
78#define SET_INT32(field) SET(field, MakeInt64Value)
79#define SET_INT32_REP(field) SET_REP(field, MakeInt64Value)
80#define SET_INT64(field) SET(field, MakeInt64Value)
81#define SET_INT64_REP(field) SET_REP(field, MakeInt64Value)
82#define SET_STR(field) SET(field, Value::CreateStringValue)
83
84#define SET_EXTENSION(ns, field, fn)                                    \
85  do {                                                                  \
86    if (specifics.HasExtension(ns::field)) {                            \
87      value->Set(#field, fn(specifics.GetExtension(ns::field)));        \
88    }                                                                   \
89  } while (0)
90
91// If you add another macro, don't forget to add an #undef at the end
92// of this file, too.
93
94DictionaryValue* EncryptedDataToValue(const sync_pb::EncryptedData& proto) {
95  DictionaryValue* value = new DictionaryValue();
96  SET_STR(key_name);
97  // TODO(akalin): Shouldn't blob be of type bytes instead of string?
98  SET_BYTES(blob);
99  return value;
100}
101
102DictionaryValue* SessionHeaderToValue(
103    const sync_pb::SessionHeader& proto) {
104  DictionaryValue* value = new DictionaryValue();
105  SET_REP(window, SessionWindowToValue);
106  return value;
107}
108
109DictionaryValue* SessionTabToValue(
110    const sync_pb::SessionTab& proto) {
111  DictionaryValue* value = new DictionaryValue();
112  SET_INT32(tab_id);
113  SET_INT32(window_id);
114  SET_INT32(tab_visual_index);
115  SET_INT32(current_navigation_index);
116  SET_BOOL(pinned);
117  SET_STR(extension_app_id);
118  SET_REP(navigation, TabNavigationToValue);
119  return value;
120}
121
122DictionaryValue* SessionWindowToValue(
123    const sync_pb::SessionWindow& proto) {
124  DictionaryValue* value = new DictionaryValue();
125  SET_INT32(window_id);
126  SET_INT32(selected_tab_index);
127  SET_INT32_REP(tab);
128  SET_ENUM(browser_type, GetBrowserTypeString);
129  return value;
130}
131
132DictionaryValue* TabNavigationToValue(
133    const sync_pb::TabNavigation& proto) {
134  DictionaryValue* value = new DictionaryValue();
135  SET_INT32(index);
136  SET_STR(virtual_url);
137  SET_STR(referrer);
138  SET_STR(title);
139  SET_STR(state);
140  SET_ENUM(page_transition, GetPageTransitionString);
141  SET_ENUM(navigation_qualifier, GetPageTransitionQualifierString);
142  return value;
143}
144
145DictionaryValue* PasswordSpecificsDataToValue(
146    const sync_pb::PasswordSpecificsData& proto) {
147  DictionaryValue* value = new DictionaryValue();
148  SET_INT32(scheme);
149  SET_STR(signon_realm);
150  SET_STR(origin);
151  SET_STR(action);
152  SET_STR(username_element);
153  SET_STR(username_value);
154  SET_STR(password_element);
155  value->SetString("password_value", "<redacted>");
156  SET_BOOL(ssl_valid);
157  SET_BOOL(preferred);
158  SET_INT64(date_created);
159  SET_BOOL(blacklisted);
160  return value;
161}
162
163DictionaryValue* AppSpecificsToValue(
164    const sync_pb::AppSpecifics& proto) {
165  DictionaryValue* value = new DictionaryValue();
166  SET(extension, ExtensionSpecificsToValue);
167  return value;
168}
169
170DictionaryValue* AutofillSpecificsToValue(
171    const sync_pb::AutofillSpecifics& proto) {
172  DictionaryValue* value = new DictionaryValue();
173  SET_STR(name);
174  SET_STR(value);
175  SET_INT64_REP(usage_timestamp);
176  SET(profile, AutofillProfileSpecificsToValue);
177  SET_BYTES(encrypted_credit_card);
178  SET(credit_card, AutofillCreditCardSpecificsToValue);
179  return value;
180}
181
182DictionaryValue* AutofillCreditCardSpecificsToValue(
183    const sync_pb::AutofillCreditCardSpecifics& proto) {
184  DictionaryValue* value = new DictionaryValue();
185  SET_STR(label);
186  SET_STR(name_on_card);
187  SET_STR(type);
188  SET_STR(card_number);
189  SET_STR(expiration_month);
190  SET_STR(expiration_year);
191  SET_STR(verification_code);
192  SET_STR(billing_address);
193  SET_STR(shipping_address);
194  return value;
195}
196
197DictionaryValue* AutofillProfileSpecificsToValue(
198    const sync_pb::AutofillProfileSpecifics& proto) {
199  DictionaryValue* value = new DictionaryValue();
200  SET_STR(label);
201  SET_STR(guid);
202
203  SET_STR(name_first);
204  SET_STR(name_middle);
205  SET_STR(name_last);
206  SET_STR(email_address);
207  SET_STR(company_name);
208
209  SET_STR(address_home_line1);
210  SET_STR(address_home_line2);
211  SET_STR(address_home_city);
212  SET_STR(address_home_state);
213  SET_STR(address_home_zip);
214  SET_STR(address_home_country);
215
216  SET_STR(phone_home_whole_number);
217  SET_STR(phone_fax_whole_number);
218  return value;
219}
220
221DictionaryValue* BookmarkSpecificsToValue(
222    const sync_pb::BookmarkSpecifics& proto) {
223  DictionaryValue* value = new DictionaryValue();
224  SET_STR(url);
225  SET_BYTES(favicon);
226  return value;
227}
228
229DictionaryValue* ExtensionSpecificsToValue(
230    const sync_pb::ExtensionSpecifics& proto) {
231  DictionaryValue* value = new DictionaryValue();
232  SET_STR(id);
233  SET_STR(version);
234  SET_STR(update_url);
235  SET_BOOL(enabled);
236  SET_BOOL(incognito_enabled);
237  SET_STR(name);
238  return value;
239}
240
241DictionaryValue* NigoriSpecificsToValue(
242    const sync_pb::NigoriSpecifics& proto) {
243  DictionaryValue* value = new DictionaryValue();
244  SET(encrypted, EncryptedDataToValue);
245  SET_BOOL(using_explicit_passphrase);
246  return value;
247}
248
249DictionaryValue* PasswordSpecificsToValue(
250    const sync_pb::PasswordSpecifics& proto) {
251  DictionaryValue* value = new DictionaryValue();
252  SET(encrypted, EncryptedDataToValue);
253  return value;
254}
255
256DictionaryValue* PreferenceSpecificsToValue(
257    const sync_pb::PreferenceSpecifics& proto) {
258  DictionaryValue* value = new DictionaryValue();
259  SET_STR(name);
260  SET_STR(value);
261  return value;
262}
263
264DictionaryValue* SessionSpecificsToValue(
265    const sync_pb::SessionSpecifics& proto) {
266  DictionaryValue* value = new DictionaryValue();
267  SET_STR(session_tag);
268  SET(header, SessionHeaderToValue);
269  SET(tab, SessionTabToValue);
270  return value;
271}
272
273DictionaryValue* ThemeSpecificsToValue(
274    const sync_pb::ThemeSpecifics& proto) {
275  DictionaryValue* value = new DictionaryValue();
276  SET_BOOL(use_custom_theme);
277  SET_BOOL(use_system_theme_by_default);
278  SET_STR(custom_theme_name);
279  SET_STR(custom_theme_id);
280  SET_STR(custom_theme_update_url);
281  return value;
282}
283
284DictionaryValue* TypedUrlSpecificsToValue(
285    const sync_pb::TypedUrlSpecifics& proto) {
286  DictionaryValue* value = new DictionaryValue();
287  SET_STR(url);
288  SET_STR(title);
289  SET_INT32(typed_count);
290  SET_BOOL(hidden);
291  SET_INT64_REP(visit);
292  return value;
293}
294
295DictionaryValue* EntitySpecificsToValue(
296    const sync_pb::EntitySpecifics& specifics) {
297  DictionaryValue* value = new DictionaryValue();
298  SET_EXTENSION(sync_pb, app, AppSpecificsToValue);
299  SET_EXTENSION(sync_pb, autofill, AutofillSpecificsToValue);
300  SET_EXTENSION(sync_pb, autofill_profile, AutofillProfileSpecificsToValue);
301  SET_EXTENSION(sync_pb, bookmark, BookmarkSpecificsToValue);
302  SET_EXTENSION(sync_pb, extension, ExtensionSpecificsToValue);
303  SET_EXTENSION(sync_pb, nigori, NigoriSpecificsToValue);
304  SET_EXTENSION(sync_pb, password, PasswordSpecificsToValue);
305  SET_EXTENSION(sync_pb, preference, PreferenceSpecificsToValue);
306  SET_EXTENSION(sync_pb, session, SessionSpecificsToValue);
307  SET_EXTENSION(sync_pb, theme, ThemeSpecificsToValue);
308  SET_EXTENSION(sync_pb, typed_url, TypedUrlSpecificsToValue);
309  return value;
310}
311
312#undef SET
313#undef SET_REP
314
315#undef SET_BOOL
316#undef SET_BYTES
317#undef SET_INT32
318#undef SET_INT64
319#undef SET_INT64_REP
320#undef SET_STR
321
322#undef SET_EXTENSION
323
324}  // namespace browser_sync
325