blob: ebd3629791bcb905f252e0cb6744162ac876d116 [file] [log] [blame]
// Copyright 2022 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/notifications/multi_capture_notification.h"
#include <memory>
#include "ash/constants/notifier_catalogs.h"
#include "ash/public/cpp/notification_utils.h"
#include "ash/resources/vector_icons/vector_icons.h"
#include "ash/shell.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/safe_ref.h"
#include "base/notreached.h"
#include "base/strings/strcat.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "chrome/browser/notifications/system_notification_helper.h"
#include "chrome/grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/message_center/public/cpp/notification.h"
#include "ui/message_center/public/cpp/notifier_id.h"
namespace {
const char kMultiCaptureId[] = "multi_capture";
const char kNotifierMultiCapture[] = "ash.multi_capture";
constexpr base::TimeDelta kMinimumNotificationPresenceTime = base::Seconds(6);
std::unique_ptr<message_center::Notification> CreateNotification(
const url::Origin& origin) {
message_center::NotifierId notifier_id(
message_center::NotifierType::SYSTEM_COMPONENT, kNotifierMultiCapture,
ash::NotificationCatalogName::kMultiCapture);
const std::string host = origin.host();
std::u16string converted_host;
if (!base::UTF8ToUTF16(host.c_str(), host.size(), &converted_host)) {
NOTREACHED();
return nullptr;
}
// TODO(crbug.com/1356101): Add "Don't show again" for managed sessions.
return ash::CreateSystemNotificationPtr(
message_center::NOTIFICATION_TYPE_SIMPLE,
base::StrCat({kMultiCaptureId, ":", host}),
/*title=*/
l10n_util::GetStringFUTF16(IDS_MULTI_CAPTURE_NOTIFICATION_TITLE,
converted_host),
/*message=*/
l10n_util::GetStringFUTF16(IDS_MULTI_CAPTURE_NOTIFICATION_MESSAGE,
converted_host),
/*display_source=*/std::u16string(), /*origin_url=*/GURL(), notifier_id,
/*optional_fields=*/message_center::RichNotificationData(),
/*delegate=*/
base::MakeRefCounted<message_center::HandleNotificationClickDelegate>(
message_center::HandleNotificationClickDelegate::ButtonClickCallback(
base::DoNothing())),
ash::kPrivacyIndicatorsScreenShareIcon,
message_center::SystemNotificationWarningLevel::NORMAL);
}
} // namespace
namespace ash {
MultiCaptureNotification::NotificationMetadata::NotificationMetadata(
std::string id,
base::TimeTicks time_created)
: id(std::move(id)), time_created(std::move(time_created)) {}
MultiCaptureNotification::NotificationMetadata::NotificationMetadata(
MultiCaptureNotification::NotificationMetadata&& metadata) = default;
MultiCaptureNotification::NotificationMetadata&
MultiCaptureNotification::NotificationMetadata::operator=(
MultiCaptureNotification::NotificationMetadata&& metadata) = default;
MultiCaptureNotification::NotificationMetadata::~NotificationMetadata() =
default;
MultiCaptureNotification::MultiCaptureNotification() {
DCHECK(Shell::HasInstance());
multi_capture_service_client_observation_.Observe(
Shell::Get()->multi_capture_service_client());
}
MultiCaptureNotification::~MultiCaptureNotification() = default;
void MultiCaptureNotification::MultiCaptureStarted(const std::string& label,
const url::Origin& origin) {
std::unique_ptr<message_center::Notification> notification =
CreateNotification(origin);
notifications_metadata_.emplace(
label, NotificationMetadata(notification->id(), base::TimeTicks::Now()));
// TODO(crbug.com/1356102): Make sure the notification does not disappear
// automatically after some time.
SystemNotificationHelper::GetInstance()->Display(*notification);
}
void MultiCaptureNotification::MultiCaptureStopped(const std::string& label) {
const auto notifications_metadata_iterator =
notifications_metadata_.find(label);
if (notifications_metadata_iterator == notifications_metadata_.end()) {
LOG(ERROR) << "Label could not be found";
return;
}
NotificationMetadata& metadata = notifications_metadata_iterator->second;
const base::TimeDelta time_already_shown =
base::TimeTicks::Now() - metadata.time_created;
if (time_already_shown >= kMinimumNotificationPresenceTime) {
SystemNotificationHelper::GetInstance()->Close(
/*notification_id=*/metadata.id);
notifications_metadata_.erase(notifications_metadata_iterator);
} else if (!metadata.closing_timer) {
metadata.closing_timer = std::make_unique<base::OneShotTimer>();
metadata.closing_timer->Start(
FROM_HERE, kMinimumNotificationPresenceTime - time_already_shown,
base::BindOnce(&MultiCaptureNotification::MultiCaptureStopped,
weak_factory_.GetSafeRef(), label));
}
}
void MultiCaptureNotification::MultiCaptureServiceClientDestroyed() {
multi_capture_service_client_observation_.Reset();
for (const auto& [label, notification_metadata] : notifications_metadata_) {
SystemNotificationHelper::GetInstance()->Close(
/*notification_id=*/notification_metadata.id);
}
notifications_metadata_.clear();
}
} // namespace ash