Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / sync / syncable / entry_kernel.cc
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.
4
5 #include "sync/syncable/entry_kernel.h"
6
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"
11
12 namespace syncer {
13 namespace syncable {
14
15 EntryKernel::EntryKernel() : dirty_(false) {
16   // Everything else should already be default-initialized.
17   for (int i = INT64_FIELDS_BEGIN; i < INT64_FIELDS_END; ++i) {
18     int64_fields[i] = 0;
19   }
20 }
21
22 EntryKernel::~EntryKernel() {}
23
24 ModelType EntryKernel::GetModelType() const {
25   ModelType specifics_type = GetModelTypeFromSpecifics(ref(SPECIFICS));
26   if (specifics_type != UNSPECIFIED)
27     return specifics_type;
28   if (ref(ID).IsRoot())
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;
34
35   return UNSPECIFIED;
36 }
37
38 ModelType EntryKernel::GetServerModelType() const {
39   ModelType specifics_type = GetModelTypeFromSpecifics(ref(SERVER_SPECIFICS));
40   if (specifics_type != UNSPECIFIED)
41     return specifics_type;
42   if (ref(ID).IsRoot())
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;
48
49   return UNSPECIFIED;
50 }
51
52 bool EntryKernel::ShouldMaintainPosition() const {
53   // We maintain positions for all bookmarks, except those that are
54   // server-created top-level folders.
55   return (GetModelTypeFromSpecifics(ref(SPECIFICS)) == syncer::BOOKMARKS)
56       && !(!ref(UNIQUE_SERVER_TAG).empty() && ref(IS_DIR));
57 }
58
59 bool EntryKernel::ShouldMaintainHierarchy() const {
60   // We maintain hierarchy for bookmarks, device info, 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 (GetModelTypeFromSpecifics(ref(SPECIFICS)) == syncer::BOOKMARKS)
64       || (!ref(UNIQUE_SERVER_TAG).empty());
65 }
66
67 namespace {
68
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.
71 //
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);
85   }
86 }
87
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);
97
98     base::DictionaryValue* value = NULL;
99     sync_pb::EntitySpecifics decrypted;
100     const sync_pb::EncryptedData& encrypted = kernel.ref(field).encrypted();
101     if (cryptographer &&
102         kernel.ref(field).has_encrypted() &&
103         cryptographer->CanDecrypt(encrypted) &&
104         cryptographer->Decrypt(encrypted, &decrypted)) {
105       value = EntitySpecificsToValue(decrypted);
106       value->SetBoolean("encrypted", true);
107     } else {
108       value = EntitySpecificsToValue(kernel.ref(field));
109     }
110     dictionary_value->Set(key, value);
111   }
112 }
113
114 // Helper functions for SetFieldValues().
115
116 base::StringValue* Int64ToValue(int64 i) {
117   return new base::StringValue(base::Int64ToString(i));
118 }
119
120 base::StringValue* TimeToValue(const base::Time& t) {
121   return new base::StringValue(GetTimeDebugString(t));
122 }
123
124 base::StringValue* IdToValue(const Id& id) {
125   return id.ToValue();
126 }
127
128 base::FundamentalValue* BooleanToValue(bool bool_val) {
129   return new base::FundamentalValue(bool_val);
130 }
131
132 base::StringValue* StringToValue(const std::string& str) {
133   return new base::StringValue(str);
134 }
135
136 base::StringValue* UniquePositionToValue(const UniquePosition& pos) {
137   return new base::StringValue(pos.ToDebugString());
138 }
139
140 base::StringValue* AttachmentMetadataToValue(
141     const sync_pb::AttachmentMetadata& a) {
142   return new base::StringValue(a.SerializeAsString());
143 }
144
145 }  // namespace
146
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   kernel_info->Set("serverModelType", ModelTypeToValue(GetServerModelType()));
152
153   // Int64 fields.
154   SetFieldValues(*this, kernel_info,
155                  &GetMetahandleFieldString, &Int64ToValue,
156                  INT64_FIELDS_BEGIN, META_HANDLE);
157   SetFieldValues(*this, kernel_info,
158                  &GetBaseVersionString, &Int64ToValue,
159                  META_HANDLE + 1, BASE_VERSION);
160   SetFieldValues(*this, kernel_info,
161                  &GetInt64FieldString, &Int64ToValue,
162                  BASE_VERSION + 1, INT64_FIELDS_END - 1);
163
164   // Time fields.
165   SetFieldValues(*this, kernel_info,
166                  &GetTimeFieldString, &TimeToValue,
167                  TIME_FIELDS_BEGIN, TIME_FIELDS_END - 1);
168
169   // ID fields.
170   SetFieldValues(*this, kernel_info,
171                  &GetIdFieldString, &IdToValue,
172                  ID_FIELDS_BEGIN, ID_FIELDS_END - 1);
173
174   // Bit fields.
175   SetFieldValues(*this, kernel_info,
176                  &GetIndexedBitFieldString, &BooleanToValue,
177                  BIT_FIELDS_BEGIN, INDEXED_BIT_FIELDS_END - 1);
178   SetFieldValues(*this, kernel_info,
179                  &GetIsDelFieldString, &BooleanToValue,
180                  INDEXED_BIT_FIELDS_END, IS_DEL);
181   SetFieldValues(*this, kernel_info,
182                  &GetBitFieldString, &BooleanToValue,
183                  IS_DEL + 1, BIT_FIELDS_END - 1);
184
185   // String fields.
186   {
187     // Pick out the function overload we want.
188     SetFieldValues(*this, kernel_info,
189                    &GetStringFieldString, &StringToValue,
190                    STRING_FIELDS_BEGIN, STRING_FIELDS_END - 1);
191   }
192
193   // Proto fields.
194   SetEncryptableProtoValues(*this, cryptographer, kernel_info,
195                             PROTO_FIELDS_BEGIN, PROTO_FIELDS_END - 1);
196
197   // UniquePosition fields
198   SetFieldValues(*this, kernel_info,
199                  &GetUniquePositionFieldString, &UniquePositionToValue,
200                  UNIQUE_POSITION_FIELDS_BEGIN, UNIQUE_POSITION_FIELDS_END - 1);
201
202   // AttachmentMetadata fields
203   SetFieldValues(*this,
204                  kernel_info,
205                  &GetAttachmentMetadataFieldString,
206                  &AttachmentMetadataToValue,
207                  ATTACHMENT_METADATA_FIELDS_BEGIN,
208                  ATTACHMENT_METADATA_FIELDS_END - 1);
209
210   // Bit temps.
211   SetFieldValues(*this, kernel_info,
212                  &GetBitTempString, &BooleanToValue,
213                  BIT_TEMPS_BEGIN, BIT_TEMPS_END - 1);
214
215   return kernel_info;
216 }
217
218 base::ListValue* EntryKernelMutationMapToValue(
219     const EntryKernelMutationMap& mutations) {
220   base::ListValue* list = new base::ListValue();
221   for (EntryKernelMutationMap::const_iterator it = mutations.begin();
222        it != mutations.end(); ++it) {
223     list->Append(EntryKernelMutationToValue(it->second));
224   }
225   return list;
226 }
227
228 base::DictionaryValue* EntryKernelMutationToValue(
229     const EntryKernelMutation& mutation) {
230   base::DictionaryValue* dict = new base::DictionaryValue();
231   dict->Set("original", mutation.original.ToValue(NULL));
232   dict->Set("mutated", mutation.mutated.ToValue(NULL));
233   return dict;
234 }
235
236 }  // namespace syncer
237 }  // namespace syncable