12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/entry.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <iomanip>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/string_escape.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/blob.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/directory.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "sync/syncable/syncable_base_transaction.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/syncable/syncable_columns.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::string;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace syncer {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace syncable {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Entry::Entry(BaseTransaction* trans, GetById, const Id& id)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : basetrans_(trans) {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kernel_ = trans->directory()->GetEntryById(id);
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Entry::Entry(BaseTransaction* trans, GetByClientTag, const string& tag)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : basetrans_(trans) {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kernel_ = trans->directory()->GetEntryByClientTag(tag);
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)Entry::Entry(BaseTransaction* trans, GetTypeRoot, ModelType type)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : basetrans_(trans) {
3346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const std::string& tag = ModelTypeToRootTag(type);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kernel_ = trans->directory()->GetEntryByServerTag(tag);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Entry::Entry(BaseTransaction* trans, GetByHandle, int64 metahandle)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : basetrans_(trans) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  kernel_ = trans->directory()->GetEntryByHandle(metahandle);
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)Entry::Entry(BaseTransaction* trans, GetByServerTag, const string& tag)
4346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : basetrans_(trans) {
4446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  kernel_ = trans->directory()->GetEntryByServerTag(tag);
4546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
4646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Directory* Entry::dir() const {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return basetrans_->directory();
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbase::DictionaryValue* Entry::ToValue(Cryptographer* cryptographer) const {
52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::DictionaryValue* entry_info = new base::DictionaryValue();
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  entry_info->SetBoolean("good", good());
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (good()) {
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    entry_info->Set("kernel", kernel_->ToValue(cryptographer));
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry_info->Set("modelType",
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ModelTypeToValue(GetModelType()));
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry_info->SetBoolean("existsOnClientBecauseNameIsNonEmpty",
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           ExistsOnClientBecauseNameIsNonEmpty());
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    entry_info->SetBoolean("isRoot", IsRoot());
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return entry_info;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ModelType Entry::GetServerModelType() const {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ModelType specifics_type = kernel_->GetServerModelType();
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (specifics_type != UNSPECIFIED)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return specifics_type;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Otherwise, we don't have a server type yet.  That should only happen
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if the item is an uncommitted locally created item.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It's possible we'll need to relax these checks in the future; they're
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // just here for now as a safety measure.
74d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(GetIsUnsynced());
75d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK_EQ(GetServerVersion(), 0);
76d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  DCHECK(GetServerIsDel());
77d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Note: can't enforce !GetId().ServerKnows() here because that could
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // actually happen if we hit AttemptReuniteLostCommitResponses.
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return UNSPECIFIED;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ModelType Entry::GetModelType() const {
83d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  ModelType specifics_type = GetModelTypeFromSpecifics(GetSpecifics());
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (specifics_type != UNSPECIFIED)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return specifics_type;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsRoot())
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TOP_LEVEL_FOLDER;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Loose check for server-created top-level folders that aren't
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bound to a particular model type.
90d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (!GetUniqueServerTag().empty() && GetIsDir())
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TOP_LEVEL_FOLDER;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return UNSPECIFIED;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Id Entry::GetPredecessorId() const {
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return dir()->GetPredecessorId(kernel_);
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Id Entry::GetSuccessorId() const {
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return dir()->GetSuccessorId(kernel_);
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Id Entry::GetFirstChildId() const {
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return dir()->GetFirstChildId(basetrans_, kernel_);
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void Entry::GetChildHandles(std::vector<int64>* result) const {
109d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  dir()->GetChildHandlesById(basetrans_, GetId(), result);
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int Entry::GetTotalNodeCount() const {
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return dir()->GetTotalNodeCount(basetrans_, kernel_);
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)int Entry::GetPositionIndex() const {
1177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return dir()->GetPositionIndex(basetrans_, kernel_);
1187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool Entry::ShouldMaintainPosition() const {
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return kernel_->ShouldMaintainPosition();
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
124116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool Entry::ShouldMaintainHierarchy() const {
125116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return kernel_->ShouldMaintainHierarchy();
126116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
127116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::ostream& operator<<(std::ostream& s, const Blob& blob) {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (Blob::const_iterator i = blob.begin(); i != blob.end(); ++i)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    s << std::hex << std::setw(2)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << std::setfill('0') << static_cast<unsigned int>(*i);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return s << std::dec;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::ostream& operator<<(std::ostream& os, const Entry& entry) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EntryKernel* const kernel = entry.kernel_;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = BEGIN_FIELDS; i < INT64_FIELDS_END; ++i) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    os << g_metas_columns[i].name << ": "
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << kernel->ref(static_cast<Int64Field>(i)) << ", ";
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for ( ; i < TIME_FIELDS_END; ++i) {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    os << g_metas_columns[i].name << ": "
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << GetTimeDebugString(kernel->ref(static_cast<TimeField>(i))) << ", ";
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for ( ; i < ID_FIELDS_END; ++i) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    os << g_metas_columns[i].name << ": "
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << kernel->ref(static_cast<IdField>(i)) << ", ";
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  os << "Flags: ";
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for ( ; i < BIT_FIELDS_END; ++i) {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (kernel->ref(static_cast<BitField>(i)))
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      os << g_metas_columns[i].name << ", ";
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for ( ; i < STRING_FIELDS_END; ++i) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& field = kernel->ref(static_cast<StringField>(i));
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    os << g_metas_columns[i].name << ": " << field << ", ";
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for ( ; i < PROTO_FIELDS_END; ++i) {
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::string escaped_str = base::EscapeBytesAsInvalidJSONString(
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kernel->ref(static_cast<ProtoField>(i)).SerializeAsString(),
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        false);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    os << g_metas_columns[i].name << ": " << escaped_str << ", ";
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for ( ; i < UNIQUE_POSITION_FIELDS_END; ++i) {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    os << g_metas_columns[i].name << ": "
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       << kernel->ref(static_cast<UniquePositionField>(i)).ToDebugString()
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << ", ";
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
170e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  for ( ; i < ATTACHMENT_METADATA_FIELDS_END; ++i) {
171e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    std::string escaped_str = base::EscapeBytesAsInvalidJSONString(
172e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        kernel->ref(static_cast<AttachmentMetadataField>(i))
173e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch            .SerializeAsString(),
174e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        false);
175e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    os << g_metas_columns[i].name << ": " << escaped_str << ", ";
176e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  os << "TempFlags: ";
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for ( ; i < BIT_TEMPS_END; ++i) {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (kernel->ref(static_cast<BitTemp>(i)))
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      os << "#" << i - BIT_TEMPS_BEGIN << ", ";
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return os;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace syncable
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace syncer
187