1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "ash/public/cpp/test/shell_test_api.h"
6 
7 #include <memory>
8 #include <utility>
9 
10 #include "ash/accelerators/accelerator_commands.h"
11 #include "ash/accelerometer/accelerometer_reader.h"
12 #include "ash/app_list/app_list_controller_impl.h"
13 #include "ash/app_list/views/app_list_view.h"
14 #include "ash/keyboard/keyboard_controller_impl.h"
15 #include "ash/public/cpp/autotest_private_api_utils.h"
16 #include "ash/public/cpp/tablet_mode_observer.h"
17 #include "ash/root_window_controller.h"
18 #include "ash/shell.h"
19 #include "ash/system/power/backlights_forced_off_setter.h"
20 #include "ash/system/power/power_button_controller.h"
21 #include "ash/wm/overview/overview_animation_state_waiter.h"
22 #include "ash/wm/overview/overview_controller.h"
23 #include "ash/wm/splitview/split_view_controller.h"
24 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
25 #include "ash/wm/workspace_controller.h"
26 #include "base/run_loop.h"
27 #include "components/prefs/testing_pref_service.h"
28 #include "ui/aura/window_tree_host.h"
29 #include "ui/compositor/compositor.h"
30 #include "ui/compositor/compositor_observer.h"
31 #include "ui/compositor/layer_animation_observer.h"
32 #include "ui/display/manager/display_manager.h"
33 #include "ui/events/devices/device_data_manager_test_api.h"
34 #include "ui/events/gesture_detection/gesture_configuration.h"
35 
36 namespace ash {
37 namespace {
38 
39 // Wait for a WindowTreeHost to no longer be holding pointer events.
40 class PointerMoveLoopWaiter : public ui::CompositorObserver {
41  public:
PointerMoveLoopWaiter(aura::WindowTreeHost * window_tree_host)42   explicit PointerMoveLoopWaiter(aura::WindowTreeHost* window_tree_host)
43       : window_tree_host_(window_tree_host) {
44     window_tree_host_->compositor()->AddObserver(this);
45   }
46 
~PointerMoveLoopWaiter()47   ~PointerMoveLoopWaiter() override {
48     window_tree_host_->compositor()->RemoveObserver(this);
49   }
50 
Wait()51   void Wait() {
52     // Use a while loop as it's possible for releasing the lock to trigger
53     // processing events, which again grabs the lock.
54     while (window_tree_host_->holding_pointer_moves()) {
55       run_loop_ = std::make_unique<base::RunLoop>(
56           base::RunLoop::Type::kNestableTasksAllowed);
57       run_loop_->Run();
58       run_loop_.reset();
59     }
60   }
61 
62   // ui::CompositorObserver:
OnCompositingEnded(ui::Compositor * compositor)63   void OnCompositingEnded(ui::Compositor* compositor) override {
64     if (run_loop_)
65       run_loop_->Quit();
66   }
67 
68  private:
69   aura::WindowTreeHost* window_tree_host_;
70   std::unique_ptr<base::RunLoop> run_loop_;
71 
72   DISALLOW_COPY_AND_ASSIGN(PointerMoveLoopWaiter);
73 };
74 
75 class WindowAnimationWaiter : public ui::LayerAnimationObserver {
76  public:
WindowAnimationWaiter(aura::Window * window)77   explicit WindowAnimationWaiter(aura::Window* window)
78       : animator_(window->layer()->GetAnimator()) {
79     animator_->AddObserver(this);
80   }
81   ~WindowAnimationWaiter() override = default;
82 
83   WindowAnimationWaiter(const WindowAnimationWaiter& other) = delete;
84   WindowAnimationWaiter& operator=(const WindowAnimationWaiter& rhs) = delete;
85 
86   // ui::LayerAnimationObserver:
OnLayerAnimationEnded(ui::LayerAnimationSequence * sequence)87   void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override {
88     if (!animator_->is_animating()) {
89       animator_->RemoveObserver(this);
90       run_loop_.Quit();
91     }
92   }
OnLayerAnimationAborted(ui::LayerAnimationSequence * sequence)93   void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override {}
OnLayerAnimationScheduled(ui::LayerAnimationSequence * sequence)94   void OnLayerAnimationScheduled(
95       ui::LayerAnimationSequence* sequence) override {}
96 
Wait()97   void Wait() {
98     run_loop_.Run();
99   }
100 
101  private:
102   ui::LayerAnimator* animator_;
103   base::RunLoop run_loop_;
104 };
105 
106 }  // namespace
107 
ShellTestApi()108 ShellTestApi::ShellTestApi() : shell_(Shell::Get()) {}
109 ShellTestApi::~ShellTestApi() = default;
110 
111 // static
SetTabletControllerUseScreenshotForTest(bool use_screenshot)112 void ShellTestApi::SetTabletControllerUseScreenshotForTest(
113     bool use_screenshot) {
114   TabletModeController::SetUseScreenshotForTest(use_screenshot);
115 }
116 
message_center_controller()117 MessageCenterController* ShellTestApi::message_center_controller() {
118   return shell_->message_center_controller_.get();
119 }
120 
system_gesture_event_filter()121 SystemGestureEventFilter* ShellTestApi::system_gesture_event_filter() {
122   return shell_->system_gesture_filter_.get();
123 }
124 
workspace_controller()125 WorkspaceController* ShellTestApi::workspace_controller() {
126   // TODO(afakhry): Split this into two, one for root, and one for context.
127   return GetActiveWorkspaceController(shell_->GetPrimaryRootWindow());
128 }
129 
screen_position_controller()130 ScreenPositionController* ShellTestApi::screen_position_controller() {
131   return shell_->screen_position_controller_.get();
132 }
133 
native_cursor_manager_ash()134 NativeCursorManagerAsh* ShellTestApi::native_cursor_manager_ash() {
135   return shell_->native_cursor_manager_;
136 }
137 
drag_drop_controller()138 DragDropController* ShellTestApi::drag_drop_controller() {
139   return shell_->drag_drop_controller_.get();
140 }
141 
power_prefs()142 PowerPrefs* ShellTestApi::power_prefs() {
143   return shell_->power_prefs_.get();
144 }
145 
display_manager()146 display::DisplayManager* ShellTestApi::display_manager() {
147   return shell_->display_manager();
148 }
149 
ResetPowerButtonControllerForTest()150 void ShellTestApi::ResetPowerButtonControllerForTest() {
151   shell_->backlights_forced_off_setter_->ResetForTest();
152   shell_->power_button_controller_ = std::make_unique<PowerButtonController>(
153       shell_->backlights_forced_off_setter_.get());
154 }
155 
SimulateModalWindowOpenForTest(bool modal_window_open)156 void ShellTestApi::SimulateModalWindowOpenForTest(bool modal_window_open) {
157   shell_->simulate_modal_window_open_for_test_ = modal_window_open;
158 }
159 
IsSystemModalWindowOpen()160 bool ShellTestApi::IsSystemModalWindowOpen() {
161   return Shell::IsSystemModalWindowOpen();
162 }
163 
SetTabletModeEnabledForTest(bool enable,bool wait_for_completion)164 void ShellTestApi::SetTabletModeEnabledForTest(bool enable,
165                                                bool wait_for_completion) {
166   // Detach mouse devices, so we can enter tablet mode.
167   // Calling RunUntilIdle() here is necessary before setting the mouse devices
168   // to prevent the callback from evdev thread from overwriting whatever we set
169   // here below. See `InputDeviceFactoryEvdevProxy::OnStartupScanComplete()`.
170   base::RunLoop().RunUntilIdle();
171   ui::DeviceDataManagerTestApi().OnDeviceListsComplete();
172   ui::DeviceDataManagerTestApi().SetMouseDevices({});
173 
174   TabletMode::Waiter waiter(enable);
175   shell_->tablet_mode_controller()->SetEnabledForTest(enable);
176   waiter.Wait();
177 }
178 
EnableVirtualKeyboard()179 void ShellTestApi::EnableVirtualKeyboard() {
180   shell_->keyboard_controller()->SetEnableFlag(
181       keyboard::KeyboardEnableFlag::kCommandLineEnabled);
182 }
183 
ToggleFullscreen()184 void ShellTestApi::ToggleFullscreen() {
185   accelerators::ToggleFullscreen();
186 }
187 
IsOverviewSelecting()188 bool ShellTestApi::IsOverviewSelecting() {
189   return shell_->overview_controller()->InOverviewSession();
190 }
191 
AddRemoveDisplay()192 void ShellTestApi::AddRemoveDisplay() {
193   shell_->display_manager()->AddRemoveDisplay();
194 }
195 
WaitForNoPointerHoldLock()196 void ShellTestApi::WaitForNoPointerHoldLock() {
197   aura::WindowTreeHost* primary_host =
198       Shell::GetPrimaryRootWindowController()->GetHost();
199   if (primary_host->holding_pointer_moves())
200     PointerMoveLoopWaiter(primary_host).Wait();
201 }
202 
WaitForNextFrame(base::OnceClosure closure)203 void ShellTestApi::WaitForNextFrame(base::OnceClosure closure) {
204   Shell::GetPrimaryRootWindowController()
205       ->GetHost()
206       ->compositor()
207       ->RequestPresentationTimeForNextFrame(base::BindOnce(
208           [](base::OnceClosure closure,
209              const gfx::PresentationFeedback& feedback) {
210             std::move(closure).Run();
211           },
212           std::move(closure)));
213 }
214 
WaitForOverviewAnimationState(OverviewAnimationState state)215 void ShellTestApi::WaitForOverviewAnimationState(OverviewAnimationState state) {
216   auto* overview_controller = shell_->overview_controller();
217   if (state == OverviewAnimationState::kEnterAnimationComplete &&
218       overview_controller->InOverviewSession() &&
219       !overview_controller->IsInStartAnimation()) {
220     // If there is no animation applied, call the callback immediately.
221     return;
222   }
223   if (state == OverviewAnimationState::kExitAnimationComplete &&
224       !overview_controller->InOverviewSession() &&
225       !overview_controller->IsCompletingShutdownAnimations()) {
226     // If there is no animation applied, call the callback immediately.
227     return;
228   }
229   base::RunLoop run_loop;
230   new OverviewAnimationStateWaiter(
231       state, base::BindOnce([](base::RunLoop* run_loop,
232                                bool finished) { run_loop->QuitWhenIdle(); },
233                             base::Unretained(&run_loop)));
234   run_loop.Run();
235 }
236 
WaitForLauncherAnimationState(AppListViewState target_state)237 void ShellTestApi::WaitForLauncherAnimationState(
238     AppListViewState target_state) {
239   base::RunLoop run_loop;
240   WaitForLauncherState(target_state, run_loop.QuitWhenIdleClosure());
241   run_loop.Run();
242 }
243 
WaitForWindowFinishAnimating(aura::Window * window)244 void ShellTestApi::WaitForWindowFinishAnimating(aura::Window* window) {
245   WindowAnimationWaiter waiter(window);
246   waiter.Wait();
247 }
248 
CreateWaiterForFinishingWindowAnimation(aura::Window * window)249 base::OnceClosure ShellTestApi::CreateWaiterForFinishingWindowAnimation(
250     aura::Window* window) {
251   auto waiter = std::make_unique<WindowAnimationWaiter>(window);
252   return base::BindOnce(&WindowAnimationWaiter::Wait, std::move(waiter));
253 }
254 
GetAppListPaginationModel()255 PaginationModel* ShellTestApi::GetAppListPaginationModel() {
256   AppListView* view =
257       Shell::Get()->app_list_controller()->presenter()->GetView();
258   if (!view)
259     return nullptr;
260   return view->GetAppsPaginationModel();
261 }
262 
GetItemWindowListInOverviewGrids()263 std::vector<aura::Window*> ShellTestApi::GetItemWindowListInOverviewGrids() {
264   return Shell::Get()
265       ->overview_controller()
266       ->GetItemWindowListInOverviewGridsForTest();
267 }
268 
269 }  // namespace ash
270