Moves some utility functions out of bookmark model into
bookmark_utils. In addition I've converted to using
TreeNodeIterator. This doesn't contain any functionality changes.

BUG=4065
TEST=none

Review URL: http://codereview.chromium.org/13642

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@6589 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/autocomplete/history_contents_provider.cc b/chrome/browser/autocomplete/history_contents_provider.cc
index 9eef77c2..cc1598f 100644
--- a/chrome/browser/autocomplete/history_contents_provider.cc
+++ b/chrome/browser/autocomplete/history_contents_provider.cc
@@ -6,6 +6,7 @@
 
 #include "base/histogram.h"
 #include "base/string_util.h"
+#include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/history/query_parser.h"
 #include "chrome/browser/profile.h"
 #include "net/base/net_util.h"
@@ -272,9 +273,9 @@
                                  // empty.
 
   TimeTicks start_time = TimeTicks::Now();
-  std::vector<BookmarkModel::TitleMatch> matches;
-  bookmark_model->GetBookmarksMatchingText(input.text(), kMaxMatchCount,
-                                           &matches);
+  std::vector<bookmark_utils::TitleMatch> matches;
+  bookmark_utils::GetBookmarksMatchingText(bookmark_model, input.text(),
+                                           kMaxMatchCount, &matches);
   for (size_t i = 0; i < matches.size(); ++i)
     AddBookmarkTitleMatchToResults(matches[i]);
   UMA_HISTOGRAM_TIMES(L"Omnibox.QueryBookmarksTime",
@@ -282,7 +283,7 @@
 }
 
 void HistoryContentsProvider::AddBookmarkTitleMatchToResults(
-    const BookmarkModel::TitleMatch& match) {
+    const bookmark_utils::TitleMatch& match) {
   history::URLResult url_result(match.node->GetURL(), match.match_positions);
   url_result.set_title(match.node->GetTitle());
   results_.AppendURLBySwapping(&url_result);
diff --git a/chrome/browser/autocomplete/history_contents_provider.h b/chrome/browser/autocomplete/history_contents_provider.h
index 8c4f62cb..ea02ff2 100644
--- a/chrome/browser/autocomplete/history_contents_provider.h
+++ b/chrome/browser/autocomplete/history_contents_provider.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_AUTOCOMPLETE_HISTORY_CONTENTS_PROVIDER_H__
 
 #include "chrome/browser/autocomplete/autocomplete.h"
-#include "chrome/browser/bookmarks/bookmark_model.h"
+#include "chrome/browser/bookmarks/bookmark_utils.h"
 #include "chrome/browser/history/history.h"
 
 // HistoryContentsProvider is an AutocompleteProvider that provides results from
@@ -66,7 +66,7 @@
 
   // Converts a BookmarkModel::TitleMatch to a QueryResult and adds it to
   // results_.
-  void AddBookmarkTitleMatchToResults(const BookmarkModel::TitleMatch& match);
+  void AddBookmarkTitleMatchToResults(const bookmark_utils::TitleMatch& match);
 
   CancelableRequestConsumerT<int, 0> request_consumer_;
 
diff --git a/chrome/browser/bookmarks/bookmark_model.cc b/chrome/browser/bookmarks/bookmark_model.cc
index 7d8bccc..dd4b1fb 100644
--- a/chrome/browser/bookmarks/bookmark_model.cc
+++ b/chrome/browser/bookmarks/bookmark_model.cc
@@ -5,8 +5,8 @@
 #include "chrome/browser/bookmarks/bookmark_model.h"
 
 #include "base/gfx/png_decoder.h"
+#include "chrome/browser/bookmarks/bookmark_utils.h"
 #include "chrome/browser/bookmarks/bookmark_storage.h"
-#include "chrome/browser/history/query_parser.h"
 #include "chrome/browser/profile.h"
 #include "chrome/common/l10n_util.h"
 #include "chrome/common/scoped_vector.h"
@@ -15,19 +15,6 @@
 
 using base::Time;
 
-namespace {
-
-// Functions used for sorting.
-bool MoreRecentlyModified(BookmarkNode* n1, BookmarkNode* n2) {
-  return n1->date_group_modified() > n2->date_group_modified();
-}
-
-bool MoreRecentlyAdded(BookmarkNode* n1, BookmarkNode* n2) {
-  return n1->date_added() > n2->date_added();
-}
-
-}  // namespace
-
 // BookmarkNode ---------------------------------------------------------------
 
 namespace {
@@ -139,87 +126,11 @@
 }
 
 BookmarkNode* BookmarkModel::GetParentForNewNodes() {
-  std::vector<BookmarkNode*> nodes;
-
-  GetMostRecentlyModifiedGroupNodes(&root_, 1, &nodes);
+  std::vector<BookmarkNode*> nodes =
+      bookmark_utils::GetMostRecentlyModifiedGroups(this, 1);
   return nodes.empty() ? bookmark_bar_node_ : nodes[0];
 }
 
-std::vector<BookmarkNode*> BookmarkModel::GetMostRecentlyModifiedGroups(
-    size_t max_count) {
-  std::vector<BookmarkNode*> nodes;
-  GetMostRecentlyModifiedGroupNodes(&root_, max_count, &nodes);
-
-  if (nodes.size() < max_count) {
-    // Add the bookmark bar and other nodes if there is space.
-    if (find(nodes.begin(), nodes.end(), bookmark_bar_node_) == nodes.end())
-      nodes.push_back(bookmark_bar_node_);
-
-    if (nodes.size() < max_count &&
-        find(nodes.begin(), nodes.end(), other_node_) == nodes.end()) {
-      nodes.push_back(other_node_);
-    }
-  }
-  return nodes;
-}
-
-void BookmarkModel::GetMostRecentlyAddedEntries(
-    size_t count,
-    std::vector<BookmarkNode*>* nodes) {
-  AutoLock url_lock(url_lock_);
-  for (NodesOrderedByURLSet::iterator i = nodes_ordered_by_url_set_.begin();
-       i != nodes_ordered_by_url_set_.end(); ++i) {
-    std::vector<BookmarkNode*>::iterator insert_position =
-        std::upper_bound(nodes->begin(), nodes->end(), *i, &MoreRecentlyAdded);
-    if (nodes->size() < count || insert_position != nodes->end()) {
-      nodes->insert(insert_position, *i);
-      while (nodes->size() > count)
-        nodes->pop_back();
-    }
-  }
-}
-
-void BookmarkModel::GetBookmarksMatchingText(
-    const std::wstring& text,
-    size_t max_count,
-    std::vector<TitleMatch>* matches) {
-  QueryParser parser;
-  ScopedVector<QueryNode> query_nodes;
-  parser.ParseQuery(text, &query_nodes.get());
-  if (query_nodes.empty())
-    return;
-
-  AutoLock url_lock(url_lock_);
-  Snippet::MatchPositions match_position;
-  for (NodesOrderedByURLSet::iterator i = nodes_ordered_by_url_set_.begin();
-       i != nodes_ordered_by_url_set_.end(); ++i) {
-    if (parser.DoesQueryMatch((*i)->GetTitle(), query_nodes.get(),
-                              &match_position)) {
-      matches->push_back(TitleMatch());
-      matches->back().node = *i;
-      matches->back().match_positions.swap(match_position);
-      if (matches->size() == max_count)
-        break;
-    }
-  }
-}
-
-bool BookmarkModel::DoesBookmarkMatchText(const std::wstring& text,
-                                          BookmarkNode* node) {
-  if (!node->is_url())
-    return false;
-
-  QueryParser parser;
-  ScopedVector<QueryNode> query_nodes;
-  parser.ParseQuery(text, &query_nodes.get());
-  if (query_nodes.empty())
-    return false;
-
-  Snippet::MatchPositions match_position;
-  return parser.DoesQueryMatch(node->GetTitle(), query_nodes.get(),
-                               &match_position);
-}
-
 void BookmarkModel::Remove(BookmarkNode* parent, int index) {
   if (!loaded_ || !IsValidIndex(parent, index, false) || parent == &root_) {
     NOTREACHED();
@@ -302,7 +213,7 @@
   if (nodes.empty())
     return NULL;
 
-  std::sort(nodes.begin(), nodes.end(), &MoreRecentlyAdded);
+  std::sort(nodes.begin(), nodes.end(), &bookmark_utils::MoreRecentlyAdded);
   return nodes.front();
 }
 
@@ -704,33 +615,6 @@
   }
 }
 
