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/strings/string_number_conversions.h"
8 #include "sync/protocol/proto_value_conversions.h"
9 #include "sync/syncable/syncable_enum_conversions.h"
10 #include "sync/util/cryptographer.h"
15 EntryKernel::EntryKernel() : dirty_(false) {
16 // Everything else should already be default-initialized.
17 for (int i
= 0; i
< INT64_FIELDS_COUNT
; ++i
) {
22 EntryKernel::~EntryKernel() {}
24 ModelType
EntryKernel::GetModelType() const {
25 ModelType specifics_type
= GetModelTypeFromSpecifics(ref(SPECIFICS
));
26 if (specifics_type
!= UNSPECIFIED
)
27 return specifics_type
;
29 return TOP_LEVEL_FOLDER
;
30 // Loose check for server-created top-level folders that aren't
31 // bound to a particular model type.
32 if (!ref(UNIQUE_SERVER_TAG
).empty() && ref(SERVER_IS_DIR
))
33 return TOP_LEVEL_FOLDER
;
38 ModelType
EntryKernel::GetServerModelType() const {
39 ModelType specifics_type
= GetModelTypeFromSpecifics(ref(SERVER_SPECIFICS
));
40 if (specifics_type
!= UNSPECIFIED
)
41 return specifics_type
;
43 return TOP_LEVEL_FOLDER
;
44 // Loose check for server-created top-level folders that aren't
45 // bound to a particular model type.
46 if (!ref(UNIQUE_SERVER_TAG
).empty() && ref(SERVER_IS_DIR
))
47 return TOP_LEVEL_FOLDER
;
52 bool EntryKernel::ShouldMaintainPosition() const {
53 // We maintain positions for all bookmarks, except those that are
54 // server-created top-level folders.
55 return TypeSupportsOrdering(GetModelTypeFromSpecifics(ref(SPECIFICS
))) &&
56 !(!ref(UNIQUE_SERVER_TAG
).empty() && ref(IS_DIR
));
59 bool EntryKernel::ShouldMaintainHierarchy() const {
60 // We maintain hierarchy for bookmarks and top-level folders,
61 // but no other types. Note that the Nigori node consists of a single
62 // top-level folder, so it's included in this set.
63 return TypeSupportsHierarchy(GetModelTypeFromSpecifics(ref(SPECIFICS
))) ||
64 (!ref(UNIQUE_SERVER_TAG
).empty());
69 // Utility function to loop through a set of enum values and add the
70 // field keys/values in the kernel to the given dictionary.
72 // V should be convertible to Value.
73 template <class T
, class U
, class V
>
74 void SetFieldValues(const EntryKernel
& kernel
,
75 base::DictionaryValue
* dictionary_value
,
76 const char* (*enum_key_fn
)(T
),
77 V
* (*enum_value_fn
)(U
),
78 int field_key_min
, int field_key_max
) {
79 DCHECK_LE(field_key_min
, field_key_max
);
80 for (int i
= field_key_min
; i
<= field_key_max
; ++i
) {
81 T field
= static_cast<T
>(i
);
82 const std::string
& key
= enum_key_fn(field
);
83 V
* value
= enum_value_fn(kernel
.ref(field
));
84 dictionary_value
->Set(key
, value
);
88 void SetEncryptableProtoValues(
89 const EntryKernel
& kernel
,
90 Cryptographer
* cryptographer
,
91 base::DictionaryValue
* dictionary_value
,
92 int field_key_min
, int field_key_max
) {
93 DCHECK_LE(field_key_min
, field_key_max
);
94 for (int i
= field_key_min
; i
<= field_key_max
; ++i
) {
95 ProtoField field
= static_cast<ProtoField
>(i
);
96 const std::string
& key
= GetProtoFieldString(field
);
98 scoped_ptr
<base::DictionaryValue
> value
;
99 sync_pb::EntitySpecifics decrypted
;
100 const sync_pb::EncryptedData
& encrypted
= kernel
.ref(field
).encrypted();
102 kernel
.ref(field
).has_encrypted() &&
103 cryptographer
->CanDecrypt(encrypted
) &&
104 cryptographer
->Decrypt(encrypted
, &decrypted
)) {
105 value
= EntitySpecificsToValue(decrypted
);
106 value
->SetBoolean("encrypted", true);
108 value
= EntitySpecificsToValue(kernel
.ref(field
));
110 dictionary_value
->Set(key
, value
.Pass());
114 // Helper functions for SetFieldValues().
116 base::StringValue
* Int64ToValue(int64 i
) {
117 return new base::StringValue(base::Int64ToString(i
));
120 base::StringValue
* TimeToValue(const base::Time
& t
) {
121 return new base::StringValue(GetTimeDebugString(t
));
124 base::StringValue
* IdToValue(const Id
& id
) {
128 base::FundamentalValue
* BooleanToValue(bool bool_val
) {
129 return new base::FundamentalValue(bool_val
);
132 base::StringValue
* StringToValue(const std::string
& str
) {
133 return new base::StringValue(str
);
136 base::StringValue
* UniquePositionToValue(const UniquePosition
& pos
) {
137 return new base::StringValue(pos
.ToDebugString());
140 base::StringValue
* AttachmentMetadataToValue(
141 const sync_pb::AttachmentMetadata
& a
) {
142 return new base::StringValue(a
.SerializeAsString());
147 base::DictionaryValue
* EntryKernel::ToValue(
148 Cryptographer
* cryptographer
) const {
149 base::DictionaryValue
* kernel_info
= new base::DictionaryValue();
150 kernel_info
->SetBoolean("isDirty", is_dirty());
151 ModelType dataType
= GetServerModelType();
152 if (!IsRealDataType(dataType
))
153 dataType
= GetModelType();
154 kernel_info
->Set("modelType", ModelTypeToValue(dataType
));
157 SetFieldValues(*this, kernel_info
,
158 &GetMetahandleFieldString
, &Int64ToValue
,
159 INT64_FIELDS_BEGIN
, META_HANDLE
);
160 SetFieldValues(*this, kernel_info
,
161 &GetBaseVersionString
, &Int64ToValue
,
162 META_HANDLE
+ 1, BASE_VERSION
);
163 SetFieldValues(*this, kernel_info
,
164 &GetInt64FieldString
, &Int64ToValue
,
165 BASE_VERSION
+ 1, INT64_FIELDS_END
- 1);
168 SetFieldValues(*this, kernel_info
,
169 &GetTimeFieldString
, &TimeToValue
,
170 TIME_FIELDS_BEGIN
, TIME_FIELDS_END
- 1);
173 SetFieldValues(*this, kernel_info
,
174 &GetIdFieldString
, &IdToValue
,
175 ID_FIELDS_BEGIN
, ID_FIELDS_END
- 1);
178 SetFieldValues(*this, kernel_info
,
179 &GetIndexedBitFieldString
, &BooleanToValue
,
180 BIT_FIELDS_BEGIN
, INDEXED_BIT_FIELDS_END
- 1);
181 SetFieldValues(*this, kernel_info
,
182 &GetIsDelFieldString
, &BooleanToValue
,
183 INDEXED_BIT_FIELDS_END
, IS_DEL
);
184 SetFieldValues(*this, kernel_info
,
185 &GetBitFieldString
, &BooleanToValue
,
186 IS_DEL
+ 1, BIT_FIELDS_END
- 1);
190 // Pick out the function overload we want.
191 SetFieldValues(*this, kernel_info
,
192 &GetStringFieldString
, &StringToValue
,
193 STRING_FIELDS_BEGIN
, STRING_FIELDS_END
- 1);
197 SetEncryptableProtoValues(*this, cryptographer
, kernel_info
,
198 PROTO_FIELDS_BEGIN
, PROTO_FIELDS_END
- 1);
200 // UniquePosition fields
201 SetFieldValues(*this, kernel_info
,
202 &GetUniquePositionFieldString
, &UniquePositionToValue
,
203 UNIQUE_POSITION_FIELDS_BEGIN
, UNIQUE_POSITION_FIELDS_END
- 1);
205 // AttachmentMetadata fields
206 SetFieldValues(*this,
208 &GetAttachmentMetadataFieldString
,
209 &AttachmentMetadataToValue
,
210 ATTACHMENT_METADATA_FIELDS_BEGIN
,
211 ATTACHMENT_METADATA_FIELDS_END
- 1);
214 SetFieldValues(*this, kernel_info
,
215 &GetBitTempString
, &BooleanToValue
,
216 BIT_TEMPS_BEGIN
, BIT_TEMPS_END
- 1);
221 base::ListValue
* EntryKernelMutationMapToValue(
222 const EntryKernelMutationMap
& mutations
) {
223 base::ListValue
* list
= new base::ListValue();
224 for (EntryKernelMutationMap::const_iterator it
= mutations
.begin();
225 it
!= mutations
.end(); ++it
) {
226 list
->Append(EntryKernelMutationToValue(it
->second
));
231 base::DictionaryValue
* EntryKernelMutationToValue(
232 const EntryKernelMutation
& mutation
) {
233 base::DictionaryValue
* dict
= new base::DictionaryValue();
234 dict
->Set("original", mutation
.original
.ToValue(NULL
));
235 dict
->Set("mutated", mutation
.mutated
.ToValue(NULL
));
239 } // namespace syncer
240 } // namespace syncable