Expose TreeNode::children() publicly and use it to remove empty().

Since the public getter is const, this converts BookmarkModel (which was using a
non-const getter) to use direct member access, with a friend declaration.  Filed
bug 965314 about cleaning this up.

This also converts/comments the rest of tree_node_model.h in preparation for
removing child_count() and GetChild().

Bug: 956419
Change-Id: I28152e15ee380ada61a2668ab38bb53f25771b18
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1621027
Reviewed-by: Marc Treib <treib@chromium.org>
Reviewed-by: Rohit Rao <rohitrao@chromium.org>
Reviewed-by: Theresa <twellington@chromium.org>
Reviewed-by: Tommy Li <tommycli@chromium.org>
Reviewed-by: Scott Violet <sky@chromium.org>
Reviewed-by: Ilya Sherman <isherman@chromium.org>
Commit-Queue: Peter Kasting <pkasting@chromium.org>
Cr-Commit-Position: refs/heads/master@{#661887}
diff --git a/chrome/browser/android/bookmarks/bookmark_bridge.cc b/chrome/browser/android/bookmarks/bookmark_bridge.cc
index f5b702b..a85e6c4 100644
--- a/chrome/browser/android/bookmarks/bookmark_bridge.cc
+++ b/chrome/browser/android/bookmarks/bookmark_bridge.cc
@@ -808,7 +808,7 @@
   const BookmarkNode* folder = GetNodeByID(folder_id, type);
   if (!folder || folder->type() == BookmarkNode::URL ||
       !IsFolderAvailable(folder)) {
-    if (!managed_bookmark_service_->managed_node()->empty())
+    if (!managed_bookmark_service_->managed_node()->children().empty())
       folder = managed_bookmark_service_->managed_node();
     else
       folder = bookmark_model_->mobile_node();
@@ -876,7 +876,8 @@
     const BookmarkNode* folder) const {
   // The managed bookmarks folder is not shown if there are no bookmarks
   // configured via policy.
-  if (folder == managed_bookmark_service_->managed_node() && folder->empty())
+  if (folder == managed_bookmark_service_->managed_node() &&
+      folder->children().empty())
     return false;
 
   auto* identity_manager =
diff --git a/chrome/browser/bookmarks/managed_bookmark_service_unittest.cc b/chrome/browser/bookmarks/managed_bookmark_service_unittest.cc
index 779b937..ef5ece5 100644
--- a/chrome/browser/bookmarks/managed_bookmark_service_unittest.cc
+++ b/chrome/browser/bookmarks/managed_bookmark_service_unittest.cc
@@ -52,7 +52,7 @@
   DCHECK(managed);
 
   ASSERT_TRUE(managed->managed_node());
-  EXPECT_TRUE(managed->managed_node()->empty());
+  EXPECT_TRUE(managed->managed_node()->children().empty());
   EXPECT_FALSE(managed->managed_node()->IsVisible());
 }
 
@@ -166,9 +166,9 @@
 
 TEST_F(ManagedBookmarkServiceTest, LoadInitial) {
   // Verifies that the initial load picks up the initial policy too.
-  EXPECT_TRUE(model_->bookmark_bar_node()->empty());
-  EXPECT_TRUE(model_->other_node()->empty());
-  EXPECT_FALSE(managed_->managed_node()->empty());
+  EXPECT_TRUE(model_->bookmark_bar_node()->children().empty());
+  EXPECT_TRUE(model_->other_node()->children().empty());
+  EXPECT_FALSE(managed_->managed_node()->children().empty());
   EXPECT_TRUE(managed_->managed_node()->IsVisible());
 
   std::unique_ptr<base::DictionaryValue> expected(CreateExpectedTree());
@@ -239,7 +239,7 @@
   prefs_->RemoveManagedPref(bookmarks::prefs::kManagedBookmarks);
   Mock::VerifyAndClearExpectations(&observer_);
 
-  EXPECT_TRUE(managed_->managed_node()->empty());
+  EXPECT_TRUE(managed_->managed_node()->children().empty());
   EXPECT_FALSE(managed_->managed_node()->IsVisible());
 }
 
diff --git a/chrome/browser/browsing_data/cookies_tree_model.cc b/chrome/browser/browsing_data/cookies_tree_model.cc
index fcfb230..b09b2f2 100644
--- a/chrome/browser/browsing_data/cookies_tree_model.cc
+++ b/chrome/browser/browsing_data/cookies_tree_model.cc
@@ -1451,7 +1451,7 @@
   cookie_node->DeleteStoredObjects();
   CookieTreeNode* parent_node = cookie_node->parent();
   Remove(parent_node, cookie_node);
-  if (parent_node->empty())
+  if (parent_node->children().empty())
     DeleteCookieNode(parent_node);
 }
 