-void BookmarkModel::GetMostRecentlyModifiedGroupNodes(
-    BookmarkNode* parent,
-    size_t count,
-    std::vector<BookmarkNode*>* nodes) {
-  if (parent != &root_ && parent->is_folder() &&
-      parent->date_group_modified() > Time()) {
-    if (count == 0) {
-      nodes->push_back(parent);
-    } else {
-      std::vector<BookmarkNode*>::iterator i =
-          std::upper_bound(nodes->begin(), nodes->end(), parent,
-                           &MoreRecentlyModified);
-      if (nodes->size() < count || i != nodes->end()) {
-        nodes->insert(i, parent);
-        while (nodes->size() > count)
-          nodes->pop_back();
-      }
-    }
-  }  // else case, the root node, which we don't care about or imported nodes
-     // (which have a time of 0).
-  for (int i = 0; i < parent->GetChildCount(); ++i) {
-    BookmarkNode* child = parent->GetChild(i);
-    if (child->is_folder())
-      GetMostRecentlyModifiedGroupNodes(child, count, nodes);
-  }
-}
-
 void BookmarkModel::Observe(NotificationType type,
                             const NotificationSource& source,
                             const NotificationDetails& details) {
diff --git a/chrome/browser/bookmarks/bookmark_model.h b/chrome/browser/bookmarks/bookmark_model.h
index 182d3cc..675405b 100644
--- a/chrome/browser/bookmarks/bookmark_model.h
+++ b/chrome/browser/bookmarks/bookmark_model.h
@@ -190,7 +190,7 @@
  public:
   explicit BookmarkModel(Profile* profile);
   virtual ~BookmarkModel();
-  
+
   // Loads the bookmarks. This is called by Profile upon creation of the
   // BookmarkModel. You need not invoke this directly.
   void Load();
@@ -209,34 +209,6 @@
   // (as long as the model is loaded).
   BookmarkNode* GetParentForNewNodes();
 
-  // Returns a vector containing up to |max_count| of the most recently
-  // modified groups. This never returns an empty vector.
-  std::vector<BookmarkNode*> GetMostRecentlyModifiedGroups(size_t max_count);
-
-  // Returns the most recently added bookmarks. This does not return groups,
-  // only nodes of type url.
-  void GetMostRecentlyAddedEntries(size_t count,
-                                   std::vector<BookmarkNode*>* nodes);
-
-  // Used by GetBookmarksMatchingText to return a matching node and the location
-  // of the match in the title.
-  struct TitleMatch {
-    BookmarkNode* node;
-
-    // Location of the matching words in the title of the node.
-    Snippet::MatchPositions match_positions;
-  };
-
-  // Returns the bookmarks whose title contains text. At most |max_count|
-  // matches are returned in |matches|.
-  void GetBookmarksMatchingText(const std::wstring& text,
-                                size_t max_count,
-                                std::vector<TitleMatch>* matches);
-
-  // Returns true if the specified bookmark's title matches the specified
-  // text.
-  bool DoesBookmarkMatchText(const std::wstring& text, BookmarkNode* node);
-
   void AddObserver(BookmarkModelObserver* observer) {
     observers_.AddObserver(observer);
   }
@@ -405,12 +377,6 @@
   // If we're waiting on a favicon for node, the load request is canceled.
   void CancelPendingFavIconLoadRequests(BookmarkNode* node);
 
-  // Returns up to count of the most recently modified groups. This may not
-  // add anything.
-  void GetMostRecentlyModifiedGroupNodes(BookmarkNode* parent,
-                                         size_t count,
-                                         std::vector<BookmarkNode*>* nodes);
-
   // NotificationObserver.
   virtual void Observe(NotificationType type,
                        const NotificationSource& source,
diff --git a/chrome/browser/bookmarks/bookmark_model_unittest.cc b/chrome/browser/bookmarks/bookmark_model_unittest.cc
index 2136347..a78dec6c 100644
--- a/chrome/browser/bookmarks/bookmark_model_unittest.cc
+++ b/chrome/browser/bookmarks/bookmark_model_unittest.cc
@@ -5,6 +5,7 @@
 #include "base/string_util.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_codec.h"
+#include "chrome/browser/bookmarks/bookmark_utils.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/notification_registrar.h"
@@ -303,14 +304,15 @@
 
   // Make sure group is in the most recently modified.
   std::vector<BookmarkNode*> most_recent_groups =
-      model.GetMostRecentlyModifiedGroups(1);
+      bookmark_utils::GetMostRecentlyModifiedGroups(&model, 1);
   ASSERT_EQ(1, most_recent_groups.size());
   ASSERT_EQ(group, most_recent_groups[0]);
 
   // Nuke the group and do another fetch, making sure group isn't in the
   // returned list.
   model.Remove(group->GetParent(), 0);
-  most_recent_groups = model.GetMostRecentlyModifiedGroups(1);
+  most_recent_groups =
+      bookmark_utils::GetMostRecentlyModifiedGroups(&model, 1);
   ASSERT_EQ(1, most_recent_groups.size());
   ASSERT_TRUE(most_recent_groups[0] != group);
 }
@@ -335,7 +337,7 @@
 
   // Make sure order is honored.
   std::vector<BookmarkNode*> recently_added;
-  model.GetMostRecentlyAddedEntries(2, &recently_added);
+  bookmark_utils::GetMostRecentlyAddedEntries(&model, 2, &recently_added);
   ASSERT_EQ(2, recently_added.size());
   ASSERT_TRUE(n1 == recently_added[0]);
   ASSERT_TRUE(n2 == recently_added[1]);
@@ -343,7 +345,7 @@
   // swap 1 and 2, then check again.
   recently_added.clear();
   std::swap(n1->date_added_, n2->date_added_);
-  model.GetMostRecentlyAddedEntries(4, &recently_added);
+  bookmark_utils::GetMostRecentlyAddedEntries(&model, 4, &recently_added);
   ASSERT_EQ(4, recently_added.size());
   ASSERT_TRUE(n2 == recently_added[0]);
   ASSERT_TRUE(n1 == recently_added[1]);
@@ -362,13 +364,13 @@
   model.AddGroup(model.GetBookmarkBarNode(), 2, L"blah");
 
   // Make sure we don't get back the folder.
-  std::vector<BookmarkModel::TitleMatch> results;
-  model.GetBookmarksMatchingText(L"blah", 2, &results);
+  std::vector<bookmark_utils::TitleMatch> results;
+  bookmark_utils::GetBookmarksMatchingText(&model, L"blah", 2, &results);
   ASSERT_EQ(1U, results.size());
   EXPECT_EQ(n1, results[0].node);
   results.clear();
 
-  model.GetBookmarksMatchingText(L"x", 2, &results);
+  bookmark_utils::GetBookmarksMatchingText(&model, L"x", 2, &results);
   ASSERT_EQ(1U, results.size());
   EXPECT_EQ(n2, results[0].node);
 }
