| // Copyright 2021 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ash/system/usb_peripheral/usb_peripheral_notification_controller.h" |
| |
| #include <optional> |
| |
| #include "ash/constants/ash_pref_names.h" |
| #include "ash/constants/notifier_catalogs.h" |
| #include "ash/public/cpp/new_window_delegate.h" |
| #include "ash/public/cpp/notification_utils.h" |
| #include "ash/resources/vector_icons/vector_icons.h" |
| #include "ash/session/session_controller_impl.h" |
| #include "ash/shell.h" |
| #include "ash/strings/grit/ash_strings.h" |
| #include "components/prefs/pref_registry_simple.h" |
| #include "components/prefs/pref_service.h" |
| #include "components/vector_icons/vector_icons.h" |
| #include "third_party/cros_system_api/dbus/typecd/dbus-constants.h" |
| #include "ui/base/l10n/l10n_util.h" |
| #include "ui/message_center/message_center.h" |
| #include "ui/message_center/public/cpp/notification.h" |
| #include "ui/message_center/public/cpp/notification_types.h" |
| #include "url/gurl.h" |
| |
| namespace ash { |
| |
| namespace { |
| const char kNotifierUsbPeripheral[] = "ash.usb_peripheral"; |
| const char kUsbPeripheralInvalidDpCableNotificationId[] = |
| "cros_usb_peripheral_invalid_dp_cable_notification_id"; |
| const char kUsbPeripheralInvalidUSB4ValidTBTCableNotificationId[] = |
| "cros_usb_peripheral_invalid_usb4_valid_tbt_cable_notification_id"; |
| const char kUsbPeripheralInvalidUSB4CableNotificationId[] = |
| "cros_usb_peripheral_invalid_usb4_cable_notification_id"; |
| const char kUsbPeripheralInvalidTBTCableNotificationId[] = |
| "cros_usb_peripheral_invalid_tbt_cable_notification_id"; |
| const char kUsbPeripheralSpeedLimitingCableNotificationId[] = |
| "cros_usb_peripheral_speed_limiting_cable_notification_id"; |
| const char kUsbPeripheralDeviceOrEndpointLimitNotificationId[] = |
| "cros_usb_peripheral_device_or_endpoint_limit_notification_id"; |
| const char kNotificationDisplayLandingPageUrl[] = |
| "https://support.google.com/chromebook?p=cable_notification"; |
| const char kNotificationDeviceLandingPageUrl[] = |
| "https://support.google.com/chromebook?p=cable_notification_2"; |
| |
| bool GetCableSpeedNotificationShownPref() { |
| PrefService* prefs = |
| Shell::Get()->session_controller()->GetActivePrefService(); |
| return prefs->GetBoolean(prefs::kUsbPeripheralCableSpeedNotificationShown); |
| } |
| |
| void SetCableSpeedNotificationShownPref(bool pref) { |
| PrefService* prefs = |
| Shell::Get()->session_controller()->GetActivePrefService(); |
| prefs->SetBoolean(prefs::kUsbPeripheralCableSpeedNotificationShown, pref); |
| } |
| |
| bool ShouldDisplayNotification() { |
| return Shell::Get()->session_controller()->GetSessionState() == |
| session_manager::SessionState::ACTIVE && |
| !Shell::Get()->session_controller()->IsUserSessionBlocked(); |
| } |
| |
| void OnCableNotificationClicked(const std::string& notification_id, |
| const std::string& landing_page, |
| std::optional<int> button_index) { |
| if (notification_id == kUsbPeripheralSpeedLimitingCableNotificationId) |
| SetCableSpeedNotificationShownPref(true); |
| |
| if (button_index) { |
| NewWindowDelegate::GetInstance()->OpenUrl( |
| GURL(landing_page), NewWindowDelegate::OpenUrlFrom::kUserInteraction, |
| NewWindowDelegate::Disposition::kNewForegroundTab); |
| } |
| |
| message_center::MessageCenter::Get()->RemoveNotification(notification_id, |
| /*from_user=*/true); |
| } |
| |
| } // namespace |
| |
| UsbPeripheralNotificationController::UsbPeripheralNotificationController( |
| message_center::MessageCenter* message_center) |
| : message_center_(message_center) { |
| DCHECK(message_center_); |
| } |
| |
| UsbPeripheralNotificationController::~UsbPeripheralNotificationController() { |
| if (ash::PeripheralNotificationManager::IsInitialized()) |
| ash::PeripheralNotificationManager::Get()->RemoveObserver(this); |
| } |
| |
| // static |
| void UsbPeripheralNotificationController::RegisterProfilePrefs( |
| PrefRegistrySimple* registry) { |
| registry->RegisterBooleanPref( |
| prefs::kUsbPeripheralCableSpeedNotificationShown, false); |
| } |
| |
| void UsbPeripheralNotificationController:: |
| OnPeripheralNotificationManagerInitialized() { |
| DCHECK(ash::PeripheralNotificationManager::IsInitialized()); |
| ash::PeripheralNotificationManager::Get()->AddObserver(this); |
| } |
| |
| // Notify the user that the current cable may not support dp alt mode. |
| void UsbPeripheralNotificationController::OnInvalidDpCableWarning() { |
| if (!ShouldDisplayNotification()) |
| return; |
| |
| message_center::RichNotificationData optional; |
| optional.buttons.push_back(message_center::ButtonInfo( |
| l10n_util::GetStringUTF16(IDS_ASH_USB_NOTIFICATION_V2_LEARN_MORE))); |
| |
| std::unique_ptr<message_center::Notification> notification = |
| CreateSystemNotificationPtr( |
| message_center::NOTIFICATION_TYPE_SIMPLE, |
| kUsbPeripheralInvalidDpCableNotificationId, |
| l10n_util::GetStringUTF16( |
| IDS_ASH_USB_NOTIFICATION_V2_CABLE_WARNING_DISPLAY_TITLE), |
| l10n_util::GetStringUTF16( |
| IDS_ASH_USB_NOTIFICATION_V2_CABLE_WARNING_DISPLAY_BODY), |
| /*display_source=*/std::u16string(), GURL(), |
| message_center::NotifierId( |
| message_center::NotifierType::SYSTEM_COMPONENT, |
| kNotifierUsbPeripheral, |
| NotificationCatalogName::kUSBPeripheralInvalidDpCable), |
| optional, |
| base::MakeRefCounted<message_center::HandleNotificationClickDelegate>( |
| base::BindRepeating(&OnCableNotificationClicked, |
| kUsbPeripheralInvalidDpCableNotificationId, |
| kNotificationDisplayLandingPageUrl)), |
| kSettingsIcon, |
| message_center::SystemNotificationWarningLevel::WARNING); |
| |
| message_center_->AddNotification(std::move(notification)); |
| } |
| |
| // Notify the user that the USB4 device will use TBT due to the cable. |
| void UsbPeripheralNotificationController::OnInvalidUSB4ValidTBTCableWarning() { |
| if (!ShouldDisplayNotification()) |
| return; |
| |
| message_center::RichNotificationData optional; |
| optional.buttons.push_back(message_center::ButtonInfo( |
| l10n_util::GetStringUTF16(IDS_ASH_USB_NOTIFICATION_V2_LEARN_MORE))); |
| |
| std::unique_ptr<message_center::Notification> notification = |
| CreateSystemNotificationPtr( |
| message_center::NOTIFICATION_TYPE_SIMPLE, |
| kUsbPeripheralInvalidUSB4ValidTBTCableNotificationId, |
| l10n_util::GetStringUTF16( |
| IDS_ASH_USB_NOTIFICATION_V2_CABLE_WARNING_PERFORMANCE_TITLE), |
| l10n_util::GetStringUTF16( |
| IDS_ASH_USB_NOTIFICATION_V2_CABLE_WARNING_NO_USB4_SUPPORT_BODY), |
| /*display_source=*/std::u16string(), GURL(), |
| message_center::NotifierId( |
| message_center::NotifierType::SYSTEM_COMPONENT, |
| kNotifierUsbPeripheral, |
| NotificationCatalogName::kUSBPeripheralInvalidUSB4ValidTBTCable), |
| optional, |
| base::MakeRefCounted<message_center::HandleNotificationClickDelegate>( |
| base::BindRepeating( |
| &OnCableNotificationClicked, |
| kUsbPeripheralInvalidUSB4ValidTBTCableNotificationId, |
| kNotificationDeviceLandingPageUrl)), |
| kSettingsIcon, |
| message_center::SystemNotificationWarningLevel::WARNING); |
| |
| message_center_->AddNotification(std::move(notification)); |
| } |
| |
| // Notify the user that the USB4 device will use DisplayPort, |
| // USB 3.2 or USB 2.0 due to the cable. |
| void UsbPeripheralNotificationController::OnInvalidUSB4CableWarning() { |
| if (!ShouldDisplayNotification()) |
| return; |
| |
| message_center::RichNotificationData optional; |
| optional.buttons.push_back(message_center::ButtonInfo( |
| l10n_util::GetStringUTF16(IDS_ASH_USB_NOTIFICATION_V2_LEARN_MORE))); |
| |
| std::unique_ptr<message_center::Notification> notification = |
| CreateSystemNotificationPtr( |
| message_center::NOTIFICATION_TYPE_SIMPLE, |
| kUsbPeripheralInvalidUSB4CableNotificationId, |
| l10n_util::GetStringUTF16( |
| IDS_ASH_USB_NOTIFICATION_V2_CABLE_WARNING_PERFORMANCE_TITLE), |
| l10n_util::GetStringUTF16( |
| IDS_ASH_USB_NOTIFICATION_V2_CABLE_WARNING_NO_USB4_SUPPORT_BODY), |
| /*display_source=*/std::u16string(), GURL(), |
| message_center::NotifierId( |
| message_center::NotifierType::SYSTEM_COMPONENT, |
| kNotifierUsbPeripheral, |
| NotificationCatalogName::kUSBPeripheralInvalidUSB4Cable), |
| optional, |
| base::MakeRefCounted<message_center::HandleNotificationClickDelegate>( |
| base::BindRepeating(&OnCableNotificationClicked, |
| kUsbPeripheralInvalidUSB4CableNotificationId, |
| kNotificationDeviceLandingPageUrl)), |
| kSettingsIcon, |
| message_center::SystemNotificationWarningLevel::WARNING); |
| |
| message_center_->AddNotification(std::move(notification)); |
| } |
| |
| // Notify the user that the TBT device will use DisplayPort, |
| // USB 3.2 or USB 2.0 due to the cable. |
| void UsbPeripheralNotificationController::OnInvalidTBTCableWarning() { |
| if (!ShouldDisplayNotification()) |
| return; |
| |
| message_center::RichNotificationData optional; |
| optional.buttons.push_back(message_center::ButtonInfo( |
| l10n_util::GetStringUTF16(IDS_ASH_USB_NOTIFICATION_V2_LEARN_MORE))); |
| |
| std::unique_ptr<message_center::Notification> notification = |
| CreateSystemNotificationPtr( |
| message_center::NOTIFICATION_TYPE_SIMPLE, |
| kUsbPeripheralInvalidTBTCableNotificationId, |
| l10n_util::GetStringUTF16( |
| IDS_ASH_USB_NOTIFICATION_V2_CABLE_WARNING_PERFORMANCE_TITLE), |
| l10n_util::GetStringUTF16( |
| IDS_ASH_USB_NOTIFICATION_V2_CABLE_WARNING_NO_TBT_SUPPORT_BODY), |
| /*display_source=*/std::u16string(), GURL(), |
| message_center::NotifierId( |
| message_center::NotifierType::SYSTEM_COMPONENT, |
| kNotifierUsbPeripheral, |
| NotificationCatalogName::kUSBPeripheralInvalidTBTCable), |
| optional, |
| base::MakeRefCounted<message_center::HandleNotificationClickDelegate>( |
| base::BindRepeating(&OnCableNotificationClicked, |
| kUsbPeripheralInvalidTBTCableNotificationId, |
| kNotificationDeviceLandingPageUrl)), |
| kSettingsIcon, |
| message_center::SystemNotificationWarningLevel::WARNING); |
| |
| message_center_->AddNotification(std::move(notification)); |
| } |
| |
| // Notify the user that the cable limits USB device performance. |
| void UsbPeripheralNotificationController::OnSpeedLimitingCableWarning() { |
| if (!ShouldDisplayNotification() || GetCableSpeedNotificationShownPref()) |
| return; |
| |
| message_center::RichNotificationData optional; |
| optional.buttons.push_back(message_center::ButtonInfo( |
| l10n_util::GetStringUTF16(IDS_ASH_USB_NOTIFICATION_V2_LEARN_MORE))); |
| |
| std::unique_ptr<message_center::Notification> notification = |
| CreateSystemNotificationPtr( |
| message_center::NOTIFICATION_TYPE_SIMPLE, |
| kUsbPeripheralSpeedLimitingCableNotificationId, |
| l10n_util::GetStringUTF16( |
| IDS_ASH_USB_NOTIFICATION_V2_CABLE_WARNING_PERFORMANCE_TITLE), |
| l10n_util::GetStringUTF16( |
| IDS_ASH_USB_NOTIFICATION_V2_CABLE_WARNING_SPEED_LIMITED_BODY), |
| /*display_source=*/std::u16string(), GURL(), |
| message_center::NotifierId( |
| message_center::NotifierType::SYSTEM_COMPONENT, |
| kNotifierUsbPeripheral, |
| NotificationCatalogName::kUSBPeripheralSpeedLimitingCable), |
| optional, |
| base::MakeRefCounted<message_center::HandleNotificationClickDelegate>( |
| base::BindRepeating( |
| &OnCableNotificationClicked, |
| kUsbPeripheralSpeedLimitingCableNotificationId, |
| kNotificationDeviceLandingPageUrl)), |
| kSettingsIcon, |
| message_center::SystemNotificationWarningLevel::WARNING); |
| |
| message_center_->AddNotification(std::move(notification)); |
| } |
| |
| // Notify the user that they have reached a USB device or endpoint limit. |
| void UsbPeripheralNotificationController::OnUsbDeviceOrEndpointLimit() { |
| if (!ShouldDisplayNotification()) { |
| return; |
| } |
| |
| message_center::RichNotificationData optional; |
| optional.pinned = false; |
| std::unique_ptr<message_center::Notification> notification = |
| CreateSystemNotificationPtr( |
| message_center::NOTIFICATION_TYPE_SIMPLE, |
| kUsbPeripheralDeviceOrEndpointLimitNotificationId, |
| l10n_util::GetStringUTF16( |
| IDS_ASH_USB_NOTIFICATION_LIMIT_REACHED_TITLE), |
| l10n_util::GetStringUTF16( |
| IDS_ASH_USB_NOTIFICATION_LIMIT_REACHED_BODY), |
| /*display_source=*/std::u16string(), GURL(), |
| message_center::NotifierId( |
| message_center::NotifierType::SYSTEM_COMPONENT, |
| kNotifierUsbPeripheral, |
| NotificationCatalogName::kUsbPeripheralDeviceOrEndpointLimit), |
| optional, |
| base::MakeRefCounted<message_center::HandleNotificationClickDelegate>( |
| message_center::HandleNotificationClickDelegate:: |
| ButtonClickCallback(base::DoNothing())), |
| vector_icons::kUsbIcon, |
| message_center::SystemNotificationWarningLevel::WARNING); |
| |
| message_center_->AddNotification(std::move(notification)); |
| } |
| |
| } // namespace ash |