| Index: components/bookmarks/browser/bookmark_model_unittest.cc | 
| diff --git a/components/bookmarks/browser/bookmark_model_unittest.cc b/components/bookmarks/browser/bookmark_model_unittest.cc | 
| index ac22fbf35892ef6a175ebe61cd0e9a1b23f0eb38..a6ae03bebc081776b9d394dcde081e08d84bd3e9 100644 | 
| --- a/components/bookmarks/browser/bookmark_model_unittest.cc | 
| +++ b/components/bookmarks/browser/bookmark_model_unittest.cc | 
| @@ -18,6 +18,7 @@ | 
| #include "base/strings/utf_string_conversions.h" | 
| #include "base/time/time.h" | 
| #include "components/bookmarks/browser/bookmark_model_observer.h" | 
| +#include "components/bookmarks/browser/bookmark_undo_delegate.h" | 
| #include "components/bookmarks/browser/bookmark_utils.h" | 
| #include "components/bookmarks/test/bookmark_test_helpers.h" | 
| #include "components/bookmarks/test/test_bookmark_client.h" | 
| @@ -211,7 +212,8 @@ void VerifyNoDuplicateIDs(BookmarkModel* model) { | 
| } | 
|  | 
| class BookmarkModelTest : public testing::Test, | 
| -                          public BookmarkModelObserver { | 
| +                          public BookmarkModelObserver, | 
| +                          public BookmarkUndoDelegate { | 
| public: | 
| struct ObserverDetails { | 
| ObserverDetails() { | 
| @@ -245,6 +247,23 @@ class BookmarkModelTest : public testing::Test, | 
| int index2_; | 
| }; | 
|  | 
| +  struct NodeRemovalDetail { | 
| +    NodeRemovalDetail(const BookmarkNode* parent, | 
| +                      int index, | 
| +                      const BookmarkNode* node) | 
| +        : parent_node_id(parent->id()), index(index), node_id(node->id()) {} | 
| + | 
| +    bool operator==(const NodeRemovalDetail& other) const { | 
| +      return parent_node_id == other.parent_node_id && | 
| +             index == other.index && | 
| +             node_id == other.node_id; | 
| +    } | 
| + | 
| +    int64_t parent_node_id; | 
| +    int index; | 
| +    int64_t node_id; | 
| +  }; | 
| + | 
| BookmarkModelTest() : model_(client_.CreateModel()) { | 
| model_->AddObserver(this); | 
| ClearCounts(); | 
| @@ -278,6 +297,8 @@ class BookmarkModelTest : public testing::Test, | 
| ++before_remove_count_; | 
| } | 
|  | 
| +  void SetUndoProvider(BookmarkUndoProvider* provider) override {} | 
| + | 
| void BookmarkNodeRemoved(BookmarkModel* model, | 
| const BookmarkNode* parent, | 
| int old_index, | 
| @@ -332,12 +353,29 @@ class BookmarkModelTest : public testing::Test, | 
| ++before_remove_all_count_; | 
| } | 
|  | 
| +  void GroupedBookmarkChangesBeginning(BookmarkModel* model) override { | 
| +    ++grouped_changes_beginning_count_; | 
| +  } | 
| + | 
| +  void GroupedBookmarkChangesEnded(BookmarkModel* model) override { | 
| +    ++grouped_changes_ended_count_; | 
| +  } | 
| + | 
| +  void OnBookmarkNodeRemoved(BookmarkModel* model, | 
| +                             const BookmarkNode* parent, | 
| +                             int index, | 
| +                             scoped_ptr<BookmarkNode> node) override { | 
| +    node_removal_details_.push_back( | 
| +        NodeRemovalDetail(parent, index, node.get())); | 
| +  } | 
| + | 
| void ClearCounts() { | 
| added_count_ = moved_count_ = removed_count_ = changed_count_ = | 
| reordered_count_ = extensive_changes_beginning_count_ = | 
| extensive_changes_ended_count_ = all_bookmarks_removed_ = | 
| before_remove_count_ = before_change_count_ = before_reorder_count_ = | 
| -        before_remove_all_count_ = 0; | 
| +        before_remove_all_count_ = grouped_changes_beginning_count_ = | 
| +        grouped_changes_ended_count_ = 0; | 
| } | 
|  | 
| void AssertObserverCount(int added_count, | 
| @@ -368,6 +406,14 @@ class BookmarkModelTest : public testing::Test, | 
| EXPECT_EQ(extensive_changes_ended_count, extensive_changes_ended_count_); | 
| } | 
|  | 
| +  void AssertGroupedChangesObserverCount( | 
| +      int grouped_changes_beginning_count, | 
| +      int grouped_changes_ended_count) { | 
| +    EXPECT_EQ(grouped_changes_beginning_count, | 
| +              grouped_changes_beginning_count_); | 
| +    EXPECT_EQ(grouped_changes_ended_count, grouped_changes_ended_count_); | 
| +  } | 
| + | 
| int AllNodesRemovedObserverCount() const { return all_bookmarks_removed_; } | 
|  | 
| BookmarkPermanentNode* ReloadModelWithExtraNode() { | 
| @@ -391,6 +437,7 @@ class BookmarkModelTest : public testing::Test, | 
| TestBookmarkClient client_; | 
| scoped_ptr<BookmarkModel> model_; | 
| ObserverDetails observer_details_; | 
| +  std::vector<NodeRemovalDetail> node_removal_details_; | 
|  | 
| private: | 
| int added_count_; | 
| @@ -405,6 +452,8 @@ class BookmarkModelTest : public testing::Test, | 
| int before_change_count_; | 
| int before_reorder_count_; | 
| int before_remove_all_count_; | 
| +  int grouped_changes_beginning_count_; | 
| +  int grouped_changes_ended_count_; | 
|  | 
| DISALLOW_COPY_AND_ASSIGN(BookmarkModelTest); | 
| }; | 
| @@ -621,7 +670,8 @@ TEST_F(BookmarkModelTest, RemoveAllUserBookmarks) { | 
| // Add a url to bookmark bar. | 
| base::string16 title(ASCIIToUTF16("foo")); | 
| GURL url("http://foo.com"); | 
| -  model_->AddURL(bookmark_bar_node, 0, title, url); | 
| +  const BookmarkNode* url_node = | 
| +      model_->AddURL(bookmark_bar_node, 0, title, url); | 
|  | 
| // Add a folder with child URL. | 
| const BookmarkNode* folder = model_->AddFolder(bookmark_bar_node, 0, title); | 
| @@ -630,14 +680,29 @@ TEST_F(BookmarkModelTest, RemoveAllUserBookmarks) { | 
| AssertObserverCount(3, 0, 0, 0, 0, 0, 0, 0, 0); | 
| ClearCounts(); | 
|  | 
| +  int permanent_node_count = model_->root_node()->child_count(); | 
| + | 
| +  NodeRemovalDetail expected_node_removal_details[] = { | 
| +    NodeRemovalDetail(bookmark_bar_node, 1, url_node), | 
| +    NodeRemovalDetail(bookmark_bar_node, 0, folder), | 
| +  }; | 
| + | 
| +  model_->SetUndoDelegate(this); | 
| model_->RemoveAllUserBookmarks(); | 
|  | 
| EXPECT_EQ(0, bookmark_bar_node->child_count()); | 
| +  // No permanent node should be removed. | 
| +  EXPECT_EQ(permanent_node_count, model_->root_node()->child_count()); | 
| // No individual BookmarkNodeRemoved events are fired, so removed count | 
| // should be 0. | 
| AssertObserverCount(0, 0, 0, 0, 0, 0, 0, 0, 1); | 
| AssertExtensiveChangesObserverCount(1, 1); | 
| +  AssertGroupedChangesObserverCount(1, 1); | 
| +  EXPECT_EQ(1, AllNodesRemovedObserverCount()); | 
| EXPECT_EQ(1, AllNodesRemovedObserverCount()); | 
| +  ASSERT_EQ(2u, node_removal_details_.size()); | 
| +  EXPECT_EQ(expected_node_removal_details[0], node_removal_details_[0]); | 
| +  EXPECT_EQ(expected_node_removal_details[1], node_removal_details_[1]); | 
| } | 
|  | 
| TEST_F(BookmarkModelTest, SetTitle) { | 
|  |