accelerator_notifications.cc 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  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/accelerators/accelerator_notifications.h"
  5. #include <memory>
  6. #include <string>
  7. #include <vector>
  8. #include "ash/constants/notifier_catalogs.h"
  9. #include "ash/public/cpp/new_window_delegate.h"
  10. #include "ash/public/cpp/notification_utils.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/shell_delegate.h"
  15. #include "ash/strings/grit/ash_strings.h"
  16. #include "ash/system/model/enterprise_domain_model.h"
  17. #include "ash/system/model/system_tray_model.h"
  18. #include "base/strings/string_split.h"
  19. #include "chromeos/ui/vector_icons/vector_icons.h"
  20. #include "ui/base/l10n/l10n_util.h"
  21. #include "ui/message_center/message_center.h"
  22. namespace ash {
  23. using gfx::VectorIcon;
  24. using message_center::ButtonInfo;
  25. using message_center::HandleNotificationClickDelegate;
  26. using message_center::MessageCenter;
  27. using message_center::Notification;
  28. using message_center::NotificationDelegate;
  29. using message_center::NotifierId;
  30. using message_center::NotifierType;
  31. using message_center::RichNotificationData;
  32. using message_center::SystemNotificationWarningLevel;
  33. namespace {
  34. constexpr char kNotifierAccelerator[] = "ash.accelerator-controller";
  35. constexpr char kSpokenFeedbackToggleAccelNotificationId[] =
  36. "chrome://settings/accessibility/spokenfeedback";
  37. // Ensures that there are no word breaks at the "+"s in the shortcut texts such
  38. // as "Ctrl+Shift+Space".
  39. void EnsureNoWordBreaks(std::u16string* shortcut_text) {
  40. std::vector<std::u16string> keys = base::SplitString(
  41. *shortcut_text, u"+", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
  42. if (keys.size() < 2U)
  43. return;
  44. // The plus sign surrounded by the word joiner to guarantee an non-breaking
  45. // shortcut.
  46. const std::u16string non_breaking_plus = u"\u2060+\u2060";
  47. shortcut_text->clear();
  48. for (size_t i = 0; i < keys.size() - 1; ++i) {
  49. *shortcut_text += keys[i];
  50. *shortcut_text += non_breaking_plus;
  51. }
  52. *shortcut_text += keys.back();
  53. }
  54. // Gets the notification message after it formats it in such a way that there
  55. // are no line breaks in the middle of the shortcut texts.
  56. std::u16string GetNotificationText(int message_id,
  57. int old_shortcut_id,
  58. int new_shortcut_id) {
  59. std::u16string old_shortcut = l10n_util::GetStringUTF16(old_shortcut_id);
  60. std::u16string new_shortcut = l10n_util::GetStringUTF16(new_shortcut_id);
  61. EnsureNoWordBreaks(&old_shortcut);
  62. EnsureNoWordBreaks(&new_shortcut);
  63. return l10n_util::GetStringFUTF16(message_id, new_shortcut, old_shortcut);
  64. }
  65. std::unique_ptr<Notification> CreateNotification(
  66. const std::string& notification_id,
  67. const NotificationCatalogName& catalog_name,
  68. const std::u16string& title,
  69. const std::u16string& message,
  70. const VectorIcon& icon,
  71. scoped_refptr<NotificationDelegate> click_handler = nullptr,
  72. const RichNotificationData& rich_data = RichNotificationData()) {
  73. return CreateSystemNotification(
  74. message_center::NOTIFICATION_TYPE_SIMPLE, notification_id, title, message,
  75. std::u16string() /* display source */, GURL(),
  76. NotifierId(NotifierType::SYSTEM_COMPONENT, kNotifierAccelerator,
  77. catalog_name),
  78. rich_data, click_handler, icon, SystemNotificationWarningLevel::NORMAL);
  79. }
  80. void CreateAndShowStickyNotification(
  81. const std::string& notification_id,
  82. const NotificationCatalogName& catalog_name,
  83. const std::u16string& title,
  84. const std::u16string& message,
  85. const VectorIcon& icon) {
  86. std::unique_ptr<Notification> notification =
  87. CreateNotification(notification_id, catalog_name, title, message, icon);
  88. notification->set_priority(message_center::SYSTEM_PRIORITY);
  89. MessageCenter::Get()->AddNotification(std::move(notification));
  90. }
  91. void CreateAndShowNotification(
  92. const std::string& notification_id,
  93. const NotificationCatalogName& catalog_name,
  94. const std::u16string& title,
  95. const std::u16string& message,
  96. const VectorIcon& icon,
  97. scoped_refptr<NotificationDelegate> click_handler = nullptr,
  98. const RichNotificationData& rich_data = RichNotificationData()) {
  99. std::unique_ptr<Notification> notification =
  100. CreateNotification(notification_id, catalog_name, title, message, icon,
  101. click_handler, rich_data);
  102. MessageCenter::Get()->AddNotification(std::move(notification));
  103. }
  104. void NotifyAccessibilityFeatureDisabledByAdmin(
  105. int feature_name_id,
  106. bool feature_state,
  107. const std::string& notification_id) {
  108. const std::u16string title = l10n_util::GetStringUTF16(
  109. IDS_ASH_ACCESSIBILITY_FEATURE_SHORTCUT_DISABLED_TITLE);
  110. const std::u16string organization_manager =
  111. base::UTF8ToUTF16(Shell::Get()
  112. ->system_tray_model()
  113. ->enterprise_domain()
  114. ->enterprise_domain_manager());
  115. const std::u16string activation_string = l10n_util::GetStringUTF16(
  116. feature_state ? IDS_ASH_ACCESSIBILITY_FEATURE_ACTIVATED
  117. : IDS_ASH_ACCESSIBILITY_FEATURE_DEACTIVATED);
  118. const std::u16string message = l10n_util::GetStringFUTF16(
  119. IDS_ASH_ACCESSIBILITY_FEATURE_SHORTCUT_DISABLED_MSG, organization_manager,
  120. activation_string, l10n_util::GetStringUTF16(feature_name_id));
  121. CreateAndShowStickyNotification(
  122. notification_id, NotificationCatalogName::kAccessibilityFeatureDisabled,
  123. title, message, chromeos::kEnterpriseIcon);
  124. }
  125. void ShowAccessibilityNotification(
  126. int title_id,
  127. int message_id,
  128. const std::string& notification_id,
  129. const NotificationCatalogName& catalog_name) {
  130. CreateAndShowStickyNotification(
  131. notification_id, catalog_name, l10n_util::GetStringUTF16(title_id),
  132. l10n_util::GetStringUTF16(message_id), kNotificationAccessibilityIcon);
  133. }
  134. void RemoveNotification(const std::string& notification_id) {
  135. MessageCenter::Get()->RemoveNotification(notification_id,
  136. /*by_user=*/false);
  137. }
  138. } // namespace
  139. // Shortcut help URL.
  140. const char kKeyboardShortcutHelpPageUrl[] =
  141. "https://support.google.com/chromebook/answer/183101";
  142. // Accessibility notification ids.
  143. const char kDockedMagnifierToggleAccelNotificationId[] =
  144. "chrome://settings/accessibility/dockedmagnifier";
  145. const char kFullscreenMagnifierToggleAccelNotificationId[] =
  146. "chrome://settings/accessibility/fullscreenmagnifier";
  147. const char kHighContrastToggleAccelNotificationId[] =
  148. "chrome://settings/accessibility/highcontrast";
  149. void ShowDeprecatedAcceleratorNotification(const char* notification_id,
  150. int message_id,
  151. int old_shortcut_id,
  152. int new_shortcut_id) {
  153. const std::u16string title =
  154. l10n_util::GetStringUTF16(IDS_DEPRECATED_SHORTCUT_TITLE);
  155. const std::u16string message =
  156. GetNotificationText(message_id, old_shortcut_id, new_shortcut_id);
  157. auto on_click_handler = base::MakeRefCounted<HandleNotificationClickDelegate>(
  158. base::BindRepeating([]() {
  159. if (!Shell::Get()->session_controller()->IsUserSessionBlocked())
  160. Shell::Get()->shell_delegate()->OpenKeyboardShortcutHelpPage();
  161. }));
  162. CreateAndShowNotification(
  163. notification_id, NotificationCatalogName::kDeprecatedAccelerator, title,
  164. message, kNotificationKeyboardIcon, on_click_handler);
  165. }
  166. void ShowDockedMagnifierNotification() {
  167. ShowAccessibilityNotification(
  168. IDS_DOCKED_MAGNIFIER_ACCEL_TITLE, IDS_DOCKED_MAGNIFIER_ACCEL_MSG,
  169. kDockedMagnifierToggleAccelNotificationId,
  170. NotificationCatalogName::kDockedMagnifierEnabled);
  171. }
  172. void ShowDockedMagnifierDisabledByAdminNotification(bool feature_state) {
  173. NotifyAccessibilityFeatureDisabledByAdmin(
  174. IDS_ASH_DOCKED_MAGNIFIER_SHORTCUT_DISABLED, feature_state,
  175. kDockedMagnifierToggleAccelNotificationId);
  176. }
  177. void RemoveDockedMagnifierNotification() {
  178. RemoveNotification(kDockedMagnifierToggleAccelNotificationId);
  179. }
  180. void ShowFullscreenMagnifierNotification() {
  181. ShowAccessibilityNotification(
  182. IDS_FULLSCREEN_MAGNIFIER_ACCEL_TITLE, IDS_FULLSCREEN_MAGNIFIER_ACCEL_MSG,
  183. kFullscreenMagnifierToggleAccelNotificationId,
  184. NotificationCatalogName::kFullScreenMagnifierEnabled);
  185. }
  186. void ShowFullscreenMagnifierDisabledByAdminNotification(bool feature_state) {
  187. NotifyAccessibilityFeatureDisabledByAdmin(
  188. IDS_ASH_FULLSCREEN_MAGNIFIER_SHORTCUT_DISABLED, feature_state,
  189. kFullscreenMagnifierToggleAccelNotificationId);
  190. }
  191. void RemoveFullscreenMagnifierNotification() {
  192. RemoveNotification(kFullscreenMagnifierToggleAccelNotificationId);
  193. }
  194. void ShowHighContrastNotification() {
  195. ShowAccessibilityNotification(IDS_HIGH_CONTRAST_ACCEL_TITLE,
  196. IDS_HIGH_CONTRAST_ACCEL_MSG,
  197. kHighContrastToggleAccelNotificationId,
  198. NotificationCatalogName::kHighContrastEnabled);
  199. }
  200. void ShowHighContrastDisabledByAdminNotification(bool feature_state) {
  201. NotifyAccessibilityFeatureDisabledByAdmin(
  202. IDS_ASH_HIGH_CONTRAST_SHORTCUT_DISABLED, feature_state,
  203. kHighContrastToggleAccelNotificationId);
  204. }
  205. void RemoveHighContrastNotification() {
  206. RemoveNotification(kHighContrastToggleAccelNotificationId);
  207. }
  208. void ShowSpokenFeedbackDisabledByAdminNotification(bool feature_state) {
  209. NotifyAccessibilityFeatureDisabledByAdmin(
  210. IDS_ASH_SPOKEN_FEEDBACK_SHORTCUT_DISABLED, feature_state,
  211. kSpokenFeedbackToggleAccelNotificationId);
  212. }
  213. void RemoveSpokenFeedbackNotification() {
  214. RemoveNotification(kSpokenFeedbackToggleAccelNotificationId);
  215. }
  216. } // namespace ash