| // Copyright 2018 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/ash/child_accounts/time_limit_notifier.h" |
| |
| #include <memory> |
| #include <string> |
| |
| #include "ash/constants/notifier_catalogs.h" |
| #include "ash/public/cpp/notification_utils.h" |
| #include "base/functional/bind.h" |
| #include "base/i18n/time_formatting.h" |
| #include "chrome/browser/notifications/notification_display_service.h" |
| #include "chrome/browser/notifications/notification_display_service_factory.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/grit/generated_resources.h" |
| #include "chromeos/ui/vector_icons/vector_icons.h" |
| #include "content/public/browser/browser_context.h" |
| #include "ui/base/l10n/l10n_util.h" |
| #include "ui/base/l10n/time_format.h" |
| #include "ui/message_center/public/cpp/notification.h" |
| #include "url/gurl.h" |
| |
| namespace ash { |
| |
| namespace { |
| |
| constexpr base::TimeDelta kWarningNotificationTimeout = base::Minutes(5); |
| constexpr base::TimeDelta kExitNotificationTimeout = base::Minutes(1); |
| |
| // Lock notification id. All the time limit lock notifications share the same id |
| // so that a subsequent notification can replace the previous one. |
| constexpr char kTimeLimitLockNotificationId[] = "time-limit-lock-notification"; |
| |
| // Policy update notification id. Each limit has its own id, because we want to |
| // display all updates, which may happen simultaneously. |
| constexpr char kTimeLimitBedtimeUpdatedId[] = "time-limit-bedtime-updated"; |
| constexpr char kTimeLimitScreenTimeUpdatedId[] = |
| "time-limit-screen-time-updated"; |
| constexpr char kTimeLimitOverrideUpdatedId[] = "time-limit-override-updated"; |
| |
| // The notifier id representing the app. |
| constexpr char kTimeLimitNotifierId[] = "family-link"; |
| |
| void ShowNotification(std::u16string title, |
| const NotificationCatalogName& catalog_name, |
| std::u16string message, |
| const std::string& notification_id, |
| content::BrowserContext* context) { |
| message_center::RichNotificationData option_fields; |
| option_fields.fullscreen_visibility = |
| message_center::FullscreenVisibility::OVER_USER; |
| message_center::Notification notification = CreateSystemNotification( |
| message_center::NOTIFICATION_TYPE_SIMPLE, notification_id, title, message, |
| l10n_util::GetStringUTF16(IDS_TIME_LIMIT_NOTIFICATION_DISPLAY_SOURCE), |
| GURL(), |
| message_center::NotifierId(message_center::NotifierType::SYSTEM_COMPONENT, |
| kTimeLimitNotifierId, catalog_name), |
| option_fields, |
| base::MakeRefCounted<message_center::NotificationDelegate>(), |
| chromeos::kNotificationSupervisedUserIcon, |
| message_center::SystemNotificationWarningLevel::NORMAL); |
| NotificationDisplayServiceFactory::GetForProfile( |
| Profile::FromBrowserContext(context)) |
| ->Display(NotificationHandler::Type::TRANSIENT, notification, |
| /*metadata=*/nullptr); |
| } |
| |
| std::u16string RemainingTimeString(base::TimeDelta time_remaining) { |
| return ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_DURATION, |
| ui::TimeFormat::LENGTH_LONG, time_remaining); |
| } |
| |
| } // namespace |
| |
| TimeLimitNotifier::TimeLimitNotifier(content::BrowserContext* context) |
| : context_(context) {} |
| TimeLimitNotifier::~TimeLimitNotifier() = default; |
| |
| void TimeLimitNotifier::MaybeScheduleLockNotifications( |
| LimitType limit_type, |
| base::TimeDelta remaining_time) { |
| // Stop any previously set timers. |
| UnscheduleNotifications(); |
| |
| int title_id; |
| NotificationCatalogName catalog_name; |
| switch (limit_type) { |
| case LimitType::kScreenTime: |
| title_id = IDS_SCREEN_TIME_NOTIFICATION_TITLE; |
| catalog_name = NotificationCatalogName::kScreenTimeLimit; |
| break; |
| case LimitType::kBedTime: |
| case LimitType::kOverride: |
| title_id = IDS_BED_TIME_NOTIFICATION_TITLE; |
| catalog_name = NotificationCatalogName::kBedtimeLimit; |
| break; |
| } |
| |
| const std::u16string title = l10n_util::GetStringUTF16(title_id); |
| |
| if (remaining_time >= kWarningNotificationTimeout) { |
| warning_notification_timer_.Start( |
| FROM_HERE, remaining_time - kWarningNotificationTimeout, |
| base::BindOnce(&ShowNotification, title, catalog_name, |
| RemainingTimeString(kWarningNotificationTimeout), |
| kTimeLimitLockNotificationId, context_)); |
| } |
| if (remaining_time >= kExitNotificationTimeout) { |
| exit_notification_timer_.Start( |
| FROM_HERE, remaining_time - kExitNotificationTimeout, |
| base::BindOnce(&ShowNotification, title, catalog_name, |
| RemainingTimeString(kExitNotificationTimeout), |
| kTimeLimitLockNotificationId, context_)); |
| } |
| } |
| |
| void TimeLimitNotifier::ShowPolicyUpdateNotification( |
| LimitType limit_type, |
| std::optional<base::Time> lock_time) { |
| int title_id; |
| std::u16string message; |
| std::string notification_id; |
| NotificationCatalogName catalog_name; |
| switch (limit_type) { |
| case LimitType::kScreenTime: |
| title_id = IDS_TIME_LIMIT_UPDATED_NOTIFICATION_TITLE; |
| message = l10n_util::GetStringUTF16( |
| IDS_SCREEN_TIME_UPDATED_NOTIFICATION_MESSAGE); |
| notification_id = kTimeLimitScreenTimeUpdatedId; |
| catalog_name = NotificationCatalogName::kScreenTimeLimitUpdated; |
| break; |
| case LimitType::kBedTime: |
| title_id = IDS_TIME_LIMIT_UPDATED_NOTIFICATION_TITLE; |
| message = |
| l10n_util::GetStringUTF16(IDS_BEDTIME_UPDATED_NOTIFICATION_MESSAGE); |
| notification_id = kTimeLimitBedtimeUpdatedId; |
| catalog_name = NotificationCatalogName::kBedtimeUpdated; |
| break; |
| case LimitType::kOverride: |
| if (!lock_time) |
| return; |
| title_id = IDS_OVERRIDE_WITH_DURATION_UPDATED_NOTIFICATION_TITLE; |
| message = l10n_util::GetStringFUTF16( |
| IDS_OVERRIDE_WITH_DURATION_UPDATED_NOTIFICATION_MESSAGE, |
| base::TimeFormatTimeOfDay(lock_time.value())); |
| notification_id = kTimeLimitOverrideUpdatedId; |
| catalog_name = NotificationCatalogName::kTimeLimitOverride; |
| break; |
| } |
| ShowNotification(l10n_util::GetStringUTF16(title_id), catalog_name, message, |
| notification_id, context_); |
| } |
| |
| void TimeLimitNotifier::UnscheduleNotifications() { |
| warning_notification_timer_.Stop(); |
| exit_notification_timer_.Stop(); |
| } |
| |
| } // namespace ash |