| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 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 "chrome/browser/sync/glue/generic_change_processor.h" | 5 #include "chrome/browser/sync/glue/generic_change_processor.h" |
| 6 | 6 |
| 7 #include "base/location.h" | 7 #include "base/location.h" |
| 8 #include "base/string_number_conversions.h" | 8 #include "base/string_number_conversions.h" |
| 9 #include "base/utf_string_conversions.h" | 9 #include "base/utf_string_conversions.h" |
| 10 #include "content/public/browser/browser_thread.h" | 10 #include "content/public/browser/browser_thread.h" |
| 11 #include "sync/api/sync_change.h" | 11 #include "sync/api/sync_change.h" |
| 12 #include "sync/api/sync_error.h" | 12 #include "sync/api/sync_error.h" |
| 13 #include "sync/api/syncable_service.h" | 13 #include "sync/api/syncable_service.h" |
| 14 #include "sync/internal_api/public/base_node.h" | 14 #include "sync/internal_api/public/base_node.h" |
| 15 #include "sync/internal_api/public/change_record.h" | 15 #include "sync/internal_api/public/change_record.h" |
| 16 #include "sync/internal_api/public/read_node.h" | 16 #include "sync/internal_api/public/read_node.h" |
| 17 #include "sync/internal_api/public/read_transaction.h" | 17 #include "sync/internal_api/public/read_transaction.h" |
| 18 #include "sync/internal_api/public/util/unrecoverable_error_handler.h" | 18 #include "sync/internal_api/public/util/unrecoverable_error_handler.h" |
| 19 #include "sync/internal_api/public/write_node.h" | 19 #include "sync/internal_api/public/write_node.h" |
| 20 #include "sync/internal_api/public/write_transaction.h" | 20 #include "sync/internal_api/public/write_transaction.h" |
| 21 #include "sync/syncable/entry.h" // TODO(tim): Bug 123674. | 21 #include "sync/syncable/entry.h" // TODO(tim): Bug 123674. |
| 22 | 22 |
| 23 using content::BrowserThread; | 23 using content::BrowserThread; |
| 24 | 24 |
| 25 namespace browser_sync { | 25 namespace browser_sync { |
| 26 | 26 |
| 27 GenericChangeProcessor::GenericChangeProcessor( | 27 GenericChangeProcessor::GenericChangeProcessor( |
| 28 DataTypeErrorHandler* error_handler, | 28 DataTypeErrorHandler* error_handler, |
| 29 const base::WeakPtr<SyncableService>& local_service, | 29 const base::WeakPtr<csync::SyncableService>& local_service, |
| 30 csync::UserShare* user_share) | 30 csync::UserShare* user_share) |
| 31 : ChangeProcessor(error_handler), | 31 : ChangeProcessor(error_handler), |
| 32 local_service_(local_service), | 32 local_service_(local_service), |
| 33 share_handle_(user_share) { | 33 share_handle_(user_share) { |
| 34 DCHECK(CalledOnValidThread()); | 34 DCHECK(CalledOnValidThread()); |
| 35 } | 35 } |
| 36 | 36 |
| 37 GenericChangeProcessor::~GenericChangeProcessor() { | 37 GenericChangeProcessor::~GenericChangeProcessor() { |
| 38 DCHECK(CalledOnValidThread()); | 38 DCHECK(CalledOnValidThread()); |
| 39 } | 39 } |
| 40 | 40 |
| 41 void GenericChangeProcessor::ApplyChangesFromSyncModel( | 41 void GenericChangeProcessor::ApplyChangesFromSyncModel( |
| 42 const csync::BaseTransaction* trans, | 42 const csync::BaseTransaction* trans, |
| 43 const csync::ImmutableChangeRecordList& changes) { | 43 const csync::ImmutableChangeRecordList& changes) { |
| 44 DCHECK(CalledOnValidThread()); | 44 DCHECK(CalledOnValidThread()); |
| 45 DCHECK(running()); | 45 DCHECK(running()); |
| 46 DCHECK(syncer_changes_.empty()); | 46 DCHECK(syncer_changes_.empty()); |
| 47 for (csync::ChangeRecordList::const_iterator it = | 47 for (csync::ChangeRecordList::const_iterator it = |
| 48 changes.Get().begin(); it != changes.Get().end(); ++it) { | 48 changes.Get().begin(); it != changes.Get().end(); ++it) { |
| 49 if (it->action == csync::ChangeRecord::ACTION_DELETE) { | 49 if (it->action == csync::ChangeRecord::ACTION_DELETE) { |
| 50 syncer_changes_.push_back( | 50 syncer_changes_.push_back( |
| 51 SyncChange(SyncChange::ACTION_DELETE, | 51 csync::SyncChange(csync::SyncChange::ACTION_DELETE, |
| 52 SyncData::CreateRemoteData(it->id, it->specifics))); | 52 csync::SyncData::CreateRemoteData(it->id, it->specifics))); |
| 53 } else { | 53 } else { |
| 54 SyncChange::SyncChangeType action = | 54 csync::SyncChange::SyncChangeType action = |
| 55 (it->action == csync::ChangeRecord::ACTION_ADD) ? | 55 (it->action == csync::ChangeRecord::ACTION_ADD) ? |
| 56 SyncChange::ACTION_ADD : SyncChange::ACTION_UPDATE; | 56 csync::SyncChange::ACTION_ADD : csync::SyncChange::ACTION_UPDATE; |
| 57 // Need to load specifics from node. | 57 // Need to load specifics from node. |
| 58 csync::ReadNode read_node(trans); | 58 csync::ReadNode read_node(trans); |
| 59 if (read_node.InitByIdLookup(it->id) != csync::BaseNode::INIT_OK) { | 59 if (read_node.InitByIdLookup(it->id) != csync::BaseNode::INIT_OK) { |
| 60 error_handler()->OnSingleDatatypeUnrecoverableError( | 60 error_handler()->OnSingleDatatypeUnrecoverableError( |
| 61 FROM_HERE, | 61 FROM_HERE, |
| 62 "Failed to look up data for received change with id " + | 62 "Failed to look up data for received change with id " + |
| 63 base::Int64ToString(it->id)); | 63 base::Int64ToString(it->id)); |
| 64 return; | 64 return; |
| 65 } | 65 } |
| 66 syncer_changes_.push_back( | 66 syncer_changes_.push_back( |
| 67 SyncChange(action, | 67 csync::SyncChange(action, |
| 68 SyncData::CreateRemoteData( | 68 csync::SyncData::CreateRemoteData( |
| 69 it->id, read_node.GetEntitySpecifics()))); | 69 it->id, read_node.GetEntitySpecifics()))); |
| 70 } | 70 } |
| 71 } | 71 } |
| 72 } | 72 } |
| 73 | 73 |
| 74 void GenericChangeProcessor::CommitChangesFromSyncModel() { | 74 void GenericChangeProcessor::CommitChangesFromSyncModel() { |
| 75 DCHECK(CalledOnValidThread()); | 75 DCHECK(CalledOnValidThread()); |
| 76 if (!running()) | 76 if (!running()) |
| 77 return; | 77 return; |
| 78 if (syncer_changes_.empty()) | 78 if (syncer_changes_.empty()) |
| 79 return; | 79 return; |
| 80 if (!local_service_) { | 80 if (!local_service_) { |
| 81 syncable::ModelType type = syncer_changes_[0].sync_data().GetDataType(); | 81 syncable::ModelType type = syncer_changes_[0].sync_data().GetDataType(); |
| 82 SyncError error(FROM_HERE, "Local service destroyed.", type); | 82 csync::SyncError error(FROM_HERE, "Local service destroyed.", type); |
| 83 error_handler()->OnSingleDatatypeUnrecoverableError(error.location(), | 83 error_handler()->OnSingleDatatypeUnrecoverableError(error.location(), |
| 84 error.message()); | 84 error.message()); |
| 85 return; | 85 return; |
| 86 } | 86 } |
| 87 SyncError error = local_service_->ProcessSyncChanges(FROM_HERE, | 87 csync::SyncError error = local_service_->ProcessSyncChanges(FROM_HERE, |
| 88 syncer_changes_); | 88 syncer_changes_); |
| 89 syncer_changes_.clear(); | 89 syncer_changes_.clear(); |
| 90 if (error.IsSet()) { | 90 if (error.IsSet()) { |
| 91 error_handler()->OnSingleDatatypeUnrecoverableError( | 91 error_handler()->OnSingleDatatypeUnrecoverableError( |
| 92 error.location(), error.message()); | 92 error.location(), error.message()); |
| 93 } | 93 } |
| 94 } | 94 } |
| 95 | 95 |
| 96 SyncError GenericChangeProcessor::GetSyncDataForType( | 96 csync::SyncError GenericChangeProcessor::GetSyncDataForType( |
| 97 syncable::ModelType type, | 97 syncable::ModelType type, |
| 98 SyncDataList* current_sync_data) { | 98 csync::SyncDataList* current_sync_data) { |
| 99 DCHECK(CalledOnValidThread()); | 99 DCHECK(CalledOnValidThread()); |
| 100 std::string type_name = syncable::ModelTypeToString(type); | 100 std::string type_name = syncable::ModelTypeToString(type); |
| 101 csync::ReadTransaction trans(FROM_HERE, share_handle()); | 101 csync::ReadTransaction trans(FROM_HERE, share_handle()); |
| 102 csync::ReadNode root(&trans); | 102 csync::ReadNode root(&trans); |
| 103 if (root.InitByTagLookup(syncable::ModelTypeToRootTag(type)) != | 103 if (root.InitByTagLookup(syncable::ModelTypeToRootTag(type)) != |
| 104 csync::BaseNode::INIT_OK) { | 104 csync::BaseNode::INIT_OK) { |
| 105 SyncError error(FROM_HERE, | 105 csync::SyncError error(FROM_HERE, |
| 106 "Server did not create the top-level " + type_name + | 106 "Server did not create the top-level " + type_name + |
| 107 " node. We might be running against an out-of-date server.", | 107 " node. We might be running against an out-of-date server.", |
| 108 type); | 108 type); |
| 109 return error; | 109 return error; |
| 110 } | 110 } |
| 111 | 111 |
| 112 // TODO(akalin): We'll have to do a tree traversal for bookmarks. | 112 // TODO(akalin): We'll have to do a tree traversal for bookmarks. |
| 113 DCHECK_NE(type, syncable::BOOKMARKS); | 113 DCHECK_NE(type, syncable::BOOKMARKS); |
| 114 | 114 |
| 115 int64 sync_child_id = root.GetFirstChildId(); | 115 int64 sync_child_id = root.GetFirstChildId(); |
| 116 while (sync_child_id != csync::kInvalidId) { | 116 while (sync_child_id != csync::kInvalidId) { |
| 117 csync::ReadNode sync_child_node(&trans); | 117 csync::ReadNode sync_child_node(&trans); |
| 118 if (sync_child_node.InitByIdLookup(sync_child_id) != | 118 if (sync_child_node.InitByIdLookup(sync_child_id) != |
| 119 csync::BaseNode::INIT_OK) { | 119 csync::BaseNode::INIT_OK) { |
| 120 SyncError error(FROM_HERE, | 120 csync::SyncError error(FROM_HERE, |
| 121 "Failed to fetch child node for type " + type_name + ".", | 121 "Failed to fetch child node for type " + type_name + ".", |
| 122 type); | 122 type); |
| 123 return error; | 123 return error; |
| 124 } | 124 } |
| 125 current_sync_data->push_back(SyncData::CreateRemoteData( | 125 current_sync_data->push_back(csync::SyncData::CreateRemoteData( |
| 126 sync_child_node.GetId(), sync_child_node.GetEntitySpecifics())); | 126 sync_child_node.GetId(), sync_child_node.GetEntitySpecifics())); |
| 127 sync_child_id = sync_child_node.GetSuccessorId(); | 127 sync_child_id = sync_child_node.GetSuccessorId(); |
| 128 } | 128 } |
| 129 return SyncError(); | 129 return csync::SyncError(); |
| 130 } | 130 } |
| 131 | 131 |
| 132 namespace { | 132 namespace { |
| 133 | 133 |
| 134 // TODO(isherman): Investigating http://crbug.com/121592 | 134 // TODO(isherman): Investigating http://crbug.com/121592 |
| 135 // WARNING: this code is sensitive to compiler optimizations. Be careful | 135 // WARNING: this code is sensitive to compiler optimizations. Be careful |
| 136 // modifying any code around an OnSingleDatatypeUnrecoverableError call, else | 136 // modifying any code around an OnSingleDatatypeUnrecoverableError call, else |
| 137 // the compiler attempts to merge it with other calls, losing useful information | 137 // the compiler attempts to merge it with other calls, losing useful information |
| 138 // in breakpad uploads. | 138 // in breakpad uploads. |
| 139 SyncError LogLookupFailure(csync::BaseNode::InitByLookupResult lookup_result, | 139 csync::SyncError LogLookupFailure( |
| 140 const tracked_objects::Location& from_here, | 140 csync::BaseNode::InitByLookupResult lookup_result, |
| 141 const std::string& error_prefix, | 141 const tracked_objects::Location& from_here, |
| 142 syncable::ModelType type, | 142 const std::string& error_prefix, |
| 143 DataTypeErrorHandler* error_handler) { | 143 syncable::ModelType type, |
| 144 DataTypeErrorHandler* error_handler) { |
| 144 switch (lookup_result) { | 145 switch (lookup_result) { |
| 145 case csync::BaseNode::INIT_FAILED_ENTRY_NOT_GOOD: { | 146 case csync::BaseNode::INIT_FAILED_ENTRY_NOT_GOOD: { |
| 146 SyncError error; | 147 csync::SyncError error; |
| 147 error.Reset(from_here, | 148 error.Reset(from_here, |
| 148 error_prefix + | 149 error_prefix + |
| 149 "could not find entry matching the lookup criteria.", | 150 "could not find entry matching the lookup criteria.", |
| 150 type); | 151 type); |
| 151 error_handler->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 152 error_handler->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
| 152 error.message()); | 153 error.message()); |
| 153 LOG(ERROR) << "Delete: Bad entry."; | 154 LOG(ERROR) << "Delete: Bad entry."; |
| 154 return error; | 155 return error; |
| 155 } | 156 } |
| 156 case csync::BaseNode::INIT_FAILED_ENTRY_IS_DEL: { | 157 case csync::BaseNode::INIT_FAILED_ENTRY_IS_DEL: { |
| 157 SyncError error; | 158 csync::SyncError error; |
| 158 error.Reset(from_here, error_prefix + "entry is already deleted.", type); | 159 error.Reset(from_here, error_prefix + "entry is already deleted.", type); |
| 159 error_handler->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 160 error_handler->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
| 160 error.message()); | 161 error.message()); |
| 161 LOG(ERROR) << "Delete: Deleted entry."; | 162 LOG(ERROR) << "Delete: Deleted entry."; |
| 162 return error; | 163 return error; |
| 163 } | 164 } |
| 164 case csync::BaseNode::INIT_FAILED_DECRYPT_IF_NECESSARY: { | 165 case csync::BaseNode::INIT_FAILED_DECRYPT_IF_NECESSARY: { |
| 165 SyncError error; | 166 csync::SyncError error; |
| 166 error.Reset(from_here, error_prefix + "unable to decrypt", type); | 167 error.Reset(from_here, error_prefix + "unable to decrypt", type); |
| 167 error_handler->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 168 error_handler->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
| 168 error.message()); | 169 error.message()); |
| 169 LOG(ERROR) << "Delete: Undecryptable entry."; | 170 LOG(ERROR) << "Delete: Undecryptable entry."; |
| 170 return error; | 171 return error; |
| 171 } | 172 } |
| 172 case csync::BaseNode::INIT_FAILED_PRECONDITION: { | 173 case csync::BaseNode::INIT_FAILED_PRECONDITION: { |
| 173 SyncError error; | 174 csync::SyncError error; |
| 174 error.Reset(from_here, | 175 error.Reset(from_here, |
| 175 error_prefix + "a precondition was not met for calling init.", | 176 error_prefix + "a precondition was not met for calling init.", |
| 176 type); | 177 type); |
| 177 error_handler->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 178 error_handler->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
| 178 error.message()); | 179 error.message()); |
| 179 LOG(ERROR) << "Delete: Failed precondition."; | 180 LOG(ERROR) << "Delete: Failed precondition."; |
| 180 return error; | 181 return error; |
| 181 } | 182 } |
| 182 default: { | 183 default: { |
| 183 SyncError error; | 184 csync::SyncError error; |
| 184 // Should have listed all the possible error cases above. | 185 // Should have listed all the possible error cases above. |
| 185 error.Reset(from_here, error_prefix + "unknown error", type); | 186 error.Reset(from_here, error_prefix + "unknown error", type); |
| 186 error_handler->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 187 error_handler->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
| 187 error.message()); | 188 error.message()); |
| 188 LOG(ERROR) << "Delete: Unknown error."; | 189 LOG(ERROR) << "Delete: Unknown error."; |
| 189 return error; | 190 return error; |
| 190 } | 191 } |
| 191 } | 192 } |
| 192 } | 193 } |
| 193 | 194 |
| 194 SyncError AttemptDelete(const SyncChange& change, | 195 csync::SyncError AttemptDelete(const csync::SyncChange& change, |
| 195 syncable::ModelType type, | 196 syncable::ModelType type, |
| 196 const std::string& type_str, | 197 const std::string& type_str, |
| 197 csync::WriteNode* node, | 198 csync::WriteNode* node, |
| 198 DataTypeErrorHandler* error_handler) { | 199 DataTypeErrorHandler* error_handler) { |
| 199 DCHECK_EQ(change.change_type(), SyncChange::ACTION_DELETE); | 200 DCHECK_EQ(change.change_type(), csync::SyncChange::ACTION_DELETE); |
| 200 if (change.sync_data().IsLocal()) { | 201 if (change.sync_data().IsLocal()) { |
| 201 const std::string& tag = change.sync_data().GetTag(); | 202 const std::string& tag = change.sync_data().GetTag(); |
| 202 if (tag.empty()) { | 203 if (tag.empty()) { |
| 203 SyncError error( | 204 csync::SyncError error( |
| 204 FROM_HERE, | 205 FROM_HERE, |
| 205 "Failed to delete " + type_str + " node. Local data, empty tag.", | 206 "Failed to delete " + type_str + " node. Local data, empty tag.", |
| 206 type); | 207 type); |
| 207 error_handler->OnSingleDatatypeUnrecoverableError(error.location(), | 208 error_handler->OnSingleDatatypeUnrecoverableError(error.location(), |
| 208 error.message()); | 209 error.message()); |
| 209 NOTREACHED(); | 210 NOTREACHED(); |
| 210 return error; | 211 return error; |
| 211 } | 212 } |
| 212 | 213 |
| 213 csync::BaseNode::InitByLookupResult result = | 214 csync::BaseNode::InitByLookupResult result = |
| 214 node->InitByClientTagLookup(change.sync_data().GetDataType(), tag); | 215 node->InitByClientTagLookup(change.sync_data().GetDataType(), tag); |
| 215 if (result != csync::BaseNode::INIT_OK) { | 216 if (result != csync::BaseNode::INIT_OK) { |
| 216 return LogLookupFailure( | 217 return LogLookupFailure( |
| 217 result, FROM_HERE, | 218 result, FROM_HERE, |
| 218 "Failed to delete " + type_str + " node. Local data, ", | 219 "Failed to delete " + type_str + " node. Local data, ", |
| 219 type, error_handler); | 220 type, error_handler); |
| 220 } | 221 } |
| 221 } else { | 222 } else { |
| 222 csync::BaseNode::InitByLookupResult result = | 223 csync::BaseNode::InitByLookupResult result = |
| 223 node->InitByIdLookup(change.sync_data().GetRemoteId()); | 224 node->InitByIdLookup(change.sync_data().GetRemoteId()); |
| 224 if (result != csync::BaseNode::INIT_OK) { | 225 if (result != csync::BaseNode::INIT_OK) { |
| 225 return LogLookupFailure( | 226 return LogLookupFailure( |
| 226 result, FROM_HERE, | 227 result, FROM_HERE, |
| 227 "Failed to delete " + type_str + " node. Non-local data, ", | 228 "Failed to delete " + type_str + " node. Non-local data, ", |
| 228 type, error_handler); | 229 type, error_handler); |
| 229 } | 230 } |
| 230 } | 231 } |
| 231 node->Remove(); | 232 node->Remove(); |
| 232 return SyncError(); | 233 return csync::SyncError(); |
| 233 } | 234 } |
| 234 | 235 |
| 235 } // namespace | 236 } // namespace |
| 236 | 237 |
| 237 // WARNING: this code is sensitive to compiler optimizations. Be careful | 238 // WARNING: this code is sensitive to compiler optimizations. Be careful |
| 238 // modifying any code around an OnSingleDatatypeUnrecoverableError call, else | 239 // modifying any code around an OnSingleDatatypeUnrecoverableError call, else |
| 239 // the compiler attempts to merge it with other calls, losing useful information | 240 // the compiler attempts to merge it with other calls, losing useful information |
| 240 // in breakpad uploads. | 241 // in breakpad uploads. |
| 241 SyncError GenericChangeProcessor::ProcessSyncChanges( | 242 csync::SyncError GenericChangeProcessor::ProcessSyncChanges( |
| 242 const tracked_objects::Location& from_here, | 243 const tracked_objects::Location& from_here, |
| 243 const SyncChangeList& list_of_changes) { | 244 const csync::SyncChangeList& list_of_changes) { |
| 244 DCHECK(CalledOnValidThread()); | 245 DCHECK(CalledOnValidThread()); |
| 245 csync::WriteTransaction trans(from_here, share_handle()); | 246 csync::WriteTransaction trans(from_here, share_handle()); |
| 246 | 247 |
| 247 for (SyncChangeList::const_iterator iter = list_of_changes.begin(); | 248 for (csync::SyncChangeList::const_iterator iter = list_of_changes.begin(); |
| 248 iter != list_of_changes.end(); | 249 iter != list_of_changes.end(); |
| 249 ++iter) { | 250 ++iter) { |
| 250 const SyncChange& change = *iter; | 251 const csync::SyncChange& change = *iter; |
| 251 DCHECK_NE(change.sync_data().GetDataType(), syncable::UNSPECIFIED); | 252 DCHECK_NE(change.sync_data().GetDataType(), syncable::UNSPECIFIED); |
| 252 syncable::ModelType type = change.sync_data().GetDataType(); | 253 syncable::ModelType type = change.sync_data().GetDataType(); |
| 253 std::string type_str = syncable::ModelTypeToString(type); | 254 std::string type_str = syncable::ModelTypeToString(type); |
| 254 csync::WriteNode sync_node(&trans); | 255 csync::WriteNode sync_node(&trans); |
| 255 if (change.change_type() == SyncChange::ACTION_DELETE) { | 256 if (change.change_type() == csync::SyncChange::ACTION_DELETE) { |
| 256 SyncError error = AttemptDelete(change, type, type_str, &sync_node, | 257 csync::SyncError error = AttemptDelete(change, type, type_str, &sync_node, |
| 257 error_handler()); | 258 error_handler()); |
| 258 if (error.IsSet()) { | 259 if (error.IsSet()) { |
| 259 NOTREACHED(); | 260 NOTREACHED(); |
| 260 return error; | 261 return error; |
| 261 } | 262 } |
| 262 } else if (change.change_type() == SyncChange::ACTION_ADD) { | 263 } else if (change.change_type() == csync::SyncChange::ACTION_ADD) { |
| 263 // TODO(sync): Handle other types of creation (custom parents, folders, | 264 // TODO(sync): Handle other types of creation (custom parents, folders, |
| 264 // etc.). | 265 // etc.). |
| 265 csync::ReadNode root_node(&trans); | 266 csync::ReadNode root_node(&trans); |
| 266 if (root_node.InitByTagLookup( | 267 if (root_node.InitByTagLookup( |
| 267 syncable::ModelTypeToRootTag(change.sync_data().GetDataType())) != | 268 syncable::ModelTypeToRootTag(change.sync_data().GetDataType())) != |
| 268 csync::BaseNode::INIT_OK) { | 269 csync::BaseNode::INIT_OK) { |
| 269 SyncError error(FROM_HERE, | 270 csync::SyncError error(FROM_HERE, |
| 270 "Failed to look up root node for type " + type_str, | 271 "Failed to look up root node for type " + type_str, |
| 271 type); | 272 type); |
| 272 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 273 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
| 273 error.message()); | 274 error.message()); |
| 274 NOTREACHED(); | 275 NOTREACHED(); |
| 275 LOG(ERROR) << "Create: no root node."; | 276 LOG(ERROR) << "Create: no root node."; |
| 276 return error; | 277 return error; |
| 277 } | 278 } |
| 278 csync::WriteNode::InitUniqueByCreationResult result = | 279 csync::WriteNode::InitUniqueByCreationResult result = |
| 279 sync_node.InitUniqueByCreation(change.sync_data().GetDataType(), | 280 sync_node.InitUniqueByCreation(change.sync_data().GetDataType(), |
| 280 root_node, | 281 root_node, |
| 281 change.sync_data().GetTag()); | 282 change.sync_data().GetTag()); |
| 282 if (result != csync::WriteNode::INIT_SUCCESS) { | 283 if (result != csync::WriteNode::INIT_SUCCESS) { |
| 283 std::string error_prefix = "Failed to create " + type_str + " node: "; | 284 std::string error_prefix = "Failed to create " + type_str + " node: "; |
| 284 switch (result) { | 285 switch (result) { |
| 285 case csync::WriteNode::INIT_FAILED_EMPTY_TAG: { | 286 case csync::WriteNode::INIT_FAILED_EMPTY_TAG: { |
| 286 SyncError error; | 287 csync::SyncError error; |
| 287 error.Reset(FROM_HERE, error_prefix + "empty tag", type); | 288 error.Reset(FROM_HERE, error_prefix + "empty tag", type); |
| 288 error_handler()->OnSingleDatatypeUnrecoverableError( | 289 error_handler()->OnSingleDatatypeUnrecoverableError( |
| 289 FROM_HERE, error.message()); | 290 FROM_HERE, error.message()); |
| 290 LOG(ERROR) << "Create: Empty tag."; | 291 LOG(ERROR) << "Create: Empty tag."; |
| 291 return error; | 292 return error; |
| 292 } | 293 } |
| 293 case csync::WriteNode::INIT_FAILED_ENTRY_ALREADY_EXISTS: { | 294 case csync::WriteNode::INIT_FAILED_ENTRY_ALREADY_EXISTS: { |
| 294 SyncError error; | 295 csync::SyncError error; |
| 295 error.Reset(FROM_HERE, error_prefix + "entry already exists", type); | 296 error.Reset(FROM_HERE, error_prefix + "entry already exists", type); |
| 296 error_handler()->OnSingleDatatypeUnrecoverableError( | 297 error_handler()->OnSingleDatatypeUnrecoverableError( |
| 297 FROM_HERE, error.message()); | 298 FROM_HERE, error.message()); |
| 298 LOG(ERROR) << "Create: Entry exists."; | 299 LOG(ERROR) << "Create: Entry exists."; |
| 299 return error; | 300 return error; |
| 300 } | 301 } |
| 301 case csync::WriteNode::INIT_FAILED_COULD_NOT_CREATE_ENTRY: { | 302 case csync::WriteNode::INIT_FAILED_COULD_NOT_CREATE_ENTRY: { |
| 302 SyncError error; | 303 csync::SyncError error; |
| 303 error.Reset(FROM_HERE, error_prefix + "failed to create entry", | 304 error.Reset(FROM_HERE, error_prefix + "failed to create entry", |
| 304 type); | 305 type); |
| 305 error_handler()->OnSingleDatatypeUnrecoverableError( | 306 error_handler()->OnSingleDatatypeUnrecoverableError( |
| 306 FROM_HERE, error.message()); | 307 FROM_HERE, error.message()); |
| 307 LOG(ERROR) << "Create: Could not create entry."; | 308 LOG(ERROR) << "Create: Could not create entry."; |
| 308 return error; | 309 return error; |
| 309 } | 310 } |
| 310 case csync::WriteNode::INIT_FAILED_SET_PREDECESSOR: { | 311 case csync::WriteNode::INIT_FAILED_SET_PREDECESSOR: { |
| 311 SyncError error; | 312 csync::SyncError error; |
| 312 error.Reset(FROM_HERE, error_prefix + "failed to set predecessor", | 313 error.Reset(FROM_HERE, error_prefix + "failed to set predecessor", |
| 313 type); | 314 type); |
| 314 error_handler()->OnSingleDatatypeUnrecoverableError( | 315 error_handler()->OnSingleDatatypeUnrecoverableError( |
| 315 FROM_HERE, error.message()); | 316 FROM_HERE, error.message()); |
| 316 LOG(ERROR) << "Create: Bad predecessor."; | 317 LOG(ERROR) << "Create: Bad predecessor."; |
| 317 return error; | 318 return error; |
| 318 } | 319 } |
| 319 default: { | 320 default: { |
| 320 SyncError error; | 321 csync::SyncError error; |
| 321 error.Reset(FROM_HERE, error_prefix + "unknown error", type); | 322 error.Reset(FROM_HERE, error_prefix + "unknown error", type); |
| 322 error_handler()->OnSingleDatatypeUnrecoverableError( | 323 error_handler()->OnSingleDatatypeUnrecoverableError( |
| 323 FROM_HERE, error.message()); | 324 FROM_HERE, error.message()); |
| 324 LOG(ERROR) << "Create: Unknown error."; | 325 LOG(ERROR) << "Create: Unknown error."; |
| 325 return error; | 326 return error; |
| 326 } | 327 } |
| 327 } | 328 } |
| 328 } | 329 } |
| 329 sync_node.SetTitle(UTF8ToWide(change.sync_data().GetTitle())); | 330 sync_node.SetTitle(UTF8ToWide(change.sync_data().GetTitle())); |
| 330 sync_node.SetEntitySpecifics(change.sync_data().GetSpecifics()); | 331 sync_node.SetEntitySpecifics(change.sync_data().GetSpecifics()); |
| 331 } else if (change.change_type() == SyncChange::ACTION_UPDATE) { | 332 } else if (change.change_type() == csync::SyncChange::ACTION_UPDATE) { |
| 332 // TODO(zea): consider having this logic for all possible changes? | 333 // TODO(zea): consider having this logic for all possible changes? |
| 333 csync::BaseNode::InitByLookupResult result = | 334 csync::BaseNode::InitByLookupResult result = |
| 334 sync_node.InitByClientTagLookup(change.sync_data().GetDataType(), | 335 sync_node.InitByClientTagLookup(change.sync_data().GetDataType(), |
| 335 change.sync_data().GetTag()); | 336 change.sync_data().GetTag()); |
| 336 if (result != csync::BaseNode::INIT_OK) { | 337 if (result != csync::BaseNode::INIT_OK) { |
| 337 if (result == csync::BaseNode::INIT_FAILED_PRECONDITION) { | 338 if (result == csync::BaseNode::INIT_FAILED_PRECONDITION) { |
| 338 SyncError error; | 339 csync::SyncError error; |
| 339 error.Reset(FROM_HERE, | 340 error.Reset(FROM_HERE, |
| 340 "Failed to load entry w/empty tag for " + type_str + ".", | 341 "Failed to load entry w/empty tag for " + type_str + ".", |
| 341 type); | 342 type); |
| 342 error_handler()->OnSingleDatatypeUnrecoverableError( | 343 error_handler()->OnSingleDatatypeUnrecoverableError( |
| 343 FROM_HERE, error.message()); | 344 FROM_HERE, error.message()); |
| 344 LOG(ERROR) << "Update: Empty tag."; | 345 LOG(ERROR) << "Update: Empty tag."; |
| 345 return error; | 346 return error; |
| 346 } else if (result == csync::BaseNode::INIT_FAILED_ENTRY_NOT_GOOD) { | 347 } else if (result == csync::BaseNode::INIT_FAILED_ENTRY_NOT_GOOD) { |
| 347 SyncError error; | 348 csync::SyncError error; |
| 348 error.Reset(FROM_HERE, | 349 error.Reset(FROM_HERE, |
| 349 "Failed to load bad entry for " + type_str + ".", | 350 "Failed to load bad entry for " + type_str + ".", |
| 350 type); | 351 type); |
| 351 error_handler()->OnSingleDatatypeUnrecoverableError( | 352 error_handler()->OnSingleDatatypeUnrecoverableError( |
| 352 FROM_HERE, error.message()); | 353 FROM_HERE, error.message()); |
| 353 LOG(ERROR) << "Update: bad entry."; | 354 LOG(ERROR) << "Update: bad entry."; |
| 354 return error; | 355 return error; |
| 355 } else if (result == csync::BaseNode::INIT_FAILED_ENTRY_IS_DEL) { | 356 } else if (result == csync::BaseNode::INIT_FAILED_ENTRY_IS_DEL) { |
| 356 SyncError error; | 357 csync::SyncError error; |
| 357 error.Reset(FROM_HERE, | 358 error.Reset(FROM_HERE, |
| 358 "Failed to load deleted entry for " + type_str + ".", | 359 "Failed to load deleted entry for " + type_str + ".", |
| 359 type); | 360 type); |
| 360 error_handler()->OnSingleDatatypeUnrecoverableError( | 361 error_handler()->OnSingleDatatypeUnrecoverableError( |
| 361 FROM_HERE, error.message()); | 362 FROM_HERE, error.message()); |
| 362 LOG(ERROR) << "Update: deleted entry."; | 363 LOG(ERROR) << "Update: deleted entry."; |
| 363 return error; | 364 return error; |
| 364 } else { | 365 } else { |
| 365 csync::Cryptographer* crypto = trans.GetCryptographer(); | 366 csync::Cryptographer* crypto = trans.GetCryptographer(); |
| 366 syncable::ModelTypeSet encrypted_types(crypto->GetEncryptedTypes()); | 367 syncable::ModelTypeSet encrypted_types(crypto->GetEncryptedTypes()); |
| 367 const sync_pb::EntitySpecifics& specifics = | 368 const sync_pb::EntitySpecifics& specifics = |
| 368 sync_node.GetEntry()->Get(syncable::SPECIFICS); | 369 sync_node.GetEntry()->Get(syncable::SPECIFICS); |
| 369 CHECK(specifics.has_encrypted()); | 370 CHECK(specifics.has_encrypted()); |
| 370 const bool can_decrypt = crypto->CanDecrypt(specifics.encrypted()); | 371 const bool can_decrypt = crypto->CanDecrypt(specifics.encrypted()); |
| 371 const bool agreement = encrypted_types.Has(type); | 372 const bool agreement = encrypted_types.Has(type); |
| 372 if (!agreement && !can_decrypt) { | 373 if (!agreement && !can_decrypt) { |
| 373 SyncError error; | 374 csync::SyncError error; |
| 374 error.Reset(FROM_HERE, | 375 error.Reset(FROM_HERE, |
| 375 "Failed to load encrypted entry, missing key and " | 376 "Failed to load encrypted entry, missing key and " |
| 376 "nigori mismatch for " + type_str + ".", | 377 "nigori mismatch for " + type_str + ".", |
| 377 type); | 378 type); |
| 378 error_handler()->OnSingleDatatypeUnrecoverableError( | 379 error_handler()->OnSingleDatatypeUnrecoverableError( |
| 379 FROM_HERE, error.message()); | 380 FROM_HERE, error.message()); |
| 380 LOG(ERROR) << "Update: encr case 1."; | 381 LOG(ERROR) << "Update: encr case 1."; |
| 381 return error; | 382 return error; |
| 382 } else if (agreement && can_decrypt) { | 383 } else if (agreement && can_decrypt) { |
| 383 SyncError error; | 384 csync::SyncError error; |
| 384 error.Reset(FROM_HERE, | 385 error.Reset(FROM_HERE, |
| 385 "Failed to load encrypted entry, we have the key " | 386 "Failed to load encrypted entry, we have the key " |
| 386 "and the nigori matches (?!) for " + type_str + ".", | 387 "and the nigori matches (?!) for " + type_str + ".", |
| 387 type); | 388 type); |
| 388 error_handler()->OnSingleDatatypeUnrecoverableError( | 389 error_handler()->OnSingleDatatypeUnrecoverableError( |
| 389 FROM_HERE, error.message()); | 390 FROM_HERE, error.message()); |
| 390 LOG(ERROR) << "Update: encr case 2."; | 391 LOG(ERROR) << "Update: encr case 2."; |
| 391 return error; | 392 return error; |
| 392 } else if (agreement) { | 393 } else if (agreement) { |
| 393 SyncError error; | 394 csync::SyncError error; |
| 394 error.Reset(FROM_HERE, | 395 error.Reset(FROM_HERE, |
| 395 "Failed to load encrypted entry, missing key and " | 396 "Failed to load encrypted entry, missing key and " |
| 396 "the nigori matches for " + type_str + ".", | 397 "the nigori matches for " + type_str + ".", |
| 397 type); | 398 type); |
| 398 error_handler()->OnSingleDatatypeUnrecoverableError( | 399 error_handler()->OnSingleDatatypeUnrecoverableError( |
| 399 FROM_HERE, error.message()); | 400 FROM_HERE, error.message()); |
| 400 LOG(ERROR) << "Update: encr case 3."; | 401 LOG(ERROR) << "Update: encr case 3."; |
| 401 return error; | 402 return error; |
| 402 } else { | 403 } else { |
| 403 SyncError error; | 404 csync::SyncError error; |
| 404 error.Reset(FROM_HERE, | 405 error.Reset(FROM_HERE, |
| 405 "Failed to load encrypted entry, we have the key" | 406 "Failed to load encrypted entry, we have the key" |
| 406 "(?!) and nigori mismatch for " + type_str + ".", | 407 "(?!) and nigori mismatch for " + type_str + ".", |
| 407 type); | 408 type); |
| 408 error_handler()->OnSingleDatatypeUnrecoverableError( | 409 error_handler()->OnSingleDatatypeUnrecoverableError( |
| 409 FROM_HERE, error.message()); | 410 FROM_HERE, error.message()); |
| 410 LOG(ERROR) << "Update: encr case 4."; | 411 LOG(ERROR) << "Update: encr case 4."; |
| 411 return error; | 412 return error; |
| 412 } | 413 } |
| 413 } | 414 } |
| 414 } else { | 415 } else { |
| 415 sync_node.SetTitle(UTF8ToWide(change.sync_data().GetTitle())); | 416 sync_node.SetTitle(UTF8ToWide(change.sync_data().GetTitle())); |
| 416 sync_node.SetEntitySpecifics(change.sync_data().GetSpecifics()); | 417 sync_node.SetEntitySpecifics(change.sync_data().GetSpecifics()); |
| 417 // TODO(sync): Support updating other parts of the sync node (title, | 418 // TODO(sync): Support updating other parts of the sync node (title, |
| 418 // successor, parent, etc.). | 419 // successor, parent, etc.). |
| 419 } | 420 } |
| 420 } else { | 421 } else { |
| 421 SyncError error(FROM_HERE, | 422 csync::SyncError error( |
| 422 "Received unset SyncChange in the change processor.", | 423 FROM_HERE, |
| 423 type); | 424 "Received unset csync::SyncChange in the change processor.", |
| 425 type); |
| 424 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 426 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
| 425 error.message()); | 427 error.message()); |
| 426 NOTREACHED(); | 428 NOTREACHED(); |
| 427 LOG(ERROR) << "Unset sync change."; | 429 LOG(ERROR) << "Unset sync change."; |
| 428 return error; | 430 return error; |
| 429 } | 431 } |
| 430 } | 432 } |
| 431 return SyncError(); | 433 return csync::SyncError(); |
| 432 } | 434 } |
| 433 | 435 |
| 434 bool GenericChangeProcessor::SyncModelHasUserCreatedNodes( | 436 bool GenericChangeProcessor::SyncModelHasUserCreatedNodes( |
| 435 syncable::ModelType type, | 437 syncable::ModelType type, |
| 436 bool* has_nodes) { | 438 bool* has_nodes) { |
| 437 DCHECK(CalledOnValidThread()); | 439 DCHECK(CalledOnValidThread()); |
| 438 DCHECK(has_nodes); | 440 DCHECK(has_nodes); |
| 439 DCHECK_NE(type, syncable::UNSPECIFIED); | 441 DCHECK_NE(type, syncable::UNSPECIFIED); |
| 440 std::string type_name = syncable::ModelTypeToString(type); | 442 std::string type_name = syncable::ModelTypeToString(type); |
| 441 std::string err_str = "Server did not create the top-level " + type_name + | 443 std::string err_str = "Server did not create the top-level " + type_name + |
| (...skipping 30 matching lines...) Expand all Loading... |
| 472 void GenericChangeProcessor::StopImpl() { | 474 void GenericChangeProcessor::StopImpl() { |
| 473 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 475 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 474 } | 476 } |
| 475 | 477 |
| 476 csync::UserShare* GenericChangeProcessor::share_handle() const { | 478 csync::UserShare* GenericChangeProcessor::share_handle() const { |
| 477 DCHECK(CalledOnValidThread()); | 479 DCHECK(CalledOnValidThread()); |
| 478 return share_handle_; | 480 return share_handle_; |
| 479 } | 481 } |
| 480 | 482 |
| 481 } // namespace browser_sync | 483 } // namespace browser_sync |
| OLD | NEW |