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_bar_view.h"
7 #include "base/prefs/pref_service.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "base/values.h"
10 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/search_engines/template_url_service_factory.h"
13 #include "chrome/browser/ui/app_list/app_list_util.h"
14 #include "chrome/browser/ui/views/bookmarks/bookmark_bar_view_test_helper.h"
15 #include "chrome/common/pref_names.h"
16 #include "chrome/common/url_constants.h"
17 #include "chrome/test/base/browser_with_test_window_test.h"
18 #include "chrome/test/base/scoped_testing_local_state.h"
19 #include "chrome/test/base/testing_browser_process.h"
20 #include "chrome/test/base/testing_pref_service_syncable.h"
21 #include "components/bookmarks/browser/bookmark_model.h"
22 #include "components/bookmarks/test/bookmark_test_helpers.h"
23 #include "components/search_engines/search_terms_data.h"
24 #include "components/search_engines/template_url_service.h"
25 #include "components/search_engines/template_url_service_client.h"
26 #include "ui/views/controls/button/label_button.h"
27 #include "ui/views/controls/button/menu_button.h"
29 using bookmarks::BookmarkNode
;
31 class BookmarkBarViewTest
: public BrowserWithTestWindowTest
{
33 BookmarkBarViewTest() {}
35 void SetUp() override
{
36 BrowserWithTestWindowTest::SetUp();
38 new ScopedTestingLocalState(TestingBrowserProcess::GetGlobal()));
41 void TearDown() override
{
43 bookmark_bar_view_
.reset();
45 BrowserWithTestWindowTest::TearDown();
49 // Returns a string containing the label of each of the *visible* buttons on
50 // the bookmark bar. Each label is separated by a space.
51 std::string
GetStringForVisibleButtons() {
53 for (int i
= 0; i
< test_helper_
->GetBookmarkButtonCount() &&
54 test_helper_
->GetBookmarkButton(i
)->visible();
59 base::UTF16ToASCII(test_helper_
->GetBookmarkButton(i
)->GetText());
64 // Continues sizing the bookmark bar until it has |count| buttons that are
66 // NOTE: if the model has more than |count| buttons this results in
67 // |count| + 1 buttons.
68 void SizeUntilButtonsVisible(int count
) {
69 const int start_width
= bookmark_bar_view_
->width();
70 const int height
= bookmark_bar_view_
->GetPreferredSize().height();
72 i
< 100 && (test_helper_
->GetBookmarkButtonCount() < count
||
73 !test_helper_
->GetBookmarkButton(count
- 1)->visible());
75 bookmark_bar_view_
->SetBounds(0, 0, start_width
+ i
* 10, height
);
76 bookmark_bar_view_
->Layout();
80 const BookmarkNode
* GetBookmarkBarNode() {
81 return BookmarkModelFactory::GetForProfile(profile())->bookmark_bar_node();
84 void WaitForBookmarkModelToLoad() {
85 bookmarks::test::WaitForBookmarkModelToLoad(
86 BookmarkModelFactory::GetForProfile(profile()));
89 // Adds nodes to the bookmark bar node from |string|. See
90 // bookmarks::test::AddNodesFromModelString() for details on |string|.
91 void AddNodesToBookmarkBarFromModelString(const std::string
& string
) {
92 bookmarks::test::AddNodesFromModelString(
93 BookmarkModelFactory::GetForProfile(profile()),
97 // Creates the BookmarkBarView and BookmarkBarViewTestHelper. Generally you'll
98 // want to use CreateBookmarkModelAndBookmarkBarView(), but use this if
99 // need to create the BookmarkBarView after the model has populated.
100 void CreateBookmarkBarView() {
101 bookmark_bar_view_
.reset(new BookmarkBarView(browser(), nullptr));
102 test_helper_
.reset(new BookmarkBarViewTestHelper(bookmark_bar_view_
.get()));
105 // Creates the model, blocking until it loads, then creates the
107 void CreateBookmarkModelAndBookmarkBarView() {
108 profile()->CreateBookmarkModel(true);
109 WaitForBookmarkModelToLoad();
110 CreateBookmarkBarView();
113 // BrowserWithTestWindowTest:
114 TestingProfile
* CreateProfile() override
{
115 TestingProfile
* profile
= BrowserWithTestWindowTest::CreateProfile();
116 // TemplateURLService is normally NULL during testing. Instant extended
117 // needs this service so set a custom factory function.
118 TemplateURLServiceFactory::GetInstance()->SetTestingFactory(
119 profile
, &BookmarkBarViewTest::CreateTemplateURLService
);
123 scoped_ptr
<BookmarkBarViewTestHelper
> test_helper_
;
124 scoped_ptr
<BookmarkBarView
> bookmark_bar_view_
;
127 static KeyedService
* CreateTemplateURLService(
128 content::BrowserContext
* profile
) {
129 return new TemplateURLService(
130 static_cast<Profile
*>(profile
)->GetPrefs(),
131 make_scoped_ptr(new SearchTermsData
), NULL
,
132 scoped_ptr
<TemplateURLServiceClient
>(), NULL
, NULL
, base::Closure());
135 scoped_ptr
<ScopedTestingLocalState
> local_state_
;
137 DISALLOW_COPY_AND_ASSIGN(BookmarkBarViewTest
);
140 // Verify that in instant extended mode the visibility of the apps shortcut
141 // button properly follows the pref value.
142 TEST_F(BookmarkBarViewTest
, AppsShortcutVisibility
) {
143 CreateBookmarkModelAndBookmarkBarView();
144 browser()->profile()->GetPrefs()->SetBoolean(
145 bookmarks::prefs::kShowAppsShortcutInBookmarkBar
, false);
146 EXPECT_FALSE(test_helper_
->apps_page_shortcut()->visible());
148 // Try to make the Apps shortcut visible. Its visibility depends on whether
149 // the app launcher is enabled.
150 browser()->profile()->GetPrefs()->SetBoolean(
151 bookmarks::prefs::kShowAppsShortcutInBookmarkBar
, true);
152 if (IsAppLauncherEnabled()) {
153 EXPECT_FALSE(test_helper_
->apps_page_shortcut()->visible());
155 EXPECT_TRUE(test_helper_
->apps_page_shortcut()->visible());
158 // Make sure we can also properly transition from true to false.
159 browser()->profile()->GetPrefs()->SetBoolean(
160 bookmarks::prefs::kShowAppsShortcutInBookmarkBar
, false);
161 EXPECT_FALSE(test_helper_
->apps_page_shortcut()->visible());
164 // Various assertions around visibilty of the overflow_button.
165 TEST_F(BookmarkBarViewTest
, OverflowVisibility
) {
166 profile()->CreateBookmarkModel(true);
167 CreateBookmarkBarView();
168 EXPECT_FALSE(test_helper_
->overflow_button()->visible());
170 WaitForBookmarkModelToLoad();
171 AddNodesToBookmarkBarFromModelString("a b c d e f ");
172 EXPECT_TRUE(test_helper_
->overflow_button()->visible());
174 SizeUntilButtonsVisible(1);
175 EXPECT_EQ(2, test_helper_
->GetBookmarkButtonCount());
176 const int width_for_one
= bookmark_bar_view_
->bounds().width();
177 EXPECT_TRUE(test_helper_
->overflow_button()->visible());
179 // Go really big, which should force all buttons to be added.
180 bookmark_bar_view_
->SetBounds(
181 0, 0, 5000, bookmark_bar_view_
->bounds().height());
182 bookmark_bar_view_
->Layout();
183 EXPECT_EQ(6, test_helper_
->GetBookmarkButtonCount());
184 EXPECT_FALSE(test_helper_
->overflow_button()->visible());
186 bookmark_bar_view_
->SetBounds(
187 0, 0, width_for_one
, bookmark_bar_view_
->bounds().height());
188 bookmark_bar_view_
->Layout();
189 EXPECT_TRUE(test_helper_
->overflow_button()->visible());
192 // Verifies buttons get added correctly when BookmarkBarView is created after
193 // the model and the model has nodes.
194 TEST_F(BookmarkBarViewTest
, ButtonsDynamicallyAddedAfterModelHasNodes
) {
195 profile()->CreateBookmarkModel(true);
196 WaitForBookmarkModelToLoad();
197 EXPECT_TRUE(BookmarkModelFactory::GetForProfile(profile())->loaded());
198 AddNodesToBookmarkBarFromModelString("a b c d e f ");
199 CreateBookmarkBarView();
200 EXPECT_EQ(0, test_helper_
->GetBookmarkButtonCount());
202 SizeUntilButtonsVisible(1);
203 EXPECT_EQ(2, test_helper_
->GetBookmarkButtonCount());
205 // Go really big, which should force all buttons to be added.
206 bookmark_bar_view_
->SetBounds(
207 0, 0, 5000, bookmark_bar_view_
->bounds().height());
208 bookmark_bar_view_
->Layout();
209 EXPECT_EQ(6, test_helper_
->GetBookmarkButtonCount());
212 // Verifies buttons are added as the model and size change.
213 TEST_F(BookmarkBarViewTest
, ButtonsDynamicallyAdded
) {
214 CreateBookmarkModelAndBookmarkBarView();
215 EXPECT_TRUE(BookmarkModelFactory::GetForProfile(profile())->loaded());
216 AddNodesToBookmarkBarFromModelString("a b c d e f ");
217 EXPECT_EQ(0, test_helper_
->GetBookmarkButtonCount());
218 SizeUntilButtonsVisible(1);
219 EXPECT_EQ(2, test_helper_
->GetBookmarkButtonCount());
221 // Go really big, which should force all buttons to be added.
222 bookmark_bar_view_
->SetBounds(
223 0, 0, 5000, bookmark_bar_view_
->bounds().height());
224 bookmark_bar_view_
->Layout();
225 EXPECT_EQ(6, test_helper_
->GetBookmarkButtonCount());
228 TEST_F(BookmarkBarViewTest
, AddNodesWhenBarAlreadySized
) {
229 CreateBookmarkModelAndBookmarkBarView();
230 bookmark_bar_view_
->SetBounds(
231 0, 0, 5000, bookmark_bar_view_
->bounds().height());
232 AddNodesToBookmarkBarFromModelString("a b c d e f ");
233 bookmark_bar_view_
->Layout();
234 EXPECT_EQ("a b c d e f", GetStringForVisibleButtons());
237 // Various assertions for removing nodes.
238 TEST_F(BookmarkBarViewTest
, RemoveNode
) {
239 CreateBookmarkModelAndBookmarkBarView();
240 const BookmarkNode
* bookmark_bar_node
=
241 BookmarkModelFactory::GetForProfile(profile())->bookmark_bar_node();
242 AddNodesToBookmarkBarFromModelString("a b c d e f ");
243 EXPECT_EQ(0, test_helper_
->GetBookmarkButtonCount());
244 SizeUntilButtonsVisible(1);
245 EXPECT_EQ(2, test_helper_
->GetBookmarkButtonCount());
247 // Remove the 2nd node, should still only have 1 visible.
248 BookmarkModelFactory::GetForProfile(profile())->Remove(bookmark_bar_node
, 1);
249 EXPECT_EQ("a", GetStringForVisibleButtons());
251 // Remove the first node, should force a new button (for the 'c' node).
252 BookmarkModelFactory::GetForProfile(profile())->Remove(bookmark_bar_node
, 0);
253 ASSERT_EQ("c", GetStringForVisibleButtons());
256 // Assertions for moving a node on the bookmark bar.
257 TEST_F(BookmarkBarViewTest
, MoveNode
) {
258 CreateBookmarkModelAndBookmarkBarView();
259 const BookmarkNode
* bookmark_bar_node
=
260 BookmarkModelFactory::GetForProfile(profile())->bookmark_bar_node();
261 AddNodesToBookmarkBarFromModelString("a b c d e f ");
262 EXPECT_EQ(0, test_helper_
->GetBookmarkButtonCount());
264 // Move 'c' first resulting in 'c a b d e f'.
265 BookmarkModelFactory::GetForProfile(profile())
266 ->Move(bookmark_bar_node
->GetChild(2), bookmark_bar_node
, 0);
267 EXPECT_EQ(0, test_helper_
->GetBookmarkButtonCount());
269 // Make enough room for 1 node.
270 SizeUntilButtonsVisible(1);
271 EXPECT_EQ("c", GetStringForVisibleButtons());
273 // Move 'f' first, resulting in 'f c a b d e'.
274 BookmarkModelFactory::GetForProfile(profile())
275 ->Move(bookmark_bar_node
->GetChild(5), bookmark_bar_node
, 0);
276 SizeUntilButtonsVisible(2);
277 EXPECT_EQ("f c", GetStringForVisibleButtons());
279 // Move 'f' to the end, resulting in 'c a b d e f'.
280 BookmarkModelFactory::GetForProfile(profile())
281 ->Move(bookmark_bar_node
->GetChild(0), bookmark_bar_node
, 6);
282 SizeUntilButtonsVisible(2);
283 EXPECT_EQ("c a", GetStringForVisibleButtons());
285 // Move 'c' after 'a', resulting in 'a c b d e f'.
286 BookmarkModelFactory::GetForProfile(profile())
287 ->Move(bookmark_bar_node
->GetChild(0), bookmark_bar_node
, 2);
288 SizeUntilButtonsVisible(2);
289 EXPECT_EQ("a c", GetStringForVisibleButtons());
292 // Assertions for changing the title of a node.
293 TEST_F(BookmarkBarViewTest
, ChangeTitle
) {
294 CreateBookmarkModelAndBookmarkBarView();
295 const BookmarkNode
* bookmark_bar_node
= GetBookmarkBarNode();
296 AddNodesToBookmarkBarFromModelString("a b c d e f ");
297 EXPECT_EQ(0, test_helper_
->GetBookmarkButtonCount());
299 BookmarkModelFactory::GetForProfile(profile())
300 ->SetTitle(bookmark_bar_node
->GetChild(0), base::ASCIIToUTF16("a1"));
301 EXPECT_EQ(0, test_helper_
->GetBookmarkButtonCount());
303 // Make enough room for 1 node.
304 SizeUntilButtonsVisible(1);
305 EXPECT_EQ("a1", GetStringForVisibleButtons());
307 BookmarkModelFactory::GetForProfile(profile())
308 ->SetTitle(bookmark_bar_node
->GetChild(1), base::ASCIIToUTF16("b1"));
309 EXPECT_EQ("a1", GetStringForVisibleButtons());
311 BookmarkModelFactory::GetForProfile(profile())
312 ->SetTitle(bookmark_bar_node
->GetChild(5), base::ASCIIToUTF16("f1"));
313 EXPECT_EQ("a1", GetStringForVisibleButtons());
315 BookmarkModelFactory::GetForProfile(profile())
316 ->SetTitle(bookmark_bar_node
->GetChild(3), base::ASCIIToUTF16("d1"));
318 // Make the second button visible, changes the title of the first to something
319 // really long and make sure the second button hides.
320 SizeUntilButtonsVisible(2);
321 EXPECT_EQ("a1 b1", GetStringForVisibleButtons());
322 BookmarkModelFactory::GetForProfile(profile())
323 ->SetTitle(bookmark_bar_node
->GetChild(0),
324 base::ASCIIToUTF16("a_really_long_title"));
325 EXPECT_LE(1, test_helper_
->GetBookmarkButtonCount());
327 // Change the title back and make sure the 2nd button is visible again. Don't
328 // use GetStringForVisibleButtons() here as more buttons may have been
330 BookmarkModelFactory::GetForProfile(profile())
331 ->SetTitle(bookmark_bar_node
->GetChild(0), base::ASCIIToUTF16("a1"));
332 ASSERT_LE(2, test_helper_
->GetBookmarkButtonCount());
333 EXPECT_TRUE(test_helper_
->GetBookmarkButton(0)->visible());
334 EXPECT_TRUE(test_helper_
->GetBookmarkButton(1)->visible());
336 bookmark_bar_view_
->SetBounds(
337 0, 0, 5000, bookmark_bar_view_
->bounds().height());
338 bookmark_bar_view_
->Layout();
339 EXPECT_EQ("a1 b1 c d1 e f1", GetStringForVisibleButtons());
342 #if !defined(OS_CHROMEOS)
343 // Verifies that the apps shortcut is shown or hidden following the policy
344 // value. This policy (and the apps shortcut) isn't present on ChromeOS.
345 TEST_F(BookmarkBarViewTest
, ManagedShowAppsShortcutInBookmarksBar
) {
346 CreateBookmarkModelAndBookmarkBarView();
347 // By default, the pref is not managed and the apps shortcut is shown.
348 TestingPrefServiceSyncable
* prefs
= profile()->GetTestingPrefService();
349 EXPECT_FALSE(prefs
->IsManagedPreference(
350 bookmarks::prefs::kShowAppsShortcutInBookmarkBar
));
351 EXPECT_TRUE(test_helper_
->apps_page_shortcut()->visible());
353 // Hide the apps shortcut by policy, via the managed pref.
354 prefs
->SetManagedPref(bookmarks::prefs::kShowAppsShortcutInBookmarkBar
,
355 new base::FundamentalValue(false));
356 EXPECT_FALSE(test_helper_
->apps_page_shortcut()->visible());
358 // And try showing it via policy too.
359 prefs
->SetManagedPref(bookmarks::prefs::kShowAppsShortcutInBookmarkBar
,
360 new base::FundamentalValue(true));
361 EXPECT_TRUE(test_helper_
->apps_page_shortcut()->visible());