| 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 "chrome/browser/sync/api/sync_change.h" | 10 #include "chrome/browser/sync/api/sync_change.h" |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 if (it->action == sync_api::ChangeRecord::ACTION_DELETE) { | 48 if (it->action == sync_api::ChangeRecord::ACTION_DELETE) { |
| 49 syncer_changes_.push_back( | 49 syncer_changes_.push_back( |
| 50 SyncChange(SyncChange::ACTION_DELETE, | 50 SyncChange(SyncChange::ACTION_DELETE, |
| 51 SyncData::CreateRemoteData(it->id, it->specifics))); | 51 SyncData::CreateRemoteData(it->id, it->specifics))); |
| 52 } else { | 52 } else { |
| 53 SyncChange::SyncChangeType action = | 53 SyncChange::SyncChangeType action = |
| 54 (it->action == sync_api::ChangeRecord::ACTION_ADD) ? | 54 (it->action == sync_api::ChangeRecord::ACTION_ADD) ? |
| 55 SyncChange::ACTION_ADD : SyncChange::ACTION_UPDATE; | 55 SyncChange::ACTION_ADD : SyncChange::ACTION_UPDATE; |
| 56 // Need to load specifics from node. | 56 // Need to load specifics from node. |
| 57 sync_api::ReadNode read_node(trans); | 57 sync_api::ReadNode read_node(trans); |
| 58 if (!read_node.InitByIdLookup(it->id)) { | 58 if (read_node.InitByIdLookup(it->id) != sync_api::BaseNode::INIT_OK) { |
| 59 error_handler()->OnUnrecoverableError( | 59 error_handler()->OnUnrecoverableError( |
| 60 FROM_HERE, | 60 FROM_HERE, |
| 61 "Failed to look up data for received change with id " + | 61 "Failed to look up data for received change with id " + |
| 62 base::Int64ToString(it->id)); | 62 base::Int64ToString(it->id)); |
| 63 return; | 63 return; |
| 64 } | 64 } |
| 65 syncer_changes_.push_back( | 65 syncer_changes_.push_back( |
| 66 SyncChange(action, | 66 SyncChange(action, |
| 67 SyncData::CreateRemoteData( | 67 SyncData::CreateRemoteData( |
| 68 it->id, read_node.GetEntitySpecifics()))); | 68 it->id, read_node.GetEntitySpecifics()))); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 90 } | 90 } |
| 91 } | 91 } |
| 92 | 92 |
| 93 SyncError GenericChangeProcessor::GetSyncDataForType( | 93 SyncError GenericChangeProcessor::GetSyncDataForType( |
| 94 syncable::ModelType type, | 94 syncable::ModelType type, |
| 95 SyncDataList* current_sync_data) { | 95 SyncDataList* current_sync_data) { |
| 96 DCHECK(CalledOnValidThread()); | 96 DCHECK(CalledOnValidThread()); |
| 97 std::string type_name = syncable::ModelTypeToString(type); | 97 std::string type_name = syncable::ModelTypeToString(type); |
| 98 sync_api::ReadTransaction trans(FROM_HERE, share_handle()); | 98 sync_api::ReadTransaction trans(FROM_HERE, share_handle()); |
| 99 sync_api::ReadNode root(&trans); | 99 sync_api::ReadNode root(&trans); |
| 100 if (!root.InitByTagLookup(syncable::ModelTypeToRootTag(type))) { | 100 if (root.InitByTagLookup(syncable::ModelTypeToRootTag(type)) != |
| 101 sync_api::BaseNode::INIT_OK) { |
| 101 SyncError error(FROM_HERE, | 102 SyncError error(FROM_HERE, |
| 102 "Server did not create the top-level " + type_name + | 103 "Server did not create the top-level " + type_name + |
| 103 " node. We might be running against an out-of-date server.", | 104 " node. We might be running against an out-of-date server.", |
| 104 type); | 105 type); |
| 105 return error; | 106 return error; |
| 106 } | 107 } |
| 107 | 108 |
| 108 // TODO(akalin): We'll have to do a tree traversal for bookmarks. | 109 // TODO(akalin): We'll have to do a tree traversal for bookmarks. |
| 109 DCHECK_NE(type, syncable::BOOKMARKS); | 110 DCHECK_NE(type, syncable::BOOKMARKS); |
| 110 | 111 |
| 111 int64 sync_child_id = root.GetFirstChildId(); | 112 int64 sync_child_id = root.GetFirstChildId(); |
| 112 while (sync_child_id != sync_api::kInvalidId) { | 113 while (sync_child_id != sync_api::kInvalidId) { |
| 113 sync_api::ReadNode sync_child_node(&trans); | 114 sync_api::ReadNode sync_child_node(&trans); |
| 114 if (!sync_child_node.InitByIdLookup(sync_child_id)) { | 115 if (sync_child_node.InitByIdLookup(sync_child_id) != |
| 116 sync_api::BaseNode::INIT_OK) { |
| 115 SyncError error(FROM_HERE, | 117 SyncError error(FROM_HERE, |
| 116 "Failed to fetch child node for type " + type_name + ".", | 118 "Failed to fetch child node for type " + type_name + ".", |
| 117 type); | 119 type); |
| 118 return error; | 120 return error; |
| 119 } | 121 } |
| 120 current_sync_data->push_back(SyncData::CreateRemoteData( | 122 current_sync_data->push_back(SyncData::CreateRemoteData( |
| 121 sync_child_node.GetId(), sync_child_node.GetEntitySpecifics())); | 123 sync_child_node.GetId(), sync_child_node.GetEntitySpecifics())); |
| 122 sync_child_id = sync_child_node.GetSuccessorId(); | 124 sync_child_id = sync_child_node.GetSuccessorId(); |
| 123 } | 125 } |
| 124 return SyncError(); | 126 return SyncError(); |
| 125 } | 127 } |
| 126 | 128 |
| 127 namespace { | 129 namespace { |
| 128 | 130 |
| 129 bool AttemptDelete(const SyncChange& change, sync_api::WriteNode* node) { | 131 bool AttemptDelete(const SyncChange& change, sync_api::WriteNode* node) { |
| 130 DCHECK_EQ(change.change_type(), SyncChange::ACTION_DELETE); | 132 DCHECK_EQ(change.change_type(), SyncChange::ACTION_DELETE); |
| 131 if (change.sync_data().IsLocal()) { | 133 if (change.sync_data().IsLocal()) { |
| 132 const std::string& tag = change.sync_data().GetTag(); | 134 const std::string& tag = change.sync_data().GetTag(); |
| 133 if (tag.empty()) { | 135 if (tag.empty()) { |
| 134 return false; | 136 return false; |
| 135 } | 137 } |
| 136 if (!node->InitByClientTagLookup( | 138 if (node->InitByClientTagLookup( |
| 137 change.sync_data().GetDataType(), tag)) { | 139 change.sync_data().GetDataType(), tag) != |
| 140 sync_api::BaseNode::INIT_OK) { |
| 138 return false; | 141 return false; |
| 139 } | 142 } |
| 140 } else { | 143 } else { |
| 141 if (!node->InitByIdLookup(change.sync_data().GetRemoteId())) { | 144 if (node->InitByIdLookup(change.sync_data().GetRemoteId()) != |
| 145 sync_api::BaseNode::INIT_OK) { |
| 142 return false; | 146 return false; |
| 143 } | 147 } |
| 144 } | 148 } |
| 145 node->Remove(); | 149 node->Remove(); |
| 146 return true; | 150 return true; |
| 147 } | 151 } |
| 148 | 152 |
| 149 } // namespace | 153 } // namespace |
| 150 | 154 |
| 151 SyncError GenericChangeProcessor::ProcessSyncChanges( | 155 SyncError GenericChangeProcessor::ProcessSyncChanges( |
| (...skipping 17 matching lines...) Expand all Loading... |
| 169 "Failed to delete " + type_str + " node.", | 173 "Failed to delete " + type_str + " node.", |
| 170 type); | 174 type); |
| 171 error_handler()->OnSingleDatatypeUnrecoverableError(error.location(), | 175 error_handler()->OnSingleDatatypeUnrecoverableError(error.location(), |
| 172 error.message()); | 176 error.message()); |
| 173 return error; | 177 return error; |
| 174 } | 178 } |
| 175 } else if (change.change_type() == SyncChange::ACTION_ADD) { | 179 } else if (change.change_type() == SyncChange::ACTION_ADD) { |
| 176 // TODO(sync): Handle other types of creation (custom parents, folders, | 180 // TODO(sync): Handle other types of creation (custom parents, folders, |
| 177 // etc.). | 181 // etc.). |
| 178 sync_api::ReadNode root_node(&trans); | 182 sync_api::ReadNode root_node(&trans); |
| 179 if (!root_node.InitByTagLookup( | 183 if (root_node.InitByTagLookup( |
| 180 syncable::ModelTypeToRootTag(change.sync_data().GetDataType()))) { | 184 syncable::ModelTypeToRootTag(change.sync_data().GetDataType())) != |
| 185 sync_api::BaseNode::INIT_OK) { |
| 181 NOTREACHED(); | 186 NOTREACHED(); |
| 182 SyncError error(FROM_HERE, | 187 SyncError error(FROM_HERE, |
| 183 "Failed to look up root node for type " + type_str, | 188 "Failed to look up root node for type " + type_str, |
| 184 type); | 189 type); |
| 185 error_handler()->OnSingleDatatypeUnrecoverableError(error.location(), | 190 error_handler()->OnSingleDatatypeUnrecoverableError(error.location(), |
| 186 error.message()); | 191 error.message()); |
| 187 return error; | 192 return error; |
| 188 } | 193 } |
| 189 if (!sync_node.InitUniqueByCreation(change.sync_data().GetDataType(), | 194 if (!sync_node.InitUniqueByCreation(change.sync_data().GetDataType(), |
| 190 root_node, | 195 root_node, |
| 191 change.sync_data().GetTag())) { | 196 change.sync_data().GetTag())) { |
| 192 NOTREACHED(); | 197 NOTREACHED(); |
| 193 SyncError error(FROM_HERE, | 198 SyncError error(FROM_HERE, |
| 194 "Failed to create " + type_str + " node.", | 199 "Failed to create " + type_str + " node.", |
| 195 type); | 200 type); |
| 196 error_handler()->OnSingleDatatypeUnrecoverableError(error.location(), | 201 error_handler()->OnSingleDatatypeUnrecoverableError(error.location(), |
| 197 error.message()); | 202 error.message()); |
| 198 return error; | 203 return error; |
| 199 } | 204 } |
| 200 sync_node.SetTitle(UTF8ToWide(change.sync_data().GetTitle())); | 205 sync_node.SetTitle(UTF8ToWide(change.sync_data().GetTitle())); |
| 201 sync_node.SetEntitySpecifics(change.sync_data().GetSpecifics()); | 206 sync_node.SetEntitySpecifics(change.sync_data().GetSpecifics()); |
| 202 } else if (change.change_type() == SyncChange::ACTION_UPDATE) { | 207 } else if (change.change_type() == SyncChange::ACTION_UPDATE) { |
| 203 if (change.sync_data().GetTag() == "" || | 208 if (change.sync_data().GetTag() == "" || |
| 204 !sync_node.InitByClientTagLookup(change.sync_data().GetDataType(), | 209 sync_node.InitByClientTagLookup(change.sync_data().GetDataType(), |
| 205 change.sync_data().GetTag())) { | 210 change.sync_data().GetTag()) != |
| 211 sync_api::BaseNode::INIT_OK) { |
| 206 NOTREACHED(); | 212 NOTREACHED(); |
| 207 SyncError error(FROM_HERE, | 213 SyncError error(FROM_HERE, |
| 208 "Failed to update " + type_str + " node.", | 214 "Failed to update " + type_str + " node.", |
| 209 type); | 215 type); |
| 210 error_handler()->OnSingleDatatypeUnrecoverableError(error.location(), | 216 error_handler()->OnSingleDatatypeUnrecoverableError(error.location(), |
| 211 error.message()); | 217 error.message()); |
| 212 return error; | 218 return error; |
| 213 } | 219 } |
| 214 sync_node.SetTitle(UTF8ToWide(change.sync_data().GetTitle())); | 220 sync_node.SetTitle(UTF8ToWide(change.sync_data().GetTitle())); |
| 215 sync_node.SetEntitySpecifics(change.sync_data().GetSpecifics()); | 221 sync_node.SetEntitySpecifics(change.sync_data().GetSpecifics()); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 233 bool* has_nodes) { | 239 bool* has_nodes) { |
| 234 DCHECK(CalledOnValidThread()); | 240 DCHECK(CalledOnValidThread()); |
| 235 DCHECK(has_nodes); | 241 DCHECK(has_nodes); |
| 236 DCHECK_NE(type, syncable::UNSPECIFIED); | 242 DCHECK_NE(type, syncable::UNSPECIFIED); |
| 237 std::string type_name = syncable::ModelTypeToString(type); | 243 std::string type_name = syncable::ModelTypeToString(type); |
| 238 std::string err_str = "Server did not create the top-level " + type_name + | 244 std::string err_str = "Server did not create the top-level " + type_name + |
| 239 " node. We might be running against an out-of-date server."; | 245 " node. We might be running against an out-of-date server."; |
| 240 *has_nodes = false; | 246 *has_nodes = false; |
| 241 sync_api::ReadTransaction trans(FROM_HERE, share_handle()); | 247 sync_api::ReadTransaction trans(FROM_HERE, share_handle()); |
| 242 sync_api::ReadNode type_root_node(&trans); | 248 sync_api::ReadNode type_root_node(&trans); |
| 243 if (!type_root_node.InitByTagLookup(syncable::ModelTypeToRootTag(type))) { | 249 if (type_root_node.InitByTagLookup(syncable::ModelTypeToRootTag(type)) != |
| 250 sync_api::BaseNode::INIT_OK) { |
| 244 LOG(ERROR) << err_str; | 251 LOG(ERROR) << err_str; |
| 245 return false; | 252 return false; |
| 246 } | 253 } |
| 247 | 254 |
| 248 // The sync model has user created nodes if the type's root node has any | 255 // The sync model has user created nodes if the type's root node has any |
| 249 // children. | 256 // children. |
| 250 *has_nodes = type_root_node.HasChildren(); | 257 *has_nodes = type_root_node.HasChildren(); |
| 251 return true; | 258 return true; |
| 252 } | 259 } |
| 253 | 260 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 268 void GenericChangeProcessor::StopImpl() { | 275 void GenericChangeProcessor::StopImpl() { |
| 269 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 276 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 270 } | 277 } |
| 271 | 278 |
| 272 sync_api::UserShare* GenericChangeProcessor::share_handle() const { | 279 sync_api::UserShare* GenericChangeProcessor::share_handle() const { |
| 273 DCHECK(CalledOnValidThread()); | 280 DCHECK(CalledOnValidThread()); |
| 274 return share_handle_; | 281 return share_handle_; |
| 275 } | 282 } |
| 276 | 283 |
| 277 } // namespace browser_sync | 284 } // namespace browser_sync |
| OLD | NEW |