| 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 |