Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(572)

Side by Side Diff: ui/views/controls/menu/menu_controller_unittest.cc

Issue 2779373002: Remove Nested Message Loop from MenuController (Closed)
Patch Set: unneeded runloop Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/views/controls/menu/menu_controller.cc ('k') | ui/views/controls/menu/menu_message_loop.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/views/controls/menu/menu_controller.h" 5 #include "ui/views/controls/menu/menu_controller.h"
6 6
7 #include "base/callback.h" 7 #include "base/callback.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/macros.h" 9 #include "base/macros.h"
10 #include "base/single_thread_task_runner.h" 10 #include "base/single_thread_task_runner.h"
11 #include "base/strings/utf_string_conversions.h" 11 #include "base/strings/utf_string_conversions.h"
12 #include "base/threading/thread_task_runner_handle.h" 12 #include "base/threading/thread_task_runner_handle.h"
13 #include "build/build_config.h" 13 #include "build/build_config.h"
14 #include "ui/aura/scoped_window_targeter.h" 14 #include "ui/aura/scoped_window_targeter.h"
15 #include "ui/aura/window.h" 15 #include "ui/aura/window.h"
16 #include "ui/events/event.h" 16 #include "ui/events/event.h"
17 #include "ui/events/event_constants.h" 17 #include "ui/events/event_constants.h"
18 #include "ui/events/event_handler.h" 18 #include "ui/events/event_handler.h"
19 #include "ui/events/event_utils.h" 19 #include "ui/events/event_utils.h"
20 #include "ui/events/null_event_targeter.h" 20 #include "ui/events/null_event_targeter.h"
21 #include "ui/events/test/event_generator.h" 21 #include "ui/events/test/event_generator.h"
22 #include "ui/gfx/geometry/point.h" 22 #include "ui/gfx/geometry/point.h"
23 #include "ui/gfx/geometry/rect.h" 23 #include "ui/gfx/geometry/rect.h"
24 #include "ui/views/controls/menu/menu_controller_delegate.h" 24 #include "ui/views/controls/menu/menu_controller_delegate.h"
25 #include "ui/views/controls/menu/menu_delegate.h" 25 #include "ui/views/controls/menu/menu_delegate.h"
26 #include "ui/views/controls/menu/menu_host.h" 26 #include "ui/views/controls/menu/menu_host.h"
27 #include "ui/views/controls/menu/menu_host_root_view.h" 27 #include "ui/views/controls/menu/menu_host_root_view.h"
28 #include "ui/views/controls/menu/menu_item_view.h" 28 #include "ui/views/controls/menu/menu_item_view.h"
29 #include "ui/views/controls/menu/menu_message_loop.h"
30 #include "ui/views/controls/menu/menu_scroll_view_container.h" 29 #include "ui/views/controls/menu/menu_scroll_view_container.h"
31 #include "ui/views/controls/menu/submenu_view.h" 30 #include "ui/views/controls/menu/submenu_view.h"
32 #include "ui/views/test/menu_test_utils.h" 31 #include "ui/views/test/menu_test_utils.h"
33 #include "ui/views/test/test_views_delegate.h" 32 #include "ui/views/test/test_views_delegate.h"
34 #include "ui/views/test/views_test_base.h" 33 #include "ui/views/test/views_test_base.h"
35 #include "ui/views/widget/root_view.h" 34 #include "ui/views/widget/root_view.h"
36 35
37 #if defined(USE_AURA) 36 #if defined(USE_AURA)
38 #include "ui/aura/client/drag_drop_client.h" 37 #include "ui/aura/client/drag_drop_client.h"
39 #include "ui/aura/scoped_window_targeter.h" 38 #include "ui/aura/scoped_window_targeter.h"
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 } 145 }
147 } 146 }
148 147
149 int outstanding_touches() const { return outstanding_touches_; } 148 int outstanding_touches() const { return outstanding_touches_; }
150 149
151 private: 150 private:
152 int outstanding_touches_; 151 int outstanding_touches_;
153 DISALLOW_COPY_AND_ASSIGN(TestEventHandler); 152 DISALLOW_COPY_AND_ASSIGN(TestEventHandler);
154 }; 153 };
155 154
156 // A wrapper around MenuMessageLoop that can be used to track whether a message
157 // loop is running or not.
158 class TestMenuMessageLoop : public MenuMessageLoop {
159 public:
160 explicit TestMenuMessageLoop(std::unique_ptr<MenuMessageLoop> original);
161 ~TestMenuMessageLoop() override;
162
163 bool is_running() const { return is_running_; }
164
165 // MenuMessageLoop:
166 void QuitNow() override;
167
168 private:
169 // MenuMessageLoop:
170 void Run() override;
171
172 std::unique_ptr<MenuMessageLoop> original_;
173 bool is_running_;
174
175 DISALLOW_COPY_AND_ASSIGN(TestMenuMessageLoop);
176 };
177
178 TestMenuMessageLoop::TestMenuMessageLoop(
179 std::unique_ptr<MenuMessageLoop> original)
180 : original_(std::move(original)) {
181 DCHECK(original_);
182 }
183
184 TestMenuMessageLoop::~TestMenuMessageLoop() {}
185
186 void TestMenuMessageLoop::Run() {
187 is_running_ = true;
188 original_->Run();
189 }
190
191 void TestMenuMessageLoop::QuitNow() {
192 is_running_ = false;
193 original_->QuitNow();
194 }
195
196 #if defined(USE_AURA) 155 #if defined(USE_AURA)
197 // A DragDropClient which does not trigger a nested message loop. Instead a 156 // A DragDropClient which does not trigger a nested message loop. Instead a
198 // callback is triggered during StartDragAndDrop in order to allow testing. 157 // callback is triggered during StartDragAndDrop in order to allow testing.
199 class TestDragDropClient : public aura::client::DragDropClient { 158 class TestDragDropClient : public aura::client::DragDropClient {
200 public: 159 public:
201 explicit TestDragDropClient(const base::Closure& callback) 160 explicit TestDragDropClient(const base::Closure& callback)
202 : start_drag_and_drop_callback_(callback), drag_in_progress_(false) {} 161 : start_drag_and_drop_callback_(callback), drag_in_progress_(false) {}
203 ~TestDragDropClient() override {} 162 ~TestDragDropClient() override {}
204 163
205 // aura::client::DragDropClient: 164 // aura::client::DragDropClient:
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 } 269 }
311 270
312 void ReleaseTouchId(int id) { 271 void ReleaseTouchId(int id) {
313 event_generator_->ReleaseTouchId(id); 272 event_generator_->ReleaseTouchId(id);
314 } 273 }
315 274
316 void PressKey(ui::KeyboardCode key_code) { 275 void PressKey(ui::KeyboardCode key_code) {
317 event_generator_->PressKey(key_code, 0); 276 event_generator_->PressKey(key_code, 0);
318 } 277 }
319 278
320 #if defined(OS_LINUX) && defined(USE_X11)
321 void TestEventTargeter() {
322 {
323 // With the |ui::NullEventTargeter| instantiated and assigned we expect
324 // the menu to not handle the key event.
325 aura::ScopedWindowTargeter scoped_targeter(
326 owner()->GetNativeWindow()->GetRootWindow(),
327 std::unique_ptr<ui::EventTargeter>(new ui::NullEventTargeter));
328 event_generator_->PressKey(ui::VKEY_ESCAPE, 0);
329 EXPECT_EQ(MenuController::EXIT_NONE, menu_exit_type());
330 }
331 // Now that the targeter has been destroyed, expect to exit the menu
332 // normally when hitting escape.
333 event_generator_->PressKey(ui::VKEY_ESCAPE, 0);
334 EXPECT_EQ(MenuController::EXIT_ALL, menu_exit_type());
335 }
336 #endif // defined(OS_LINUX) && defined(USE_X11
337
338 #if defined(USE_AURA) 279 #if defined(USE_AURA)
339 // Verifies that a non-nested menu fully closes when receiving an escape key. 280 // Verifies that a non-nested menu fully closes when receiving an escape key.
340 void TestAsyncEscapeKey() { 281 void TestAsyncEscapeKey() {
341 ui::KeyEvent event(ui::EventType::ET_KEY_PRESSED, ui::VKEY_ESCAPE, 0); 282 ui::KeyEvent event(ui::EventType::ET_KEY_PRESSED, ui::VKEY_ESCAPE, 0);
342 menu_controller_->OnWillDispatchKeyEvent(&event); 283 menu_controller_->OnWillDispatchKeyEvent(&event);
343 } 284 }
344 285
345 // Verifies that an open menu receives a cancel event, and closes. 286 // Verifies that an open menu receives a cancel event, and closes.
346 void TestCancelEvent() { 287 void TestCancelEvent() {
347 EXPECT_EQ(MenuController::EXIT_NONE, menu_controller_->exit_type()); 288 EXPECT_EQ(MenuController::EXIT_NONE, menu_controller_->exit_type());
(...skipping 11 matching lines...) Expand all
359 } 300 }
360 301
361 // Setups |menu_controller_delegate_| to be destroyed when OnMenuClosed is 302 // Setups |menu_controller_delegate_| to be destroyed when OnMenuClosed is
362 // called. 303 // called.
363 void TestDragCompleteThenDestroyOnMenuClosed() { 304 void TestDragCompleteThenDestroyOnMenuClosed() {
364 menu_controller_delegate_->set_on_menu_closed_callback( 305 menu_controller_delegate_->set_on_menu_closed_callback(
365 base::Bind(&MenuControllerTest::VerifyDragCompleteThenDestroy, 306 base::Bind(&MenuControllerTest::VerifyDragCompleteThenDestroy,
366 base::Unretained(this))); 307 base::Unretained(this)));
367 } 308 }
368 309
369 void TestAsynchronousNestedExitAll() {
370 ASSERT_TRUE(test_message_loop_->is_running());
371
372 std::unique_ptr<TestMenuControllerDelegate> nested_delegate(
373 new TestMenuControllerDelegate());
374
375 menu_controller()->AddNestedDelegate(nested_delegate.get());
376 menu_controller()->SetAsyncRun(true);
377
378 int mouse_event_flags = 0;
379 MenuItemView* run_result = menu_controller()->Run(
380 owner(), nullptr, menu_item(), gfx::Rect(), MENU_ANCHOR_TOPLEFT, false,
381 false, &mouse_event_flags);
382 EXPECT_EQ(run_result, nullptr);
383
384 // Exit all menus and check that the parent menu's message loop is
385 // terminated.
386 menu_controller()->Cancel(MenuController::EXIT_ALL);
387 EXPECT_EQ(MenuController::EXIT_ALL, menu_controller()->exit_type());
388 EXPECT_FALSE(test_message_loop_->is_running());
389 }
390
391 void TestAsynchronousNestedExitOutermost() {
392 ASSERT_TRUE(test_message_loop_->is_running());
393
394 std::unique_ptr<TestMenuControllerDelegate> nested_delegate(
395 new TestMenuControllerDelegate());
396
397 menu_controller()->AddNestedDelegate(nested_delegate.get());
398 menu_controller()->SetAsyncRun(true);
399
400 int mouse_event_flags = 0;
401 MenuItemView* run_result = menu_controller()->Run(
402 owner(), nullptr, menu_item(), gfx::Rect(), MENU_ANCHOR_TOPLEFT, false,
403 false, &mouse_event_flags);
404 EXPECT_EQ(run_result, nullptr);
405
406 // Exit the nested menu and check that the parent menu's message loop is
407 // still running.
408 menu_controller()->Cancel(MenuController::EXIT_OUTERMOST);
409 EXPECT_EQ(MenuController::EXIT_NONE, menu_controller()->exit_type());
410 EXPECT_TRUE(test_message_loop_->is_running());
411
412 // Now, exit the parent menu and check that its message loop is terminated.
413 menu_controller()->Cancel(MenuController::EXIT_OUTERMOST);
414 EXPECT_EQ(MenuController::EXIT_OUTERMOST, menu_controller()->exit_type());
415 EXPECT_FALSE(test_message_loop_->is_running());
416 }
417
418 // This nested an asynchronous delegate onto a menu with a nested message
419 // loop, then kills the loop. Simulates the loop being killed not by
420 // MenuController.
421 void TestNestedMessageLoopKillsItself(
422 TestMenuControllerDelegate* nested_delegate) {
423 menu_controller_->AddNestedDelegate(nested_delegate);
424 menu_controller_->SetAsyncRun(true);
425
426 test_message_loop_->QuitNow();
427 }
428
429 // Tests destroying the active |menu_controller_| and replacing it with a new 310 // Tests destroying the active |menu_controller_| and replacing it with a new
430 // active instance. 311 // active instance.
431 void TestMenuControllerReplacementDuringDrag() { 312 void TestMenuControllerReplacementDuringDrag() {
432 DestroyMenuController(); 313 DestroyMenuController();
433 menu_item()->GetSubmenu()->Close(); 314 menu_item()->GetSubmenu()->Close();
434 menu_controller_ = 315 menu_controller_ =
435 new MenuController(true, menu_controller_delegate_.get()); 316 new MenuController(true, menu_controller_delegate_.get());
436 menu_controller_->owner_ = owner_.get(); 317 menu_controller_->owner_ = owner_.get();
437 menu_controller_->showing_ = true; 318 menu_controller_->showing_ = true;
438 } 319 }
439 320
440 // Tests that the menu does not destroy itself when canceled during a drag. 321 // Tests that the menu does not destroy itself when canceled during a drag.
441 void TestCancelAllDuringDrag() { 322 void TestCancelAllDuringDrag() {
442 menu_controller_->CancelAll(); 323 menu_controller_->CancelAll();
443 EXPECT_EQ(0, menu_controller_delegate_->on_menu_closed_called()); 324 EXPECT_EQ(0, menu_controller_delegate_->on_menu_closed_called());
444 } 325 }
445 326
446 // Tests that destroying the menu during ViewsDelegate::ReleaseRef does not 327 // Tests that destroying the menu during ViewsDelegate::ReleaseRef does not
447 // cause a crash. 328 // cause a crash.
448 void TestDestroyedDuringViewsRelease() { 329 void TestDestroyedDuringViewsRelease() {
449 // |test_views_delegate_| is owned by views::ViewsTestBase and not deleted 330 // |test_views_delegate_| is owned by views::ViewsTestBase and not deleted
450 // until TearDown. MenuControllerTest outlives it. 331 // until TearDown. MenuControllerTest outlives it.
451 test_views_delegate_->set_release_ref_callback(base::Bind( 332 test_views_delegate_->set_release_ref_callback(base::Bind(
452 &MenuControllerTest::DestroyMenuController, base::Unretained(this))); 333 &MenuControllerTest::DestroyMenuController, base::Unretained(this)));
453 menu_controller_->ExitAsyncRun(); 334 menu_controller_->ExitMenu();
454 } 335 }
455 336
456 protected: 337 protected:
457 void SetPendingStateItem(MenuItemView* item) { 338 void SetPendingStateItem(MenuItemView* item) {
458 menu_controller_->pending_state_.item = item; 339 menu_controller_->pending_state_.item = item;
459 menu_controller_->pending_state_.submenu_open = true; 340 menu_controller_->pending_state_.submenu_open = true;
460 } 341 }
461 342
462 void SetState(MenuItemView* item) { 343 void SetState(MenuItemView* item) {
463 menu_controller_->state_.item = item; 344 menu_controller_->state_.item = item;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
508 MenuItemView* FindPreviousSelectableMenuItem(MenuItemView* parent, 389 MenuItemView* FindPreviousSelectableMenuItem(MenuItemView* parent,
509 int index) { 390 int index) {
510 return menu_controller_->FindNextSelectableMenuItem( 391 return menu_controller_->FindNextSelectableMenuItem(
511 parent, index, MenuController::INCREMENT_SELECTION_UP); 392 parent, index, MenuController::INCREMENT_SELECTION_UP);
512 } 393 }
513 394
514 internal::MenuControllerDelegate* GetCurrentDelegate() { 395 internal::MenuControllerDelegate* GetCurrentDelegate() {
515 return menu_controller_->delegate_; 396 return menu_controller_->delegate_;
516 } 397 }
517 398
518 bool IsAsyncRun() { return menu_controller_->async_run_; }
519
520 bool IsShowing() { return menu_controller_->showing_; } 399 bool IsShowing() { return menu_controller_->showing_; }
521 400
522 MenuHost* GetMenuHost(SubmenuView* submenu) { return submenu->host_; } 401 MenuHost* GetMenuHost(SubmenuView* submenu) { return submenu->host_; }
523 402
524 MenuHostRootView* CreateMenuHostRootView(MenuHost* host) { 403 MenuHostRootView* CreateMenuHostRootView(MenuHost* host) {
525 return static_cast<MenuHostRootView*>(host->CreateRootView()); 404 return static_cast<MenuHostRootView*>(host->CreateRootView());
526 } 405 }
527 406
528 void MenuHostOnDragWillStart(MenuHost* host) { host->OnDragWillStart(); } 407 void MenuHostOnDragWillStart(MenuHost* host) { host->OnDragWillStart(); }
529 408
(...skipping 28 matching lines...) Expand all
558 } 437 }
559 438
560 void ProcessMouseMoved(SubmenuView* source, const ui::MouseEvent& event) { 439 void ProcessMouseMoved(SubmenuView* source, const ui::MouseEvent& event) {
561 menu_controller_->OnMouseMoved(source, event); 440 menu_controller_->OnMouseMoved(source, event);
562 } 441 }
563 442
564 void ProcessMouseReleased(SubmenuView* source, const ui::MouseEvent& event) { 443 void ProcessMouseReleased(SubmenuView* source, const ui::MouseEvent& event) {
565 menu_controller_->OnMouseReleased(source, event); 444 menu_controller_->OnMouseReleased(source, event);
566 } 445 }
567 446
568 void RunMenu() {
569 #if defined(USE_AURA)
570 std::unique_ptr<MenuPreTargetHandler> menu_pre_target_handler(
571 new MenuPreTargetHandler(menu_controller_, owner_.get()));
572 #endif
573
574 menu_controller_->message_loop_depth_++;
575 menu_controller_->RunMessageLoop();
576 menu_controller_->message_loop_depth_--;
577 }
578
579 void Accept(MenuItemView* item, int event_flags) { 447 void Accept(MenuItemView* item, int event_flags) {
580 menu_controller_->Accept(item, event_flags); 448 menu_controller_->Accept(item, event_flags);
581 } 449 }
582 450
583 void InstallTestMenuMessageLoop() {
584 test_message_loop_ =
585 new TestMenuMessageLoop(std::move(menu_controller_->message_loop_));
586 menu_controller_->message_loop_.reset(test_message_loop_);
587 }
588
589 // Causes the |menu_controller_| to begin dragging. Use TestDragDropClient to 451 // Causes the |menu_controller_| to begin dragging. Use TestDragDropClient to
590 // avoid nesting message loops. 452 // avoid nesting message loops.
591 void StartDrag() { 453 void StartDrag() {
592 const gfx::Point location; 454 const gfx::Point location;
593 menu_controller_->state_.item = menu_item()->GetSubmenu()->GetMenuItemAt(0); 455 menu_controller_->state_.item = menu_item()->GetSubmenu()->GetMenuItemAt(0);
594 menu_controller_->StartDrag( 456 menu_controller_->StartDrag(
595 menu_item()->GetSubmenu()->GetMenuItemAt(0)->CreateSubmenu(), location); 457 menu_item()->GetSubmenu()->GetMenuItemAt(0)->CreateSubmenu(), location);
596 } 458 }
597 459
598 Widget* owner() { return owner_.get(); } 460 Widget* owner() { return owner_.get(); }
(...skipping 30 matching lines...) Expand all
629 CustomButton* GetHotButton() { 491 CustomButton* GetHotButton() {
630 return menu_controller_->hot_button_; 492 return menu_controller_->hot_button_;
631 } 493 }
632 494
633 void SetHotTrackedButton(CustomButton* hot_button) { 495 void SetHotTrackedButton(CustomButton* hot_button) {
634 menu_controller_->SetHotTrackedButton(hot_button); 496 menu_controller_->SetHotTrackedButton(hot_button);
635 } 497 }
636 498
637 void ExitMenuRun() { 499 void ExitMenuRun() {
638 menu_controller_->SetExitType(MenuController::ExitType::EXIT_OUTERMOST); 500 menu_controller_->SetExitType(MenuController::ExitType::EXIT_OUTERMOST);
639 menu_controller_->ExitMenuRun(); 501 menu_controller_->ExitTopMostMenu();
640 } 502 }
641 503
642 void DestroyMenuController() { 504 void DestroyMenuController() {
643 if (!menu_controller_) 505 if (!menu_controller_)
644 return; 506 return;
645 507
646 if (!owner_->IsClosed()) 508 if (!owner_->IsClosed())
647 owner_->RemoveObserver(menu_controller_); 509 owner_->RemoveObserver(menu_controller_);
648 510
649 menu_controller_->showing_ = false; 511 menu_controller_->showing_ = false;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
688 550
689 // Not owned. 551 // Not owned.
690 DestructingTestViewsDelegate* test_views_delegate_; 552 DestructingTestViewsDelegate* test_views_delegate_;
691 553
692 std::unique_ptr<Widget> owner_; 554 std::unique_ptr<Widget> owner_;
693 std::unique_ptr<ui::test::EventGenerator> event_generator_; 555 std::unique_ptr<ui::test::EventGenerator> event_generator_;
694 std::unique_ptr<TestMenuItemViewShown> menu_item_; 556 std::unique_ptr<TestMenuItemViewShown> menu_item_;
695 std::unique_ptr<TestMenuControllerDelegate> menu_controller_delegate_; 557 std::unique_ptr<TestMenuControllerDelegate> menu_controller_delegate_;
696 std::unique_ptr<TestMenuDelegate> menu_delegate_; 558 std::unique_ptr<TestMenuDelegate> menu_delegate_;
697 MenuController* menu_controller_; 559 MenuController* menu_controller_;
698 TestMenuMessageLoop* test_message_loop_;
699 560
700 DISALLOW_COPY_AND_ASSIGN(MenuControllerTest); 561 DISALLOW_COPY_AND_ASSIGN(MenuControllerTest);
701 }; 562 };
702 563
703 #if defined(OS_LINUX) && defined(USE_X11) 564 #if defined(OS_LINUX) && defined(USE_X11)
704 // Tests that an event targeter which blocks events will be honored by the menu 565 // Tests that an event targeter which blocks events will be honored by the menu
705 // event dispatcher. 566 // event dispatcher.
706 TEST_F(MenuControllerTest, EventTargeter) { 567 TEST_F(MenuControllerTest, EventTargeter) {
707 base::ThreadTaskRunnerHandle::Get()->PostTask( 568 {
708 FROM_HERE, base::Bind(&MenuControllerTest::TestEventTargeter, 569 // With the |ui::NullEventTargeter| instantiated and assigned we expect
709 base::Unretained(this))); 570 // the menu to not handle the key event.
710 RunMenu(); 571 aura::ScopedWindowTargeter scoped_targeter(
711 } 572 owner()->GetNativeWindow()->GetRootWindow(),
712 573 std::unique_ptr<ui::EventTargeter>(new ui::NullEventTargeter));
713 // Tests that an non-nested menu receiving an escape key will fully shut. This 574 PressKey(ui::VKEY_ESCAPE);
714 // should not crash by attempting to retarget the key to an inner menu. 575 EXPECT_EQ(MenuController::EXIT_NONE, menu_exit_type());
715 TEST_F(MenuControllerTest, AsyncEscapeKey) { 576 }
716 menu_controller()->SetAsyncRun(true); 577 // Now that the targeter has been destroyed, expect to exit the menu
578 // normally when hitting escape.
717 TestAsyncEscapeKey(); 579 TestAsyncEscapeKey();
718 EXPECT_EQ(MenuController::EXIT_ALL, menu_exit_type()); 580 EXPECT_EQ(MenuController::EXIT_ALL, menu_exit_type());
719 } 581 }
720 582
721 #endif // defined(OS_LINUX) && defined(USE_X11) 583 #endif // defined(OS_LINUX) && defined(USE_X11)
722 584
723 #if defined(USE_X11) 585 #if defined(USE_X11)
724 // Tests that touch event ids are released correctly. See crbug.com/439051 for 586 // Tests that touch event ids are released correctly. See crbug.com/439051 for
725 // details. When the ids aren't managed correctly, we get stuck down touches. 587 // details. When the ids aren't managed correctly, we get stuck down touches.
726 TEST_F(MenuControllerTest, TouchIdsReleasedCorrectly) { 588 TEST_F(MenuControllerTest, TouchIdsReleasedCorrectly) {
727 TestEventHandler test_event_handler; 589 TestEventHandler test_event_handler;
728 owner()->GetNativeWindow()->GetRootWindow()->AddPreTargetHandler( 590 owner()->GetNativeWindow()->GetRootWindow()->AddPreTargetHandler(
729 &test_event_handler); 591 &test_event_handler);
730 592
731 std::vector<int> devices; 593 std::vector<int> devices;
732 devices.push_back(1); 594 devices.push_back(1);
733 ui::SetUpTouchDevicesForTest(devices); 595 ui::SetUpTouchDevicesForTest(devices);
734 596
735 event_generator()->PressTouchId(0); 597 event_generator()->PressTouchId(0);
736 event_generator()->PressTouchId(1); 598 event_generator()->PressTouchId(1);
737 event_generator()->ReleaseTouchId(0); 599 event_generator()->ReleaseTouchId(0);
738 600
739 base::ThreadTaskRunnerHandle::Get()->PostTask( 601 int mouse_event_flags = 0;
740 FROM_HERE, base::Bind(&MenuControllerTest::ReleaseTouchId, 602 MenuItemView* run_result = menu_controller()->Run(
741 base::Unretained(this), 1)); 603 owner(), nullptr, menu_item(), gfx::Rect(), MENU_ANCHOR_TOPLEFT, false,
604 false, &mouse_event_flags);
605 EXPECT_EQ(run_result, nullptr);
742 606
743 base::ThreadTaskRunnerHandle::Get()->PostTask( 607 MenuControllerTest::ReleaseTouchId(1);
744 FROM_HERE, base::Bind(&MenuControllerTest::PressKey, 608 TestAsyncEscapeKey();
745 base::Unretained(this), ui::VKEY_ESCAPE));
746
747 RunMenu();
748 609
749 EXPECT_EQ(MenuController::EXIT_ALL, menu_exit_type()); 610 EXPECT_EQ(MenuController::EXIT_ALL, menu_exit_type());
750 EXPECT_EQ(0, test_event_handler.outstanding_touches()); 611 EXPECT_EQ(0, test_event_handler.outstanding_touches());
751 612
752 owner()->GetNativeWindow()->GetRootWindow()->RemovePreTargetHandler( 613 owner()->GetNativeWindow()->GetRootWindow()->RemovePreTargetHandler(
753 &test_event_handler); 614 &test_event_handler);
754 } 615 }
755 #endif // defined(USE_X11) 616 #endif // defined(USE_X11)
756 617
757 // Tests that initial selected menu items are correct when items are enabled or 618 // Tests that initial selected menu items are correct when items are enabled or
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after
1045 // Increment twice to move selection to |button2|. 906 // Increment twice to move selection to |button2|.
1046 IncrementSelection(); 907 IncrementSelection();
1047 IncrementSelection(); 908 IncrementSelection();
1048 EXPECT_EQ(5, pending_state_item()->GetCommand()); 909 EXPECT_EQ(5, pending_state_item()->GetCommand());
1049 EXPECT_FALSE(button1->IsHotTracked()); 910 EXPECT_FALSE(button1->IsHotTracked());
1050 EXPECT_TRUE(button2->IsHotTracked()); 911 EXPECT_TRUE(button2->IsHotTracked());
1051 EXPECT_FALSE(button3->IsHotTracked()); 912 EXPECT_FALSE(button3->IsHotTracked());
1052 EXPECT_EQ(button2, GetHotButton()); 913 EXPECT_EQ(button2, GetHotButton());
1053 914
1054 MenuController* controller = menu_controller(); 915 MenuController* controller = menu_controller();
1055 controller->SetAsyncRun(true);
1056 int mouse_event_flags = 0; 916 int mouse_event_flags = 0;
1057 MenuItemView* run_result = 917 MenuItemView* run_result =
1058 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(), 918 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(),
1059 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags); 919 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags);
1060 EXPECT_EQ(run_result, nullptr); 920 EXPECT_EQ(run_result, nullptr);
1061 921
1062 // |button2| should stay in hot-tracked state but menu controller should not 922 // |button2| should stay in hot-tracked state but menu controller should not
1063 // track it anymore (preventing resetting hot-tracked state when changing 923 // track it anymore (preventing resetting hot-tracked state when changing
1064 // selection while a nested run is active). 924 // selection while a nested run is active).
1065 EXPECT_TRUE(button2->IsHotTracked()); 925 EXPECT_TRUE(button2->IsHotTracked());
1066 EXPECT_EQ(nullptr, GetHotButton()); 926 EXPECT_EQ(nullptr, GetHotButton());
1067 927
1068 // Setting hot-tracked button while nested should get reverted when nested 928 // Setting hot-tracked button while nested should get reverted when nested
1069 // menu run ends. 929 // menu run ends.
1070 SetHotTrackedButton(button1); 930 SetHotTrackedButton(button1);
1071 EXPECT_TRUE(button1->IsHotTracked()); 931 EXPECT_TRUE(button1->IsHotTracked());
1072 EXPECT_EQ(button1, GetHotButton()); 932 EXPECT_EQ(button1, GetHotButton());
1073 933
1074 ExitMenuRun(); 934 ExitMenuRun();
1075 EXPECT_FALSE(button1->IsHotTracked()); 935 EXPECT_FALSE(button1->IsHotTracked());
1076 EXPECT_TRUE(button2->IsHotTracked()); 936 EXPECT_TRUE(button2->IsHotTracked());
1077 EXPECT_EQ(button2, GetHotButton()); 937 EXPECT_EQ(button2, GetHotButton());
1078 } 938 }
1079 939
1080 // Tests that a menu opened asynchronously, will notify its 940 // Tests that a menu opened asynchronously, will notify its
1081 // MenuControllerDelegate when Accept is called. 941 // MenuControllerDelegate when Accept is called.
1082 TEST_F(MenuControllerTest, AsynchronousAccept) { 942 TEST_F(MenuControllerTest, AsynchronousAccept) {
1083 MenuController* controller = menu_controller(); 943 MenuController* controller = menu_controller();
1084 controller->SetAsyncRun(true);
1085 944
1086 int mouse_event_flags = 0; 945 int mouse_event_flags = 0;
1087 MenuItemView* run_result = 946 MenuItemView* run_result =
1088 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(), 947 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(),
1089 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags); 948 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags);
1090 EXPECT_EQ(run_result, nullptr); 949 EXPECT_EQ(run_result, nullptr);
1091 TestMenuControllerDelegate* delegate = menu_controller_delegate(); 950 TestMenuControllerDelegate* delegate = menu_controller_delegate();
1092 EXPECT_EQ(0, delegate->on_menu_closed_called()); 951 EXPECT_EQ(0, delegate->on_menu_closed_called());
1093 952
1094 MenuItemView* accepted = menu_item()->GetSubmenu()->GetMenuItemAt(0); 953 MenuItemView* accepted = menu_item()->GetSubmenu()->GetMenuItemAt(0);
1095 const int kEventFlags = 42; 954 const int kEventFlags = 42;
1096 Accept(accepted, kEventFlags); 955 Accept(accepted, kEventFlags);
1097 956
1098 EXPECT_EQ(1, delegate->on_menu_closed_called()); 957 EXPECT_EQ(1, delegate->on_menu_closed_called());
1099 EXPECT_EQ(accepted, delegate->on_menu_closed_menu()); 958 EXPECT_EQ(accepted, delegate->on_menu_closed_menu());
1100 EXPECT_EQ(kEventFlags, delegate->on_menu_closed_mouse_event_flags()); 959 EXPECT_EQ(kEventFlags, delegate->on_menu_closed_mouse_event_flags());
1101 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE, 960 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE,
1102 delegate->on_menu_closed_notify_type()); 961 delegate->on_menu_closed_notify_type());
1103 } 962 }
1104 963
1105 // Tests that a menu opened asynchronously, will notify its 964 // Tests that a menu opened asynchronously, will notify its
1106 // MenuControllerDelegate when CancelAll is called. 965 // MenuControllerDelegate when CancelAll is called.
1107 TEST_F(MenuControllerTest, AsynchronousCancelAll) { 966 TEST_F(MenuControllerTest, AsynchronousCancelAll) {
1108 MenuController* controller = menu_controller(); 967 MenuController* controller = menu_controller();
1109 controller->SetAsyncRun(true);
1110 968
1111 int mouse_event_flags = 0; 969 int mouse_event_flags = 0;
1112 MenuItemView* run_result = 970 MenuItemView* run_result =
1113 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(), 971 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(),
1114 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags); 972 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags);
1115 EXPECT_EQ(run_result, nullptr); 973 EXPECT_EQ(run_result, nullptr);
1116 TestMenuControllerDelegate* delegate = menu_controller_delegate(); 974 TestMenuControllerDelegate* delegate = menu_controller_delegate();
1117 EXPECT_EQ(0, delegate->on_menu_closed_called()); 975 EXPECT_EQ(0, delegate->on_menu_closed_called());
1118 976
1119 controller->CancelAll(); 977 controller->CancelAll();
1120 EXPECT_EQ(1, delegate->on_menu_closed_called()); 978 EXPECT_EQ(1, delegate->on_menu_closed_called());
1121 EXPECT_EQ(nullptr, delegate->on_menu_closed_menu()); 979 EXPECT_EQ(nullptr, delegate->on_menu_closed_menu());
1122 EXPECT_EQ(0, delegate->on_menu_closed_mouse_event_flags()); 980 EXPECT_EQ(0, delegate->on_menu_closed_mouse_event_flags());
1123 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE, 981 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE,
1124 delegate->on_menu_closed_notify_type()); 982 delegate->on_menu_closed_notify_type());
1125 EXPECT_EQ(MenuController::EXIT_ALL, controller->exit_type()); 983 EXPECT_EQ(MenuController::EXIT_ALL, controller->exit_type());
1126 } 984 }
1127 985
1128 // Tests that an asynchrnous menu nested within a synchronous menu restores the 986 // Tests that canceling a nested menu restores the previous
1129 // previous MenuControllerDelegate and synchronous settings. 987 // MenuControllerDelegate, and notifies each delegate.
1130 TEST_F(MenuControllerTest, AsynchronousNestedDelegate) { 988 TEST_F(MenuControllerTest, AsynchronousNestedDelegate) {
1131 MenuController* controller = menu_controller(); 989 MenuController* controller = menu_controller();
1132 TestMenuControllerDelegate* delegate = menu_controller_delegate(); 990 TestMenuControllerDelegate* delegate = menu_controller_delegate();
1133 std::unique_ptr<TestMenuControllerDelegate> nested_delegate( 991 std::unique_ptr<TestMenuControllerDelegate> nested_delegate(
1134 new TestMenuControllerDelegate()); 992 new TestMenuControllerDelegate());
1135 993
1136 ASSERT_FALSE(IsAsyncRun());
1137 controller->AddNestedDelegate(nested_delegate.get()); 994 controller->AddNestedDelegate(nested_delegate.get());
1138 controller->SetAsyncRun(true);
1139
1140 EXPECT_TRUE(IsAsyncRun());
1141 EXPECT_EQ(nested_delegate.get(), GetCurrentDelegate()); 995 EXPECT_EQ(nested_delegate.get(), GetCurrentDelegate());
1142 996
1143 int mouse_event_flags = 0; 997 int mouse_event_flags = 0;
1144 MenuItemView* run_result = 998 MenuItemView* run_result =
1145 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(), 999 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(),
1146 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags); 1000 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags);
1147 EXPECT_EQ(run_result, nullptr); 1001 EXPECT_EQ(run_result, nullptr);
1148 1002
1149 controller->CancelAll(); 1003 controller->CancelAll();
1150 EXPECT_FALSE(IsAsyncRun());
1151 EXPECT_EQ(delegate, GetCurrentDelegate()); 1004 EXPECT_EQ(delegate, GetCurrentDelegate());
1152 EXPECT_EQ(0, delegate->on_menu_closed_called()); 1005 EXPECT_EQ(1, delegate->on_menu_closed_called());
1153 EXPECT_EQ(1, nested_delegate->on_menu_closed_called()); 1006 EXPECT_EQ(1, nested_delegate->on_menu_closed_called());
1154 EXPECT_EQ(nullptr, nested_delegate->on_menu_closed_menu()); 1007 EXPECT_EQ(nullptr, nested_delegate->on_menu_closed_menu());
1155 EXPECT_EQ(0, nested_delegate->on_menu_closed_mouse_event_flags()); 1008 EXPECT_EQ(0, nested_delegate->on_menu_closed_mouse_event_flags());
1156 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE, 1009 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE,
1157 nested_delegate->on_menu_closed_notify_type()); 1010 nested_delegate->on_menu_closed_notify_type());
1158 EXPECT_EQ(MenuController::EXIT_ALL, controller->exit_type()); 1011 EXPECT_EQ(MenuController::EXIT_ALL, controller->exit_type());
1159 } 1012 }
1160 1013
1161 // Tests that dropping within an asynchronous menu stops the menu from showing 1014 // Tests that dropping within an asynchronous menu stops the menu from showing
1162 // and does not notify the controller. 1015 // and does not notify the controller.
1163 TEST_F(MenuControllerTest, AsynchronousPerformDrop) { 1016 TEST_F(MenuControllerTest, AsynchronousPerformDrop) {
1164 MenuController* controller = menu_controller(); 1017 MenuController* controller = menu_controller();
1165 controller->SetAsyncRun(true);
1166 SubmenuView* source = menu_item()->GetSubmenu(); 1018 SubmenuView* source = menu_item()->GetSubmenu();
1167 MenuItemView* target = source->GetMenuItemAt(0); 1019 MenuItemView* target = source->GetMenuItemAt(0);
1168 1020
1169 SetDropMenuItem(target, MenuDelegate::DropPosition::DROP_AFTER); 1021 SetDropMenuItem(target, MenuDelegate::DropPosition::DROP_AFTER);
1170 1022
1171 ui::OSExchangeData drop_data; 1023 ui::OSExchangeData drop_data;
1172 gfx::Rect bounds(target->bounds()); 1024 gfx::Rect bounds(target->bounds());
1173 gfx::Point location(bounds.x(), bounds.y()); 1025 gfx::Point location(bounds.x(), bounds.y());
1174 ui::DropTargetEvent target_event(drop_data, location, location, 1026 ui::DropTargetEvent target_event(drop_data, location, location,
1175 ui::DragDropTypes::DRAG_MOVE); 1027 ui::DragDropTypes::DRAG_MOVE);
1176 controller->OnPerformDrop(source, target_event); 1028 controller->OnPerformDrop(source, target_event);
1177 1029
1178 TestMenuDelegate* menu_delegate = 1030 TestMenuDelegate* menu_delegate =
1179 static_cast<TestMenuDelegate*>(target->GetDelegate()); 1031 static_cast<TestMenuDelegate*>(target->GetDelegate());
1180 TestMenuControllerDelegate* controller_delegate = menu_controller_delegate(); 1032 TestMenuControllerDelegate* controller_delegate = menu_controller_delegate();
1181 EXPECT_TRUE(menu_delegate->on_perform_drop_called()); 1033 EXPECT_TRUE(menu_delegate->on_perform_drop_called());
1182 EXPECT_FALSE(IsShowing()); 1034 EXPECT_FALSE(IsShowing());
1183 EXPECT_EQ(0, controller_delegate->on_menu_closed_called()); 1035 EXPECT_EQ(0, controller_delegate->on_menu_closed_called());
1184 } 1036 }
1185 1037
1186 // Tests that dragging within an asynchronous menu notifies the 1038 // Tests that dragging within an asynchronous menu notifies the
1187 // MenuControllerDelegate for shutdown. 1039 // MenuControllerDelegate for shutdown.
1188 TEST_F(MenuControllerTest, AsynchronousDragComplete) { 1040 TEST_F(MenuControllerTest, AsynchronousDragComplete) {
1189 MenuController* controller = menu_controller(); 1041 MenuController* controller = menu_controller();
1190 controller->SetAsyncRun(true);
1191 TestDragCompleteThenDestroyOnMenuClosed(); 1042 TestDragCompleteThenDestroyOnMenuClosed();
1192 1043
1193 controller->OnDragWillStart(); 1044 controller->OnDragWillStart();
1194 controller->OnDragComplete(true); 1045 controller->OnDragComplete(true);
1195 1046
1196 TestMenuControllerDelegate* controller_delegate = menu_controller_delegate(); 1047 TestMenuControllerDelegate* controller_delegate = menu_controller_delegate();
1197 EXPECT_EQ(1, controller_delegate->on_menu_closed_called()); 1048 EXPECT_EQ(1, controller_delegate->on_menu_closed_called());
1198 EXPECT_EQ(nullptr, controller_delegate->on_menu_closed_menu()); 1049 EXPECT_EQ(nullptr, controller_delegate->on_menu_closed_menu());
1199 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE, 1050 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE,
1200 controller_delegate->on_menu_closed_notify_type()); 1051 controller_delegate->on_menu_closed_notify_type());
1201 } 1052 }
1202 1053
1203 // Tests that if Cancel is called during a drag, that OnMenuClosed is still 1054 // Tests that if Cancel is called during a drag, that OnMenuClosed is still
1204 // notified when the drag completes. 1055 // notified when the drag completes.
1205 TEST_F(MenuControllerTest, AsynchronousCancelDuringDrag) { 1056 TEST_F(MenuControllerTest, AsynchronousCancelDuringDrag) {
1206 MenuController* controller = menu_controller(); 1057 MenuController* controller = menu_controller();
1207 controller->SetAsyncRun(true);
1208 TestDragCompleteThenDestroyOnMenuClosed(); 1058 TestDragCompleteThenDestroyOnMenuClosed();
1209 1059
1210 controller->OnDragWillStart(); 1060 controller->OnDragWillStart();
1211 controller->CancelAll(); 1061 controller->CancelAll();
1212 controller->OnDragComplete(true); 1062 controller->OnDragComplete(true);
1213 1063
1214 TestMenuControllerDelegate* controller_delegate = menu_controller_delegate(); 1064 TestMenuControllerDelegate* controller_delegate = menu_controller_delegate();
1215 EXPECT_EQ(1, controller_delegate->on_menu_closed_called()); 1065 EXPECT_EQ(1, controller_delegate->on_menu_closed_called());
1216 EXPECT_EQ(nullptr, controller_delegate->on_menu_closed_menu()); 1066 EXPECT_EQ(nullptr, controller_delegate->on_menu_closed_menu());
1217 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE, 1067 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE,
1218 controller_delegate->on_menu_closed_notify_type()); 1068 controller_delegate->on_menu_closed_notify_type());
1219 } 1069 }
1220 1070
1221 // Tests that if a menu is destroyed while drag operations are occuring, that 1071 // Tests that if a menu is destroyed while drag operations are occuring, that
1222 // the MenuHost does not crash as the drag completes. 1072 // the MenuHost does not crash as the drag completes.
1223 TEST_F(MenuControllerTest, AsynchronousDragHostDeleted) { 1073 TEST_F(MenuControllerTest, AsynchronousDragHostDeleted) {
1224 MenuController* controller = menu_controller();
1225 controller->SetAsyncRun(true);
1226
1227 SubmenuView* submenu = menu_item()->GetSubmenu(); 1074 SubmenuView* submenu = menu_item()->GetSubmenu();
1228 submenu->ShowAt(owner(), menu_item()->bounds(), false); 1075 submenu->ShowAt(owner(), menu_item()->bounds(), false);
1229 MenuHost* host = GetMenuHost(submenu); 1076 MenuHost* host = GetMenuHost(submenu);
1230 MenuHostOnDragWillStart(host); 1077 MenuHostOnDragWillStart(host);
1231 submenu->Close(); 1078 submenu->Close();
1232 DestroyMenuItem(); 1079 DestroyMenuItem();
1233 MenuHostOnDragComplete(host); 1080 MenuHostOnDragComplete(host);
1234 } 1081 }
1235 1082
1236 // Widget destruction and cleanup occurs on the MessageLoop after the 1083 // Widget destruction and cleanup occurs on the MessageLoop after the
1237 // MenuController has been destroyed. A MenuHostRootView should not attempt to 1084 // MenuController has been destroyed. A MenuHostRootView should not attempt to
1238 // access a destroyed MenuController. This test should not cause a crash. 1085 // access a destroyed MenuController. This test should not cause a crash.
1239 TEST_F(MenuControllerTest, HostReceivesInputBeforeDestruction) { 1086 TEST_F(MenuControllerTest, HostReceivesInputBeforeDestruction) {
1240 MenuController* controller = menu_controller();
1241 controller->SetAsyncRun(true);
1242
1243 SubmenuView* submenu = menu_item()->GetSubmenu(); 1087 SubmenuView* submenu = menu_item()->GetSubmenu();
1244 submenu->ShowAt(owner(), menu_item()->bounds(), false); 1088 submenu->ShowAt(owner(), menu_item()->bounds(), false);
1245 gfx::Point location(submenu->bounds().bottom_right()); 1089 gfx::Point location(submenu->bounds().bottom_right());
1246 location.Offset(1, 1); 1090 location.Offset(1, 1);
1247 1091
1248 MenuHost* host = GetMenuHost(submenu); 1092 MenuHost* host = GetMenuHost(submenu);
1249 // Normally created as the full Widget is brought up. Explicitly created here 1093 // Normally created as the full Widget is brought up. Explicitly created here
1250 // for testing. 1094 // for testing.
1251 std::unique_ptr<MenuHostRootView> root_view(CreateMenuHostRootView(host)); 1095 std::unique_ptr<MenuHostRootView> root_view(CreateMenuHostRootView(host));
1252 DestroyMenuController(); 1096 DestroyMenuController();
1253 1097
1254 ui::MouseEvent event(ui::ET_MOUSE_MOVED, location, location, 1098 ui::MouseEvent event(ui::ET_MOUSE_MOVED, location, location,
1255 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, 0); 1099 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, 0);
1256 1100
1257 // This should not attempt to access the destroyed MenuController and should 1101 // This should not attempt to access the destroyed MenuController and should
1258 // not crash. 1102 // not crash.
1259 root_view->OnMouseMoved(event); 1103 root_view->OnMouseMoved(event);
1260 } 1104 }
1261 1105
1262 // Tets that an asynchronous menu nested within an asynchronous menu closes both 1106 // Tets that an asynchronous menu nested within an asynchronous menu closes both
1263 // menus, and notifies both delegates. 1107 // menus, and notifies both delegates.
1264 TEST_F(MenuControllerTest, DoubleAsynchronousNested) { 1108 TEST_F(MenuControllerTest, DoubleAsynchronousNested) {
1265 MenuController* controller = menu_controller(); 1109 MenuController* controller = menu_controller();
1266 TestMenuControllerDelegate* delegate = menu_controller_delegate(); 1110 TestMenuControllerDelegate* delegate = menu_controller_delegate();
1267 std::unique_ptr<TestMenuControllerDelegate> nested_delegate( 1111 std::unique_ptr<TestMenuControllerDelegate> nested_delegate(
1268 new TestMenuControllerDelegate()); 1112 new TestMenuControllerDelegate());
1269 1113
1270 ASSERT_FALSE(IsAsyncRun());
1271 // Sets the run created in SetUp
1272 controller->SetAsyncRun(true);
1273
1274 // Nested run 1114 // Nested run
1275 controller->AddNestedDelegate(nested_delegate.get()); 1115 controller->AddNestedDelegate(nested_delegate.get());
1276 controller->SetAsyncRun(true);
1277 int mouse_event_flags = 0; 1116 int mouse_event_flags = 0;
1278 MenuItemView* run_result = 1117 MenuItemView* run_result =
1279 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(), 1118 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(),
1280 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags); 1119 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags);
1281 EXPECT_EQ(run_result, nullptr); 1120 EXPECT_EQ(run_result, nullptr);
1282 1121
1283 controller->CancelAll(); 1122 controller->CancelAll();
1284 EXPECT_EQ(1, delegate->on_menu_closed_called()); 1123 EXPECT_EQ(1, delegate->on_menu_closed_called());
1285 EXPECT_EQ(1, nested_delegate->on_menu_closed_called()); 1124 EXPECT_EQ(1, nested_delegate->on_menu_closed_called());
1286 } 1125 }
1287 1126
1288 // Tests that an asynchronous menu nested within a synchronous menu does not 1127 // Tests that a nested menu does not crash when trying to repost events that
1289 // crash when trying to repost events that occur outside of the bounds of the 1128 // occur outside of the bounds of the menu. Instead a proper shutdown should
1290 // menu. Instead a proper shutdown should occur. 1129 // occur.
1291 TEST_F(MenuControllerTest, AsynchronousRepostEvent) { 1130 TEST_F(MenuControllerTest, AsynchronousRepostEvent) {
1292 MenuController* controller = menu_controller(); 1131 MenuController* controller = menu_controller();
1293 TestMenuControllerDelegate* delegate = menu_controller_delegate(); 1132 TestMenuControllerDelegate* delegate = menu_controller_delegate();
1294 std::unique_ptr<TestMenuControllerDelegate> nested_delegate( 1133 std::unique_ptr<TestMenuControllerDelegate> nested_delegate(
1295 new TestMenuControllerDelegate()); 1134 new TestMenuControllerDelegate());
1296 1135
1297 ASSERT_FALSE(IsAsyncRun());
1298
1299 controller->AddNestedDelegate(nested_delegate.get()); 1136 controller->AddNestedDelegate(nested_delegate.get());
1300 controller->SetAsyncRun(true);
1301
1302 EXPECT_TRUE(IsAsyncRun());
1303 EXPECT_EQ(nested_delegate.get(), GetCurrentDelegate()); 1137 EXPECT_EQ(nested_delegate.get(), GetCurrentDelegate());
1304 1138
1305 MenuItemView* item = menu_item(); 1139 MenuItemView* item = menu_item();
1306 int mouse_event_flags = 0; 1140 int mouse_event_flags = 0;
1307 MenuItemView* run_result = 1141 MenuItemView* run_result =
1308 controller->Run(owner(), nullptr, item, gfx::Rect(), MENU_ANCHOR_TOPLEFT, 1142 controller->Run(owner(), nullptr, item, gfx::Rect(), MENU_ANCHOR_TOPLEFT,
1309 false, false, &mouse_event_flags); 1143 false, false, &mouse_event_flags);
1310 EXPECT_EQ(run_result, nullptr); 1144 EXPECT_EQ(run_result, nullptr);
1311 1145
1312 // Show a sub menu to target with a pointer selection. However have the event 1146 // Show a sub menu to target with a pointer selection. However have the event
1313 // occur outside of the bounds of the entire menu. 1147 // occur outside of the bounds of the entire menu.
1314 SubmenuView* sub_menu = item->GetSubmenu(); 1148 SubmenuView* sub_menu = item->GetSubmenu();
1315 sub_menu->ShowAt(owner(), item->bounds(), false); 1149 sub_menu->ShowAt(owner(), item->bounds(), false);
1316 gfx::Point location(sub_menu->bounds().bottom_right()); 1150 gfx::Point location(sub_menu->bounds().bottom_right());
1317 location.Offset(1, 1); 1151 location.Offset(1, 1);
1318 ui::MouseEvent event(ui::ET_MOUSE_PRESSED, location, location, 1152 ui::MouseEvent event(ui::ET_MOUSE_PRESSED, location, location,
1319 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, 0); 1153 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, 0);
1320 1154
1321 // When attempting to select outside of all menus this should lead to a 1155 // When attempting to select outside of all menus this should lead to a
1322 // shutdown. This should not crash while attempting to repost the event. 1156 // shutdown. This should not crash while attempting to repost the event.
1323 SetSelectionOnPointerDown(sub_menu, &event); 1157 SetSelectionOnPointerDown(sub_menu, &event);
1324 1158
1325 EXPECT_FALSE(IsAsyncRun());
1326 EXPECT_EQ(delegate, GetCurrentDelegate()); 1159 EXPECT_EQ(delegate, GetCurrentDelegate());
1327 EXPECT_EQ(0, delegate->on_menu_closed_called()); 1160 EXPECT_EQ(1, delegate->on_menu_closed_called());
1328 EXPECT_EQ(1, nested_delegate->on_menu_closed_called()); 1161 EXPECT_EQ(1, nested_delegate->on_menu_closed_called());
1329 EXPECT_EQ(nullptr, nested_delegate->on_menu_closed_menu()); 1162 EXPECT_EQ(nullptr, nested_delegate->on_menu_closed_menu());
1330 EXPECT_EQ(0, nested_delegate->on_menu_closed_mouse_event_flags()); 1163 EXPECT_EQ(0, nested_delegate->on_menu_closed_mouse_event_flags());
1331 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE, 1164 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE,
1332 nested_delegate->on_menu_closed_notify_type()); 1165 nested_delegate->on_menu_closed_notify_type());
1333 EXPECT_EQ(MenuController::EXIT_ALL, controller->exit_type()); 1166 EXPECT_EQ(MenuController::EXIT_ALL, controller->exit_type());
1334 } 1167 }
1335 1168
1336 // Tests that an asynchronous menu reposts touch events that occur outside of 1169 // Tests that an asynchronous menu reposts touch events that occur outside of
1337 // the bounds of the menu, and that the menu closes. 1170 // the bounds of the menu, and that the menu closes.
1338 TEST_F(MenuControllerTest, AsynchronousTouchEventRepostEvent) { 1171 TEST_F(MenuControllerTest, AsynchronousTouchEventRepostEvent) {
1339 MenuController* controller = menu_controller(); 1172 MenuController* controller = menu_controller();
1340 TestMenuControllerDelegate* delegate = menu_controller_delegate(); 1173 TestMenuControllerDelegate* delegate = menu_controller_delegate();
1341 controller->SetAsyncRun(true);
1342 1174
1343 // Show a sub menu to target with a touch event. However have the event occur 1175 // Show a sub menu to target with a touch event. However have the event occur
1344 // outside of the bounds of the entire menu. 1176 // outside of the bounds of the entire menu.
1345 MenuItemView* item = menu_item(); 1177 MenuItemView* item = menu_item();
1346 SubmenuView* sub_menu = item->GetSubmenu(); 1178 SubmenuView* sub_menu = item->GetSubmenu();
1347 sub_menu->ShowAt(owner(), item->bounds(), false); 1179 sub_menu->ShowAt(owner(), item->bounds(), false);
1348 gfx::Point location(sub_menu->bounds().bottom_right()); 1180 gfx::Point location(sub_menu->bounds().bottom_right());
1349 location.Offset(1, 1); 1181 location.Offset(1, 1);
1350 ui::TouchEvent event( 1182 ui::TouchEvent event(
1351 ui::ET_TOUCH_PRESSED, location, ui::EventTimeForNow(), 1183 ui::ET_TOUCH_PRESSED, location, ui::EventTimeForNow(),
1352 ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0)); 1184 ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
1353 controller->OnTouchEvent(sub_menu, &event); 1185 controller->OnTouchEvent(sub_menu, &event);
1354 1186
1355 EXPECT_FALSE(IsShowing()); 1187 EXPECT_FALSE(IsShowing());
1356 EXPECT_EQ(1, delegate->on_menu_closed_called()); 1188 EXPECT_EQ(1, delegate->on_menu_closed_called());
1357 EXPECT_EQ(nullptr, delegate->on_menu_closed_menu()); 1189 EXPECT_EQ(nullptr, delegate->on_menu_closed_menu());
1358 EXPECT_EQ(0, delegate->on_menu_closed_mouse_event_flags()); 1190 EXPECT_EQ(0, delegate->on_menu_closed_mouse_event_flags());
1359 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE, 1191 EXPECT_EQ(internal::MenuControllerDelegate::NOTIFY_DELEGATE,
1360 delegate->on_menu_closed_notify_type()); 1192 delegate->on_menu_closed_notify_type());
1361 EXPECT_EQ(MenuController::EXIT_ALL, controller->exit_type()); 1193 EXPECT_EQ(MenuController::EXIT_ALL, controller->exit_type());
1362 } 1194 }
1363 1195
1364 // Tests that if you exit all menus when an asynchrnous menu is nested within a
1365 // synchronous menu, the message loop for the parent menu finishes running.
1366 TEST_F(MenuControllerTest, AsynchronousNestedExitAll) {
1367 InstallTestMenuMessageLoop();
1368
1369 base::ThreadTaskRunnerHandle::Get()->PostTask(
1370 FROM_HERE, base::Bind(&MenuControllerTest::TestAsynchronousNestedExitAll,
1371 base::Unretained(this)));
1372
1373 RunMenu();
1374 }
1375
1376 // Tests that if you exit the nested menu when an asynchrnous menu is nested
1377 // within a synchronous menu, the message loop for the parent menu remains
1378 // running.
1379 TEST_F(MenuControllerTest, AsynchronousNestedExitOutermost) {
1380 InstallTestMenuMessageLoop();
1381
1382 base::ThreadTaskRunnerHandle::Get()->PostTask(
1383 FROM_HERE,
1384 base::Bind(&MenuControllerTest::TestAsynchronousNestedExitOutermost,
1385 base::Unretained(this)));
1386
1387 RunMenu();
1388 }
1389
1390 // Tests that having the MenuController deleted during RepostEvent does not 1196 // Tests that having the MenuController deleted during RepostEvent does not
1391 // cause a crash. ASAN bots should not detect use-after-free in MenuController. 1197 // cause a crash. ASAN bots should not detect use-after-free in MenuController.
1392 TEST_F(MenuControllerTest, AsynchronousRepostEventDeletesController) { 1198 TEST_F(MenuControllerTest, AsynchronousRepostEventDeletesController) {
1393 MenuController* controller = menu_controller(); 1199 MenuController* controller = menu_controller();
1394 std::unique_ptr<TestMenuControllerDelegate> nested_delegate( 1200 std::unique_ptr<TestMenuControllerDelegate> nested_delegate(
1395 new TestMenuControllerDelegate()); 1201 new TestMenuControllerDelegate());
1396 1202
1397 ASSERT_FALSE(IsAsyncRun());
1398
1399 controller->AddNestedDelegate(nested_delegate.get()); 1203 controller->AddNestedDelegate(nested_delegate.get());
1400 controller->SetAsyncRun(true);
1401
1402 EXPECT_TRUE(IsAsyncRun());
1403 EXPECT_EQ(nested_delegate.get(), GetCurrentDelegate()); 1204 EXPECT_EQ(nested_delegate.get(), GetCurrentDelegate());
1404 1205
1405 MenuItemView* item = menu_item(); 1206 MenuItemView* item = menu_item();
1406 int mouse_event_flags = 0; 1207 int mouse_event_flags = 0;
1407 MenuItemView* run_result = 1208 MenuItemView* run_result =
1408 controller->Run(owner(), nullptr, item, gfx::Rect(), MENU_ANCHOR_TOPLEFT, 1209 controller->Run(owner(), nullptr, item, gfx::Rect(), MENU_ANCHOR_TOPLEFT,
1409 false, false, &mouse_event_flags); 1210 false, false, &mouse_event_flags);
1410 EXPECT_EQ(run_result, nullptr); 1211 EXPECT_EQ(run_result, nullptr);
1411 1212
1412 // Show a sub menu to target with a pointer selection. However have the event 1213 // Show a sub menu to target with a pointer selection. However have the event
(...skipping 16 matching lines...) Expand all
1429 sub_menu->Close(); 1230 sub_menu->Close();
1430 EXPECT_EQ(1, nested_delegate->on_menu_closed_called()); 1231 EXPECT_EQ(1, nested_delegate->on_menu_closed_called());
1431 } 1232 }
1432 1233
1433 // Tests that having the MenuController deleted during OnGestureEvent does not 1234 // Tests that having the MenuController deleted during OnGestureEvent does not
1434 // cause a crash. ASAN bots should not detect use-after-free in MenuController. 1235 // cause a crash. ASAN bots should not detect use-after-free in MenuController.
1435 TEST_F(MenuControllerTest, AsynchronousGestureDeletesController) { 1236 TEST_F(MenuControllerTest, AsynchronousGestureDeletesController) {
1436 MenuController* controller = menu_controller(); 1237 MenuController* controller = menu_controller();
1437 std::unique_ptr<TestMenuControllerDelegate> nested_delegate( 1238 std::unique_ptr<TestMenuControllerDelegate> nested_delegate(
1438 new TestMenuControllerDelegate()); 1239 new TestMenuControllerDelegate());
1439 ASSERT_FALSE(IsAsyncRun());
1440 1240
1441 controller->AddNestedDelegate(nested_delegate.get()); 1241 controller->AddNestedDelegate(nested_delegate.get());
1442 controller->SetAsyncRun(true);
1443
1444 EXPECT_TRUE(IsAsyncRun());
1445 EXPECT_EQ(nested_delegate.get(), GetCurrentDelegate()); 1242 EXPECT_EQ(nested_delegate.get(), GetCurrentDelegate());
1446 1243
1447 MenuItemView* item = menu_item(); 1244 MenuItemView* item = menu_item();
1448 int mouse_event_flags = 0; 1245 int mouse_event_flags = 0;
1449 MenuItemView* run_result = 1246 MenuItemView* run_result =
1450 controller->Run(owner(), nullptr, item, gfx::Rect(), MENU_ANCHOR_TOPLEFT, 1247 controller->Run(owner(), nullptr, item, gfx::Rect(), MENU_ANCHOR_TOPLEFT,
1451 false, false, &mouse_event_flags); 1248 false, false, &mouse_event_flags);
1452 EXPECT_EQ(run_result, nullptr); 1249 EXPECT_EQ(run_result, nullptr);
1453 1250
1454 // Show a sub menu to target with a tap event. 1251 // Show a sub menu to target with a tap event.
1455 SubmenuView* sub_menu = item->GetSubmenu(); 1252 SubmenuView* sub_menu = item->GetSubmenu();
1456 sub_menu->ShowAt(owner(), gfx::Rect(0, 0, 100, 100), true); 1253 sub_menu->ShowAt(owner(), gfx::Rect(0, 0, 100, 100), true);
1457 1254
1458 gfx::Point location(sub_menu->bounds().CenterPoint()); 1255 gfx::Point location(sub_menu->bounds().CenterPoint());
1459 ui::GestureEvent event(location.x(), location.y(), 0, ui::EventTimeForNow(), 1256 ui::GestureEvent event(location.x(), location.y(), 0, ui::EventTimeForNow(),
1460 ui::GestureEventDetails(ui::ET_GESTURE_TAP)); 1257 ui::GestureEventDetails(ui::ET_GESTURE_TAP));
1461 1258
1462 // This will lead to MenuController being deleted during the processing of the 1259 // This will lead to MenuController being deleted during the processing of the
1463 // gesture event. The remainder of this test, and TearDown should not crash. 1260 // gesture event. The remainder of this test, and TearDown should not crash.
1464 DestroyMenuControllerOnMenuClosed(nested_delegate.get()); 1261 DestroyMenuControllerOnMenuClosed(nested_delegate.get());
1465 controller->OnGestureEvent(sub_menu, &event); 1262 controller->OnGestureEvent(sub_menu, &event);
1466 1263
1467 // Close to remove observers before test TearDown 1264 // Close to remove observers before test TearDown
1468 sub_menu->Close(); 1265 sub_menu->Close();
1469 EXPECT_EQ(1, nested_delegate->on_menu_closed_called()); 1266 EXPECT_EQ(1, nested_delegate->on_menu_closed_called());
1470 } 1267 }
1471 1268
1472 // Tests that when an asynchronous menu is nested, and the nested message loop
1473 // is kill not by the MenuController, that the nested menu is notified of
1474 // destruction.
1475 TEST_F(MenuControllerTest, NestedMessageLoopDiesWithNestedMenu) {
1476 menu_controller()->CancelAll();
1477 InstallTestMenuMessageLoop();
1478 std::unique_ptr<TestMenuControllerDelegate> nested_delegate(
1479 new TestMenuControllerDelegate());
1480 // This will nest an asynchronous menu, and then kill the nested message loop.
1481 base::ThreadTaskRunnerHandle::Get()->PostTask(
1482 FROM_HERE,
1483 base::Bind(&MenuControllerTest::TestNestedMessageLoopKillsItself,
1484 base::Unretained(this), nested_delegate.get()));
1485
1486 int result_event_flags = 0;
1487 // This creates a nested message loop.
1488 EXPECT_EQ(nullptr, menu_controller()->Run(owner(), nullptr, menu_item(),
1489 gfx::Rect(), MENU_ANCHOR_TOPLEFT,
1490 false, false, &result_event_flags));
1491 EXPECT_FALSE(menu_controller_delegate()->on_menu_closed_called());
1492 EXPECT_TRUE(nested_delegate->on_menu_closed_called());
1493 }
1494
1495 #if defined(USE_AURA) 1269 #if defined(USE_AURA)
1496 // Tests that when a synchronous menu receives a cancel event, that it closes.
1497 TEST_F(MenuControllerTest, SynchronousCancelEvent) {
1498 ExitMenuRun();
1499 // Post actual test to run once the menu has created a nested message loop.
1500 base::ThreadTaskRunnerHandle::Get()->PostTask(
1501 FROM_HERE,
1502 base::Bind(&MenuControllerTest::TestCancelEvent, base::Unretained(this)));
1503 int mouse_event_flags = 0;
1504 MenuItemView* run_result = menu_controller()->Run(
1505 owner(), nullptr, menu_item(), gfx::Rect(), MENU_ANCHOR_TOPLEFT, false,
1506 false, &mouse_event_flags);
1507 EXPECT_EQ(run_result, nullptr);
1508 }
1509
1510 // Tests that when an asynchronous menu receives a cancel event, that it closes. 1270 // Tests that when an asynchronous menu receives a cancel event, that it closes.
1511 TEST_F(MenuControllerTest, AsynchronousCancelEvent) { 1271 TEST_F(MenuControllerTest, AsynchronousCancelEvent) {
1512 ExitMenuRun(); 1272 ExitMenuRun();
1513 MenuController* controller = menu_controller(); 1273 MenuController* controller = menu_controller();
1514 controller->SetAsyncRun(true);
1515 1274
1516 int mouse_event_flags = 0; 1275 int mouse_event_flags = 0;
1517 MenuItemView* run_result = 1276 MenuItemView* run_result =
1518 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(), 1277 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(),
1519 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags); 1278 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags);
1520 EXPECT_EQ(run_result, nullptr); 1279 EXPECT_EQ(run_result, nullptr);
1521 TestCancelEvent(); 1280 EXPECT_EQ(MenuController::EXIT_NONE, controller->exit_type());
1281 ui::CancelModeEvent cancel_event;
1282 event_generator()->Dispatch(&cancel_event);
1283 EXPECT_EQ(MenuController::EXIT_ALL, controller->exit_type());
1522 } 1284 }
1523 1285
1524 // Tests that if a menu is ran without a widget, that MenuPreTargetHandler does 1286 // Tests that if a menu is ran without a widget, that MenuPreTargetHandler does
1525 // not cause a crash. 1287 // not cause a crash.
1526 TEST_F(MenuControllerTest, RunWithoutWidgetDoesntCrash) { 1288 TEST_F(MenuControllerTest, RunWithoutWidgetDoesntCrash) {
1527 ExitMenuRun(); 1289 ExitMenuRun();
1528 MenuController* controller = menu_controller(); 1290 MenuController* controller = menu_controller();
1529 controller->SetAsyncRun(true);
1530 int mouse_event_flags = 0; 1291 int mouse_event_flags = 0;
1531 MenuItemView* run_result = 1292 MenuItemView* run_result =
1532 controller->Run(nullptr, nullptr, menu_item(), gfx::Rect(), 1293 controller->Run(nullptr, nullptr, menu_item(), gfx::Rect(),
1533 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags); 1294 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags);
1534 EXPECT_EQ(run_result, nullptr); 1295 EXPECT_EQ(run_result, nullptr);
1535 } 1296 }
1536 1297
1537 // Tests that if a MenuController is destroying during drag/drop, and another 1298 // Tests that if a MenuController is destroying during drag/drop, and another
1538 // MenuController becomes active, that the exiting of drag does not cause a 1299 // MenuController becomes active, that the exiting of drag does not cause a
1539 // crash. 1300 // crash.
(...skipping 10 matching lines...) Expand all
1550 ->GetNativeWindow() 1311 ->GetNativeWindow()
1551 ->GetRootWindow(), 1312 ->GetRootWindow(),
1552 &drag_drop_client); 1313 &drag_drop_client);
1553 StartDrag(); 1314 StartDrag();
1554 } 1315 }
1555 1316
1556 // Tests that if a CancelAll is called during drag-and-drop that it does not 1317 // Tests that if a CancelAll is called during drag-and-drop that it does not
1557 // destroy the MenuController. On Windows and Linux this destruction also 1318 // destroy the MenuController. On Windows and Linux this destruction also
1558 // destroys the Widget used for drag-and-drop, thereby ending the drag. 1319 // destroys the Widget used for drag-and-drop, thereby ending the drag.
1559 TEST_F(MenuControllerTest, CancelAllDuringDrag) { 1320 TEST_F(MenuControllerTest, CancelAllDuringDrag) {
1560 MenuController* controller = menu_controller();
1561 controller->SetAsyncRun(true);
1562
1563 // Build the menu so that the appropriate root window is available to set the 1321 // Build the menu so that the appropriate root window is available to set the
1564 // drag drop client on. 1322 // drag drop client on.
1565 AddButtonMenuItems(); 1323 AddButtonMenuItems();
1566 TestDragDropClient drag_drop_client(base::Bind( 1324 TestDragDropClient drag_drop_client(base::Bind(
1567 &MenuControllerTest::TestCancelAllDuringDrag, base::Unretained(this))); 1325 &MenuControllerTest::TestCancelAllDuringDrag, base::Unretained(this)));
1568 aura::client::SetDragDropClient(menu_item() 1326 aura::client::SetDragDropClient(menu_item()
1569 ->GetSubmenu() 1327 ->GetSubmenu()
1570 ->GetWidget() 1328 ->GetWidget()
1571 ->GetNativeWindow() 1329 ->GetNativeWindow()
1572 ->GetRootWindow(), 1330 ->GetRootWindow(),
1573 &drag_drop_client); 1331 &drag_drop_client);
1574 StartDrag(); 1332 StartDrag();
1575 } 1333 }
1576 1334
1577 // Tests that when releasing the ref on ViewsDelegate and MenuController is 1335 // Tests that when releasing the ref on ViewsDelegate and MenuController is
1578 // deleted, that shutdown occurs without crashing. 1336 // deleted, that shutdown occurs without crashing.
1579 TEST_F(MenuControllerTest, DestroyedDuringViewsRelease) { 1337 TEST_F(MenuControllerTest, DestroyedDuringViewsRelease) {
1580 ExitMenuRun(); 1338 ExitMenuRun();
1581 MenuController* controller = menu_controller(); 1339 MenuController* controller = menu_controller();
1582 controller->SetAsyncRun(true);
1583 1340
1584 int mouse_event_flags = 0; 1341 int mouse_event_flags = 0;
1585 MenuItemView* run_result = 1342 MenuItemView* run_result =
1586 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(), 1343 controller->Run(owner(), nullptr, menu_item(), gfx::Rect(),
1587 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags); 1344 MENU_ANCHOR_TOPLEFT, false, false, &mouse_event_flags);
1588 EXPECT_EQ(run_result, nullptr); 1345 EXPECT_EQ(run_result, nullptr);
1589 TestDestroyedDuringViewsRelease(); 1346 TestDestroyedDuringViewsRelease();
1590 } 1347 }
1591 1348
1592 // Tests that when a context menu is opened above an empty menu item, and a 1349 // Tests that when a context menu is opened above an empty menu item, and a
1593 // right-click occurs over the empty item, that the bottom menu is not hidden, 1350 // right-click occurs over the empty item, that the bottom menu is not hidden,
1594 // that a request to relaunch the context menu is received, and that 1351 // that a request to relaunch the context menu is received, and that
1595 // subsequently pressing ESC does not crash the browser. 1352 // subsequently pressing ESC does not crash the browser.
1596 TEST_F(MenuControllerTest, RepostEventToEmptyMenuItem) { 1353 TEST_F(MenuControllerTest, RepostEventToEmptyMenuItem) {
1597 // Setup a submenu. Additionally hook up appropriate Widget and View 1354 // Setup a submenu. Additionally hook up appropriate Widget and View
1598 // containers, with bounds, so that hit testing works. 1355 // containers, with bounds, so that hit testing works.
1599 MenuController* controller = menu_controller(); 1356 MenuController* controller = menu_controller();
1600 controller->SetAsyncRun(true);
1601 MenuItemView* base_menu = menu_item(); 1357 MenuItemView* base_menu = menu_item();
1602 base_menu->SetBounds(0, 0, 200, 200); 1358 base_menu->SetBounds(0, 0, 200, 200);
1603 SubmenuView* base_submenu = base_menu->GetSubmenu(); 1359 SubmenuView* base_submenu = base_menu->GetSubmenu();
1604 base_submenu->SetBounds(0, 0, 200, 200); 1360 base_submenu->SetBounds(0, 0, 200, 200);
1605 base_submenu->ShowAt(owner(), gfx::Rect(0, 0, 200, 200), false); 1361 base_submenu->ShowAt(owner(), gfx::Rect(0, 0, 200, 200), false);
1606 GetMenuHost(base_submenu) 1362 GetMenuHost(base_submenu)
1607 ->SetContentsView(base_submenu->GetScrollViewContainer()); 1363 ->SetContentsView(base_submenu->GetScrollViewContainer());
1608 1364
1609 // Build the submenu to have an empty menu item. Additionally hook up 1365 // Build the submenu to have an empty menu item. Additionally hook up
1610 // appropriate Widget and View containersm with counds, so that hit testing 1366 // appropriate Widget and View containersm with counds, so that hit testing
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
1699 // crash. 1455 // crash.
1700 TestAsyncEscapeKey(); 1456 TestAsyncEscapeKey();
1701 EXPECT_EQ(nested_controller_delegate_2->on_menu_closed_called(), 1); 1457 EXPECT_EQ(nested_controller_delegate_2->on_menu_closed_called(), 1);
1702 EXPECT_EQ(menu_controller_delegate(), GetCurrentDelegate()); 1458 EXPECT_EQ(menu_controller_delegate(), GetCurrentDelegate());
1703 } 1459 }
1704 1460
1705 #endif // defined(USE_AURA) 1461 #endif // defined(USE_AURA)
1706 1462
1707 } // namespace test 1463 } // namespace test
1708 } // namespace views 1464 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/controls/menu/menu_controller.cc ('k') | ui/views/controls/menu/menu_message_loop.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698