OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "sync/internal_api/public/base_node.h" | 5 #include "sync/internal_api/public/base_node.h" |
6 | 6 |
7 #include <stack> | 7 #include <stack> |
8 | 8 |
9 #include "base/base64.h" | |
10 #include "base/sha1.h" | |
11 #include "base/string_number_conversions.h" | 9 #include "base/string_number_conversions.h" |
12 #include "base/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
13 #include "base/values.h" | 11 #include "base/values.h" |
14 #include "sync/internal_api/public/base_transaction.h" | 12 #include "sync/internal_api/public/base_transaction.h" |
15 #include "sync/internal_api/syncapi_internal.h" | 13 #include "sync/internal_api/syncapi_internal.h" |
16 #include "sync/protocol/app_specifics.pb.h" | 14 #include "sync/protocol/app_specifics.pb.h" |
17 #include "sync/protocol/autofill_specifics.pb.h" | 15 #include "sync/protocol/autofill_specifics.pb.h" |
18 #include "sync/protocol/bookmark_specifics.pb.h" | 16 #include "sync/protocol/bookmark_specifics.pb.h" |
19 #include "sync/protocol/extension_specifics.pb.h" | 17 #include "sync/protocol/extension_specifics.pb.h" |
20 #include "sync/protocol/nigori_specifics.pb.h" | 18 #include "sync/protocol/nigori_specifics.pb.h" |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 EndsWithSpace(server_name)) { | 56 EndsWithSpace(server_name)) { |
59 --length_to_copy; | 57 --length_to_copy; |
60 } | 58 } |
61 *out = std::string(server_name.c_str(), length_to_copy); | 59 *out = std::string(server_name.c_str(), length_to_copy); |
62 } | 60 } |
63 | 61 |
64 BaseNode::BaseNode() : password_data_(new sync_pb::PasswordSpecificsData) {} | 62 BaseNode::BaseNode() : password_data_(new sync_pb::PasswordSpecificsData) {} |
65 | 63 |
66 BaseNode::~BaseNode() {} | 64 BaseNode::~BaseNode() {} |
67 | 65 |
68 std::string BaseNode::GenerateSyncableHash( | |
69 ModelType model_type, const std::string& client_tag) { | |
70 // Blank PB with just the field in it has termination symbol, | |
71 // handy for delimiter. | |
72 sync_pb::EntitySpecifics serialized_type; | |
73 AddDefaultFieldValue(model_type, &serialized_type); | |
74 std::string hash_input; | |
75 serialized_type.AppendToString(&hash_input); | |
76 hash_input.append(client_tag); | |
77 | |
78 std::string encode_output; | |
79 CHECK(base::Base64Encode(base::SHA1HashString(hash_input), &encode_output)); | |
80 return encode_output; | |
81 } | |
82 | |
83 bool BaseNode::DecryptIfNecessary() { | 66 bool BaseNode::DecryptIfNecessary() { |
84 if (!GetEntry()->Get(syncable::UNIQUE_SERVER_TAG).empty()) | 67 if (!GetEntry()->Get(syncable::UNIQUE_SERVER_TAG).empty()) |
85 return true; // Ignore unique folders. | 68 return true; // Ignore unique folders. |
86 const sync_pb::EntitySpecifics& specifics = | 69 const sync_pb::EntitySpecifics& specifics = |
87 GetEntry()->Get(syncable::SPECIFICS); | 70 GetEntry()->Get(syncable::SPECIFICS); |
88 if (specifics.has_password()) { | 71 if (specifics.has_password()) { |
89 // Passwords have their own legacy encryption structure. | 72 // Passwords have their own legacy encryption structure. |
90 scoped_ptr<sync_pb::PasswordSpecificsData> data(DecryptPasswordSpecifics( | 73 scoped_ptr<sync_pb::PasswordSpecificsData> data(DecryptPasswordSpecifics( |
91 specifics, GetTransaction()->GetCryptographer())); | 74 specifics, GetTransaction()->GetCryptographer())); |
92 if (!data.get()) { | 75 if (!data.get()) { |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 return result; | 188 return result; |
206 } | 189 } |
207 | 190 |
208 bool BaseNode::HasChildren() const { | 191 bool BaseNode::HasChildren() const { |
209 syncable::Directory* dir = GetTransaction()->GetDirectory(); | 192 syncable::Directory* dir = GetTransaction()->GetDirectory(); |
210 syncable::BaseTransaction* trans = GetTransaction()->GetWrappedTrans(); | 193 syncable::BaseTransaction* trans = GetTransaction()->GetWrappedTrans(); |
211 return dir->HasChildren(trans, GetEntry()->Get(syncable::ID)); | 194 return dir->HasChildren(trans, GetEntry()->Get(syncable::ID)); |
212 } | 195 } |
213 | 196 |
214 int64 BaseNode::GetPredecessorId() const { | 197 int64 BaseNode::GetPredecessorId() const { |
215 syncable::Id id_string = GetEntry()->Get(syncable::PREV_ID); | 198 syncable::Id id_string = GetEntry()->GetPredecessorId(); |
216 if (id_string.IsRoot()) | 199 if (id_string.IsRoot()) |
217 return kInvalidId; | 200 return kInvalidId; |
218 return IdToMetahandle(GetTransaction()->GetWrappedTrans(), id_string); | 201 return IdToMetahandle(GetTransaction()->GetWrappedTrans(), id_string); |
219 } | 202 } |
220 | 203 |
221 int64 BaseNode::GetSuccessorId() const { | 204 int64 BaseNode::GetSuccessorId() const { |
222 syncable::Id id_string = GetEntry()->Get(syncable::NEXT_ID); | 205 syncable::Id id_string = GetEntry()->GetSuccessorId(); |
223 if (id_string.IsRoot()) | 206 if (id_string.IsRoot()) |
224 return kInvalidId; | 207 return kInvalidId; |
225 return IdToMetahandle(GetTransaction()->GetWrappedTrans(), id_string); | 208 return IdToMetahandle(GetTransaction()->GetWrappedTrans(), id_string); |
226 } | 209 } |
227 | 210 |
228 int64 BaseNode::GetFirstChildId() const { | 211 int64 BaseNode::GetFirstChildId() const { |
229 syncable::Directory* dir = GetTransaction()->GetDirectory(); | 212 syncable::Id id_string = GetEntry()->GetFirstChildId(); |
230 syncable::BaseTransaction* trans = GetTransaction()->GetWrappedTrans(); | |
231 syncable::Id id_string; | |
232 // TODO(akalin): Propagate up the error further (see | |
233 // http://crbug.com/100907). | |
234 CHECK(dir->GetFirstChildId(trans, | |
235 GetEntry()->Get(syncable::ID), &id_string)); | |
236 if (id_string.IsRoot()) | 213 if (id_string.IsRoot()) |
237 return kInvalidId; | 214 return kInvalidId; |
238 return IdToMetahandle(GetTransaction()->GetWrappedTrans(), id_string); | 215 return IdToMetahandle(GetTransaction()->GetWrappedTrans(), id_string); |
239 } | 216 } |
240 | 217 |
241 int BaseNode::GetTotalNodeCount() const { | 218 int BaseNode::GetTotalNodeCount() const { |
242 syncable::Directory* dir = GetTransaction()->GetDirectory(); | |
243 syncable::BaseTransaction* trans = GetTransaction()->GetWrappedTrans(); | 219 syncable::BaseTransaction* trans = GetTransaction()->GetWrappedTrans(); |
244 | 220 |
245 int count = 1; // Start with one to include the node itself. | 221 int count = 1; // Start with one to include the node itself. |
246 | 222 |
247 std::stack<int64> stack; | 223 std::stack<int64> stack; |
248 stack.push(GetFirstChildId()); | 224 stack.push(GetFirstChildId()); |
249 while (!stack.empty()) { | 225 while (!stack.empty()) { |
250 int64 handle = stack.top(); | 226 int64 handle = stack.top(); |
251 stack.pop(); | 227 stack.pop(); |
252 if (handle == kInvalidId) | 228 if (handle == kInvalidId) |
253 continue; | 229 continue; |
254 count++; | 230 count++; |
255 syncable::Entry entry(trans, syncable::GET_BY_HANDLE, handle); | 231 syncable::Entry entry(trans, syncable::GET_BY_HANDLE, handle); |
256 if (!entry.good()) | 232 if (!entry.good()) |
257 continue; | 233 continue; |
258 syncable::Id id = entry.Get(syncable::ID); | 234 syncable::Id id = entry.Get(syncable::ID); |
259 syncable::Id child_id; | 235 syncable::Id successor_id = entry.GetSuccessorId(); |
260 if (dir->GetFirstChildId(trans, id, &child_id) && !child_id.IsRoot()) | |
261 stack.push(IdToMetahandle(trans, child_id)); | |
262 syncable::Id successor_id = entry.Get(syncable::NEXT_ID); | |
263 if (!successor_id.IsRoot()) | 236 if (!successor_id.IsRoot()) |
264 stack.push(IdToMetahandle(trans, successor_id)); | 237 stack.push(IdToMetahandle(trans, successor_id)); |
| 238 if (!entry.Get(syncable::IS_DIR)) |
| 239 continue; |
| 240 syncable::Id child_id = entry.GetFirstChildId(); |
| 241 if (!child_id.IsRoot()) |
| 242 stack.push(IdToMetahandle(trans, child_id)); |
265 } | 243 } |
266 return count; | 244 return count; |
267 } | 245 } |
268 | 246 |
269 DictionaryValue* BaseNode::GetSummaryAsValue() const { | 247 DictionaryValue* BaseNode::GetSummaryAsValue() const { |
270 DictionaryValue* node_info = new DictionaryValue(); | 248 DictionaryValue* node_info = new DictionaryValue(); |
271 node_info->SetString("id", base::Int64ToString(GetId())); | 249 node_info->SetString("id", base::Int64ToString(GetId())); |
272 node_info->SetBoolean("isFolder", GetIsFolder()); | 250 node_info->SetBoolean("isFolder", GetIsFolder()); |
273 node_info->SetString("title", GetTitle()); | 251 node_info->SetString("title", GetTitle()); |
274 node_info->Set("type", ModelTypeToValue(GetModelType())); | 252 node_info->Set("type", ModelTypeToValue(GetModelType())); |
275 return node_info; | 253 return node_info; |
276 } | 254 } |
277 | 255 |
278 DictionaryValue* BaseNode::GetDetailsAsValue() const { | 256 DictionaryValue* BaseNode::GetDetailsAsValue() const { |
279 DictionaryValue* node_info = GetSummaryAsValue(); | 257 DictionaryValue* node_info = GetSummaryAsValue(); |
280 node_info->SetString( | 258 node_info->SetString( |
281 "modificationTime", | 259 "modificationTime", |
282 GetTimeDebugString(GetModificationTime())); | 260 GetTimeDebugString(GetModificationTime())); |
283 node_info->SetString("parentId", base::Int64ToString(GetParentId())); | 261 node_info->SetString("parentId", base::Int64ToString(GetParentId())); |
284 // Specifics are already in the Entry value, so no need to duplicate | 262 // Specifics are already in the Entry value, so no need to duplicate |
285 // it here. | 263 // it here. |
286 node_info->SetString("externalId", | 264 node_info->SetString("externalId", |
287 base::Int64ToString(GetExternalId())); | 265 base::Int64ToString(GetExternalId())); |
288 node_info->SetString("predecessorId", | |
289 base::Int64ToString(GetPredecessorId())); | |
290 node_info->SetString("successorId", | |
291 base::Int64ToString(GetSuccessorId())); | |
292 node_info->SetString("firstChildId", | |
293 base::Int64ToString(GetFirstChildId())); | |
294 node_info->Set("entry", | 266 node_info->Set("entry", |
295 GetEntry()->ToValue(GetTransaction()->GetCryptographer())); | 267 GetEntry()->ToValue(GetTransaction()->GetCryptographer())); |
296 return node_info; | 268 return node_info; |
297 } | 269 } |
298 | 270 |
299 int64 BaseNode::GetExternalId() const { | 271 int64 BaseNode::GetExternalId() const { |
300 return GetEntry()->Get(syncable::LOCAL_EXTERNAL_ID); | 272 return GetEntry()->Get(syncable::LOCAL_EXTERNAL_ID); |
301 } | 273 } |
302 | 274 |
303 const sync_pb::AppSpecifics& BaseNode::GetAppSpecifics() const { | 275 const sync_pb::AppSpecifics& BaseNode::GetAppSpecifics() const { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 const sync_pb::EntitySpecifics& specifics) { | 344 const sync_pb::EntitySpecifics& specifics) { |
373 ModelType type = GetModelTypeFromSpecifics(specifics); | 345 ModelType type = GetModelTypeFromSpecifics(specifics); |
374 DCHECK_NE(UNSPECIFIED, type); | 346 DCHECK_NE(UNSPECIFIED, type); |
375 if (GetModelType() != UNSPECIFIED) { | 347 if (GetModelType() != UNSPECIFIED) { |
376 DCHECK_EQ(GetModelType(), type); | 348 DCHECK_EQ(GetModelType(), type); |
377 } | 349 } |
378 unencrypted_data_.CopyFrom(specifics); | 350 unencrypted_data_.CopyFrom(specifics); |
379 } | 351 } |
380 | 352 |
381 } // namespace syncer | 353 } // namespace syncer |
OLD | NEW |