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

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

Issue 7453014: [Sync] Refactor sync datatype error handling. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase and fix final unit test <3 c++ Created 9 years, 5 months 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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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_model_associator.h" 5 #include "chrome/browser/sync/glue/bookmark_model_associator.h"
6 6
7 #include <stack> 7 #include <stack>
8 8
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/hash_tables.h" 10 #include "base/hash_tables.h"
11 #include "base/message_loop.h" 11 #include "base/message_loop.h"
12 #include "base/task.h" 12 #include "base/task.h"
13 #include "base/tracked.h" 13 #include "base/tracked.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/profiles/profile.h" 16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/sync/api/sync_error.h"
17 #include "chrome/browser/sync/engine/syncapi.h" 18 #include "chrome/browser/sync/engine/syncapi.h"
18 #include "chrome/browser/sync/glue/bookmark_change_processor.h" 19 #include "chrome/browser/sync/glue/bookmark_change_processor.h"
19 #include "chrome/browser/sync/syncable/nigori_util.h" 20 #include "chrome/browser/sync/syncable/nigori_util.h"
20 #include "chrome/browser/sync/util/cryptographer.h" 21 #include "chrome/browser/sync/util/cryptographer.h"
21 #include "chrome/common/chrome_switches.h" 22 #include "chrome/common/chrome_switches.h"
22 #include "content/browser/browser_thread.h" 23 #include "content/browser/browser_thread.h"
23 24
24 namespace browser_sync { 25 namespace browser_sync {
25 26
26 // The sync protocol identifies top-level entities by means of well-known tags, 27 // The sync protocol identifies top-level entities by means of well-known tags,
(...skipping 10 matching lines...) Expand all
37 // the sync server) to create these tagged nodes when initializing sync 38 // the sync server) to create these tagged nodes when initializing sync
38 // for the first time for a user. Thus, once the backend finishes 39 // for the first time for a user. Thus, once the backend finishes
39 // initializing, the ProfileSyncService can rely on the presence of tagged 40 // initializing, the ProfileSyncService can rely on the presence of tagged
40 // nodes. 41 // nodes.
41 // 42 //
42 // TODO(ncarter): Pull these tags from an external protocol specification 43 // TODO(ncarter): Pull these tags from an external protocol specification
43 // rather than hardcoding them here. 44 // rather than hardcoding them here.
44 static const char kBookmarkBarTag[] = "bookmark_bar"; 45 static const char kBookmarkBarTag[] = "bookmark_bar";
45 static const char kSyncedBookmarksTag[] = "synced_bookmarks"; 46 static const char kSyncedBookmarksTag[] = "synced_bookmarks";
46 static const char kOtherBookmarksTag[] = "other_bookmarks"; 47 static const char kOtherBookmarksTag[] = "other_bookmarks";
48 static const char kServerError[] =
49 "Server did not create top-level nodes. Possibly we are running against "
50 "an out-of-date server?";
47 51
48 // Bookmark comparer for map of bookmark nodes. 52 // Bookmark comparer for map of bookmark nodes.
49 class BookmarkComparer { 53 class BookmarkComparer {
50 public: 54 public:
51 // Compares the two given nodes and returns whether node1 should appear 55 // Compares the two given nodes and returns whether node1 should appear
52 // before node2 in strict weak ordering. 56 // before node2 in strict weak ordering.
53 bool operator()(const BookmarkNode* node1, 57 bool operator()(const BookmarkNode* node1,
54 const BookmarkNode* node2) const { 58 const BookmarkNode* node2) const {
55 DCHECK(node1); 59 DCHECK(node1);
56 DCHECK(node2); 60 DCHECK(node2);
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 175 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
172 DCHECK(bookmark_model_); 176 DCHECK(bookmark_model_);
173 DCHECK(user_share_); 177 DCHECK(user_share_);
174 DCHECK(unrecoverable_error_handler_); 178 DCHECK(unrecoverable_error_handler_);
175 } 179 }
176 180
177 BookmarkModelAssociator::~BookmarkModelAssociator() { 181 BookmarkModelAssociator::~BookmarkModelAssociator() {
178 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 182 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
179 } 183 }
180 184
181 bool BookmarkModelAssociator::DisassociateModels() { 185 bool BookmarkModelAssociator::DisassociateModels(SyncError* error) {
182 id_map_.clear(); 186 id_map_.clear();
183 id_map_inverse_.clear(); 187 id_map_inverse_.clear();
184 dirty_associations_sync_ids_.clear(); 188 dirty_associations_sync_ids_.clear();
185 return true; 189 return true;
186 } 190 }
187 191
188 int64 BookmarkModelAssociator::GetSyncIdFromChromeId(const int64& node_id) { 192 int64 BookmarkModelAssociator::GetSyncIdFromChromeId(const int64& node_id) {
189 BookmarkIdToSyncIdMap::const_iterator iter = id_map_.find(node_id); 193 BookmarkIdToSyncIdMap::const_iterator iter = id_map_.find(node_id);
190 return iter == id_map_.end() ? sync_api::kInvalidId : iter->second; 194 return iter == id_map_.end() ? sync_api::kInvalidId : iter->second;
191 } 195 }
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
308 bool BookmarkModelAssociator::GetSyncIdForTaggedNode(const std::string& tag, 312 bool BookmarkModelAssociator::GetSyncIdForTaggedNode(const std::string& tag,
309 int64* sync_id) { 313 int64* sync_id) {
310 sync_api::ReadTransaction trans(FROM_HERE, user_share_); 314 sync_api::ReadTransaction trans(FROM_HERE, user_share_);
311 sync_api::ReadNode sync_node(&trans); 315 sync_api::ReadNode sync_node(&trans);
312 if (!sync_node.InitByTagLookup(tag.c_str())) 316 if (!sync_node.InitByTagLookup(tag.c_str()))
313 return false; 317 return false;
314 *sync_id = sync_node.GetId(); 318 *sync_id = sync_node.GetId();
315 return true; 319 return true;
316 } 320 }
317 321
318 bool BookmarkModelAssociator::AssociateModels() { 322 bool BookmarkModelAssociator::AssociateModels(SyncError* error) {
319 // Try to load model associations from persisted associations first. If that 323 // Try to load model associations from persisted associations first. If that
320 // succeeds, we don't need to run the complex model matching algorithm. 324 // succeeds, we don't need to run the complex model matching algorithm.
321 if (LoadAssociations()) 325 if (LoadAssociations())
322 return true; 326 return true;
323 327
324 DisassociateModels(); 328 DisassociateModels(error);
325 329
326 // We couldn't load model associations from persisted associations. So build 330 // We couldn't load model associations from persisted associations. So build
327 // them. 331 // them.
328 return BuildAssociations(); 332 return BuildAssociations(error);
329 } 333 }
330 334
331 bool BookmarkModelAssociator::BuildAssociations() { 335 bool BookmarkModelAssociator::BuildAssociations(SyncError* error) {
332 // Algorithm description: 336 // Algorithm description:
333 // Match up the roots and recursively do the following: 337 // Match up the roots and recursively do the following:
334 // * For each sync node for the current sync parent node, find the best 338 // * For each sync node for the current sync parent node, find the best
335 // matching bookmark node under the corresponding bookmark parent node. 339 // matching bookmark node under the corresponding bookmark parent node.
336 // If no matching node is found, create a new bookmark node in the same 340 // If no matching node is found, create a new bookmark node in the same
337 // position as the corresponding sync node. 341 // position as the corresponding sync node.
338 // If a matching node is found, update the properties of it from the 342 // If a matching node is found, update the properties of it from the
339 // corresponding sync node. 343 // corresponding sync node.
340 // * When all children sync nodes are done, add the extra children bookmark 344 // * When all children sync nodes are done, add the extra children bookmark
341 // nodes to the sync parent node. 345 // nodes to the sync parent node.
342 // 346 //
343 // This algorithm will do a good job of merging when folder names are a good 347 // This algorithm will do a good job of merging when folder names are a good
344 // indicator of the two folders being the same. It will handle reordering and 348 // indicator of the two folders being the same. It will handle reordering and
345 // new node addition very well (without creating duplicates). 349 // new node addition very well (without creating duplicates).
346 // This algorithm will not do well if the folder name has changes but the 350 // This algorithm will not do well if the folder name has changes but the
347 // children under them are all the same. 351 // children under them are all the same.
348 352
349 DCHECK(bookmark_model_->IsLoaded()); 353 DCHECK(bookmark_model_->IsLoaded());
350 354
351 // To prime our association, we associate the top-level nodes, Bookmark Bar 355 // To prime our association, we associate the top-level nodes, Bookmark Bar
352 // and Other Bookmarks. 356 // and Other Bookmarks.
353 if (!AssociateTaggedPermanentNode(bookmark_model_->other_node(), 357 if (!AssociateTaggedPermanentNode(bookmark_model_->other_node(),
354 kOtherBookmarksTag)) { 358 kOtherBookmarksTag)) {
355 LOG(ERROR) << "Server did not create top-level nodes. Possibly we " 359 error->Reset(FROM_HERE, kServerError, model_type());
356 << "are running against an out-of-date server?";
357 return false; 360 return false;
358 } 361 }
359 if (!AssociateTaggedPermanentNode(bookmark_model_->bookmark_bar_node(), 362 if (!AssociateTaggedPermanentNode(bookmark_model_->bookmark_bar_node(),
360 kBookmarkBarTag)) { 363 kBookmarkBarTag)) {
361 LOG(ERROR) << "Server did not create top-level nodes. Possibly we " 364 error->Reset(FROM_HERE, kServerError, model_type());
362 << "are running against an out-of-date server?";
363 return false; 365 return false;
364 } 366 }
365 if (!AssociateTaggedPermanentNode(bookmark_model_->synced_node(), 367 if (!AssociateTaggedPermanentNode(bookmark_model_->synced_node(),
366 kSyncedBookmarksTag) && 368 kSyncedBookmarksTag) &&
367 // We only need to ensure that the "synced bookmarks" folder exists on the 369 // We only need to ensure that the "synced bookmarks" folder exists on the
368 // server if the command line flag is set. 370 // server if the command line flag is set.
369 CommandLine::ForCurrentProcess()->HasSwitch( 371 CommandLine::ForCurrentProcess()->HasSwitch(
370 switches::kEnableSyncedBookmarksFolder)) { 372 switches::kEnableSyncedBookmarksFolder)) {
371 LOG(ERROR) << "Server did not create top-level synced nodes. Possibly " 373 error->Reset(FROM_HERE, kServerError, model_type());
372 << "we are running against an out-of-date server?";
373 return false; 374 return false;
374 } 375 }
375 int64 bookmark_bar_sync_id = GetSyncIdFromChromeId( 376 int64 bookmark_bar_sync_id = GetSyncIdFromChromeId(
376 bookmark_model_->bookmark_bar_node()->id()); 377 bookmark_model_->bookmark_bar_node()->id());
377 DCHECK_NE(bookmark_bar_sync_id, sync_api::kInvalidId); 378 DCHECK_NE(bookmark_bar_sync_id, sync_api::kInvalidId);
378 int64 other_bookmarks_sync_id = GetSyncIdFromChromeId( 379 int64 other_bookmarks_sync_id = GetSyncIdFromChromeId(
379 bookmark_model_->other_node()->id()); 380 bookmark_model_->other_node()->id());
380 DCHECK_NE(other_bookmarks_sync_id, sync_api::kInvalidId); 381 DCHECK_NE(other_bookmarks_sync_id, sync_api::kInvalidId);
381 int64 synced_bookmarks_sync_id = GetSyncIdFromChromeId( 382 int64 synced_bookmarks_sync_id = GetSyncIdFromChromeId(
382 bookmark_model_->synced_node()->id()); 383 bookmark_model_->synced_node()->id());
383 if (CommandLine::ForCurrentProcess()->HasSwitch( 384 if (CommandLine::ForCurrentProcess()->HasSwitch(
384 switches::kEnableSyncedBookmarksFolder)) { 385 switches::kEnableSyncedBookmarksFolder)) {
385 DCHECK_NE(synced_bookmarks_sync_id, sync_api::kInvalidId); 386 DCHECK_NE(synced_bookmarks_sync_id, sync_api::kInvalidId);
386 } 387 }
387 388
388 std::stack<int64> dfs_stack; 389 std::stack<int64> dfs_stack;
389 if (synced_bookmarks_sync_id != sync_api::kInvalidId) 390 if (synced_bookmarks_sync_id != sync_api::kInvalidId)
390 dfs_stack.push(synced_bookmarks_sync_id); 391 dfs_stack.push(synced_bookmarks_sync_id);
391 dfs_stack.push(other_bookmarks_sync_id); 392 dfs_stack.push(other_bookmarks_sync_id);
392 dfs_stack.push(bookmark_bar_sync_id); 393 dfs_stack.push(bookmark_bar_sync_id);
393 394
394 sync_api::WriteTransaction trans(FROM_HERE, user_share_); 395 sync_api::WriteTransaction trans(FROM_HERE, user_share_);
395 396
396 while (!dfs_stack.empty()) { 397 while (!dfs_stack.empty()) {
397 int64 sync_parent_id = dfs_stack.top(); 398 int64 sync_parent_id = dfs_stack.top();
398 dfs_stack.pop(); 399 dfs_stack.pop();
399 400
400 sync_api::ReadNode sync_parent(&trans); 401 sync_api::ReadNode sync_parent(&trans);
401 if (!sync_parent.InitByIdLookup(sync_parent_id)) { 402 if (!sync_parent.InitByIdLookup(sync_parent_id)) {
403 error->Reset(FROM_HERE, "Failed to lookup node.", model_type());
402 return false; 404 return false;
403 } 405 }
404 // Only folder nodes are pushed on to the stack. 406 // Only folder nodes are pushed on to the stack.
405 DCHECK(sync_parent.GetIsFolder()); 407 DCHECK(sync_parent.GetIsFolder());
406 408
407 const BookmarkNode* parent_node = GetChromeNodeFromSyncId(sync_parent_id); 409 const BookmarkNode* parent_node = GetChromeNodeFromSyncId(sync_parent_id);
408 DCHECK(parent_node->is_folder()); 410 DCHECK(parent_node->is_folder());
409 411
410 BookmarkNodeFinder node_finder(parent_node); 412 BookmarkNodeFinder node_finder(parent_node);
411 413
412 int index = 0; 414 int index = 0;
413 int64 sync_child_id = sync_parent.GetFirstChildId(); 415 int64 sync_child_id = sync_parent.GetFirstChildId();
414 while (sync_child_id != sync_api::kInvalidId) { 416 while (sync_child_id != sync_api::kInvalidId) {
415 sync_api::WriteNode sync_child_node(&trans); 417 sync_api::WriteNode sync_child_node(&trans);
416 if (!sync_child_node.InitByIdLookup(sync_child_id)) { 418 if (!sync_child_node.InitByIdLookup(sync_child_id)) {
419 error->Reset(FROM_HERE, "Failed to lookup node.", model_type());
417 return false; 420 return false;
418 } 421 }
419 422
420 const BookmarkNode* child_node = NULL; 423 const BookmarkNode* child_node = NULL;
421 child_node = node_finder.FindBookmarkNode(sync_child_node); 424 child_node = node_finder.FindBookmarkNode(sync_child_node);
422 if (child_node) { 425 if (child_node) {
423 bookmark_model_->Move(child_node, parent_node, index); 426 bookmark_model_->Move(child_node, parent_node, index);
424 // Set the favicon for bookmark node from sync node or vice versa. 427 // Set the favicon for bookmark node from sync node or vice versa.
425 if (BookmarkChangeProcessor::SetBookmarkFavicon( 428 if (BookmarkChangeProcessor::SetBookmarkFavicon(
426 &sync_child_node, child_node, bookmark_model_)) { 429 &sync_child_node, child_node, bookmark_model_)) {
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
598 bool BookmarkModelAssociator::CryptoReadyIfNecessary() { 601 bool BookmarkModelAssociator::CryptoReadyIfNecessary() {
599 // We only access the cryptographer while holding a transaction. 602 // We only access the cryptographer while holding a transaction.
600 sync_api::ReadTransaction trans(FROM_HERE, user_share_); 603 sync_api::ReadTransaction trans(FROM_HERE, user_share_);
601 const syncable::ModelTypeSet& encrypted_types = 604 const syncable::ModelTypeSet& encrypted_types =
602 sync_api::GetEncryptedTypes(&trans); 605 sync_api::GetEncryptedTypes(&trans);
603 return encrypted_types.count(syncable::BOOKMARKS) == 0 || 606 return encrypted_types.count(syncable::BOOKMARKS) == 0 ||
604 trans.GetCryptographer()->is_ready(); 607 trans.GetCryptographer()->is_ready();
605 } 608 }
606 609
607 } // namespace browser_sync 610 } // namespace browser_sync
OLDNEW
« no previous file with comments | « chrome/browser/sync/glue/bookmark_model_associator.h ('k') | chrome/browser/sync/glue/data_type_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698