diff --git a/chrome/browser/bookmarks/bookmark_table_model.cc b/chrome/browser/bookmarks/bookmark_table_model.cc
index a9122fa..234628d1 100644
--- a/chrome/browser/bookmarks/bookmark_table_model.cc
+++ b/chrome/browser/bookmarks/bookmark_table_model.cc
@@ -10,6 +10,7 @@
 #include "base/time.h"
 #include "base/time_format.h"
 #include "chrome/app/theme/theme_resources.h"
+#include "chrome/browser/bookmarks/bookmark_utils.h"
 #include "chrome/common/resource_bundle.h"
 #include "googleurl/src/gurl.h"
 
@@ -185,7 +186,9 @@
  private:
   void UpdateRecentlyBookmarked() {
     nodes().clear();
-    model()->GetMostRecentlyAddedEntries(kRecentlyBookmarkedCount, &nodes());
+    bookmark_utils::GetMostRecentlyAddedEntries(model(),
+                                                kRecentlyBookmarkedCount,
+                                                &nodes());
     if (observer())
       observer()->OnModelChanged();
   }
@@ -201,9 +204,9 @@
                            const std::wstring& search_text)
       : VectorBackedBookmarkTableModel(model),
         search_text_(search_text) {
-    std::vector<BookmarkModel::TitleMatch> matches;
-    model->GetBookmarksMatchingText(search_text,
-                                    std::numeric_limits<int>::max(), &matches);
+    std::vector<bookmark_utils::TitleMatch> matches;
+    bookmark_utils::GetBookmarksMatchingText(
+        model, search_text, std::numeric_limits<int>::max(), &matches);
     for (size_t i = 0; i < matches.size(); ++i)
       nodes().push_back(matches[i].node);
   }
