shelf_context_menu_model_unittest.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  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_context_menu_model.h"
  5. #include <tuple>
  6. #include "ash/constants/ash_features.h"
  7. #include "ash/public/cpp/app_menu_constants.h"
  8. #include "ash/public/cpp/shelf_item_delegate.h"
  9. #include "ash/public/cpp/test/test_new_window_delegate.h"
  10. #include "ash/public/cpp/wallpaper/wallpaper_controller_client.h"
  11. #include "ash/session/test_session_controller_client.h"
  12. #include "ash/shelf/shelf.h"
  13. #include "ash/shell.h"
  14. #include "ash/test/ash_test_base.h"
  15. #include "ash/test_shell_delegate.h"
  16. #include "ash/wallpaper/test_wallpaper_controller_client.h"
  17. #include "ash/wallpaper/wallpaper_controller_impl.h"
  18. #include "ash/wm/tablet_mode/tablet_mode_controller.h"
  19. #include "base/strings/utf_string_conversions.h"
  20. #include "base/test/scoped_feature_list.h"
  21. #include "components/user_manager/user_type.h"
  22. #include "testing/gmock/include/gmock/gmock.h"
  23. #include "testing/gtest/include/gtest/gtest.h"
  24. #include "ui/display/display.h"
  25. #include "ui/views/widget/widget.h"
  26. namespace ash {
  27. namespace {
  28. using CommandId = ShelfContextMenuModel::CommandId;
  29. class MockNewWindowDelegate
  30. : public testing::StrictMock<TestNewWindowDelegate> {
  31. public:
  32. // TestNewWindowDelegate:
  33. MOCK_METHOD(void, OpenPersonalizationHub, (), (override));
  34. };
  35. class ShelfContextMenuModelTest
  36. : public AshTestBase,
  37. public ::testing::WithParamInterface<
  38. std::tuple<user_manager::UserType, bool>> {
  39. public:
  40. ShelfContextMenuModelTest() {
  41. feature_list_.InitWithFeatureState(ash::features::kPersonalizationHub,
  42. IsPersonalizationHubParamEnabled());
  43. }
  44. ShelfContextMenuModelTest(const ShelfContextMenuModelTest&) = delete;
  45. ShelfContextMenuModelTest& operator=(const ShelfContextMenuModelTest&) =
  46. delete;
  47. ~ShelfContextMenuModelTest() override = default;
  48. void SetUp() override {
  49. delegate_provider_ = std::make_unique<TestNewWindowDelegateProvider>(
  50. std::make_unique<MockNewWindowDelegate>());
  51. AshTestBase::SetUp();
  52. TestSessionControllerClient* session = GetSessionControllerClient();
  53. session->AddUserSession("user1@test.com", GetUserType());
  54. session->SetSessionState(session_manager::SessionState::ACTIVE);
  55. session->SwitchActiveUser(AccountId::FromUserEmail("user1@test.com"));
  56. }
  57. user_manager::UserType GetUserType() const { return std::get<0>(GetParam()); }
  58. bool IsPersonalizationHubParamEnabled() const {
  59. return std::get<1>(GetParam());
  60. }
  61. MockNewWindowDelegate* GetMockNewWindowDelegate() {
  62. return static_cast<MockNewWindowDelegate*>(
  63. delegate_provider_->GetPrimary());
  64. }
  65. private:
  66. base::test::ScopedFeatureList feature_list_;
  67. std::unique_ptr<TestNewWindowDelegateProvider> delegate_provider_;
  68. };
  69. // A test shelf item delegate that records the commands sent for execution.
  70. class TestShelfItemDelegate : public ShelfItemDelegate {
  71. public:
  72. TestShelfItemDelegate() : ShelfItemDelegate(ShelfID()) {}
  73. TestShelfItemDelegate(const TestShelfItemDelegate&) = delete;
  74. TestShelfItemDelegate& operator=(const TestShelfItemDelegate&) = delete;
  75. ~TestShelfItemDelegate() override = default;
  76. int last_executed_command() const { return last_executed_command_; }
  77. // ShelfItemDelegate:
  78. void ItemSelected(std::unique_ptr<ui::Event> event,
  79. int64_t display_id,
  80. ShelfLaunchSource source,
  81. ItemSelectedCallback callback,
  82. const ItemFilterPredicate& filter_predicate) override {}
  83. void ExecuteCommand(bool from_context_menu,
  84. int64_t command_id,
  85. int32_t event_flags,
  86. int64_t display_id) override {
  87. ASSERT_TRUE(from_context_menu);
  88. last_executed_command_ = command_id;
  89. }
  90. void Close() override {}
  91. private:
  92. int last_executed_command_ = 0;
  93. };
  94. INSTANTIATE_TEST_SUITE_P(
  95. ,
  96. ShelfContextMenuModelTest,
  97. ::testing::Combine(::testing::Values(user_manager::USER_TYPE_REGULAR,
  98. user_manager::USER_TYPE_CHILD),
  99. ::testing::Bool()));
  100. // Tests the default items in a shelf context menu.
  101. TEST_P(ShelfContextMenuModelTest, Basic) {
  102. ShelfContextMenuModel menu(nullptr, GetPrimaryDisplay().id());
  103. ASSERT_EQ(3u, menu.GetItemCount());
  104. EXPECT_EQ(CommandId::MENU_AUTO_HIDE, menu.GetCommandIdAt(0));
  105. EXPECT_EQ(CommandId::MENU_ALIGNMENT_MENU, menu.GetCommandIdAt(1));
  106. if (IsPersonalizationHubParamEnabled()) {
  107. EXPECT_EQ(CommandId::MENU_PERSONALIZATION_HUB, menu.GetCommandIdAt(2));
  108. } else {
  109. EXPECT_EQ(CommandId::MENU_CHANGE_WALLPAPER, menu.GetCommandIdAt(2));
  110. }
  111. for (size_t i = 0; i < menu.GetItemCount(); ++i) {
  112. EXPECT_TRUE(menu.IsEnabledAt(i));
  113. EXPECT_TRUE(menu.IsVisibleAt(i));
  114. }
  115. // Check the alignment submenu.
  116. EXPECT_EQ(ui::MenuModel::TYPE_SUBMENU, menu.GetTypeAt(1));
  117. ui::MenuModel* submenu = menu.GetSubmenuModelAt(1);
  118. ASSERT_TRUE(submenu);
  119. ASSERT_EQ(3u, submenu->GetItemCount());
  120. EXPECT_EQ(CommandId::MENU_ALIGNMENT_LEFT, submenu->GetCommandIdAt(0));
  121. EXPECT_EQ(CommandId::MENU_ALIGNMENT_BOTTOM, submenu->GetCommandIdAt(1));
  122. EXPECT_EQ(CommandId::MENU_ALIGNMENT_RIGHT, submenu->GetCommandIdAt(2));
  123. }
  124. // Test invocation of the default menu items.
  125. TEST_P(ShelfContextMenuModelTest, Invocation) {
  126. int64_t primary_id = GetPrimaryDisplay().id();
  127. Shelf* shelf = GetPrimaryShelf();
  128. // Check the shelf auto-hide behavior and menu interaction.
  129. ShelfContextMenuModel menu1(nullptr, primary_id);
  130. EXPECT_EQ(ShelfAutoHideBehavior::kNever, shelf->auto_hide_behavior());
  131. menu1.ActivatedAt(0);
  132. EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
  133. // Recreate the menu, auto-hide should still be enabled.
  134. ShelfContextMenuModel menu2(nullptr, primary_id);
  135. EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
  136. // By default the shelf should be on bottom, shelf alignment options in order:
  137. // Left, Bottom, Right. Bottom should be checked.
  138. ui::MenuModel* submenu = menu2.GetSubmenuModelAt(1);
  139. EXPECT_TRUE(submenu->IsItemCheckedAt(1));
  140. EXPECT_EQ(ShelfAlignment::kBottom, shelf->alignment());
  141. // Activate the left shelf alignment option.
  142. submenu->ActivatedAt(0);
  143. EXPECT_EQ(ShelfAlignment::kLeft, shelf->alignment());
  144. // Recreate the menu, it should show left alignment checked.
  145. ShelfContextMenuModel menu3(nullptr, primary_id);
  146. submenu = menu3.GetSubmenuModelAt(1);
  147. EXPECT_TRUE(submenu->IsItemCheckedAt(0));
  148. }
  149. TEST_P(ShelfContextMenuModelTest, OpensPersonalizationHubOrWallpaper) {
  150. int64_t display_id = GetPrimaryDisplay().id();
  151. ShelfContextMenuModel menu(nullptr, display_id);
  152. if (IsPersonalizationHubParamEnabled()) {
  153. // Personalization hub feature enabled should open hub.
  154. EXPECT_CALL(*GetMockNewWindowDelegate(), OpenPersonalizationHub).Times(1);
  155. menu.ActivatedAt(2);
  156. } else {
  157. TestWallpaperControllerClient client;
  158. Shell::Get()->wallpaper_controller()->SetClient(&client);
  159. EXPECT_EQ(0u, client.open_count());
  160. // Click the third option, wallpaper picker. It should open.
  161. menu.ActivatedAt(2);
  162. EXPECT_EQ(1u, client.open_count());
  163. }
  164. }
  165. // Tests custom items in a shelf context menu for an application.
  166. TEST_P(ShelfContextMenuModelTest, CustomItems) {
  167. // Pass a valid delegate to indicate the menu is for an application.
  168. TestShelfItemDelegate delegate;
  169. ShelfContextMenuModel menu(&delegate, GetPrimaryDisplay().id());
  170. // Because the delegate is valid, the context menu will not have the desktop
  171. // menu options (autohide, shelf position, and wallpaper picker).
  172. ASSERT_EQ(0u, menu.GetItemCount());
  173. // Add some custom items.
  174. menu.AddItem(203, u"item");
  175. menu.AddCheckItem(107, u"check");
  176. menu.AddRadioItem(101, u"radio", 0);
  177. ui::SimpleMenuModel submenu(nullptr);
  178. menu.AddSubMenu(55, u"submenu", &submenu);
  179. // Ensure the menu contents match the items above.
  180. ASSERT_EQ(4u, menu.GetItemCount());
  181. EXPECT_EQ(ui::MenuModel::TYPE_COMMAND, menu.GetTypeAt(0));
  182. EXPECT_EQ(ui::MenuModel::TYPE_CHECK, menu.GetTypeAt(1));
  183. EXPECT_EQ(ui::MenuModel::TYPE_RADIO, menu.GetTypeAt(2));
  184. EXPECT_EQ(ui::MenuModel::TYPE_SUBMENU, menu.GetTypeAt(3));
  185. // Invoking a custom item should execute the command id on the delegate.
  186. menu.ActivatedAt(1);
  187. EXPECT_EQ(107, delegate.last_executed_command());
  188. }
  189. // Tests fullscreen's per-display removal of "Autohide shelf": crbug.com/496681
  190. TEST_P(ShelfContextMenuModelTest, AutohideShelfOptionOnExternalDisplay) {
  191. UpdateDisplay("940x550,940x550");
  192. int64_t primary_id = GetPrimaryDisplay().id();
  193. int64_t secondary_id = GetSecondaryDisplay().id();
  194. // Create a normal window on the primary display.
  195. std::unique_ptr<views::Widget> widget = CreateTestWidget();
  196. widget->Show();
  197. widget->SetFullscreen(true);
  198. ShelfContextMenuModel primary_menu(nullptr, primary_id);
  199. ShelfContextMenuModel secondary_menu(nullptr, secondary_id);
  200. EXPECT_FALSE(
  201. primary_menu.GetIndexOfCommandId(CommandId::MENU_AUTO_HIDE).has_value());
  202. EXPECT_TRUE(secondary_menu.GetIndexOfCommandId(CommandId::MENU_AUTO_HIDE)
  203. .has_value());
  204. }
  205. // Tests that the autohide and alignment menu options are not included in tablet
  206. // mode.
  207. TEST_P(ShelfContextMenuModelTest, ExcludeClamshellOptionsOnTabletMode) {
  208. TabletModeController* tablet_mode_controller =
  209. Shell::Get()->tablet_mode_controller();
  210. int64_t primary_id = GetPrimaryDisplay().id();
  211. // In tablet mode, the wallpaper picker and auto-hide should be the only two
  212. // options because other options are disabled.
  213. tablet_mode_controller->SetEnabledForTest(true);
  214. ShelfContextMenuModel menu1(nullptr, primary_id);
  215. EXPECT_EQ(2u, menu1.GetItemCount());
  216. EXPECT_EQ(ShelfContextMenuModel::MENU_AUTO_HIDE, menu1.GetCommandIdAt(0));
  217. if (IsPersonalizationHubParamEnabled()) {
  218. EXPECT_EQ(ShelfContextMenuModel::MENU_PERSONALIZATION_HUB,
  219. menu1.GetCommandIdAt(1));
  220. } else {
  221. EXPECT_EQ(ShelfContextMenuModel::MENU_CHANGE_WALLPAPER,
  222. menu1.GetCommandIdAt(1));
  223. }
  224. // Test that a menu shown out of tablet mode includes all three options:
  225. // MENU_AUTO_HIDE, MENU_ALIGNMENT_MENU, and MENU_CHANGE_WALLPAPER.
  226. tablet_mode_controller->SetEnabledForTest(false);
  227. ShelfContextMenuModel menu2(nullptr, primary_id);
  228. EXPECT_EQ(3u, menu2.GetItemCount());
  229. // Test the auto hide option.
  230. EXPECT_EQ(ShelfContextMenuModel::MENU_AUTO_HIDE, menu2.GetCommandIdAt(0));
  231. EXPECT_TRUE(menu2.IsEnabledAt(0));
  232. // Test the shelf alignment menu option.
  233. EXPECT_EQ(ShelfContextMenuModel::MENU_ALIGNMENT_MENU,
  234. menu2.GetCommandIdAt(1));
  235. EXPECT_TRUE(menu2.IsEnabledAt(1));
  236. // Test the shelf alignment submenu.
  237. ui::MenuModel* submenu = menu2.GetSubmenuModelAt(1);
  238. EXPECT_EQ(ShelfContextMenuModel::MENU_ALIGNMENT_LEFT,
  239. submenu->GetCommandIdAt(0));
  240. EXPECT_TRUE(submenu->IsEnabledAt(0));
  241. EXPECT_EQ(ShelfContextMenuModel::MENU_ALIGNMENT_BOTTOM,
  242. submenu->GetCommandIdAt(1));
  243. EXPECT_TRUE(submenu->IsEnabledAt(1));
  244. EXPECT_EQ(ShelfContextMenuModel::MENU_ALIGNMENT_RIGHT,
  245. submenu->GetCommandIdAt(2));
  246. EXPECT_TRUE(submenu->IsEnabledAt(2));
  247. // Test the wallpaper picker option.
  248. if (IsPersonalizationHubParamEnabled()) {
  249. EXPECT_EQ(ShelfContextMenuModel::MENU_PERSONALIZATION_HUB,
  250. menu2.GetCommandIdAt(2));
  251. } else {
  252. EXPECT_EQ(ShelfContextMenuModel::MENU_CHANGE_WALLPAPER,
  253. menu2.GetCommandIdAt(2));
  254. }
  255. EXPECT_TRUE(menu2.IsEnabledAt(2));
  256. }
  257. TEST_P(ShelfContextMenuModelTest, CommandIdsMatchEnumsForHistograms) {
  258. // Tests that CommandId enums are not changed as the values are used in
  259. // histograms.
  260. EXPECT_EQ(500, ShelfContextMenuModel::MENU_AUTO_HIDE);
  261. EXPECT_EQ(501, ShelfContextMenuModel::MENU_ALIGNMENT_MENU);
  262. EXPECT_EQ(502, ShelfContextMenuModel::MENU_ALIGNMENT_LEFT);
  263. EXPECT_EQ(503, ShelfContextMenuModel::MENU_ALIGNMENT_RIGHT);
  264. EXPECT_EQ(504, ShelfContextMenuModel::MENU_ALIGNMENT_BOTTOM);
  265. EXPECT_EQ(505, ShelfContextMenuModel::MENU_CHANGE_WALLPAPER);
  266. }
  267. TEST_P(ShelfContextMenuModelTest, ShelfContextMenuOptions) {
  268. // Tests that there are exactly 3 shelf context menu options. If you're adding
  269. // a context menu option ensure that you have added the enum to
  270. // tools/metrics/enums.xml and that you haven't modified the order of the
  271. // existing enums.
  272. ShelfContextMenuModel menu(nullptr, GetPrimaryDisplay().id());
  273. EXPECT_EQ(3u, menu.GetItemCount());
  274. }
  275. TEST_P(ShelfContextMenuModelTest, NotificationContainerEnabled) {
  276. // Tests that NOTIFICATION_CONTAINER is enabled. This ensures that the
  277. // container is able to handle gesture events.
  278. ShelfContextMenuModel menu(nullptr, GetPrimaryDisplay().id());
  279. menu.AddItem(NOTIFICATION_CONTAINER, std::u16string());
  280. EXPECT_TRUE(menu.IsCommandIdEnabled(NOTIFICATION_CONTAINER));
  281. }
  282. } // namespace
  283. } // namespace ash