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/api/sync_data.h" 6 7 #include <ostream> 8 9 #include "base/json/json_writer.h" 10 #include "base/memory/scoped_ptr.h" 11 #include "base/strings/string_number_conversions.h" 12 #include "base/values.h" 13 #include "sync/internal_api/public/attachments/attachment_service_proxy.h" 14 #include "sync/internal_api/public/base/model_type.h" 15 #include "sync/internal_api/public/base_node.h" 16 #include "sync/protocol/proto_value_conversions.h" 17 #include "sync/protocol/sync.pb.h" 18 19 namespace { 20 21 sync_pb::AttachmentIdProto IdToProto( 22 const syncer::AttachmentId& attachment_id) { 23 return attachment_id.GetProto(); 24 } 25 26 syncer::AttachmentId ProtoToId(const sync_pb::AttachmentIdProto& proto) { 27 return syncer::AttachmentId::CreateFromProto(proto); 28 } 29 30 // Return true iff |attachment_ids| contains duplicates. 31 bool ContainsDuplicateAttachments( 32 const syncer::AttachmentIdList& attachment_ids) { 33 syncer::AttachmentIdSet id_set; 34 id_set.insert(attachment_ids.begin(), attachment_ids.end()); 35 return id_set.size() != attachment_ids.size(); 36 } 37 38 } // namespace 39 40 namespace syncer { 41 42 void SyncData::ImmutableSyncEntityTraits::InitializeWrapper(Wrapper* wrapper) { 43 *wrapper = new sync_pb::SyncEntity(); 44 } 45 46 void SyncData::ImmutableSyncEntityTraits::DestroyWrapper(Wrapper* wrapper) { 47 delete *wrapper; 48 } 49 50 const sync_pb::SyncEntity& SyncData::ImmutableSyncEntityTraits::Unwrap( 51 const Wrapper& wrapper) { 52 return *wrapper; 53 } 54 55 sync_pb::SyncEntity* SyncData::ImmutableSyncEntityTraits::UnwrapMutable( 56 Wrapper* wrapper) { 57 return *wrapper; 58 } 59 60 void SyncData::ImmutableSyncEntityTraits::Swap(sync_pb::SyncEntity* t1, 61 sync_pb::SyncEntity* t2) { 62 t1->Swap(t2); 63 } 64 65 SyncData::SyncData() : id_(kInvalidId), is_valid_(false) {} 66 67 SyncData::SyncData(int64 id, 68 sync_pb::SyncEntity* entity, 69 const base::Time& remote_modification_time, 70 const syncer::AttachmentServiceProxy& attachment_service) 71 : id_(id), 72 remote_modification_time_(remote_modification_time), 73 immutable_entity_(entity), 74 attachment_service_(attachment_service), 75 is_valid_(true) {} 76 77 SyncData::~SyncData() {} 78 79 // Static. 80 SyncData SyncData::CreateLocalDelete(const std::string& sync_tag, 81 ModelType datatype) { 82 sync_pb::EntitySpecifics specifics; 83 AddDefaultFieldValue(datatype, &specifics); 84 return CreateLocalData(sync_tag, std::string(), specifics); 85 } 86 87 // Static. 88 SyncData SyncData::CreateLocalData(const std::string& sync_tag, 89 const std::string& non_unique_title, 90 const sync_pb::EntitySpecifics& specifics) { 91 syncer::AttachmentIdList attachment_ids; 92 return CreateLocalDataWithAttachments( 93 sync_tag, non_unique_title, specifics, attachment_ids); 94 } 95 96 // Static. 97 SyncData SyncData::CreateLocalDataWithAttachments( 98 const std::string& sync_tag, 99 const std::string& non_unique_title, 100 const sync_pb::EntitySpecifics& specifics, 101 const AttachmentIdList& attachment_ids) { 102 DCHECK(!ContainsDuplicateAttachments(attachment_ids)); 103 sync_pb::SyncEntity entity; 104 entity.set_client_defined_unique_tag(sync_tag); 105 entity.set_non_unique_name(non_unique_title); 106 entity.mutable_specifics()->CopyFrom(specifics); 107 std::transform(attachment_ids.begin(), 108 attachment_ids.end(), 109 RepeatedFieldBackInserter(entity.mutable_attachment_id()), 110 IdToProto); 111 return SyncData(kInvalidId, 112 &entity, 113 base::Time(), 114 AttachmentServiceProxy()); 115 } 116 117 // Static. 118 SyncData SyncData::CreateRemoteData( 119 int64 id, 120 const sync_pb::EntitySpecifics& specifics, 121 const base::Time& modification_time, 122 const AttachmentIdList& attachment_ids, 123 const AttachmentServiceProxy& attachment_service) { 124 DCHECK_NE(id, kInvalidId); 125 sync_pb::SyncEntity entity; 126 entity.mutable_specifics()->CopyFrom(specifics); 127 std::transform(attachment_ids.begin(), 128 attachment_ids.end(), 129 RepeatedFieldBackInserter(entity.mutable_attachment_id()), 130 IdToProto); 131 return SyncData(id, &entity, modification_time, attachment_service); 132 } 133 134 bool SyncData::IsValid() const { return is_valid_; } 135 136 const sync_pb::EntitySpecifics& SyncData::GetSpecifics() const { 137 return immutable_entity_.Get().specifics(); 138 } 139 140 ModelType SyncData::GetDataType() const { 141 return GetModelTypeFromSpecifics(GetSpecifics()); 142 } 143 144 const std::string& SyncData::GetTitle() const { 145 // TODO(zea): set this for data coming from the syncer too. 146 DCHECK(immutable_entity_.Get().has_non_unique_name()); 147 return immutable_entity_.Get().non_unique_name(); 148 } 149 150 bool SyncData::IsLocal() const { return id_ == kInvalidId; } 151 152 std::string SyncData::ToString() const { 153 if (!IsValid()) 154 return "<Invalid SyncData>"; 155 156 std::string type = ModelTypeToString(GetDataType()); 157 std::string specifics; 158 scoped_ptr<base::DictionaryValue> value( 159 EntitySpecificsToValue(GetSpecifics())); 160 base::JSONWriter::WriteWithOptions( 161 value.get(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &specifics); 162 163 if (IsLocal()) { 164 SyncDataLocal sync_data_local(*this); 165 return "{ isLocal: true, type: " + type + ", tag: " + 166 sync_data_local.GetTag() + ", title: " + GetTitle() + 167 ", specifics: " + specifics + "}"; 168 } 169 170 SyncDataRemote sync_data_remote(*this); 171 std::string id = base::Int64ToString(sync_data_remote.GetId()); 172 return "{ isLocal: false, type: " + type + ", specifics: " + specifics + 173 ", id: " + id + "}"; 174 } 175 176 void PrintTo(const SyncData& sync_data, std::ostream* os) { 177 *os << sync_data.ToString(); 178 } 179 180 AttachmentIdList SyncData::GetAttachmentIds() const { 181 AttachmentIdList result; 182 const sync_pb::SyncEntity& entity = immutable_entity_.Get(); 183 std::transform(entity.attachment_id().begin(), 184 entity.attachment_id().end(), 185 std::back_inserter(result), 186 ProtoToId); 187 return result; 188 } 189 190 SyncDataLocal::SyncDataLocal(const SyncData& sync_data) : SyncData(sync_data) { 191 DCHECK(sync_data.IsLocal()); 192 } 193 194 SyncDataLocal::~SyncDataLocal() {} 195 196 const std::string& SyncDataLocal::GetTag() const { 197 return immutable_entity_.Get().client_defined_unique_tag(); 198 } 199 200 SyncDataRemote::SyncDataRemote(const SyncData& sync_data) 201 : SyncData(sync_data) { 202 DCHECK(!sync_data.IsLocal()); 203 } 204 205 SyncDataRemote::~SyncDataRemote() {} 206 207 const base::Time& SyncDataRemote::GetModifiedTime() const { 208 return remote_modification_time_; 209 } 210 211 int64 SyncDataRemote::GetId() const { 212 return id_; 213 } 214 215 void SyncDataRemote::GetOrDownloadAttachments( 216 const AttachmentIdList& attachment_ids, 217 const AttachmentService::GetOrDownloadCallback& callback) { 218 attachment_service_.GetOrDownloadAttachments(attachment_ids, callback); 219 } 220 221 void SyncDataRemote::DropAttachments( 222 const AttachmentIdList& attachment_ids, 223 const AttachmentService::DropCallback& callback) { 224 attachment_service_.DropAttachments(attachment_ids, callback); 225 } 226 227 } // namespace syncer 228