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/memory/scoped_ptr.h"
8 #include "base/prefs/pref_service.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/values.h"
11 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/search_engines/template_url_service_factory.h"
14 #include "chrome/browser/ui/app_list/app_list_util.h"
15 #include "chrome/browser/ui/views/bookmarks/bookmark_bar_view_test_helper.h"
16 #include "chrome/common/pref_names.h"
17 #include "chrome/common/url_constants.h"
18 #include "chrome/test/base/browser_with_test_window_test.h"
19 #include "chrome/test/base/scoped_testing_local_state.h"
20 #include "chrome/test/base/testing_browser_process.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 "components/syncable_prefs/testing_pref_service_syncable.h"
27 #include "ui/views/controls/button/label_button.h"
28 #include "ui/views/controls/button/menu_button.h"
30 using bookmarks::BookmarkModel
;
31 using bookmarks::BookmarkNode
;
33 class BookmarkBarViewTest
: public BrowserWithTestWindowTest
{
35 BookmarkBarViewTest() {}
37 void SetUp() override
{
38 BrowserWithTestWindowTest::SetUp();
40 new ScopedTestingLocalState(TestingBrowserProcess::GetGlobal()));
43 void TearDown() override
{
45 bookmark_bar_view_
.reset();
47 BrowserWithTestWindowTest::TearDown();
51 // Returns a string containing the label of each of the *visible* buttons on
52 // the bookmark bar. Each label is separated by a space.
53 std::string
GetStringForVisibleButtons() {
55 for (int i
= 0; i
< test_helper_
->GetBookmarkButtonCount() &&
56 test_helper_
->GetBookmarkButton(i
)->visible();
61 base::UTF16ToASCII(test_helper_
->GetBookmarkButton(i
)->GetText());
66 // Continues sizing the bookmark bar until it has |count| buttons that are
68 // NOTE: if the model has more than |count| buttons this results in
69 // |count| + 1 buttons.
70 void SizeUntilButtonsVisible(int count
) {
71 const int start_width
= bookmark_bar_view_
->width();
72 const int height
= bookmark_bar_view_
->GetPreferredSize().height();
74 i
< 100 && (test_helper_
->GetBookmarkButtonCount() < count
||
75 !test_helper_
->GetBookmarkButton(count
- 1)->visible());
77 bookmark_bar_view_
->SetBounds(0, 0, start_width
+ i
* 10, height
);
78 bookmark_bar_view_
->Layout();
82 void WaitForBookmarkModelToLoad() {
83 bookmarks::test::WaitForBookmarkModelToLoad(
84 BookmarkModelFactory::GetForProfile(profile()));
87 // Adds nodes to the bookmark bar node from |string|. See
88 // bookmarks::test::AddNodesFromModelString() for details on |string|.
89 void AddNodesToBookmarkBarFromModelString(const std::string
& string
) {
90 BookmarkModel
* model
= BookmarkModelFactory::GetForProfile(profile());
91 bookmarks::test::AddNodesFromModelString(model
, model
->bookmark_bar_node(),
94 // Creates the BookmarkBarView and BookmarkBarViewTestHelper. Generally you'll
95 // want to use CreateBookmarkModelAndBookmarkBarView(), but use this if
96 // need to create the BookmarkBarView after the model has populated.
97 void CreateBookmarkBarView() {
98 bookmark_bar_view_
.reset(new BookmarkBarView(browser(), nullptr));
99 test_helper_
.reset(new BookmarkBarViewTestHelper(bookmark_bar_view_
.get()));
102 // Creates the model, blocking until it loads, then creates the
104 void CreateBookmarkModelAndBookmarkBarView() {
105 profile()->CreateBookmarkModel(true);
106 WaitForBookmarkModelToLoad();
107 CreateBookmarkBarView();
110 // BrowserWithTestWindowTest:
111 TestingProfile
* CreateProfile() override
{
112 TestingProfile
* profile
= BrowserWithTestWindowTest::CreateProfile();
113 // TemplateURLService is normally NULL during testing. Instant extended
114 // needs this service so set a custom factory function.
115 TemplateURLServiceFactory::GetInstance()->SetTestingFactory(
116 profile
, &BookmarkBarViewTest::CreateTemplateURLService
);
120 scoped_ptr
<BookmarkBarViewTestHelper
> test_helper_
;
121 scoped_ptr
<BookmarkBarView
> bookmark_bar_view_
;
124 static scoped_ptr
<KeyedService
> CreateTemplateURLService(
125 content::BrowserContext
* profile
) {
126 return make_scoped_ptr(new TemplateURLService(
127 static_cast<Profile
*>(profile
)->GetPrefs(),
128 make_scoped_ptr(new SearchTermsData
), NULL
,
129 scoped_ptr
<TemplateURLServiceClient
>(), NULL
, NULL
, base::Closure()));
132 scoped_ptr
<ScopedTestingLocalState
> local_state_
;
134 DISALLOW_COPY_AND_ASSIGN(BookmarkBarViewTest
);
137 // Verify that in instant extended mode the visibility of the apps shortcut
138 // button properly follows the pref value.
139 TEST_F(BookmarkBarViewTest
, AppsShortcutVisibility
) {
140 CreateBookmarkModelAndBookmarkBarView();
141 browser()->profile()->GetPrefs()->SetBoolean(
142 bookmarks::prefs::kShowAppsShortcutInBookmarkBar
, false);
143 EXPECT_FALSE(test_helper_
->apps_page_shortcut()->visible());
145 // Try to make the Apps shortcut visible. Its visibility depends on whether
146 // the app launcher is enabled.
147 browser()->profile()->GetPrefs()->SetBoolean(
148 bookmarks::prefs::kShowAppsShortcutInBookmarkBar
, true);
149 if (IsAppLauncherEnabled()) {
150 EXPECT_FALSE(test_helper_
->apps_page_shortcut()->visible());
152 EXPECT_TRUE(test_helper_
->apps_page_shortcut()->visible());
155 // Make sure we can also properly transition from true to false.
156 browser()->profile()->GetPrefs()->SetBoolean(
157 bookmarks::prefs::kShowAppsShortcutInBookmarkBar
, false);
158 EXPECT_FALSE(test_helper_
->apps_page_shortcut()->visible());
161 // Various assertions around visibility of the overflow_button.
162 TEST_F(BookmarkBarViewTest
, OverflowVisibility
) {
163 profile()->CreateBookmarkModel(true);
164 CreateBookmarkBarView();
165 EXPECT_FALSE(test_helper_
->overflow_button()->visible());
167 WaitForBookmarkModelToLoad();
168 AddNodesToBookmarkBarFromModelString("a b c d e f ");
169 EXPECT_TRUE(test_helper_
->overflow_button()->visible());
171 SizeUntilButtonsVisible(1);
172 EXPECT_EQ(2, test_helper_
->GetBookmarkButtonCount());
173 const int width_for_one
= bookmark_bar_view_
->bounds().width();
174 EXPECT_TRUE(test_helper_
->overflow_button()->visible());
176 // Go really big, which should force all buttons to be added.
177 bookmark_bar_view_
->SetBounds(
178 0, 0, 5000, bookmark_bar_view_
->bounds().height());
179 bookmark_bar_view_
->Layout();
180 EXPECT_EQ(6, test_helper_
->GetBookmarkButtonCount());
181 EXPECT_FALSE(test_helper_
->overflow_button()->visible());
183 bookmark_bar_view_
->SetBounds(
184 0, 0, width_for_one
, bookmark_bar_view_
->bounds().height());
185 bookmark_bar_view_
->Layout();
186 EXPECT_TRUE(test_helper_
->overflow_button()->visible());
189 // Verifies buttons get added correctly when BookmarkBarView is created after
190 // the model and the model has nodes.
191 TEST_F(BookmarkBarViewTest
, ButtonsDynamicallyAddedAfterModelHasNodes
) {
192 profile()->CreateBookmarkModel(true);
193 WaitForBookmarkModelToLoad();
194 EXPECT_TRUE(BookmarkModelFactory::GetForProfile(profile())->loaded());
195 AddNodesToBookmarkBarFromModelString("a b c d e f ");
196 CreateBookmarkBarView();
197 EXPECT_EQ(0, test_helper_
->GetBookmarkButtonCount());
199 SizeUntilButtonsVisible(1);
200 EXPECT_EQ(2, test_helper_
->GetBookmarkButtonCount());
202 // Go really big, which should force all buttons to be added.
203 bookmark_bar_view_
->SetBounds(
204 0, 0, 5000, bookmark_bar_view_
->bounds().height());
205 bookmark_bar_view_
->Layout();
206 EXPECT_EQ(6, test_helper_
->GetBookmarkButtonCount());
209 // Verifies buttons are added as the model and size change.
210 TEST_F(BookmarkBarViewTest
, ButtonsDynamicallyAdded
) {
211 CreateBookmarkModelAndBookmarkBarView();
212 EXPECT_TRUE(BookmarkModelFactory::GetForProfile(profile())->loaded());
213 AddNodesToBookmarkBarFromModelString("a b c d e f ");
214 EXPECT_EQ(0, test_helper_
->GetBookmarkButtonCount());
215 SizeUntilButtonsVisible(1);
216 EXPECT_EQ(2, test_helper_
->GetBookmarkButtonCount());
218 // Go really big, which should force all buttons to be added.
219 bookmark_bar_view_
->SetBounds(
220 0, 0, 5000, bookmark_bar_view_
->bounds().height());
221 bookmark_bar_view_
->Layout();
222 EXPECT_EQ(6, test_helper_
->GetBookmarkButtonCount());
225 TEST_F(BookmarkBarViewTest
, AddNodesWhenBarAlreadySized
) {
226 CreateBookmarkModelAndBookmarkBarView();
227 bookmark_bar_view_
->SetBounds(
228 0, 0, 5000, bookmark_bar_view_
->bounds().height());
229 AddNodesToBookmarkBarFromModelString("a b c d e f ");
230 bookmark_bar_view_
->Layout();
231 EXPECT_EQ("a b c d e f", GetStringForVisibleButtons());
234 // Various assertions for removing nodes.
235 TEST_F(BookmarkBarViewTest
, RemoveNode
) {
236 CreateBookmarkModelAndBookmarkBarView();
237 BookmarkModel
* model
= BookmarkModelFactory::GetForProfile(profile());
238 const BookmarkNode
* bookmark_bar_node
= model
->bookmark_bar_node();
239 AddNodesToBookmarkBarFromModelString("a b c d e f ");
240 EXPECT_EQ(0, test_helper_
->GetBookmarkButtonCount());
241 SizeUntilButtonsVisible(1);
242 EXPECT_EQ(2, test_helper_
->GetBookmarkButtonCount());
244 // Remove the 2nd node, should still only have 1 visible.
245 model
->Remove(bookmark_bar_node
->GetChild(1));
246 EXPECT_EQ("a", GetStringForVisibleButtons());
248 // Remove the first node, should force a new button (for the 'c' node).
249 model
->Remove(bookmark_bar_node
->GetChild(0));
250 ASSERT_EQ("c", GetStringForVisibleButtons());
253 // Assertions for moving a node on the bookmark bar.
254 TEST_F(BookmarkBarViewTest
, MoveNode
) {
255 CreateBookmarkModelAndBookmarkBarView();
256 BookmarkModel
* model
= BookmarkModelFactory::GetForProfile(profile());
257 const BookmarkNode
* bookmark_bar_node
= model
->bookmark_bar_node();
258 AddNodesToBookmarkBarFromModelString("a b c d e f ");
259 EXPECT_EQ(0, test_helper_
->GetBookmarkButtonCount());
261 // Move 'c' first resulting in 'c a b d e f'.
262 model
->Move(bookmark_bar_node
->GetChild(2), bookmark_bar_node
, 0);
263 EXPECT_EQ(0, test_helper_
->GetBookmarkButtonCount());
265 // Make enough room for 1 node.
266 SizeUntilButtonsVisible(1);
267 EXPECT_EQ("c", GetStringForVisibleButtons());
269 // Move 'f' first, resulting in 'f c a b d e'.
270 model
->Move(bookmark_bar_node
->GetChild(5), bookmark_bar_node
, 0);
271 SizeUntilButtonsVisible(2);
272 EXPECT_EQ("f c", GetStringForVisibleButtons());
274 // Move 'f' to the end, resulting in 'c a b d e f'.
275 model
->Move(bookmark_bar_node
->GetChild(0), bookmark_bar_node
, 6);
276 SizeUntilButtonsVisible(2);
277 EXPECT_EQ("c a", GetStringForVisibleButtons());
279 // Move 'c' after 'a', resulting in 'a c b d e f'.
280 model
->Move(bookmark_bar_node
->GetChild(0), bookmark_bar_node
, 2);
281 SizeUntilButtonsVisible(2);
282 EXPECT_EQ("a c", GetStringForVisibleButtons());
285 // Assertions for changing the title of a node.
286 TEST_F(BookmarkBarViewTest
, ChangeTitle
) {
287 CreateBookmarkModelAndBookmarkBarView();
288 BookmarkModel
* model
= BookmarkModelFactory::GetForProfile(profile());
289 const BookmarkNode
* bookmark_bar_node
= model
->bookmark_bar_node();
290 AddNodesToBookmarkBarFromModelString("a b c d e f ");
291 EXPECT_EQ(0, test_helper_
->GetBookmarkButtonCount());
293 model
->SetTitle(bookmark_bar_node
->GetChild(0), base::ASCIIToUTF16("a1"));
294 EXPECT_EQ(0, test_helper_
->GetBookmarkButtonCount());
296 // Make enough room for 1 node.
297 SizeUntilButtonsVisible(1);
298 EXPECT_EQ("a1", GetStringForVisibleButtons());
300 model
->SetTitle(bookmark_bar_node
->GetChild(1), base::ASCIIToUTF16("b1"));
301 EXPECT_EQ("a1", GetStringForVisibleButtons());
303 model
->SetTitle(bookmark_bar_node
->GetChild(5), base::ASCIIToUTF16("f1"));
304 EXPECT_EQ("a1", GetStringForVisibleButtons());
306 model
->SetTitle(bookmark_bar_node
->GetChild(3), base::ASCIIToUTF16("d1"));
308 // Make the second button visible, changes the title of the first to something
309 // really long and make sure the second button hides.
310 SizeUntilButtonsVisible(2);
311 EXPECT_EQ("a1 b1", GetStringForVisibleButtons());
312 model
->SetTitle(bookmark_bar_node
->GetChild(0),
313 base::ASCIIToUTF16("a_really_long_title"));
314 EXPECT_LE(1, test_helper_
->GetBookmarkButtonCount());
316 // Change the title back and make sure the 2nd button is visible again. Don't
317 // use GetStringForVisibleButtons() here as more buttons may have been
319 model
->SetTitle(bookmark_bar_node
->GetChild(0), base::ASCIIToUTF16("a1"));
320 ASSERT_LE(2, test_helper_
->GetBookmarkButtonCount());
321 EXPECT_TRUE(test_helper_
->GetBookmarkButton(0)->visible());
322 EXPECT_TRUE(test_helper_
->GetBookmarkButton(1)->visible());
324 bookmark_bar_view_
->SetBounds(
325 0, 0, 5000, bookmark_bar_view_
->bounds().height());
326 bookmark_bar_view_
->Layout();
327 EXPECT_EQ("a1 b1 c d1 e f1", GetStringForVisibleButtons());
330 #if !defined(OS_CHROMEOS)
331 // Verifies that the apps shortcut is shown or hidden following the policy
332 // value. This policy (and the apps shortcut) isn't present on ChromeOS.
333 TEST_F(BookmarkBarViewTest
, ManagedShowAppsShortcutInBookmarksBar
) {
334 CreateBookmarkModelAndBookmarkBarView();
335 // By default, the pref is not managed and the apps shortcut is shown.
336 syncable_prefs::TestingPrefServiceSyncable
* prefs
=
337 profile()->GetTestingPrefService();
338 EXPECT_FALSE(prefs
->IsManagedPreference(
339 bookmarks::prefs::kShowAppsShortcutInBookmarkBar
));
340 EXPECT_TRUE(test_helper_
->apps_page_shortcut()->visible());
342 // Hide the apps shortcut by policy, via the managed pref.
343 prefs
->SetManagedPref(bookmarks::prefs::kShowAppsShortcutInBookmarkBar
,
344 new base::FundamentalValue(false));
345 EXPECT_FALSE(test_helper_
->apps_page_shortcut()->visible());
347 // And try showing it via policy too.
348 prefs
->SetManagedPref(bookmarks::prefs::kShowAppsShortcutInBookmarkBar
,
349 new base::FundamentalValue(true));
350 EXPECT_TRUE(test_helper_
->apps_page_shortcut()->visible());