pcie_peripheral_notification_controller.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  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 <string>
  6. #include "ash/constants/ash_pref_names.h"
  7. #include "ash/constants/notifier_catalogs.h"
  8. #include "ash/public/cpp/new_window_delegate.h"
  9. #include "ash/public/cpp/notification_utils.h"
  10. #include "ash/public/cpp/system_tray_client.h"
  11. #include "ash/resources/vector_icons/vector_icons.h"
  12. #include "ash/session/session_controller_impl.h"
  13. #include "ash/shell.h"
  14. #include "ash/strings/grit/ash_strings.h"
  15. #include "ash/system/model/system_tray_model.h"
  16. #include "base/bind.h"
  17. #include "base/strings/utf_string_conversions.h"
  18. #include "components/prefs/pref_registry_simple.h"
  19. #include "components/prefs/pref_service.h"
  20. #include "third_party/abseil-cpp/absl/types/optional.h"
  21. #include "ui/base/l10n/l10n_util.h"
  22. #include "ui/message_center/message_center.h"
  23. #include "ui/message_center/public/cpp/notification.h"
  24. #include "ui/message_center/public/cpp/notification_types.h"
  25. #include "url/gurl.h"
  26. namespace ash {
  27. namespace {
  28. const char kNotifierPciePeripheral[] = "ash.pcie_peripheral";
  29. const char kLearnMoreHelpUrl[] =
  30. "https://www.support.google.com/chromebook?p=connect_thblt_usb4_accy";
  31. const int kNotificationsClicksThreshold = 3;
  32. const char kPciePeripheralLimitedPerformanceNotificationId[] =
  33. "cros_pcie_peripheral_limited_performance_notification_id";
  34. const char kPciePeripheralLimitedPerformanceGuestModeNotificationId[] =
  35. "cros_pcie_peripheral_limited_performance_guest_mode_notification_id";
  36. const char kPciePeripheralGuestModeNotSupportedNotificationId[] =
  37. "cros_pcie_peripheral_guest_mode_not_supported_notifcation_id";
  38. const char kPciePeripheralDeviceBlockedNotificationId[] =
  39. "cros_pcie_peripheral_device_blocked_notifcation_id";
  40. const char kPciePeripheralBillboardDeviceNotificationId[] =
  41. "cros_pcie_peripheral_billboard_device_notifcation_id";
  42. // Represents the buttons in the notification.
  43. enum ButtonIndex { kSettings, kLearnMore };
  44. int GetNotificationClickPrefCount() {
  45. PrefService* prefs =
  46. Shell::Get()->session_controller()->GetActivePrefService();
  47. return prefs->GetInteger(prefs::kPciePeripheralDisplayNotificationRemaining);
  48. }
  49. void UpdateNotificationPrefCount(bool clicked_settings) {
  50. int current_pref_val = GetNotificationClickPrefCount();
  51. // We're already not showing any new notifications, don't update.
  52. if (current_pref_val == 0)
  53. return;
  54. PrefService* prefs =
  55. Shell::Get()->session_controller()->GetActivePrefService();
  56. // If the user has reached the settings page through the notification, do
  57. // not show any more new notifications.
  58. if (clicked_settings) {
  59. prefs->SetInteger(prefs::kPciePeripheralDisplayNotificationRemaining, 0);
  60. return;
  61. }
  62. // Otherwise, decrement the pref count.
  63. prefs->SetInteger(prefs::kPciePeripheralDisplayNotificationRemaining,
  64. current_pref_val - 1);
  65. }
  66. void ShowPrivacyAndSecuritySettings() {
  67. Shell::Get()->system_tray_model()->client()->ShowPrivacyAndSecuritySettings();
  68. }
  69. void RemoveNotification(const std::string& notification_id) {
  70. message_center::MessageCenter::Get()->RemoveNotification(notification_id,
  71. /*from_user=*/true);
  72. }
  73. void OnPeripheralLimitedNotificationClicked(absl::optional<int> button_index) {
  74. // Clicked on body.
  75. if (!button_index) {
  76. ShowPrivacyAndSecuritySettings();
  77. UpdateNotificationPrefCount(/*clicked_settings=*/true);
  78. RemoveNotification(kPciePeripheralLimitedPerformanceNotificationId);
  79. return;
  80. }
  81. switch (*button_index) {
  82. case ButtonIndex::kSettings:
  83. ShowPrivacyAndSecuritySettings();
  84. UpdateNotificationPrefCount(/*clicked_settings=*/true);
  85. break;
  86. case ButtonIndex::kLearnMore:
  87. NewWindowDelegate::GetPrimary()->OpenUrl(
  88. GURL(kLearnMoreHelpUrl),
  89. NewWindowDelegate::OpenUrlFrom::kUserInteraction,
  90. NewWindowDelegate::Disposition::kNewForegroundTab);
  91. break;
  92. }
  93. RemoveNotification(kPciePeripheralLimitedPerformanceNotificationId);
  94. }
  95. void OnGuestNotificationClicked(bool is_thunderbolt_only) {
  96. NewWindowDelegate::GetPrimary()->OpenUrl(
  97. GURL(kLearnMoreHelpUrl), NewWindowDelegate::OpenUrlFrom::kUserInteraction,
  98. NewWindowDelegate::Disposition::kNewForegroundTab);
  99. if (is_thunderbolt_only) {
  100. RemoveNotification(kPciePeripheralGuestModeNotSupportedNotificationId);
  101. return;
  102. }
  103. RemoveNotification(kPciePeripheralLimitedPerformanceGuestModeNotificationId);
  104. }
  105. void OnPeripheralBlockedNotificationClicked() {
  106. NewWindowDelegate::GetPrimary()->OpenUrl(
  107. GURL(kLearnMoreHelpUrl), NewWindowDelegate::OpenUrlFrom::kUserInteraction,
  108. NewWindowDelegate::Disposition::kNewForegroundTab);
  109. RemoveNotification(kPciePeripheralDeviceBlockedNotificationId);
  110. }
  111. void OnBillboardNotificationClicked() {
  112. NewWindowDelegate::GetPrimary()->OpenUrl(
  113. GURL(kLearnMoreHelpUrl), NewWindowDelegate::OpenUrlFrom::kUserInteraction,
  114. NewWindowDelegate::Disposition::kNewForegroundTab);
  115. RemoveNotification(kPciePeripheralBillboardDeviceNotificationId);
  116. }
  117. // We only display notifications for active user sessions (signed-in/guest with
  118. // desktop ready). Also do not show notifications in signin or lock screen.
  119. bool ShouldDisplayNotification() {
  120. return Shell::Get()->session_controller()->GetSessionState() ==
  121. session_manager::SessionState::ACTIVE &&
  122. !Shell::Get()->session_controller()->IsUserSessionBlocked();
  123. }
  124. } // namespace
  125. PciePeripheralNotificationController::PciePeripheralNotificationController(
  126. message_center::MessageCenter* message_center)
  127. : message_center_(message_center) {
  128. DCHECK(message_center_);
  129. }
  130. PciePeripheralNotificationController::~PciePeripheralNotificationController() {
  131. if (ash::PeripheralNotificationManager::IsInitialized())
  132. ash::PeripheralNotificationManager::Get()->RemoveObserver(this);
  133. }
  134. void PciePeripheralNotificationController::
  135. OnPeripheralNotificationManagerInitialized() {
  136. DCHECK(ash::PeripheralNotificationManager::IsInitialized());
  137. ash::PeripheralNotificationManager::Get()->AddObserver(this);
  138. }
  139. void PciePeripheralNotificationController::NotifyBillboardDevice() {
  140. std::unique_ptr<message_center::Notification> notification =
  141. CreateSystemNotification(
  142. message_center::NOTIFICATION_TYPE_SIMPLE,
  143. kPciePeripheralBillboardDeviceNotificationId,
  144. /*title=*/std::u16string(),
  145. l10n_util::GetStringUTF16(
  146. IDS_ASH_PCIE_PERIPHERAL_NOTIFICATION_BILLBOARD_DEVICE),
  147. /*display_source=*/std::u16string(), GURL(),
  148. message_center::NotifierId(
  149. message_center::NotifierType::SYSTEM_COMPONENT,
  150. kNotifierPciePeripheral,
  151. NotificationCatalogName::kPcieBillboardDevice),
  152. message_center::RichNotificationData(),
  153. base::MakeRefCounted<message_center::HandleNotificationClickDelegate>(
  154. base::BindRepeating(&OnBillboardNotificationClicked)),
  155. kSettingsIcon,
  156. message_center::SystemNotificationWarningLevel::CRITICAL_WARNING);
  157. message_center_->AddNotification(std::move(notification));
  158. }
  159. void PciePeripheralNotificationController::NotifyLimitedPerformance() {
  160. // Don't show the notification if the user has already clicked on the
  161. // notification three times.
  162. if (!ShouldDisplayNotification() || GetNotificationClickPrefCount() == 0)
  163. return;
  164. message_center::RichNotificationData optional;
  165. optional.buttons.push_back(
  166. message_center::ButtonInfo(l10n_util::GetStringUTF16(
  167. IDS_ASH_PCIE_PERIPHERAL_NOTIFICATION_SETTINGS_BUTTON_TEXT)));
  168. optional.buttons.push_back(
  169. message_center::ButtonInfo(l10n_util::GetStringUTF16(
  170. IDS_ASH_PCIE_PERIPHERAL_NOTIFICATION_LEARN_MORE_BUTTON_TEXT)));
  171. std::unique_ptr<message_center::Notification> notification =
  172. CreateSystemNotification(
  173. message_center::NOTIFICATION_TYPE_SIMPLE,
  174. kPciePeripheralLimitedPerformanceNotificationId,
  175. l10n_util::GetStringUTF16(
  176. IDS_ASH_PCIE_PERIPHERAL_NOTIFICATION_PERFORMANCE_LIMITED_TITLE),
  177. l10n_util::GetStringUTF16(
  178. IDS_ASH_PCIE_PERIPHERAL_NOTIFICATION_PERFORMANCE_LIMITED_BODY),
  179. /*display_source=*/std::u16string(), GURL(),
  180. message_center::NotifierId(
  181. message_center::NotifierType::SYSTEM_COMPONENT,
  182. kNotifierPciePeripheral,
  183. NotificationCatalogName::kPcieLimitedPerformance),
  184. optional,
  185. base::MakeRefCounted<message_center::HandleNotificationClickDelegate>(
  186. base::BindRepeating(&OnPeripheralLimitedNotificationClicked)),
  187. kSettingsIcon,
  188. message_center::SystemNotificationWarningLevel::WARNING);
  189. message_center_->AddNotification(std::move(notification));
  190. UpdateNotificationPrefCount(/*clicked_settings=*/false);
  191. }
  192. void PciePeripheralNotificationController::NotifyGuestModeNotification(
  193. bool is_thunderbolt_only) {
  194. if (!ShouldDisplayNotification())
  195. return;
  196. std::unique_ptr<message_center::Notification> notification = CreateSystemNotification(
  197. message_center::NOTIFICATION_TYPE_SIMPLE,
  198. is_thunderbolt_only
  199. ? kPciePeripheralGuestModeNotSupportedNotificationId
  200. : kPciePeripheralLimitedPerformanceGuestModeNotificationId,
  201. /*title=*/std::u16string(),
  202. is_thunderbolt_only
  203. ? l10n_util::GetStringUTF16(
  204. IDS_ASH_PCIE_PERIPHERAL_NOTIFICATION_GUEST_MODE_NOT_SUPPORTED)
  205. : l10n_util::GetStringUTF16(
  206. IDS_ASH_PCIE_PERIPHERAL_NOTIFICATION_PERFORMANCE_LIMITED_GUEST_MODE),
  207. /*display_source=*/std::u16string(), GURL(),
  208. message_center::NotifierId(message_center::NotifierType::SYSTEM_COMPONENT,
  209. kNotifierPciePeripheral,
  210. NotificationCatalogName::kPcieGuestMode),
  211. message_center::RichNotificationData(),
  212. base::MakeRefCounted<message_center::HandleNotificationClickDelegate>(
  213. base::BindRepeating(&OnGuestNotificationClicked,
  214. is_thunderbolt_only)),
  215. kSettingsIcon,
  216. is_thunderbolt_only
  217. ? message_center::SystemNotificationWarningLevel::CRITICAL_WARNING
  218. : message_center::SystemNotificationWarningLevel::WARNING);
  219. message_center_->AddNotification(std::move(notification));
  220. }
  221. void PciePeripheralNotificationController::
  222. NotifyPeripheralBlockedNotification() {
  223. std::unique_ptr<message_center::Notification> notification =
  224. CreateSystemNotification(
  225. message_center::NOTIFICATION_TYPE_SIMPLE,
  226. kPciePeripheralDeviceBlockedNotificationId,
  227. l10n_util::GetStringUTF16(
  228. IDS_ASH_PCIE_PERIPHERAL_NOTIFICATION_DEVICE_BLOCKED_TITLE),
  229. l10n_util::GetStringUTF16(
  230. IDS_ASH_PCIE_PERIPHERAL_NOTIFICATION_DEVICE_BLOCKED_BODY),
  231. /*display_source=*/std::u16string(), GURL(),
  232. message_center::NotifierId(
  233. message_center::NotifierType::SYSTEM_COMPONENT,
  234. kNotifierPciePeripheral,
  235. NotificationCatalogName::kPciePeripheralBlocked),
  236. message_center::RichNotificationData(),
  237. base::MakeRefCounted<message_center::HandleNotificationClickDelegate>(
  238. base::BindRepeating(&OnPeripheralBlockedNotificationClicked)),
  239. kSettingsIcon,
  240. message_center::SystemNotificationWarningLevel::CRITICAL_WARNING);
  241. message_center_->AddNotification(std::move(notification));
  242. }
  243. void PciePeripheralNotificationController::
  244. OnLimitedPerformancePeripheralReceived() {
  245. NotifyLimitedPerformance();
  246. }
  247. void PciePeripheralNotificationController::OnGuestModeNotificationReceived(
  248. bool is_thunderbolt_only) {
  249. NotifyGuestModeNotification(is_thunderbolt_only);
  250. }
  251. void PciePeripheralNotificationController::OnPeripheralBlockedReceived() {
  252. NotifyPeripheralBlockedNotification();
  253. }
  254. void PciePeripheralNotificationController::OnBillboardDeviceConnected() {
  255. NotifyBillboardDevice();
  256. }
  257. // static
  258. void PciePeripheralNotificationController::RegisterProfilePrefs(
  259. PrefRegistrySimple* registry) {
  260. // By default, we let the user click on the notifications three times before
  261. // hiding future notifications.
  262. registry->RegisterIntegerPref(
  263. prefs::kPciePeripheralDisplayNotificationRemaining,
  264. kNotificationsClicksThreshold);
  265. }
  266. } // namespace ash