chromium/ash/system/notification_center/notification_metrics_recorder.cc

// Copyright 2023 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/notification_center/notification_metrics_recorder.h"

#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "ash/system/notification_center/metrics_utils.h"
#include "ash/system/notification_center/notification_center_tray.h"
#include "base/check.h"
#include "base/time/time.h"
#include "ui/message_center/message_center.h"

namespace ash {
namespace {

// Duration used to log the number of notifications shown after a user logs in.
constexpr base::TimeDelta kLoginNotificationLogDuration = base::Minutes(1);

}  // namespace

NotificationMetricsRecorder::NotificationMetricsRecorder(
    NotificationCenterTray* tray)
    : tray_(tray) {
  CHECK(tray_);
  message_center::MessageCenter::Get()->AddObserver(this);
  Shell::Get()->session_controller()->AddObserver(this);
}

NotificationMetricsRecorder::~NotificationMetricsRecorder() {
  Shell::Get()->session_controller()->RemoveObserver(this);
  message_center::MessageCenter::Get()->RemoveObserver(this);
}

void NotificationMetricsRecorder::OnNotificationAdded(
    const std::string& notification_id) {
  metrics_utils::LogNotificationAdded(notification_id);
}

void NotificationMetricsRecorder::OnNotificationClicked(
    const std::string& notification_id,
    const std::optional<int>& button_index,
    const std::optional<std::u16string>& reply) {
  bool is_popup = !IsNotificationCenterVisible();
  if (reply.has_value()) {
    metrics_utils::LogInlineReplySent(notification_id, is_popup);
  } else if (button_index.has_value()) {
    metrics_utils::LogClickedActionButton(notification_id, is_popup,
                                          button_index.value());
  } else {
    metrics_utils::LogClickedBody(notification_id, is_popup);
  }
}

void NotificationMetricsRecorder::OnNotificationDisplayed(
    const std::string& notification_id,
    const message_center::DisplaySource source) {
  if (login_notification_logging_timer_.IsRunning()) {
    notifications_displayed_in_first_minute_count_++;
  }
}

void NotificationMetricsRecorder::OnNotificationPopupShown(
    const std::string& notification_id,
    bool mark_notification_as_read) {
  // Timed out popup notifications are not marked as read.
  if (!mark_notification_as_read) {
    metrics_utils::LogPopupExpiredToTray(notification_id);
  }
}

void NotificationMetricsRecorder::OnMessageViewHovered(
    const std::string& notification_id) {
  metrics_utils::LogHover(notification_id,
                          /*is_popup=*/!IsNotificationCenterVisible());
}

void NotificationMetricsRecorder::OnFirstSessionStarted() {
  login_notification_logging_timer_.Start(
      FROM_HERE, kLoginNotificationLogDuration, this,
      &NotificationMetricsRecorder::OnLoginTimerEnded);
}

void NotificationMetricsRecorder::OnLoginTimerEnded() {
  metrics_utils::LogNotificationsShownInFirstMinute(
      notifications_displayed_in_first_minute_count_);
}

bool NotificationMetricsRecorder::IsNotificationCenterVisible() const {
  return tray_->IsBubbleShown();
}

}  // namespace ash