1 // Copyright (c) 2012 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_bar_view.h"
6 #include "base/bind.h"
7 #include "base/callback.h"
8 #include "base/compiler_specific.h"
9 #include "base/location.h"
10 #include "base/macros.h"
11 #include "base/run_loop.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/threading/thread_task_runner_handle.h"
16 #include "build/build_config.h"
17 #include "chrome/app/chrome_command_ids.h"
18 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
19 #include "chrome/browser/bookmarks/managed_bookmark_service_factory.h"
20 #include "chrome/browser/chrome_content_browser_client.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
23 #include "chrome/browser/ui/bookmarks/bookmark_utils_desktop.h"
24 #include "chrome/browser/ui/browser.h"
25 #include "chrome/browser/ui/browser_tabstrip.h"
26 #include "chrome/browser/ui/browser_window.h"
27 #include "chrome/browser/ui/tabs/tab_strip_model.h"
28 #include "chrome/browser/ui/views/bookmarks/bookmark_bar_view_observer.h"
29 #include "chrome/browser/ui/views/bookmarks/bookmark_context_menu.h"
30 #include "chrome/browser/ui/views/bookmarks/bookmark_menu_controller_views.h"
31 #include "chrome/browser/ui/views/chrome_constrained_window_views_client.h"
32 #include "chrome/browser/ui/views/chrome_layout_provider.h"
33 #include "chrome/browser/ui/views/test/view_event_test_base.h"
34 #include "chrome/common/chrome_content_client.h"
35 #include "chrome/test/base/interactive_test_utils.h"
36 #include "chrome/test/base/scoped_testing_local_state.h"
37 #include "chrome/test/base/test_browser_window.h"
38 #include "chrome/test/base/testing_browser_process.h"
39 #include "chrome/test/base/testing_profile.h"
40 #include "chrome/test/base/ui_test_utils.h"
41 #include "components/bookmarks/browser/bookmark_model.h"
42 #include "components/bookmarks/common/bookmark_pref_names.h"
43 #include "components/bookmarks/test/bookmark_test_helpers.h"
44 #include "components/constrained_window/constrained_window_views.h"
45 #include "components/prefs/pref_service.h"
46 #include "content/public/browser/page_navigator.h"
47 #include "ui/base/test/ui_controls.h"
48 #include "ui/events/keycodes/keyboard_codes.h"
49 #include "ui/views/background.h"
50 #include "ui/views/controls/button/menu_button.h"
51 #include "ui/views/controls/menu/menu_controller.h"
52 #include "ui/views/controls/menu/menu_item_view.h"
53 #include "ui/views/controls/menu/submenu_view.h"
54 #include "ui/views/layout/flex_layout.h"
55 #include "ui/views/layout/flex_layout_types.h"
56 #include "ui/views/layout/layout_provider.h"
57 #include "ui/views/view_class_properties.h"
58 #include "ui/views/widget/drop_helper.h"
59 #include "ui/views/widget/widget.h"
60
61 #if !defined(OS_MAC)
62 #include "ui/aura/env.h"
63 #include "ui/aura/env_observer.h"
64 #include "ui/aura/window.h"
65 #endif
66
67 #if defined(OS_WIN)
68 #include "base/win/windows_version.h"
69 #include "ui/aura/window_tree_host.h"
70 #endif
71
72 using base::ASCIIToUTF16;
73 using bookmarks::BookmarkModel;
74 using bookmarks::BookmarkNode;
75 using content::BrowserThread;
76 using content::OpenURLParams;
77 using content::PageNavigator;
78 using content::WebContents;
79
80 namespace {
81
82 #if !defined(OS_MAC)
83
84 // Waits for a views::Widget dialog to show up.
85 class DialogWaiter : public aura::EnvObserver,
86 public views::WidgetObserver {
87 public:
DialogWaiter()88 DialogWaiter() { aura::Env::GetInstance()->AddObserver(this); }
89
~DialogWaiter()90 ~DialogWaiter() override { aura::Env::GetInstance()->RemoveObserver(this); }
91
WaitForDialog()92 views::Widget* WaitForDialog() {
93 if (dialog_created_)
94 return dialog_;
95 base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
96 quit_closure_ = run_loop.QuitClosure();
97 run_loop.Run();
98 return dialog_;
99 }
100
101 private:
102 // aura::EnvObserver:
OnWindowInitialized(aura::Window * window)103 void OnWindowInitialized(aura::Window* window) override {
104 if (dialog_)
105 return;
106 views::Widget* widget = views::Widget::GetWidgetForNativeView(window);
107 if (!widget || !widget->IsDialogBox())
108 return;
109 dialog_ = widget;
110 dialog_->AddObserver(this);
111 }
112
113 // views::WidgetObserver:
OnWidgetActivationChanged(views::Widget * widget,bool active)114 void OnWidgetActivationChanged(views::Widget* widget, bool active) override {
115 CHECK_EQ(dialog_, widget);
116 if (active) {
117 dialog_created_ = true;
118 dialog_->RemoveObserver(this);
119 if (!quit_closure_.is_null())
120 quit_closure_.Run();
121 }
122 }
123
124 bool dialog_created_ = false;
125 views::Widget* dialog_ = nullptr;
126 base::Closure quit_closure_;
127
128 DISALLOW_COPY_AND_ASSIGN(DialogWaiter);
129 };
130
131 // Waits for a dialog to terminate.
132 class DialogCloseWaiter : public views::WidgetObserver {
133 public:
DialogCloseWaiter(views::Widget * dialog)134 explicit DialogCloseWaiter(views::Widget* dialog)
135 : dialog_closed_(false) {
136 dialog->AddObserver(this);
137 }
138
~DialogCloseWaiter()139 ~DialogCloseWaiter() override {
140 // It is not necessary to remove |this| from the dialog's observer, since
141 // the dialog is destroyed before this waiter.
142 }
143
WaitForDialogClose()144 void WaitForDialogClose() {
145 if (dialog_closed_)
146 return;
147 base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
148 quit_closure_ = run_loop.QuitClosure();
149 run_loop.Run();
150 }
151
152 private:
153 // views::WidgetObserver:
OnWidgetDestroyed(views::Widget * widget)154 void OnWidgetDestroyed(views::Widget* widget) override {
155 dialog_closed_ = true;
156 if (!quit_closure_.is_null())
157 quit_closure_.Run();
158 }
159
160 bool dialog_closed_;
161 base::Closure quit_closure_;
162
163 DISALLOW_COPY_AND_ASSIGN(DialogCloseWaiter);
164 };
165
166 // Waits for a views::Widget to receive a Tab key.
167 class TabKeyWaiter : public ui::EventHandler {
168 public:
TabKeyWaiter(views::Widget * widget)169 explicit TabKeyWaiter(views::Widget* widget)
170 : widget_(widget),
171 received_tab_(false) {
172 widget_->GetNativeWindow()->AddPreTargetHandler(this);
173 }
174
~TabKeyWaiter()175 ~TabKeyWaiter() override {
176 widget_->GetNativeWindow()->RemovePreTargetHandler(this);
177 }
178
WaitForTab()179 void WaitForTab() {
180 if (received_tab_)
181 return;
182 base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
183 quit_closure_ = run_loop.QuitClosure();
184 run_loop.Run();
185 }
186
187 private:
188 // ui::EventHandler:
OnKeyEvent(ui::KeyEvent * event)189 void OnKeyEvent(ui::KeyEvent* event) override {
190 if (event->type() == ui::ET_KEY_RELEASED &&
191 event->key_code() == ui::VKEY_TAB) {
192 received_tab_ = true;
193 if (!quit_closure_.is_null())
194 quit_closure_.Run();
195 }
196 }
197
198 views::Widget* widget_;
199 bool received_tab_;
200 base::Closure quit_closure_;
201
202 DISALLOW_COPY_AND_ASSIGN(TabKeyWaiter);
203 };
204
MoveMouseAndPress(const gfx::Point & screen_pos,ui_controls::MouseButton button,int button_state,base::OnceClosure closure)205 void MoveMouseAndPress(const gfx::Point& screen_pos,
206 ui_controls::MouseButton button,
207 int button_state,
208 base::OnceClosure closure) {
209 ASSERT_TRUE(ui_controls::SendMouseMove(screen_pos.x(), screen_pos.y()));
210 ASSERT_TRUE(ui_controls::SendMouseEventsNotifyWhenDone(button, button_state,
211 std::move(closure)));
212 }
213
214 #endif // !defined(OS_MAC)
215
216 // PageNavigator implementation that records the URL.
217 class TestingPageNavigator : public PageNavigator {
218 public:
TestingPageNavigator()219 TestingPageNavigator() {}
~TestingPageNavigator()220 ~TestingPageNavigator() override {}
221
OpenURL(const OpenURLParams & params)222 WebContents* OpenURL(const OpenURLParams& params) override {
223 urls_.push_back(params.url);
224 transitions_.push_back(params.transition);
225 return NULL;
226 }
227
urls() const228 const std::vector<GURL>& urls() const { return urls_; }
last_url() const229 GURL last_url() const { return urls_.empty() ? GURL() : urls_.back(); }
230
last_transition() const231 ui::PageTransition last_transition() const {
232 return transitions_.empty() ? ui::PAGE_TRANSITION_LINK
233 : transitions_.back();
234 }
235
236 private:
237 std::vector<GURL> urls_;
238 std::vector<ui::PageTransition> transitions_;
239
240 DISALLOW_COPY_AND_ASSIGN(TestingPageNavigator);
241 };
242
243 } // namespace
244
245 // Base class for event generating bookmark view tests. These test are intended
246 // to exercise View's menus, but that's easier done with BookmarkBarView rather
247 // than View's menu itself.
248 //
249 // SetUp creates a bookmark model with the following structure.
250 // All folders are in upper case, all URLs in lower case.
251 // F1
252 // f1a
253 // F11
254 // f11a
255 // f1b
256 // *
257 // a
258 // b
259 // c
260 // d
261 // F2
262 // e
263 // OTHER
264 // oa
265 // OF
266 // ofa
267 // ofb
268 // OF2
269 // of2a
270 // of2b
271 //
272 // * if CreateBigMenu returns return true, 100 menu items are created here with
273 // the names f1-f100.
274 //
275 // Subclasses should be sure and invoke super's implementation of SetUp and
276 // TearDown.
277 class BookmarkBarViewEventTestBase : public ViewEventTestBase {
278 public:
279 BookmarkBarViewEventTestBase() = default;
280 ~BookmarkBarViewEventTestBase() override = default;
281
SetUp()282 void SetUp() override {
283 content_client_ = std::make_unique<ChromeContentClient>();
284 content::SetContentClient(content_client_.get());
285 browser_content_client_ = std::make_unique<ChromeContentBrowserClient>();
286 content::SetBrowserClientForTesting(browser_content_client_.get());
287
288 views::MenuController::TurnOffMenuSelectionHoldForTest();
289 BookmarkBarView::DisableAnimationsForTesting(true);
290 SetConstrainedWindowViewsClient(CreateChromeConstrainedWindowViewsClient());
291
292 local_state_.reset(
293 new ScopedTestingLocalState(TestingBrowserProcess::GetGlobal()));
294 TestingProfile::Builder profile_builder;
295 profile_builder.AddTestingFactory(
296 BookmarkModelFactory::GetInstance(),
297 BookmarkModelFactory::GetDefaultFactory());
298 profile_builder.AddTestingFactory(
299 ManagedBookmarkServiceFactory::GetInstance(),
300 ManagedBookmarkServiceFactory::GetDefaultFactory());
301 profile_ = profile_builder.Build();
302 model_ = BookmarkModelFactory::GetForBrowserContext(profile_.get());
303 bookmarks::test::WaitForBookmarkModelToLoad(model_);
304 profile_->GetPrefs()->SetBoolean(bookmarks::prefs::kShowBookmarkBar, true);
305
306 Browser::CreateParams native_params(profile_.get(), true);
307 browser_ = CreateBrowserWithTestWindowForParams(native_params);
308
309 model_->ClearStore();
310
311 AddTestData(CreateBigMenu());
312
313 // Create the Widget. Note the initial size is given by
314 // GetPreferredSizeForContents() during initialization. This occurs after
315 // the WidgetDelegate provides |bb_view_| as the contents view and adds it
316 // to the hierarchy.
317 ViewEventTestBase::SetUp();
318 ASSERT_TRUE(bb_view_);
319
320 // Verify the layout triggered by the initial size preserves the overflow
321 // state calculated in GetPreferredSizeForContents().
322 EXPECT_TRUE(GetBookmarkButton(5)->GetVisible());
323 EXPECT_FALSE(GetBookmarkButton(6)->GetVisible());
324 }
325
TearDown()326 void TearDown() override {
327 if (window()) {
328 // Closing the window ensures |bb_view_| is deleted, which must happen
329 // before |model_| is deleted (which happens when |profile_| is reset).
330 window()->CloseNow();
331 }
332
333 browser_->tab_strip_model()->CloseAllTabs();
334 browser_.reset();
335 profile_.reset();
336
337 // Run the message loop to ensure we delete all tasks and fully shut down.
338 base::RunLoop().RunUntilIdle();
339
340 ViewEventTestBase::TearDown();
341
342 BookmarkBarView::DisableAnimationsForTesting(false);
343 constrained_window::SetConstrainedWindowViewsClient(nullptr);
344
345 browser_content_client_.reset();
346 content_client_.reset();
347 content::SetContentClient(NULL);
348 }
349
350 protected:
CreateContentsView()351 std::unique_ptr<views::View> CreateContentsView() override {
352 auto bb_view = std::make_unique<BookmarkBarView>(browser_.get(), nullptr);
353 // Real bookmark bars get a BookmarkBarViewBackground. Set an opaque
354 // background here just to avoid triggering subpixel rendering issues.
355 bb_view->SetBackground(views::CreateSolidBackground(SK_ColorWHITE));
356 bb_view->SetPageNavigator(&navigator_);
357 bb_view_ = bb_view.get();
358 return bb_view;
359 }
360
GetPreferredSizeForContents() const361 gfx::Size GetPreferredSizeForContents() const override {
362 // Calculate the preferred size so that one button doesn't fit, which
363 // triggers the overflow button to appear. We have to do this incrementally
364 // as there isn't a good way to determine the point at which the overflow
365 // button is shown.
366 //
367 // This code looks a bit hacky, but it is written so that it shouldn't
368 // depend on any of the layout code in BookmarkBarView, or extra buttons
369 // added to the right of the bookmarks. Instead, brute force search for a
370 // size that triggers the overflow button.
371 gfx::Size size = bb_view_->GetPreferredSize();
372 size.set_width(1000);
373 do {
374 size.set_width(size.width() - 25);
375 bb_view_->SetBounds(0, 0, size.width(), size.height());
376 bb_view_->Layout();
377 } while (bb_view_->bookmark_buttons_[6]->GetVisible());
378 return size;
379 }
380
GetBookmarkButton(size_t view_index)381 views::LabelButton* GetBookmarkButton(size_t view_index) {
382 return bb_view_->bookmark_buttons_[view_index];
383 }
384
385 // See comment above class description for what this does.
CreateBigMenu()386 virtual bool CreateBigMenu() { return false; }
387
388 BookmarkModel* model_ = nullptr;
389 BookmarkBarView* bb_view_ = nullptr;
390 TestingPageNavigator navigator_;
391
392 private:
AddTestData(bool big_menu)393 void AddTestData(bool big_menu) {
394 const BookmarkNode* bb_node = model_->bookmark_bar_node();
395 std::string test_base = "file:///c:/tmp/";
396 const BookmarkNode* f1 = model_->AddFolder(bb_node, 0, ASCIIToUTF16("F1"));
397 model_->AddURL(f1, 0, ASCIIToUTF16("f1a"), GURL(test_base + "f1a"));
398 const BookmarkNode* f11 = model_->AddFolder(f1, 1, ASCIIToUTF16("F11"));
399 model_->AddURL(f11, 0, ASCIIToUTF16("f11a"), GURL(test_base + "f11a"));
400 model_->AddURL(f1, 2, ASCIIToUTF16("f1b"), GURL(test_base + "f1b"));
401 if (big_menu) {
402 for (size_t i = 1; i <= 100; ++i) {
403 model_->AddURL(f1, i + 1, ASCIIToUTF16("f") + base::NumberToString16(i),
404 GURL(test_base + "f" + base::NumberToString(i)));
405 }
406 }
407 model_->AddURL(bb_node, 1, ASCIIToUTF16("a"), GURL(test_base + "a"));
408 model_->AddURL(bb_node, 2, ASCIIToUTF16("b"), GURL(test_base + "b"));
409 model_->AddURL(bb_node, 3, ASCIIToUTF16("c"), GURL(test_base + "c"));
410 model_->AddURL(bb_node, 4, ASCIIToUTF16("d"), GURL(test_base + "d"));
411 model_->AddFolder(bb_node, 5, ASCIIToUTF16("F2"));
412 model_->AddURL(bb_node, 6, ASCIIToUTF16("d"), GURL(test_base + "d"));
413
414 model_->AddURL(model_->other_node(), 0, ASCIIToUTF16("oa"),
415 GURL(test_base + "oa"));
416 const BookmarkNode* of = model_->AddFolder(model_->other_node(), 1,
417 ASCIIToUTF16("OF"));
418 model_->AddURL(of, 0, ASCIIToUTF16("ofa"), GURL(test_base + "ofa"));
419 model_->AddURL(of, 1, ASCIIToUTF16("ofb"), GURL(test_base + "ofb"));
420 const BookmarkNode* of2 = model_->AddFolder(model_->other_node(), 2,
421 ASCIIToUTF16("OF2"));
422 model_->AddURL(of2, 0, ASCIIToUTF16("of2a"), GURL(test_base + "of2a"));
423 model_->AddURL(of2, 1, ASCIIToUTF16("of2b"), GURL(test_base + "of2b"));
424 }
425
426 std::unique_ptr<ChromeContentClient> content_client_;
427 std::unique_ptr<ChromeContentBrowserClient> browser_content_client_;
428 std::unique_ptr<TestingProfile> profile_;
429 std::unique_ptr<Browser> browser_;
430 std::unique_ptr<ScopedTestingLocalState> local_state_;
431 };
432
433 class BookmarkBarViewDragTestBase : public BookmarkBarViewEventTestBase,
434 public BookmarkBarViewObserver,
435 public views::WidgetObserver {
436 public:
437 BookmarkBarViewDragTestBase() = default;
438 ~BookmarkBarViewDragTestBase() override = default;
439
440 // views::WidgetObserver:
OnWidgetDragWillStart(views::Widget * widget)441 void OnWidgetDragWillStart(views::Widget* widget) override {
442 const gfx::Point target = GetDragTargetInScreen();
443 GetDragTaskRunner()->PostTask(
444 FROM_HERE,
445 base::BindOnce(base::IgnoreResult(&ui_controls::SendMouseMove),
446 target.x(), target.y()));
447 }
448
OnWidgetDragComplete(views::Widget * widget)449 void OnWidgetDragComplete(views::Widget* widget) override {
450 // All drag tests drag node f1a, so at the end of the test, if the node was
451 // dropped where it was expected, the dropped node should have f1a's URL.
452 EXPECT_EQ(f1a_url_, GetDroppedNode()->url());
453
454 Done();
455 }
456
OnWidgetDestroying(views::Widget * widget)457 void OnWidgetDestroying(views::Widget* widget) override {
458 if (widget == window())
459 bookmark_bar_observer_.RemoveAll();
460 }
461
OnWidgetDestroyed(views::Widget * widget)462 void OnWidgetDestroyed(views::Widget* widget) override {
463 widget_observer_.Remove(widget);
464 }
465
466 protected:
467 // BookmarkBarViewEventTestBase:
DoTestOnMessageLoop()468 void DoTestOnMessageLoop() override {
469 widget_observer_.Add(window());
470 bookmark_bar_observer_.Add(bb_view_);
471
472 // Record the URL for node f1a.
473 const auto& f1 = model_->bookmark_bar_node()->children().front();
474 f1a_url_ = f1->children().front()->url();
475
476 // Move the mouse to the first folder on the bookmark bar and press the
477 // mouse.
478 views::LabelButton* button = GetBookmarkButton(0);
479 ui_test_utils::MoveMouseToCenterAndPress(
480 button, ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
481 CreateEventTask(this, &BookmarkBarViewDragTestBase::OnMenuOpened));
482 }
483
OnMenuOpened()484 virtual void OnMenuOpened() {
485 // Menu should be showing.
486 views::MenuItemView* menu = bb_view_->GetMenu();
487 ASSERT_NE(nullptr, menu);
488 views::SubmenuView* submenu = menu->GetSubmenu();
489 ASSERT_TRUE(submenu->IsShowing());
490
491 // The menu is showing, so it has a widget we can observe now.
492 widget_observer_.Add(submenu->GetWidget());
493
494 // Move mouse to center of node f1a and press button.
495 views::View* f1a = submenu->GetMenuItemAt(0);
496 ASSERT_NE(nullptr, f1a);
497 ui_test_utils::MoveMouseToCenterAndPress(
498 f1a, ui_controls::LEFT, ui_controls::DOWN,
499 CreateEventTask(this, &BookmarkBarViewDragTestBase::StartDrag));
500 }
501
OnDragEntered()502 virtual void OnDragEntered() {
503 // Drop the element, which should result in calling OnWidgetDragComplete().
504 GetDragTaskRunner()->PostTask(
505 FROM_HERE,
506 base::BindOnce(base::IgnoreResult(&ui_controls::SendMouseEvents),
507 ui_controls::LEFT, ui_controls::UP,
508 ui_controls::kNoAccelerator));
509 }
510
511 // Called after the drag ends; returns the node the test thinks should be the
512 // dropped node. This is used to verify that the dragged node was dropped in
513 // the expected position.
514 virtual const BookmarkNode* GetDroppedNode() const = 0;
515
516 // Returns the point the node should be dragged to, in screen coordinates.
517 virtual gfx::Point GetDragTargetInScreen() const = 0;
518
SetStopDraggingView(const views::View * view)519 void SetStopDraggingView(const views::View* view) {
520 views::DropHelper::SetDragEnteredCallbackForTesting(
521 view, base::BindRepeating(&BookmarkBarViewDragTestBase::OnDragEntered,
522 base::Unretained(this)));
523 }
524
525 private:
StartDrag()526 void StartDrag() {
527 const views::View* drag_view =
528 bb_view_->GetMenu()->GetSubmenu()->GetMenuItemAt(0);
529 const gfx::Point current_position =
530 ui_test_utils::GetCenterInScreenCoordinates(drag_view);
531 EXPECT_TRUE(ui_controls::SendMouseMove(current_position.x() + 10,
532 current_position.y()));
533 }
534
535 GURL f1a_url_;
536 ScopedObserver<BookmarkBarView, BookmarkBarViewObserver>
537 bookmark_bar_observer_{this};
538 ScopedObserver<views::Widget, views::WidgetObserver> widget_observer_{this};
539 };
540
541 #if !defined(OS_MAC)
542 // The following tests were not enabled on Mac before. Consider enabling those
543 // that are able to run on Mac (https://crbug.com/845342).
544
545 // Clicks on first menu, makes sure button is depressed. Moves mouse to first
546 // child, clicks it and makes sure a navigation occurs.
547 class BookmarkBarViewTest1 : public BookmarkBarViewEventTestBase {
548 protected:
DoTestOnMessageLoop()549 void DoTestOnMessageLoop() override {
550 // Move the mouse to the first folder on the bookmark bar and press the
551 // mouse.
552 views::LabelButton* button = GetBookmarkButton(0);
553 ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
554 ui_controls::DOWN | ui_controls::UP,
555 CreateEventTask(this, &BookmarkBarViewTest1::Step2));
556 }
557
558 private:
Step2()559 void Step2() {
560 // Menu should be showing.
561 views::MenuItemView* menu = bb_view_->GetMenu();
562 ASSERT_TRUE(menu != NULL);
563 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
564
565 // Button should be depressed.
566 views::LabelButton* button = GetBookmarkButton(0);
567 ASSERT_TRUE(button->GetState() == views::Button::STATE_PRESSED);
568
569 // Click on the 2nd menu item (A URL).
570 ASSERT_TRUE(menu->GetSubmenu());
571
572 views::MenuItemView* menu_to_select =
573 menu->GetSubmenu()->GetMenuItemAt(0);
574 ui_test_utils::MoveMouseToCenterAndPress(menu_to_select, ui_controls::LEFT,
575 ui_controls::DOWN | ui_controls::UP,
576 CreateEventTask(this, &BookmarkBarViewTest1::Step3));
577 }
578
Step3()579 void Step3() {
580 // We should have navigated to URL f1a.
581 const auto& f1 = model_->bookmark_bar_node()->children().front();
582 ASSERT_EQ(navigator_.last_url(), f1->children().front()->url());
583 ASSERT_FALSE(PageTransitionIsWebTriggerable(navigator_.last_transition()));
584
585 // Make sure button is no longer pushed.
586 views::LabelButton* button = GetBookmarkButton(0);
587 ASSERT_TRUE(button->GetState() == views::Button::STATE_NORMAL);
588
589 views::MenuItemView* menu = bb_view_->GetMenu();
590 ASSERT_TRUE(menu == NULL || !menu->GetSubmenu()->IsShowing());
591
592 Done();
593 }
594 };
595
596 VIEW_TEST(BookmarkBarViewTest1, Basic)
597
598 // Brings up menu, clicks on empty space and make sure menu hides.
599 class BookmarkBarViewTest2 : public BookmarkBarViewEventTestBase {
600 protected:
DoTestOnMessageLoop()601 void DoTestOnMessageLoop() override {
602 // Move the mouse to the first folder on the bookmark bar and press the
603 // mouse.
604 views::LabelButton* button = GetBookmarkButton(0);
605 ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
606 ui_controls::DOWN | ui_controls::UP,
607 CreateEventTask(this, &BookmarkBarViewTest2::Step2));
608 }
609
610 private:
Step2()611 void Step2() {
612 // Menu should be showing.
613 views::MenuItemView* menu = bb_view_->GetMenu();
614 ASSERT_TRUE(menu != NULL && menu->GetSubmenu()->IsShowing());
615
616 // Click on 0x0, which should trigger closing menu.
617 // NOTE: this code assume there is a left margin, which is currently
618 // true. If that changes, this code will need to find another empty space
619 // to press the mouse on.
620 ASSERT_TRUE(ui_controls::SendMouseMoveNotifyWhenDone(
621 0, 0, CreateEventTask(this, &BookmarkBarViewTest2::Step3)));
622 }
623
Step3()624 void Step3() {
625 // As the click is on the desktop the hook never sees the up, so we only
626 // wait on the down. We still send the up though else the system thinks
627 // the mouse is still down.
628 ASSERT_TRUE(ui_controls::SendMouseEventsNotifyWhenDone(
629 ui_controls::LEFT, ui_controls::DOWN,
630 CreateEventTask(this, &BookmarkBarViewTest2::Step4)));
631 ASSERT_TRUE(
632 ui_controls::SendMouseEvents(ui_controls::LEFT, ui_controls::UP));
633 }
634
Step4()635 void Step4() {
636 // The menu shouldn't be showing.
637 views::MenuItemView* menu = bb_view_->GetMenu();
638 ASSERT_TRUE(menu == NULL || !menu->GetSubmenu()->IsShowing());
639
640 // Make sure button is no longer pushed.
641 views::LabelButton* button = GetBookmarkButton(0);
642 ASSERT_TRUE(button->GetState() == views::Button::STATE_NORMAL);
643
644 Done();
645 }
646 };
647
648 VIEW_TEST(BookmarkBarViewTest2, HideOnDesktopClick)
649
650 // Brings up menu. Moves over child to make sure submenu appears, moves over
651 // another child and make sure next menu appears.
652 class BookmarkBarViewTest3 : public BookmarkBarViewEventTestBase {
653 protected:
DoTestOnMessageLoop()654 void DoTestOnMessageLoop() override {
655 // Move the mouse to the first folder on the bookmark bar and press the
656 // mouse.
657 views::MenuButton* button = bb_view_->other_bookmarks_button();
658 ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
659 ui_controls::DOWN | ui_controls::UP,
660 CreateEventTask(this, &BookmarkBarViewTest3::Step2));
661 }
662
663 private:
Step2()664 void Step2() {
665 // Menu should be showing.
666 views::MenuItemView* menu = bb_view_->GetMenu();
667 ASSERT_TRUE(menu != NULL);
668 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
669
670 views::MenuItemView* child_menu =
671 menu->GetSubmenu()->GetMenuItemAt(1);
672 ASSERT_TRUE(child_menu != NULL);
673
674 // Click on second child, which has a submenu.
675 ui_test_utils::MoveMouseToCenterAndPress(child_menu, ui_controls::LEFT,
676 ui_controls::DOWN | ui_controls::UP,
677 CreateEventTask(this, &BookmarkBarViewTest3::Step3));
678 }
679
Step3()680 void Step3() {
681 // Make sure sub menu is showing.
682 views::MenuItemView* menu = bb_view_->GetMenu();
683 ASSERT_TRUE(menu);
684 views::MenuItemView* child_menu =
685 menu->GetSubmenu()->GetMenuItemAt(1);
686 ASSERT_TRUE(child_menu->GetSubmenu() != NULL);
687 ASSERT_TRUE(child_menu->GetSubmenu()->IsShowing());
688
689 // Click on third child, which has a submenu too.
690 child_menu = menu->GetSubmenu()->GetMenuItemAt(2);
691 ASSERT_TRUE(child_menu != NULL);
692 ui_test_utils::MoveMouseToCenterAndPress(child_menu, ui_controls::LEFT,
693 ui_controls::DOWN | ui_controls::UP,
694 CreateEventTask(this, &BookmarkBarViewTest3::Step4));
695 }
696
Step4()697 void Step4() {
698 // Make sure sub menu we first clicked isn't showing.
699 views::MenuItemView* menu = bb_view_->GetMenu();
700 views::MenuItemView* child_menu =
701 menu->GetSubmenu()->GetMenuItemAt(1);
702 ASSERT_TRUE(child_menu->GetSubmenu() != NULL);
703 ASSERT_FALSE(child_menu->GetSubmenu()->IsShowing());
704
705 // And submenu we last clicked is showing.
706 child_menu = menu->GetSubmenu()->GetMenuItemAt(2);
707 ASSERT_TRUE(child_menu != NULL);
708 ASSERT_TRUE(child_menu->GetSubmenu()->IsShowing());
709
710 // Nothing should have been selected.
711 EXPECT_EQ(GURL(), navigator_.last_url());
712
713 // Hide menu.
714 menu->GetMenuController()->Cancel(views::MenuController::ExitType::kAll);
715
716 Done();
717 }
718 };
719
720 VIEW_TEST(BookmarkBarViewTest3, Submenus)
721
722 // Observer that posts a task upon the context menu creation.
723 // This is necessary for Linux as the context menu has to check the clipboard,
724 // which invokes the event loop.
725 // Because |task| is a OnceClosure, callers should use a separate observer
726 // instance for each successive context menu creation they wish to observe.
727 class BookmarkContextMenuNotificationObserver {
728 public:
BookmarkContextMenuNotificationObserver(base::OnceClosure task)729 explicit BookmarkContextMenuNotificationObserver(base::OnceClosure task)
730 : task_(std::move(task)) {
731 BookmarkContextMenu::InstallPreRunCallback(base::BindOnce(
732 &BookmarkContextMenuNotificationObserver::ScheduleCallback,
733 base::Unretained(this)));
734 }
735
ScheduleCallback()736 void ScheduleCallback() {
737 DCHECK(!task_.is_null());
738 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(task_));
739 }
740
741 private:
742 base::OnceClosure task_;
743
744 DISALLOW_COPY_AND_ASSIGN(BookmarkContextMenuNotificationObserver);
745 };
746
747 // Tests context menus by way of opening a context menu for a bookmark,
748 // then right clicking to get context menu and selecting the first menu item
749 // (open).
750 class BookmarkBarViewTest4 : public BookmarkBarViewEventTestBase {
751 public:
BookmarkBarViewTest4()752 BookmarkBarViewTest4()
753 : observer_(CreateEventTask(this, &BookmarkBarViewTest4::Step3)) {
754 }
755
756 protected:
DoTestOnMessageLoop()757 void DoTestOnMessageLoop() override {
758 // Move the mouse to the first folder on the bookmark bar and press the
759 // mouse.
760 views::LabelButton* button = bb_view_->other_bookmarks_button();
761 ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
762 ui_controls::DOWN | ui_controls::UP,
763 CreateEventTask(this, &BookmarkBarViewTest4::Step2));
764 }
765
766 private:
Step2()767 void Step2() {
768 // Menu should be showing.
769 views::MenuItemView* menu = bb_view_->GetMenu();
770 ASSERT_TRUE(menu != NULL);
771 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
772
773 views::MenuItemView* child_menu =
774 menu->GetSubmenu()->GetMenuItemAt(0);
775 ASSERT_TRUE(child_menu != NULL);
776
777 // Right click on the first child to get its context menu.
778 ui_test_utils::MoveMouseToCenterAndPress(
779 child_menu, ui_controls::RIGHT, ui_controls::DOWN | ui_controls::UP,
780 base::OnceClosure());
781 // Step3 will be invoked by BookmarkContextMenuNotificationObserver.
782 }
783
Step3()784 void Step3() {
785 // Make sure the context menu is showing.
786 views::MenuItemView* menu = bb_view_->GetContextMenu();
787 ASSERT_TRUE(menu != NULL);
788 ASSERT_TRUE(menu->GetSubmenu());
789 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
790
791 // Select the first menu item (open).
792 ui_test_utils::MoveMouseToCenterAndPress(
793 menu->GetSubmenu()->GetMenuItemAt(0),
794 ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
795 CreateEventTask(this, &BookmarkBarViewTest4::Step4));
796 }
797
Step4()798 void Step4() {
799 EXPECT_EQ(navigator_.last_url(),
800 model_->other_node()->children().front()->url());
801 ASSERT_FALSE(PageTransitionIsWebTriggerable(navigator_.last_transition()));
802 Done();
803 }
804
805 BookmarkContextMenuNotificationObserver observer_;
806 };
807
808 VIEW_TEST(BookmarkBarViewTest4, ContextMenus)
809
810 // Tests drag and drop within the same menu.
811 class BookmarkBarViewTest5 : public BookmarkBarViewDragTestBase {
812 protected:
813 // BookmarkBarViewDragTestBase:
OnMenuOpened()814 void OnMenuOpened() override {
815 BookmarkBarViewDragTestBase::OnMenuOpened();
816
817 // Cause the second menu item to trigger a mouse up when dragged over.
818 SetStopDraggingView(bb_view_->GetMenu()->GetSubmenu()->GetMenuItemAt(1));
819 }
820
GetDroppedNode() const821 const BookmarkNode* GetDroppedNode() const override {
822 return model_->bookmark_bar_node()->children()[0]->children()[1].get();
823 }
824
GetDragTargetInScreen() const825 gfx::Point GetDragTargetInScreen() const override {
826 const views::View* target_view =
827 bb_view_->GetMenu()->GetSubmenu()->GetMenuItemAt(1);
828 gfx::Point target(target_view->width() / 2, target_view->height() - 1);
829 views::View::ConvertPointToScreen(target_view, &target);
830 return target;
831 }
832 };
833
834 VIEW_TEST(BookmarkBarViewTest5, DND)
835
836 // Tests holding mouse down on overflow button, dragging such that menu pops up
837 // then selecting an item.
838 class BookmarkBarViewTest6 : public BookmarkBarViewEventTestBase {
839 protected:
DoTestOnMessageLoop()840 void DoTestOnMessageLoop() override {
841 // Press the mouse button on the overflow button. Don't release it though.
842 views::LabelButton* button = bb_view_->overflow_button();
843 ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
844 ui_controls::DOWN, CreateEventTask(this, &BookmarkBarViewTest6::Step2));
845 }
846
847 private:
Step2()848 void Step2() {
849 // Menu should be showing.
850 views::MenuItemView* menu = bb_view_->GetMenu();
851 ASSERT_TRUE(menu != NULL);
852 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
853
854 views::MenuItemView* child_menu =
855 menu->GetSubmenu()->GetMenuItemAt(0);
856 ASSERT_TRUE(child_menu != NULL);
857
858 // Move mouse to center of menu and release mouse.
859 ui_test_utils::MoveMouseToCenterAndPress(child_menu, ui_controls::LEFT,
860 ui_controls::UP, CreateEventTask(this, &BookmarkBarViewTest6::Step3));
861 }
862
Step3()863 void Step3() {
864 ASSERT_EQ(navigator_.last_url(),
865 model_->bookmark_bar_node()->children()[6]->url());
866 ASSERT_FALSE(PageTransitionIsWebTriggerable(navigator_.last_transition()));
867 Done();
868 }
869 };
870
871 // If this flakes, disable and log details in http://crbug.com/523255.
872 VIEW_TEST(BookmarkBarViewTest6, OpenMenuOnClickAndHold)
873
874 // Tests drag and drop to different menu.
875 class BookmarkBarViewTest7 : public BookmarkBarViewDragTestBase {
876 public:
877 // BookmarkBarViewDragTestBase:
OnDropMenuShown()878 void OnDropMenuShown() override {
879 views::MenuItemView* drop_menu = bb_view_->GetDropMenu();
880 ASSERT_NE(nullptr, drop_menu);
881 views::SubmenuView* drop_submenu = drop_menu->GetSubmenu();
882 ASSERT_TRUE(drop_submenu->IsShowing());
883
884 // The button should be highlighted now.
885 EXPECT_EQ(views::Button::STATE_PRESSED,
886 bb_view_->other_bookmarks_button()->GetState());
887
888 // Cause the target view to trigger a mouse up when dragged over.
889 const views::View* target_view = drop_submenu->GetMenuItemAt(0);
890 SetStopDraggingView(target_view);
891
892 // Drag to the top of the target view.
893 gfx::Point target(target_view->width() / 2, 0);
894 views::View::ConvertPointToScreen(target_view, &target);
895 GetDragTaskRunner()->PostTask(
896 FROM_HERE,
897 base::BindOnce(base::IgnoreResult(&ui_controls::SendMouseMove),
898 target.x(), target.y()));
899 }
900
OnWidgetDragComplete(views::Widget * widget)901 void OnWidgetDragComplete(views::Widget* widget) override {
902 // The button should be in normal state now.
903 EXPECT_EQ(views::Button::STATE_NORMAL,
904 bb_view_->other_bookmarks_button()->GetState());
905
906 BookmarkBarViewDragTestBase::OnWidgetDragComplete(widget);
907 }
908
909 protected:
910 // BookmarkBarViewDragTestBase:
GetDroppedNode() const911 const BookmarkNode* GetDroppedNode() const override {
912 return model_->other_node()->children().front().get();
913 }
914
GetDragTargetInScreen() const915 gfx::Point GetDragTargetInScreen() const override {
916 return ui_test_utils::GetCenterInScreenCoordinates(
917 bb_view_->other_bookmarks_button());
918 }
919 };
920
921 VIEW_TEST(BookmarkBarViewTest7, DNDToDifferentMenu)
922
923 // Drags from one menu to next so that original menu closes, then back to
924 // original menu.
925 class BookmarkBarViewTest8 : public BookmarkBarViewDragTestBase {
926 public:
927 // BookmarkBarViewDragTestBase:
OnDropMenuShown()928 void OnDropMenuShown() override {
929 views::MenuItemView* drop_menu = bb_view_->GetDropMenu();
930 ASSERT_NE(nullptr, drop_menu);
931 views::SubmenuView* drop_submenu = drop_menu->GetSubmenu();
932 ASSERT_TRUE(drop_submenu->IsShowing());
933
934 const views::View* target_view;
935 const auto* controller =
936 static_cast<const BookmarkMenuController*>(drop_menu->GetDelegate());
937 if (controller->node() == model_->other_node()) {
938 // Now drag back over first menu.
939 target_view = GetBookmarkButton(0);
940 } else {
941 // Drag to folder F11.
942 target_view = drop_submenu->GetMenuItemAt(1);
943
944 // Cause folder F11 to trigger a mouse up when dragged over.
945 SetStopDraggingView(target_view);
946 }
947 const gfx::Point target =
948 ui_test_utils::GetCenterInScreenCoordinates(target_view);
949 GetDragTaskRunner()->PostTask(
950 FROM_HERE,
951 base::BindOnce(base::IgnoreResult(&ui_controls::SendMouseMove),
952 target.x(), target.y()));
953 }
954
955 protected:
956 // BookmarkBarViewDragTestBase:
GetDroppedNode() const957 const BookmarkNode* GetDroppedNode() const override {
958 const auto& f1 = model_->bookmark_bar_node()->children()[0];
959 return f1->children()[0]->children()[1].get();
960 }
961
GetDragTargetInScreen() const962 gfx::Point GetDragTargetInScreen() const override {
963 return ui_test_utils::GetCenterInScreenCoordinates(
964 bb_view_->other_bookmarks_button());
965 }
966 };
967
968 VIEW_TEST(BookmarkBarViewTest8, DNDBackToOriginatingMenu)
969
970 // Moves the mouse over the scroll button and makes sure we get scrolling.
971 class BookmarkBarViewTest9 : public BookmarkBarViewEventTestBase {
972 protected:
CreateBigMenu()973 bool CreateBigMenu() override { return true; }
974
DoTestOnMessageLoop()975 void DoTestOnMessageLoop() override {
976 // Move the mouse to the first folder on the bookmark bar and press the
977 // mouse.
978 views::LabelButton* button = GetBookmarkButton(0);
979 ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
980 ui_controls::DOWN | ui_controls::UP,
981 CreateEventTask(this, &BookmarkBarViewTest9::Step2));
982 }
983
984 private:
Step2()985 void Step2() {
986 // Menu should be showing.
987 views::MenuItemView* menu = bb_view_->GetMenu();
988 ASSERT_TRUE(menu != NULL);
989 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
990
991 first_menu_ = menu->GetSubmenu()->GetMenuItemAt(0);
992 gfx::Point menu_loc;
993 views::View::ConvertPointToScreen(first_menu_, &menu_loc);
994 start_y_ = menu_loc.y();
995
996 // Move the mouse over the scroll button.
997 views::View* scroll_container = menu->GetSubmenu()->parent();
998 ASSERT_TRUE(scroll_container != NULL);
999 scroll_container = scroll_container->parent();
1000 ASSERT_TRUE(scroll_container != NULL);
1001 views::View* scroll_down_button = scroll_container->children()[2];
1002 ASSERT_TRUE(scroll_down_button);
1003 gfx::Point loc(scroll_down_button->width() / 2,
1004 scroll_down_button->height() / 2);
1005 views::View::ConvertPointToScreen(scroll_down_button, &loc);
1006
1007 // On linux, the sending one location isn't enough.
1008 ASSERT_TRUE(ui_controls::SendMouseMove(loc.x() - 1, loc.y() - 1));
1009 ASSERT_TRUE(ui_controls::SendMouseMoveNotifyWhenDone(
1010 loc.x(), loc.y(), CreateEventTask(this, &BookmarkBarViewTest9::Step3)));
1011 }
1012
Step3()1013 void Step3() {
1014 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
1015 FROM_HERE,
1016 base::BindOnce(&BookmarkBarViewTest9::Step4, base::Unretained(this)),
1017 base::TimeDelta::FromMilliseconds(200));
1018 }
1019
Step4()1020 void Step4() {
1021 gfx::Point menu_loc;
1022 views::View::ConvertPointToScreen(first_menu_, &menu_loc);
1023 ASSERT_NE(start_y_, menu_loc.y());
1024
1025 // Hide menu.
1026 bb_view_->GetMenu()->GetMenuController()->Cancel(
1027 views::MenuController::ExitType::kAll);
1028
1029 // On linux, Cancelling menu will call Quit on the message loop,
1030 // which can interfere with Done. We need to run Done in the
1031 // next execution loop.
1032 base::ThreadTaskRunnerHandle::Get()->PostTask(
1033 FROM_HERE,
1034 base::BindOnce(&ViewEventTestBase::Done, base::Unretained(this)));
1035 }
1036
1037 int start_y_;
1038 views::MenuItemView* first_menu_;
1039 };
1040
1041 VIEW_TEST(BookmarkBarViewTest9, ScrollButtonScrolls)
1042
1043 // Tests up/down/left/enter key messages.
1044 class BookmarkBarViewTest10 : public BookmarkBarViewEventTestBase {
1045 protected:
DoTestOnMessageLoop()1046 void DoTestOnMessageLoop() override {
1047 // Move the mouse to the first folder on the bookmark bar and press the
1048 // mouse.
1049 views::LabelButton* button = GetBookmarkButton(0);
1050 ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
1051 ui_controls::DOWN | ui_controls::UP,
1052 CreateEventTask(this, &BookmarkBarViewTest10::Step2));
1053 }
1054
1055 private:
Step2()1056 void Step2() {
1057 // Menu should be showing.
1058 views::MenuItemView* menu = bb_view_->GetMenu();
1059 ASSERT_TRUE(menu != NULL);
1060 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1061
1062 // Send a down event, which should select the first item.
1063 ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone(
1064 window()->GetNativeWindow(), ui::VKEY_DOWN, false, false, false, false,
1065 CreateEventTask(this, &BookmarkBarViewTest10::Step3)));
1066 }
1067
Step3()1068 void Step3() {
1069 // Make sure menu is showing and item is selected.
1070 views::MenuItemView* menu = bb_view_->GetMenu();
1071 ASSERT_TRUE(menu != NULL);
1072 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1073 ASSERT_TRUE(menu->GetSubmenu()->GetMenuItemAt(0)->IsSelected());
1074
1075 // Send a key down event, which should select the next item.
1076 ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone(
1077 window()->GetNativeWindow(), ui::VKEY_DOWN, false, false, false, false,
1078 CreateEventTask(this, &BookmarkBarViewTest10::Step4)));
1079 }
1080
Step4()1081 void Step4() {
1082 views::MenuItemView* menu = bb_view_->GetMenu();
1083 ASSERT_TRUE(menu != NULL);
1084 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1085 ASSERT_FALSE(menu->GetSubmenu()->GetMenuItemAt(0)->IsSelected());
1086 ASSERT_TRUE(menu->GetSubmenu()->GetMenuItemAt(1)->IsSelected());
1087
1088 // Send a right arrow to force the menu to open.
1089 ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone(
1090 window()->GetNativeWindow(), ui::VKEY_RIGHT, false, false, false, false,
1091 CreateEventTask(this, &BookmarkBarViewTest10::Step5)));
1092 }
1093
Step5()1094 void Step5() {
1095 // Make sure the submenu is showing.
1096 views::MenuItemView* menu = bb_view_->GetMenu();
1097 ASSERT_TRUE(menu != NULL);
1098 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1099 views::MenuItemView* submenu = menu->GetSubmenu()->GetMenuItemAt(1);
1100 ASSERT_TRUE(submenu->IsSelected());
1101 ASSERT_TRUE(submenu->GetSubmenu());
1102 ASSERT_TRUE(submenu->GetSubmenu()->IsShowing());
1103
1104 // Send a left arrow to close the submenu.
1105 ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone(
1106 window()->GetNativeWindow(), ui::VKEY_LEFT, false, false, false, false,
1107 CreateEventTask(this, &BookmarkBarViewTest10::Step6)));
1108 }
1109
Step6()1110 void Step6() {
1111 // Make sure the submenu is showing.
1112 views::MenuItemView* menu = bb_view_->GetMenu();
1113 ASSERT_TRUE(menu != NULL);
1114 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1115 views::MenuItemView* submenu = menu->GetSubmenu()->GetMenuItemAt(1);
1116 ASSERT_TRUE(submenu->IsSelected());
1117 ASSERT_TRUE(!submenu->GetSubmenu() || !submenu->GetSubmenu()->IsShowing());
1118
1119 // Send a down arrow to go down to f1b.
1120 ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone(
1121 window()->GetNativeWindow(), ui::VKEY_DOWN, false, false, false, false,
1122 CreateEventTask(this, &BookmarkBarViewTest10::Step7)));
1123 }
1124
Step7()1125 void Step7() {
1126 // Make sure menu is showing and item is selected.
1127 views::MenuItemView* menu = bb_view_->GetMenu();
1128 ASSERT_TRUE(menu != NULL);
1129 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1130 ASSERT_TRUE(menu->GetSubmenu()->GetMenuItemAt(2)->IsSelected());
1131
1132 // Send a down arrow to wrap back to f1a.
1133 ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone(
1134 window()->GetNativeWindow(), ui::VKEY_DOWN, false, false, false, false,
1135 CreateEventTask(this, &BookmarkBarViewTest10::Step8)));
1136 }
1137
Step8()1138 void Step8() {
1139 // Make sure menu is showing and item is selected.
1140 views::MenuItemView* menu = bb_view_->GetMenu();
1141 ASSERT_TRUE(menu != NULL);
1142 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1143 ASSERT_TRUE(menu->GetSubmenu()->GetMenuItemAt(0)->IsSelected());
1144
1145 // Send enter, which should select the item.
1146 ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone(
1147 window()->GetNativeWindow(), ui::VKEY_RETURN, false, false, false,
1148 false, CreateEventTask(this, &BookmarkBarViewTest10::Step9)));
1149 }
1150
Step9()1151 void Step9() {
1152 const auto& f1 = model_->bookmark_bar_node()->children().front();
1153 ASSERT_EQ(navigator_.last_url(), f1->children().front()->url());
1154 ASSERT_FALSE(PageTransitionIsWebTriggerable(navigator_.last_transition()));
1155 Done();
1156 }
1157 };
1158
1159 #if defined(OS_WIN) // Fails on latest versions of Windows.
1160 // https://crbug.com/1108551.
1161 #define MAYBE_KeyEvents DISABLED_KeyEvents
1162 #else
1163 #define MAYBE_KeyEvents KeyEvents
1164 #endif
1165 VIEW_TEST(BookmarkBarViewTest10, MAYBE_KeyEvents)
1166
1167 // Make sure the menu closes with the following sequence: show menu, show
1168 // context menu, close context menu (via escape), then click else where. This
1169 // effectively verifies we maintain mouse capture after the context menu is
1170 // hidden.
1171 class BookmarkBarViewTest11 : public BookmarkBarViewEventTestBase {
1172 public:
BookmarkBarViewTest11()1173 BookmarkBarViewTest11()
1174 : observer_(CreateEventTask(this, &BookmarkBarViewTest11::Step3)) {
1175 }
1176
1177 protected:
DoTestOnMessageLoop()1178 void DoTestOnMessageLoop() override {
1179 // Move the mouse to the first folder on the bookmark bar and press the
1180 // mouse.
1181 views::LabelButton* button = bb_view_->other_bookmarks_button();
1182 ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
1183 ui_controls::DOWN | ui_controls::UP,
1184 CreateEventTask(this, &BookmarkBarViewTest11::Step2));
1185 }
1186
1187 private:
Step2()1188 void Step2() {
1189 // Menu should be showing.
1190 views::MenuItemView* menu = bb_view_->GetMenu();
1191 ASSERT_TRUE(menu != NULL);
1192 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1193
1194 views::MenuItemView* child_menu =
1195 menu->GetSubmenu()->GetMenuItemAt(0);
1196 ASSERT_TRUE(child_menu != NULL);
1197
1198 // Right click on the first child to get its context menu.
1199 ui_test_utils::MoveMouseToCenterAndPress(
1200 child_menu, ui_controls::RIGHT, ui_controls::DOWN | ui_controls::UP,
1201 base::OnceClosure());
1202 // Step3 will be invoked by BookmarkContextMenuNotificationObserver.
1203 }
1204
Step3()1205 void Step3() {
1206 // Send escape so that the context menu hides.
1207 ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone(
1208 window()->GetNativeWindow(), ui::VKEY_ESCAPE, false, false, false,
1209 false, CreateEventTask(this, &BookmarkBarViewTest11::Step4)));
1210 }
1211
Step4()1212 void Step4() {
1213 // Make sure the context menu is no longer showing.
1214 views::MenuItemView* menu = bb_view_->GetContextMenu();
1215 ASSERT_TRUE(!menu || !menu->GetSubmenu() ||
1216 !menu->GetSubmenu()->IsShowing());
1217
1218 // But the menu should be showing.
1219 menu = bb_view_->GetMenu();
1220 ASSERT_TRUE(menu && menu->GetSubmenu() && menu->GetSubmenu()->IsShowing());
1221
1222 // Now click on empty space.
1223 gfx::Point mouse_loc;
1224 views::View::ConvertPointToScreen(bb_view_, &mouse_loc);
1225 ASSERT_TRUE(ui_controls::SendMouseMove(mouse_loc.x(), mouse_loc.y()));
1226 ASSERT_TRUE(ui_controls::SendMouseEventsNotifyWhenDone(
1227 ui_controls::LEFT, ui_controls::UP | ui_controls::DOWN,
1228 CreateEventTask(this, &BookmarkBarViewTest11::Step5)));
1229 }
1230
Step5()1231 void Step5() {
1232 // Make sure the menu is not showing.
1233 views::MenuItemView* menu = bb_view_->GetMenu();
1234 ASSERT_TRUE(!menu || !menu->GetSubmenu() ||
1235 !menu->GetSubmenu()->IsShowing());
1236 Done();
1237 }
1238
1239 BookmarkContextMenuNotificationObserver observer_;
1240 };
1241
1242 VIEW_TEST(BookmarkBarViewTest11, CloseMenuAfterClosingContextMenu)
1243
1244 // Tests showing a modal dialog from a context menu.
1245 class BookmarkBarViewTest12 : public BookmarkBarViewEventTestBase {
1246 protected:
DoTestOnMessageLoop()1247 void DoTestOnMessageLoop() override {
1248 // Open up the other folder.
1249 views::LabelButton* button = bb_view_->other_bookmarks_button();
1250 ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
1251 ui_controls::DOWN | ui_controls::UP,
1252 CreateEventTask(this, &BookmarkBarViewTest12::Step2));
1253 chrome::kNumBookmarkUrlsBeforePrompting = 1;
1254 }
1255
~BookmarkBarViewTest12()1256 ~BookmarkBarViewTest12() override {
1257 chrome::kNumBookmarkUrlsBeforePrompting = 15;
1258 }
1259
1260 private:
Step2()1261 void Step2() {
1262 // Menu should be showing.
1263 views::MenuItemView* menu = bb_view_->GetMenu();
1264 ASSERT_TRUE(menu != NULL);
1265 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1266
1267 views::MenuItemView* child_menu =
1268 menu->GetSubmenu()->GetMenuItemAt(1);
1269 ASSERT_TRUE(child_menu != NULL);
1270
1271 // Right click on the second child (a folder) to get its context menu.
1272 ui_test_utils::MoveMouseToCenterAndPress(child_menu, ui_controls::RIGHT,
1273 ui_controls::DOWN | ui_controls::UP,
1274 CreateEventTask(this, &BookmarkBarViewTest12::Step3));
1275 }
1276
Step3()1277 void Step3() {
1278 // Make sure the context menu is showing.
1279 views::MenuItemView* menu = bb_view_->GetContextMenu();
1280 ASSERT_TRUE(menu);
1281 ASSERT_TRUE(menu->GetSubmenu());
1282 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1283
1284 // Select the first item in the context menu (open all).
1285 views::MenuItemView* child_menu =
1286 menu->GetSubmenu()->GetMenuItemAt(0);
1287 ASSERT_TRUE(child_menu != NULL);
1288
1289 // Click and wait until the dialog box appears.
1290 auto dialog_waiter = std::make_unique<DialogWaiter>();
1291 ui_test_utils::MoveMouseToCenterAndPress(
1292 child_menu, ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
1293 base::BindOnce(&BookmarkBarViewTest12::Step4, base::Unretained(this),
1294 std::move(dialog_waiter)));
1295 }
1296
Step4(std::unique_ptr<DialogWaiter> waiter)1297 void Step4(std::unique_ptr<DialogWaiter> waiter) {
1298 views::Widget* dialog = waiter->WaitForDialog();
1299 waiter.reset();
1300
1301 // Press tab to give focus to the cancel button. Wait until the widget
1302 // receives the tab key.
1303 TabKeyWaiter tab_waiter(dialog);
1304 ASSERT_TRUE(ui_controls::SendKeyPress(
1305 dialog->GetNativeWindow(), ui::VKEY_TAB, false, false, false, false));
1306 tab_waiter.WaitForTab();
1307
1308 // For some reason return isn't processed correctly unless we delay.
1309 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
1310 FROM_HERE,
1311 base::BindOnce(&BookmarkBarViewTest12::Step5, base::Unretained(this),
1312 base::Unretained(dialog)),
1313 base::TimeDelta::FromSeconds(1));
1314 }
1315
Step5(views::Widget * dialog)1316 void Step5(views::Widget* dialog) {
1317 DialogCloseWaiter waiter(dialog);
1318 // And press enter so that the cancel button is selected.
1319 ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone(
1320 dialog->GetNativeWindow(), ui::VKEY_RETURN, false, false, false, false,
1321 base::OnceClosure()));
1322 waiter.WaitForDialogClose();
1323 Done();
1324 }
1325 };
1326
1327 VIEW_TEST(BookmarkBarViewTest12, CloseWithModalDialog)
1328
1329 // Tests clicking on the separator of a context menu (this is for coverage of
1330 // bug 17862).
1331 class BookmarkBarViewTest13 : public BookmarkBarViewEventTestBase {
1332 public:
BookmarkBarViewTest13()1333 BookmarkBarViewTest13()
1334 : observer_(CreateEventTask(this, &BookmarkBarViewTest13::Step3)) {
1335 }
1336
1337 protected:
DoTestOnMessageLoop()1338 void DoTestOnMessageLoop() override {
1339 // Move the mouse to the first folder on the bookmark bar and press the
1340 // mouse.
1341 views::LabelButton* button = bb_view_->other_bookmarks_button();
1342 ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
1343 ui_controls::DOWN | ui_controls::UP,
1344 CreateEventTask(this, &BookmarkBarViewTest13::Step2));
1345 }
1346
1347 private:
Step2()1348 void Step2() {
1349 // Menu should be showing.
1350 views::MenuItemView* menu = bb_view_->GetMenu();
1351 ASSERT_TRUE(menu != NULL);
1352 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1353
1354 views::MenuItemView* child_menu =
1355 menu->GetSubmenu()->GetMenuItemAt(0);
1356 ASSERT_TRUE(child_menu != NULL);
1357
1358 // Right click on the first child to get its context menu.
1359 ui_test_utils::MoveMouseToCenterAndPress(
1360 child_menu, ui_controls::RIGHT, ui_controls::DOWN | ui_controls::UP,
1361 base::OnceClosure());
1362 // Step3 will be invoked by BookmarkContextMenuNotificationObserver.
1363 }
1364
Step3()1365 void Step3() {
1366 // Make sure the context menu is showing.
1367 views::MenuItemView* menu = bb_view_->GetContextMenu();
1368 ASSERT_TRUE(menu != NULL);
1369 ASSERT_TRUE(menu->GetSubmenu());
1370 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1371
1372 // Find the first separator.
1373 views::SubmenuView* submenu = menu->GetSubmenu();
1374 const auto i = std::find_if(
1375 submenu->children().begin(), submenu->children().end(),
1376 [](const auto* child) {
1377 return child->GetID() != views::MenuItemView::kMenuItemViewID;
1378 });
1379 ASSERT_FALSE(i == submenu->children().end());
1380
1381 // Click on the separator. Clicking on the separator shouldn't visually
1382 // change anything.
1383 ui_test_utils::MoveMouseToCenterAndPress(
1384 *i, ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
1385 CreateEventTask(this, &BookmarkBarViewTest13::Step4));
1386 }
1387
Step4()1388 void Step4() {
1389 // The context menu should still be showing.
1390 views::MenuItemView* menu = bb_view_->GetContextMenu();
1391 ASSERT_TRUE(menu != NULL);
1392 ASSERT_TRUE(menu->GetSubmenu());
1393 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1394
1395 // Select the first context menu item.
1396 ui_test_utils::MoveMouseToCenterAndPress(
1397 menu->GetSubmenu()->GetMenuItemAt(0),
1398 ui_controls::LEFT,
1399 ui_controls::DOWN | ui_controls::UP,
1400 CreateEventTask(this, &BookmarkBarViewTest13::Step5));
1401 }
1402
Step5()1403 void Step5() {
1404 Done();
1405 }
1406
1407 BookmarkContextMenuNotificationObserver observer_;
1408 };
1409
1410 VIEW_TEST(BookmarkBarViewTest13, ClickOnContextMenuSeparator)
1411
1412 // Makes sure right clicking on a folder on the bookmark bar doesn't result in
1413 // both a context menu and showing the menu.
1414 class BookmarkBarViewTest14 : public BookmarkBarViewEventTestBase {
1415 public:
BookmarkBarViewTest14()1416 BookmarkBarViewTest14()
1417 : observer_(CreateEventTask(this, &BookmarkBarViewTest14::Step2)) {
1418 }
1419
1420 protected:
DoTestOnMessageLoop()1421 void DoTestOnMessageLoop() override {
1422 // Move the mouse to the first folder on the bookmark bar and press the
1423 // right mouse button.
1424 views::LabelButton* button = GetBookmarkButton(0);
1425 ui_test_utils::MoveMouseToCenterAndPress(
1426 button, ui_controls::RIGHT, ui_controls::DOWN | ui_controls::UP,
1427 base::OnceClosure());
1428 // Step2 will be invoked by BookmarkContextMenuNotificationObserver.
1429 }
1430
1431 private:
1432
Step2()1433 void Step2() {
1434 // Menu should NOT be showing.
1435 views::MenuItemView* menu = bb_view_->GetMenu();
1436 ASSERT_TRUE(menu == NULL);
1437
1438 // Send escape so that the context menu hides.
1439 ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone(
1440 window()->GetNativeWindow(), ui::VKEY_ESCAPE, false, false, false,
1441 false, CreateEventTask(this, &BookmarkBarViewTest14::Step3)));
1442 }
1443
Step3()1444 void Step3() {
1445 Done();
1446 }
1447
1448 BookmarkContextMenuNotificationObserver observer_;
1449 };
1450
1451 VIEW_TEST(BookmarkBarViewTest14, ContextMenus2)
1452
1453 // Makes sure deleting from the context menu keeps the bookmark menu showing.
1454 class BookmarkBarViewTest15 : public BookmarkBarViewEventTestBase {
1455 public:
BookmarkBarViewTest15()1456 BookmarkBarViewTest15()
1457 : deleted_menu_id_(0),
1458 observer_(CreateEventTask(this, &BookmarkBarViewTest15::Step3)) {
1459 }
1460
1461 protected:
DoTestOnMessageLoop()1462 void DoTestOnMessageLoop() override {
1463 // Show the other bookmarks.
1464 views::LabelButton* button = bb_view_->other_bookmarks_button();
1465 ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
1466 ui_controls::DOWN | ui_controls::UP,
1467 CreateEventTask(this, &BookmarkBarViewTest15::Step2));
1468 }
1469
1470 private:
Step2()1471 void Step2() {
1472 // Menu should be showing.
1473 views::MenuItemView* menu = bb_view_->GetMenu();
1474 ASSERT_TRUE(menu != NULL);
1475 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1476
1477 views::MenuItemView* child_menu =
1478 menu->GetSubmenu()->GetMenuItemAt(1);
1479 ASSERT_TRUE(child_menu != NULL);
1480
1481 deleted_menu_id_ = child_menu->GetCommand();
1482
1483 // Right click on the second child to get its context menu.
1484 ui_test_utils::MoveMouseToCenterAndPress(
1485 child_menu, ui_controls::RIGHT, ui_controls::DOWN | ui_controls::UP,
1486 base::OnceClosure());
1487 // Step3 will be invoked by BookmarkContextMenuNotificationObserver.
1488 }
1489
Step3()1490 void Step3() {
1491 // Make sure the context menu is showing.
1492 views::MenuItemView* menu = bb_view_->GetContextMenu();
1493 ASSERT_TRUE(menu != NULL);
1494 ASSERT_TRUE(menu->GetSubmenu());
1495 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1496
1497 views::MenuItemView* delete_menu =
1498 menu->GetMenuItemByID(IDC_BOOKMARK_BAR_REMOVE);
1499 ASSERT_TRUE(delete_menu);
1500
1501 // Click on the delete button.
1502 ui_test_utils::MoveMouseToCenterAndPress(delete_menu,
1503 ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
1504 CreateEventTask(this, &BookmarkBarViewTest15::Step4));
1505 }
1506
Step4()1507 void Step4() {
1508 // The context menu should not be showing.
1509 views::MenuItemView* context_menu = bb_view_->GetContextMenu();
1510 ASSERT_TRUE(context_menu == NULL);
1511
1512 // But the menu should be showing.
1513 views::MenuItemView* menu = bb_view_->GetMenu();
1514 ASSERT_TRUE(menu != NULL);
1515 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1516
1517 // And the deleted_menu_id_ should have been removed.
1518 ASSERT_TRUE(menu->GetMenuItemByID(deleted_menu_id_) == NULL);
1519
1520 bb_view_->GetMenu()->GetMenuController()->Cancel(
1521 views::MenuController::ExitType::kAll);
1522
1523 Done();
1524 }
1525
1526 int deleted_menu_id_;
1527 BookmarkContextMenuNotificationObserver observer_;
1528 };
1529
1530 VIEW_TEST(BookmarkBarViewTest15, MenuStaysVisibleAfterDelete)
1531
1532 // Tests that we don't crash or get stuck if the parent of a menu is closed.
1533 class BookmarkBarViewTest16 : public BookmarkBarViewEventTestBase {
1534 protected:
DoTestOnMessageLoop()1535 void DoTestOnMessageLoop() override {
1536 // Move the mouse to the first folder on the bookmark bar and press the
1537 // mouse.
1538 views::LabelButton* button = GetBookmarkButton(0);
1539 ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
1540 ui_controls::DOWN | ui_controls::UP,
1541 CreateEventTask(this, &BookmarkBarViewTest16::Step2));
1542 }
1543
1544 private:
Step2()1545 void Step2() {
1546 // Menu should be showing.
1547 views::MenuItemView* menu = bb_view_->GetMenu();
1548 ASSERT_TRUE(menu != NULL);
1549 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1550
1551 // Button should be depressed.
1552 views::LabelButton* button = GetBookmarkButton(0);
1553 ASSERT_TRUE(button->GetState() == views::Button::STATE_PRESSED);
1554
1555 // Close the window.
1556 window()->Close();
1557
1558 base::ThreadTaskRunnerHandle::Get()->PostTask(
1559 FROM_HERE, CreateEventTask(this, &BookmarkBarViewTest16::Done));
1560 }
1561 };
1562
1563 VIEW_TEST(BookmarkBarViewTest16, DeleteMenu)
1564
1565 // Makes sure right clicking on an item while a context menu is already showing
1566 // doesn't crash and works.
1567 class BookmarkBarViewTest17 : public BookmarkBarViewEventTestBase {
1568 public:
BookmarkBarViewTest17()1569 BookmarkBarViewTest17()
1570 : observer_(std::make_unique<BookmarkContextMenuNotificationObserver>(
1571 CreateEventTask(this, &BookmarkBarViewTest17::Step3))) {}
1572
1573 protected:
DoTestOnMessageLoop()1574 void DoTestOnMessageLoop() override {
1575 #if defined(OS_WIN)
1576 // TODO(crbug.com/453796): Flaky on Windows7.
1577 if (base::win::GetVersion() <= base::win::Version::WIN7) {
1578 Done();
1579 return;
1580 }
1581 #endif
1582
1583 // Move the mouse to the other folder on the bookmark bar and press the
1584 // left mouse button.
1585 views::LabelButton* button = bb_view_->other_bookmarks_button();
1586 ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
1587 ui_controls::DOWN | ui_controls::UP,
1588 CreateEventTask(this, &BookmarkBarViewTest17::Step2));
1589 }
1590
1591 private:
Step2()1592 void Step2() {
1593 // Menu should be showing.
1594 views::MenuItemView* menu = bb_view_->GetMenu();
1595 ASSERT_TRUE(menu != NULL);
1596 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1597
1598 // Right click on the second item to show its context menu.
1599 views::MenuItemView* child_menu = menu->GetSubmenu()->GetMenuItemAt(2);
1600 ASSERT_TRUE(child_menu != NULL);
1601 ui_test_utils::MoveMouseToCenterAndPress(
1602 child_menu, ui_controls::RIGHT, ui_controls::DOWN | ui_controls::UP,
1603 base::OnceClosure());
1604 // Step3 will be invoked by BookmarkContextMenuNotificationObserver.
1605 }
1606
Step3()1607 void Step3() {
1608 // Make sure the context menu is showing.
1609 views::MenuItemView* context_menu = bb_view_->GetContextMenu();
1610 ASSERT_TRUE(context_menu != NULL);
1611 ASSERT_TRUE(context_menu->GetSubmenu());
1612 ASSERT_TRUE(context_menu->GetSubmenu()->IsShowing());
1613
1614 // Right click on the first menu item to trigger its context menu.
1615 views::MenuItemView* menu = bb_view_->GetMenu();
1616 ASSERT_TRUE(menu != NULL);
1617 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1618 views::MenuItemView* child_menu = menu->GetSubmenu()->GetMenuItemAt(1);
1619 ASSERT_TRUE(child_menu != NULL);
1620
1621 // The context menu and child_menu can be overlapped, calculate the
1622 // non-intersected Rect of the child menu and click on its center to make
1623 // sure the click is always on the child menu.
1624 gfx::Rect context_rect = context_menu->GetSubmenu()->GetBoundsInScreen();
1625 gfx::Rect child_menu_rect = child_menu->GetBoundsInScreen();
1626 gfx::Rect clickable_rect =
1627 gfx::SubtractRects(child_menu_rect, context_rect);
1628 ASSERT_FALSE(clickable_rect.IsEmpty());
1629 observer_ = std::make_unique<BookmarkContextMenuNotificationObserver>(
1630 CreateEventTask(this, &BookmarkBarViewTest17::Step4));
1631 MoveMouseAndPress(clickable_rect.CenterPoint(), ui_controls::RIGHT,
1632 ui_controls::DOWN | ui_controls::UP, base::Closure());
1633 // Step4 will be invoked by BookmarkContextMenuNotificationObserver.
1634 }
1635
Step4()1636 void Step4() {
1637 // The context menu should still be showing.
1638 views::MenuItemView* context_menu = bb_view_->GetContextMenu();
1639 ASSERT_TRUE(context_menu != NULL);
1640
1641 // And the menu should be showing.
1642 views::MenuItemView* menu = bb_view_->GetMenu();
1643 ASSERT_TRUE(menu != NULL);
1644 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1645
1646 bb_view_->GetMenu()->GetMenuController()->Cancel(
1647 views::MenuController::ExitType::kAll);
1648
1649 Done();
1650 }
1651
1652 std::unique_ptr<BookmarkContextMenuNotificationObserver> observer_;
1653 };
1654
1655 VIEW_TEST(BookmarkBarViewTest17, ContextMenus3)
1656
1657 // Verifies sibling menus works. Clicks on the 'other bookmarks' folder, then
1658 // moves the mouse over the first item on the bookmark bar and makes sure the
1659 // menu appears.
1660 class BookmarkBarViewTest18 : public BookmarkBarViewEventTestBase {
1661 protected:
DoTestOnMessageLoop()1662 void DoTestOnMessageLoop() override {
1663 // Move the mouse to the other folder on the bookmark bar and press the
1664 // left mouse button.
1665 views::LabelButton* button = bb_view_->other_bookmarks_button();
1666 ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
1667 ui_controls::DOWN | ui_controls::UP,
1668 CreateEventTask(this, &BookmarkBarViewTest18::Step2));
1669 }
1670
1671 private:
Step2()1672 void Step2() {
1673 // Menu should be showing.
1674 views::MenuItemView* menu = bb_view_->GetMenu();
1675 ASSERT_TRUE(menu != NULL);
1676 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1677 // The button should be pressed.
1678 EXPECT_EQ(views::Button::STATE_PRESSED,
1679 bb_view_->other_bookmarks_button()->GetState());
1680
1681 // Move the mouse to the first folder on the bookmark bar.
1682 views::LabelButton* button = GetBookmarkButton(0);
1683 gfx::Point button_center(button->width() / 2, button->height() / 2);
1684 views::View::ConvertPointToScreen(button, &button_center);
1685 ASSERT_TRUE(ui_controls::SendMouseMoveNotifyWhenDone(
1686 button_center.x(), button_center.y(),
1687 CreateEventTask(this, &BookmarkBarViewTest18::Step3)));
1688 }
1689
Step3()1690 void Step3() {
1691 // Make sure the menu is showing.
1692 views::MenuItemView* menu = bb_view_->GetMenu();
1693 ASSERT_TRUE(menu != NULL);
1694 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1695
1696 // The menu for the first folder should be in the pressed state (since the
1697 // menu is showing for it)...
1698 EXPECT_EQ(views::Button::STATE_PRESSED, GetBookmarkButton(0)->GetState());
1699 // ... And the "other bookmarks" button should no longer be pressed.
1700 EXPECT_EQ(views::Button::STATE_NORMAL,
1701 bb_view_->other_bookmarks_button()->GetState());
1702
1703 menu->GetMenuController()->Cancel(views::MenuController::ExitType::kAll);
1704
1705 Done();
1706 }
1707 };
1708
1709 VIEW_TEST(BookmarkBarViewTest18, BookmarkBarViewTest18_SiblingMenu)
1710
1711 // Verifies mousing over an already open sibling menu doesn't prematurely cancel
1712 // the menu.
1713 class BookmarkBarViewTest19 : public BookmarkBarViewEventTestBase {
1714 protected:
DoTestOnMessageLoop()1715 void DoTestOnMessageLoop() override {
1716 // Move the mouse to the other folder on the bookmark bar and press the
1717 // left mouse button.
1718 views::LabelButton* button = bb_view_->other_bookmarks_button();
1719 ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
1720 ui_controls::DOWN | ui_controls::UP,
1721 CreateEventTask(this, &BookmarkBarViewTest19::Step2));
1722 }
1723
1724 private:
Step2()1725 void Step2() {
1726 // Menu should be showing.
1727 views::MenuItemView* menu = bb_view_->GetMenu();
1728 ASSERT_TRUE(menu != NULL);
1729 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1730
1731 // Click on the first folder.
1732 views::MenuItemView* child_menu = menu->GetSubmenu()->GetMenuItemAt(1);
1733 ASSERT_TRUE(child_menu != NULL);
1734 ui_test_utils::MoveMouseToCenterAndPress(
1735 child_menu, ui_controls::LEFT,
1736 ui_controls::DOWN | ui_controls::UP,
1737 CreateEventTask(this, &BookmarkBarViewTest19::Step3));
1738 }
1739
Step3()1740 void Step3() {
1741 // Make sure the menu is showing.
1742 views::MenuItemView* menu = bb_view_->GetMenu();
1743 ASSERT_TRUE(menu != NULL);
1744 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1745
1746 // Move the mouse back to the "Other Bookmarks" button.
1747 views::LabelButton* button = bb_view_->other_bookmarks_button();
1748 gfx::Point button_center(button->width() / 2, button->height() / 2);
1749 views::View::ConvertPointToScreen(button, &button_center);
1750 ASSERT_TRUE(ui_controls::SendMouseMoveNotifyWhenDone(
1751 button_center.x() + 1, button_center.y() + 1,
1752 CreateEventTask(this, &BookmarkBarViewTest19::Step4)));
1753 }
1754
Step4()1755 void Step4() {
1756 // Menu should be showing.
1757 views::MenuItemView* menu = bb_view_->GetMenu();
1758 ASSERT_TRUE(menu != NULL);
1759 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1760
1761 // Click on the first folder.
1762 views::MenuItemView* child_menu = menu->GetSubmenu()->GetMenuItemAt(1);
1763 ASSERT_TRUE(child_menu != NULL);
1764 ui_test_utils::MoveMouseToCenterAndPress(
1765 child_menu,
1766 ui_controls::LEFT,
1767 ui_controls::DOWN | ui_controls::UP,
1768 CreateEventTask(this, &BookmarkBarViewTest19::Step5));
1769 }
1770
Step5()1771 void Step5() {
1772 // Make sure the menu is showing.
1773 views::MenuItemView* menu = bb_view_->GetMenu();
1774 ASSERT_TRUE(menu != NULL);
1775 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1776
1777 menu->GetMenuController()->Cancel(views::MenuController::ExitType::kAll);
1778
1779 Done();
1780 }
1781 };
1782
1783 VIEW_TEST(BookmarkBarViewTest19, BookmarkBarViewTest19_SiblingMenu)
1784
1785 // Verify that when clicking a mouse button outside a context menu,
1786 // the context menu is dismissed *and* the underlying view receives
1787 // the the mouse event (due to event reposting).
1788 class BookmarkBarViewTest20 : public BookmarkBarViewEventTestBase {
1789 public:
1790 BookmarkBarViewTest20() = default;
1791
1792 protected:
DoTestOnMessageLoop()1793 void DoTestOnMessageLoop() override {
1794 // Add |test_view_| next to |bb_view_|.
1795 views::View* parent = bb_view_->parent();
1796 parent->RemoveChildView(bb_view_);
1797 auto* const container_view =
1798 parent->AddChildView(std::make_unique<views::View>());
1799 auto* const layout =
1800 container_view->SetLayoutManager(std::make_unique<views::FlexLayout>());
1801 layout->SetIgnoreDefaultMainAxisMargins(true)
1802 .SetCollapseMargins(true)
1803 .SetDefault(views::kMarginsKey, gfx::Insets(0, 2));
1804 container_view->AddChildView(bb_view_);
1805 bb_view_->SetProperty(
1806 views::kFlexBehaviorKey,
1807 views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToZero,
1808 views::MaximumFlexSizeRule::kUnbounded));
1809 test_view_ =
1810 container_view->AddChildView(std::make_unique<TestViewForMenuExit>());
1811 test_view_->SetPreferredSize(gfx::Size(20, 0));
1812 parent->Layout();
1813
1814 EXPECT_EQ(0, test_view_->press_count());
1815
1816 // Move the mouse to the Test View and press the left mouse button.
1817 ui_test_utils::MoveMouseToCenterAndPress(
1818 test_view_, ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
1819 CreateEventTask(this, &BookmarkBarViewTest20::Step1));
1820 }
1821
1822 private:
Step1()1823 void Step1() {
1824 EXPECT_EQ(1, test_view_->press_count());
1825 EXPECT_EQ(nullptr, bb_view_->GetMenu());
1826
1827 // Move the mouse to the first folder on the bookmark bar and press the
1828 // left mouse button.
1829 ui_test_utils::MoveMouseToCenterAndPress(
1830 GetBookmarkButton(0), ui_controls::LEFT,
1831 ui_controls::DOWN | ui_controls::UP,
1832 CreateEventTask(this, &BookmarkBarViewTest20::Step2));
1833 }
1834
Step2()1835 void Step2() {
1836 EXPECT_EQ(1, test_view_->press_count());
1837 views::MenuItemView* menu = bb_view_->GetMenu();
1838 ASSERT_NE(nullptr, menu);
1839 EXPECT_TRUE(menu->GetSubmenu()->IsShowing());
1840
1841 // Move the mouse to the Test View and press the left mouse button.
1842 // The context menu will consume the event and exit. Thereafter,
1843 // the event is reposted and delivered to the Test View which
1844 // increases its press-count.
1845 ui_test_utils::MoveMouseToCenterAndPress(
1846 test_view_, ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
1847 CreateEventTask(this, &BookmarkBarViewTest20::Step3));
1848 }
1849
Step3()1850 void Step3() {
1851 #if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_BSD)
1852 EXPECT_EQ(1, test_view_->press_count());
1853 #else
1854 EXPECT_EQ(2, test_view_->press_count());
1855 #endif
1856 EXPECT_EQ(nullptr, bb_view_->GetMenu());
1857 Done();
1858 }
1859
1860 class TestViewForMenuExit : public views::View {
1861 public:
1862 TestViewForMenuExit() = default;
1863
OnMousePressed(const ui::MouseEvent & event)1864 bool OnMousePressed(const ui::MouseEvent& event) override {
1865 ++press_count_;
1866 return true;
1867 }
press_count() const1868 int press_count() const { return press_count_; }
1869
1870 private:
1871 int press_count_ = 0;
1872 };
1873
1874 TestViewForMenuExit* test_view_ = nullptr;
1875 };
1876
1877 VIEW_TEST(BookmarkBarViewTest20, ContextMenuExitTest)
1878
1879 // Tests context menu by way of opening a context menu for a empty folder menu.
1880 // The opened context menu should behave as it is from the folder button.
1881 class BookmarkBarViewTest21 : public BookmarkBarViewEventTestBase {
1882 public:
BookmarkBarViewTest21()1883 BookmarkBarViewTest21()
1884 : observer_(CreateEventTask(this, &BookmarkBarViewTest21::Step3)) {
1885 }
1886
1887 protected:
1888 // Move the mouse to the empty folder on the bookmark bar and press the
1889 // left mouse button.
DoTestOnMessageLoop()1890 void DoTestOnMessageLoop() override {
1891 views::LabelButton* button = GetBookmarkButton(5);
1892 ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
1893 ui_controls::DOWN | ui_controls::UP,
1894 CreateEventTask(this, &BookmarkBarViewTest21::Step2));
1895 }
1896
1897 private:
1898 // Confirm that a menu for empty folder shows and right click the menu.
Step2()1899 void Step2() {
1900 // Menu should be showing.
1901 views::MenuItemView* menu = bb_view_->GetMenu();
1902 ASSERT_TRUE(menu != NULL);
1903
1904 views::SubmenuView* submenu = menu->GetSubmenu();
1905 ASSERT_TRUE(submenu->IsShowing());
1906 ASSERT_EQ(1u, submenu->children().size());
1907
1908 views::View* view = submenu->children().front();
1909 ASSERT_NE(nullptr, view);
1910 EXPECT_EQ(views::MenuItemView::kEmptyMenuItemViewID, view->GetID());
1911
1912 // Right click on the first child to get its context menu.
1913 ui_test_utils::MoveMouseToCenterAndPress(
1914 view, ui_controls::RIGHT, ui_controls::DOWN | ui_controls::UP,
1915 base::OnceClosure());
1916 // Step3 will be invoked by BookmarkContextMenuNotificationObserver.
1917 }
1918
1919 // Confirm that context menu shows and click REMOVE menu.
Step3()1920 void Step3() {
1921 // Make sure the context menu is showing.
1922 views::MenuItemView* menu = bb_view_->GetContextMenu();
1923 ASSERT_TRUE(menu != NULL);
1924 ASSERT_TRUE(menu->GetSubmenu());
1925 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
1926
1927 views::MenuItemView* delete_menu =
1928 menu->GetMenuItemByID(IDC_BOOKMARK_BAR_REMOVE);
1929 ASSERT_TRUE(delete_menu);
1930
1931 // Click on the delete menu item.
1932 ui_test_utils::MoveMouseToCenterAndPress(delete_menu,
1933 ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
1934 CreateEventTask(this, &BookmarkBarViewTest21::Step4));
1935 }
1936
1937 // Confirm that the empty folder gets removed and menu doesn't show.
Step4()1938 void Step4() {
1939 views::LabelButton* button = GetBookmarkButton(5);
1940 ASSERT_TRUE(button);
1941 EXPECT_EQ(ASCIIToUTF16("d"), button->GetText());
1942 EXPECT_TRUE(bb_view_->GetContextMenu() == NULL);
1943 EXPECT_TRUE(bb_view_->GetMenu() == NULL);
1944
1945 Done();
1946 }
1947
1948 BookmarkContextMenuNotificationObserver observer_;
1949 };
1950
1951 // If this flakes, disable and log details in http://crbug.com/523255.
1952 VIEW_TEST(BookmarkBarViewTest21, ContextMenusForEmptyFolder)
1953
1954 // Test that closing the source browser window while dragging a bookmark does
1955 // not cause a crash.
1956 class BookmarkBarViewTest22 : public BookmarkBarViewDragTestBase {
1957 public:
1958 // BookmarkBarViewDragTestBase:
OnWidgetDragComplete(views::Widget * widget)1959 void OnWidgetDragComplete(views::Widget* widget) override {}
1960
OnWidgetDestroyed(views::Widget * widget)1961 void OnWidgetDestroyed(views::Widget* widget) override {
1962 BookmarkBarViewDragTestBase::OnWidgetDestroyed(widget);
1963 Done();
1964 }
1965
1966 protected:
1967 // BookmarkBarViewDragTestBase:
OnMenuOpened()1968 void OnMenuOpened() override {
1969 BookmarkBarViewDragTestBase::OnMenuOpened();
1970
1971 // Cause the second menu item to close the window when dragged over.
1972 SetStopDraggingView(bb_view_->GetMenu()->GetSubmenu()->GetMenuItemAt(1));
1973 }
1974
OnDragEntered()1975 void OnDragEntered() override {
1976 // Stop the drag, so any nested message loop will terminate; closing the
1977 // window alone may not exit this message loop.
1978 BookmarkBarViewDragTestBase::OnDragEntered();
1979
1980 window()->Close();
1981 }
1982
GetDroppedNode() const1983 const BookmarkNode* GetDroppedNode() const override {
1984 // This test doesn't check what happens on drop.
1985 return nullptr;
1986 }
1987
GetDragTargetInScreen() const1988 gfx::Point GetDragTargetInScreen() const override {
1989 return ui_test_utils::GetCenterInScreenCoordinates(
1990 bb_view_->GetMenu()->GetSubmenu()->GetMenuItemAt(1));
1991 }
1992 };
1993
1994 VIEW_TEST(BookmarkBarViewTest22, CloseSourceBrowserDuringDrag)
1995
1996 // Tests opening a context menu for a bookmark node from the keyboard.
1997 class BookmarkBarViewTest23 : public BookmarkBarViewEventTestBase {
1998 public:
BookmarkBarViewTest23()1999 BookmarkBarViewTest23()
2000 : observer_(CreateEventTask(this, &BookmarkBarViewTest23::Step4)) {
2001 }
2002
2003 protected:
DoTestOnMessageLoop()2004 void DoTestOnMessageLoop() override {
2005 // Move the mouse to the first folder on the bookmark bar and press the
2006 // mouse.
2007 views::LabelButton* button = bb_view_->other_bookmarks_button();
2008 ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
2009 ui_controls::DOWN | ui_controls::UP,
2010 CreateEventTask(this, &BookmarkBarViewTest23::Step2));
2011 }
2012
2013 private:
Step2()2014 void Step2() {
2015 // Menu should be showing.
2016 views::MenuItemView* menu = bb_view_->GetMenu();
2017 ASSERT_TRUE(menu);
2018 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
2019
2020 // Navigate down to highlight the first menu item.
2021 ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone(
2022 window()->GetNativeWindow(), ui::VKEY_DOWN, false, false, false, false,
2023 CreateEventTask(this, &BookmarkBarViewTest23::Step3)));
2024 }
2025
Step3()2026 void Step3() {
2027 // Menu should be showing.
2028 views::MenuItemView* menu = bb_view_->GetMenu();
2029 ASSERT_TRUE(menu);
2030 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
2031
2032 // Open the context menu via the keyboard.
2033 ASSERT_TRUE(ui_controls::SendKeyPress(window()->GetNativeWindow(),
2034 ui::VKEY_APPS, false, false, false,
2035 false));
2036 // The BookmarkContextMenuNotificationObserver triggers Step4.
2037 }
2038
Step4()2039 void Step4() {
2040 // Make sure the context menu is showing.
2041 views::MenuItemView* menu = bb_view_->GetContextMenu();
2042 ASSERT_TRUE(menu);
2043 ASSERT_TRUE(menu->GetSubmenu());
2044 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
2045
2046 // Select the first menu item (open).
2047 ui_test_utils::MoveMouseToCenterAndPress(
2048 menu->GetSubmenu()->GetMenuItemAt(0),
2049 ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
2050 CreateEventTask(this, &BookmarkBarViewTest23::Step5));
2051 }
2052
Step5()2053 void Step5() {
2054 EXPECT_EQ(navigator_.last_url(),
2055 model_->other_node()->children().front()->url());
2056 ASSERT_FALSE(PageTransitionIsWebTriggerable(navigator_.last_transition()));
2057 Done();
2058 }
2059
2060 BookmarkContextMenuNotificationObserver observer_;
2061 };
2062
2063 #if defined(OS_WIN) // Fails on latest versions of Windows.
2064 // https://crbug.com/1108551.
2065 #define MAYBE_ContextMenusKeyboard DISABLED_ContextMenusKeyboard
2066 #else
2067 #define MAYBE_ContextMenusKeyboard ContextMenusKeyboard
2068 #endif
2069 VIEW_TEST(BookmarkBarViewTest23, MAYBE_ContextMenusKeyboard)
2070
2071 // Test that pressing escape on a menu opened via the keyboard dismisses the
2072 // context menu but not the parent menu.
2073 class BookmarkBarViewTest24 : public BookmarkBarViewEventTestBase {
2074 public:
BookmarkBarViewTest24()2075 BookmarkBarViewTest24()
2076 : observer_(CreateEventTask(this, &BookmarkBarViewTest24::Step4)) {}
2077
2078 protected:
DoTestOnMessageLoop()2079 void DoTestOnMessageLoop() override {
2080 // Move the mouse to the first folder on the bookmark bar and press the
2081 // mouse.
2082 views::LabelButton* button = bb_view_->other_bookmarks_button();
2083 ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
2084 ui_controls::DOWN | ui_controls::UP,
2085 CreateEventTask(this, &BookmarkBarViewTest24::Step2));
2086 }
2087
2088 private:
Step2()2089 void Step2() {
2090 // Menu should be showing.
2091 views::MenuItemView* menu = bb_view_->GetMenu();
2092 ASSERT_TRUE(menu);
2093 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
2094
2095 // Navigate down to highlight the first menu item.
2096 ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone(
2097 window()->GetNativeWindow(), ui::VKEY_DOWN, false, false, false, false,
2098 CreateEventTask(this, &BookmarkBarViewTest24::Step3)));
2099 }
2100
Step3()2101 void Step3() {
2102 // Menu should be showing.
2103 views::MenuItemView* menu = bb_view_->GetMenu();
2104 ASSERT_TRUE(menu);
2105 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
2106
2107 // Open the context menu via the keyboard.
2108 ASSERT_TRUE(ui_controls::SendKeyPress(window()->GetNativeWindow(),
2109 ui::VKEY_APPS, false, false, false,
2110 false));
2111 // The BookmarkContextMenuNotificationObserver triggers Step4.
2112 }
2113
Step4()2114 void Step4() {
2115 // Make sure the context menu is showing.
2116 views::MenuItemView* menu = bb_view_->GetContextMenu();
2117 ASSERT_TRUE(menu);
2118 ASSERT_TRUE(menu->GetSubmenu());
2119 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
2120
2121 // Send escape to close the context menu.
2122 ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone(
2123 window()->GetNativeWindow(), ui::VKEY_ESCAPE, false, false, false,
2124 false, CreateEventTask(this, &BookmarkBarViewTest24::Step5)));
2125 }
2126
Step5()2127 void Step5() {
2128 // The context menu should be closed but the parent menu should still be
2129 // showing.
2130 ASSERT_FALSE(bb_view_->GetContextMenu());
2131
2132 views::MenuItemView* menu = bb_view_->GetMenu();
2133 ASSERT_TRUE(menu);
2134 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
2135
2136 // Send escape to close the main menu.
2137 ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone(
2138 window()->GetNativeWindow(), ui::VKEY_ESCAPE, false, false, false,
2139 false, CreateEventTask(this, &BookmarkBarViewTest24::Done)));
2140 }
2141
2142 BookmarkContextMenuNotificationObserver observer_;
2143 };
2144
2145 #if defined(OS_WIN) // Fails on latest versions of Windows.
2146 // https://crbug.com/1108551.
2147 #define MAYBE_ContextMenusKeyboardEscape DISABLED_ContextMenusKeyboardEscape
2148 #else
2149 #define MAYBE_ContextMenusKeyboardEscape ContextMenusKeyboardEscape
2150 #endif
2151 VIEW_TEST(BookmarkBarViewTest24, MAYBE_ContextMenusKeyboardEscape)
2152
2153 #if defined(OS_WIN)
2154 // Tests that pressing the key KEYCODE closes the menu.
2155 template <ui::KeyboardCode KEYCODE>
2156 class BookmarkBarViewTest25 : public BookmarkBarViewEventTestBase {
2157 protected:
DoTestOnMessageLoop()2158 void DoTestOnMessageLoop() override {
2159 // Move the mouse to the first folder on the bookmark bar and press the
2160 // mouse.
2161 views::LabelButton* button = GetBookmarkButton(0);
2162 ui_test_utils::MoveMouseToCenterAndPress(
2163 button, ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
2164 CreateEventTask(this, &BookmarkBarViewTest25::Step2));
2165 }
2166
2167 private:
Step2()2168 void Step2() {
2169 // Menu should be showing.
2170 views::MenuItemView* menu = bb_view_->GetMenu();
2171 ASSERT_TRUE(menu);
2172 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
2173
2174 // Send KEYCODE key event, which should close the menu.
2175 ASSERT_TRUE(ui_controls::SendKeyPressNotifyWhenDone(
2176 window()->GetNativeWindow(), KEYCODE, false, false, false, false,
2177 CreateEventTask(this, &BookmarkBarViewTest25::Step3)));
2178 }
2179
Step3()2180 void Step3() {
2181 // Make sure menu is not showing.
2182 views::MenuItemView* menu = bb_view_->GetMenu();
2183 ASSERT_TRUE(menu == nullptr);
2184
2185 Done();
2186 }
2187 };
2188
2189 // Tests that pressing F10 system key closes the menu.
2190 using BookmarkBarViewTest25F10 = BookmarkBarViewTest25<ui::VKEY_F10>;
2191 VIEW_TEST(BookmarkBarViewTest25F10, F10ClosesMenu)
2192
2193 // Tests that pressing Alt system key closes the menu.
2194 using BookmarkBarViewTest25Alt = BookmarkBarViewTest25<ui::VKEY_MENU>;
2195 VIEW_TEST(BookmarkBarViewTest25Alt, AltClosesMenu)
2196
2197 // Tests that WM_CANCELMODE closes the menu.
2198 class BookmarkBarViewTest26 : public BookmarkBarViewEventTestBase {
2199 protected:
DoTestOnMessageLoop()2200 void DoTestOnMessageLoop() override {
2201 // Move the mouse to the first folder on the bookmark bar and press the
2202 // mouse.
2203 views::LabelButton* button = GetBookmarkButton(0);
2204 ui_test_utils::MoveMouseToCenterAndPress(
2205 button, ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
2206 CreateEventTask(this, &BookmarkBarViewTest26::Step2));
2207 }
2208
2209 private:
Step2()2210 void Step2() {
2211 // Menu should be showing.
2212 views::MenuItemView* menu = bb_view_->GetMenu();
2213 ASSERT_TRUE(menu);
2214 ASSERT_TRUE(menu->GetSubmenu()->IsShowing());
2215
2216 // Send WM_CANCELMODE, which should close the menu. The message is sent
2217 // synchronously, however, we post a task to make sure that the message is
2218 // processed completely before finishing the test.
2219 ::SendMessage(window()->GetNativeView()->GetHost()->GetAcceleratedWidget(),
2220 WM_CANCELMODE, 0, 0);
2221
2222 base::ThreadTaskRunnerHandle::Get()->PostTask(
2223 FROM_HERE,
2224 base::BindOnce(&BookmarkBarViewTest26::Step3, base::Unretained(this)));
2225 }
2226
Step3()2227 void Step3() {
2228 // Menu should not be showing anymore.
2229 views::MenuItemView* menu = bb_view_->GetMenu();
2230 ASSERT_TRUE(menu == nullptr);
2231
2232 Done();
2233 }
2234 };
2235
2236 VIEW_TEST(BookmarkBarViewTest26, CancelModeClosesMenu)
2237 #endif
2238
2239 class BookmarkBarViewTest27 : public BookmarkBarViewEventTestBase {
2240 protected:
DoTestOnMessageLoop()2241 void DoTestOnMessageLoop() override {
2242 views::LabelButton* button = GetBookmarkButton(0);
2243 ui_test_utils::MoveMouseToCenterAndPress(
2244 button, ui_controls::MIDDLE, ui_controls::DOWN | ui_controls::UP,
2245 CreateEventTask(this, &BookmarkBarViewTest27::Step2));
2246 }
2247
2248 private:
Step2()2249 void Step2() {
2250 ASSERT_EQ(2u, navigator_.urls().size());
2251 EXPECT_EQ(navigator_.urls()[0],
2252 model_->bookmark_bar_node()->children()[0]->children()[0]->url());
2253 EXPECT_EQ(navigator_.urls()[1],
2254 model_->bookmark_bar_node()->children()[0]->children()[2]->url());
2255 Done();
2256 }
2257 };
2258
2259 VIEW_TEST(BookmarkBarViewTest27, MiddleClickOnFolderOpensAllBookmarks)
2260
2261 #endif // defined(OS_MAC)
2262
2263 class BookmarkBarViewTest28 : public BookmarkBarViewEventTestBase {
2264 protected:
2265 #if defined(OS_MAC)
2266 const ui_controls::AcceleratorState kAccelatorState = ui_controls::kCommand;
2267 #else
2268 const ui_controls::AcceleratorState kAccelatorState = ui_controls::kControl;
2269 #endif // defined(OS_MAC)
2270
DoTestOnMessageLoop()2271 void DoTestOnMessageLoop() override {
2272 views::LabelButton* button = GetBookmarkButton(0);
2273 ui_test_utils::MoveMouseToCenterAndPress(
2274 button, ui_controls::LEFT, ui_controls::UP | ui_controls::DOWN,
2275 CreateEventTask(this, &BookmarkBarViewTest28::Step2), kAccelatorState);
2276 }
2277
2278 private:
Step2()2279 void Step2() {
2280 ASSERT_EQ(2u, navigator_.urls().size());
2281 EXPECT_EQ(navigator_.urls()[0],
2282 model_->bookmark_bar_node()->children()[0]->children()[0]->url());
2283 EXPECT_EQ(navigator_.urls()[1],
2284 model_->bookmark_bar_node()->children()[0]->children()[2]->url());
2285 Done();
2286 }
2287 };
2288
2289 VIEW_TEST(BookmarkBarViewTest28, ClickWithModifierOnFolderOpensAllBookmarks)
2290