pcie_peripheral_notification_controller_unittest.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. // Copyright 2021 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/system/pcie_peripheral/pcie_peripheral_notification_controller.h"
  5. #include <memory>
  6. #include <vector>
  7. #include "ash/constants/ash_pref_names.h"
  8. #include "ash/public/cpp/test/test_new_window_delegate.h"
  9. #include "ash/public/cpp/test/test_system_tray_client.h"
  10. #include "ash/session/session_controller_impl.h"
  11. #include "ash/shell.h"
  12. #include "ash/test/ash_test_base.h"
  13. #include "components/prefs/pref_service.h"
  14. #include "testing/gmock/include/gmock/gmock.h"
  15. #include "third_party/abseil-cpp/absl/types/optional.h"
  16. #include "ui/message_center/fake_message_center.h"
  17. #include "ui/message_center/message_center.h"
  18. #include "ui/message_center/public/cpp/notification.h"
  19. #include "ui/message_center/public/cpp/notification_types.h"
  20. using message_center::MessageCenter;
  21. namespace ash {
  22. namespace {
  23. const char kPciePeripheralLimitedPerformanceNotificationId[] =
  24. "cros_pcie_peripheral_limited_performance_notification_id";
  25. const char kPciePeripheralLimitedPerformanceGuestModeNotificationId[] =
  26. "cros_pcie_peripheral_limited_performance_guest_mode_notification_id";
  27. const char kPciePeripheralGuestModeNotSupportedNotificationId[] =
  28. "cros_pcie_peripheral_guest_mode_not_supported_notifcation_id";
  29. const char kPciePeripheralDeviceBlockedNotificationId[] =
  30. "cros_pcie_peripheral_device_blocked_notifcation_id";
  31. const char kPciePeripheralBillboardDeviceNotificationId[] =
  32. "cros_pcie_peripheral_billboard_device_notifcation_id";
  33. const char kLearnMoreHelpUrl[] =
  34. "https://www.support.google.com/chromebook?p=connect_thblt_usb4_accy";
  35. // A mock implementation of |NewWindowDelegate| for use in tests.
  36. class MockNewWindowDelegate : public testing::NiceMock<TestNewWindowDelegate> {
  37. public:
  38. // TestNewWindowDelegate:
  39. MOCK_METHOD(void,
  40. OpenUrl,
  41. (const GURL& url, OpenUrlFrom from, Disposition disposition),
  42. (override));
  43. };
  44. } // namespace
  45. class PciePeripheralNotificationControllerTest : public AshTestBase {
  46. public:
  47. PciePeripheralNotificationControllerTest() {
  48. auto instance = std::make_unique<MockNewWindowDelegate>();
  49. auto primary = std::make_unique<MockNewWindowDelegate>();
  50. new_window_delegate_primary_ = primary.get();
  51. delegate_provider_ = std::make_unique<TestNewWindowDelegateProvider>(
  52. std::move(instance), std::move(primary));
  53. }
  54. PciePeripheralNotificationControllerTest(
  55. const PciePeripheralNotificationControllerTest&) = delete;
  56. PciePeripheralNotificationControllerTest& operator=(
  57. const PciePeripheralNotificationControllerTest&) = delete;
  58. ~PciePeripheralNotificationControllerTest() override = default;
  59. PciePeripheralNotificationController* controller() {
  60. return Shell::Get()->pcie_peripheral_notification_controller();
  61. }
  62. MockNewWindowDelegate& new_window_delegate_primary() {
  63. return *new_window_delegate_primary_;
  64. }
  65. message_center::Notification* GetLimitedPerformanceNotification() {
  66. return MessageCenter::Get()->FindVisibleNotificationById(
  67. kPciePeripheralLimitedPerformanceNotificationId);
  68. }
  69. message_center::Notification* GetLimitedPerformanceGuestModeNotification() {
  70. return MessageCenter::Get()->FindVisibleNotificationById(
  71. kPciePeripheralLimitedPerformanceGuestModeNotificationId);
  72. }
  73. message_center::Notification* GetGuestModeNotSupportedNotification() {
  74. return MessageCenter::Get()->FindVisibleNotificationById(
  75. kPciePeripheralGuestModeNotSupportedNotificationId);
  76. }
  77. message_center::Notification* GetPeripheralBlockedNotification() {
  78. return MessageCenter::Get()->FindVisibleNotificationById(
  79. kPciePeripheralDeviceBlockedNotificationId);
  80. }
  81. message_center::Notification* GetBillboardDeviceNotification() {
  82. return MessageCenter::Get()->FindVisibleNotificationById(
  83. kPciePeripheralBillboardDeviceNotificationId);
  84. }
  85. int GetNumOsPrivacySettingsOpened() {
  86. return GetSystemTrayClient()->show_os_settings_privacy_and_security_count();
  87. }
  88. int GetPrefNotificationCount() {
  89. PrefService* prefs =
  90. Shell::Get()->session_controller()->GetActivePrefService();
  91. return prefs->GetInteger(
  92. prefs::kPciePeripheralDisplayNotificationRemaining);
  93. }
  94. void ClickLimitedNotificationButton(absl::optional<int> button_index) {
  95. // No button index means the notification body was clicked.
  96. if (!button_index.has_value()) {
  97. message_center::Notification* notification =
  98. MessageCenter::Get()->FindVisibleNotificationById(
  99. kPciePeripheralLimitedPerformanceNotificationId);
  100. notification->delegate()->Click(absl::nullopt, absl::nullopt);
  101. return;
  102. }
  103. message_center::Notification* notification =
  104. MessageCenter::Get()->FindVisibleNotificationById(
  105. kPciePeripheralLimitedPerformanceNotificationId);
  106. notification->delegate()->Click(button_index, absl::nullopt);
  107. }
  108. void ClickGuestNotification(bool is_thunderbolt_only) {
  109. if (is_thunderbolt_only) {
  110. MessageCenter::Get()->ClickOnNotification(
  111. kPciePeripheralGuestModeNotSupportedNotificationId);
  112. return;
  113. }
  114. MessageCenter::Get()->ClickOnNotification(
  115. kPciePeripheralLimitedPerformanceGuestModeNotificationId);
  116. }
  117. void RemoveAllNotifications() {
  118. MessageCenter::Get()->RemoveAllNotifications(
  119. /*by_user=*/false, message_center::MessageCenter::RemoveType::ALL);
  120. }
  121. private:
  122. MockNewWindowDelegate* new_window_delegate_primary_;
  123. std::unique_ptr<TestNewWindowDelegateProvider> delegate_provider_;
  124. };
  125. TEST_F(PciePeripheralNotificationControllerTest, GuestNotificationTbtOnly) {
  126. EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount());
  127. controller()->NotifyGuestModeNotification(/*is_thunderbolt_only=*/true);
  128. EXPECT_EQ(1u, MessageCenter::Get()->NotificationCount());
  129. message_center::Notification* notification =
  130. GetGuestModeNotSupportedNotification();
  131. ASSERT_TRUE(notification);
  132. // This notification has no buttons.
  133. EXPECT_EQ(0u, notification->buttons().size());
  134. controller()->NotifyGuestModeNotification(/*is_thunderbolt_only=*/true);
  135. EXPECT_EQ(1u, MessageCenter::Get()->NotificationCount());
  136. // Click on the notification and expect the Learn More page to appear.
  137. EXPECT_CALL(new_window_delegate_primary(),
  138. OpenUrl(GURL(kLearnMoreHelpUrl),
  139. NewWindowDelegate::OpenUrlFrom::kUserInteraction,
  140. NewWindowDelegate::Disposition::kNewForegroundTab));
  141. ClickGuestNotification(/*is_thunderbolt_only=*/true);
  142. EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount());
  143. }
  144. TEST_F(PciePeripheralNotificationControllerTest, GuestNotificationTbtAltMode) {
  145. EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount());
  146. controller()->NotifyGuestModeNotification(/*is_thunderbolt_only=*/false);
  147. EXPECT_EQ(1u, MessageCenter::Get()->NotificationCount());
  148. message_center::Notification* notification =
  149. GetLimitedPerformanceGuestModeNotification();
  150. ASSERT_TRUE(notification);
  151. // This notification has no buttons.
  152. EXPECT_EQ(0u, notification->buttons().size());
  153. controller()->NotifyGuestModeNotification(/*is_thunderbolt_only=*/false);
  154. EXPECT_EQ(1u, MessageCenter::Get()->NotificationCount());
  155. // Click on the notification and expect the Learn More page to appear.
  156. EXPECT_CALL(new_window_delegate_primary(),
  157. OpenUrl(GURL(kLearnMoreHelpUrl),
  158. NewWindowDelegate::OpenUrlFrom::kUserInteraction,
  159. NewWindowDelegate::Disposition::kNewForegroundTab));
  160. ClickGuestNotification(/*is_thunderbolt_only=*/false);
  161. EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount());
  162. }
  163. TEST_F(PciePeripheralNotificationControllerTest,
  164. PeripheralBlockedNotification) {
  165. EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount());
  166. controller()->NotifyPeripheralBlockedNotification();
  167. EXPECT_EQ(1u, MessageCenter::Get()->NotificationCount());
  168. message_center::Notification* notification =
  169. GetPeripheralBlockedNotification();
  170. ASSERT_TRUE(notification);
  171. // This notification has no buttons.
  172. EXPECT_EQ(0u, notification->buttons().size());
  173. // Click on the notification and expect the Learn More page to appear.
  174. EXPECT_CALL(new_window_delegate_primary(),
  175. OpenUrl(GURL(kLearnMoreHelpUrl),
  176. NewWindowDelegate::OpenUrlFrom::kUserInteraction,
  177. NewWindowDelegate::Disposition::kNewForegroundTab));
  178. MessageCenter::Get()->ClickOnNotification(
  179. kPciePeripheralDeviceBlockedNotificationId);
  180. EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount());
  181. }
  182. TEST_F(PciePeripheralNotificationControllerTest, BillboardDeviceNotification) {
  183. EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount());
  184. EXPECT_EQ(3, GetPrefNotificationCount());
  185. controller()->NotifyBillboardDevice();
  186. EXPECT_EQ(1u, MessageCenter::Get()->NotificationCount());
  187. message_center::Notification* notification = GetBillboardDeviceNotification();
  188. ASSERT_TRUE(notification);
  189. // This notification has no buttons.
  190. EXPECT_EQ(0u, notification->buttons().size());
  191. controller()->NotifyBillboardDevice();
  192. EXPECT_EQ(1u, MessageCenter::Get()->NotificationCount());
  193. // Click on the notification and expect the Learn More page to appear.
  194. EXPECT_CALL(new_window_delegate_primary(),
  195. OpenUrl(GURL(kLearnMoreHelpUrl),
  196. NewWindowDelegate::OpenUrlFrom::kUserInteraction,
  197. NewWindowDelegate::Disposition::kNewForegroundTab));
  198. MessageCenter::Get()->ClickOnNotification(
  199. kPciePeripheralBillboardDeviceNotificationId);
  200. EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount());
  201. EXPECT_EQ(3, GetPrefNotificationCount());
  202. }
  203. TEST_F(PciePeripheralNotificationControllerTest,
  204. LimitedPerformanceNotificationLearnMoreClick) {
  205. EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount());
  206. EXPECT_EQ(3, GetPrefNotificationCount());
  207. controller()->NotifyLimitedPerformance();
  208. EXPECT_EQ(1u, MessageCenter::Get()->NotificationCount());
  209. message_center::Notification* notification =
  210. GetLimitedPerformanceNotification();
  211. ASSERT_TRUE(notification);
  212. // Ensure this notification has the two correct buttons.
  213. EXPECT_EQ(2u, notification->buttons().size());
  214. EXPECT_CALL(new_window_delegate_primary(),
  215. OpenUrl(GURL(kLearnMoreHelpUrl),
  216. NewWindowDelegate::OpenUrlFrom::kUserInteraction,
  217. NewWindowDelegate::Disposition::kNewForegroundTab));
  218. // Click the learn more link.
  219. ClickLimitedNotificationButton(/*button_index=*/1);
  220. EXPECT_EQ(2, GetPrefNotificationCount());
  221. EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount());
  222. EXPECT_CALL(new_window_delegate_primary(),
  223. OpenUrl(GURL(kLearnMoreHelpUrl),
  224. NewWindowDelegate::OpenUrlFrom::kUserInteraction,
  225. NewWindowDelegate::Disposition::kNewForegroundTab));
  226. controller()->NotifyLimitedPerformance();
  227. ClickLimitedNotificationButton(/*button_index=*/1);
  228. EXPECT_EQ(1, GetPrefNotificationCount());
  229. EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount());
  230. EXPECT_CALL(new_window_delegate_primary(),
  231. OpenUrl(GURL(kLearnMoreHelpUrl),
  232. NewWindowDelegate::OpenUrlFrom::kUserInteraction,
  233. NewWindowDelegate::Disposition::kNewForegroundTab));
  234. controller()->NotifyLimitedPerformance();
  235. ClickLimitedNotificationButton(/*button_index=*/1);
  236. EXPECT_EQ(0, GetPrefNotificationCount());
  237. EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount());
  238. controller()->NotifyLimitedPerformance();
  239. // Pref is currently at 0, so no new notifications should appear.
  240. EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount());
  241. }
  242. TEST_F(PciePeripheralNotificationControllerTest,
  243. LimitedPerformanceNotificationBodyClick) {
  244. EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount());
  245. EXPECT_EQ(3, GetPrefNotificationCount());
  246. controller()->NotifyLimitedPerformance();
  247. EXPECT_EQ(1u, MessageCenter::Get()->NotificationCount());
  248. // New notifications will decrement the counter.
  249. EXPECT_EQ(2, GetPrefNotificationCount());
  250. message_center::Notification* notification =
  251. GetLimitedPerformanceNotification();
  252. ASSERT_TRUE(notification);
  253. // Ensure this notification has the two correct buttons.
  254. EXPECT_EQ(2u, notification->buttons().size());
  255. // Click the notification body.
  256. ClickLimitedNotificationButton(absl::nullopt);
  257. EXPECT_EQ(0, GetPrefNotificationCount());
  258. EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount());
  259. EXPECT_EQ(1, GetNumOsPrivacySettingsOpened());
  260. // No new notifications can appear.
  261. controller()->NotifyLimitedPerformance();
  262. EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount());
  263. }
  264. TEST_F(PciePeripheralNotificationControllerTest,
  265. LimitedPerformanceNotificationSettingsButtonClick) {
  266. EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount());
  267. EXPECT_EQ(3, GetPrefNotificationCount());
  268. controller()->NotifyLimitedPerformance();
  269. EXPECT_EQ(1u, MessageCenter::Get()->NotificationCount());
  270. // New notifications will decrement the counter.
  271. EXPECT_EQ(2, GetPrefNotificationCount());
  272. message_center::Notification* notification =
  273. GetLimitedPerformanceNotification();
  274. ASSERT_TRUE(notification);
  275. // Ensure this notification has the two correct buttons.
  276. EXPECT_EQ(2u, notification->buttons().size());
  277. // Click the Settings button.
  278. ClickLimitedNotificationButton(/*button_index=*/0);
  279. EXPECT_EQ(0, GetPrefNotificationCount());
  280. EXPECT_EQ(1, GetNumOsPrivacySettingsOpened());
  281. EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount());
  282. // No new notifications can appear.
  283. controller()->NotifyLimitedPerformance();
  284. EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount());
  285. }
  286. TEST_F(PciePeripheralNotificationControllerTest,
  287. ClickGuestNotificationTbtOnly) {
  288. EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount());
  289. EXPECT_EQ(3, GetPrefNotificationCount());
  290. controller()->NotifyGuestModeNotification(/*is_thunderbolt_only=*/true);
  291. EXPECT_EQ(1u, MessageCenter::Get()->NotificationCount());
  292. message_center::Notification* notification =
  293. GetGuestModeNotSupportedNotification();
  294. ASSERT_TRUE(notification);
  295. // This notification has no buttons.
  296. EXPECT_EQ(0u, notification->buttons().size());
  297. // We will always show guest notifications, expect that the pref did not
  298. // decrement.
  299. EXPECT_CALL(new_window_delegate_primary(),
  300. OpenUrl(GURL(kLearnMoreHelpUrl),
  301. NewWindowDelegate::OpenUrlFrom::kUserInteraction,
  302. NewWindowDelegate::Disposition::kNewForegroundTab));
  303. ClickGuestNotification(/*is_thunderbolt_only=*/true);
  304. EXPECT_EQ(3, GetPrefNotificationCount());
  305. EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount());
  306. controller()->NotifyGuestModeNotification(/*is_thunderbolt_only=*/true);
  307. EXPECT_EQ(1u, MessageCenter::Get()->NotificationCount());
  308. }
  309. TEST_F(PciePeripheralNotificationControllerTest,
  310. ClickGuestNotificationTbtAltMode) {
  311. EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount());
  312. EXPECT_EQ(3, GetPrefNotificationCount());
  313. controller()->NotifyGuestModeNotification(/*is_thunderbolt_only=*/false);
  314. EXPECT_EQ(1u, MessageCenter::Get()->NotificationCount());
  315. message_center::Notification* notification =
  316. GetLimitedPerformanceGuestModeNotification();
  317. ASSERT_TRUE(notification);
  318. // This notification has no buttons.
  319. EXPECT_EQ(0u, notification->buttons().size());
  320. // We will always show guest notifications, expect that the pref did not
  321. // decrement.
  322. EXPECT_CALL(new_window_delegate_primary(),
  323. OpenUrl(GURL(kLearnMoreHelpUrl),
  324. NewWindowDelegate::OpenUrlFrom::kUserInteraction,
  325. NewWindowDelegate::Disposition::kNewForegroundTab));
  326. ClickGuestNotification(/*is_thunderbolt_only=*/false);
  327. EXPECT_EQ(3, GetPrefNotificationCount());
  328. EXPECT_EQ(0u, MessageCenter::Get()->NotificationCount());
  329. controller()->NotifyGuestModeNotification(/*is_thunderbolt_only=*/false);
  330. EXPECT_EQ(1u, MessageCenter::Get()->NotificationCount());
  331. }
  332. } // namespace ash