// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// 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 "chrome/browser/sync/protocol/proto_value_conversions.h"
#include "base/base64.h"
#include "base/basictypes.h"
#include "base/logging.h"
#include "base/string_number_conversions.h"
#include "base/values.h"
#include "chrome/browser/sync/protocol/app_specifics.pb.h"
#include "chrome/browser/sync/protocol/autofill_specifics.pb.h"
#include "chrome/browser/sync/protocol/bookmark_specifics.pb.h"
#include "chrome/browser/sync/protocol/encryption.pb.h"
#include "chrome/browser/sync/protocol/extension_specifics.pb.h"
#include "chrome/browser/sync/protocol/nigori_specifics.pb.h"
#include "chrome/browser/sync/protocol/password_specifics.pb.h"
#include "chrome/browser/sync/protocol/preference_specifics.pb.h"
#include "chrome/browser/sync/protocol/proto_enum_conversions.h"
#include "chrome/browser/sync/protocol/session_specifics.pb.h"
#include "chrome/browser/sync/protocol/sync.pb.h"
#include "chrome/browser/sync/protocol/theme_specifics.pb.h"
#include "chrome/browser/sync/protocol/typed_url_specifics.pb.h"
namespace browser_sync {
namespace {
// Basic Type -> Value functions.
StringValue* MakeInt64Value(int64 x) {
return Value::CreateStringValue(base::Int64ToString(x));
}
// TODO(akalin): Perhaps make JSONWriter support BinaryValue and use
// that instead of a StringValue.
StringValue* MakeBytesValue(const std::string& bytes) {
std::string bytes_base64;
if (!base::Base64Encode(bytes, &bytes_base64)) {
NOTREACHED();
}
return Value::CreateStringValue(bytes_base64);
}
// T is the enum type.
template <class T>
StringValue* MakeEnumValue(T t, const char* (*converter_fn)(T)) {
return Value::CreateStringValue(converter_fn(t));
}
// T is the field type, F is either RepeatedField or RepeatedPtrField,
// and V is a subclass of Value.
template <class T, class F, class V>
ListValue* MakeRepeatedValue(const F& fields, V* (*converter_fn)(T)) {
ListValue* list = new ListValue();
for (typename F::const_iterator it = fields.begin(); it != fields.end();
++it) {
list->Append(converter_fn(*it));
}
return list;
}
} // namespace
// Helper macros to reduce the amount of boilerplate.
#define SET(field, fn) value->Set(#field, fn(proto.field()))
#define SET_REP(field, fn) \
value->Set(#field, MakeRepeatedValue(proto.field(), fn))
#define SET_ENUM(field, fn) \
value->Set(#field, MakeEnumValue(proto.field(), fn))
#define SET_BOOL(field) SET(field, Value::CreateBooleanValue)
#define SET_BYTES(field) SET(field, MakeBytesValue)
#define SET_INT32(field) SET(field, MakeInt64Value)
#define SET_INT32_REP(field) SET_REP(field, MakeInt64Value)
#define SET_INT64(field) SET(field, MakeInt64Value)
#define SET_INT64_REP(field) SET_REP(field, MakeInt64Value)
#define SET_STR(field) SET(field, Value::CreateStringValue)
#define SET_EXTENSION(ns, field, fn) \
do { \
if (specifics.HasExtension(ns::field)) { \
value->Set(#field, fn(specifics.GetExtension(ns::field))); \
} \
} while (0)
// If you add another macro, don't forget to add an #undef at the end
// of this file, too.
DictionaryValue* EncryptedDataToValue(const sync_pb::EncryptedData& proto) {
DictionaryValue* value = new DictionaryValue();
SET_STR(key_name);
// TODO(akalin): Shouldn't blob be of type bytes instead of string?
SET_BYTES(blob);
return value;
}
DictionaryValue* SessionHeaderToValue(
const sync_pb::SessionHeader& proto) {
DictionaryValue* value = new DictionaryValue();
SET_REP(window, SessionWindowToValue);
return value;
}
DictionaryValue* SessionTabToValue(
const sync_pb::SessionTab& proto) {
DictionaryValue* value = new DictionaryValue();
SET_INT32(tab_id);
SET_INT32(window_id);
SET_INT32(tab_visual_index);
SET_INT32(current_navigation_index);
SET_BOOL(pinned);
SET_STR(extension_app_id);
SET_REP(navigation, TabNavigationToValue);
return value;
}
DictionaryValue* SessionWindowToValue(
const sync_pb::SessionWindow& proto) {
DictionaryValue* value = new DictionaryValue();
SET_INT32(window_id);
SET_INT32(selected_tab_index);
SET_INT32_REP(tab);
SET_ENUM(browser_type, GetBrowserTypeString);
return value;
}
DictionaryValue* TabNavigationToValue(
const sync_pb::TabNavigation& proto) {
DictionaryValue* value = new DictionaryValue();
SET_INT32(index);
SET_STR(virtual_url);
SET_STR(referrer);
SET_STR(title);
SET_STR(state);
SET_ENUM(page_transition, GetPageTransitionString);
SET_ENUM(navigation_qualifier, GetPageTransitionQualifierString);
return value;
}
DictionaryValue* PasswordSpecificsDataToValue(
const sync_pb::PasswordSpecificsData& proto) {
DictionaryValue* value = new DictionaryValue();
SET_INT32(scheme);
SET_STR(signon_realm);
SET_STR(origin);
SET_STR(action);
SET_STR(username_element);
SET_STR(username_value);
SET_STR(password_element);
value->SetString("password_value", "<redacted>");
SET_BOOL(ssl_valid);
SET_BOOL(preferred);
SET_INT64(date_created);
SET_BOOL(blacklisted);
return value;
}
DictionaryValue* AppSpecificsToValue(
const sync_pb::AppSpecifics& proto) {
DictionaryValue* value = new DictionaryValue();
SET(extension, ExtensionSpecificsToValue);
return value;
}
DictionaryValue* AutofillSpecificsToValue(
const sync_pb::AutofillSpecifics& proto) {
DictionaryValue* value = new DictionaryValue();
SET_STR(name);
SET_STR(value);
SET_INT64_REP(usage_timestamp);
SET(profile, AutofillProfileSpecificsToValue);
SET_BYTES(encrypted_credit_card);
SET(credit_card, AutofillCreditCardSpecificsToValue);
return value;
}
DictionaryValue* AutofillCreditCardSpecificsToValue(
const sync_pb::AutofillCreditCardSpecifics& proto) {
DictionaryValue* value = new DictionaryValue();
SET_STR(label);
SET_STR(name_on_card);
SET_STR(type);
SET_STR(card_number);
SET_STR(expiration_month);
SET_STR(expiration_year);
SET_STR(verification_code);
SET_STR(billing_address);
SET_STR(shipping_address);
return value;
}
DictionaryValue* AutofillProfileSpecificsToValue(
const sync_pb::AutofillProfileSpecifics& proto) {
DictionaryValue* value = new DictionaryValue();
SET_STR(label);
SET_STR(guid);
SET_STR(name_first);
SET_STR(name_middle);
SET_STR(name_last);
SET_STR(email_address);
SET_STR(company_name);
SET_STR(address_home_line1);
SET_STR(address_home_line2);
SET_STR(address_home_city);
SET_STR(address_home_state);
SET_STR(address_home_zip);
SET_STR(address_home_country);
SET_STR(phone_home_whole_number);
SET_STR(phone_fax_whole_number);
return value;
}
DictionaryValue* BookmarkSpecificsToValue(
const sync_pb::BookmarkSpecifics& proto) {
DictionaryValue* value = new DictionaryValue();
SET_STR(url);
SET_BYTES(favicon);
return value;
}
DictionaryValue* ExtensionSpecificsToValue(
const sync_pb::ExtensionSpecifics& proto) {
DictionaryValue* value = new DictionaryValue();
SET_STR(id);
SET_STR(version);
SET_STR(update_url);
SET_BOOL(enabled);
SET_BOOL(incognito_enabled);
SET_STR(name);
return value;
}
DictionaryValue* NigoriSpecificsToValue(
const sync_pb::NigoriSpecifics& proto) {
DictionaryValue* value = new DictionaryValue();
SET(encrypted, EncryptedDataToValue);
SET_BOOL(using_explicit_passphrase);
return value;
}
DictionaryValue* PasswordSpecificsToValue(
const sync_pb::PasswordSpecifics& proto) {
DictionaryValue* value = new DictionaryValue();
SET(encrypted, EncryptedDataToValue);
return value;
}
DictionaryValue* PreferenceSpecificsToValue(
const sync_pb::PreferenceSpecifics& proto) {
DictionaryValue* value = new DictionaryValue();
SET_STR(name);
SET_STR(value);
return value;
}
DictionaryValue* SessionSpecificsToValue(
const sync_pb::SessionSpecifics& proto) {
DictionaryValue* value = new DictionaryValue();
SET_STR(session_tag);
SET(header, SessionHeaderToValue);
SET(tab, SessionTabToValue);
return value;
}
DictionaryValue* ThemeSpecificsToValue(
const sync_pb::ThemeSpecifics& proto) {
DictionaryValue* value = new DictionaryValue();
SET_BOOL(use_custom_theme);
SET_BOOL(use_system_theme_by_default);
SET_STR(custom_theme_name);
SET_STR(custom_theme_id);
SET_STR(custom_theme_update_url);
return value;
}
DictionaryValue* TypedUrlSpecificsToValue(
const sync_pb::TypedUrlSpecifics& proto) {
DictionaryValue* value = new DictionaryValue();
SET_STR(url);
SET_STR(title);
SET_INT32(typed_count);
SET_BOOL(hidden);
SET_INT64_REP(visit);
return value;
}
DictionaryValue* EntitySpecificsToValue(
const sync_pb::EntitySpecifics& specifics) {
DictionaryValue* value = new DictionaryValue();
SET_EXTENSION(sync_pb, app, AppSpecificsToValue);
SET_EXTENSION(sync_pb, autofill, AutofillSpecificsToValue);
SET_EXTENSION(sync_pb, autofill_profile, AutofillProfileSpecificsToValue);
SET_EXTENSION(sync_pb, bookmark, BookmarkSpecificsToValue);
SET_EXTENSION(sync_pb, extension, ExtensionSpecificsToValue);
SET_EXTENSION(sync_pb, nigori, NigoriSpecificsToValue);
SET_EXTENSION(sync_pb, password, PasswordSpecificsToValue);
SET_EXTENSION(sync_pb, preference, PreferenceSpecificsToValue);
SET_EXTENSION(sync_pb, session, SessionSpecificsToValue);
SET_EXTENSION(sync_pb, theme, ThemeSpecificsToValue);
SET_EXTENSION(sync_pb, typed_url, TypedUrlSpecificsToValue);
return value;
}
#undef SET
#undef SET_REP
#undef SET_BOOL
#undef SET_BYTES
#undef SET_INT32
#undef SET_INT64
#undef SET_INT64_REP
#undef SET_STR
#undef SET_EXTENSION
} // namespace browser_sync