| Index: chrome/browser/sync/glue/bookmark_model_associator.cc
 | 
| diff --git a/chrome/browser/sync/glue/bookmark_model_associator.cc b/chrome/browser/sync/glue/bookmark_model_associator.cc
 | 
| index c8395013242dde72c88ab48e2ccda0c9c04fa1a1..af7c75254ba06047a6f48325050e47b2faea7abc 100644
 | 
| --- a/chrome/browser/sync/glue/bookmark_model_associator.cc
 | 
| +++ b/chrome/browser/sync/glue/bookmark_model_associator.cc
 | 
| @@ -6,6 +6,7 @@
 | 
|  
 | 
|  #include <stack>
 | 
|  
 | 
| +#include "base/command_line.h"
 | 
|  #include "base/hash_tables.h"
 | 
|  #include "base/message_loop.h"
 | 
|  #include "base/task.h"
 | 
| @@ -17,6 +18,7 @@
 | 
|  #include "chrome/browser/sync/syncable/autofill_migration.h"
 | 
|  #include "chrome/browser/sync/syncable/nigori_util.h"
 | 
|  #include "chrome/browser/sync/util/cryptographer.h"
 | 
| +#include "chrome/common/chrome_switches.h"
 | 
|  #include "content/browser/browser_thread.h"
 | 
|  
 | 
