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/bookmark_change_processor.h" | 5 #include "chrome/browser/sync/glue/bookmark_change_processor.h" |
6 | 6 |
7 #include <stack> | 7 #include <stack> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/location.h" | 10 #include "base/location.h" |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
106 } | 106 } |
107 // This node should have no children. | 107 // This node should have no children. |
108 DCHECK(!sync_node.HasChildren()); | 108 DCHECK(!sync_node.HasChildren()); |
109 // Remove association and delete the sync node. | 109 // Remove association and delete the sync node. |
110 model_associator_->Disassociate(sync_node.GetId()); | 110 model_associator_->Disassociate(sync_node.GetId()); |
111 sync_node.Remove(); | 111 sync_node.Remove(); |
112 } | 112 } |
113 | 113 |
114 void BookmarkChangeProcessor::RemoveSyncNodeHierarchy( | 114 void BookmarkChangeProcessor::RemoveSyncNodeHierarchy( |
115 const BookmarkNode* topmost) { | 115 const BookmarkNode* topmost) { |
116 syncer::WriteTransaction trans(FROM_HERE, share_handle()); | 116 int64 new_version = -1; |
117 { | |
118 syncer::WriteTransaction trans(FROM_HERE, share_handle(), &new_version); | |
117 | 119 |
118 // Later logic assumes that |topmost| has been unlinked. | 120 // Later logic assumes that |topmost| has been unlinked. |
119 DCHECK(topmost->is_root()); | 121 DCHECK(topmost->is_root()); |
120 | 122 |
121 // A BookmarkModel deletion event means that |node| and all its children were | 123 // A BookmarkModel deletion event means that |node| and all its children |
122 // deleted. Sync backend expects children to be deleted individually, so we do | 124 // were deleted. Sync backend expects children to be deleted individually, |
123 // a depth-first-search here. At each step, we consider the |index|-th child | 125 // so we do a depth-first-search here. At each step, we consider the |
124 // of |node|. |index_stack| stores index values for the parent levels. | 126 // |index|-th child of |node|. |index_stack| stores index values for the |
125 std::stack<int> index_stack; | 127 // parent levels. |
126 index_stack.push(0); // For the final pop. It's never used. | 128 std::stack<int> index_stack; |
127 const BookmarkNode* node = topmost; | 129 index_stack.push(0); // For the final pop. It's never used. |
128 int index = 0; | 130 const BookmarkNode* node = topmost; |
129 while (node) { | 131 int index = 0; |
130 // The top of |index_stack| should always be |node|'s index. | 132 while (node) { |
131 DCHECK(node->is_root() || (node->parent()->GetIndexOf(node) == | 133 // The top of |index_stack| should always be |node|'s index. |
132 index_stack.top())); | 134 DCHECK(node->is_root() || (node->parent()->GetIndexOf(node) == |
133 if (index == node->child_count()) { | 135 index_stack.top())); |
134 // If we've processed all of |node|'s children, delete |node| and move | 136 if (index == node->child_count()) { |
135 // on to its successor. | 137 // If we've processed all of |node|'s children, delete |node| and move |
136 RemoveOneSyncNode(&trans, node); | 138 // on to its successor. |
137 node = node->parent(); | 139 RemoveOneSyncNode(&trans, node); |
138 index = index_stack.top() + 1; // (top() + 0) was what we removed. | 140 node = node->parent(); |
139 index_stack.pop(); | 141 index = index_stack.top() + 1; // (top() + 0) was what we removed. |
140 } else { | 142 index_stack.pop(); |
141 // If |node| has an unprocessed child, process it next after pushing the | 143 } else { |
142 // current state onto the stack. | 144 // If |node| has an unprocessed child, process it next after pushing the |
143 DCHECK_LT(index, node->child_count()); | 145 // current state onto the stack. |
144 index_stack.push(index); | 146 DCHECK_LT(index, node->child_count()); |
145 node = node->GetChild(index); | 147 index_stack.push(index); |
146 index = 0; | 148 node = node->GetChild(index); |
149 index = 0; | |
150 } | |
147 } | 151 } |
152 DCHECK(index_stack.empty()); // Nothing should be left on the stack. | |
148 } | 153 } |
149 DCHECK(index_stack.empty()); // Nothing should be left on the stack. | 154 |
155 // Don't need to update versions of deleted nodes. | |
156 UpdateTransactionVersion(new_version, bookmark_model_, | |
157 std::vector<const BookmarkNode*>()); | |
150 } | 158 } |
151 | 159 |
152 void BookmarkChangeProcessor::Loaded(BookmarkModel* model, | 160 void BookmarkChangeProcessor::Loaded(BookmarkModel* model, |
153 bool ids_reassigned) { | 161 bool ids_reassigned) { |
154 NOTREACHED(); | 162 NOTREACHED(); |
155 } | 163 } |
156 | 164 |
157 void BookmarkChangeProcessor::BookmarkModelBeingDeleted( | 165 void BookmarkChangeProcessor::BookmarkModelBeingDeleted( |
158 BookmarkModel* model) { | 166 BookmarkModel* model) { |
159 NOTREACHED(); | 167 NOTREACHED(); |
160 bookmark_model_ = NULL; | 168 bookmark_model_ = NULL; |
161 } | 169 } |
162 | 170 |
163 void BookmarkChangeProcessor::BookmarkNodeAdded(BookmarkModel* model, | 171 void BookmarkChangeProcessor::BookmarkNodeAdded(BookmarkModel* model, |
164 const BookmarkNode* parent, | 172 const BookmarkNode* parent, |
165 int index) { | 173 int index) { |
166 DCHECK(share_handle()); | 174 DCHECK(share_handle()); |
167 | 175 |
168 // Acquire a scoped write lock via a transaction. | 176 int64 new_version = -1; |
169 syncer::WriteTransaction trans(FROM_HERE, share_handle()); | 177 int64 sync_id = syncer::kInvalidId; |
178 { | |
179 // Acquire a scoped write lock via a transaction. | |
180 syncer::WriteTransaction trans(FROM_HERE, share_handle(), &new_version); | |
181 sync_id = CreateSyncNode(parent, model, index, &trans, | |
182 model_associator_, error_handler()); | |
183 } | |
170 | 184 |
171 CreateSyncNode(parent, model, index, &trans, model_associator_, | 185 if (syncer::kInvalidId != sync_id) { |
172 error_handler()); | 186 // Siblings of added node in sync DB will also be updated to reflect new |
187 // PREV_ID/NEXT_ID and thus get a new version. But we only update version | |
188 // of added node here. After switching to ordinals for positioning, | |
189 // PREV_ID/NEXT_ID will be deprecated and siblings will not be updated. | |
190 UpdateTransactionVersion( | |
191 new_version, model, | |
192 std::vector<const BookmarkNode*>(1, parent->GetChild(index))); | |
193 } | |
173 } | 194 } |
174 | 195 |
175 // static | 196 // static |
176 int64 BookmarkChangeProcessor::CreateSyncNode(const BookmarkNode* parent, | 197 int64 BookmarkChangeProcessor::CreateSyncNode(const BookmarkNode* parent, |
177 BookmarkModel* model, int index, syncer::WriteTransaction* trans, | 198 BookmarkModel* model, int index, syncer::WriteTransaction* trans, |
178 BookmarkModelAssociator* associator, | 199 BookmarkModelAssociator* associator, |
179 DataTypeErrorHandler* error_handler) { | 200 DataTypeErrorHandler* error_handler) { |
180 const BookmarkNode* child = parent->GetChild(index); | 201 const BookmarkNode* child = parent->GetChild(index); |
181 DCHECK(child); | 202 DCHECK(child); |
182 | 203 |
183 // Create a WriteNode container to hold the new node. | 204 // Create a WriteNode container to hold the new node. |
184 syncer::WriteNode sync_child(trans); | 205 syncer::WriteNode sync_child(trans); |
185 | 206 |
186 // Actually create the node with the appropriate initial position. | 207 // Actually create the node with the appropriate initial position. |
187 if (!PlaceSyncNode(CREATE, parent, index, trans, &sync_child, associator)) { | 208 if (!PlaceSyncNode(CREATE, parent, index, trans, &sync_child, associator)) { |
188 error_handler->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 209 error_handler->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
189 "Sync node creation failed; recovery unlikely"); | 210 "Sync node creation failed; recovery unlikely"); |
190 return syncer::kInvalidId; | 211 return syncer::kInvalidId; |
191 } | 212 } |
192 | 213 |
193 UpdateSyncNodeProperties(child, model, &sync_child); | 214 UpdateSyncNodeProperties(child, model, &sync_child); |
194 | 215 |
195 // Associate the ID from the sync domain with the bookmark node, so that we | 216 // Associate the ID from the sync domain with the bookmark node, so that we |
196 // can refer back to this item later. | 217 // can refer back to this item later. |
197 associator->Associate(child, sync_child.GetId()); | 218 associator->Associate(child, sync_child.GetId()); |
198 | 219 |
199 return sync_child.GetId(); | 220 return sync_child.GetId(); |
200 } | 221 } |
201 | 222 |
202 | |
203 void BookmarkChangeProcessor::BookmarkNodeRemoved(BookmarkModel* model, | 223 void BookmarkChangeProcessor::BookmarkNodeRemoved(BookmarkModel* model, |
204 const BookmarkNode* parent, | 224 const BookmarkNode* parent, |
205 int index, | 225 int index, |
206 const BookmarkNode* node) { | 226 const BookmarkNode* node) { |
207 RemoveSyncNodeHierarchy(node); | 227 RemoveSyncNodeHierarchy(node); |
208 } | 228 } |
209 | 229 |
210 void BookmarkChangeProcessor::BookmarkNodeChanged(BookmarkModel* model, | 230 void BookmarkChangeProcessor::BookmarkNodeChanged(BookmarkModel* model, |
211 const BookmarkNode* node) { | 231 const BookmarkNode* node) { |
212 // We shouldn't see changes to the top-level nodes. | 232 // We shouldn't see changes to the top-level nodes. |
213 if (model->is_permanent_node(node)) { | 233 if (model->is_permanent_node(node)) { |
214 NOTREACHED() << "Saw update to permanent node!"; | 234 NOTREACHED() << "Saw update to permanent node!"; |
215 return; | 235 return; |
216 } | 236 } |
217 | 237 |
218 // Acquire a scoped write lock via a transaction. | 238 int64 new_version = -1; |
219 syncer::WriteTransaction trans(FROM_HERE, share_handle()); | 239 { |
240 // Acquire a scoped write lock via a transaction. | |
241 syncer::WriteTransaction trans(FROM_HERE, share_handle(), &new_version); | |
220 | 242 |
221 // Lookup the sync node that's associated with |node|. | 243 // Lookup the sync node that's associated with |node|. |
222 syncer::WriteNode sync_node(&trans); | 244 syncer::WriteNode sync_node(&trans); |
223 if (!model_associator_->InitSyncNodeFromChromeId(node->id(), &sync_node)) { | 245 if (!model_associator_->InitSyncNodeFromChromeId(node->id(), &sync_node)) { |
224 // TODO(tim): Investigating bug 121587. | 246 // TODO(tim): Investigating bug 121587. |
225 if (model_associator_->GetSyncIdFromChromeId(node->id()) == | 247 if (model_associator_->GetSyncIdFromChromeId(node->id()) == |
226 syncer::kInvalidId) { | 248 syncer::kInvalidId) { |
227 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | |
228 "Bookmark id not found in model associator on BookmarkNodeChanged"); | |
229 LOG(ERROR) << "Bad id."; | |
230 } else if (!sync_node.GetEntry()->good()) { | |
231 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | |
232 "Could not InitByIdLookup on BookmarkNodeChanged, good() failed"); | |
233 LOG(ERROR) << "Bad entry."; | |
234 } else if (sync_node.GetEntry()->Get(syncer::syncable::IS_DEL)) { | |
235 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | |
236 "Could not InitByIdLookup on BookmarkNodeChanged, is_del true"); | |
237 LOG(ERROR) << "Deleted entry."; | |
238 } else { | |
239 syncer::Cryptographer* crypto = trans.GetCryptographer(); | |
240 syncer::ModelTypeSet encrypted_types(trans.GetEncryptedTypes()); | |
241 const sync_pb::EntitySpecifics& specifics = | |
242 sync_node.GetEntry()->Get(syncer::syncable::SPECIFICS); | |
243 CHECK(specifics.has_encrypted()); | |
244 const bool can_decrypt = crypto->CanDecrypt(specifics.encrypted()); | |
245 const bool agreement = encrypted_types.Has(syncer::BOOKMARKS); | |
246 if (!agreement && !can_decrypt) { | |
247 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 249 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
248 "Could not InitByIdLookup on BookmarkNodeChanged, " | 250 "Bookmark id not found in model associator on BookmarkNodeChanged"); |
249 " Cryptographer thinks bookmarks not encrypted, and CanDecrypt" | 251 LOG(ERROR) << "Bad id."; |
250 " failed."); | 252 } else if (!sync_node.GetEntry()->good()) { |
251 LOG(ERROR) << "Case 1."; | |
252 } else if (agreement && can_decrypt) { | |
253 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 253 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
254 "Could not InitByIdLookup on BookmarkNodeChanged, " | 254 "Could not InitByIdLookup on BookmarkNodeChanged, good() failed"); |
255 " Cryptographer thinks bookmarks are encrypted, and CanDecrypt" | 255 LOG(ERROR) << "Bad entry."; |
256 " succeeded (?!), but DecryptIfNecessary failed."); | 256 } else if (sync_node.GetEntry()->Get(syncer::syncable::IS_DEL)) { |
257 LOG(ERROR) << "Case 2."; | |
258 } else if (agreement) { | |
259 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 257 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
260 "Could not InitByIdLookup on BookmarkNodeChanged, " | 258 "Could not InitByIdLookup on BookmarkNodeChanged, is_del true"); |
261 " Cryptographer thinks bookmarks are encrypted, but CanDecrypt" | 259 LOG(ERROR) << "Deleted entry."; |
262 " failed."); | |
263 LOG(ERROR) << "Case 3."; | |
264 } else { | 260 } else { |
265 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 261 syncer::Cryptographer* crypto = trans.GetCryptographer(); |
266 "Could not InitByIdLookup on BookmarkNodeChanged, " | 262 syncer::ModelTypeSet encrypted_types(trans.GetEncryptedTypes()); |
267 " Cryptographer thinks bookmarks not encrypted, but CanDecrypt" | 263 const sync_pb::EntitySpecifics& specifics = |
268 " succeeded (super weird, btw)"); | 264 sync_node.GetEntry()->Get(syncer::syncable::SPECIFICS); |
269 LOG(ERROR) << "Case 4."; | 265 CHECK(specifics.has_encrypted()); |
266 const bool can_decrypt = crypto->CanDecrypt(specifics.encrypted()); | |
267 const bool agreement = encrypted_types.Has(syncer::BOOKMARKS); | |
268 if (!agreement && !can_decrypt) { | |
269 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | |
270 "Could not InitByIdLookup on BookmarkNodeChanged, " | |
271 " Cryptographer thinks bookmarks not encrypted, and CanDecrypt" | |
272 " failed."); | |
273 LOG(ERROR) << "Case 1."; | |
274 } else if (agreement && can_decrypt) { | |
275 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | |
276 "Could not InitByIdLookup on BookmarkNodeChanged, " | |
277 " Cryptographer thinks bookmarks are encrypted, and CanDecrypt" | |
278 " succeeded (?!), but DecryptIfNecessary failed."); | |
279 LOG(ERROR) << "Case 2."; | |
280 } else if (agreement) { | |
281 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | |
282 "Could not InitByIdLookup on BookmarkNodeChanged, " | |
283 " Cryptographer thinks bookmarks are encrypted, but CanDecrypt" | |
284 " failed."); | |
285 LOG(ERROR) << "Case 3."; | |
286 } else { | |
287 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | |
288 "Could not InitByIdLookup on BookmarkNodeChanged, " | |
289 " Cryptographer thinks bookmarks not encrypted, but CanDecrypt" | |
290 " succeeded (super weird, btw)"); | |
291 LOG(ERROR) << "Case 4."; | |
292 } | |
270 } | 293 } |
294 return; | |
271 } | 295 } |
272 return; | 296 |
297 UpdateSyncNodeProperties(node, model, &sync_node); | |
298 | |
299 DCHECK_EQ(sync_node.GetIsFolder(), node->is_folder()); | |
300 DCHECK_EQ(model_associator_->GetChromeNodeFromSyncId( | |
301 sync_node.GetParentId()), | |
302 node->parent()); | |
303 // This node's index should be one more than the predecessor's index. | |
304 DCHECK_EQ(node->parent()->GetIndexOf(node), | |
305 CalculateBookmarkModelInsertionIndex(node->parent(), | |
306 &sync_node, | |
307 model_associator_)); | |
273 } | 308 } |
274 | 309 |
275 UpdateSyncNodeProperties(node, model, &sync_node); | 310 UpdateTransactionVersion(new_version, model, |
276 | 311 std::vector<const BookmarkNode*>(1, node)); |
277 DCHECK_EQ(sync_node.GetIsFolder(), node->is_folder()); | |
278 DCHECK_EQ(model_associator_->GetChromeNodeFromSyncId( | |
279 sync_node.GetParentId()), | |
280 node->parent()); | |
281 // This node's index should be one more than the predecessor's index. | |
282 DCHECK_EQ(node->parent()->GetIndexOf(node), | |
283 CalculateBookmarkModelInsertionIndex(node->parent(), | |
284 &sync_node, | |
285 model_associator_)); | |
286 } | 312 } |
287 | 313 |
288 | |
289 void BookmarkChangeProcessor::BookmarkNodeMoved(BookmarkModel* model, | 314 void BookmarkChangeProcessor::BookmarkNodeMoved(BookmarkModel* model, |
290 const BookmarkNode* old_parent, int old_index, | 315 const BookmarkNode* old_parent, int old_index, |
291 const BookmarkNode* new_parent, int new_index) { | 316 const BookmarkNode* new_parent, int new_index) { |
292 const BookmarkNode* child = new_parent->GetChild(new_index); | 317 const BookmarkNode* child = new_parent->GetChild(new_index); |
293 // We shouldn't see changes to the top-level nodes. | 318 // We shouldn't see changes to the top-level nodes. |
294 if (model->is_permanent_node(child)) { | 319 if (model->is_permanent_node(child)) { |
295 NOTREACHED() << "Saw update to permanent node!"; | 320 NOTREACHED() << "Saw update to permanent node!"; |
296 return; | 321 return; |
297 } | 322 } |
298 | 323 |
299 // Acquire a scoped write lock via a transaction. | 324 int64 new_version = -1; |
tim (not reviewing)
2012/11/08 17:38:49
This is used in a *lot*of places. I think it'd be
haitaol1
2012/11/08 19:06:53
Done.
| |
300 syncer::WriteTransaction trans(FROM_HERE, share_handle()); | 325 { |
326 // Acquire a scoped write lock via a transaction. | |
327 syncer::WriteTransaction trans(FROM_HERE, share_handle(), &new_version); | |
301 | 328 |
302 // Lookup the sync node that's associated with |child|. | 329 // Lookup the sync node that's associated with |child|. |
303 syncer::WriteNode sync_node(&trans); | 330 syncer::WriteNode sync_node(&trans); |
304 if (!model_associator_->InitSyncNodeFromChromeId(child->id(), &sync_node)) { | 331 if (!model_associator_->InitSyncNodeFromChromeId(child->id(), &sync_node)) { |
305 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 332 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
306 std::string()); | 333 std::string()); |
307 return; | 334 return; |
335 } | |
336 | |
337 if (!PlaceSyncNode(MOVE, new_parent, new_index, &trans, &sync_node, | |
338 model_associator_)) { | |
339 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | |
340 std::string()); | |
341 return; | |
342 } | |
308 } | 343 } |
309 | 344 |
310 if (!PlaceSyncNode(MOVE, new_parent, new_index, &trans, &sync_node, | 345 UpdateTransactionVersion(new_version, model, |
311 model_associator_)) { | 346 std::vector<const BookmarkNode*>(1, child)); |
312 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | |
313 std::string()); | |
314 return; | |
315 } | |
316 } | 347 } |
317 | 348 |
318 void BookmarkChangeProcessor::BookmarkNodeFaviconChanged( | 349 void BookmarkChangeProcessor::BookmarkNodeFaviconChanged( |
319 BookmarkModel* model, | 350 BookmarkModel* model, |
320 const BookmarkNode* node) { | 351 const BookmarkNode* node) { |
321 BookmarkNodeChanged(model, node); | 352 BookmarkNodeChanged(model, node); |
322 } | 353 } |
323 | 354 |
324 void BookmarkChangeProcessor::BookmarkNodeChildrenReordered( | 355 void BookmarkChangeProcessor::BookmarkNodeChildrenReordered( |
325 BookmarkModel* model, const BookmarkNode* node) { | 356 BookmarkModel* model, const BookmarkNode* node) { |
357 int64 new_version = -1; | |
358 std::vector<const BookmarkNode*> children; | |
359 { | |
360 // Acquire a scoped write lock via a transaction. | |
361 syncer::WriteTransaction trans(FROM_HERE, share_handle(), &new_version); | |
326 | 362 |
327 // Acquire a scoped write lock via a transaction. | 363 // The given node's children got reordered. We need to reorder all the |
328 syncer::WriteTransaction trans(FROM_HERE, share_handle()); | 364 // children of the corresponding sync node. |
365 for (int i = 0; i < node->child_count(); ++i) { | |
366 const BookmarkNode* child = node->GetChild(i); | |
367 children.push_back(child); | |
329 | 368 |
330 // The given node's children got reordered. We need to reorder all the | 369 syncer::WriteNode sync_child(&trans); |
331 // children of the corresponding sync node. | 370 if (!model_associator_->InitSyncNodeFromChromeId(child->id(), |
332 for (int i = 0; i < node->child_count(); ++i) { | 371 &sync_child)) { |
333 syncer::WriteNode sync_child(&trans); | 372 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
334 if (!model_associator_->InitSyncNodeFromChromeId(node->GetChild(i)->id(), | 373 std::string()); |
335 &sync_child)) { | 374 return; |
336 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 375 } |
337 std::string()); | 376 DCHECK_EQ(sync_child.GetParentId(), |
338 return; | 377 model_associator_->GetSyncIdFromChromeId(node->id())); |
339 } | |
340 DCHECK_EQ(sync_child.GetParentId(), | |
341 model_associator_->GetSyncIdFromChromeId(node->id())); | |
342 | 378 |
343 if (!PlaceSyncNode(MOVE, node, i, &trans, &sync_child, | 379 if (!PlaceSyncNode(MOVE, node, i, &trans, &sync_child, |
344 model_associator_)) { | 380 model_associator_)) { |
345 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 381 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
346 std::string()); | 382 std::string()); |
347 return; | 383 return; |
384 } | |
348 } | 385 } |
349 } | 386 } |
387 | |
388 // TODO(haitaol): Filter out children that didn't actually change. | |
389 UpdateTransactionVersion(new_version, model, children); | |
350 } | 390 } |
351 | 391 |
352 // static | 392 // static |
353 bool BookmarkChangeProcessor::PlaceSyncNode(MoveOrCreate operation, | 393 bool BookmarkChangeProcessor::PlaceSyncNode(MoveOrCreate operation, |
354 const BookmarkNode* parent, int index, syncer::WriteTransaction* trans, | 394 const BookmarkNode* parent, int index, syncer::WriteTransaction* trans, |
355 syncer::WriteNode* dst, BookmarkModelAssociator* associator) { | 395 syncer::WriteNode* dst, BookmarkModelAssociator* associator) { |
356 syncer::ReadNode sync_parent(trans); | 396 syncer::ReadNode sync_parent(trans); |
357 if (!associator->InitSyncNodeFromChromeId(parent->id(), &sync_parent)) { | 397 if (!associator->InitSyncNodeFromChromeId(parent->id(), &sync_parent)) { |
358 LOG(WARNING) << "Parent lookup failed"; | 398 LOG(WARNING) << "Parent lookup failed"; |
359 return false; | 399 return false; |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
498 << "ACTION_ADD should be seen if and only if the node is unknown."; | 538 << "ACTION_ADD should be seen if and only if the node is unknown."; |
499 passed_deletes = true; | 539 passed_deletes = true; |
500 | 540 |
501 syncer::ReadNode src(trans); | 541 syncer::ReadNode src(trans); |
502 if (src.InitByIdLookup(it->id) != syncer::BaseNode::INIT_OK) { | 542 if (src.InitByIdLookup(it->id) != syncer::BaseNode::INIT_OK) { |
503 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, | 543 error_handler()->OnSingleDatatypeUnrecoverableError(FROM_HERE, |
504 "ApplyModelChanges was passed a bad ID"); | 544 "ApplyModelChanges was passed a bad ID"); |
505 return; | 545 return; |
506 } | 546 } |
507 | 547 |
508 if (!CreateOrUpdateBookmarkNode(&src, model, model_associator_)) { | 548 const BookmarkNode* node = CreateOrUpdateBookmarkNode(&src, model, |
549 model_associator_); | |
550 if (node) { | |
551 bookmark_model_->SetNodeMetaInfo(node, kBookmarkTransactionVersionKey, | |
552 base::Int64ToString(model_version)); | |
553 } else { | |
509 // Because the Synced Bookmarks node can be created server side, it's | 554 // Because the Synced Bookmarks node can be created server side, it's |
510 // possible it'll arrive at the client as an update. In that case it | 555 // possible it'll arrive at the client as an update. In that case it |
511 // won't have been associated at startup, the GetChromeNodeFromSyncId | 556 // won't have been associated at startup, the GetChromeNodeFromSyncId |
512 // call above will return NULL, and we won't detect it as a permanent | 557 // call above will return NULL, and we won't detect it as a permanent |
513 // node, resulting in us trying to create it here (which will | 558 // node, resulting in us trying to create it here (which will |
514 // fail). Therefore, we add special logic here just to detect the | 559 // fail). Therefore, we add special logic here just to detect the |
515 // Synced Bookmarks folder. | 560 // Synced Bookmarks folder. |
516 syncer::ReadNode synced_bookmarks(trans); | 561 syncer::ReadNode synced_bookmarks(trans); |
517 if (synced_bookmarks.InitByTagLookup(kMobileBookmarksTag) == | 562 if (synced_bookmarks.InitByTagLookup(kMobileBookmarksTag) == |
518 syncer::BaseNode::INIT_OK && | 563 syncer::BaseNode::INIT_OK && |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
591 base::Time::FromInternalValue( | 636 base::Time::FromInternalValue( |
592 src->GetBookmarkSpecifics().creation_time_us())); | 637 src->GetBookmarkSpecifics().creation_time_us())); |
593 } | 638 } |
594 | 639 |
595 SetBookmarkFavicon(src, dst, model); | 640 SetBookmarkFavicon(src, dst, model); |
596 } | 641 } |
597 | 642 |
598 return dst; | 643 return dst; |
599 } | 644 } |
600 | 645 |
646 void BookmarkChangeProcessor::UpdateTransactionVersion( | |
tim (not reviewing)
2012/11/08 17:38:49
You could re-use this function from BookmarkModelA
haitaol1
2012/11/08 19:06:53
Done.
| |
647 int64 new_version, | |
648 BookmarkModel* model, | |
649 const std::vector<const BookmarkNode*>& nodes) { | |
650 if (new_version > 0) { | |
651 model->SetNodeMetaInfo(model->root_node(), kBookmarkTransactionVersionKey, | |
652 base::Int64ToString(new_version)); | |
653 for (uint32 i = 0; i < nodes.size(); ++i) { | |
tim (not reviewing)
2012/11/08 17:38:49
prefer size_t to uint32 particularly when using th
haitaol1
2012/11/08 19:06:53
Done.
| |
654 model->SetNodeMetaInfo(nodes[i], kBookmarkTransactionVersionKey, | |
655 base::Int64ToString(new_version)); | |
656 } | |
657 } | |
658 } | |
659 | |
601 // static | 660 // static |
602 // Creates a bookmark node under the given parent node from the given sync | 661 // Creates a bookmark node under the given parent node from the given sync |
603 // node. Returns the newly created node. | 662 // node. Returns the newly created node. |
604 const BookmarkNode* BookmarkChangeProcessor::CreateBookmarkNode( | 663 const BookmarkNode* BookmarkChangeProcessor::CreateBookmarkNode( |
605 syncer::BaseNode* sync_node, | 664 syncer::BaseNode* sync_node, |
606 const BookmarkNode* parent, | 665 const BookmarkNode* parent, |
607 BookmarkModel* model, | 666 BookmarkModel* model, |
608 int index) { | 667 int index) { |
609 DCHECK(parent); | 668 DCHECK(parent); |
610 DCHECK(index >= 0 && index <= parent->child_count()); | 669 DCHECK(index >= 0 && index <= parent->child_count()); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
676 const BookmarkNode* bookmark_node, | 735 const BookmarkNode* bookmark_node, |
677 BookmarkModel* model, | 736 BookmarkModel* model, |
678 syncer::WriteNode* sync_node) { | 737 syncer::WriteNode* sync_node) { |
679 std::vector<unsigned char> favicon_bytes; | 738 std::vector<unsigned char> favicon_bytes; |
680 EncodeFavicon(bookmark_node, model, &favicon_bytes); | 739 EncodeFavicon(bookmark_node, model, &favicon_bytes); |
681 if (!favicon_bytes.empty()) | 740 if (!favicon_bytes.empty()) |
682 sync_node->SetFaviconBytes(favicon_bytes); | 741 sync_node->SetFaviconBytes(favicon_bytes); |
683 } | 742 } |
684 | 743 |
685 } // namespace browser_sync | 744 } // namespace browser_sync |
OLD | NEW |