@@ -212,7 +215,7 @@
                                  BookmarkNode* parent,
                                  int index) {
     BookmarkNode* node = parent->GetChild(index);
-    if (model->DoesBookmarkMatchText(search_text_, node)) {
+    if (bookmark_utils::DoesBookmarkMatchText(search_text_, node)) {
       nodes().push_back(node);
       if (observer())
         observer()->OnItemsAdded(static_cast<int>(nodes().size() - 1), 1);
diff --git a/chrome/browser/bookmarks/bookmark_utils.cc b/chrome/browser/bookmarks/bookmark_utils.cc
index 9e0b7c8..1a25556a 100644
--- a/chrome/browser/bookmarks/bookmark_utils.cc
+++ b/chrome/browser/bookmarks/bookmark_utils.cc
@@ -4,16 +4,19 @@
 
 #include "chrome/browser/bookmarks/bookmark_utils.h"
 
+#include "base/time.h"
 #include "chrome/browser/bookmarks/bookmark_drag_data.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/browser.h"
 #include "chrome/browser/browser_list.h"
+#include "chrome/browser/history/query_parser.h"
 #include "chrome/browser/page_navigator.h"
 #include "chrome/browser/tab_contents.h"
 #include "chrome/common/drag_drop_types.h"
 #include "chrome/common/l10n_util.h"
 #include "chrome/common/os_exchange_data.h"
 #include "chrome/views/event.h"
+#include "chrome/views/tree_node_iterator.h"
 
 #include "chromium_strings.h"
 #include "generated_resources.h"
@@ -138,6 +141,11 @@
                     MB_YESNO | MB_ICONWARNING | MB_TOPMOST) == IDYES;
 }
 
+// Comparison function that compares based on date modified of the two nodes.
+bool MoreRecentlyModified(BookmarkNode* n1, BookmarkNode* n2) {
+  return n1->date_group_modified() > n2->date_group_modified();
+}
+
 }  // namespace
 
 namespace bookmark_utils {
@@ -289,4 +297,110 @@
   return bookmark_data.Read(data_wrapper);
 }
 
