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