Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: chrome/browser/sync/glue/bookmark_change_processor.cc

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

Powered by Google App Engine
This is Rietveld 408576698