summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/sync/protocol/app_specifics.proto3
-rw-r--r--chrome/browser/sync/protocol/autofill_specifics.proto3
-rw-r--r--chrome/browser/sync/protocol/bookmark_specifics.proto3
-rw-r--r--chrome/browser/sync/protocol/encryption.proto3
-rw-r--r--chrome/browser/sync/protocol/extension_specifics.proto3
-rw-r--r--chrome/browser/sync/protocol/nigori_specifics.proto3
-rw-r--r--chrome/browser/sync/protocol/password_specifics.proto3
-rw-r--r--chrome/browser/sync/protocol/preference_specifics.proto3
-rw-r--r--chrome/browser/sync/protocol/proto_enum_conversions.cc74
-rw-r--r--chrome/browser/sync/protocol/proto_enum_conversions.h33
-rw-r--r--chrome/browser/sync/protocol/proto_enum_conversions_unittest.cc55
-rw-r--r--chrome/browser/sync/protocol/proto_value_conversions.cc306
-rw-r--r--chrome/browser/sync/protocol/proto_value_conversions.h109
-rw-r--r--chrome/browser/sync/protocol/proto_value_conversions_unittest.cc151
-rw-r--r--chrome/browser/sync/protocol/session_specifics.proto3
-rw-r--r--chrome/browser/sync/protocol/sync.proto3
-rw-r--r--chrome/browser/sync/protocol/theme_specifics.proto3
-rw-r--r--chrome/browser/sync/protocol/typed_url_specifics.proto3
-rw-r--r--chrome/chrome.gyp4
-rw-r--r--chrome/chrome_tests.gypi2
20 files changed, 770 insertions, 0 deletions
diff --git a/chrome/browser/sync/protocol/app_specifics.proto b/chrome/browser/sync/protocol/app_specifics.proto
index 452cc50..4bfc225 100644
--- a/chrome/browser/sync/protocol/app_specifics.proto
+++ b/chrome/browser/sync/protocol/app_specifics.proto
@@ -4,6 +4,9 @@
//
// Sync protocol datatype extension for apps.
+// Update proto_value_conversions{.h,.cc,_unittest.cc} if you change
+// any fields in this file.
+
syntax = "proto2";
option optimize_for = LITE_RUNTIME;
diff --git a/chrome/browser/sync/protocol/autofill_specifics.proto b/chrome/browser/sync/protocol/autofill_specifics.proto
index 536623c..520f25f 100644
--- a/chrome/browser/sync/protocol/autofill_specifics.proto
+++ b/chrome/browser/sync/protocol/autofill_specifics.proto
@@ -4,6 +4,9 @@
//
// Sync protocol datatype extension for autofill.
+// Update proto_value_conversions{.h,.cc,_unittest.cc} if you change
+// any fields in this file.
+
syntax = "proto2";
option optimize_for = LITE_RUNTIME;
diff --git a/chrome/browser/sync/protocol/bookmark_specifics.proto b/chrome/browser/sync/protocol/bookmark_specifics.proto
index c94fd2e..75321f8 100644
--- a/chrome/browser/sync/protocol/bookmark_specifics.proto
+++ b/chrome/browser/sync/protocol/bookmark_specifics.proto
@@ -4,6 +4,9 @@
//
// Sync protocol datatype extension for bookmarks.
+// Update proto_value_conversions{.h,.cc,_unittest.cc} if you change
+// any fields in this file.
+
syntax = "proto2";
option optimize_for = LITE_RUNTIME;
diff --git a/chrome/browser/sync/protocol/encryption.proto b/chrome/browser/sync/protocol/encryption.proto
index 6d6a792..da51ff0 100644
--- a/chrome/browser/sync/protocol/encryption.proto
+++ b/chrome/browser/sync/protocol/encryption.proto
@@ -4,6 +4,9 @@
//
// Common sync protocol for encrypted data.
+// Update proto_value_conversions{.h,.cc,_unittest.cc} if you change
+// any fields in this file.
+
syntax = "proto2";
option optimize_for = LITE_RUNTIME;
diff --git a/chrome/browser/sync/protocol/extension_specifics.proto b/chrome/browser/sync/protocol/extension_specifics.proto
index dff29b2..25b98a0 100644
--- a/chrome/browser/sync/protocol/extension_specifics.proto
+++ b/chrome/browser/sync/protocol/extension_specifics.proto
@@ -4,6 +4,9 @@
//
// Sync protocol datatype extension for extensions.
+// Update proto_value_conversions{.h,.cc,_unittest.cc} if you change
+// any fields in this file.
+
syntax = "proto2";
option optimize_for = LITE_RUNTIME;
diff --git a/chrome/browser/sync/protocol/nigori_specifics.proto b/chrome/browser/sync/protocol/nigori_specifics.proto
index e7458c6..98ee1b7 100644
--- a/chrome/browser/sync/protocol/nigori_specifics.proto
+++ b/chrome/browser/sync/protocol/nigori_specifics.proto
@@ -4,6 +4,9 @@
//
// Sync protocol datatype extension for nigori keys.
+// Update proto_value_conversions{.h,.cc,_unittest.cc} if you change
+// any fields in this file.
+
syntax = "proto2";
option optimize_for = LITE_RUNTIME;
diff --git a/chrome/browser/sync/protocol/password_specifics.proto b/chrome/browser/sync/protocol/password_specifics.proto
index 210ec6e..49f1343 100644
--- a/chrome/browser/sync/protocol/password_specifics.proto
+++ b/chrome/browser/sync/protocol/password_specifics.proto
@@ -4,6 +4,9 @@
//
// Sync protocol datatype extension for password data.
+// Update proto_value_conversions{.h,.cc,_unittest.cc} if you change
+// any fields in this file.
+
syntax = "proto2";
option optimize_for = LITE_RUNTIME;
diff --git a/chrome/browser/sync/protocol/preference_specifics.proto b/chrome/browser/sync/protocol/preference_specifics.proto
index 8e221444..72bc375 100644
--- a/chrome/browser/sync/protocol/preference_specifics.proto
+++ b/chrome/browser/sync/protocol/preference_specifics.proto
@@ -4,6 +4,9 @@
//
// Sync protocol datatype extension for preferences.
+// Update proto_value_conversions{.h,.cc,_unittest.cc} if you change
+// any fields in this file.
+
syntax = "proto2";
option optimize_for = LITE_RUNTIME;
diff --git a/chrome/browser/sync/protocol/proto_enum_conversions.cc b/chrome/browser/sync/protocol/proto_enum_conversions.cc
new file mode 100644
index 0000000..7421711
--- /dev/null
+++ b/chrome/browser/sync/protocol/proto_enum_conversions.cc
@@ -0,0 +1,74 @@
+// 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_enum_conversions.h"
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+
+namespace browser_sync {
+
+#define ASSERT_ENUM_BOUNDS(enum_parent, enum_type, enum_min, enum_max) \
+ COMPILE_ASSERT(enum_parent::enum_type##_MIN == enum_parent::enum_min, \
+ enum_type##_MIN_not_##enum_min); \
+ COMPILE_ASSERT(enum_parent::enum_type##_MAX == enum_parent::enum_max, \
+ enum_type##_MAX_not_##enum_max);
+
+#define ENUM_CASE(enum_parent, enum_value) \
+ case enum_parent::enum_value: return #enum_value
+
+const char* GetBrowserTypeString(
+ sync_pb::SessionWindow::BrowserType browser_type) {
+ ASSERT_ENUM_BOUNDS(sync_pb::SessionWindow, BrowserType,
+ TYPE_NORMAL, TYPE_POPUP);
+ switch (browser_type) {
+ ENUM_CASE(sync_pb::SessionWindow, TYPE_NORMAL);
+ ENUM_CASE(sync_pb::SessionWindow, TYPE_POPUP);
+ }
+ NOTREACHED();
+ return "";
+}
+
+const char* GetPageTransitionString(
+ sync_pb::TabNavigation::PageTransition page_transition) {
+ ASSERT_ENUM_BOUNDS(sync_pb::TabNavigation, PageTransition,
+ LINK, CHAIN_END);
+ switch (page_transition) {
+ ENUM_CASE(sync_pb::TabNavigation, LINK);
+ ENUM_CASE(sync_pb::TabNavigation, TYPED);
+ ENUM_CASE(sync_pb::TabNavigation, AUTO_BOOKMARK);
+ ENUM_CASE(sync_pb::TabNavigation, AUTO_SUBFRAME);
+ ENUM_CASE(sync_pb::TabNavigation, MANUAL_SUBFRAME);
+ ENUM_CASE(sync_pb::TabNavigation, GENERATED);
+ ENUM_CASE(sync_pb::TabNavigation, START_PAGE);
+ ENUM_CASE(sync_pb::TabNavigation, FORM_SUBMIT);
+ ENUM_CASE(sync_pb::TabNavigation, RELOAD);
+ ENUM_CASE(sync_pb::TabNavigation, KEYWORD);
+ ENUM_CASE(sync_pb::TabNavigation, KEYWORD_GENERATED);
+ ENUM_CASE(sync_pb::TabNavigation, CHAIN_START);
+ ENUM_CASE(sync_pb::TabNavigation, CHAIN_END);
+ }
+ NOTREACHED();
+ return "";
+}
+
+const char* GetPageTransitionQualifierString(
+ sync_pb::TabNavigation::PageTransitionQualifier
+ page_transition_qualifier) {
+ ASSERT_ENUM_BOUNDS(sync_pb::TabNavigation, PageTransitionQualifier,
+ CLIENT_REDIRECT, SERVER_REDIRECT);
+ switch (page_transition_qualifier) {
+ ENUM_CASE(sync_pb::TabNavigation, CLIENT_REDIRECT);
+ ENUM_CASE(sync_pb::TabNavigation, SERVER_REDIRECT);
+ }
+ NOTREACHED();
+ return "";
+}
+
+#undef ASSERT_ENUM_BOUNDS
+#undef ENUM_CASE
+
+} // namespace
diff --git a/chrome/browser/sync/protocol/proto_enum_conversions.h b/chrome/browser/sync/protocol/proto_enum_conversions.h
new file mode 100644
index 0000000..62b6157
--- /dev/null
+++ b/chrome/browser/sync/protocol/proto_enum_conversions.h
@@ -0,0 +1,33 @@
+// 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.
+
+#ifndef CHROME_BROWSER_SYNC_PROTOCOL_PROTO_ENUM_CONVERSIONS_H_
+#define CHROME_BROWSER_SYNC_PROTOCOL_PROTO_ENUM_CONVERSIONS_H_
+#pragma once
+
+// Keep this file in sync with the .proto files in this directory.
+
+#include "chrome/browser/sync/protocol/session_specifics.pb.h"
+
+// Utility functions to get the string equivalent for some sync proto
+// enums.
+
+namespace browser_sync {
+
+// The returned strings (which don't have to be freed) are in ASCII.
+// The result of passing in an invalid enum value is undefined.
+
+const char* GetBrowserTypeString(
+ sync_pb::SessionWindow::BrowserType browser_type);
+
+const char* GetPageTransitionString(
+ sync_pb::TabNavigation::PageTransition page_transition);
+
+const char* GetPageTransitionQualifierString(
+ sync_pb::TabNavigation::PageTransitionQualifier
+ page_transition_qualifier);
+
+} // namespace browser_sync
+
+#endif // CHROME_BROWSER_SYNC_PROTOCOL_PROTO_ENUM_CONVERSIONS_H_
diff --git a/chrome/browser/sync/protocol/proto_enum_conversions_unittest.cc b/chrome/browser/sync/protocol/proto_enum_conversions_unittest.cc
new file mode 100644
index 0000000..8825458
--- /dev/null
+++ b/chrome/browser/sync/protocol/proto_enum_conversions_unittest.cc
@@ -0,0 +1,55 @@
+// 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_enum_conversions.h"
+
+#include <string>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace browser_sync {
+namespace {
+
+class ProtoEnumConversionsTest : public testing::Test {
+};
+
+template <class T>
+void TestEnumStringFunction(const char* (*enum_string_fn)(T),
+ int enum_min, int enum_max) {
+ for (int i = enum_min; i <= enum_max; ++i) {
+ const std::string& str = enum_string_fn(static_cast<T>(i));
+ EXPECT_FALSE(str.empty());
+ }
+}
+
+TEST_F(ProtoEnumConversionsTest, GetBrowserTypeString) {
+ TestEnumStringFunction(
+ GetBrowserTypeString,
+ sync_pb::SessionWindow::BrowserType_MIN,
+ sync_pb::SessionWindow::BrowserType_MAX);
+}
+
+TEST_F(ProtoEnumConversionsTest, GetPageTransitionString) {
+ // We have a gap, so we need to do two ranges.
+ TestEnumStringFunction(
+ GetPageTransitionString,
+ sync_pb::TabNavigation::PageTransition_MIN,
+ sync_pb::TabNavigation::KEYWORD_GENERATED);
+ TestEnumStringFunction(
+ GetPageTransitionString,
+ sync_pb::TabNavigation::CHAIN_START,
+ sync_pb::TabNavigation::PageTransition_MAX);
+}
+
+TEST_F(ProtoEnumConversionsTest, GetPageTransitionQualifierString) {
+ TestEnumStringFunction(
+ GetPageTransitionQualifierString,
+ sync_pb::TabNavigation::PageTransitionQualifier_MIN,
+ sync_pb::TabNavigation::PageTransitionQualifier_MAX);
+}
+
+} // namespace
+} // namespace browser_sync
diff --git a/chrome/browser/sync/protocol/proto_value_conversions.cc b/chrome/browser/sync/protocol/proto_value_conversions.cc
new file mode 100644
index 0000000..57be094
--- /dev/null
+++ b/chrome/browser/sync/protocol/proto_value_conversions.cc
@@ -0,0 +1,306 @@
+// 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* 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* 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* 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
diff --git a/chrome/browser/sync/protocol/proto_value_conversions.h b/chrome/browser/sync/protocol/proto_value_conversions.h
new file mode 100644
index 0000000..b28fd12
--- /dev/null
+++ b/chrome/browser/sync/protocol/proto_value_conversions.h
@@ -0,0 +1,109 @@
+// 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.
+
+#ifndef CHROME_BROWSER_SYNC_PROTOCOL_PROTO_VALUE_CONVERSIONS_H_
+#define CHROME_BROWSER_SYNC_PROTOCOL_PROTO_VALUE_CONVERSIONS_H_
+#pragma once
+
+class DictionaryValue;
+
+namespace sync_pb {
+class AppSpecifics;
+class AutofillCreditCardSpecifics;
+class AutofillProfileSpecifics;
+class AutofillSpecifics;
+class BookmarkSpecifics;
+class EncryptedData;
+class EntitySpecifics;
+class ExtensionSpecifics;
+class NigoriSpecifics;
+class PasswordSpecifics;
+class PreferenceSpecifics;
+class SessionHeader;
+class SessionSpecifics;
+class SessionTab;
+class SessionWindow;
+class TabNavigation;
+class ThemeSpecifics;
+class TypedUrlSpecifics;
+} // namespace sync_pb
+
+// Utility functions to convert sync protocol buffers to dictionaries.
+// Each protocol field is mapped to a key of the same name. Repeated
+// fields are mapped to array values and sub-messages are mapped to
+// sub-dictionary values.
+//
+// TODO(akalin): Add has_* information.
+//
+// TODO(akalin): Improve enum support.
+
+namespace browser_sync {
+
+// TODO(akalin): Perhaps extend this to decrypt?
+DictionaryValue* EncryptedDataToValue(
+ const sync_pb::EncryptedData& encrypted_data);
+
+// Sub-protocols of SessionSpecifics.
+
+DictionaryValue* SessionHeaderToValue(
+ const sync_pb::SessionHeader& session_header);
+
+DictionaryValue* SessionTabToValue(
+ const sync_pb::SessionTab& session_tab);
+
+DictionaryValue* SessionWindowToValue(
+ const sync_pb::SessionWindow& session_window);
+
+DictionaryValue* TabNavigationToValue(
+ const sync_pb::TabNavigation& tab_navigation);
+
+// Main *SpecificsToValue functions.
+
+DictionaryValue* AppSpecificsToValue(
+ const sync_pb::AppSpecifics& app_specifics);
+
+DictionaryValue* AutofillSpecificsToValue(
+ const sync_pb::AutofillSpecifics& autofill_specifics);
+
+DictionaryValue* AutofillCreditCardSpecificsToValue(
+ const sync_pb::AutofillCreditCardSpecifics&
+ autofill_credit_card_specifics);
+
+DictionaryValue* AutofillProfileSpecificsToValue(
+ const sync_pb::AutofillProfileSpecifics& autofill_profile_specifics);
+
+DictionaryValue* BookmarkSpecificsToValue(
+ const sync_pb::BookmarkSpecifics& bookmark_specifics);
+
+DictionaryValue* ExtensionSpecificsToValue(
+ const sync_pb::ExtensionSpecifics& extension_specifics);
+
+DictionaryValue* NigoriSpecificsToValue(
+ const sync_pb::NigoriSpecifics& nigori_specifics);
+
+DictionaryValue* PasswordSpecificsToValue(
+ const sync_pb::PasswordSpecifics& password_specifics);
+
+DictionaryValue* PreferenceSpecificsToValue(
+ const sync_pb::PreferenceSpecifics& password_specifics);
+
+DictionaryValue* SessionSpecificsToValue(
+ const sync_pb::SessionSpecifics& session_specifics);
+
+DictionaryValue* ThemeSpecificsToValue(
+ const sync_pb::ThemeSpecifics& theme_specifics);
+
+DictionaryValue* TypedUrlSpecificsToValue(
+ const sync_pb::TypedUrlSpecifics& typed_url_specifics);
+
+// Any present extensions are mapped to sub-dictionary values with the
+// key equal to the extension name.
+DictionaryValue* EntitySpecificsToValue(
+ const sync_pb::EntitySpecifics& entity_specifics);
+
+} // namespace browser_sync
+
+#endif // CHROME_BROWSER_SYNC_PROTOCOL_PROTO_VALUE_CONVERSIONS_H_
diff --git a/chrome/browser/sync/protocol/proto_value_conversions_unittest.cc b/chrome/browser/sync/protocol/proto_value_conversions_unittest.cc
new file mode 100644
index 0000000..3416282
--- /dev/null
+++ b/chrome/browser/sync/protocol/proto_value_conversions_unittest.cc
@@ -0,0 +1,151 @@
+// 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/scoped_ptr.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/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"
+#include "chrome/browser/sync/syncable/model_type.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace browser_sync {
+namespace {
+
+class ProtoValueConversionsTest : public testing::Test {
+ protected:
+ template <class T>
+ void TestSpecificsToValue(
+ DictionaryValue* (*specifics_to_value)(const T&)) {
+ const T& specifics(T::default_instance());
+ scoped_ptr<DictionaryValue> value(specifics_to_value(specifics));
+ // We can't do much but make sure that the returned value has
+ // something in it.
+ EXPECT_FALSE(value->empty());
+ }
+};
+
+TEST_F(ProtoValueConversionsTest, ProtoChangeCheck) {
+ // If this number changes, that means we added or removed a data
+ // type. Don't forget to add a unit test for {New
+ // type}SpecificsToValue below.
+ EXPECT_EQ(13, syncable::MODEL_TYPE_COUNT);
+
+ // We'd also like to check if we changed any field in our messages.
+ // However, that's hard to do: sizeof could work, but it's
+ // platform-dependent. default_instance().ByteSize() won't change
+ // for most changes, since most of our fields are optional. So we
+ // just settle for comments in the proto files.
+}
+
+TEST_F(ProtoValueConversionsTest, EncryptedDataToValue) {
+ TestSpecificsToValue(EncryptedDataToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, AppSpecificsToValue) {
+ TestSpecificsToValue(AppSpecificsToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, AutofillSpecificsToValue) {
+ TestSpecificsToValue(AutofillSpecificsToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, AutofillCreditCardSpecificsToValue) {
+ TestSpecificsToValue(AutofillCreditCardSpecificsToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, AutofillProfileSpecificsToValue) {
+ TestSpecificsToValue(AutofillProfileSpecificsToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, BookmarkSpecificsToValue) {
+ TestSpecificsToValue(BookmarkSpecificsToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, ExtensionSpecificsToValue) {
+ TestSpecificsToValue(ExtensionSpecificsToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, NigoriSpecificsToValue) {
+ TestSpecificsToValue(NigoriSpecificsToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, PasswordSpecificsToValue) {
+ TestSpecificsToValue(PasswordSpecificsToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, PreferenceSpecificsToValue) {
+ TestSpecificsToValue(PreferenceSpecificsToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, SessionHeaderToValue) {
+ TestSpecificsToValue(SessionHeaderToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, SessionSpecificsToValue) {
+ TestSpecificsToValue(SessionSpecificsToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, SessionTabToValue) {
+ TestSpecificsToValue(SessionTabToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, SessionWindowToValue) {
+ TestSpecificsToValue(SessionWindowToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, TabNavigationToValue) {
+ TestSpecificsToValue(TabNavigationToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, ThemeSpecificsToValue) {
+ TestSpecificsToValue(ThemeSpecificsToValue);
+}
+
+TEST_F(ProtoValueConversionsTest, TypedUrlSpecificsToValue) {
+ TestSpecificsToValue(TypedUrlSpecificsToValue);
+}
+
+// TODO(akalin): Figure out how to better test EntitySpecificsToValue.
+
+TEST_F(ProtoValueConversionsTest, EntitySpecificsToValue) {
+ sync_pb::EntitySpecifics specifics;
+ // Touch the extensions to make sure it shows up in the generated
+ // value.
+#define SET_EXTENSION(key) (void)specifics.MutableExtension(sync_pb::key)
+
+ SET_EXTENSION(app);
+ SET_EXTENSION(autofill);
+ SET_EXTENSION(autofill_profile);
+ SET_EXTENSION(bookmark);
+ SET_EXTENSION(extension);
+ SET_EXTENSION(nigori);
+ SET_EXTENSION(password);
+ SET_EXTENSION(preference);
+ SET_EXTENSION(session);
+ SET_EXTENSION(theme);
+ SET_EXTENSION(typed_url);
+
+#undef SET_EXTENSION
+
+ scoped_ptr<DictionaryValue> value(EntitySpecificsToValue(specifics));
+ EXPECT_EQ(syncable::MODEL_TYPE_COUNT - syncable::FIRST_REAL_MODEL_TYPE,
+ static_cast<int>(value->size()));
+}
+
+} // namespace
+} // namespace browser_sync
diff --git a/chrome/browser/sync/protocol/session_specifics.proto b/chrome/browser/sync/protocol/session_specifics.proto
index 5b00b358..bfed4aa 100644
--- a/chrome/browser/sync/protocol/session_specifics.proto
+++ b/chrome/browser/sync/protocol/session_specifics.proto
@@ -4,6 +4,9 @@
//
// Sync protocol datatype extension for sessions.
+// Update proto_value_conversions{.h,.cc,_unittest.cc} if you change
+// any fields in this file.
+
syntax = "proto2";
option optimize_for = LITE_RUNTIME;
diff --git a/chrome/browser/sync/protocol/sync.proto b/chrome/browser/sync/protocol/sync.proto
index 1ada951..1b778f3 100644
--- a/chrome/browser/sync/protocol/sync.proto
+++ b/chrome/browser/sync/protocol/sync.proto
@@ -4,6 +4,9 @@
//
// Sync protocol for communication between sync client and server.
+// Update proto_value_conversions{.h,.cc,_unittest.cc} if you change
+// any fields in this file.
+
syntax = "proto2";
option optimize_for = LITE_RUNTIME;
diff --git a/chrome/browser/sync/protocol/theme_specifics.proto b/chrome/browser/sync/protocol/theme_specifics.proto
index 5439bc4..eb864ff 100644
--- a/chrome/browser/sync/protocol/theme_specifics.proto
+++ b/chrome/browser/sync/protocol/theme_specifics.proto
@@ -4,6 +4,9 @@
//
// Sync protocol datatype extension for themes.
+// Update proto_value_conversions{.h,.cc,_unittest.cc} if you change
+// any fields in this file.
+
syntax = "proto2";
option optimize_for = LITE_RUNTIME;
diff --git a/chrome/browser/sync/protocol/typed_url_specifics.proto b/chrome/browser/sync/protocol/typed_url_specifics.proto
index 7dd4041..011ae4e 100644
--- a/chrome/browser/sync/protocol/typed_url_specifics.proto
+++ b/chrome/browser/sync/protocol/typed_url_specifics.proto
@@ -4,6 +4,9 @@
//
// Sync protocol datatype extension for typed urls.
+// Update proto_value_conversions{.h,.cc,_unittest.cc} if you change
+// any fields in this file.
+
syntax = "proto2";
option optimize_for = LITE_RUNTIME;
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index f1da091e..c5fdad4 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -964,6 +964,10 @@
'browser/sync/js_event_handler_list.h',
'browser/sync/js_event_router.h',
'browser/sync/js_frontend.h',
+ 'browser/sync/protocol/proto_enum_conversions.cc',
+ 'browser/sync/protocol/proto_enum_conversions.h',
+ 'browser/sync/protocol/proto_value_conversions.cc',
+ 'browser/sync/protocol/proto_value_conversions.h',
'browser/sync/protocol/service_constants.h',
'browser/sync/sessions/ordered_commit_set.cc',
'browser/sync/sessions/ordered_commit_set.h',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 38ce812..2e34646 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -2751,6 +2751,8 @@
'browser/sync/notifier/registration_manager_unittest.cc',
'browser/sync/notifier/server_notifier_thread_unittest.cc',
'browser/sync/profile_sync_factory_mock.h',
+ 'browser/sync/protocol/proto_enum_conversions_unittest.cc',
+ 'browser/sync/protocol/proto_value_conversions_unittest.cc',
'browser/sync/sessions/ordered_commit_set_unittest.cc',
'browser/sync/sessions/status_controller_unittest.cc',
'browser/sync/sessions/sync_session_unittest.cc',