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

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

Issue 6931018: Initial implementation of "Synced Bookmarks" folder. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Merge Created 9 years, 7 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/hash_tables.h" 10 #include "base/hash_tables.h"
10 #include "base/message_loop.h" 11 #include "base/message_loop.h"
11 #include "base/task.h" 12 #include "base/task.h"
12 #include "base/utf_string_conversions.h" 13 #include "base/utf_string_conversions.h"
13 #include "chrome/browser/bookmarks/bookmark_model.h" 14 #include "chrome/browser/bookmarks/bookmark_model.h"
14 #include "chrome/browser/profiles/profile.h" 15 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/sync/engine/syncapi.h" 16 #include "chrome/browser/sync/engine/syncapi.h"
16 #include "chrome/browser/sync/glue/bookmark_change_processor.h" 17 #include "chrome/browser/sync/glue/bookmark_change_processor.h"
17 #include "chrome/browser/sync/syncable/autofill_migration.h" 18 #include "chrome/browser/sync/syncable/autofill_migration.h"
18 #include "chrome/browser/sync/syncable/nigori_util.h" 19 #include "chrome/browser/sync/syncable/nigori_util.h"
19 #include "chrome/browser/sync/util/cryptographer.h" 20 #include "chrome/browser/sync/util/cryptographer.h"
21 #include "chrome/common/chrome_switches.h"
20 #include "content/browser/browser_thread.h" 22 #include "content/browser/browser_thread.h"
21 23
22 namespace browser_sync { 24 namespace browser_sync {
23 25
24 // The sync protocol identifies top-level entities by means of well-known tags, 26 // The sync protocol identifies top-level entities by means of well-known tags,
25 // which should not be confused with titles. Each tag corresponds to a 27 // which should not be confused with titles. Each tag corresponds to a
26 // singleton instance of a particular top-level node in a user's share; the 28 // singleton instance of a particular top-level node in a user's share; the
27 // tags are consistent across users. The tags allow us to locate the specific 29 // tags are consistent across users. The tags allow us to locate the specific
28 // folders whose contents we care about synchronizing, without having to do a 30 // folders whose contents we care about synchronizing, without having to do a
29 // lookup by name or path. The tags should not be made user-visible. 31 // lookup by name or path. The tags should not be made user-visible.
30 // For example, the tag "bookmark_bar" represents the permanent node for 32 // For example, the tag "bookmark_bar" represents the permanent node for
31 // bookmarks bar in Chrome. The tag "other_bookmarks" represents the permanent 33 // bookmarks bar in Chrome. The tag "other_bookmarks" represents the permanent
32 // folder Other Bookmarks in Chrome. 34 // folder Other Bookmarks in Chrome.
33 // 35 //
34 // It is the responsibility of something upstream (at time of writing, 36 // It is the responsibility of something upstream (at time of writing,
35 // the sync server) to create these tagged nodes when initializing sync 37 // the sync server) to create these tagged nodes when initializing sync
36 // for the first time for a user. Thus, once the backend finishes 38 // for the first time for a user. Thus, once the backend finishes
37 // initializing, the ProfileSyncService can rely on the presence of tagged 39 // initializing, the ProfileSyncService can rely on the presence of tagged
38 // nodes. 40 // nodes.
39 // 41 //
40 // TODO(ncarter): Pull these tags from an external protocol specification 42 // TODO(ncarter): Pull these tags from an external protocol specification
41 // rather than hardcoding them here. 43 // rather than hardcoding them here.
42 static const char kBookmarkBarTag[] = "bookmark_bar"; 44 static const char kBookmarkBarTag[] = "bookmark_bar";
45 static const char kSyncedBookmarksTag[] = "synced_bookmarks";
43 static const char kOtherBookmarksTag[] = "other_bookmarks"; 46 static const char kOtherBookmarksTag[] = "other_bookmarks";
44 47
45 // Bookmark comparer for map of bookmark nodes. 48 // Bookmark comparer for map of bookmark nodes.
46 class BookmarkComparer { 49 class BookmarkComparer {
47 public: 50 public:
48 // Compares the two given nodes and returns whether node1 should appear 51 // Compares the two given nodes and returns whether node1 should appear
49 // before node2 in strict weak ordering. 52 // before node2 in strict weak ordering.
50 bool operator()(const BookmarkNode* node1, 53 bool operator()(const BookmarkNode* node1,
51 const BookmarkNode* node2) const { 54 const BookmarkNode* node2) const {
52 DCHECK(node1); 55 DCHECK(node1);
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
225 if (iter == id_map_inverse_.end()) 228 if (iter == id_map_inverse_.end())
226 return; 229 return;
227 id_map_.erase(iter->second->id()); 230 id_map_.erase(iter->second->id());
228 id_map_inverse_.erase(iter); 231 id_map_inverse_.erase(iter);
229 dirty_associations_sync_ids_.erase(sync_id); 232 dirty_associations_sync_ids_.erase(sync_id);
230 } 233 }
231 234
232 bool BookmarkModelAssociator::SyncModelHasUserCreatedNodes(bool* has_nodes) { 235 bool BookmarkModelAssociator::SyncModelHasUserCreatedNodes(bool* has_nodes) {
233 DCHECK(has_nodes); 236 DCHECK(has_nodes);
234 *has_nodes = false; 237 *has_nodes = false;
238 bool has_synced_folder = true;
235 int64 bookmark_bar_sync_id; 239 int64 bookmark_bar_sync_id;
236 if (!GetSyncIdForTaggedNode(kBookmarkBarTag, &bookmark_bar_sync_id)) { 240 if (!GetSyncIdForTaggedNode(kBookmarkBarTag, &bookmark_bar_sync_id)) {
237 return false; 241 return false;
238 } 242 }
239 int64 other_bookmarks_sync_id; 243 int64 other_bookmarks_sync_id;
240 if (!GetSyncIdForTaggedNode(kOtherBookmarksTag, &other_bookmarks_sync_id)) { 244 if (!GetSyncIdForTaggedNode(kOtherBookmarksTag, &other_bookmarks_sync_id)) {
241 return false; 245 return false;
242 } 246 }
247 int64 synced_bookmarks_sync_id;
248 if (!GetSyncIdForTaggedNode(kSyncedBookmarksTag, &synced_bookmarks_sync_id)) {
249 has_synced_folder = false;
250 }
243 251
244 sync_api::ReadTransaction trans(user_share_); 252 sync_api::ReadTransaction trans(user_share_);
245 253
246 sync_api::ReadNode bookmark_bar_node(&trans); 254 sync_api::ReadNode bookmark_bar_node(&trans);
247 if (!bookmark_bar_node.InitByIdLookup(bookmark_bar_sync_id)) { 255 if (!bookmark_bar_node.InitByIdLookup(bookmark_bar_sync_id)) {
248 return false; 256 return false;
249 } 257 }
250 258
251 sync_api::ReadNode other_bookmarks_node(&trans); 259 sync_api::ReadNode other_bookmarks_node(&trans);
252 if (!other_bookmarks_node.InitByIdLookup(other_bookmarks_sync_id)) { 260 if (!other_bookmarks_node.InitByIdLookup(other_bookmarks_sync_id)) {
253 return false; 261 return false;
254 } 262 }
255 263
264 sync_api::ReadNode synced_bookmarks_node(&trans);
265 if (has_synced_folder &&
266 !synced_bookmarks_node.InitByIdLookup(synced_bookmarks_sync_id)) {
267 return false;
268 }
269
256 // Sync model has user created nodes if either one of the permanent nodes 270 // Sync model has user created nodes if either one of the permanent nodes
257 // has children. 271 // has children.
258 *has_nodes = bookmark_bar_node.GetFirstChildId() != sync_api::kInvalidId || 272 *has_nodes = bookmark_bar_node.GetFirstChildId() != sync_api::kInvalidId ||
259 other_bookmarks_node.GetFirstChildId() != sync_api::kInvalidId; 273 other_bookmarks_node.GetFirstChildId() != sync_api::kInvalidId ||
274 (has_synced_folder &&
275 synced_bookmarks_node.GetFirstChildId() != sync_api::kInvalidId);
260 return true; 276 return true;
261 } 277 }
262 278
263 bool BookmarkModelAssociator::NodesMatch(const BookmarkNode* bookmark, 279 bool BookmarkModelAssociator::NodesMatch(const BookmarkNode* bookmark,
264 const sync_api::BaseNode* sync_node) const { 280 const sync_api::BaseNode* sync_node) const {
265 if (bookmark->GetTitle() != WideToUTF16Hack(sync_node->GetTitle())) 281 if (bookmark->GetTitle() != WideToUTF16Hack(sync_node->GetTitle()))
266 return false; 282 return false;
267 if (bookmark->is_folder() != sync_node->GetIsFolder()) 283 if (bookmark->is_folder() != sync_node->GetIsFolder())
268 return false; 284 return false;
269 if (bookmark->is_url()) { 285 if (bookmark->is_url()) {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 LOG(ERROR) << "Server did not create top-level nodes. Possibly we " 355 LOG(ERROR) << "Server did not create top-level nodes. Possibly we "
340 << "are running against an out-of-date server?"; 356 << "are running against an out-of-date server?";
341 return false; 357 return false;
342 } 358 }
343 if (!AssociateTaggedPermanentNode(bookmark_model_->GetBookmarkBarNode(), 359 if (!AssociateTaggedPermanentNode(bookmark_model_->GetBookmarkBarNode(),
344 kBookmarkBarTag)) { 360 kBookmarkBarTag)) {
345 LOG(ERROR) << "Server did not create top-level nodes. Possibly we " 361 LOG(ERROR) << "Server did not create top-level nodes. Possibly we "
346 << "are running against an out-of-date server?"; 362 << "are running against an out-of-date server?";
347 return false; 363 return false;
348 } 364 }
365 // We only need to ensure that the "synced bookmarks" folder exists on the
366 // server if the command line flag is set.
367 if (CommandLine::ForCurrentProcess()->HasSwitch(
368 switches::kEnableSyncedBookmarksFolder) &&
369 !AssociateTaggedPermanentNode(bookmark_model_->synced_node(),
370 kSyncedBookmarksTag)) {
371 LOG(ERROR) << "Server did not create top-level synced nodes. Possibly "
372 << "we are running against an out-of-date server?";
373 return false;
374 }
349 int64 bookmark_bar_sync_id = GetSyncIdFromChromeId( 375 int64 bookmark_bar_sync_id = GetSyncIdFromChromeId(
350 bookmark_model_->GetBookmarkBarNode()->id()); 376 bookmark_model_->GetBookmarkBarNode()->id());
351 DCHECK(bookmark_bar_sync_id != sync_api::kInvalidId); 377 DCHECK(bookmark_bar_sync_id != sync_api::kInvalidId);
352 int64 other_bookmarks_sync_id = GetSyncIdFromChromeId( 378 int64 other_bookmarks_sync_id = GetSyncIdFromChromeId(
353 bookmark_model_->other_node()->id()); 379 bookmark_model_->other_node()->id());
354 DCHECK(other_bookmarks_sync_id != sync_api::kInvalidId); 380 DCHECK(other_bookmarks_sync_id != sync_api::kInvalidId);
381 int64 synced_bookmarks_sync_id = GetSyncIdFromChromeId(
382 bookmark_model_->synced_node()->id());
383 if (CommandLine::ForCurrentProcess()->HasSwitch(
384 switches::kEnableSyncedBookmarksFolder)) {
385 DCHECK(synced_bookmarks_sync_id != sync_api::kInvalidId);
386 }
355 387
356 std::stack<int64> dfs_stack; 388 std::stack<int64> dfs_stack;
389 if (synced_bookmarks_sync_id != sync_api::kInvalidId)
390 dfs_stack.push(synced_bookmarks_sync_id);
357 dfs_stack.push(other_bookmarks_sync_id); 391 dfs_stack.push(other_bookmarks_sync_id);
358 dfs_stack.push(bookmark_bar_sync_id); 392 dfs_stack.push(bookmark_bar_sync_id);
359 393
360 sync_api::WriteTransaction trans(user_share_); 394 sync_api::WriteTransaction trans(user_share_);
361 395
362 while (!dfs_stack.empty()) { 396 while (!dfs_stack.empty()) {
363 int64 sync_parent_id = dfs_stack.top(); 397 int64 sync_parent_id = dfs_stack.top();
364 dfs_stack.pop(); 398 dfs_stack.pop();
365 399
366 sync_api::ReadNode sync_parent(&trans); 400 sync_api::ReadNode sync_parent(&trans);
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
479 int64 bookmark_bar_id; 513 int64 bookmark_bar_id;
480 if (!GetSyncIdForTaggedNode(kBookmarkBarTag, &bookmark_bar_id)) { 514 if (!GetSyncIdForTaggedNode(kBookmarkBarTag, &bookmark_bar_id)) {
481 // We should always be able to find the permanent nodes. 515 // We should always be able to find the permanent nodes.
482 return false; 516 return false;
483 } 517 }
484 int64 other_bookmarks_id; 518 int64 other_bookmarks_id;
485 if (!GetSyncIdForTaggedNode(kOtherBookmarksTag, &other_bookmarks_id)) { 519 if (!GetSyncIdForTaggedNode(kOtherBookmarksTag, &other_bookmarks_id)) {
486 // We should always be able to find the permanent nodes. 520 // We should always be able to find the permanent nodes.
487 return false; 521 return false;
488 } 522 }
523 int64 synced_bookmarks_id = -1;
524 if (CommandLine::ForCurrentProcess()->HasSwitch(
525 switches::kEnableSyncedBookmarksFolder) &&
526 !GetSyncIdForTaggedNode(kSyncedBookmarksTag, &synced_bookmarks_id)) {
527 // We should always be able to find the permanent nodes.
528 return false;
529 }
489 530
490 // Build a bookmark node ID index since we are going to repeatedly search for 531 // Build a bookmark node ID index since we are going to repeatedly search for
491 // bookmark nodes by their IDs. 532 // bookmark nodes by their IDs.
492 BookmarkNodeIdIndex id_index; 533 BookmarkNodeIdIndex id_index;
493 id_index.AddAll(bookmark_model_->GetBookmarkBarNode()); 534 id_index.AddAll(bookmark_model_->GetBookmarkBarNode());
494 id_index.AddAll(bookmark_model_->other_node()); 535 id_index.AddAll(bookmark_model_->other_node());
536 id_index.AddAll(bookmark_model_->synced_node());
495 537
496 std::stack<int64> dfs_stack; 538 std::stack<int64> dfs_stack;
539 if (synced_bookmarks_id != -1)
540 dfs_stack.push(synced_bookmarks_id);
497 dfs_stack.push(other_bookmarks_id); 541 dfs_stack.push(other_bookmarks_id);
498 dfs_stack.push(bookmark_bar_id); 542 dfs_stack.push(bookmark_bar_id);
499 543
500 sync_api::ReadTransaction trans(user_share_); 544 sync_api::ReadTransaction trans(user_share_);
501 545
502 // Count total number of nodes in sync model so that we can compare that 546 // Count total number of nodes in sync model so that we can compare that
503 // with the total number of nodes in the bookmark model. 547 // with the total number of nodes in the bookmark model.
504 size_t sync_node_count = 0; 548 size_t sync_node_count = 0;
505 while (!dfs_stack.empty()) { 549 while (!dfs_stack.empty()) {
506 int64 parent_id = dfs_stack.top(); 550 int64 parent_id = dfs_stack.top();
507 dfs_stack.pop(); 551 dfs_stack.pop();
508 ++sync_node_count; 552 ++sync_node_count;
509 sync_api::ReadNode sync_parent(&trans); 553 sync_api::ReadNode sync_parent(&trans);
510 if (!sync_parent.InitByIdLookup(parent_id)) { 554 if (!sync_parent.InitByIdLookup(parent_id)) {
511 return false; 555 return false;
512 } 556 }
513 557
514 int64 external_id = sync_parent.GetExternalId(); 558 int64 external_id = sync_parent.GetExternalId();
515 if (external_id == 0) 559 if (external_id == 0)
516 return false; 560 return false;
517 561
518 const BookmarkNode* node = id_index.Find(external_id); 562 const BookmarkNode* node = id_index.Find(external_id);
519 if (!node) 563 if (!node)
520 return false; 564 return false;
521 565
522 // Don't try to call NodesMatch on permanent nodes like bookmark bar and 566 // Don't try to call NodesMatch on permanent nodes like bookmark bar and
523 // other bookmarks. They are not expected to match. 567 // other bookmarks. They are not expected to match.
524 if (node != bookmark_model_->GetBookmarkBarNode() && 568 if (node != bookmark_model_->GetBookmarkBarNode() &&
569 node != bookmark_model_->synced_node() &&
525 node != bookmark_model_->other_node() && 570 node != bookmark_model_->other_node() &&
526 !NodesMatch(node, &sync_parent)) 571 !NodesMatch(node, &sync_parent))
527 return false; 572 return false;
528 573
529 Associate(node, sync_parent.GetId()); 574 Associate(node, sync_parent.GetId());
530 575
531 // Add all children of the current node to the stack. 576 // Add all children of the current node to the stack.
532 int64 child_id = sync_parent.GetFirstChildId(); 577 int64 child_id = sync_parent.GetFirstChildId();
533 while (child_id != sync_api::kInvalidId) { 578 while (child_id != sync_api::kInvalidId) {
534 dfs_stack.push(child_id); 579 dfs_stack.push(child_id);
(...skipping 17 matching lines...) Expand all
552 bool BookmarkModelAssociator::CryptoReadyIfNecessary() { 597 bool BookmarkModelAssociator::CryptoReadyIfNecessary() {
553 // We only access the cryptographer while holding a transaction. 598 // We only access the cryptographer while holding a transaction.
554 sync_api::ReadTransaction trans(user_share_); 599 sync_api::ReadTransaction trans(user_share_);
555 const syncable::ModelTypeSet& encrypted_types = 600 const syncable::ModelTypeSet& encrypted_types =
556 GetEncryptedDataTypes(trans.GetWrappedTrans()); 601 GetEncryptedDataTypes(trans.GetWrappedTrans());
557 return encrypted_types.count(syncable::BOOKMARKS) == 0 || 602 return encrypted_types.count(syncable::BOOKMARKS) == 0 ||
558 trans.GetCryptographer()->is_ready(); 603 trans.GetCryptographer()->is_ready();
559 } 604 }
560 605
561 } // namespace browser_sync 606 } // namespace browser_sync
OLDNEW
« no previous file with comments | « chrome/browser/sync/glue/bookmark_change_processor.cc ('k') | chrome/browser/sync/profile_sync_service_bookmark_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698