ash_focus_rules_unittest.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. // Copyright 2015 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. #include <memory>
  5. #include "ash/public/cpp/shell_window_ids.h"
  6. #include "ash/session/session_controller_impl.h"
  7. #include "ash/session/test_pref_service_provider.h"
  8. #include "ash/session/test_session_controller_client.h"
  9. #include "ash/shelf/shelf.h"
  10. #include "ash/shell.h"
  11. #include "ash/test/ash_test_base.h"
  12. #include "ash/test/ash_test_helper.h"
  13. #include "ash/wm/desks/desks_util.h"
  14. #include "ash/wm/lock_state_controller.h"
  15. #include "ash/wm/window_state.h"
  16. #include "ash/wm/window_util.h"
  17. #include "ui/aura/client/aura_constants.h"
  18. #include "ui/aura/client/window_parenting_client.h"
  19. #include "ui/aura/window.h"
  20. #include "ui/base/ui_base_types.h"
  21. #include "ui/views/test/widget_test.h"
  22. #include "ui/views/view.h"
  23. #include "ui/views/widget/widget.h"
  24. #include "ui/wm/core/window_util.h"
  25. namespace ash {
  26. namespace {
  27. // Defines a |SessionControllerClient| that is used to create and destroy the
  28. // test lock screen widget.
  29. class LockScreenSessionControllerClient : public TestSessionControllerClient {
  30. public:
  31. LockScreenSessionControllerClient(SessionControllerImpl* controller,
  32. TestPrefServiceProvider* prefs_provider)
  33. : TestSessionControllerClient(controller, prefs_provider) {
  34. InitializeAndSetClient();
  35. CreatePredefinedUserSessions(1);
  36. }
  37. LockScreenSessionControllerClient(const LockScreenSessionControllerClient&) =
  38. delete;
  39. LockScreenSessionControllerClient& operator=(
  40. const LockScreenSessionControllerClient&) = delete;
  41. ~LockScreenSessionControllerClient() override = default;
  42. // TestSessionControllerClient:
  43. void RequestLockScreen() override {
  44. TestSessionControllerClient::RequestLockScreen();
  45. CreateLockScreen();
  46. Shelf::UpdateShelfVisibility();
  47. }
  48. void UnlockScreen() override {
  49. TestSessionControllerClient::UnlockScreen();
  50. if (lock_screen_widget_.get()) {
  51. lock_screen_widget_->Close();
  52. lock_screen_widget_.reset(nullptr);
  53. }
  54. Shelf::UpdateShelfVisibility();
  55. }
  56. private:
  57. void CreateLockScreen() {
  58. auto lock_view = std::make_unique<views::View>();
  59. lock_screen_widget_ = std::make_unique<views::Widget>();
  60. views::Widget::InitParams params(
  61. views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
  62. gfx::Size ps = lock_view->GetPreferredSize();
  63. gfx::Size root_window_size = Shell::GetPrimaryRootWindow()->bounds().size();
  64. params.bounds = gfx::Rect((root_window_size.width() - ps.width()) / 2,
  65. (root_window_size.height() - ps.height()) / 2,
  66. ps.width(), ps.height());
  67. params.parent = Shell::GetContainer(Shell::GetPrimaryRootWindow(),
  68. kShellWindowId_LockScreenContainer);
  69. params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
  70. lock_screen_widget_->Init(std::move(params));
  71. lock_screen_widget_->SetContentsView(std::move(lock_view));
  72. lock_screen_widget_->Show();
  73. lock_screen_widget_->GetNativeView()->SetName("LockView");
  74. lock_screen_widget_->GetNativeView()->Focus();
  75. }
  76. std::unique_ptr<views::Widget> lock_screen_widget_;
  77. };
  78. ////////////////////////////////////////////////////////////////////////////////
  79. // Defines a class that will be used to test the correct behavior of
  80. // |AshFocusRules| when locking and unlocking the screen.
  81. class LockScreenAshFocusRulesTest : public AshTestBase {
  82. public:
  83. LockScreenAshFocusRulesTest() = default;
  84. LockScreenAshFocusRulesTest(const LockScreenAshFocusRulesTest&) = delete;
  85. LockScreenAshFocusRulesTest& operator=(const LockScreenAshFocusRulesTest&) =
  86. delete;
  87. ~LockScreenAshFocusRulesTest() override = default;
  88. void SetUp() override {
  89. AshTestBase::SetUp();
  90. ash_test_helper()->set_test_session_controller_client(
  91. std::make_unique<LockScreenSessionControllerClient>(
  92. Shell::Get()->session_controller(),
  93. ash_test_helper()->prefs_provider()));
  94. }
  95. aura::Window* CreateWindowInActiveDesk() {
  96. return CreateWindowInContainer(desks_util::GetActiveDeskContainerId());
  97. }
  98. aura::Window* CreateWindowInAppListContainer() {
  99. return CreateWindowInContainer(kShellWindowId_AppListContainer);
  100. }
  101. aura::Window* CreateWindowInAlwaysOnTopContainer() {
  102. aura::Window* window =
  103. CreateWindowInContainer(kShellWindowId_AlwaysOnTopContainer);
  104. window->SetProperty(aura::client::kZOrderingKey,
  105. ui::ZOrderLevel::kFloatingWindow);
  106. return window;
  107. }
  108. aura::Window* CreateWindowInLockContainer() {
  109. return CreateWindowInContainer(kShellWindowId_LockScreenContainer);
  110. }
  111. aura::Window* CreateWindowInShelfContainer() {
  112. return CreateWindowInContainer(kShellWindowId_ShelfContainer);
  113. }
  114. aura::Window* CreateWindowInLockSystemModalContainer() {
  115. aura::Window* window =
  116. CreateWindowInContainer(kShellWindowId_LockSystemModalContainer);
  117. window->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_SYSTEM);
  118. return window;
  119. }
  120. aura::Window* CreateWindowInSystemModalContainer() {
  121. aura::Window* window =
  122. CreateWindowInContainer(kShellWindowId_SystemModalContainer);
  123. window->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_SYSTEM);
  124. return window;
  125. }
  126. private:
  127. aura::Window* CreateWindowInContainer(int container_id) {
  128. aura::Window* root_window = Shell::GetPrimaryRootWindow();
  129. aura::Window* container = Shell::GetContainer(root_window, container_id);
  130. aura::Window* window = new aura::Window(nullptr);
  131. window->SetId(0);
  132. window->SetType(aura::client::WINDOW_TYPE_NORMAL);
  133. window->Init(ui::LAYER_TEXTURED);
  134. window->Show();
  135. window->SetProperty(aura::client::kResizeBehaviorKey,
  136. aura::client::kResizeBehaviorCanMaximize |
  137. aura::client::kResizeBehaviorCanMinimize |
  138. aura::client::kResizeBehaviorCanResize);
  139. container->AddChild(window);
  140. return window;
  141. }
  142. std::unique_ptr<LockScreenSessionControllerClient> session_controller_client_;
  143. };
  144. } // namespace
  145. // Verifies focus is returned (after unlocking the screen) to the most recent
  146. // window that had it before locking the screen.
  147. TEST_F(LockScreenAshFocusRulesTest, RegainFocusAfterUnlock) {
  148. std::unique_ptr<aura::Window> normal_window(CreateWindowInActiveDesk());
  149. std::unique_ptr<aura::Window> always_on_top_window(
  150. CreateWindowInAlwaysOnTopContainer());
  151. wm::ActivateWindow(always_on_top_window.get());
  152. wm::ActivateWindow(normal_window.get());
  153. EXPECT_TRUE(wm::IsActiveWindow(normal_window.get()));
  154. EXPECT_TRUE(normal_window->IsVisible());
  155. EXPECT_TRUE(always_on_top_window->IsVisible());
  156. EXPECT_TRUE(normal_window->HasFocus());
  157. EXPECT_FALSE(always_on_top_window->HasFocus());
  158. WindowState* normal_window_state = WindowState::Get(normal_window.get());
  159. WindowState* always_on_top_window_state =
  160. WindowState::Get(always_on_top_window.get());
  161. EXPECT_TRUE(normal_window_state->CanActivate());
  162. EXPECT_TRUE(always_on_top_window_state->CanActivate());
  163. BlockUserSession(BLOCKED_BY_LOCK_SCREEN);
  164. EXPECT_TRUE(Shell::Get()->session_controller()->IsScreenLocked());
  165. EXPECT_FALSE(normal_window->HasFocus());
  166. EXPECT_FALSE(always_on_top_window->HasFocus());
  167. EXPECT_FALSE(normal_window_state->IsMinimized());
  168. EXPECT_FALSE(always_on_top_window_state->IsMinimized());
  169. EXPECT_FALSE(normal_window_state->CanActivate());
  170. EXPECT_FALSE(always_on_top_window_state->CanActivate());
  171. UnblockUserSession();
  172. EXPECT_FALSE(Shell::Get()->session_controller()->IsScreenLocked());
  173. EXPECT_FALSE(normal_window_state->IsMinimized());
  174. EXPECT_FALSE(always_on_top_window_state->IsMinimized());
  175. EXPECT_TRUE(normal_window_state->CanActivate());
  176. EXPECT_TRUE(always_on_top_window_state->CanActivate());
  177. EXPECT_FALSE(always_on_top_window->HasFocus());
  178. EXPECT_TRUE(normal_window->HasFocus());
  179. }
  180. // Tests that if a widget has a view which should be initially focused, this
  181. // view doesn't get focused if the widget shows behind the lock screen.
  182. TEST_F(LockScreenAshFocusRulesTest, PreventFocusChangeWithLockScreenPresent) {
  183. BlockUserSession(BLOCKED_BY_LOCK_SCREEN);
  184. EXPECT_TRUE(Shell::Get()->session_controller()->IsScreenLocked());
  185. views::test::TestInitialFocusWidgetDelegate delegate(GetContext());
  186. EXPECT_FALSE(delegate.view()->HasFocus());
  187. delegate.GetWidget()->Show();
  188. EXPECT_FALSE(delegate.GetWidget()->IsActive());
  189. EXPECT_FALSE(delegate.view()->HasFocus());
  190. UnblockUserSession();
  191. EXPECT_FALSE(Shell::Get()->session_controller()->IsScreenLocked());
  192. EXPECT_TRUE(delegate.GetWidget()->IsActive());
  193. EXPECT_TRUE(delegate.view()->HasFocus());
  194. }
  195. // Verifies that a window in lock container cannot be activated if a lock
  196. // system modal window is shown.
  197. TEST_F(LockScreenAshFocusRulesTest,
  198. PreventLockScreenActivationUnderLockSystemModalWindow) {
  199. // System modal window - given that it's not lock system modal, it should
  200. // have no impact on activation of windows while user session is locked.
  201. std::unique_ptr<aura::Window> system_modal_window(
  202. CreateWindowInSystemModalContainer());
  203. EXPECT_TRUE(wm::IsActiveWindow(system_modal_window.get()));
  204. BlockUserSession(BLOCKED_BY_LOCK_SCREEN);
  205. EXPECT_TRUE(Shell::Get()->session_controller()->IsScreenLocked());
  206. std::unique_ptr<aura::Window> lock_window(CreateWindowInLockContainer());
  207. std::unique_ptr<aura::Window> lock_system_modal_window(
  208. CreateWindowInLockSystemModalContainer());
  209. EXPECT_TRUE(wm::IsActiveWindow(lock_system_modal_window.get()));
  210. // Try to activate a lock container window - it should not succeed if a lock
  211. // system modal dialog is present.
  212. wm::ActivateWindow(lock_window.get());
  213. EXPECT_TRUE(wm::IsActiveWindow(lock_system_modal_window.get()));
  214. lock_system_modal_window.reset();
  215. // Activating lock window should succeed after system modal widnow is closed.
  216. wm::ActivateWindow(lock_window.get());
  217. EXPECT_TRUE(wm::IsActiveWindow(lock_window.get()));
  218. lock_window.reset();
  219. EXPECT_FALSE(wm::IsActiveWindow(system_modal_window.get()));
  220. UnblockUserSession();
  221. // Upon unlocking the session, the system modal window should be reactivated.
  222. EXPECT_TRUE(wm::IsActiveWindow(system_modal_window.get()));
  223. }
  224. // Verifies that the shelf can be activated in login/lock screen even if there
  225. // is a lock system modal present.
  226. TEST_F(LockScreenAshFocusRulesTest,
  227. AllowShelfActivationWithLockSystemModalWindow) {
  228. BlockUserSession(BLOCKED_BY_LOCK_SCREEN);
  229. EXPECT_TRUE(Shell::Get()->session_controller()->IsScreenLocked());
  230. std::unique_ptr<aura::Window> lock_window(CreateWindowInLockContainer());
  231. std::unique_ptr<aura::Window> lock_shelf_window(
  232. CreateWindowInShelfContainer());
  233. std::unique_ptr<aura::Window> lock_system_modal_window(
  234. CreateWindowInLockSystemModalContainer());
  235. EXPECT_TRUE(wm::IsActiveWindow(lock_system_modal_window.get()));
  236. wm::ActivateWindow(lock_shelf_window.get());
  237. EXPECT_TRUE(wm::IsActiveWindow(lock_shelf_window.get()));
  238. }
  239. // Simulates a transient child dialog of the applist when it gets closed and
  240. // loses focus, the focus should be returned to the applist transient parent,
  241. // not to another window in the MRU list. https://crbug.com/950469.
  242. TEST_F(LockScreenAshFocusRulesTest, TransientChildLosingFocus) {
  243. std::unique_ptr<aura::Window> normal_window(CreateWindowInActiveDesk());
  244. std::unique_ptr<aura::Window> transient_parent(
  245. CreateWindowInAppListContainer());
  246. std::unique_ptr<aura::Window> transient_child(
  247. CreateWindowInAppListContainer());
  248. ::wm::AddTransientChild(transient_parent.get(), transient_child.get());
  249. wm::ActivateWindow(transient_child.get());
  250. EXPECT_TRUE(wm::IsActiveWindow(transient_child.get()));
  251. transient_child->Hide();
  252. EXPECT_TRUE(wm::IsActiveWindow(transient_parent.get()));
  253. }
  254. } // namespace ash