+std::vector<BookmarkNode*> GetMostRecentlyModifiedGroups(
+    BookmarkModel* model,
+    size_t max_count) {
+  std::vector<BookmarkNode*> nodes;
+  views::TreeNodeIterator<BookmarkNode> iterator(model->root_node());
+  while (iterator.has_next()) {
+    BookmarkNode* parent = iterator.Next();
+    if (parent->is_folder() && parent->date_group_modified() > base::Time()) {
+      if (max_count == 0) {
+        nodes.push_back(parent);
+      } else {
+        std::vector<BookmarkNode*>::iterator i =
+            std::upper_bound(nodes.begin(), nodes.end(), parent,
+                             &MoreRecentlyModified);
+        if (nodes.size() < max_count || i != nodes.end()) {
+          nodes.insert(i, parent);
+          while (nodes.size() > max_count)
+            nodes.pop_back();
+        }
+      }
+    }  // else case, the root node, which we don't care about or imported nodes
+       // (which have a time of 0).
+  }
+
+  if (nodes.size() < max_count) {
+    // Add the bookmark bar and other nodes if there is space.
+    if (find(nodes.begin(), nodes.end(), model->GetBookmarkBarNode()) ==
+        nodes.end()) {
+      nodes.push_back(model->GetBookmarkBarNode());
+    }
+
+    if (nodes.size() < max_count &&
+        find(nodes.begin(), nodes.end(), model->other_node()) == nodes.end()) {
+      nodes.push_back(model->other_node());
+    }
+  }
+  return nodes;
+}
+
+void GetMostRecentlyAddedEntries(BookmarkModel* model,
+                                 size_t count,
+                                 std::vector<BookmarkNode*>* nodes) {
+  views::TreeNodeIterator<BookmarkNode> iterator(model->root_node());
+  while (iterator.has_next()) {
+    BookmarkNode* node = iterator.Next();
+    if (node->is_url()) {
+      std::vector<BookmarkNode*>::iterator insert_position =
+          std::upper_bound(nodes->begin(), nodes->end(), node,
+                           &MoreRecentlyAdded);
+      if (nodes->size() < count || insert_position != nodes->end()) {
+        nodes->insert(insert_position, node);
+        while (nodes->size() > count)
+          nodes->pop_back();
+      }
+    }
+  }
+}
+
+void GetBookmarksMatchingText(BookmarkModel* model,
+                              const std::wstring& text,
+                              size_t max_count,
+                              std::vector<TitleMatch>* matches) {
+  QueryParser parser;
+  ScopedVector<QueryNode> query_nodes;
+  parser.ParseQuery(text, &query_nodes.get());
+  if (query_nodes.empty())
+    return;
+
+  views::TreeNodeIterator<BookmarkNode> iterator(model->root_node());
+  Snippet::MatchPositions match_position;
+  while (iterator.has_next()) {
+    BookmarkNode* node = iterator.Next();
+    if (node->GetURL().spec() == "http://www.google.com/") {
+      DLOG(INFO) << "BLAH";
+    }
+    if (node->is_url() &&
+        parser.DoesQueryMatch(node->GetTitle(), query_nodes.get(),
+                              &match_position)) {
+      matches->push_back(TitleMatch());
+      matches->back().node = node;
+      matches->back().match_positions.swap(match_position);
+      if (matches->size() == max_count)
+        break;
+    }
+  }
+}
+
+bool DoesBookmarkMatchText(const std::wstring& text, BookmarkNode* node) {
+  if (!node->is_url())
+    return false;
+
+  QueryParser parser;
+  ScopedVector<QueryNode> query_nodes;
+  parser.ParseQuery(text, &query_nodes.get());
+  if (query_nodes.empty())
+    return false;
+
+  Snippet::MatchPositions match_position;
+  return parser.DoesQueryMatch(node->GetTitle(), query_nodes.get(),
+                               &match_position);
+}
+
+bool MoreRecentlyAdded(BookmarkNode* n1, BookmarkNode* n2) {
+  return n1->date_added() > n2->date_added();
+}
+
 }  // namespace bookmark_utils
