1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.h" 6 7#include "base/strings/utf_string_conversions.h" 8#include "chrome/browser/bookmarks/bookmark_model_factory.h" 9#include "chrome/browser/bookmarks/bookmark_stats.h" 10#include "chrome/browser/profiles/profile.h" 11#include "chrome/test/base/browser_with_test_window_test.h" 12#include "chrome/test/base/testing_profile.h" 13#include "components/bookmarks/browser/bookmark_model.h" 14#include "components/bookmarks/test/bookmark_test_helpers.h" 15#include "ui/views/controls/menu/menu_item_view.h" 16#include "ui/views/controls/menu/menu_runner.h" 17#include "ui/views/controls/menu/submenu_view.h" 18 19using base::ASCIIToUTF16; 20 21class BookmarkMenuDelegateTest : public BrowserWithTestWindowTest { 22 public: 23 BookmarkMenuDelegateTest() : model_(NULL) {} 24 25 virtual void SetUp() OVERRIDE { 26 BrowserWithTestWindowTest::SetUp(); 27 28 profile()->CreateBookmarkModel(true); 29 30 model_ = BookmarkModelFactory::GetForProfile(profile()); 31 test::WaitForBookmarkModelToLoad(model_); 32 33 AddTestData(); 34 } 35 36 virtual void TearDown() OVERRIDE { 37 if (bookmark_menu_delegate_.get()) { 38 // Since we never show the menu we need to pass the MenuItemView to 39 // MenuRunner so that the MenuItemView is destroyed. 40 views::MenuRunner menu_runner(bookmark_menu_delegate_->menu(), 0); 41 bookmark_menu_delegate_.reset(); 42 } 43 BrowserWithTestWindowTest::TearDown(); 44 } 45 46 protected: 47 void NewDelegate(int min_menu_id, int max_menu_id) { 48 // Destroy current menu if available, see comments in TearDown(). 49 if (bookmark_menu_delegate_.get()) 50 views::MenuRunner menu_runner(bookmark_menu_delegate_->menu(), 0); 51 52 bookmark_menu_delegate_.reset( 53 new BookmarkMenuDelegate(browser(), NULL, NULL, 54 min_menu_id, max_menu_id)); 55 } 56 57 void NewAndInitDelegateForPermanent(int min_menu_id, 58 int max_menu_id) { 59 const BookmarkNode* node = model_->bookmark_bar_node(); 60 NewDelegate(min_menu_id, max_menu_id); 61 bookmark_menu_delegate_->Init(&test_delegate_, NULL, node, 0, 62 BookmarkMenuDelegate::SHOW_PERMANENT_FOLDERS, 63 BOOKMARK_LAUNCH_LOCATION_NONE); 64 } 65 66 BookmarkModel* model_; 67 68 scoped_ptr<BookmarkMenuDelegate> bookmark_menu_delegate_; 69 70 private: 71 std::string base_path() const { return "file:///c:/tmp/"; } 72 73 // Creates the following structure: 74 // bookmark bar node 75 // a 76 // F1 77 // f1a 78 // F11 79 // f11a 80 // F2 81 // other node 82 // oa 83 // OF1 84 // of1a 85 void AddTestData() { 86 const BookmarkNode* bb_node = model_->bookmark_bar_node(); 87 std::string test_base = base_path(); 88 model_->AddURL(bb_node, 0, ASCIIToUTF16("a"), GURL(test_base + "a")); 89 const BookmarkNode* f1 = model_->AddFolder(bb_node, 1, ASCIIToUTF16("F1")); 90 model_->AddURL(f1, 0, ASCIIToUTF16("f1a"), GURL(test_base + "f1a")); 91 const BookmarkNode* f11 = model_->AddFolder(f1, 1, ASCIIToUTF16("F11")); 92 model_->AddURL(f11, 0, ASCIIToUTF16("f11a"), GURL(test_base + "f11a")); 93 model_->AddFolder(bb_node, 2, ASCIIToUTF16("F2")); 94 95 // Children of the other node. 96 model_->AddURL(model_->other_node(), 0, ASCIIToUTF16("oa"), 97 GURL(test_base + "oa")); 98 const BookmarkNode* of1 = 99 model_->AddFolder(model_->other_node(), 1, ASCIIToUTF16("OF1")); 100 model_->AddURL(of1, 0, ASCIIToUTF16("of1a"), GURL(test_base + "of1a")); 101 } 102 103 views::MenuDelegate test_delegate_; 104 105 DISALLOW_COPY_AND_ASSIGN(BookmarkMenuDelegateTest); 106}; 107 108// Verifies WillRemoveBookmarks() doesn't attempt to access MenuItemViews that 109// have since been deleted. 110TEST_F(BookmarkMenuDelegateTest, RemoveBookmarks) { 111 views::MenuDelegate test_delegate; 112 const BookmarkNode* node = model_->bookmark_bar_node()->GetChild(1); 113 NewDelegate(0, kint32max); 114 bookmark_menu_delegate_->Init(&test_delegate, NULL, node, 0, 115 BookmarkMenuDelegate::HIDE_PERMANENT_FOLDERS, 116 BOOKMARK_LAUNCH_LOCATION_NONE); 117 std::vector<const BookmarkNode*> nodes_to_remove; 118 nodes_to_remove.push_back(node->GetChild(1)); 119 bookmark_menu_delegate_->WillRemoveBookmarks(nodes_to_remove); 120 nodes_to_remove.clear(); 121 bookmark_menu_delegate_->DidRemoveBookmarks(); 122} 123 124// Verifies menu ID's of items in menu fall within the specified range. 125TEST_F(BookmarkMenuDelegateTest, MenuIdRange) { 126 // Start with maximum menu Id of 10 - the number of items that AddTestData() 127 // populated. Everything should be created. 128 NewAndInitDelegateForPermanent(0, 10); 129 views::MenuItemView* root_item = bookmark_menu_delegate_->menu(); 130 ASSERT_TRUE(root_item->HasSubmenu()); 131 EXPECT_EQ(4, root_item->GetSubmenu()->GetMenuItemCount()); 132 EXPECT_EQ(5, root_item->GetSubmenu()->child_count()); // Includes separator. 133 views::MenuItemView* F1_item = root_item->GetSubmenu()->GetMenuItemAt(1); 134 ASSERT_TRUE(F1_item->HasSubmenu()); 135 EXPECT_EQ(2, F1_item->GetSubmenu()->GetMenuItemCount()); 136 views::MenuItemView* F11_item = F1_item->GetSubmenu()->GetMenuItemAt(1); 137 ASSERT_TRUE(F11_item->HasSubmenu()); 138 EXPECT_EQ(1, F11_item->GetSubmenu()->GetMenuItemCount()); 139 views::MenuItemView* other_item = root_item->GetSubmenu()->GetMenuItemAt(3); 140 ASSERT_TRUE(other_item->HasSubmenu()); 141 EXPECT_EQ(2, other_item->GetSubmenu()->GetMenuItemCount()); 142 views::MenuItemView* OF1_item = other_item->GetSubmenu()->GetMenuItemAt(1); 143 ASSERT_TRUE(OF1_item->HasSubmenu()); 144 EXPECT_EQ(1, OF1_item->GetSubmenu()->GetMenuItemCount()); 145 146 // Reduce maximum 9. "of1a" item should not be created. 147 NewAndInitDelegateForPermanent(0, 9); 148 root_item = bookmark_menu_delegate_->menu(); 149 EXPECT_EQ(4, root_item->GetSubmenu()->GetMenuItemCount()); 150 EXPECT_EQ(5, root_item->GetSubmenu()->child_count()); // Includes separator. 151 other_item = root_item->GetSubmenu()->GetMenuItemAt(3); 152 OF1_item = other_item->GetSubmenu()->GetMenuItemAt(1); 153 EXPECT_EQ(0, OF1_item->GetSubmenu()->GetMenuItemCount()); 154 155 // Reduce maximum 8. "OF1" submenu should not be created. 156 NewAndInitDelegateForPermanent(0, 8); 157 root_item = bookmark_menu_delegate_->menu(); 158 EXPECT_EQ(4, root_item->GetSubmenu()->GetMenuItemCount()); 159 EXPECT_EQ(5, root_item->GetSubmenu()->child_count()); // Includes separator. 160 other_item = root_item->GetSubmenu()->GetMenuItemAt(3); 161 EXPECT_EQ(1, other_item->GetSubmenu()->GetMenuItemCount()); 162 163 // Reduce maximum 7. "Other" submenu should be empty. 164 NewAndInitDelegateForPermanent(0, 7); 165 root_item = bookmark_menu_delegate_->menu(); 166 EXPECT_EQ(4, root_item->GetSubmenu()->GetMenuItemCount()); 167 EXPECT_EQ(5, root_item->GetSubmenu()->child_count()); // Includes separator. 168 other_item = root_item->GetSubmenu()->GetMenuItemAt(3); 169 EXPECT_EQ(0, other_item->GetSubmenu()->GetMenuItemCount()); 170 171 // Reduce maximum to 6. "Other" submenu should not be created, and no 172 // separator. 173 NewAndInitDelegateForPermanent(0, 6); 174 root_item = bookmark_menu_delegate_->menu(); 175 EXPECT_EQ(3, root_item->GetSubmenu()->GetMenuItemCount()); 176 EXPECT_EQ(3, root_item->GetSubmenu()->child_count()); // No separator. 177 178 // Reduce maximum 5. "F2" and "Other" submenus shouldn't be created. 179 NewAndInitDelegateForPermanent(0, 5); 180 root_item = bookmark_menu_delegate_->menu(); 181 EXPECT_EQ(2, root_item->GetSubmenu()->GetMenuItemCount()); 182 EXPECT_EQ(2, root_item->GetSubmenu()->child_count()); // No separator. 183 F1_item = root_item->GetSubmenu()->GetMenuItemAt(1); 184 F11_item = F1_item->GetSubmenu()->GetMenuItemAt(1); 185 EXPECT_EQ(1, F11_item->GetSubmenu()->GetMenuItemCount()); 186 187 // Reduce maximum to 4. "f11a" item and "F2" and "Other" submenus should 188 // not be created. 189 NewAndInitDelegateForPermanent(0, 4); 190 root_item = bookmark_menu_delegate_->menu(); 191 EXPECT_EQ(2, root_item->GetSubmenu()->GetMenuItemCount()); 192 EXPECT_EQ(2, root_item->GetSubmenu()->child_count()); // No separator. 193 F1_item = root_item->GetSubmenu()->GetMenuItemAt(1); 194 F11_item = F1_item->GetSubmenu()->GetMenuItemAt(1); 195 EXPECT_EQ(0, F11_item->GetSubmenu()->GetMenuItemCount()); 196 197 // Reduce maximum to 3. "F11", "F2" and "Other" submenus should not be 198 // created. 199 NewAndInitDelegateForPermanent(0, 3); 200 root_item = bookmark_menu_delegate_->menu(); 201 EXPECT_EQ(2, root_item->GetSubmenu()->GetMenuItemCount()); 202 EXPECT_EQ(2, root_item->GetSubmenu()->child_count()); // No separator. 203 F1_item = root_item->GetSubmenu()->GetMenuItemAt(1); 204 EXPECT_EQ(views::MenuItemView::SUBMENU, F1_item->GetType()); 205 EXPECT_EQ(1, F1_item->GetSubmenu()->GetMenuItemCount()); 206 207 // Reduce maximum 2. Only "a" item and empty "F1" submenu should be created. 208 NewAndInitDelegateForPermanent(0, 2); 209 root_item = bookmark_menu_delegate_->menu(); 210 EXPECT_EQ(2, root_item->GetSubmenu()->GetMenuItemCount()); 211 EXPECT_EQ(2, root_item->GetSubmenu()->child_count()); // No separator. 212 F1_item = root_item->GetSubmenu()->GetMenuItemAt(1); 213 EXPECT_EQ(views::MenuItemView::SUBMENU, F1_item->GetType()); 214 EXPECT_EQ(0, F1_item->GetSubmenu()->GetMenuItemCount()); 215 216 // Reduce maximum to 1. Only "a" item should be created. 217 NewAndInitDelegateForPermanent(0, 1); 218 root_item = bookmark_menu_delegate_->menu(); 219 EXPECT_EQ(1, root_item->GetSubmenu()->GetMenuItemCount()); 220 EXPECT_EQ(1, root_item->GetSubmenu()->child_count()); // No separator. 221 222 // Verify correct handling of integer overflow with range, set kint32max as 223 // maximum and 1 less as minimum. Only "a" item should be created. 224 NewAndInitDelegateForPermanent(kint32max - 1, kint32max); 225 root_item = bookmark_menu_delegate_->menu(); 226 EXPECT_EQ(1, root_item->GetSubmenu()->GetMenuItemCount()); 227 EXPECT_EQ(1, root_item->GetSubmenu()->child_count()); // No separator. 228} 229