OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "components/sync/driver/generic_change_processor.h" | 5 #include "components/sync/driver/generic_change_processor.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <string> | 10 #include <string> |
(...skipping 12 matching lines...) Expand all Loading... |
23 #include "components/sync/core/base_node.h" | 23 #include "components/sync/core/base_node.h" |
24 #include "components/sync/core/change_record.h" | 24 #include "components/sync/core/change_record.h" |
25 #include "components/sync/core/read_node.h" | 25 #include "components/sync/core/read_node.h" |
26 #include "components/sync/core/read_transaction.h" | 26 #include "components/sync/core/read_transaction.h" |
27 #include "components/sync/core/write_node.h" | 27 #include "components/sync/core/write_node.h" |
28 #include "components/sync/core/write_transaction.h" | 28 #include "components/sync/core/write_transaction.h" |
29 #include "components/sync/driver/sync_api_component_factory.h" | 29 #include "components/sync/driver/sync_api_component_factory.h" |
30 #include "components/sync/driver/sync_client.h" | 30 #include "components/sync/driver/sync_client.h" |
31 #include "components/sync/syncable/entry.h" // TODO(tim): Bug 123674. | 31 #include "components/sync/syncable/entry.h" // TODO(tim): Bug 123674. |
32 | 32 |
33 namespace sync_driver { | 33 namespace syncer { |
34 | 34 |
35 namespace { | 35 namespace { |
36 | 36 |
37 const int kContextSizeLimit = 1024; // Datatype context size limit. | 37 const int kContextSizeLimit = 1024; // Datatype context size limit. |
38 | 38 |
39 void SetNodeSpecifics(const sync_pb::EntitySpecifics& entity_specifics, | 39 void SetNodeSpecifics(const sync_pb::EntitySpecifics& entity_specifics, |
40 syncer::WriteNode* write_node) { | 40 WriteNode* write_node) { |
41 if (syncer::GetModelTypeFromSpecifics(entity_specifics) == | 41 if (GetModelTypeFromSpecifics(entity_specifics) == PASSWORDS) { |
42 syncer::PASSWORDS) { | |
43 write_node->SetPasswordSpecifics( | 42 write_node->SetPasswordSpecifics( |
44 entity_specifics.password().client_only_encrypted_data()); | 43 entity_specifics.password().client_only_encrypted_data()); |
45 } else { | 44 } else { |
46 write_node->SetEntitySpecifics(entity_specifics); | 45 write_node->SetEntitySpecifics(entity_specifics); |
47 } | 46 } |
48 } | 47 } |
49 | 48 |
50 // Helper function to convert AttachmentId to AttachmentMetadataRecord. | 49 // Helper function to convert AttachmentId to AttachmentMetadataRecord. |
51 sync_pb::AttachmentMetadataRecord AttachmentIdToRecord( | 50 sync_pb::AttachmentMetadataRecord AttachmentIdToRecord( |
52 const syncer::AttachmentId& attachment_id) { | 51 const AttachmentId& attachment_id) { |
53 sync_pb::AttachmentMetadataRecord record; | 52 sync_pb::AttachmentMetadataRecord record; |
54 *record.mutable_id() = attachment_id.GetProto(); | 53 *record.mutable_id() = attachment_id.GetProto(); |
55 return record; | 54 return record; |
56 } | 55 } |
57 | 56 |
58 // Replace |write_nodes|'s attachment ids with |attachment_ids|. | 57 // Replace |write_nodes|'s attachment ids with |attachment_ids|. |
59 void SetAttachmentMetadata(const syncer::AttachmentIdList& attachment_ids, | 58 void SetAttachmentMetadata(const AttachmentIdList& attachment_ids, |
60 syncer::WriteNode* write_node) { | 59 WriteNode* write_node) { |
61 DCHECK(write_node); | 60 DCHECK(write_node); |
62 sync_pb::AttachmentMetadata attachment_metadata; | 61 sync_pb::AttachmentMetadata attachment_metadata; |
63 std::transform( | 62 std::transform( |
64 attachment_ids.begin(), attachment_ids.end(), | 63 attachment_ids.begin(), attachment_ids.end(), |
65 RepeatedFieldBackInserter(attachment_metadata.mutable_record()), | 64 RepeatedFieldBackInserter(attachment_metadata.mutable_record()), |
66 AttachmentIdToRecord); | 65 AttachmentIdToRecord); |
67 write_node->SetAttachmentMetadata(attachment_metadata); | 66 write_node->SetAttachmentMetadata(attachment_metadata); |
68 } | 67 } |
69 | 68 |
70 syncer::SyncData BuildRemoteSyncData( | 69 SyncData BuildRemoteSyncData( |
71 int64_t sync_id, | 70 int64_t sync_id, |
72 const syncer::ReadNode& read_node, | 71 const ReadNode& read_node, |
73 const syncer::AttachmentServiceProxy& attachment_service_proxy) { | 72 const AttachmentServiceProxy& attachment_service_proxy) { |
74 const syncer::AttachmentIdList& attachment_ids = read_node.GetAttachmentIds(); | 73 const AttachmentIdList& attachment_ids = read_node.GetAttachmentIds(); |
75 switch (read_node.GetModelType()) { | 74 switch (read_node.GetModelType()) { |
76 case syncer::PASSWORDS: { | 75 case PASSWORDS: { |
77 // Passwords must be accessed differently, to account for their | 76 // Passwords must be accessed differently, to account for their |
78 // encryption, and stored into a temporary EntitySpecifics. | 77 // encryption, and stored into a temporary EntitySpecifics. |
79 sync_pb::EntitySpecifics password_holder; | 78 sync_pb::EntitySpecifics password_holder; |
80 password_holder.mutable_password() | 79 password_holder.mutable_password() |
81 ->mutable_client_only_encrypted_data() | 80 ->mutable_client_only_encrypted_data() |
82 ->CopyFrom(read_node.GetPasswordSpecifics()); | 81 ->CopyFrom(read_node.GetPasswordSpecifics()); |
83 return syncer::SyncData::CreateRemoteData( | 82 return SyncData::CreateRemoteData( |
84 sync_id, password_holder, read_node.GetModificationTime(), | 83 sync_id, password_holder, read_node.GetModificationTime(), |
85 attachment_ids, attachment_service_proxy); | 84 attachment_ids, attachment_service_proxy); |
86 } | 85 } |
87 case syncer::SESSIONS: | 86 case SESSIONS: |
88 // Include tag hashes for sessions data type to allow discarding during | 87 // Include tag hashes for sessions data type to allow discarding during |
89 // merge if re-hashing by the service gives a different value. This is to | 88 // merge if re-hashing by the service gives a different value. This is to |
90 // allow removal of incorrectly hashed values, see crbug.com/604657. This | 89 // allow removal of incorrectly hashed values, see crbug.com/604657. This |
91 // cannot be done in the processor because only the service knows how to | 90 // cannot be done in the processor because only the service knows how to |
92 // generate a tag from the specifics. We don't set this value for other | 91 // generate a tag from the specifics. We don't set this value for other |
93 // data types because they shouldn't need it and it costs memory to hold | 92 // data types because they shouldn't need it and it costs memory to hold |
94 // another copy of this string around. | 93 // another copy of this string around. |
95 return syncer::SyncData::CreateRemoteData( | 94 return SyncData::CreateRemoteData( |
96 sync_id, read_node.GetEntitySpecifics(), | 95 sync_id, read_node.GetEntitySpecifics(), |
97 read_node.GetModificationTime(), attachment_ids, | 96 read_node.GetModificationTime(), attachment_ids, |
98 attachment_service_proxy, read_node.GetEntry()->GetUniqueClientTag()); | 97 attachment_service_proxy, read_node.GetEntry()->GetUniqueClientTag()); |
99 default: | 98 default: |
100 // Use the specifics directly, encryption has already been handled. | 99 // Use the specifics directly, encryption has already been handled. |
101 return syncer::SyncData::CreateRemoteData( | 100 return SyncData::CreateRemoteData(sync_id, read_node.GetEntitySpecifics(), |
102 sync_id, read_node.GetEntitySpecifics(), | 101 read_node.GetModificationTime(), |
103 read_node.GetModificationTime(), attachment_ids, | 102 attachment_ids, |
104 attachment_service_proxy); | 103 attachment_service_proxy); |
105 } | 104 } |
106 } | 105 } |
107 | 106 |
108 } // namespace | 107 } // namespace |
109 | 108 |
110 GenericChangeProcessor::GenericChangeProcessor( | 109 GenericChangeProcessor::GenericChangeProcessor( |
111 syncer::ModelType type, | 110 ModelType type, |
112 std::unique_ptr<syncer::DataTypeErrorHandler> error_handler, | 111 std::unique_ptr<DataTypeErrorHandler> error_handler, |
113 const base::WeakPtr<syncer::SyncableService>& local_service, | 112 const base::WeakPtr<SyncableService>& local_service, |
114 const base::WeakPtr<syncer::SyncMergeResult>& merge_result, | 113 const base::WeakPtr<SyncMergeResult>& merge_result, |
115 syncer::UserShare* user_share, | 114 UserShare* user_share, |
116 SyncClient* sync_client, | 115 SyncClient* sync_client, |
117 std::unique_ptr<syncer::AttachmentStoreForSync> attachment_store) | 116 std::unique_ptr<AttachmentStoreForSync> attachment_store) |
118 : ChangeProcessor(std::move(error_handler)), | 117 : ChangeProcessor(std::move(error_handler)), |
119 type_(type), | 118 type_(type), |
120 local_service_(local_service), | 119 local_service_(local_service), |
121 merge_result_(merge_result), | 120 merge_result_(merge_result), |
122 share_handle_(user_share), | 121 share_handle_(user_share), |
123 weak_ptr_factory_(this) { | 122 weak_ptr_factory_(this) { |
124 DCHECK(CalledOnValidThread()); | 123 DCHECK(CalledOnValidThread()); |
125 DCHECK_NE(type_, syncer::UNSPECIFIED); | 124 DCHECK_NE(type_, UNSPECIFIED); |
126 if (attachment_store) { | 125 if (attachment_store) { |
127 std::string store_birthday; | 126 std::string store_birthday; |
128 { | 127 { |
129 syncer::ReadTransaction trans(FROM_HERE, share_handle()); | 128 ReadTransaction trans(FROM_HERE, share_handle()); |
130 store_birthday = trans.GetStoreBirthday(); | 129 store_birthday = trans.GetStoreBirthday(); |
131 } | 130 } |
132 attachment_service_ = | 131 attachment_service_ = |
133 sync_client->GetSyncApiComponentFactory()->CreateAttachmentService( | 132 sync_client->GetSyncApiComponentFactory()->CreateAttachmentService( |
134 std::move(attachment_store), *user_share, store_birthday, type, | 133 std::move(attachment_store), *user_share, store_birthday, type, |
135 this); | 134 this); |
136 attachment_service_weak_ptr_factory_.reset( | 135 attachment_service_weak_ptr_factory_.reset( |
137 new base::WeakPtrFactory<syncer::AttachmentService>( | 136 new base::WeakPtrFactory<AttachmentService>(attachment_service_.get())); |
138 attachment_service_.get())); | 137 attachment_service_proxy_ = AttachmentServiceProxy( |
139 attachment_service_proxy_ = syncer::AttachmentServiceProxy( | |
140 base::ThreadTaskRunnerHandle::Get(), | 138 base::ThreadTaskRunnerHandle::Get(), |
141 attachment_service_weak_ptr_factory_->GetWeakPtr()); | 139 attachment_service_weak_ptr_factory_->GetWeakPtr()); |
142 UploadAllAttachmentsNotOnServer(); | 140 UploadAllAttachmentsNotOnServer(); |
143 } else { | 141 } else { |
144 attachment_service_proxy_ = syncer::AttachmentServiceProxy( | 142 attachment_service_proxy_ = |
145 base::ThreadTaskRunnerHandle::Get(), | 143 AttachmentServiceProxy(base::ThreadTaskRunnerHandle::Get(), |
146 base::WeakPtr<syncer::AttachmentService>()); | 144 base::WeakPtr<AttachmentService>()); |
147 } | 145 } |
148 } | 146 } |
149 | 147 |
150 GenericChangeProcessor::~GenericChangeProcessor() { | 148 GenericChangeProcessor::~GenericChangeProcessor() { |
151 DCHECK(CalledOnValidThread()); | 149 DCHECK(CalledOnValidThread()); |
152 } | 150 } |
153 | 151 |
154 void GenericChangeProcessor::ApplyChangesFromSyncModel( | 152 void GenericChangeProcessor::ApplyChangesFromSyncModel( |
155 const syncer::BaseTransaction* trans, | 153 const BaseTransaction* trans, |
156 int64_t model_version, | 154 int64_t model_version, |
157 const syncer::ImmutableChangeRecordList& changes) { | 155 const ImmutableChangeRecordList& changes) { |
158 DCHECK(CalledOnValidThread()); | 156 DCHECK(CalledOnValidThread()); |
159 DCHECK(syncer_changes_.empty()); | 157 DCHECK(syncer_changes_.empty()); |
160 for (syncer::ChangeRecordList::const_iterator it = changes.Get().begin(); | 158 for (ChangeRecordList::const_iterator it = changes.Get().begin(); |
161 it != changes.Get().end(); ++it) { | 159 it != changes.Get().end(); ++it) { |
162 if (it->action == syncer::ChangeRecord::ACTION_DELETE) { | 160 if (it->action == ChangeRecord::ACTION_DELETE) { |
163 std::unique_ptr<sync_pb::EntitySpecifics> specifics; | 161 std::unique_ptr<sync_pb::EntitySpecifics> specifics; |
164 if (it->specifics.has_password()) { | 162 if (it->specifics.has_password()) { |
165 DCHECK(it->extra.get()); | 163 DCHECK(it->extra.get()); |
166 specifics.reset(new sync_pb::EntitySpecifics(it->specifics)); | 164 specifics.reset(new sync_pb::EntitySpecifics(it->specifics)); |
167 specifics->mutable_password() | 165 specifics->mutable_password() |
168 ->mutable_client_only_encrypted_data() | 166 ->mutable_client_only_encrypted_data() |
169 ->CopyFrom(it->extra->unencrypted()); | 167 ->CopyFrom(it->extra->unencrypted()); |
170 } | 168 } |
171 const syncer::AttachmentIdList empty_list_of_attachment_ids; | 169 const AttachmentIdList empty_list_of_attachment_ids; |
172 syncer_changes_.push_back(syncer::SyncChange( | 170 syncer_changes_.push_back(SyncChange( |
173 FROM_HERE, syncer::SyncChange::ACTION_DELETE, | 171 FROM_HERE, SyncChange::ACTION_DELETE, |
174 syncer::SyncData::CreateRemoteData( | 172 SyncData::CreateRemoteData( |
175 it->id, specifics ? *specifics : it->specifics, base::Time(), | 173 it->id, specifics ? *specifics : it->specifics, base::Time(), |
176 empty_list_of_attachment_ids, attachment_service_proxy_))); | 174 empty_list_of_attachment_ids, attachment_service_proxy_))); |
177 } else { | 175 } else { |
178 syncer::SyncChange::SyncChangeType action = | 176 SyncChange::SyncChangeType action = |
179 (it->action == syncer::ChangeRecord::ACTION_ADD) | 177 (it->action == ChangeRecord::ACTION_ADD) ? SyncChange::ACTION_ADD |
180 ? syncer::SyncChange::ACTION_ADD | 178 : SyncChange::ACTION_UPDATE; |
181 : syncer::SyncChange::ACTION_UPDATE; | |
182 // Need to load specifics from node. | 179 // Need to load specifics from node. |
183 syncer::ReadNode read_node(trans); | 180 ReadNode read_node(trans); |
184 if (read_node.InitByIdLookup(it->id) != syncer::BaseNode::INIT_OK) { | 181 if (read_node.InitByIdLookup(it->id) != BaseNode::INIT_OK) { |
185 syncer::SyncError error( | 182 SyncError error(FROM_HERE, SyncError::DATATYPE_ERROR, |
186 FROM_HERE, syncer::SyncError::DATATYPE_ERROR, | 183 "Failed to look up data for received change with id " + |
187 "Failed to look up data for received change with id " + | 184 base::Int64ToString(it->id), |
188 base::Int64ToString(it->id), | 185 GetModelTypeFromSpecifics(it->specifics)); |
189 syncer::GetModelTypeFromSpecifics(it->specifics)); | |
190 error_handler()->OnUnrecoverableError(error); | 186 error_handler()->OnUnrecoverableError(error); |
191 return; | 187 return; |
192 } | 188 } |
193 syncer_changes_.push_back(syncer::SyncChange( | 189 syncer_changes_.push_back(SyncChange( |
194 FROM_HERE, action, | 190 FROM_HERE, action, |
195 BuildRemoteSyncData(it->id, read_node, attachment_service_proxy_))); | 191 BuildRemoteSyncData(it->id, read_node, attachment_service_proxy_))); |
196 } | 192 } |
197 } | 193 } |
198 } | 194 } |
199 | 195 |
200 void GenericChangeProcessor::CommitChangesFromSyncModel() { | 196 void GenericChangeProcessor::CommitChangesFromSyncModel() { |
201 DCHECK(CalledOnValidThread()); | 197 DCHECK(CalledOnValidThread()); |
202 if (syncer_changes_.empty()) | 198 if (syncer_changes_.empty()) |
203 return; | 199 return; |
204 if (!local_service_.get()) { | 200 if (!local_service_.get()) { |
205 syncer::ModelType type = syncer_changes_[0].sync_data().GetDataType(); | 201 ModelType type = syncer_changes_[0].sync_data().GetDataType(); |
206 syncer::SyncError error(FROM_HERE, syncer::SyncError::DATATYPE_ERROR, | 202 SyncError error(FROM_HERE, SyncError::DATATYPE_ERROR, |
207 "Local service destroyed.", type); | 203 "Local service destroyed.", type); |
208 error_handler()->OnUnrecoverableError(error); | 204 error_handler()->OnUnrecoverableError(error); |
209 return; | 205 return; |
210 } | 206 } |
211 syncer::SyncError error = | 207 SyncError error = |
212 local_service_->ProcessSyncChanges(FROM_HERE, syncer_changes_); | 208 local_service_->ProcessSyncChanges(FROM_HERE, syncer_changes_); |
213 syncer_changes_.clear(); | 209 syncer_changes_.clear(); |
214 if (error.IsSet()) | 210 if (error.IsSet()) |
215 error_handler()->OnUnrecoverableError(error); | 211 error_handler()->OnUnrecoverableError(error); |
216 } | 212 } |
217 | 213 |
218 syncer::SyncDataList GenericChangeProcessor::GetAllSyncData( | 214 SyncDataList GenericChangeProcessor::GetAllSyncData(ModelType type) const { |
219 syncer::ModelType type) const { | |
220 DCHECK_EQ(type_, type); | 215 DCHECK_EQ(type_, type); |
221 // This is slow / memory intensive. Should be used sparingly by datatypes. | 216 // This is slow / memory intensive. Should be used sparingly by datatypes. |
222 syncer::SyncDataList data; | 217 SyncDataList data; |
223 GetAllSyncDataReturnError(&data); | 218 GetAllSyncDataReturnError(&data); |
224 return data; | 219 return data; |
225 } | 220 } |
226 | 221 |
227 syncer::SyncError GenericChangeProcessor::UpdateDataTypeContext( | 222 SyncError GenericChangeProcessor::UpdateDataTypeContext( |
228 syncer::ModelType type, | 223 ModelType type, |
229 syncer::SyncChangeProcessor::ContextRefreshStatus refresh_status, | 224 SyncChangeProcessor::ContextRefreshStatus refresh_status, |
230 const std::string& context) { | 225 const std::string& context) { |
231 DCHECK(syncer::ProtocolTypes().Has(type)); | 226 DCHECK(ProtocolTypes().Has(type)); |
232 DCHECK_EQ(type_, type); | 227 DCHECK_EQ(type_, type); |
233 | 228 |
234 if (context.size() > static_cast<size_t>(kContextSizeLimit)) { | 229 if (context.size() > static_cast<size_t>(kContextSizeLimit)) { |
235 return syncer::SyncError(FROM_HERE, syncer::SyncError::DATATYPE_ERROR, | 230 return SyncError(FROM_HERE, SyncError::DATATYPE_ERROR, |
236 "Context size limit exceeded.", type); | 231 "Context size limit exceeded.", type); |
237 } | 232 } |
238 | 233 |
239 syncer::WriteTransaction trans(FROM_HERE, share_handle()); | 234 WriteTransaction trans(FROM_HERE, share_handle()); |
240 trans.SetDataTypeContext(type, refresh_status, context); | 235 trans.SetDataTypeContext(type, refresh_status, context); |
241 | 236 |
242 // TODO(zea): plumb a pointer to the PSS or SyncManagerImpl here so we can | 237 // TODO(zea): plumb a pointer to the PSS or SyncManagerImpl here so we can |
243 // trigger a datatype nudge if |refresh_status == REFRESH_NEEDED|. | 238 // trigger a datatype nudge if |refresh_status == REFRESH_NEEDED|. |
244 | 239 |
245 return syncer::SyncError(); | 240 return SyncError(); |
246 } | 241 } |
247 | 242 |
248 void GenericChangeProcessor::AddLocalChangeObserver( | 243 void GenericChangeProcessor::AddLocalChangeObserver( |
249 syncer::LocalChangeObserver* observer) { | 244 LocalChangeObserver* observer) { |
250 local_change_observers_.AddObserver(observer); | 245 local_change_observers_.AddObserver(observer); |
251 } | 246 } |
252 | 247 |
253 void GenericChangeProcessor::RemoveLocalChangeObserver( | 248 void GenericChangeProcessor::RemoveLocalChangeObserver( |
254 syncer::LocalChangeObserver* observer) { | 249 LocalChangeObserver* observer) { |
255 local_change_observers_.RemoveObserver(observer); | 250 local_change_observers_.RemoveObserver(observer); |
256 } | 251 } |
257 | 252 |
258 void GenericChangeProcessor::OnAttachmentUploaded( | 253 void GenericChangeProcessor::OnAttachmentUploaded( |
259 const syncer::AttachmentId& attachment_id) { | 254 const AttachmentId& attachment_id) { |
260 syncer::WriteTransaction trans(FROM_HERE, share_handle()); | 255 WriteTransaction trans(FROM_HERE, share_handle()); |
261 trans.UpdateEntriesMarkAttachmentAsOnServer(attachment_id); | 256 trans.UpdateEntriesMarkAttachmentAsOnServer(attachment_id); |
262 } | 257 } |
263 | 258 |
264 syncer::SyncError GenericChangeProcessor::GetAllSyncDataReturnError( | 259 SyncError GenericChangeProcessor::GetAllSyncDataReturnError( |
265 syncer::SyncDataList* current_sync_data) const { | 260 SyncDataList* current_sync_data) const { |
266 DCHECK(CalledOnValidThread()); | 261 DCHECK(CalledOnValidThread()); |
267 std::string type_name = syncer::ModelTypeToString(type_); | 262 std::string type_name = ModelTypeToString(type_); |
268 syncer::ReadTransaction trans(FROM_HERE, share_handle()); | 263 ReadTransaction trans(FROM_HERE, share_handle()); |
269 syncer::ReadNode root(&trans); | 264 ReadNode root(&trans); |
270 if (root.InitTypeRoot(type_) != syncer::BaseNode::INIT_OK) { | 265 if (root.InitTypeRoot(type_) != BaseNode::INIT_OK) { |
271 syncer::SyncError error(FROM_HERE, syncer::SyncError::DATATYPE_ERROR, | 266 SyncError error(FROM_HERE, SyncError::DATATYPE_ERROR, |
272 "Server did not create the top-level " + type_name + | 267 "Server did not create the top-level " + type_name + |
273 " node. We might be running against an out-of-" | 268 " node. We might be running against an out-of-" |
274 "date server.", | 269 "date server.", |
275 type_); | 270 type_); |
276 return error; | 271 return error; |
277 } | 272 } |
278 | 273 |
279 // TODO(akalin): We'll have to do a tree traversal for bookmarks. | 274 // TODO(akalin): We'll have to do a tree traversal for bookmarks. |
280 DCHECK_NE(type_, syncer::BOOKMARKS); | 275 DCHECK_NE(type_, BOOKMARKS); |
281 | 276 |
282 std::vector<int64_t> child_ids; | 277 std::vector<int64_t> child_ids; |
283 root.GetChildIds(&child_ids); | 278 root.GetChildIds(&child_ids); |
284 | 279 |
285 for (std::vector<int64_t>::iterator it = child_ids.begin(); | 280 for (std::vector<int64_t>::iterator it = child_ids.begin(); |
286 it != child_ids.end(); ++it) { | 281 it != child_ids.end(); ++it) { |
287 syncer::ReadNode sync_child_node(&trans); | 282 ReadNode sync_child_node(&trans); |
288 if (sync_child_node.InitByIdLookup(*it) != syncer::BaseNode::INIT_OK) { | 283 if (sync_child_node.InitByIdLookup(*it) != BaseNode::INIT_OK) { |
289 syncer::SyncError error( | 284 SyncError error(FROM_HERE, SyncError::DATATYPE_ERROR, |
290 FROM_HERE, syncer::SyncError::DATATYPE_ERROR, | 285 "Failed to fetch child node for type " + type_name + ".", |
291 "Failed to fetch child node for type " + type_name + ".", type_); | 286 type_); |
292 return error; | 287 return error; |
293 } | 288 } |
294 current_sync_data->push_back(BuildRemoteSyncData( | 289 current_sync_data->push_back(BuildRemoteSyncData( |
295 sync_child_node.GetId(), sync_child_node, attachment_service_proxy_)); | 290 sync_child_node.GetId(), sync_child_node, attachment_service_proxy_)); |
296 } | 291 } |
297 return syncer::SyncError(); | 292 return SyncError(); |
298 } | 293 } |
299 | 294 |
300 bool GenericChangeProcessor::GetDataTypeContext(std::string* context) const { | 295 bool GenericChangeProcessor::GetDataTypeContext(std::string* context) const { |
301 syncer::ReadTransaction trans(FROM_HERE, share_handle()); | 296 ReadTransaction trans(FROM_HERE, share_handle()); |
302 sync_pb::DataTypeContext context_proto; | 297 sync_pb::DataTypeContext context_proto; |
303 trans.GetDataTypeContext(type_, &context_proto); | 298 trans.GetDataTypeContext(type_, &context_proto); |
304 if (!context_proto.has_context()) | 299 if (!context_proto.has_context()) |
305 return false; | 300 return false; |
306 | 301 |
307 DCHECK_EQ(type_, syncer::GetModelTypeFromSpecificsFieldNumber( | 302 DCHECK_EQ(type_, |
308 context_proto.data_type_id())); | 303 GetModelTypeFromSpecificsFieldNumber(context_proto.data_type_id())); |
309 *context = context_proto.context(); | 304 *context = context_proto.context(); |
310 return true; | 305 return true; |
311 } | 306 } |
312 | 307 |
313 int GenericChangeProcessor::GetSyncCount() { | 308 int GenericChangeProcessor::GetSyncCount() { |
314 syncer::ReadTransaction trans(FROM_HERE, share_handle()); | 309 ReadTransaction trans(FROM_HERE, share_handle()); |
315 syncer::ReadNode root(&trans); | 310 ReadNode root(&trans); |
316 if (root.InitTypeRoot(type_) != syncer::BaseNode::INIT_OK) | 311 if (root.InitTypeRoot(type_) != BaseNode::INIT_OK) |
317 return 0; | 312 return 0; |
318 | 313 |
319 // Subtract one to account for type's root node. | 314 // Subtract one to account for type's root node. |
320 return root.GetTotalNodeCount() - 1; | 315 return root.GetTotalNodeCount() - 1; |
321 } | 316 } |
322 | 317 |
323 namespace { | 318 namespace { |
324 | 319 |
325 // WARNING: this code is sensitive to compiler optimizations. Be careful | 320 // WARNING: this code is sensitive to compiler optimizations. Be careful |
326 // modifying any code around an OnUnrecoverableError call, else the compiler | 321 // modifying any code around an OnUnrecoverableError call, else the compiler |
327 // attempts to merge it with other calls, losing useful information in | 322 // attempts to merge it with other calls, losing useful information in |
328 // breakpad uploads. | 323 // breakpad uploads. |
329 syncer::SyncError LogLookupFailure( | 324 SyncError LogLookupFailure(BaseNode::InitByLookupResult lookup_result, |
330 syncer::BaseNode::InitByLookupResult lookup_result, | 325 const tracked_objects::Location& from_here, |
331 const tracked_objects::Location& from_here, | 326 const std::string& error_prefix, |
332 const std::string& error_prefix, | 327 ModelType type, |
333 syncer::ModelType type, | 328 DataTypeErrorHandler* error_handler) { |
334 syncer::DataTypeErrorHandler* error_handler) { | |
335 switch (lookup_result) { | 329 switch (lookup_result) { |
336 case syncer::BaseNode::INIT_FAILED_ENTRY_NOT_GOOD: { | 330 case BaseNode::INIT_FAILED_ENTRY_NOT_GOOD: { |
337 syncer::SyncError error; | 331 SyncError error; |
338 error.Reset( | 332 error.Reset( |
339 from_here, | 333 from_here, |
340 error_prefix + "could not find entry matching the lookup criteria.", | 334 error_prefix + "could not find entry matching the lookup criteria.", |
341 type); | 335 type); |
342 error_handler->OnUnrecoverableError(error); | 336 error_handler->OnUnrecoverableError(error); |
343 LOG(ERROR) << "Delete: Bad entry."; | 337 LOG(ERROR) << "Delete: Bad entry."; |
344 return error; | 338 return error; |
345 } | 339 } |
346 case syncer::BaseNode::INIT_FAILED_ENTRY_IS_DEL: { | 340 case BaseNode::INIT_FAILED_ENTRY_IS_DEL: { |
347 syncer::SyncError error; | 341 SyncError error; |
348 error.Reset(from_here, error_prefix + "entry is already deleted.", type); | 342 error.Reset(from_here, error_prefix + "entry is already deleted.", type); |
349 error_handler->OnUnrecoverableError(error); | 343 error_handler->OnUnrecoverableError(error); |
350 LOG(ERROR) << "Delete: Deleted entry."; | 344 LOG(ERROR) << "Delete: Deleted entry."; |
351 return error; | 345 return error; |
352 } | 346 } |
353 case syncer::BaseNode::INIT_FAILED_DECRYPT_IF_NECESSARY: { | 347 case BaseNode::INIT_FAILED_DECRYPT_IF_NECESSARY: { |
354 syncer::SyncError error; | 348 SyncError error; |
355 error.Reset(from_here, error_prefix + "unable to decrypt", type); | 349 error.Reset(from_here, error_prefix + "unable to decrypt", type); |
356 error_handler->OnUnrecoverableError(error); | 350 error_handler->OnUnrecoverableError(error); |
357 LOG(ERROR) << "Delete: Undecryptable entry."; | 351 LOG(ERROR) << "Delete: Undecryptable entry."; |
358 return error; | 352 return error; |
359 } | 353 } |
360 case syncer::BaseNode::INIT_FAILED_PRECONDITION: { | 354 case BaseNode::INIT_FAILED_PRECONDITION: { |
361 syncer::SyncError error; | 355 SyncError error; |
362 error.Reset(from_here, | 356 error.Reset(from_here, |
363 error_prefix + "a precondition was not met for calling init.", | 357 error_prefix + "a precondition was not met for calling init.", |
364 type); | 358 type); |
365 error_handler->OnUnrecoverableError(error); | 359 error_handler->OnUnrecoverableError(error); |
366 LOG(ERROR) << "Delete: Failed precondition."; | 360 LOG(ERROR) << "Delete: Failed precondition."; |
367 return error; | 361 return error; |
368 } | 362 } |
369 default: { | 363 default: { |
370 syncer::SyncError error; | 364 SyncError error; |
371 // Should have listed all the possible error cases above. | 365 // Should have listed all the possible error cases above. |
372 error.Reset(from_here, error_prefix + "unknown error", type); | 366 error.Reset(from_here, error_prefix + "unknown error", type); |
373 error_handler->OnUnrecoverableError(error); | 367 error_handler->OnUnrecoverableError(error); |
374 LOG(ERROR) << "Delete: Unknown error."; | 368 LOG(ERROR) << "Delete: Unknown error."; |
375 return error; | 369 return error; |
376 } | 370 } |
377 } | 371 } |
378 } | 372 } |
379 | 373 |
380 } // namespace | 374 } // namespace |
381 | 375 |
382 syncer::SyncError GenericChangeProcessor::AttemptDelete( | 376 SyncError GenericChangeProcessor::AttemptDelete( |
383 const syncer::SyncChange& change, | 377 const SyncChange& change, |
384 syncer::ModelType type, | 378 ModelType type, |
385 const std::string& type_str, | 379 const std::string& type_str, |
386 syncer::WriteNode* node, | 380 WriteNode* node, |
387 syncer::DataTypeErrorHandler* error_handler) { | 381 DataTypeErrorHandler* error_handler) { |
388 DCHECK_EQ(change.change_type(), syncer::SyncChange::ACTION_DELETE); | 382 DCHECK_EQ(change.change_type(), SyncChange::ACTION_DELETE); |
389 if (change.sync_data().IsLocal()) { | 383 if (change.sync_data().IsLocal()) { |
390 const std::string& tag = syncer::SyncDataLocal(change.sync_data()).GetTag(); | 384 const std::string& tag = SyncDataLocal(change.sync_data()).GetTag(); |
391 if (tag.empty()) { | 385 if (tag.empty()) { |
392 syncer::SyncError error(FROM_HERE, syncer::SyncError::DATATYPE_ERROR, | 386 SyncError error(FROM_HERE, SyncError::DATATYPE_ERROR, |
393 "Failed to delete " + type_str + | 387 "Failed to delete " + type_str + |
394 " node. Local data, empty tag. " + | 388 " node. Local data, empty tag. " + |
395 change.location().ToString(), | 389 change.location().ToString(), |
396 type); | 390 type); |
397 error_handler->OnUnrecoverableError(error); | 391 error_handler->OnUnrecoverableError(error); |
398 NOTREACHED(); | 392 NOTREACHED(); |
399 return error; | 393 return error; |
400 } | 394 } |
401 | 395 |
402 syncer::BaseNode::InitByLookupResult result = | 396 BaseNode::InitByLookupResult result = |
403 node->InitByClientTagLookup(change.sync_data().GetDataType(), tag); | 397 node->InitByClientTagLookup(change.sync_data().GetDataType(), tag); |
404 if (result != syncer::BaseNode::INIT_OK) { | 398 if (result != BaseNode::INIT_OK) { |
405 return LogLookupFailure(result, FROM_HERE, | 399 return LogLookupFailure(result, FROM_HERE, |
406 "Failed to delete " + type_str + | 400 "Failed to delete " + type_str + |
407 " node. Local data. " + | 401 " node. Local data. " + |
408 change.location().ToString(), | 402 change.location().ToString(), |
409 type, error_handler); | 403 type, error_handler); |
410 } | 404 } |
411 } else { | 405 } else { |
412 syncer::BaseNode::InitByLookupResult result = node->InitByIdLookup( | 406 BaseNode::InitByLookupResult result = |
413 syncer::SyncDataRemote(change.sync_data()).GetId()); | 407 node->InitByIdLookup(SyncDataRemote(change.sync_data()).GetId()); |
414 if (result != syncer::BaseNode::INIT_OK) { | 408 if (result != BaseNode::INIT_OK) { |
415 return LogLookupFailure(result, FROM_HERE, | 409 return LogLookupFailure(result, FROM_HERE, |
416 "Failed to delete " + type_str + | 410 "Failed to delete " + type_str + |
417 " node. Non-local data. " + | 411 " node. Non-local data. " + |
418 change.location().ToString(), | 412 change.location().ToString(), |
419 type, error_handler); | 413 type, error_handler); |
420 } | 414 } |
421 } | 415 } |
422 NotifyLocalChangeObservers(node->GetEntry(), change); | 416 NotifyLocalChangeObservers(node->GetEntry(), change); |
423 if (IsActOnceDataType(type)) | 417 if (IsActOnceDataType(type)) |
424 node->Drop(); | 418 node->Drop(); |
425 else | 419 else |
426 node->Tombstone(); | 420 node->Tombstone(); |
427 return syncer::SyncError(); | 421 return SyncError(); |
428 } | 422 } |
429 | 423 |
430 syncer::SyncError GenericChangeProcessor::ProcessSyncChanges( | 424 SyncError GenericChangeProcessor::ProcessSyncChanges( |
431 const tracked_objects::Location& from_here, | 425 const tracked_objects::Location& from_here, |
432 const syncer::SyncChangeList& list_of_changes) { | 426 const SyncChangeList& list_of_changes) { |
433 DCHECK(CalledOnValidThread()); | 427 DCHECK(CalledOnValidThread()); |
434 | 428 |
435 if (list_of_changes.empty()) { | 429 if (list_of_changes.empty()) { |
436 // No work. Exit without entering WriteTransaction. | 430 // No work. Exit without entering WriteTransaction. |
437 return syncer::SyncError(); | 431 return SyncError(); |
438 } | 432 } |
439 | 433 |
440 // Keep track of brand new attachments so we can persist them on this device | 434 // Keep track of brand new attachments so we can persist them on this device |
441 // and upload them to the server. | 435 // and upload them to the server. |
442 syncer::AttachmentIdSet new_attachments; | 436 AttachmentIdSet new_attachments; |
443 | 437 |
444 syncer::WriteTransaction trans(from_here, share_handle()); | 438 WriteTransaction trans(from_here, share_handle()); |
445 | 439 |
446 for (syncer::SyncChangeList::const_iterator iter = list_of_changes.begin(); | 440 for (SyncChangeList::const_iterator iter = list_of_changes.begin(); |
447 iter != list_of_changes.end(); ++iter) { | 441 iter != list_of_changes.end(); ++iter) { |
448 const syncer::SyncChange& change = *iter; | 442 const SyncChange& change = *iter; |
449 DCHECK_EQ(change.sync_data().GetDataType(), type_); | 443 DCHECK_EQ(change.sync_data().GetDataType(), type_); |
450 std::string type_str = syncer::ModelTypeToString(type_); | 444 std::string type_str = ModelTypeToString(type_); |
451 syncer::WriteNode sync_node(&trans); | 445 WriteNode sync_node(&trans); |
452 if (change.change_type() == syncer::SyncChange::ACTION_DELETE) { | 446 if (change.change_type() == SyncChange::ACTION_DELETE) { |
453 syncer::SyncError error = | 447 SyncError error = |
454 AttemptDelete(change, type_, type_str, &sync_node, error_handler()); | 448 AttemptDelete(change, type_, type_str, &sync_node, error_handler()); |
455 if (error.IsSet()) { | 449 if (error.IsSet()) { |
456 NOTREACHED(); | 450 NOTREACHED(); |
457 return error; | 451 return error; |
458 } | 452 } |
459 if (merge_result_.get()) { | 453 if (merge_result_.get()) { |
460 merge_result_->set_num_items_deleted( | 454 merge_result_->set_num_items_deleted( |
461 merge_result_->num_items_deleted() + 1); | 455 merge_result_->num_items_deleted() + 1); |
462 } | 456 } |
463 } else if (change.change_type() == syncer::SyncChange::ACTION_ADD) { | 457 } else if (change.change_type() == SyncChange::ACTION_ADD) { |
464 syncer::SyncError error = HandleActionAdd(change, type_str, trans, | 458 SyncError error = HandleActionAdd(change, type_str, trans, &sync_node, |
465 &sync_node, &new_attachments); | 459 &new_attachments); |
466 if (error.IsSet()) { | 460 if (error.IsSet()) { |
467 return error; | 461 return error; |
468 } | 462 } |
469 } else if (change.change_type() == syncer::SyncChange::ACTION_UPDATE) { | 463 } else if (change.change_type() == SyncChange::ACTION_UPDATE) { |
470 syncer::SyncError error = HandleActionUpdate( | 464 SyncError error = HandleActionUpdate(change, type_str, trans, &sync_node, |
471 change, type_str, trans, &sync_node, &new_attachments); | 465 &new_attachments); |
472 if (error.IsSet()) { | 466 if (error.IsSet()) { |
473 return error; | 467 return error; |
474 } | 468 } |
475 } else { | 469 } else { |
476 syncer::SyncError error( | 470 SyncError error(FROM_HERE, SyncError::DATATYPE_ERROR, |
477 FROM_HERE, syncer::SyncError::DATATYPE_ERROR, | 471 "Received unset SyncChange in the change processor, " + |
478 "Received unset SyncChange in the change processor, " + | 472 change.location().ToString(), |
479 change.location().ToString(), | 473 type_); |
480 type_); | |
481 error_handler()->OnUnrecoverableError(error); | 474 error_handler()->OnUnrecoverableError(error); |
482 NOTREACHED(); | 475 NOTREACHED(); |
483 LOG(ERROR) << "Unset sync change."; | 476 LOG(ERROR) << "Unset sync change."; |
484 return error; | 477 return error; |
485 } | 478 } |
486 } | 479 } |
487 | 480 |
488 if (!new_attachments.empty()) { | 481 if (!new_attachments.empty()) { |
489 // If datatype uses attachments it should have supplied attachment store | 482 // If datatype uses attachments it should have supplied attachment store |
490 // which would initialize attachment_service_. Fail if it isn't so. | 483 // which would initialize attachment_service_. Fail if it isn't so. |
491 if (!attachment_service_.get()) { | 484 if (!attachment_service_.get()) { |
492 syncer::SyncError error( | 485 SyncError error( |
493 FROM_HERE, syncer::SyncError::DATATYPE_ERROR, | 486 FROM_HERE, SyncError::DATATYPE_ERROR, |
494 "Datatype performs attachment operation without initializing " | 487 "Datatype performs attachment operation without initializing " |
495 "attachment store", | 488 "attachment store", |
496 type_); | 489 type_); |
497 error_handler()->OnUnrecoverableError(error); | 490 error_handler()->OnUnrecoverableError(error); |
498 NOTREACHED(); | 491 NOTREACHED(); |
499 return error; | 492 return error; |
500 } | 493 } |
501 syncer::AttachmentIdList ids_to_upload; | 494 AttachmentIdList ids_to_upload; |
502 ids_to_upload.reserve(new_attachments.size()); | 495 ids_to_upload.reserve(new_attachments.size()); |
503 std::copy(new_attachments.begin(), new_attachments.end(), | 496 std::copy(new_attachments.begin(), new_attachments.end(), |
504 std::back_inserter(ids_to_upload)); | 497 std::back_inserter(ids_to_upload)); |
505 attachment_service_->UploadAttachments(ids_to_upload); | 498 attachment_service_->UploadAttachments(ids_to_upload); |
506 } | 499 } |
507 | 500 |
508 return syncer::SyncError(); | 501 return SyncError(); |
509 } | 502 } |
510 | 503 |
511 // WARNING: this code is sensitive to compiler optimizations. Be careful | 504 // WARNING: this code is sensitive to compiler optimizations. Be careful |
512 // modifying any code around an OnUnrecoverableError call, else the compiler | 505 // modifying any code around an OnUnrecoverableError call, else the compiler |
513 // attempts to merge it with other calls, losing useful information in | 506 // attempts to merge it with other calls, losing useful information in |
514 // breakpad uploads. | 507 // breakpad uploads. |
515 syncer::SyncError GenericChangeProcessor::HandleActionAdd( | 508 SyncError GenericChangeProcessor::HandleActionAdd( |
516 const syncer::SyncChange& change, | 509 const SyncChange& change, |
517 const std::string& type_str, | 510 const std::string& type_str, |
518 const syncer::WriteTransaction& trans, | 511 const WriteTransaction& trans, |
519 syncer::WriteNode* sync_node, | 512 WriteNode* sync_node, |
520 syncer::AttachmentIdSet* new_attachments) { | 513 AttachmentIdSet* new_attachments) { |
521 // TODO(sync): Handle other types of creation (custom parents, folders, | 514 // TODO(sync): Handle other types of creation (custom parents, folders, |
522 // etc.). | 515 // etc.). |
523 const syncer::SyncDataLocal sync_data_local(change.sync_data()); | 516 const SyncDataLocal sync_data_local(change.sync_data()); |
524 syncer::WriteNode::InitUniqueByCreationResult result = | 517 WriteNode::InitUniqueByCreationResult result = |
525 sync_node->InitUniqueByCreation(sync_data_local.GetDataType(), | 518 sync_node->InitUniqueByCreation(sync_data_local.GetDataType(), |
526 sync_data_local.GetTag()); | 519 sync_data_local.GetTag()); |
527 if (result != syncer::WriteNode::INIT_SUCCESS) { | 520 if (result != WriteNode::INIT_SUCCESS) { |
528 std::string error_prefix = "Failed to create " + type_str + " node: " + | 521 std::string error_prefix = "Failed to create " + type_str + " node: " + |
529 change.location().ToString() + ", "; | 522 change.location().ToString() + ", "; |
530 switch (result) { | 523 switch (result) { |
531 case syncer::WriteNode::INIT_FAILED_EMPTY_TAG: { | 524 case WriteNode::INIT_FAILED_EMPTY_TAG: { |
532 syncer::SyncError error; | 525 SyncError error; |
533 error.Reset(FROM_HERE, error_prefix + "empty tag", type_); | 526 error.Reset(FROM_HERE, error_prefix + "empty tag", type_); |
534 error_handler()->OnUnrecoverableError(error); | 527 error_handler()->OnUnrecoverableError(error); |
535 LOG(ERROR) << "Create: Empty tag."; | 528 LOG(ERROR) << "Create: Empty tag."; |
536 return error; | 529 return error; |
537 } | 530 } |
538 case syncer::WriteNode::INIT_FAILED_COULD_NOT_CREATE_ENTRY: { | 531 case WriteNode::INIT_FAILED_COULD_NOT_CREATE_ENTRY: { |
539 syncer::SyncError error; | 532 SyncError error; |
540 error.Reset(FROM_HERE, error_prefix + "failed to create entry", type_); | 533 error.Reset(FROM_HERE, error_prefix + "failed to create entry", type_); |
541 error_handler()->OnUnrecoverableError(error); | 534 error_handler()->OnUnrecoverableError(error); |
542 LOG(ERROR) << "Create: Could not create entry."; | 535 LOG(ERROR) << "Create: Could not create entry."; |
543 return error; | 536 return error; |
544 } | 537 } |
545 case syncer::WriteNode::INIT_FAILED_SET_PREDECESSOR: { | 538 case WriteNode::INIT_FAILED_SET_PREDECESSOR: { |
546 syncer::SyncError error; | 539 SyncError error; |
547 error.Reset(FROM_HERE, error_prefix + "failed to set predecessor", | 540 error.Reset(FROM_HERE, error_prefix + "failed to set predecessor", |
548 type_); | 541 type_); |
549 error_handler()->OnUnrecoverableError(error); | 542 error_handler()->OnUnrecoverableError(error); |
550 LOG(ERROR) << "Create: Bad predecessor."; | 543 LOG(ERROR) << "Create: Bad predecessor."; |
551 return error; | 544 return error; |
552 } | 545 } |
553 case syncer::WriteNode::INIT_FAILED_DECRYPT_EXISTING_ENTRY: { | 546 case WriteNode::INIT_FAILED_DECRYPT_EXISTING_ENTRY: { |
554 syncer::SyncError error; | 547 SyncError error; |
555 error.Reset(FROM_HERE, error_prefix + "failed to decrypt", type_); | 548 error.Reset(FROM_HERE, error_prefix + "failed to decrypt", type_); |
556 error_handler()->OnUnrecoverableError(error); | 549 error_handler()->OnUnrecoverableError(error); |
557 LOG(ERROR) << "Create: Failed to decrypt."; | 550 LOG(ERROR) << "Create: Failed to decrypt."; |
558 return error; | 551 return error; |
559 } | 552 } |
560 default: { | 553 default: { |
561 syncer::SyncError error; | 554 SyncError error; |
562 error.Reset(FROM_HERE, error_prefix + "unknown error", type_); | 555 error.Reset(FROM_HERE, error_prefix + "unknown error", type_); |
563 error_handler()->OnUnrecoverableError(error); | 556 error_handler()->OnUnrecoverableError(error); |
564 LOG(ERROR) << "Create: Unknown error."; | 557 LOG(ERROR) << "Create: Unknown error."; |
565 return error; | 558 return error; |
566 } | 559 } |
567 } | 560 } |
568 } | 561 } |
569 NotifyLocalChangeObservers(sync_node->GetEntry(), change); | 562 NotifyLocalChangeObservers(sync_node->GetEntry(), change); |
570 | 563 |
571 sync_node->SetTitle(change.sync_data().GetTitle()); | 564 sync_node->SetTitle(change.sync_data().GetTitle()); |
572 SetNodeSpecifics(sync_data_local.GetSpecifics(), sync_node); | 565 SetNodeSpecifics(sync_data_local.GetSpecifics(), sync_node); |
573 | 566 |
574 syncer::AttachmentIdList attachment_ids = sync_data_local.GetAttachmentIds(); | 567 AttachmentIdList attachment_ids = sync_data_local.GetAttachmentIds(); |
575 SetAttachmentMetadata(attachment_ids, sync_node); | 568 SetAttachmentMetadata(attachment_ids, sync_node); |
576 | 569 |
577 // Return any newly added attachments. | 570 // Return any newly added attachments. |
578 new_attachments->insert(attachment_ids.begin(), attachment_ids.end()); | 571 new_attachments->insert(attachment_ids.begin(), attachment_ids.end()); |
579 if (merge_result_.get()) { | 572 if (merge_result_.get()) { |
580 merge_result_->set_num_items_added(merge_result_->num_items_added() + 1); | 573 merge_result_->set_num_items_added(merge_result_->num_items_added() + 1); |
581 } | 574 } |
582 return syncer::SyncError(); | 575 return SyncError(); |
583 } | 576 } |
584 // WARNING: this code is sensitive to compiler optimizations. Be careful | 577 // WARNING: this code is sensitive to compiler optimizations. Be careful |
585 // modifying any code around an OnUnrecoverableError call, else the compiler | 578 // modifying any code around an OnUnrecoverableError call, else the compiler |
586 // attempts to merge it with other calls, losing useful information in | 579 // attempts to merge it with other calls, losing useful information in |
587 // breakpad uploads. | 580 // breakpad uploads. |
588 syncer::SyncError GenericChangeProcessor::HandleActionUpdate( | 581 SyncError GenericChangeProcessor::HandleActionUpdate( |
589 const syncer::SyncChange& change, | 582 const SyncChange& change, |
590 const std::string& type_str, | 583 const std::string& type_str, |
591 const syncer::WriteTransaction& trans, | 584 const WriteTransaction& trans, |
592 syncer::WriteNode* sync_node, | 585 WriteNode* sync_node, |
593 syncer::AttachmentIdSet* new_attachments) { | 586 AttachmentIdSet* new_attachments) { |
594 const syncer::SyncDataLocal sync_data_local(change.sync_data()); | 587 const SyncDataLocal sync_data_local(change.sync_data()); |
595 syncer::BaseNode::InitByLookupResult result = | 588 BaseNode::InitByLookupResult result = sync_node->InitByClientTagLookup( |
596 sync_node->InitByClientTagLookup(sync_data_local.GetDataType(), | 589 sync_data_local.GetDataType(), sync_data_local.GetTag()); |
597 sync_data_local.GetTag()); | 590 if (result != BaseNode::INIT_OK) { |
598 if (result != syncer::BaseNode::INIT_OK) { | |
599 std::string error_prefix = "Failed to load " + type_str + " node. " + | 591 std::string error_prefix = "Failed to load " + type_str + " node. " + |
600 change.location().ToString() + ", "; | 592 change.location().ToString() + ", "; |
601 if (result == syncer::BaseNode::INIT_FAILED_PRECONDITION) { | 593 if (result == BaseNode::INIT_FAILED_PRECONDITION) { |
602 syncer::SyncError error; | 594 SyncError error; |
603 error.Reset(FROM_HERE, error_prefix + "empty tag", type_); | 595 error.Reset(FROM_HERE, error_prefix + "empty tag", type_); |
604 error_handler()->OnUnrecoverableError(error); | 596 error_handler()->OnUnrecoverableError(error); |
605 LOG(ERROR) << "Update: Empty tag."; | 597 LOG(ERROR) << "Update: Empty tag."; |
606 return error; | 598 return error; |
607 } else if (result == syncer::BaseNode::INIT_FAILED_ENTRY_NOT_GOOD) { | 599 } else if (result == BaseNode::INIT_FAILED_ENTRY_NOT_GOOD) { |
608 syncer::SyncError error; | 600 SyncError error; |
609 error.Reset(FROM_HERE, error_prefix + "bad entry", type_); | 601 error.Reset(FROM_HERE, error_prefix + "bad entry", type_); |
610 error_handler()->OnUnrecoverableError(error); | 602 error_handler()->OnUnrecoverableError(error); |
611 LOG(ERROR) << "Update: bad entry."; | 603 LOG(ERROR) << "Update: bad entry."; |
612 return error; | 604 return error; |
613 } else if (result == syncer::BaseNode::INIT_FAILED_ENTRY_IS_DEL) { | 605 } else if (result == BaseNode::INIT_FAILED_ENTRY_IS_DEL) { |
614 syncer::SyncError error; | 606 SyncError error; |
615 error.Reset(FROM_HERE, error_prefix + "deleted entry", type_); | 607 error.Reset(FROM_HERE, error_prefix + "deleted entry", type_); |
616 error_handler()->OnUnrecoverableError(error); | 608 error_handler()->OnUnrecoverableError(error); |
617 LOG(ERROR) << "Update: deleted entry."; | 609 LOG(ERROR) << "Update: deleted entry."; |
618 return error; | 610 return error; |
619 } else if (result == syncer::BaseNode::INIT_FAILED_DECRYPT_IF_NECESSARY) { | 611 } else if (result == BaseNode::INIT_FAILED_DECRYPT_IF_NECESSARY) { |
620 syncer::SyncError error; | 612 SyncError error; |
621 error.Reset(FROM_HERE, error_prefix + "failed to decrypt", type_); | 613 error.Reset(FROM_HERE, error_prefix + "failed to decrypt", type_); |
622 error_handler()->OnUnrecoverableError(error); | 614 error_handler()->OnUnrecoverableError(error); |
623 LOG(ERROR) << "Update: Failed to decrypt."; | 615 LOG(ERROR) << "Update: Failed to decrypt."; |
624 return error; | 616 return error; |
625 } else { | 617 } else { |
626 NOTREACHED(); | 618 NOTREACHED(); |
627 syncer::SyncError error; | 619 SyncError error; |
628 error.Reset(FROM_HERE, error_prefix + "unknown error", type_); | 620 error.Reset(FROM_HERE, error_prefix + "unknown error", type_); |
629 error_handler()->OnUnrecoverableError(error); | 621 error_handler()->OnUnrecoverableError(error); |
630 LOG(ERROR) << "Update: Unknown error."; | 622 LOG(ERROR) << "Update: Unknown error."; |
631 return error; | 623 return error; |
632 } | 624 } |
633 } | 625 } |
634 | 626 |
635 NotifyLocalChangeObservers(sync_node->GetEntry(), change); | 627 NotifyLocalChangeObservers(sync_node->GetEntry(), change); |
636 | 628 |
637 sync_node->SetTitle(change.sync_data().GetTitle()); | 629 sync_node->SetTitle(change.sync_data().GetTitle()); |
638 SetNodeSpecifics(sync_data_local.GetSpecifics(), sync_node); | 630 SetNodeSpecifics(sync_data_local.GetSpecifics(), sync_node); |
639 syncer::AttachmentIdList attachment_ids = sync_data_local.GetAttachmentIds(); | 631 AttachmentIdList attachment_ids = sync_data_local.GetAttachmentIds(); |
640 SetAttachmentMetadata(attachment_ids, sync_node); | 632 SetAttachmentMetadata(attachment_ids, sync_node); |
641 | 633 |
642 // Return any newly added attachments. | 634 // Return any newly added attachments. |
643 new_attachments->insert(attachment_ids.begin(), attachment_ids.end()); | 635 new_attachments->insert(attachment_ids.begin(), attachment_ids.end()); |
644 | 636 |
645 if (merge_result_.get()) { | 637 if (merge_result_.get()) { |
646 merge_result_->set_num_items_modified(merge_result_->num_items_modified() + | 638 merge_result_->set_num_items_modified(merge_result_->num_items_modified() + |
647 1); | 639 1); |
648 } | 640 } |
649 // TODO(sync): Support updating other parts of the sync node (title, | 641 // TODO(sync): Support updating other parts of the sync node (title, |
650 // successor, parent, etc.). | 642 // successor, parent, etc.). |
651 return syncer::SyncError(); | 643 return SyncError(); |
652 } | 644 } |
653 | 645 |
654 bool GenericChangeProcessor::SyncModelHasUserCreatedNodes(bool* has_nodes) { | 646 bool GenericChangeProcessor::SyncModelHasUserCreatedNodes(bool* has_nodes) { |
655 DCHECK(CalledOnValidThread()); | 647 DCHECK(CalledOnValidThread()); |
656 DCHECK(has_nodes); | 648 DCHECK(has_nodes); |
657 std::string type_name = syncer::ModelTypeToString(type_); | 649 std::string type_name = ModelTypeToString(type_); |
658 std::string err_str = | 650 std::string err_str = |
659 "Server did not create the top-level " + type_name + | 651 "Server did not create the top-level " + type_name + |
660 " node. We might be running against an out-of-date server."; | 652 " node. We might be running against an out-of-date server."; |
661 *has_nodes = false; | 653 *has_nodes = false; |
662 syncer::ReadTransaction trans(FROM_HERE, share_handle()); | 654 ReadTransaction trans(FROM_HERE, share_handle()); |
663 syncer::ReadNode type_root_node(&trans); | 655 ReadNode type_root_node(&trans); |
664 if (type_root_node.InitTypeRoot(type_) != syncer::BaseNode::INIT_OK) { | 656 if (type_root_node.InitTypeRoot(type_) != BaseNode::INIT_OK) { |
665 LOG(ERROR) << err_str; | 657 LOG(ERROR) << err_str; |
666 return false; | 658 return false; |
667 } | 659 } |
668 | 660 |
669 // The sync model has user created nodes if the type's root node has any | 661 // The sync model has user created nodes if the type's root node has any |
670 // children. | 662 // children. |
671 *has_nodes = type_root_node.HasChildren(); | 663 *has_nodes = type_root_node.HasChildren(); |
672 return true; | 664 return true; |
673 } | 665 } |
674 | 666 |
675 bool GenericChangeProcessor::CryptoReadyIfNecessary() { | 667 bool GenericChangeProcessor::CryptoReadyIfNecessary() { |
676 DCHECK(CalledOnValidThread()); | 668 DCHECK(CalledOnValidThread()); |
677 // We only access the cryptographer while holding a transaction. | 669 // We only access the cryptographer while holding a transaction. |
678 syncer::ReadTransaction trans(FROM_HERE, share_handle()); | 670 ReadTransaction trans(FROM_HERE, share_handle()); |
679 const syncer::ModelTypeSet encrypted_types = trans.GetEncryptedTypes(); | 671 const ModelTypeSet encrypted_types = trans.GetEncryptedTypes(); |
680 return !encrypted_types.Has(type_) || trans.GetCryptographer()->is_ready(); | 672 return !encrypted_types.Has(type_) || trans.GetCryptographer()->is_ready(); |
681 } | 673 } |
682 | 674 |
683 void GenericChangeProcessor::StartImpl() {} | 675 void GenericChangeProcessor::StartImpl() {} |
684 | 676 |
685 syncer::UserShare* GenericChangeProcessor::share_handle() const { | 677 UserShare* GenericChangeProcessor::share_handle() const { |
686 DCHECK(CalledOnValidThread()); | 678 DCHECK(CalledOnValidThread()); |
687 return share_handle_; | 679 return share_handle_; |
688 } | 680 } |
689 | 681 |
690 void GenericChangeProcessor::UploadAllAttachmentsNotOnServer() { | 682 void GenericChangeProcessor::UploadAllAttachmentsNotOnServer() { |
691 DCHECK(CalledOnValidThread()); | 683 DCHECK(CalledOnValidThread()); |
692 DCHECK(attachment_service_.get()); | 684 DCHECK(attachment_service_.get()); |
693 syncer::AttachmentIdList ids; | 685 AttachmentIdList ids; |
694 { | 686 { |
695 syncer::ReadTransaction trans(FROM_HERE, share_handle()); | 687 ReadTransaction trans(FROM_HERE, share_handle()); |
696 trans.GetAttachmentIdsToUpload(type_, &ids); | 688 trans.GetAttachmentIdsToUpload(type_, &ids); |
697 } | 689 } |
698 if (!ids.empty()) { | 690 if (!ids.empty()) { |
699 attachment_service_->UploadAttachments(ids); | 691 attachment_service_->UploadAttachments(ids); |
700 } | 692 } |
701 } | 693 } |
702 | 694 |
703 void GenericChangeProcessor::NotifyLocalChangeObservers( | 695 void GenericChangeProcessor::NotifyLocalChangeObservers( |
704 const syncer::syncable::Entry* current_entry, | 696 const syncable::Entry* current_entry, |
705 const syncer::SyncChange& change) { | 697 const SyncChange& change) { |
706 FOR_EACH_OBSERVER(syncer::LocalChangeObserver, local_change_observers_, | 698 FOR_EACH_OBSERVER(LocalChangeObserver, local_change_observers_, |
707 OnLocalChange(current_entry, change)); | 699 OnLocalChange(current_entry, change)); |
708 } | 700 } |
709 | 701 |
710 std::unique_ptr<syncer::AttachmentService> | 702 std::unique_ptr<AttachmentService> |
711 GenericChangeProcessor::GetAttachmentService() const { | 703 GenericChangeProcessor::GetAttachmentService() const { |
712 return std::unique_ptr<syncer::AttachmentService>( | 704 return std::unique_ptr<AttachmentService>( |
713 new syncer::AttachmentServiceProxy(attachment_service_proxy_)); | 705 new AttachmentServiceProxy(attachment_service_proxy_)); |
714 } | 706 } |
715 | 707 |
716 } // namespace sync_driver | 708 } // namespace syncer |
OLD | NEW |