Upstream version 5.34.104.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 namespace {
60
61 // Utility function to loop through a set of enum values and add the
62 // field keys/values in the kernel to the given dictionary.
63 //
64 // V should be convertible to Value.
65 template <class T, class U, class V>
66 void SetFieldValues(const EntryKernel& kernel,
67                     base::DictionaryValue* dictionary_value,
68                     const char* (*enum_key_fn)(T),
69                     V* (*enum_value_fn)(U),
70                     int field_key_min, int field_key_max) {
71   DCHECK_LE(field_key_min, field_key_max);
72   for (int i = field_key_min; i <= field_key_max; ++i) {
73     T field = static_cast<T>(i);
74     const std::string& key = enum_key_fn(field);
75     V* value = enum_value_fn(kernel.ref(field));
76     dictionary_value->Set(key, value);
77   }
78 }
79
80 void SetEncryptableProtoValues(
81     const EntryKernel& kernel,
82     Cryptographer* cryptographer,
83     base::DictionaryValue* dictionary_value,
84     int field_key_min, int field_key_max) {
85   DCHECK_LE(field_key_min, field_key_max);
86   for (int i = field_key_min; i <= field_key_max; ++i) {
87     ProtoField field = static_cast<ProtoField>(i);
88     const std::string& key = GetProtoFieldString(field);
89
90     base::DictionaryValue* value = NULL;
91     sync_pb::EntitySpecifics decrypted;
92     const sync_pb::EncryptedData& encrypted = kernel.ref(field).encrypted();
93     if (cryptographer &&
94         kernel.ref(field).has_encrypted() &&
95         cryptographer->CanDecrypt(encrypted) &&
96         cryptographer->Decrypt(encrypted, &decrypted)) {
97       value = EntitySpecificsToValue(decrypted);
98       value->SetBoolean("encrypted", true);
99     } else {
100       value = EntitySpecificsToValue(kernel.ref(field));
101     }
102     dictionary_value->Set(key, value);
103   }
104 }
105
106 // Helper functions for SetFieldValues().
107
108 base::StringValue* Int64ToValue(int64 i) {
109   return new base::StringValue(base::Int64ToString(i));
110 }
111
112 base::StringValue* TimeToValue(const base::Time& t) {
113   return new base::StringValue(GetTimeDebugString(t));
114 }
115
116 base::StringValue* IdToValue(const Id& id) {
117   return id.ToValue();
118 }
119
120 base::FundamentalValue* BooleanToValue(bool bool_val) {
121   return new base::FundamentalValue(bool_val);
122 }
123
124 base::StringValue* StringToValue(const std::string& str) {
125   return new base::StringValue(str);
126 }
127
128 base::StringValue* UniquePositionToValue(const UniquePosition& pos) {
129   return new base::StringValue(pos.ToDebugString());
130 }
131
132 }  // namespace
133
134 base::DictionaryValue* EntryKernel::ToValue(
135     Cryptographer* cryptographer) const {
136   base::DictionaryValue* kernel_info = new base::DictionaryValue();
137   kernel_info->SetBoolean("isDirty", is_dirty());
138   kernel_info->Set("serverModelType", ModelTypeToValue(GetServerModelType()));
139
140   // Int64 fields.
141   SetFieldValues(*this, kernel_info,
142                  &GetMetahandleFieldString, &Int64ToValue,
143                  INT64_FIELDS_BEGIN, META_HANDLE);
144   SetFieldValues(*this, kernel_info,
145                  &GetBaseVersionString, &Int64ToValue,
146                  META_HANDLE + 1, BASE_VERSION);
147   SetFieldValues(*this, kernel_info,
148                  &GetInt64FieldString, &Int64ToValue,
149                  BASE_VERSION + 1, INT64_FIELDS_END - 1);
150
151   // Time fields.
152   SetFieldValues(*this, kernel_info,
153                  &GetTimeFieldString, &TimeToValue,
154                  TIME_FIELDS_BEGIN, TIME_FIELDS_END - 1);
155
156   // ID fields.
157   SetFieldValues(*this, kernel_info,
158                  &GetIdFieldString, &IdToValue,
159                  ID_FIELDS_BEGIN, ID_FIELDS_END - 1);
160
161   // Bit fields.
162   SetFieldValues(*this, kernel_info,
163                  &GetIndexedBitFieldString, &BooleanToValue,
164                  BIT_FIELDS_BEGIN, INDEXED_BIT_FIELDS_END - 1);
165   SetFieldValues(*this, kernel_info,
166                  &GetIsDelFieldString, &BooleanToValue,
167                  INDEXED_BIT_FIELDS_END, IS_DEL);
168   SetFieldValues(*this, kernel_info,
169                  &GetBitFieldString, &BooleanToValue,
170                  IS_DEL + 1, BIT_FIELDS_END - 1);
171
172   // String fields.
173   {
174     // Pick out the function overload we want.
175     SetFieldValues(*this, kernel_info,
176                    &GetStringFieldString, &StringToValue,
177                    STRING_FIELDS_BEGIN, STRING_FIELDS_END - 1);
178   }
179
180   // Proto fields.
181   SetEncryptableProtoValues(*this, cryptographer, kernel_info,
182                             PROTO_FIELDS_BEGIN, PROTO_FIELDS_END - 1);
183
184   // UniquePosition fields
185   SetFieldValues(*this, kernel_info,
186                  &GetUniquePositionFieldString, &UniquePositionToValue,
187                  UNIQUE_POSITION_FIELDS_BEGIN, UNIQUE_POSITION_FIELDS_END - 1);
188
189   // Bit temps.
190   SetFieldValues(*this, kernel_info,
191                  &GetBitTempString, &BooleanToValue,
192                  BIT_TEMPS_BEGIN, BIT_TEMPS_END - 1);
193
194   return kernel_info;
195 }
196
197 base::ListValue* EntryKernelMutationMapToValue(
198     const EntryKernelMutationMap& mutations) {
199   base::ListValue* list = new base::ListValue();
200   for (EntryKernelMutationMap::const_iterator it = mutations.begin();
201        it != mutations.end(); ++it) {
202     list->Append(EntryKernelMutationToValue(it->second));
203   }
204   return list;
205 }
206
207 base::DictionaryValue* EntryKernelMutationToValue(
208     const EntryKernelMutation& mutation) {
209   base::DictionaryValue* dict = new base::DictionaryValue();
210   dict->Set("original", mutation.original.ToValue(NULL));
211   dict->Set("mutated", mutation.mutated.ToValue(NULL));
212   return dict;
213 }
214
215 }  // namespace syncer
216 }  // namespace syncable