diff --git a/chrome/browser/browsing_data/cookies_tree_model_unittest.cc b/chrome/browser/browsing_data/cookies_tree_model_unittest.cc
index d0a699e..504f3bb 100644
--- a/chrome/browser/browsing_data/cookies_tree_model_unittest.cc
+++ b/chrome/browser/browsing_data/cookies_tree_model_unittest.cc
@@ -230,13 +230,11 @@
       CookieTreeNode::DetailedInfo::NodeType node_type,
       content_settings::CookieSettings* cookie_settings,
       const GURL& expected_url) {
-    if (!node->empty()) {
-      for (int i = 0; i < node->child_count(); ++i) {
-        const CookieTreeNode* child = node->GetChild(i);
-        CheckContentSettingsUrlForHostNodes(child,
-                                            child->GetDetailedInfo().node_type,
-                                            cookie_settings, expected_url);
-      }
+    for (int i = 0; i < node->child_count(); ++i) {
+      const CookieTreeNode* child = node->GetChild(i);
+      CheckContentSettingsUrlForHostNodes(child,
+                                          child->GetDetailedInfo().node_type,
+                                          cookie_settings, expected_url);
     }
 
     ASSERT_EQ(node_type, node->GetDetailedInfo().node_type);
@@ -261,7 +259,7 @@
   std::string GetNodesOfChildren(
       const CookieTreeNode* node,
       CookieTreeNode::DetailedInfo::NodeType node_type) {
-    if (!node->empty()) {
+    if (!node->children().empty()) {
       std::string retval;
       for (int i = 0; i < node->child_count(); ++i) {
         retval += GetNodesOfChildren(node->GetChild(i), node_type);
diff --git a/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers.cc b/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers.cc
index 8b04de2..4a0be82 100644
--- a/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers.cc
+++ b/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers.cc
@@ -137,7 +137,7 @@
     *error = bookmark_api_constants::kModifyManagedError;
     return false;
   }
-  if (node->is_folder() && !node->empty() && !recursive) {
+  if (node->is_folder() && !node->children().empty() && !recursive) {
     *error = bookmark_api_constants::kFolderNotEmptyError;
     return false;
   }
diff --git a/chrome/browser/importer/profile_writer.cc b/chrome/browser/importer/profile_writer.cc
index 78bb6b0..b5f31b4 100644
--- a/chrome/browser/importer/profile_writer.cc
+++ b/chrome/browser/importer/profile_writer.cc
@@ -128,7 +128,7 @@
   // If the bookmark bar is currently empty, we should import directly to it.
   // Otherwise, we should import everything to a subfolder.
   const BookmarkNode* bookmark_bar = model->bookmark_bar_node();
-  bool import_to_top_level = bookmark_bar->empty();
+  bool import_to_top_level = bookmark_bar->children().empty();
 
   // Reorder bookmarks so that the toolbar entries come first.
   std::vector<ImportedBookmarkEntry> toolbar_bookmarks;
diff --git a/chrome/browser/sync/test/integration/performance/bookmarks_sync_perf_test.cc b/chrome/browser/sync/test/integration/performance/bookmarks_sync_perf_test.cc
index 400352d..db033a2 100644
--- a/chrome/browser/sync/test/integration/performance/bookmarks_sync_perf_test.cc
+++ b/chrome/browser/sync/test/integration/performance/bookmarks_sync_perf_test.cc
@@ -70,7 +70,7 @@
 }
 
 void BookmarksSyncPerfTest::RemoveURLs(int profile) {
-  while (!GetBookmarkBarNode(profile)->empty()) {
+  while (!GetBookmarkBarNode(profile)->children().empty()) {
     Remove(profile, GetBookmarkBarNode(profile), 0);
   }
 }
diff --git a/chrome/browser/sync/test/integration/two_client_bookmarks_sync_test.cc b/chrome/browser/sync/test/integration/two_client_bookmarks_sync_test.cc
index 802229e..f45a1f4 100644
--- a/chrome/browser/sync/test/integration/two_client_bookmarks_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_bookmarks_sync_test.cc
@@ -2106,18 +2106,18 @@
   // Verify that there are no managed bookmarks at startup in either profile.
   // The Managed Bookmarks folder should not be visible at this stage.
   const BookmarkNode* managed_node0 = GetManagedNode(0);
-  ASSERT_TRUE(managed_node0->empty());
+  ASSERT_TRUE(managed_node0->children().empty());
   ASSERT_FALSE(managed_node0->IsVisible());
   const BookmarkNode* managed_node1 = GetManagedNode(1);
-  ASSERT_TRUE(managed_node1->empty());
+  ASSERT_TRUE(managed_node1->children().empty());
   ASSERT_FALSE(managed_node1->IsVisible());
 
   // Verify that the bookmark bar node is empty on both profiles too.
   const BookmarkNode* bar_node0 = GetBookmarkBarNode(0);
-  ASSERT_TRUE(bar_node0->empty());
+  ASSERT_TRUE(bar_node0->children().empty());
   ASSERT_TRUE(bar_node0->IsVisible());
   const BookmarkNode* bar_node1 = GetBookmarkBarNode(1);
-  ASSERT_TRUE(bar_node1->empty());
+  ASSERT_TRUE(bar_node1->children().empty());
   ASSERT_TRUE(bar_node1->IsVisible());
 
   // Verify that adding a bookmark is observed by the second Profile.
diff --git a/chrome/browser/ui/bookmarks/bookmark_context_menu_controller.cc b/chrome/browser/ui/bookmarks/bookmark_context_menu_controller.cc
index b133ffe..1461452 100644
--- a/chrome/browser/ui/bookmarks/bookmark_context_menu_controller.cc
+++ b/chrome/browser/ui/bookmarks/bookmark_context_menu_controller.cc
@@ -482,7 +482,7 @@
     // there are any managed bookmarks configured at all.
     bookmarks::ManagedBookmarkService* managed =
         ManagedBookmarkServiceFactory::GetForProfile(profile_);
-    return !managed->managed_node()->empty();
+    return !managed->managed_node()->children().empty();
   }
 
   return true;
diff --git a/chrome/browser/ui/bookmarks/bookmark_utils_desktop.cc b/chrome/browser/ui/bookmarks/bookmark_utils_desktop.cc
index f69c727..7b7d099 100644
--- a/chrome/browser/ui/bookmarks/bookmark_utils_desktop.cc
+++ b/chrome/browser/ui/bookmarks/bookmark_utils_desktop.cc
@@ -170,7 +170,7 @@
 
 bool ConfirmDeleteBookmarkNode(const BookmarkNode* node,
                                gfx::NativeWindow window) {
-  DCHECK(node && node->is_folder() && !node->empty());
+  DCHECK(node && node->is_folder() && !node->children().empty());
   return ShowQuestionMessageBox(
              window, l10n_util::GetStringUTF16(IDS_PRODUCT_NAME),
              l10n_util::GetPluralStringFUTF16(
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.mm
index 54b4ed2..9055baf 100644
--- a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.mm
+++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.mm
@@ -112,31 +112,31 @@
       ManagedBookmarkServiceFactory::GetForProfile(profile_);
   const BookmarkNode* barNode = model->bookmark_bar_node();
   const BookmarkNode* managedNode = managed->managed_node();
-  if (!barNode->empty() || !managedNode->empty())
+  if (!barNode->children().empty() || !managedNode->children().empty())
     [menu_root_ addItem:[NSMenuItem separatorItem]];
-  if (!managedNode->empty()) {
+  if (!managedNode->children().empty()) {
     // Most users never see this node, so the image is only loaded if needed.
     ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
     NSImage* image =
         rb.GetNativeImageNamed(IDR_BOOKMARK_BAR_FOLDER_MANAGED).ToNSImage();
     AddNodeAsSubmenu(menu_root_, managedNode, image);
   }
-  if (!barNode->empty())
+  if (!barNode->children().empty())
     AddNodeToMenu(barNode, menu_root_);
 
   // If the "Other Bookmarks" folder has any content, make a submenu for it and
   // fill it in.
-  if (!model->other_node()->empty()) {
+  if (!model->other_node()->children().empty()) {
     [menu_root_ addItem:[NSMenuItem separatorItem]];
     AddNodeAsSubmenu(menu_root_, model->other_node(), folder_image_);
   }
 
   // If the "Mobile Bookmarks" folder has any content, make a submenu for it and
   // fill it in.
-  if (!model->mobile_node()->empty()) {
+  if (!model->mobile_node()->children().empty()) {
     // Add a separator if we did not already add one due to a non-empty
     // "Other Bookmarks" folder.
-    if (model->other_node()->empty())
+    if (model->other_node()->children().empty())
       [menu_root_ addItem:[NSMenuItem separatorItem]];
 
     AddNodeAsSubmenu(menu_root_, model->mobile_node(), folder_image_);
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
index 93fd77e..0f0ba6a 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
@@ -1950,7 +1950,7 @@
 }
 
 bool BookmarkBarView::UpdateOtherAndManagedButtonsVisibility() {
-  bool has_other_children = !model_->other_node()->empty();
+  bool has_other_children = !model_->other_node()->children().empty();
   bool update_other =
       has_other_children != other_bookmarks_button_->GetVisible();
   if (update_other) {
@@ -1958,7 +1958,7 @@
     UpdateBookmarksSeparatorVisibility();
   }
 
-  bool show_managed = !managed_->managed_node()->empty() &&
+  bool show_managed = !managed_->managed_node()->children().empty() &&
                       browser_->profile()->GetPrefs()->GetBoolean(
                           bookmarks::prefs::kShowManagedBookmarksInBookmarkBar);
   bool update_managed = show_managed != managed_bookmarks_button_->GetVisible();
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_context_menu_unittest.cc b/chrome/browser/ui/views/bookmarks/bookmark_context_menu_unittest.cc
index a235485..40c05d7c 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_context_menu_unittest.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_context_menu_unittest.cc
@@ -374,7 +374,7 @@
   // Verify that there are no managed nodes yet.
   bookmarks::ManagedBookmarkService* managed =
       ManagedBookmarkServiceFactory::GetForProfile(profile_.get());
-  EXPECT_TRUE(managed->managed_node()->empty());
+  EXPECT_TRUE(managed->managed_node()->children().empty());
 
   // The context menu should not show the option to "Show managed bookmarks".
   EXPECT_FALSE(
@@ -393,9 +393,9 @@
   dict->SetString("url", "http://google.com");
   base::ListValue list;
   list.Append(std::move(dict));
-  EXPECT_TRUE(managed->managed_node()->empty());
+  EXPECT_TRUE(managed->managed_node()->children().empty());
   profile_->GetPrefs()->Set(bookmarks::prefs::kManagedBookmarks, list);
-  EXPECT_FALSE(managed->managed_node()->empty());
+  EXPECT_FALSE(managed->managed_node()->children().empty());
 
   // New context menus now show the "Show managed bookmarks" option.
   controller.reset(new BookmarkContextMenu(
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc
index d7839d3..2c9e362 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc
@@ -204,9 +204,9 @@
     if (node->value != 0) {
       const BookmarkNode* b_node =
           bookmarks::GetBookmarkNodeByID(bb_model_, node->value);
-      if (!b_node->empty() &&
+      if (!b_node->children().empty() &&
           !chrome::ConfirmDeleteBookmarkNode(b_node,
-            GetWidget()->GetNativeWindow())) {
+                                             GetWidget()->GetNativeWindow())) {
         // The folder is not empty and the user didn't confirm.
         return;
       }
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc b/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc
index 0817ed3..726ac4c5 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc
@@ -108,7 +108,7 @@
     bool show_forced_folders = show_options == SHOW_PERMANENT_FOLDERS &&
                                node == model->bookmark_bar_node();
     bool show_managed =
-        show_forced_folders && !managed->managed_node()->empty();
+        show_forced_folders && !managed->managed_node()->children().empty();
     bool has_children =
         (start_child_index < node->child_count()) || show_managed;
     if (has_children && parent->GetSubmenu() &&
@@ -535,7 +535,8 @@
 void BookmarkMenuDelegate::BuildMenu(const BookmarkNode* parent,
                                      int start_child_index,
                                      MenuItemView* menu) {
-  DCHECK(parent->empty() || start_child_index < parent->child_count());
+  DCHECK(parent->children().empty() ||
+         start_child_index < parent->child_count());
   ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
   const gfx::ImageSkia folder_icon =
       chrome::GetBookmarkFolderIcon(TextColorForMenu(menu, parent_));
diff --git a/chrome/browser/ui/webui/cookies_tree_model_util.cc b/chrome/browser/ui/webui/cookies_tree_model_util.cc
index d372f98..9c411e4 100644
--- a/chrome/browser/ui/webui/cookies_tree_model_util.cc
+++ b/chrome/browser/ui/webui/cookies_tree_model_util.cc
@@ -88,7 +88,7 @@
   // Use node's address as an id for WebUI to look it up.
   dict->SetString(kKeyId, GetTreeNodeId(&node));
   dict->SetString(kKeyTitle, node.GetTitle());
-  dict->SetBoolean(kKeyHasChildren, !node.empty());
+  dict->SetBoolean(kKeyHasChildren, !node.children().empty());
 
   switch (node.GetDetailedInfo().node_type) {
     case CookieTreeNode::DetailedInfo::TYPE_HOST: {
diff --git a/components/bookmarks/browser/bookmark_model.cc b/components/bookmarks/browser/bookmark_model.cc
index 74f7b0a..78a87c7 100644
--- a/components/bookmarks/browser/bookmark_model.cc
+++ b/components/bookmarks/browser/bookmark_model.cc
@@ -550,8 +550,8 @@
 }
 
 bool BookmarkModel::HasNoUserCreatedBookmarksOrFolders() {
-  return bookmark_bar_node_->empty() && other_node_->empty() &&
-         mobile_node_->empty();
+  return bookmark_bar_node_->children().empty() &&
+         other_node_->children().empty() && mobile_node_->children().empty();
 }
 
 bool BookmarkModel::IsBookmarked(const GURL& url) {
@@ -643,8 +643,7 @@
   if (U_FAILURE(error))
     collator.reset(nullptr);
   BookmarkNode* mutable_parent = AsMutable(parent);
-  std::sort(mutable_parent->children().begin(),
-            mutable_parent->children().end(),
+  std::sort(mutable_parent->children_.begin(), mutable_parent->children_.end(),
             SortComparator(collator.get()));
 
   if (store_)
@@ -675,11 +674,11 @@
     std::vector<std::unique_ptr<BookmarkNode>> new_children(
         ordered_nodes.size());
     BookmarkNode* mutable_parent = AsMutable(parent);
-    for (auto& child : mutable_parent->children()) {
+    for (auto& child : mutable_parent->children_) {
       size_t new_location = order[child.get()];
       new_children[new_location] = std::move(child);
     }
-    mutable_parent->children().swap(new_children);
+    mutable_parent->children_.swap(new_children);
 
     if (store_)
       store_->ScheduleSave();
@@ -806,7 +805,7 @@
   index_->SetNodeSorter(std::make_unique<TypedCountSorter>(client_.get()));
   // Sorting the permanent nodes has to happen on the main thread, so we do it
   // here, after loading completes.
-  std::stable_sort(root_->children().begin(), root_->children().end(),
+  std::stable_sort(root_->children_.begin(), root_->children_.end(),
                    VisibilityComparator(client_.get()));
 
   root_->SetMetaInfoMap(details->model_meta_info_map());
diff --git a/components/bookmarks/browser/bookmark_node.cc b/components/bookmarks/browser/bookmark_node.cc
index ddc6e04..3a9b99a 100644
--- a/components/bookmarks/browser/bookmark_node.cc
+++ b/components/bookmarks/browser/bookmark_node.cc
@@ -130,7 +130,7 @@
 BookmarkPermanentNode::~BookmarkPermanentNode() = default;
 
 bool BookmarkPermanentNode::IsVisible() const {
-  return visible_ || !empty();
+  return visible_ || !children().empty();
 }
 
 }  // namespace bookmarks
diff --git a/components/bookmarks/browser/bookmark_utils_unittest.cc b/components/bookmarks/browser/bookmark_utils_unittest.cc
index 218324e..d750236 100644
--- a/components/bookmarks/browser/bookmark_utils_unittest.cc
+++ b/components/bookmarks/browser/bookmark_utils_unittest.cc
@@ -580,10 +580,10 @@
 
   std::unique_ptr<BookmarkModel> model(
       TestBookmarkClient::CreateModelWithClient(std::move(client)));
-  EXPECT_TRUE(model->bookmark_bar_node()->empty());
-  EXPECT_TRUE(model->other_node()->empty());
-  EXPECT_TRUE(model->mobile_node()->empty());
-  EXPECT_TRUE(extra_node->empty());
+  EXPECT_TRUE(model->bookmark_bar_node()->children().empty());
+  EXPECT_TRUE(model->other_node()->children().empty());
+  EXPECT_TRUE(model->mobile_node()->children().empty());
+  EXPECT_TRUE(extra_node->children().empty());
 
   const base::string16 title = base::ASCIIToUTF16("Title");
   const GURL url("http://google.com");
@@ -601,9 +601,9 @@
   nodes.clear();
   model->GetNodesByURL(url, &nodes);
   ASSERT_EQ(1u, nodes.size());
-  EXPECT_TRUE(model->bookmark_bar_node()->empty());
-  EXPECT_TRUE(model->other_node()->empty());
-  EXPECT_TRUE(model->mobile_node()->empty());
+  EXPECT_TRUE(model->bookmark_bar_node()->children().empty());
+  EXPECT_TRUE(model->other_node()->children().empty());
+  EXPECT_TRUE(model->mobile_node()->children().empty());
   EXPECT_EQ(1, extra_node->child_count());
 }
 
diff --git a/components/bookmarks/managed/managed_bookmark_service.cc b/components/bookmarks/managed/managed_bookmark_service.cc
index 4a619b9..96f1db3 100644
--- a/components/bookmarks/managed/managed_bookmark_service.cc
+++ b/components/bookmarks/managed/managed_bookmark_service.cc
@@ -49,7 +49,7 @@
     node_->set_id(*next_node_id);
     *next_node_id = ManagedBookmarksTracker::LoadInitial(
         node_.get(), initial_bookmarks_.get(), node_->id() + 1);
-    node_->set_visible(!node_->empty());
+    node_->set_visible(!node_->children().empty());
     node_->SetTitle(l10n_util::GetStringUTF16(title_id_));
     return std::move(node_);
   }
diff --git a/components/bookmarks/managed/managed_bookmarks_tracker.cc b/components/bookmarks/managed/managed_bookmarks_tracker.cc
index 3a5ae17..e7202a4 100644
--- a/components/bookmarks/managed/managed_bookmarks_tracker.cc
+++ b/components/bookmarks/managed/managed_bookmarks_tracker.cc
@@ -112,7 +112,7 @@
   UpdateBookmarks(managed_node_, list);
 
   // The managed bookmarks folder isn't visible when that pref isn't present.
-  managed_node_->set_visible(!managed_node_->empty());
+  managed_node_->set_visible(!managed_node_->children().empty());
 }
 
 void ManagedBookmarksTracker::UpdateBookmarks(const BookmarkNode* folder,
diff --git a/components/bookmarks/managed/managed_bookmarks_tracker_unittest.cc b/components/bookmarks/managed/managed_bookmarks_tracker_unittest.cc
index 9751f6f..0b807e3 100644
--- a/components/bookmarks/managed/managed_bookmarks_tracker_unittest.cc
+++ b/components/bookmarks/managed/managed_bookmarks_tracker_unittest.cc
@@ -57,7 +57,7 @@
     BookmarkPermanentNode* managed_node = new BookmarkPermanentNode(100);
     ManagedBookmarksTracker::LoadInitial(
         managed_node, prefs_.GetList(prefs::kManagedBookmarks), 101);
-    managed_node->set_visible(!managed_node->empty());
+    managed_node->set_visible(!managed_node->children().empty());
     managed_node->SetTitle(l10n_util::GetStringUTF16(
         IDS_BOOKMARK_BAR_MANAGED_FOLDER_DEFAULT_NAME));
 
@@ -181,9 +181,9 @@
 
 TEST_F(ManagedBookmarksTrackerTest, Empty) {
   CreateModel();
-  EXPECT_TRUE(model_->bookmark_bar_node()->empty());
-  EXPECT_TRUE(model_->other_node()->empty());
-  EXPECT_TRUE(managed_node()->empty());
+  EXPECT_TRUE(model_->bookmark_bar_node()->children().empty());
+  EXPECT_TRUE(model_->other_node()->children().empty());
+  EXPECT_TRUE(managed_node()->children().empty());
   EXPECT_FALSE(managed_node()->IsVisible());
 }
 
@@ -191,9 +191,9 @@
   // Set a policy before loading the model.
   prefs_.SetManagedPref(prefs::kManagedBookmarks, CreateTestTree());
   CreateModel();
-  EXPECT_TRUE(model_->bookmark_bar_node()->empty());
-  EXPECT_TRUE(model_->other_node()->empty());
-  EXPECT_FALSE(managed_node()->empty());
+  EXPECT_TRUE(model_->bookmark_bar_node()->children().empty());
+  EXPECT_TRUE(model_->other_node()->children().empty());
+  EXPECT_FALSE(managed_node()->children().empty());
   EXPECT_TRUE(managed_node()->IsVisible());
 
   std::unique_ptr<base::DictionaryValue> expected(CreateExpectedTree());
@@ -207,9 +207,9 @@
   // Set a policy before loading the model.
   prefs_.SetManagedPref(prefs::kManagedBookmarks, CreateTestTree());
   CreateModel();
-  EXPECT_TRUE(model_->bookmark_bar_node()->empty());
-  EXPECT_TRUE(model_->other_node()->empty());
-  EXPECT_FALSE(managed_node()->empty());
+  EXPECT_TRUE(model_->bookmark_bar_node()->children().empty());
+  EXPECT_TRUE(model_->other_node()->children().empty());
+  EXPECT_FALSE(managed_node()->children().empty());
   EXPECT_TRUE(managed_node()->IsVisible());
 
   std::unique_ptr<base::DictionaryValue> expected(
@@ -293,7 +293,7 @@
   prefs_.RemoveManagedPref(prefs::kManagedBookmarks);
   Mock::VerifyAndClearExpectations(&observer_);
 
-  EXPECT_TRUE(managed_node()->empty());
+  EXPECT_TRUE(managed_node()->children().empty());
   EXPECT_FALSE(managed_node()->IsVisible());
 }
 
diff --git a/components/browser_sync/profile_sync_service_bookmark_unittest.cc b/components/browser_sync/profile_sync_service_bookmark_unittest.cc
index 1cf5fbf..cfe2311 100644
--- a/components/browser_sync/profile_sync_service_bookmark_unittest.cc
+++ b/components/browser_sync/profile_sync_service_bookmark_unittest.cc
@@ -667,7 +667,7 @@
       EXPECT_EQ(gnode.GetSuccessorId(), gnext.GetId());
       EXPECT_EQ(gnode.GetParentId(), gnext.GetParentId());
     }
-    if (!bnode->empty())
+    if (!bnode->children().empty())
       EXPECT_TRUE(gnode.GetFirstChildId());
   }
 
diff --git a/components/sync_bookmarks/bookmark_change_processor.cc b/components/sync_bookmarks/bookmark_change_processor.cc
index acb064f..35a73a07 100644
--- a/components/sync_bookmarks/bookmark_change_processor.cc
+++ b/components/sync_bookmarks/bookmark_change_processor.cc
@@ -611,7 +611,7 @@
 
     // Children of a deleted node should not be deleted; they may be
     // reparented by a later change record.  Move them to a temporary place.
-    if (!dst->empty()) {
+    if (!dst->children().empty()) {
       if (!foster_parent) {
         foster_parent = model->AddFolder(model->other_node(),
                                          model->other_node()->child_count(),
diff --git a/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc b/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc
index 76015ba..75e992e 100644
--- a/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc
+++ b/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc
@@ -210,7 +210,7 @@
 
   const bookmarks::BookmarkNode* bookmarkbar =
       bookmark_model()->bookmark_bar_node();
-  EXPECT_TRUE(bookmarkbar->empty());
+  EXPECT_TRUE(bookmarkbar->children().empty());
 
   processor()->OnUpdateReceived(CreateDummyModelTypeState(),
                                 std::move(updates));
diff --git a/ios/chrome/browser/bookmarks/bookmarks_utils.cc b/ios/chrome/browser/bookmarks/bookmarks_utils.cc
index 996e4a0..f3bb3f0 100644
--- a/ios/chrome/browser/bookmarks/bookmarks_utils.cc
+++ b/ios/chrome/browser/bookmarks/bookmarks_utils.cc
@@ -35,7 +35,7 @@
     if (!bookmark_model->client()->CanBeEditedByUser(
             bookmark_model->root_node()->GetChild(i)))
       continue;
-    if (!bookmark_model->root_node()->GetChild(i)->empty())
+    if (!bookmark_model->root_node()->GetChild(i)->children().empty())
       return false;
   }
 
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_home_mediator.mm b/ios/chrome/browser/ui/bookmarks/bookmark_home_mediator.mm
index 0d6ee537..1033b38 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmark_home_mediator.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmark_home_mediator.mm
@@ -162,7 +162,7 @@
   // Add "Bookmarks Bar" and "Other Bookmarks" only when they are not empty.
   const BookmarkNode* bookmarkBar =
       self.sharedState.bookmarkModel->bookmark_bar_node();
-  if (!bookmarkBar->empty()) {
+  if (!bookmarkBar->children().empty()) {
     BookmarkHomeNodeItem* barItem =
         [[BookmarkHomeNodeItem alloc] initWithType:BookmarkHomeItemTypeBookmark
                                       bookmarkNode:bookmarkBar];
@@ -173,7 +173,7 @@
 
   const BookmarkNode* otherBookmarks =
       self.sharedState.bookmarkModel->other_node();
-  if (!otherBookmarks->empty()) {
+  if (!otherBookmarks->children().empty()) {
     BookmarkHomeNodeItem* otherItem =
         [[BookmarkHomeNodeItem alloc] initWithType:BookmarkHomeItemTypeBookmark
                                       bookmarkNode:otherBookmarks];
@@ -450,7 +450,7 @@
 
 - (BOOL)hasBookmarksOrFolders {
   return self.sharedState.tableViewDisplayedRootNode &&
-         !self.sharedState.tableViewDisplayedRootNode->empty();
+         !self.sharedState.tableViewDisplayedRootNode->children().empty();
 }
 
 // Delete all items for the given |sectionIdentifier| section, or create it
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
index 99a59e7..eff5712 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
@@ -274,7 +274,8 @@
         bookmark_utils_ios::FindFolderById(self.bookmarks, nodeID);
     DCHECK(node);
     // if node is an empty permanent node, stop.
-    if (node->empty() && IsPrimaryPermanentNode(node, self.bookmarks)) {
+    if (node->children().empty() &&
+        IsPrimaryPermanentNode(node, self.bookmarks)) {
       break;
     }
 
@@ -1226,7 +1227,7 @@
     return [self
         hasItemsInSectionIdentifier:BookmarkHomeSectionIdentifierBookmarks];
   } else {
-    return !self.sharedState.tableViewDisplayedRootNode->empty();
+    return !self.sharedState.tableViewDisplayedRootNode->children().empty();
   }
 }
 
diff --git a/ui/base/models/tree_node_iterator.h b/ui/base/models/tree_node_iterator.h
index 7d53b2d..755a8a3 100644
--- a/ui/base/models/tree_node_iterator.h
+++ b/ui/base/models/tree_node_iterator.h
@@ -45,7 +45,7 @@
   }
 
   explicit TreeNodeIterator(NodeType* node) {
-    if (!node->empty())
+    if (!node->children().empty())
       positions_.push(Position<NodeType>(node, 0));
   }
 
diff --git a/ui/base/models/tree_node_model.h b/ui/base/models/tree_node_model.h
index 70b8ef1..7563111 100644
--- a/ui/base/models/tree_node_model.h
+++ b/ui/base/models/tree_node_model.h
@@ -17,6 +17,10 @@
 #include "base/strings/string16.h"
 #include "ui/base/models/tree_model.h"
 
+namespace bookmarks {
+class BookmarkModel;
+}
+
 namespace ui {
 
 // TreeNodeModel and TreeNodes provide an implementation of TreeModel around
@@ -72,6 +76,8 @@
 template <class NodeType>
 class TreeNode : public TreeModelNode {
  public:
+  using TreeNodes = std::vector<std::unique_ptr<NodeType>>;
+
   TreeNode() : parent_(nullptr) {}
 
   explicit TreeNode(const base::string16& title)
@@ -84,7 +90,7 @@
   NodeType* Add(std::unique_ptr<NodeType> node, int index) {
     DCHECK(node);
     DCHECK_GE(index, 0);
-    DCHECK_LE(index, child_count());
+    DCHECK_LE(size_t{index}, children_.size());
     DCHECK(!node->parent_);
     node->parent_ = static_cast<NodeType*>(this);
     NodeType* node_ptr = node.get();
@@ -94,7 +100,8 @@
 
   // Removes the node at the given index. Returns the removed node.
   std::unique_ptr<NodeType> Remove(int index) {
-    DCHECK(index >= 0 && index < child_count());
+    DCHECK_GE(index, 0);
+    DCHECK_LT(size_t{index}, children_.size());
     children_[index]->parent_ = nullptr;
     std::unique_ptr<NodeType> ptr = std::move(children_[index]);
     children_.erase(children_.begin() + index);
@@ -104,12 +111,9 @@
   // Removes the given node. Prefer to remove by index if you know it to avoid
   // the search for the node to remove.
   std::unique_ptr<NodeType> Remove(NodeType* node) {
-    auto i = std::find_if(children_.begin(), children_.end(),
-                          [node](const std::unique_ptr<NodeType>& ptr) {
-                            return ptr.get() == node;
-                          });
-    DCHECK(i != children_.end());
-    return Remove(i - children_.begin());
+    int i = GetIndexOf(node);
+    DCHECK_NE(-1, i);
+    return Remove(i);
   }
 
   // Removes all the children from this node.
@@ -122,11 +126,11 @@
   // Returns true if this is the root node.
   bool is_root() const { return parent_ == nullptr; }
 
-  // Returns the number of children.
-  int child_count() const { return static_cast<int>(children_.size()); }
+  const TreeNodes& children() const { return children_; }
 
-  // Returns true if this node has no children.
-  bool empty() const { return children_.empty(); }
+  // Returns the number of children.
+  // TODO(https://crbug.com/956419): Remove; use children().size().
+  int child_count() const { return static_cast<int>(children_.size()); }
 
   // Returns the number of all nodes in the subtree rooted at this node,
   // including this node.
@@ -138,9 +142,10 @@
   }
 
   // Returns the node at |index|.
+  // TODO(https://crbug.com/956419): Remove; use children()[index].
   const NodeType* GetChild(int index) const {
     DCHECK_GE(index, 0);
-    DCHECK_LT(index, child_count());
+    DCHECK_LT(size_t{index}, children_.size());
     return children_[index].get();
   }
   NodeType* GetChild(int index) {
@@ -174,10 +179,10 @@
     return parent_ ? parent_->HasAncestor(ancestor) : false;
   }
 
- protected:
-  std::vector<std::unique_ptr<NodeType>>& children() { return children_; }
-
  private:
+  // TODO(https://crbug.com/956314): Remove this.
+  friend class bookmarks::BookmarkModel;
+
   // Title displayed in the tree.
   base::string16 title_;
 
@@ -185,7 +190,7 @@
   NodeType* parent_;
 
   // This node's children.
-  typename std::vector<std::unique_ptr<NodeType>> children_;
+  TreeNodes children_;
 
   DISALLOW_COPY_AND_ASSIGN(TreeNode);
 };
@@ -280,7 +285,7 @@
 
   int GetChildCount(TreeModelNode* parent) override {
     DCHECK(parent);
-    return AsNode(parent)->child_count();
+    return int{AsNode(parent)->children().size()};
   }
 
   NodeType* GetChild(TreeModelNode* parent, int index) override {
diff --git a/ui/base/models/tree_node_model_unittest.cc b/ui/base/models/tree_node_model_unittest.cc
index b39d82b..2cf9fee 100644
--- a/ui/base/models/tree_node_model_unittest.cc
+++ b/ui/base/models/tree_node_model_unittest.cc
@@ -140,7 +140,7 @@
   root.DeleteAll();
 
   EXPECT_EQ(0, root.child_count());
-  EXPECT_TRUE(root.empty());
+  EXPECT_TRUE(root.children().empty());
 }
 
 // Verifies if GetIndexOf() returns the correct index for the specified node.