|  namespace browser_sync {
 | 
| @@ -40,6 +42,7 @@ namespace browser_sync {
 | 
|  // TODO(ncarter): Pull these tags from an external protocol specification
 | 
|  // rather than hardcoding them here.
 | 
|  static const char kBookmarkBarTag[] = "bookmark_bar";
 | 
| +static const char kSyncedBookmarksTag[] = "synced_bookmarks";
 | 
|  static const char kOtherBookmarksTag[] = "other_bookmarks";
 | 
|  
 | 
|  // Bookmark comparer for map of bookmark nodes.
 | 
| @@ -232,6 +235,7 @@ void BookmarkModelAssociator::Disassociate(int64 sync_id) {
 | 
|  bool BookmarkModelAssociator::SyncModelHasUserCreatedNodes(bool* has_nodes) {
 | 
|    DCHECK(has_nodes);
 | 
|    *has_nodes = false;
 | 
| +  bool has_synced_folder = true;
 | 
|    int64 bookmark_bar_sync_id;
 | 
|    if (!GetSyncIdForTaggedNode(kBookmarkBarTag, &bookmark_bar_sync_id)) {
 | 
|      return false;
 | 
| @@ -240,6 +244,10 @@ bool BookmarkModelAssociator::SyncModelHasUserCreatedNodes(bool* has_nodes) {
 | 
|    if (!GetSyncIdForTaggedNode(kOtherBookmarksTag, &other_bookmarks_sync_id)) {
 | 
|      return false;
 | 
|    }
 | 
| +  int64 synced_bookmarks_sync_id;
 | 
| +  if (!GetSyncIdForTaggedNode(kSyncedBookmarksTag, &synced_bookmarks_sync_id)) {
 | 
| +    has_synced_folder = false;
 | 
| +  }
 | 
|  
 | 
|    sync_api::ReadTransaction trans(user_share_);
 | 
|  
 | 
| @@ -253,10 +261,18 @@ bool BookmarkModelAssociator::SyncModelHasUserCreatedNodes(bool* has_nodes) {
 | 
|      return false;
 | 
|    }
 | 
|  
 | 
| +  sync_api::ReadNode synced_bookmarks_node(&trans);
 | 
| +  if (has_synced_folder &&
 | 
| +      !synced_bookmarks_node.InitByIdLookup(synced_bookmarks_sync_id)) {
 | 
| +    return false;
 | 
| +  }
 | 
| +
 | 
|    // Sync model has user created nodes if either one of the permanent nodes
 | 
|    // has children.
 | 
|    *has_nodes = bookmark_bar_node.GetFirstChildId() != sync_api::kInvalidId ||
 | 
| -      other_bookmarks_node.GetFirstChildId() != sync_api::kInvalidId;
 | 
| +      other_bookmarks_node.GetFirstChildId() != sync_api::kInvalidId ||
 | 
| +      (has_synced_folder &&
 | 
| +          synced_bookmarks_node.GetFirstChildId() != sync_api::kInvalidId);
 | 
|    return true;
 | 
|  }
 | 
|  
 | 
| @@ -346,14 +362,32 @@ bool BookmarkModelAssociator::BuildAssociations() {
 | 
|                 << "are running against an out-of-date server?";
 | 
|      return false;
 | 
|    }
 | 
| +  if (!AssociateTaggedPermanentNode(bookmark_model_->synced_node(),
 | 
| +                                    kSyncedBookmarksTag) &&
 | 
| +      // We only need to ensure that the "synced bookmarks" folder exists on the
 | 
| +      // server if the command line flag is set.
 | 
| +      CommandLine::ForCurrentProcess()->HasSwitch(
 | 
| +      switches::kEnableSyncedBookmarksFolder)) {
 | 
| +    LOG(ERROR) << "Server did not create top-level synced nodes.  Possibly "
 | 
| +               << "we are running against an out-of-date server?";
 | 
| +    return false;
 | 
| +  }
 | 
|    int64 bookmark_bar_sync_id = GetSyncIdFromChromeId(
 | 
|        bookmark_model_->GetBookmarkBarNode()->id());
 | 
| -  DCHECK(bookmark_bar_sync_id != sync_api::kInvalidId);
 | 
| +  DCHECK_NE(bookmark_bar_sync_id, sync_api::kInvalidId);
 | 
|    int64 other_bookmarks_sync_id = GetSyncIdFromChromeId(
 | 
|        bookmark_model_->other_node()->id());
 | 
| -  DCHECK(other_bookmarks_sync_id != sync_api::kInvalidId);
 | 
| +  DCHECK_NE(other_bookmarks_sync_id, sync_api::kInvalidId);
 | 
| +  int64 synced_bookmarks_sync_id = GetSyncIdFromChromeId(
 | 
| +       bookmark_model_->synced_node()->id());
 | 
| +  if (CommandLine::ForCurrentProcess()->HasSwitch(
 | 
| +      switches::kEnableSyncedBookmarksFolder)) {
 | 
| +    DCHECK_NE(synced_bookmarks_sync_id, sync_api::kInvalidId);
 | 
| +  }
 | 
|  
 | 
|    std::stack<int64> dfs_stack;
 | 
| +  if (synced_bookmarks_sync_id != sync_api::kInvalidId)
 | 
| +    dfs_stack.push(synced_bookmarks_sync_id);
 | 
|    dfs_stack.push(other_bookmarks_sync_id);
 | 
|    dfs_stack.push(bookmark_bar_sync_id);
 | 
|  
 | 
| @@ -486,14 +520,25 @@ bool BookmarkModelAssociator::LoadAssociations() {
 | 
|      // We should always be able to find the permanent nodes.
 | 
|      return false;
 | 
|    }
 | 
| +  int64 synced_bookmarks_id = -1;
 | 
| +  if (!GetSyncIdForTaggedNode(kSyncedBookmarksTag, &synced_bookmarks_id) &&
 | 
| +      CommandLine::ForCurrentProcess()->HasSwitch(
 | 
| +      switches::kEnableSyncedBookmarksFolder)) {
 | 
| +
 | 
| +    // We should always be able to find the permanent nodes.
 | 
| +    return false;
 | 
| +  }
 | 
|  
 | 
|    // Build a bookmark node ID index since we are going to repeatedly search for
 | 
|    // bookmark nodes by their IDs.
 | 
|    BookmarkNodeIdIndex id_index;
 | 
|    id_index.AddAll(bookmark_model_->GetBookmarkBarNode());
 | 
|    id_index.AddAll(bookmark_model_->other_node());
 | 
| +  id_index.AddAll(bookmark_model_->synced_node());
 | 
|  
 | 
|    std::stack<int64> dfs_stack;
 | 
| +  if (synced_bookmarks_id != -1)
 | 
| +    dfs_stack.push(synced_bookmarks_id);
 | 
|    dfs_stack.push(other_bookmarks_id);
 | 
|    dfs_stack.push(bookmark_bar_id);
 | 
|  
 | 
| @@ -522,6 +567,7 @@ bool BookmarkModelAssociator::LoadAssociations() {
 | 
|      // Don't try to call NodesMatch on permanent nodes like bookmark bar and
 | 
|      // other bookmarks. They are not expected to match.
 | 
|      if (node != bookmark_model_->GetBookmarkBarNode() &&
 | 
| +        node != bookmark_model_->synced_node() &&
 | 
|          node != bookmark_model_->other_node() &&
 | 
|          !NodesMatch(node, &sync_parent))
 | 
|        return false;
 | 
| 
 |