diff --git a/chrome/browser/bookmarks/bookmark_utils.h b/chrome/browser/bookmarks/bookmark_utils.h
index 1d92e3e..9405919 100644
--- a/chrome/browser/bookmarks/bookmark_utils.h
+++ b/chrome/browser/bookmarks/bookmark_utils.h
@@ -8,8 +8,10 @@
 #include <vector>
 
 #include "chrome/browser/bookmarks/bookmark_drag_data.h"
+#include "chrome/browser/history/snippet.h"
 #include "webkit/glue/window_open_disposition.h"
 
+class BookmarkModel;
 class BookmarkNode;
 class PageNavigator;
 class Profile;
@@ -75,6 +77,40 @@
 // Returns true if the user can copy from the pasteboard.
 bool CanPasteFromClipboard(BookmarkNode* node);
 
+// Returns a vector containing up to |max_count| of the most recently modified
+// groups. This never returns an empty vector.
+std::vector<BookmarkNode*> GetMostRecentlyModifiedGroups(BookmarkModel* model,
+                                                         size_t max_count);
+
+// Returns the most recently added bookmarks. This does not return groups,
+// only nodes of type url.
+void GetMostRecentlyAddedEntries(BookmarkModel* model,
+                                 size_t count,
+                                 std::vector<BookmarkNode*>* nodes);
+
+// Used by GetBookmarksMatchingText to return a matching node and the location
+// of the match in the title.
+struct TitleMatch {
+  BookmarkNode* node;
+
+  // Location of the matching words in the title of the node.
+  Snippet::MatchPositions match_positions;
+};
+
+// Returns the bookmarks whose title contains text. At most |max_count|
+// matches are returned in |matches|.
+void GetBookmarksMatchingText(BookmarkModel* model,
+                              const std::wstring& text,
+                              size_t max_count,
+                              std::vector<TitleMatch>* matches);
+
+// Returns true if the specified bookmark's title matches the specified
+// text.
+bool DoesBookmarkMatchText(const std::wstring& text, BookmarkNode* node);
+
+// Returns true if |n1| was added more recently than |n2|.
+bool MoreRecentlyAdded(BookmarkNode* n1, BookmarkNode* n2);
+
 // Number of bookmarks we'll open before prompting the user to see if they
 // really want to open all.
 //
