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