shelf_controller_unittest.cc 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. // Copyright 2017 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 "ash/shelf/shelf_controller.h"
  5. #include <string>
  6. #include "ash/constants/ash_pref_names.h"
  7. #include "ash/public/cpp/shelf_item_delegate.h"
  8. #include "ash/public/cpp/shelf_model.h"
  9. #include "ash/public/cpp/shelf_prefs.h"
  10. #include "ash/public/cpp/test/test_shelf_item_delegate.h"
  11. #include "ash/public/cpp/window_properties.h"
  12. #include "ash/root_window_controller.h"
  13. #include "ash/session/session_controller_impl.h"
  14. #include "ash/session/test_session_controller_client.h"
  15. #include "ash/shelf/shelf.h"
  16. #include "ash/shell.h"
  17. #include "ash/test/ash_test_base.h"
  18. #include "ash/test/ash_test_helper.h"
  19. #include "ash/test_shell_delegate.h"
  20. #include "ash/wm/tablet_mode/tablet_mode_controller.h"
  21. #include "ash/wm/window_util.h"
  22. #include "base/run_loop.h"
  23. #include "base/strings/utf_string_conversions.h"
  24. #include "components/account_id/account_id.h"
  25. #include "components/prefs/pref_service.h"
  26. #include "testing/gtest/include/gtest/gtest.h"
  27. #include "ui/gfx/image/image_unittest_util.h"
  28. #include "ui/message_center/message_center.h"
  29. #include "ui/message_center/public/cpp/notifier_id.h"
  30. namespace ash {
  31. Shelf* GetShelfForDisplay(int64_t display_id) {
  32. return Shell::GetRootWindowControllerWithDisplayId(display_id)->shelf();
  33. }
  34. using ShelfControllerTest = AshTestBase;
  35. TEST_F(ShelfControllerTest, Shutdown) {
  36. // Simulate a display change occurring during shutdown (e.g. due to a screen
  37. // rotation animation being canceled).
  38. Shell::Get()->shelf_controller()->Shutdown();
  39. display_manager()->SetDisplayRotation(
  40. display::Screen::GetScreen()->GetPrimaryDisplay().id(),
  41. display::Display::ROTATE_90, display::Display::RotationSource::ACTIVE);
  42. // Ash does not crash during cleanup.
  43. }
  44. TEST_F(ShelfControllerTest, ShelfIDUpdate) {
  45. ShelfModel* model = Shell::Get()->shelf_controller()->model();
  46. const ShelfID id1("id1");
  47. const ShelfID id2("id2");
  48. std::unique_ptr<aura::Window> window(
  49. CreateTestWindow(gfx::Rect(0, 0, 100, 100)));
  50. window->SetProperty(kShelfIDKey, id1.Serialize());
  51. wm::ActivateWindow(window.get());
  52. EXPECT_EQ(id1, model->active_shelf_id());
  53. window->SetProperty(kShelfIDKey, id2.Serialize());
  54. EXPECT_EQ(id2, model->active_shelf_id());
  55. window->ClearProperty(kShelfIDKey);
  56. EXPECT_NE(id1, model->active_shelf_id());
  57. EXPECT_NE(id2, model->active_shelf_id());
  58. }
  59. class ShelfControllerNotificationIndicatorTest : public AshTestBase {
  60. public:
  61. ShelfControllerNotificationIndicatorTest() = default;
  62. ShelfControllerNotificationIndicatorTest(
  63. const ShelfControllerNotificationIndicatorTest&) = delete;
  64. ShelfControllerNotificationIndicatorTest& operator=(
  65. const ShelfControllerNotificationIndicatorTest&) = delete;
  66. ~ShelfControllerNotificationIndicatorTest() override = default;
  67. void SetUp() override {
  68. AshTestBase::SetUp();
  69. account_id_ = AccountId::FromUserEmail("test@gmail.com");
  70. }
  71. void SendAppUpdate(bool app_has_badge) {
  72. ShelfController* controller = Shell::Get()->shelf_controller();
  73. auto test_app = std::make_unique<apps::App>(apps::AppType::kArc, "app_id");
  74. test_app->has_badge = app_has_badge;
  75. apps::AppUpdate test_update(nullptr, /*delta=*/test_app.get(), account_id_);
  76. static_cast<apps::AppRegistryCache::Observer*>(controller)
  77. ->OnAppUpdate(test_update);
  78. }
  79. private:
  80. AccountId account_id_;
  81. };
  82. // Tests that the ShelfController keeps the ShelfModel updated on calls to
  83. // OnAppUpdate().
  84. TEST_F(ShelfControllerNotificationIndicatorTest, HasNotificationBasic) {
  85. ShelfController* controller = Shell::Get()->shelf_controller();
  86. const std::string app_id("app_id");
  87. ShelfItem item;
  88. item.type = TYPE_APP;
  89. item.id = ShelfID(app_id);
  90. const int index = controller->model()->Add(
  91. item, std::make_unique<TestShelfItemDelegate>(item.id));
  92. EXPECT_FALSE(controller->model()->items()[index].has_notification);
  93. // Send an app update to ShelfController for adding a notification badge.
  94. SendAppUpdate(true /* app_has_badge */);
  95. EXPECT_TRUE(controller->model()->items()[index].has_notification);
  96. // Send an app update to ShelfController for removing a notification badge.
  97. SendAppUpdate(false /* app_has_badge */);
  98. EXPECT_FALSE(controller->model()->items()[index].has_notification);
  99. }
  100. class ShelfControllerPrefsTest : public AshTestBase {
  101. public:
  102. ShelfControllerPrefsTest() = default;
  103. ShelfControllerPrefsTest(const ShelfControllerPrefsTest&) = delete;
  104. ShelfControllerPrefsTest& operator=(const ShelfControllerPrefsTest&) = delete;
  105. ~ShelfControllerPrefsTest() override = default;
  106. };
  107. // Ensure shelf settings are updated on preference changes.
  108. TEST_F(ShelfControllerPrefsTest, ShelfRespectsPrefs) {
  109. Shelf* shelf = GetPrimaryShelf();
  110. EXPECT_EQ(ShelfAlignment::kBottom, shelf->alignment());
  111. EXPECT_EQ(ShelfAutoHideBehavior::kNever, shelf->auto_hide_behavior());
  112. PrefService* prefs =
  113. Shell::Get()->session_controller()->GetLastActiveUserPrefService();
  114. prefs->SetString(prefs::kShelfAlignmentLocal, "Left");
  115. prefs->SetString(prefs::kShelfAutoHideBehaviorLocal, "Always");
  116. EXPECT_EQ(ShelfAlignment::kLeft, shelf->alignment());
  117. EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
  118. }
  119. // Ensure shelf settings are updated on per-display preference changes.
  120. TEST_F(ShelfControllerPrefsTest, ShelfRespectsPerDisplayPrefs) {
  121. UpdateDisplay("1024x768,800x600");
  122. base::RunLoop().RunUntilIdle();
  123. const int64_t id1 = GetPrimaryDisplay().id();
  124. const int64_t id2 = GetSecondaryDisplay().id();
  125. Shelf* shelf1 = GetShelfForDisplay(id1);
  126. Shelf* shelf2 = GetShelfForDisplay(id2);
  127. EXPECT_EQ(ShelfAlignment::kBottom, shelf1->alignment());
  128. EXPECT_EQ(ShelfAlignment::kBottom, shelf2->alignment());
  129. EXPECT_EQ(ShelfAutoHideBehavior::kNever, shelf1->auto_hide_behavior());
  130. EXPECT_EQ(ShelfAutoHideBehavior::kNever, shelf2->auto_hide_behavior());
  131. PrefService* prefs =
  132. Shell::Get()->session_controller()->GetLastActiveUserPrefService();
  133. SetShelfAlignmentPref(prefs, id1, ShelfAlignment::kLeft);
  134. SetShelfAlignmentPref(prefs, id2, ShelfAlignment::kRight);
  135. SetShelfAutoHideBehaviorPref(prefs, id1, ShelfAutoHideBehavior::kAlways);
  136. SetShelfAutoHideBehaviorPref(prefs, id2, ShelfAutoHideBehavior::kAlways);
  137. EXPECT_EQ(ShelfAlignment::kLeft, shelf1->alignment());
  138. EXPECT_EQ(ShelfAlignment::kRight, shelf2->alignment());
  139. EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf1->auto_hide_behavior());
  140. EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf2->auto_hide_behavior());
  141. }
  142. // Ensures that pre-Unified Mode per-display shelf settings don't prevent us
  143. // from changing the shelf settings in unified mode.
  144. TEST_F(ShelfControllerPrefsTest, ShelfRespectsPerDisplayPrefsUnified) {
  145. UpdateDisplay("1024x768,800x600");
  146. // Before enabling Unified Mode, set the shelf alignment for one of the two
  147. // displays, so that we have a per-display shelf alignment setting.
  148. ASSERT_FALSE(display_manager()->IsInUnifiedMode());
  149. const int64_t non_unified_primary_id = GetPrimaryDisplay().id();
  150. PrefService* prefs =
  151. Shell::Get()->session_controller()->GetLastActiveUserPrefService();
  152. Shelf* shelf = GetShelfForDisplay(non_unified_primary_id);
  153. EXPECT_EQ(ShelfAlignment::kBottom, shelf->alignment());
  154. SetShelfAlignmentPref(prefs, non_unified_primary_id, ShelfAlignment::kLeft);
  155. EXPECT_EQ(ShelfAlignment::kLeft, shelf->alignment());
  156. // Switch to Unified Mode, and expect to be able to change the shelf
  157. // alignment.
  158. display_manager()->SetUnifiedDesktopEnabled(true);
  159. ASSERT_TRUE(display_manager()->IsInUnifiedMode());
  160. const int64_t unified_id = display::kUnifiedDisplayId;
  161. ASSERT_EQ(unified_id, GetPrimaryDisplay().id());
  162. shelf = GetShelfForDisplay(unified_id);
  163. EXPECT_EQ(ShelfAlignment::kBottom, shelf->alignment());
  164. EXPECT_EQ(ShelfAutoHideBehavior::kNever, shelf->auto_hide_behavior());
  165. SetShelfAlignmentPref(prefs, unified_id, ShelfAlignment::kLeft);
  166. SetShelfAutoHideBehaviorPref(prefs, unified_id,
  167. ShelfAutoHideBehavior::kAlways);
  168. EXPECT_EQ(ShelfAlignment::kLeft, shelf->alignment());
  169. EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
  170. SetShelfAlignmentPref(prefs, unified_id, ShelfAlignment::kRight);
  171. EXPECT_EQ(ShelfAlignment::kRight, shelf->alignment());
  172. }
  173. // Ensure shelf settings are correct after display swap at login screen, see
  174. // crbug.com/748291
  175. TEST_F(ShelfControllerPrefsTest,
  176. ShelfSettingsValidAfterDisplaySwapAtLoginScreen) {
  177. // Simulate adding an external display at the lock screen.
  178. GetSessionControllerClient()->RequestLockScreen();
  179. UpdateDisplay("1024x768,800x600");
  180. base::RunLoop().RunUntilIdle();
  181. const int64_t internal_display_id = GetPrimaryDisplay().id();
  182. const int64_t external_display_id = GetSecondaryDisplay().id();
  183. // The primary shelf should be on the internal display.
  184. EXPECT_EQ(GetPrimaryShelf(), GetShelfForDisplay(internal_display_id));
  185. EXPECT_NE(GetPrimaryShelf(), GetShelfForDisplay(external_display_id));
  186. PrefService* prefs =
  187. Shell::Get()->session_controller()->GetLastActiveUserPrefService();
  188. // Check for the default shelf preferences.
  189. EXPECT_EQ(ShelfAutoHideBehavior::kNever,
  190. GetShelfAutoHideBehaviorPref(prefs, internal_display_id));
  191. EXPECT_EQ(ShelfAutoHideBehavior::kNever,
  192. GetShelfAutoHideBehaviorPref(prefs, external_display_id));
  193. EXPECT_EQ(ShelfAlignment::kBottom,
  194. GetShelfAlignmentPref(prefs, internal_display_id));
  195. EXPECT_EQ(ShelfAlignment::kBottom,
  196. GetShelfAlignmentPref(prefs, external_display_id));
  197. // Check the current state; shelves have locked alignments in the lock screen.
  198. EXPECT_EQ(ShelfAutoHideBehavior::kNever,
  199. GetShelfForDisplay(internal_display_id)->auto_hide_behavior());
  200. EXPECT_EQ(ShelfAutoHideBehavior::kNever,
  201. GetShelfForDisplay(external_display_id)->auto_hide_behavior());
  202. EXPECT_EQ(ShelfAlignment::kBottomLocked,
  203. GetShelfForDisplay(internal_display_id)->alignment());
  204. EXPECT_EQ(ShelfAlignment::kBottomLocked,
  205. GetShelfForDisplay(external_display_id)->alignment());
  206. // Set some shelf prefs to differentiate the two shelves, check state.
  207. SetShelfAlignmentPref(prefs, internal_display_id, ShelfAlignment::kLeft);
  208. SetShelfAlignmentPref(prefs, external_display_id, ShelfAlignment::kRight);
  209. EXPECT_EQ(ShelfAlignment::kBottomLocked,
  210. GetShelfForDisplay(internal_display_id)->alignment());
  211. EXPECT_EQ(ShelfAlignment::kBottomLocked,
  212. GetShelfForDisplay(external_display_id)->alignment());
  213. SetShelfAutoHideBehaviorPref(prefs, external_display_id,
  214. ShelfAutoHideBehavior::kAlways);
  215. EXPECT_EQ(ShelfAutoHideBehavior::kNever,
  216. GetShelfForDisplay(internal_display_id)->auto_hide_behavior());
  217. EXPECT_EQ(ShelfAutoHideBehavior::kAlways,
  218. GetShelfForDisplay(external_display_id)->auto_hide_behavior());
  219. // Simulate the external display becoming the primary display. The shelves are
  220. // swapped (each instance now has a different display id), check state.
  221. SwapPrimaryDisplay();
  222. base::RunLoop().RunUntilIdle();
  223. EXPECT_EQ(ShelfAlignment::kBottomLocked,
  224. GetShelfForDisplay(internal_display_id)->alignment());
  225. EXPECT_EQ(ShelfAlignment::kBottomLocked,
  226. GetShelfForDisplay(external_display_id)->alignment());
  227. EXPECT_EQ(ShelfAutoHideBehavior::kNever,
  228. GetShelfForDisplay(internal_display_id)->auto_hide_behavior());
  229. EXPECT_EQ(ShelfAutoHideBehavior::kAlways,
  230. GetShelfForDisplay(external_display_id)->auto_hide_behavior());
  231. // After screen unlock the shelves should have the expected alignment values.
  232. GetSessionControllerClient()->UnlockScreen();
  233. base::RunLoop().RunUntilIdle();
  234. EXPECT_EQ(ShelfAlignment::kLeft,
  235. GetShelfForDisplay(internal_display_id)->alignment());
  236. EXPECT_EQ(ShelfAlignment::kRight,
  237. GetShelfForDisplay(external_display_id)->alignment());
  238. EXPECT_EQ(ShelfAutoHideBehavior::kNever,
  239. GetShelfForDisplay(internal_display_id)->auto_hide_behavior());
  240. EXPECT_EQ(ShelfAutoHideBehavior::kAlways,
  241. GetShelfForDisplay(external_display_id)->auto_hide_behavior());
  242. }
  243. // Test display swap while logged in, which was causing a crash (see
  244. // crbug.com/1022852)
  245. TEST_F(ShelfControllerPrefsTest,
  246. ShelfSettingsValidAfterDisplaySwapWhileLoggedIn) {
  247. // Simulate adding an external display at the lock screen.
  248. GetSessionControllerClient()->RequestLockScreen();
  249. UpdateDisplay("1024x768,800x600");
  250. base::RunLoop().RunUntilIdle();
  251. const int64_t internal_display_id = GetPrimaryDisplay().id();
  252. const int64_t external_display_id = GetSecondaryDisplay().id();
  253. PrefService* prefs =
  254. Shell::Get()->session_controller()->GetLastActiveUserPrefService();
  255. // Set some shelf prefs to differentiate the two shelves.
  256. SetShelfAlignmentPref(prefs, internal_display_id, ShelfAlignment::kLeft);
  257. SetShelfAlignmentPref(prefs, external_display_id, ShelfAlignment::kRight);
  258. SetShelfAutoHideBehaviorPref(prefs, external_display_id,
  259. ShelfAutoHideBehavior::kAlways);
  260. // Unlock the screen.
  261. GetSessionControllerClient()->UnlockScreen();
  262. base::RunLoop().RunUntilIdle();
  263. // Simulate the external display becoming the primary display. The shelves are
  264. // swapped (each instance now has a different display id), check state.
  265. SwapPrimaryDisplay();
  266. base::RunLoop().RunUntilIdle();
  267. EXPECT_EQ(ShelfAlignment::kLeft,
  268. GetShelfForDisplay(internal_display_id)->alignment());
  269. EXPECT_EQ(ShelfAlignment::kRight,
  270. GetShelfForDisplay(external_display_id)->alignment());
  271. EXPECT_EQ(ShelfAutoHideBehavior::kNever,
  272. GetShelfForDisplay(internal_display_id)->auto_hide_behavior());
  273. EXPECT_EQ(ShelfAutoHideBehavior::kAlways,
  274. GetShelfForDisplay(external_display_id)->auto_hide_behavior());
  275. }
  276. TEST_F(ShelfControllerPrefsTest, ShelfSettingsInTabletMode) {
  277. Shelf* shelf = GetPrimaryShelf();
  278. PrefService* prefs =
  279. Shell::Get()->session_controller()->GetLastActiveUserPrefService();
  280. SetShelfAlignmentPref(prefs, GetPrimaryDisplay().id(), ShelfAlignment::kLeft);
  281. SetShelfAutoHideBehaviorPref(prefs, GetPrimaryDisplay().id(),
  282. ShelfAutoHideBehavior::kAlways);
  283. ASSERT_EQ(ShelfAlignment::kLeft, shelf->alignment());
  284. ASSERT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
  285. // Verify after entering tablet mode, the shelf alignment is bottom and the
  286. // auto hide behavior has not changed.
  287. Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
  288. EXPECT_EQ(ShelfAlignment::kBottom, shelf->alignment());
  289. EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
  290. // Verify that screen rotation does not change alignment or auto-hide.
  291. display_manager()->SetDisplayRotation(
  292. display::Screen::GetScreen()->GetPrimaryDisplay().id(),
  293. display::Display::ROTATE_90, display::Display::RotationSource::ACTIVE);
  294. EXPECT_EQ(ShelfAlignment::kBottom, shelf->alignment());
  295. EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
  296. // Verify after exiting tablet mode, the shelf alignment and auto hide
  297. // behavior get their stored pref values.
  298. Shell::Get()->tablet_mode_controller()->SetEnabledForTest(false);
  299. EXPECT_EQ(ShelfAlignment::kLeft, shelf->alignment());
  300. EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
  301. }
  302. using ShelfControllerAppModeTest = NoSessionAshTestBase;
  303. // Tests that shelf auto hide behavior is always hidden in app mode.
  304. TEST_F(ShelfControllerAppModeTest, AutoHideBehavior) {
  305. SimulateKioskMode(user_manager::USER_TYPE_KIOSK_APP);
  306. Shelf* shelf = GetPrimaryShelf();
  307. EXPECT_EQ(ShelfAutoHideBehavior::kAlwaysHidden, shelf->auto_hide_behavior());
  308. Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
  309. EXPECT_EQ(ShelfAutoHideBehavior::kAlwaysHidden, shelf->auto_hide_behavior());
  310. display_manager()->SetDisplayRotation(
  311. display::Screen::GetScreen()->GetPrimaryDisplay().id(),
  312. display::Display::ROTATE_90, display::Display::RotationSource::ACTIVE);
  313. EXPECT_EQ(ShelfAutoHideBehavior::kAlwaysHidden, shelf->auto_hide_behavior());
  314. Shell::Get()->tablet_mode_controller()->SetEnabledForTest(false);
  315. EXPECT_EQ(ShelfAutoHideBehavior::kAlwaysHidden, shelf->auto_hide_behavior());
  316. }
  317. using ShelfControllerShelfPartyTest = NoSessionAshTestBase;
  318. TEST_F(ShelfControllerShelfPartyTest, ShelfPartyEndedOnLockScreen) {
  319. auto* session_controller = GetSessionControllerClient();
  320. session_controller->SetSessionState(session_manager::SessionState::ACTIVE);
  321. ShelfModel* model = Shell::Get()->shelf_controller()->model();
  322. model->ToggleShelfParty();
  323. EXPECT_TRUE(model->in_shelf_party());
  324. session_controller->SetSessionState(session_manager::SessionState::LOCKED);
  325. EXPECT_FALSE(model->in_shelf_party());
  326. }
  327. TEST_F(ShelfControllerShelfPartyTest, ShelfPartyEndedOnSwitchUsers) {
  328. auto* session_controller = GetSessionControllerClient();
  329. constexpr char kEmail1[] = "user1@gmail.com";
  330. session_controller->AddUserSession(kEmail1);
  331. constexpr char kEmail2[] = "user2@gmail.com";
  332. session_controller->AddUserSession(kEmail2);
  333. session_controller->SwitchActiveUser(AccountId::FromUserEmail(kEmail1));
  334. session_controller->SetSessionState(session_manager::SessionState::ACTIVE);
  335. ShelfModel* model = Shell::Get()->shelf_controller()->model();
  336. model->ToggleShelfParty();
  337. EXPECT_TRUE(model->in_shelf_party());
  338. session_controller->SwitchActiveUser(AccountId::FromUserEmail(kEmail2));
  339. EXPECT_FALSE(model->in_shelf_party());
  340. }
  341. } // namespace ash