1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
11 #include "ash/accelerators//accelerator_tracker.h"
12 #include "ash/accessibility/chromevox/key_accessibility_enabler.h"
13 #include "ash/accessibility/magnifier/fullscreen_magnifier_controller.h"
14 #include "ash/display/mouse_cursor_event_filter.h"
15 #include "ash/drag_drop/drag_drop_controller.h"
16 #include "ash/drag_drop/drag_drop_controller_test_api.h"
17 #include "ash/keyboard/ui/keyboard_ui_controller.h"
18 #include "ash/keyboard/ui/keyboard_util.h"
19 #include "ash/public/cpp/ash_prefs.h"
20 #include "ash/public/cpp/keyboard/keyboard_switches.h"
21 #include "ash/public/cpp/shell_window_ids.h"
22 #include "ash/public/cpp/test/shell_test_api.h"
23 #include "ash/root_window_controller.h"
24 #include "ash/session/session_controller_impl.h"
25 #include "ash/session/test_session_controller_client.h"
26 #include "ash/shelf/home_button.h"
27 #include "ash/shelf/shelf.h"
28 #include "ash/shelf/shelf_layout_manager.h"
29 #include "ash/shelf/shelf_navigation_widget.h"
30 #include "ash/shelf/shelf_widget.h"
31 #include "ash/system/status_area_widget.h"
32 #include "ash/test/ash_test_base.h"
33 #include "ash/test/ash_test_helper.h"
34 #include "ash/test/test_widget_builder.h"
35 #include "ash/test_shell_delegate.h"
36 #include "ash/wallpaper/views/wallpaper_widget_controller.h"
37 #include "ash/wm/desks/desks_util.h"
38 #include "ash/wm/overview/overview_controller.h"
39 #include "base/command_line.h"
40 #include "base/containers/flat_set.h"
41 #include "base/ranges/algorithm.h"
42 #include "base/strings/utf_string_conversions.h"
43 #include "components/account_id/account_id.h"
44 #include "ui/aura/env.h"
45 #include "ui/aura/window.h"
46 #include "ui/aura/window_event_dispatcher.h"
47 #include "ui/base/models/simple_menu_model.h"
48 #include "ui/display/scoped_display_for_new_windows.h"
49 #include "ui/events/test/event_generator.h"
50 #include "ui/events/test/events_test_utils.h"
51 #include "ui/events/test/test_event_handler.h"
52 #include "ui/gfx/geometry/size.h"
53 #include "ui/views/controls/menu/menu_controller.h"
54 #include "ui/views/controls/menu/menu_runner.h"
55 #include "ui/views/widget/widget.h"
56 #include "ui/views/widget/widget_delegate.h"
57 #include "ui/views/window/dialog_delegate.h"
58 #include "ui/wm/core/accelerator_filter.h"
60 using aura::RootWindow;
66 aura::Window* GetActiveDeskContainer() {
67 return Shell::GetContainer(Shell::GetPrimaryRootWindow(),
68 desks_util::GetActiveDeskContainerId());
71 aura::Window* GetAlwaysOnTopContainer() {
72 return Shell::GetContainer(Shell::GetPrimaryRootWindow(),
73 kShellWindowId_AlwaysOnTopContainer);
76 // Expect ALL the containers!
77 void ExpectAllContainers() {
78 aura::Window* root_window = Shell::GetPrimaryRootWindow();
80 // Validate no duplicate container IDs.
81 base::flat_set<int> container_ids;
82 std::queue<aura::Window*> window_queue;
83 window_queue.push(root_window);
84 while (!window_queue.empty()) {
85 aura::Window* current_window = window_queue.front();
87 for (aura::Window* child : current_window->children())
88 window_queue.push(child);
90 const int id = current_window->GetId();
92 // Skip windows with no IDs.
93 if (id == aura::Window::kInitialId)
96 EXPECT_TRUE(container_ids.insert(id).second)
97 << "Found duplicate ID: " << id
98 << " at window: " << current_window->GetName();
102 Shell::GetContainer(root_window, kShellWindowId_WallpaperContainer));
104 for (int desk_id : desks_util::GetDesksContainersIds())
105 EXPECT_TRUE(Shell::GetContainer(root_window, desk_id));
108 Shell::GetContainer(root_window, kShellWindowId_AlwaysOnTopContainer));
109 EXPECT_TRUE(Shell::GetContainer(root_window, kShellWindowId_ShelfContainer));
111 Shell::GetContainer(root_window, kShellWindowId_SystemModalContainer));
112 EXPECT_TRUE(Shell::GetContainer(root_window,
113 kShellWindowId_LockScreenWallpaperContainer));
115 Shell::GetContainer(root_window, kShellWindowId_LockScreenContainer));
116 EXPECT_TRUE(Shell::GetContainer(root_window,
117 kShellWindowId_LockSystemModalContainer));
118 EXPECT_TRUE(Shell::GetContainer(root_window, kShellWindowId_MenuContainer));
119 EXPECT_TRUE(Shell::GetContainer(root_window,
120 kShellWindowId_DragImageAndTooltipContainer));
122 Shell::GetContainer(root_window, kShellWindowId_SettingBubbleContainer));
124 Shell::GetContainer(root_window, kShellWindowId_OverlayContainer));
125 EXPECT_TRUE(Shell::GetContainer(root_window,
126 kShellWindowId_ImeWindowParentContainer));
127 EXPECT_TRUE(Shell::GetContainer(root_window,
128 kShellWindowId_VirtualKeyboardContainer));
130 Shell::GetContainer(root_window, kShellWindowId_MouseCursorContainer));
132 // Phantom window is not a container.
133 EXPECT_EQ(0u, container_ids.count(kShellWindowId_PhantomWindow));
134 EXPECT_FALSE(Shell::GetContainer(root_window, kShellWindowId_PhantomWindow));
137 std::unique_ptr<views::WidgetDelegateView> CreateModalWidgetDelegate() {
138 auto delegate = std::make_unique<views::WidgetDelegateView>();
139 delegate->SetCanResize(true);
140 delegate->SetModalType(ui::MODAL_TYPE_SYSTEM);
141 delegate->SetOwnedByWidget(true);
142 delegate->SetTitle(u"Modal Window");
146 class SimpleMenuDelegate : public ui::SimpleMenuModel::Delegate {
148 SimpleMenuDelegate() = default;
150 SimpleMenuDelegate(const SimpleMenuDelegate&) = delete;
151 SimpleMenuDelegate& operator=(const SimpleMenuDelegate&) = delete;
153 ~SimpleMenuDelegate() override = default;
155 bool IsCommandIdChecked(int command_id) const override { return false; }
157 bool IsCommandIdEnabled(int command_id) const override { return true; }
159 void ExecuteCommand(int command_id, int event_flags) override {}
164 class ShellTest : public AshTestBase {
166 void TestCreateWindow(views::Widget::InitParams::Type type,
168 aura::Window* expected_container) {
169 TestWidgetBuilder builder;
171 builder.SetZOrderLevel(ui::ZOrderLevel::kFloatingWindow);
172 views::Widget* widget =
173 builder.SetWidgetType(type).BuildOwnedByNativeWidget();
176 expected_container->Contains(widget->GetNativeWindow()->parent()))
177 << "TestCreateWindow: type=" << type
178 << ", always_on_top=" << always_on_top;
183 void LockScreenAndVerifyMenuClosed() {
184 // Verify a menu is open before locking.
185 views::MenuController* menu_controller =
186 views::MenuController::GetActiveInstance();
187 DCHECK(menu_controller);
188 EXPECT_EQ(views::MenuController::ExitType::kNone,
189 menu_controller->exit_type());
191 // Create a LockScreen window.
192 views::Widget* lock_widget =
194 .SetWidgetType(views::Widget::InitParams::TYPE_WINDOW)
196 .BuildOwnedByNativeWidget();
197 Shell::GetContainer(Shell::GetPrimaryRootWindow(),
198 kShellWindowId_LockScreenContainer)
199 ->AddChild(lock_widget->GetNativeView());
202 // Simulate real screen locker to change session state to LOCKED
204 GetSessionControllerClient()->LockScreen();
206 SessionControllerImpl* controller = Shell::Get()->session_controller();
207 EXPECT_TRUE(controller->IsScreenLocked());
208 EXPECT_TRUE(lock_widget->GetNativeView()->HasFocus());
210 // Verify menu is closed.
211 EXPECT_EQ(nullptr, views::MenuController::GetActiveInstance());
212 lock_widget->Close();
213 GetSessionControllerClient()->UnlockScreen();
217 TEST_F(ShellTest, CreateWindow) {
218 // Normal window should be created in default container.
219 TestCreateWindow(views::Widget::InitParams::TYPE_WINDOW,
220 false, // always_on_top
221 GetActiveDeskContainer());
222 TestCreateWindow(views::Widget::InitParams::TYPE_POPUP,
223 false, // always_on_top
224 GetActiveDeskContainer());
226 // Always-on-top window and popup are created in always-on-top container.
227 TestCreateWindow(views::Widget::InitParams::TYPE_WINDOW,
228 true, // always_on_top
229 GetAlwaysOnTopContainer());
230 TestCreateWindow(views::Widget::InitParams::TYPE_POPUP,
231 true, // always_on_top
232 GetAlwaysOnTopContainer());
235 // Verifies that a window with a preferred size is created centered on the
236 // default display for new windows. Mojo apps like shortcut_viewer rely on this
238 TEST_F(ShellTest, CreateWindowWithPreferredSize) {
239 UpdateDisplay("1024x768,800x600");
241 aura::Window* secondary_root = Shell::GetAllRootWindows()[1];
242 display::ScopedDisplayForNewWindows scoped_display(secondary_root);
244 views::Widget::InitParams params;
245 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
246 // Don't specify bounds, parent or context.
248 auto delegate = std::make_unique<views::WidgetDelegateView>();
249 delegate->SetPreferredSize(gfx::Size(400, 300));
250 params.delegate = delegate.release();
252 views::Widget widget;
253 params.context = GetContext();
254 widget.Init(std::move(params));
256 // Widget is centered on secondary display.
257 EXPECT_EQ(secondary_root, widget.GetNativeWindow()->GetRootWindow());
258 EXPECT_EQ(GetSecondaryDisplay().work_area().CenterPoint(),
259 widget.GetRestoredBounds().CenterPoint());
262 TEST_F(ShellTest, ChangeZOrderLevel) {
263 // Creates a normal window.
264 views::Widget* widget = TestWidgetBuilder().BuildOwnedByNativeWidget();
266 // It should be in the active desk container.
268 GetActiveDeskContainer()->Contains(widget->GetNativeWindow()->parent()));
270 // Set the z-order to float.
271 widget->SetZOrderLevel(ui::ZOrderLevel::kFloatingWindow);
272 // And it should in always on top container now.
273 EXPECT_EQ(GetAlwaysOnTopContainer(), widget->GetNativeWindow()->parent());
275 // Put the z-order back to normal.
276 widget->SetZOrderLevel(ui::ZOrderLevel::kNormal);
277 // It should go back to the active desk container.
279 GetActiveDeskContainer()->Contains(widget->GetNativeWindow()->parent()));
281 // Set the z-order again to the normal value.
282 widget->SetZOrderLevel(ui::ZOrderLevel::kNormal);
283 // Should have no effect and we are still in the the active desk container.
285 GetActiveDeskContainer()->Contains(widget->GetNativeWindow()->parent()));
290 TEST_F(ShellTest, CreateModalWindow) {
291 // Create a normal window.
292 views::Widget* widget = TestWidgetBuilder().BuildOwnedByNativeWidget();
294 // It should be in the active desk container.
296 GetActiveDeskContainer()->Contains(widget->GetNativeWindow()->parent()));
298 // Create a modal window.
299 views::Widget* modal_widget = views::Widget::CreateWindowWithParent(
300 CreateModalWidgetDelegate(), widget->GetNativeView());
301 modal_widget->Show();
303 // It should be in modal container.
304 aura::Window* modal_container = Shell::GetContainer(
305 Shell::GetPrimaryRootWindow(), kShellWindowId_SystemModalContainer);
306 EXPECT_EQ(modal_container, modal_widget->GetNativeWindow()->parent());
308 modal_widget->Close();
312 TEST_F(ShellTest, CreateLockScreenModalWindow) {
313 // Create a normal window.
314 views::Widget* widget = TestWidgetBuilder().BuildOwnedByNativeWidget();
315 EXPECT_TRUE(widget->GetNativeView()->HasFocus());
317 // It should be in the active desk container.
319 GetActiveDeskContainer()->Contains(widget->GetNativeWindow()->parent()));
321 GetSessionControllerClient()->LockScreen();
322 // Create a LockScreen window.
323 views::Widget* lock_widget =
324 TestWidgetBuilder().SetShow(false).BuildOwnedByNativeWidget();
325 Shell::GetContainer(Shell::GetPrimaryRootWindow(),
326 kShellWindowId_LockScreenContainer)
327 ->AddChild(lock_widget->GetNativeView());
329 EXPECT_TRUE(lock_widget->GetNativeView()->HasFocus());
331 // It should be in LockScreen container.
332 aura::Window* lock_screen = Shell::GetContainer(
333 Shell::GetPrimaryRootWindow(), kShellWindowId_LockScreenContainer);
334 EXPECT_EQ(lock_screen, lock_widget->GetNativeWindow()->parent());
336 // Create a modal window with a lock window as parent.
337 views::Widget* lock_modal_widget = views::Widget::CreateWindowWithParent(
338 CreateModalWidgetDelegate(), lock_widget->GetNativeView());
339 lock_modal_widget->Show();
340 EXPECT_TRUE(lock_modal_widget->GetNativeView()->HasFocus());
342 // It should be in LockScreen modal container.
343 aura::Window* lock_modal_container =
344 Shell::GetContainer(Shell::GetPrimaryRootWindow(),
345 kShellWindowId_LockSystemModalContainer);
346 EXPECT_EQ(lock_modal_container,
347 lock_modal_widget->GetNativeWindow()->parent());
349 // Create a modal window with a normal window as parent.
350 views::Widget* modal_widget = views::Widget::CreateWindowWithParent(
351 CreateModalWidgetDelegate(), widget->GetNativeView());
352 modal_widget->Show();
353 // Window on lock screen shouldn't lost focus.
354 EXPECT_FALSE(modal_widget->GetNativeView()->HasFocus());
355 EXPECT_TRUE(lock_modal_widget->GetNativeView()->HasFocus());
357 // It should be in non-LockScreen modal container.
358 aura::Window* modal_container = Shell::GetContainer(
359 Shell::GetPrimaryRootWindow(), kShellWindowId_SystemModalContainer);
360 EXPECT_EQ(modal_container, modal_widget->GetNativeWindow()->parent());
362 // Modal widget without parent, caused crash see crbug.com/226141
363 views::Widget* modal_dialog = views::DialogDelegate::CreateDialogWidget(
364 CreateModalWidgetDelegate(), GetContext(), nullptr);
366 modal_dialog->Show();
367 EXPECT_FALSE(modal_dialog->GetNativeView()->HasFocus());
368 EXPECT_TRUE(lock_modal_widget->GetNativeView()->HasFocus());
370 modal_dialog->Close();
371 modal_widget->Close();
372 modal_widget->Close();
373 lock_modal_widget->Close();
374 lock_widget->Close();
378 TEST_F(ShellTest, IsScreenLocked) {
379 SessionControllerImpl* controller = Shell::Get()->session_controller();
380 GetSessionControllerClient()->LockScreen();
381 EXPECT_TRUE(controller->IsScreenLocked());
382 GetSessionControllerClient()->UnlockScreen();
383 EXPECT_FALSE(controller->IsScreenLocked());
386 TEST_F(ShellTest, LockScreenClosesActiveMenu) {
387 SimpleMenuDelegate menu_delegate;
388 std::unique_ptr<ui::SimpleMenuModel> menu_model(
389 new ui::SimpleMenuModel(&menu_delegate));
390 menu_model->AddItem(0, u"Menu item");
391 views::Widget* widget = Shell::GetPrimaryRootWindowController()
392 ->wallpaper_widget_controller()
394 std::unique_ptr<views::MenuRunner> menu_runner(
395 new views::MenuRunner(menu_model.get(), views::MenuRunner::CONTEXT_MENU));
397 menu_runner->RunMenuAt(widget, nullptr, gfx::Rect(),
398 views::MenuAnchorPosition::kTopLeft,
399 ui::MENU_SOURCE_MOUSE);
400 LockScreenAndVerifyMenuClosed();
403 TEST_F(ShellTest, ManagedWindowModeBasics) {
404 // We start with the usual window containers.
405 ExpectAllContainers();
407 ShelfWidget* shelf_widget = GetPrimaryShelf()->shelf_widget();
408 EXPECT_TRUE(shelf_widget->IsVisible());
409 // Shelf is at bottom-left of screen.
410 EXPECT_EQ(0, shelf_widget->GetWindowBoundsInScreen().x());
412 Shell::GetPrimaryRootWindow()->GetHost()->GetBoundsInPixels().height(),
413 shelf_widget->GetWindowBoundsInScreen().bottom());
414 // We have a wallpaper but not a bare layer.
415 // TODO (antrim): enable once we find out why it fails component build.
416 // WallpaperWidgetController* wallpaper =
417 // Shell::GetPrimaryRootWindow()->
418 // GetProperty(kWindowDesktopComponent);
419 // EXPECT_TRUE(wallpaper);
420 // EXPECT_TRUE(wallpaper->widget());
421 // EXPECT_FALSE(wallpaper->layer());
423 // Create a normal window. It is not maximized.
424 views::Widget* widget = TestWidgetBuilder()
425 .SetBounds(gfx::Rect(11, 22, 300, 400))
426 .BuildOwnedByNativeWidget();
427 EXPECT_FALSE(widget->IsMaximized());
433 // Tests that the cursor-filter is ahead of the drag-drop controller in the
435 TEST_F(ShellTest, TestPreTargetHandlerOrder) {
436 Shell* shell = Shell::Get();
437 ui::EventTargetTestApi test_api(shell);
438 ShellTestApi shell_test_api;
440 ui::EventHandlerList handlers = test_api.GetPreTargetHandlers();
441 ui::EventHandlerList::const_iterator cursor_filter =
442 base::ranges::find(handlers, shell->mouse_cursor_filter());
443 ui::EventHandlerList::const_iterator drag_drop =
444 base::ranges::find(handlers, shell_test_api.drag_drop_controller());
445 EXPECT_NE(handlers.end(), cursor_filter);
446 EXPECT_NE(handlers.end(), drag_drop);
447 EXPECT_GT(drag_drop, cursor_filter);
450 // Tests that the accelerator_tracker is ahead of the accelerator_filter in the
451 // pre-target list to make sure the accelerators won't be filtered out before
452 // getting AcceleratorTracker.
453 TEST_F(ShellTest, AcceleratorPreTargetHandlerOrder) {
454 Shell* shell = Shell::Get();
455 ui::EventTargetTestApi test_api(shell);
457 ui::EventHandlerList handlers = test_api.GetPreTargetHandlers();
458 ui::EventHandlerList::const_iterator accelerator_tracker =
459 base::ranges::find(handlers, shell->accelerator_tracker());
460 ui::EventHandlerList::const_iterator accelerator_filter =
461 base::ranges::find(handlers, shell->accelerator_filter());
462 EXPECT_NE(handlers.end(), accelerator_tracker);
463 EXPECT_NE(handlers.end(), accelerator_filter);
464 EXPECT_GT(accelerator_filter, accelerator_tracker);
467 TEST_F(ShellTest, TestAccessibilityHandlerOrder) {
468 Shell* shell = Shell::Get();
469 ui::EventTargetTestApi test_api(shell);
470 ShellTestApi shell_test_api;
472 ui::EventHandler select_to_speak;
473 shell->AddAccessibilityEventHandler(
475 AccessibilityEventHandlerManager::HandlerType::kSelectToSpeak);
478 ui::EventHandlerList handlers = test_api.GetPreTargetHandlers();
480 ui::EventHandlerList::const_iterator cursor_filter =
481 base::ranges::find(handlers, shell->mouse_cursor_filter());
482 ui::EventHandlerList::const_iterator fullscreen_magnifier_filter =
483 base::ranges::find(handlers, shell->fullscreen_magnifier_controller());
484 ui::EventHandlerList::const_iterator chromevox_filter =
485 base::ranges::find(handlers, shell->key_accessibility_enabler());
486 ui::EventHandlerList::const_iterator select_to_speak_filter =
487 base::ranges::find(handlers, &select_to_speak);
488 EXPECT_NE(handlers.end(), cursor_filter);
489 EXPECT_NE(handlers.end(), fullscreen_magnifier_filter);
490 EXPECT_NE(handlers.end(), chromevox_filter);
491 EXPECT_NE(handlers.end(), select_to_speak_filter);
493 EXPECT_LT(cursor_filter, fullscreen_magnifier_filter);
494 EXPECT_LT(fullscreen_magnifier_filter, chromevox_filter);
495 EXPECT_LT(chromevox_filter, select_to_speak_filter);
498 shell->RemoveAccessibilityEventHandler(&select_to_speak);
500 handlers = test_api.GetPreTargetHandlers();
501 cursor_filter = base::ranges::find(handlers, shell->mouse_cursor_filter());
502 fullscreen_magnifier_filter =
503 base::ranges::find(handlers, shell->fullscreen_magnifier_controller());
505 base::ranges::find(handlers, shell->key_accessibility_enabler());
506 select_to_speak_filter = base::ranges::find(handlers, &select_to_speak);
507 EXPECT_NE(handlers.end(), cursor_filter);
508 EXPECT_NE(handlers.end(), fullscreen_magnifier_filter);
509 EXPECT_NE(handlers.end(), chromevox_filter);
510 EXPECT_EQ(handlers.end(), select_to_speak_filter);
512 // Ordering still works.
513 EXPECT_LT(cursor_filter, fullscreen_magnifier_filter);
514 EXPECT_LT(fullscreen_magnifier_filter, chromevox_filter);
516 // Adding another is correct.
517 ui::EventHandler docked_magnifier;
518 shell->AddAccessibilityEventHandler(
520 AccessibilityEventHandlerManager::HandlerType::kDockedMagnifier);
522 handlers = test_api.GetPreTargetHandlers();
523 cursor_filter = base::ranges::find(handlers, shell->mouse_cursor_filter());
524 fullscreen_magnifier_filter =
525 base::ranges::find(handlers, shell->fullscreen_magnifier_controller());
527 base::ranges::find(handlers, shell->key_accessibility_enabler());
528 ui::EventHandlerList::const_iterator docked_magnifier_filter =
529 base::ranges::find(handlers, &docked_magnifier);
530 EXPECT_NE(handlers.end(), cursor_filter);
531 EXPECT_NE(handlers.end(), fullscreen_magnifier_filter);
532 EXPECT_NE(handlers.end(), docked_magnifier_filter);
533 EXPECT_NE(handlers.end(), chromevox_filter);
535 // Inserted in proper order.
536 EXPECT_LT(cursor_filter, fullscreen_magnifier_filter);
537 EXPECT_LT(fullscreen_magnifier_filter, docked_magnifier_filter);
538 EXPECT_LT(docked_magnifier_filter, chromevox_filter);
541 // Verifies an EventHandler added to Env gets notified from EventGenerator.
542 TEST_F(ShellTest, EnvPreTargetHandler) {
543 ui::test::TestEventHandler event_handler;
544 aura::Env::GetInstance()->AddPreTargetHandler(&event_handler);
545 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
546 generator.MoveMouseBy(1, 1);
547 EXPECT_NE(0, event_handler.num_mouse_events());
548 aura::Env::GetInstance()->RemovePreTargetHandler(&event_handler);
551 // Verifies that pressing tab on an empty shell (one with no windows visible)
552 // will put focus on the shelf. This enables keyboard only users to get to the
553 // shelf without knowing the more obscure accelerators. Tab should move focus to
554 // the home button, shift + tab to the status widget. From there, normal shelf
555 // tab behaviour takes over, and the shell no longer catches that event.
556 TEST_F(ShellTest, NoWindowTabFocus) {
557 ExpectAllContainers();
559 StatusAreaWidget* status_area_widget =
560 GetPrimaryShelf()->status_area_widget();
561 ShelfNavigationWidget* home_button = GetPrimaryShelf()->navigation_widget();
563 // Create a normal window. It is not maximized.
564 auto widget = CreateTestWidget();
566 // Hit tab with window open, and expect that focus is not on the navigation
567 // widget or status widget.
568 PressAndReleaseKey(ui::VKEY_TAB);
569 EXPECT_FALSE(home_button->GetNativeView()->HasFocus());
570 EXPECT_FALSE(status_area_widget->GetNativeView()->HasFocus());
572 // Minimize the window, hit tab and expect that focus is on the launcher.
574 PressAndReleaseKey(ui::VKEY_TAB);
575 EXPECT_TRUE(home_button->GetNativeView()->HasFocus());
577 // Show (to steal focus back before continuing testing) and close the window.
580 EXPECT_FALSE(home_button->GetNativeView()->HasFocus());
582 // Confirm that pressing tab when overview mode is open does not go to home
583 // button. Tab should be handled by overview mode and not hit the shell event
586 PressAndReleaseKey(ui::VKEY_TAB);
587 EXPECT_FALSE(home_button->GetNativeView()->HasFocus());
590 // Hit shift tab and expect that focus is on status widget.
591 PressAndReleaseKey(ui::VKEY_TAB, ui::EF_SHIFT_DOWN);
592 EXPECT_TRUE(status_area_widget->GetNativeView()->HasFocus());
595 // This verifies WindowObservers are removed when a window is destroyed after
596 // the Shell is destroyed. This scenario (aura::Windows being deleted after the
597 // Shell) occurs if someone is holding a reference to an unparented Window, as
598 // is the case with a RenderWidgetHostViewAura that isn't on screen. As long as
599 // everything is ok, we won't crash. If there is a bug, window's destructor will
600 // notify some deleted object (say VideoDetector or ActivationController) and
602 class ShellTest2 : public AshTestBase {
604 ShellTest2() = default;
606 ShellTest2(const ShellTest2&) = delete;
607 ShellTest2& operator=(const ShellTest2&) = delete;
609 ~ShellTest2() override = default;
612 std::unique_ptr<aura::Window> window_;
615 TEST_F(ShellTest2, DontCrashWhenWindowDeleted) {
616 window_ = std::make_unique<aura::Window>(nullptr,
617 aura::client::WINDOW_TYPE_UNKNOWN);
618 window_->Init(ui::LAYER_NOT_DRAWN);
621 using ShellLoginTest = NoSessionAshTestBase;
623 TEST_F(ShellLoginTest, DragAndDropDisabledBeforeLogin) {
624 DragDropController* drag_drop_controller =
625 ShellTestApi().drag_drop_controller();
626 DragDropControllerTestApi drag_drop_controller_test_api(drag_drop_controller);
627 EXPECT_FALSE(drag_drop_controller_test_api.enabled());
629 SimulateUserLogin("user1@test.com");
630 EXPECT_TRUE(drag_drop_controller_test_api.enabled());
633 using NoDuplicateShellContainerIdsTest = AshTestBase;
635 TEST_F(NoDuplicateShellContainerIdsTest, ValidateContainersIds) {
636 ExpectAllContainers();