Popular sites on the NTP: check that experiment group StartsWith (rather than IS...
[chromium-blink-merge.git] / sync / syncable / entry_kernel.cc
blob8fb611f23b400cca1d191258708993b5bdf6efbe
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.
5 #include "sync/syncable/entry_kernel.h"
7 #include "base/json/string_escape.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "sync/protocol/proto_value_conversions.h"
10 #include "sync/syncable/syncable_columns.h"
11 #include "sync/syncable/syncable_enum_conversions.h"
12 #include "sync/util/cryptographer.h"
14 namespace syncer {
15 namespace syncable {
17 EntryKernel::EntryKernel() : dirty_(false) {
18 // Everything else should already be default-initialized.
19 for (int i = 0; i < INT64_FIELDS_COUNT; ++i) {
20 int64_fields[i] = 0;
24 EntryKernel::~EntryKernel() {}
26 ModelType EntryKernel::GetModelType() const {
27 ModelType specifics_type = GetModelTypeFromSpecifics(ref(SPECIFICS));
28 if (specifics_type != UNSPECIFIED)
29 return specifics_type;
30 if (ref(ID).IsRoot())
31 return TOP_LEVEL_FOLDER;
32 // Loose check for server-created top-level folders that aren't
33 // bound to a particular model type.
34 if (!ref(UNIQUE_SERVER_TAG).empty() && ref(SERVER_IS_DIR))
35 return TOP_LEVEL_FOLDER;
37 return UNSPECIFIED;
40 ModelType EntryKernel::GetServerModelType() const {
41 ModelType specifics_type = GetModelTypeFromSpecifics(ref(SERVER_SPECIFICS));
42 if (specifics_type != UNSPECIFIED)
43 return specifics_type;
44 if (ref(ID).IsRoot())
45 return TOP_LEVEL_FOLDER;
46 // Loose check for server-created top-level folders that aren't
47 // bound to a particular model type.
48 if (!ref(UNIQUE_SERVER_TAG).empty() && ref(SERVER_IS_DIR))
49 return TOP_LEVEL_FOLDER;
51 return UNSPECIFIED;
54 bool EntryKernel::ShouldMaintainPosition() const {
55 // We maintain positions for all bookmarks, except those that are
56 // server-created top-level folders.
57 return TypeSupportsOrdering(GetModelTypeFromSpecifics(ref(SPECIFICS))) &&
58 !(!ref(UNIQUE_SERVER_TAG).empty() && ref(IS_DIR));
61 bool EntryKernel::ShouldMaintainHierarchy() const {
62 // We maintain hierarchy for bookmarks and top-level folders,
63 // but no other types. Note that the Nigori node consists of a single
64 // top-level folder, so it's included in this set.
65 return TypeSupportsHierarchy(GetModelTypeFromSpecifics(ref(SPECIFICS))) ||
66 (!ref(UNIQUE_SERVER_TAG).empty());
69 namespace {
71 // Utility function to loop through a set of enum values and add the
72 // field keys/values in the kernel to the given dictionary.
74 // V should be convertible to Value.
75 template <class T, class U, class V>
76 void SetFieldValues(const EntryKernel& kernel,
77 base::DictionaryValue* dictionary_value,
78 const char* (*enum_key_fn)(T),
79 V* (*enum_value_fn)(U),
80 int field_key_min, int field_key_max) {
81 DCHECK_LE(field_key_min, field_key_max);
82 for (int i = field_key_min; i <= field_key_max; ++i) {
83 T field = static_cast<T>(i);
84 const std::string& key = enum_key_fn(field);
85 V* value = enum_value_fn(kernel.ref(field));
86 dictionary_value->Set(key, value);
90 void SetEncryptableProtoValues(
91 const EntryKernel& kernel,
92 Cryptographer* cryptographer,
93 base::DictionaryValue* dictionary_value,
94 int field_key_min, int field_key_max) {
95 DCHECK_LE(field_key_min, field_key_max);
96 for (int i = field_key_min; i <= field_key_max; ++i) {
97 ProtoField field = static_cast<ProtoField>(i);
98 const std::string& key = GetProtoFieldString(field);
100 scoped_ptr<base::DictionaryValue> value;
101 sync_pb::EntitySpecifics decrypted;
102 const sync_pb::EncryptedData& encrypted = kernel.ref(field).encrypted();
103 if (cryptographer &&
104 kernel.ref(field).has_encrypted() &&
105 cryptographer->CanDecrypt(encrypted) &&
106 cryptographer->Decrypt(encrypted, &decrypted)) {
107 value = EntitySpecificsToValue(decrypted);
108 value->SetBoolean("encrypted", true);
109 } else {
110 value = EntitySpecificsToValue(kernel.ref(field));
112 dictionary_value->Set(key, value.Pass());
116 // Helper functions for SetFieldValues().
118 base::StringValue* Int64ToValue(int64 i) {
119 return new base::StringValue(base::Int64ToString(i));
122 base::StringValue* TimeToValue(const base::Time& t) {
123 return new base::StringValue(GetTimeDebugString(t));
126 base::StringValue* IdToValue(const Id& id) {
127 return id.ToValue();
130 base::FundamentalValue* BooleanToValue(bool bool_val) {
131 return new base::FundamentalValue(bool_val);
134 base::StringValue* StringToValue(const std::string& str) {
135 return new base::StringValue(str);
138 base::StringValue* UniquePositionToValue(const UniquePosition& pos) {
139 return new base::StringValue(pos.ToDebugString());
142 base::StringValue* AttachmentMetadataToValue(
143 const sync_pb::AttachmentMetadata& a) {
144 return new base::StringValue(a.SerializeAsString());
147 } // namespace
149 base::DictionaryValue* EntryKernel::ToValue(
150 Cryptographer* cryptographer) const {
151 base::DictionaryValue* kernel_info = new base::DictionaryValue();
152 kernel_info->SetBoolean("isDirty", is_dirty());
153 ModelType dataType = GetServerModelType();
154 if (!IsRealDataType(dataType))
155 dataType = GetModelType();
156 kernel_info->Set("modelType", ModelTypeToValue(dataType));
158 // Int64 fields.
159 SetFieldValues(*this, kernel_info,
160 &GetMetahandleFieldString, &Int64ToValue,
161 INT64_FIELDS_BEGIN, META_HANDLE);
162 SetFieldValues(*this, kernel_info,
163 &GetBaseVersionString, &Int64ToValue,
164 META_HANDLE + 1, BASE_VERSION);
165 SetFieldValues(*this, kernel_info,
166 &GetInt64FieldString, &Int64ToValue,
167 BASE_VERSION + 1, INT64_FIELDS_END - 1);
169 // Time fields.
170 SetFieldValues(*this, kernel_info,
171 &GetTimeFieldString, &TimeToValue,
172 TIME_FIELDS_BEGIN, TIME_FIELDS_END - 1);
174 // ID fields.
175 SetFieldValues(*this, kernel_info,
176 &GetIdFieldString, &IdToValue,
177 ID_FIELDS_BEGIN, ID_FIELDS_END - 1);
179 // Bit fields.
180 SetFieldValues(*this, kernel_info,
181 &GetIndexedBitFieldString, &BooleanToValue,
182 BIT_FIELDS_BEGIN, INDEXED_BIT_FIELDS_END - 1);
183 SetFieldValues(*this, kernel_info,
184 &GetIsDelFieldString, &BooleanToValue,
185 INDEXED_BIT_FIELDS_END, IS_DEL);
186 SetFieldValues(*this, kernel_info,
187 &GetBitFieldString, &BooleanToValue,
188 IS_DEL + 1, BIT_FIELDS_END - 1);
190 // String fields.
192 // Pick out the function overload we want.
193 SetFieldValues(*this, kernel_info,
194 &GetStringFieldString, &StringToValue,
195 STRING_FIELDS_BEGIN, STRING_FIELDS_END - 1);
198 // Proto fields.
199 SetEncryptableProtoValues(*this, cryptographer, kernel_info,
200 PROTO_FIELDS_BEGIN, PROTO_FIELDS_END - 1);
202 // UniquePosition fields
203 SetFieldValues(*this, kernel_info,
204 &GetUniquePositionFieldString, &UniquePositionToValue,
205 UNIQUE_POSITION_FIELDS_BEGIN, UNIQUE_POSITION_FIELDS_END - 1);
207 // AttachmentMetadata fields
208 SetFieldValues(*this,
209 kernel_info,
210 &GetAttachmentMetadataFieldString,
211 &AttachmentMetadataToValue,
212 ATTACHMENT_METADATA_FIELDS_BEGIN,
213 ATTACHMENT_METADATA_FIELDS_END - 1);
215 // Bit temps.
216 SetFieldValues(*this, kernel_info,
217 &GetBitTempString, &BooleanToValue,
218 BIT_TEMPS_BEGIN, BIT_TEMPS_END - 1);
220 return kernel_info;
223 base::ListValue* EntryKernelMutationMapToValue(
224 const EntryKernelMutationMap& mutations) {
225 base::ListValue* list = new base::ListValue();
226 for (EntryKernelMutationMap::const_iterator it = mutations.begin();
227 it != mutations.end(); ++it) {
228 list->Append(EntryKernelMutationToValue(it->second));
230 return list;
233 base::DictionaryValue* EntryKernelMutationToValue(
234 const EntryKernelMutation& mutation) {
235 base::DictionaryValue* dict = new base::DictionaryValue();
236 dict->Set("original", mutation.original.ToValue(NULL));
237 dict->Set("mutated", mutation.mutated.ToValue(NULL));
238 return dict;
241 std::ostream& operator<<(std::ostream& os, const EntryKernel& entry_kernel) {
242 int i;
243 EntryKernel* const kernel = const_cast<EntryKernel*>(&entry_kernel);
244 for (i = BEGIN_FIELDS; i < INT64_FIELDS_END; ++i) {
245 os << g_metas_columns[i].name << ": "
246 << kernel->ref(static_cast<Int64Field>(i)) << ", ";
248 for (; i < TIME_FIELDS_END; ++i) {
249 os << g_metas_columns[i].name << ": "
250 << GetTimeDebugString(kernel->ref(static_cast<TimeField>(i))) << ", ";
252 for (; i < ID_FIELDS_END; ++i) {
253 os << g_metas_columns[i].name << ": "
254 << kernel->ref(static_cast<IdField>(i)) << ", ";
256 os << "Flags: ";
257 for (; i < BIT_FIELDS_END; ++i) {
258 if (kernel->ref(static_cast<BitField>(i)))
259 os << g_metas_columns[i].name << ", ";
261 for (; i < STRING_FIELDS_END; ++i) {
262 const std::string& field = kernel->ref(static_cast<StringField>(i));
263 os << g_metas_columns[i].name << ": " << field << ", ";
265 for (; i < PROTO_FIELDS_END; ++i) {
266 std::string escaped_str = base::EscapeBytesAsInvalidJSONString(
267 kernel->ref(static_cast<ProtoField>(i)).SerializeAsString(), false);
268 os << g_metas_columns[i].name << ": " << escaped_str << ", ";
270 for (; i < UNIQUE_POSITION_FIELDS_END; ++i) {
271 os << g_metas_columns[i].name << ": "
272 << kernel->ref(static_cast<UniquePositionField>(i)).ToDebugString()
273 << ", ";
275 for (; i < ATTACHMENT_METADATA_FIELDS_END; ++i) {
276 std::string escaped_str = base::EscapeBytesAsInvalidJSONString(
277 kernel->ref(static_cast<AttachmentMetadataField>(i))
278 .SerializeAsString(),
279 false);
280 os << g_metas_columns[i].name << ": " << escaped_str << ", ";
282 os << "TempFlags: ";
283 for (; i < BIT_TEMPS_END; ++i) {
284 if (kernel->ref(static_cast<BitTemp>(i)))
285 os << "#" << i - BIT_TEMPS_BEGIN << ", ";
287 return os;
290 } // namespace syncer
291 } // namespace syncable