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 12namespace syncer { 13namespace syncable { 14 15EntryKernel::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 22EntryKernel::~EntryKernel() {} 23 24ModelType 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 38ModelType 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 52bool 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 59namespace { 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. 65template <class T, class U, class V> 66void 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 80void 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 108base::StringValue* Int64ToValue(int64 i) { 109 return new base::StringValue(base::Int64ToString(i)); 110} 111 112base::StringValue* TimeToValue(const base::Time& t) { 113 return new base::StringValue(GetTimeDebugString(t)); 114} 115 116base::StringValue* IdToValue(const Id& id) { 117 return id.ToValue(); 118} 119 120base::FundamentalValue* BooleanToValue(bool bool_val) { 121 return new base::FundamentalValue(bool_val); 122} 123 124base::StringValue* StringToValue(const std::string& str) { 125 return new base::StringValue(str); 126} 127 128base::StringValue* UniquePositionToValue(const UniquePosition& pos) { 129 return base::Value::CreateStringValue(pos.ToDebugString()); 130} 131 132} // namespace 133 134base::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 197base::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 207base::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 217