blob: 1de9cfe42ec74905c26d46d144fb67676ce0fc95 [file] [log] [blame]
// 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