diff --git a/chrome/browser/dom_ui/new_tab_ui.cc b/chrome/browser/dom_ui/new_tab_ui.cc
index 7d1aa82d..f242e38 100644
--- a/chrome/browser/dom_ui/new_tab_ui.cc
+++ b/chrome/browser/dom_ui/new_tab_ui.cc
@@ -7,6 +7,7 @@
 #include "base/histogram.h"
 #include "base/string_piece.h"
 #include "chrome/app/locales/locale_settings.h"
+#include "chrome/browser/bookmarks/bookmark_utils.h"
 #include "chrome/browser/browser.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_resources.h"
@@ -490,7 +491,8 @@
 
 void RecentlyBookmarkedHandler::SendBookmarksToPage() {
   std::vector<BookmarkNode*> recently_bookmarked;
-  model_->GetMostRecentlyAddedEntries(kRecentBookmarks, &recently_bookmarked);
+  bookmark_utils::GetMostRecentlyAddedEntries(
+      model_, kRecentBookmarks, &recently_bookmarked);
   ListValue list_value;
   for (size_t i = 0; i < recently_bookmarked.size(); ++i) {
     BookmarkNode* node = recently_bookmarked[i];
diff --git a/chrome/browser/views/bookmark_bubble_view.cc b/chrome/browser/views/bookmark_bubble_view.cc
index a15e939..626fd803 100644
--- a/chrome/browser/views/bookmark_bubble_view.cc
+++ b/chrome/browser/views/bookmark_bubble_view.cc
@@ -7,6 +7,7 @@
 #include "chrome/app/chrome_dll_resource.h"
 #include "chrome/app/theme/theme_resources.h"
 #include "chrome/browser/bookmarks/bookmark_model.h"
+#include "chrome/browser/bookmarks/bookmark_utils.h"
 #include "chrome/browser/profile.h"
 #include "chrome/browser/user_metrics.h"
 #include "chrome/browser/views/bookmark_editor_view.h"
@@ -53,7 +54,8 @@
 BookmarkBubbleView::RecentlyUsedFoldersModel::RecentlyUsedFoldersModel(
     BookmarkModel* bb_model, BookmarkNode* node)
       // Use + 2 to account for bookmark bar and other node.
-    : nodes_(bb_model->GetMostRecentlyModifiedGroups(kMaxMRUFolders + 2)),
+      : nodes_(bookmark_utils::GetMostRecentlyModifiedGroups(
+            bb_model, kMaxMRUFolders + 2)),
       node_parent_index_(0) {
   // TODO(sky): bug 1173415 add a separator in the combobox here.