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/api/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 using syncer::Attachment;
20 using syncer::AttachmentIdList;
21 using syncer::AttachmentList;
22
23 namespace {
24
AttachmentToProto(const syncer::Attachment & attachment)25 sync_pb::AttachmentIdProto AttachmentToProto(
26 const syncer::Attachment& attachment) {
27 return attachment.GetId().GetProto();
28 }
29
IdToProto(const syncer::AttachmentId & attachment_id)30 sync_pb::AttachmentIdProto IdToProto(
31 const syncer::AttachmentId& attachment_id) {
32 return attachment_id.GetProto();
33 }
34
ProtoToId(const sync_pb::AttachmentIdProto & proto)35 syncer::AttachmentId ProtoToId(const sync_pb::AttachmentIdProto& proto) {
36 return syncer::AttachmentId::CreateFromProto(proto);
37 }
38
39 // Return true iff |attachments| contains one or more elements with the same
40 // AttachmentId.
ContainsDuplicateAttachments(const syncer::AttachmentList & attachments)41 bool ContainsDuplicateAttachments(const syncer::AttachmentList& attachments) {
42 std::set<syncer::AttachmentId> id_set;
43 AttachmentList::const_iterator iter = attachments.begin();
44 AttachmentList::const_iterator end = attachments.end();
45 for (; iter != end; ++iter) {
46 if (id_set.find(iter->GetId()) != id_set.end()) {
47 return true;
48 }
49 id_set.insert(iter->GetId());
50 }
51 return false;
52 }
53
54 } // namespace
55
56 namespace syncer {
57
InitializeWrapper(Wrapper * wrapper)58 void SyncData::ImmutableSyncEntityTraits::InitializeWrapper(Wrapper* wrapper) {
59 *wrapper = new sync_pb::SyncEntity();
60 }
61
DestroyWrapper(Wrapper * wrapper)62 void SyncData::ImmutableSyncEntityTraits::DestroyWrapper(Wrapper* wrapper) {
63 delete *wrapper;
64 }
65
Unwrap(const Wrapper & wrapper)66 const sync_pb::SyncEntity& SyncData::ImmutableSyncEntityTraits::Unwrap(
67 const Wrapper& wrapper) {
68 return *wrapper;
69 }
70
UnwrapMutable(Wrapper * wrapper)71 sync_pb::SyncEntity* SyncData::ImmutableSyncEntityTraits::UnwrapMutable(
72 Wrapper* wrapper) {
73 return *wrapper;
74 }
75
Swap(sync_pb::SyncEntity * t1,sync_pb::SyncEntity * t2)76 void SyncData::ImmutableSyncEntityTraits::Swap(sync_pb::SyncEntity* t1,
77 sync_pb::SyncEntity* t2) {
78 t1->Swap(t2);
79 }
80
SyncData()81 SyncData::SyncData() : id_(kInvalidId), is_valid_(false) {}
82
SyncData(int64 id,sync_pb::SyncEntity * entity,AttachmentList * attachments,const base::Time & remote_modification_time,const syncer::AttachmentServiceProxy & attachment_service)83 SyncData::SyncData(int64 id,
84 sync_pb::SyncEntity* entity,
85 AttachmentList* attachments,
86 const base::Time& remote_modification_time,
87 const syncer::AttachmentServiceProxy& attachment_service)
88 : id_(id),
89 remote_modification_time_(remote_modification_time),
90 immutable_entity_(entity),
91 attachments_(attachments),
92 attachment_service_(attachment_service),
93 is_valid_(true) {}
94
~SyncData()95 SyncData::~SyncData() {}
96
97 // Static.
CreateLocalDelete(const std::string & sync_tag,ModelType datatype)98 SyncData SyncData::CreateLocalDelete(const std::string& sync_tag,
99 ModelType datatype) {
100 sync_pb::EntitySpecifics specifics;
101 AddDefaultFieldValue(datatype, &specifics);
102 return CreateLocalData(sync_tag, std::string(), specifics);
103 }
104
105 // Static.
CreateLocalData(const std::string & sync_tag,const std::string & non_unique_title,const sync_pb::EntitySpecifics & specifics)106 SyncData SyncData::CreateLocalData(const std::string& sync_tag,
107 const std::string& non_unique_title,
108 const sync_pb::EntitySpecifics& specifics) {
109 syncer::AttachmentList attachments;
110 return CreateLocalDataWithAttachments(
111 sync_tag, non_unique_title, specifics, attachments);
112 }
113
114 // Static.
CreateLocalDataWithAttachments(const std::string & sync_tag,const std::string & non_unique_title,const sync_pb::EntitySpecifics & specifics,const AttachmentList & attachments)115 SyncData SyncData::CreateLocalDataWithAttachments(
116 const std::string& sync_tag,
117 const std::string& non_unique_title,
118 const sync_pb::EntitySpecifics& specifics,
119 const AttachmentList& attachments) {
120 DCHECK(!ContainsDuplicateAttachments(attachments));
121 sync_pb::SyncEntity entity;
122 entity.set_client_defined_unique_tag(sync_tag);
123 entity.set_non_unique_name(non_unique_title);
124 entity.mutable_specifics()->CopyFrom(specifics);
125 std::transform(attachments.begin(),
126 attachments.end(),
127 RepeatedFieldBackInserter(entity.mutable_attachment_id()),
128 AttachmentToProto);
129 AttachmentList copy_of_attachments(attachments);
130 return SyncData(kInvalidId,
131 &entity,
132 ©_of_attachments,
133 base::Time(),
134 AttachmentServiceProxy());
135 }
136
137 // Static.
CreateRemoteData(int64 id,const sync_pb::EntitySpecifics & specifics,const base::Time & modification_time,const AttachmentIdList & attachment_ids,const AttachmentServiceProxy & attachment_service)138 SyncData SyncData::CreateRemoteData(
139 int64 id,
140 const sync_pb::EntitySpecifics& specifics,
141 const base::Time& modification_time,
142 const AttachmentIdList& attachment_ids,
143 const AttachmentServiceProxy& attachment_service) {
144 DCHECK_NE(id, kInvalidId);
145 sync_pb::SyncEntity entity;
146 entity.mutable_specifics()->CopyFrom(specifics);
147 std::transform(attachment_ids.begin(),
148 attachment_ids.end(),
149 RepeatedFieldBackInserter(entity.mutable_attachment_id()),
150 IdToProto);
151 AttachmentList attachments;
152 return SyncData(
153 id, &entity, &attachments, modification_time, attachment_service);
154 }
155
IsValid() const156 bool SyncData::IsValid() const { return is_valid_; }
157
GetSpecifics() const158 const sync_pb::EntitySpecifics& SyncData::GetSpecifics() const {
159 return immutable_entity_.Get().specifics();
160 }
161
GetDataType() const162 ModelType SyncData::GetDataType() const {
163 return GetModelTypeFromSpecifics(GetSpecifics());
164 }
165
GetTitle() const166 const std::string& SyncData::GetTitle() const {
167 // TODO(zea): set this for data coming from the syncer too.
168 DCHECK(immutable_entity_.Get().has_non_unique_name());
169 return immutable_entity_.Get().non_unique_name();
170 }
171
IsLocal() const172 bool SyncData::IsLocal() const { return id_ == kInvalidId; }
173
ToString() const174 std::string SyncData::ToString() const {
175 if (!IsValid())
176 return "<Invalid SyncData>";
177
178 std::string type = ModelTypeToString(GetDataType());
179 std::string specifics;
180 scoped_ptr<base::DictionaryValue> value(
181 EntitySpecificsToValue(GetSpecifics()));
182 base::JSONWriter::WriteWithOptions(
183 value.get(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &specifics);
184
185 if (IsLocal()) {
186 SyncDataLocal sync_data_local(*this);
187 return "{ isLocal: true, type: " + type + ", tag: " +
188 sync_data_local.GetTag() + ", title: " + GetTitle() +
189 ", specifics: " + specifics + "}";
190 }
191
192 SyncDataRemote sync_data_remote(*this);
193 std::string id = base::Int64ToString(sync_data_remote.GetId());
194 return "{ isLocal: false, type: " + type + ", specifics: " + specifics +
195 ", id: " + id + "}";
196 }
197
PrintTo(const SyncData & sync_data,std::ostream * os)198 void PrintTo(const SyncData& sync_data, std::ostream* os) {
199 *os << sync_data.ToString();
200 }
201
GetAttachmentIds() const202 AttachmentIdList SyncData::GetAttachmentIds() const {
203 AttachmentIdList result;
204 const sync_pb::SyncEntity& entity = immutable_entity_.Get();
205 std::transform(entity.attachment_id().begin(),
206 entity.attachment_id().end(),
207 std::back_inserter(result),
208 ProtoToId);
209 return result;
210 }
211
SyncDataLocal(const SyncData & sync_data)212 SyncDataLocal::SyncDataLocal(const SyncData& sync_data) : SyncData(sync_data) {
213 DCHECK(sync_data.IsLocal());
214 }
215
~SyncDataLocal()216 SyncDataLocal::~SyncDataLocal() {}
217
GetLocalAttachmentsForUpload() const218 const AttachmentList& SyncDataLocal::GetLocalAttachmentsForUpload() const {
219 return attachments_.Get();
220 }
221
GetTag() const222 const std::string& SyncDataLocal::GetTag() const {
223 return immutable_entity_.Get().client_defined_unique_tag();
224 }
225
SyncDataRemote(const SyncData & sync_data)226 SyncDataRemote::SyncDataRemote(const SyncData& sync_data)
227 : SyncData(sync_data) {
228 DCHECK(!sync_data.IsLocal());
229 }
230
~SyncDataRemote()231 SyncDataRemote::~SyncDataRemote() {}
232
GetModifiedTime() const233 const base::Time& SyncDataRemote::GetModifiedTime() const {
234 return remote_modification_time_;
235 }
236
GetId() const237 int64 SyncDataRemote::GetId() const {
238 return id_;
239 }
240
GetOrDownloadAttachments(const AttachmentIdList & attachment_ids,const AttachmentService::GetOrDownloadCallback & callback)241 void SyncDataRemote::GetOrDownloadAttachments(
242 const AttachmentIdList& attachment_ids,
243 const AttachmentService::GetOrDownloadCallback& callback) {
244 attachment_service_.GetOrDownloadAttachments(attachment_ids, callback);
245 }
246
DropAttachments(const AttachmentIdList & attachment_ids,const AttachmentService::DropCallback & callback)247 void SyncDataRemote::DropAttachments(
248 const AttachmentIdList& attachment_ids,
249 const AttachmentService::DropCallback& callback) {
250 attachment_service_.DropAttachments(attachment_ids, callback);
251 }
252
253 } // namespace syncer
254