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 base::StringValue* AttachmentMetadataToValue( 133 const sync_pb::AttachmentMetadata& a) { 134 return new base::StringValue(a.SerializeAsString()); 135 } 136 137 } // namespace 138 139 base::DictionaryValue* EntryKernel::ToValue( 140 Cryptographer* cryptographer) const { 141 base::DictionaryValue* kernel_info = new base::DictionaryValue(); 142 kernel_info->SetBoolean("isDirty", is_dirty()); 143 kernel_info->Set("serverModelType", ModelTypeToValue(GetServerModelType())); 144 145 // Int64 fields. 146 SetFieldValues(*this, kernel_info, 147 &GetMetahandleFieldString, &Int64ToValue, 148 INT64_FIELDS_BEGIN, META_HANDLE); 149 SetFieldValues(*this, kernel_info, 150 &GetBaseVersionString, &Int64ToValue, 151 META_HANDLE + 1, BASE_VERSION); 152 SetFieldValues(*this, kernel_info, 153 &GetInt64FieldString, &Int64ToValue, 154 BASE_VERSION + 1, INT64_FIELDS_END - 1); 155 156 // Time fields. 157 SetFieldValues(*this, kernel_info, 158 &GetTimeFieldString, &TimeToValue, 159 TIME_FIELDS_BEGIN, TIME_FIELDS_END - 1); 160 161 // ID fields. 162 SetFieldValues(*this, kernel_info, 163 &GetIdFieldString, &IdToValue, 164 ID_FIELDS_BEGIN, ID_FIELDS_END - 1); 165 166 // Bit fields. 167 SetFieldValues(*this, kernel_info, 168 &GetIndexedBitFieldString, &BooleanToValue, 169 BIT_FIELDS_BEGIN, INDEXED_BIT_FIELDS_END - 1); 170 SetFieldValues(*this, kernel_info, 171 &GetIsDelFieldString, &BooleanToValue, 172 INDEXED_BIT_FIELDS_END, IS_DEL); 173 SetFieldValues(*this, kernel_info, 174 &GetBitFieldString, &BooleanToValue, 175 IS_DEL + 1, BIT_FIELDS_END - 1); 176 177 // String fields. 178 { 179 // Pick out the function overload we want. 180 SetFieldValues(*this, kernel_info, 181 &GetStringFieldString, &StringToValue, 182 STRING_FIELDS_BEGIN, STRING_FIELDS_END - 1); 183 } 184 185 // Proto fields. 186 SetEncryptableProtoValues(*this, cryptographer, kernel_info, 187 PROTO_FIELDS_BEGIN, PROTO_FIELDS_END - 1); 188 189 // UniquePosition fields 190 SetFieldValues(*this, kernel_info, 191 &GetUniquePositionFieldString, &UniquePositionToValue, 192 UNIQUE_POSITION_FIELDS_BEGIN, UNIQUE_POSITION_FIELDS_END - 1); 193 194 // AttachmentMetadata fields 195 SetFieldValues(*this, 196 kernel_info, 197 &GetAttachmentMetadataFieldString, 198 &AttachmentMetadataToValue, 199 ATTACHMENT_METADATA_FIELDS_BEGIN, 200 ATTACHMENT_METADATA_FIELDS_END - 1); 201 202 // Bit temps. 203 SetFieldValues(*this, kernel_info, 204 &GetBitTempString, &BooleanToValue, 205 BIT_TEMPS_BEGIN, BIT_TEMPS_END - 1); 206 207 return kernel_info; 208 } 209 210 base::ListValue* EntryKernelMutationMapToValue( 211 const EntryKernelMutationMap& mutations) { 212 base::ListValue* list = new base::ListValue(); 213 for (EntryKernelMutationMap::const_iterator it = mutations.begin(); 214 it != mutations.end(); ++it) { 215 list->Append(EntryKernelMutationToValue(it->second)); 216 } 217 return list; 218 } 219 220 base::DictionaryValue* EntryKernelMutationToValue( 221 const EntryKernelMutation& mutation) { 222 base::DictionaryValue* dict = new base::DictionaryValue(); 223 dict->Set("original", mutation.original.ToValue(NULL)); 224 dict->Set("mutated", mutation.mutated.ToValue(NULL)); 225 return dict; 226 } 227 228 } // namespace syncer 229 } // namespace syncable 230