chromium/ash/webui/eche_app_ui/launch_app_helper.cc

// 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/webui/eche_app_ui/launch_app_helper.h"

#include "ash/constants/notifier_catalogs.h"
#include "ash/public/cpp/system/toast_data.h"
#include "ash/public/cpp/system/toast_manager.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "ash/webui/eche_app_ui/apps_launch_info_provider.h"
#include "ash/webui/eche_app_ui/eche_alert_generator.h"
#include "base/check.h"
#include "base/metrics/histogram_functions.h"
#include "chromeos/ash/components/phonehub/phone_hub_manager.h"
#include "chromeos/ash/components/phonehub/screen_lock_manager.h"
#include "ui/gfx/image/image.h"

namespace ash {
namespace eche_app {

namespace {

// TODO(b/265173006): Create an AppMetricsRecorder class to abstract metrics
// logging from implementation classes.
constexpr base::TimeDelta kPackageSetResetFrequency = base::Days(1);

}  // namespace

LaunchAppHelper::NotificationInfo::NotificationInfo(
    Category category,
    absl::variant<NotificationType, mojom::WebNotificationType> type)
    : category_(category), type_(type) {
  DCHECK(nullptr != absl::get_if<NotificationType>(&type)
             ? category == Category::kNative
             : category == Category::kWebUI);
  DCHECK(nullptr != absl::get_if<mojom::WebNotificationType>(&type)
             ? category == Category::kWebUI
             : category == Category::kNative);
}

LaunchAppHelper::NotificationInfo::~NotificationInfo() = default;

LaunchAppHelper::LaunchAppHelper(
    phonehub::PhoneHubManager* phone_hub_manager,
    LaunchEcheAppFunction launch_eche_app_function,
    LaunchNotificationFunction launch_notification_function,
    CloseNotificationFunction close_notification_function)
    : phone_hub_manager_(phone_hub_manager),
      launch_eche_app_function_(launch_eche_app_function),
      launch_notification_function_(launch_notification_function),
      close_notification_function_(close_notification_function) {}
LaunchAppHelper::~LaunchAppHelper() = default;

LaunchAppHelper::AppLaunchProhibitedReason
LaunchAppHelper::CheckAppLaunchProhibitedReason(FeatureStatus status) const {
  if (IsScreenLockRequired()) {
    return LaunchAppHelper::AppLaunchProhibitedReason::kDisabledByScreenLock;
  }

  return LaunchAppHelper::AppLaunchProhibitedReason::kNotProhibited;
}

bool LaunchAppHelper::IsScreenLockRequired() const {
  const bool enable_phone_screen_lock =
      phone_hub_manager_->GetScreenLockManager()->GetLockStatus() ==
      phonehub::ScreenLockManager::LockStatus::kLockedOn;
  auto* session_controller = ash::Shell::Get()->session_controller();
  const bool enable_cros_screen_lock =
      session_controller->CanLockScreen() &&
      session_controller->ShouldLockScreenAutomatically();
  // We should ask users to enable screen lock if they enabled screen lock on
  // their phone but didn't enable yet on CrOS.
  const bool should_lock = enable_phone_screen_lock && !enable_cros_screen_lock;
  return should_lock;
}

void LaunchAppHelper::ShowNotification(
    const std::optional<std::u16string>& title,
    const std::optional<std::u16string>& message,
    std::unique_ptr<NotificationInfo> info) const {
  launch_notification_function_.Run(title, message, std::move(info));
}

void LaunchAppHelper::CloseNotification(
    const std::string& notification_id) const {
  close_notification_function_.Run(notification_id);
}

void LaunchAppHelper::ShowToast(const std::u16string& text) const {
  ash::ToastManager::Get()->Show(ash::ToastData(
      kEcheAppToastId, ash::ToastCatalogName::kEcheAppToast, text));
}

void LaunchAppHelper::LaunchEcheApp(
    std::optional<int64_t> notification_id,
    const std::string& package_name,
    const std::u16string& visible_name,
    const std::optional<int64_t>& user_id,
    const gfx::Image& icon,
    const std::u16string& phone_name,
    AppsLaunchInfoProvider* apps_launch_info_provider) {
  launch_eche_app_function_.Run(notification_id, package_name, visible_name,
                                user_id, icon, phone_name,
                                apps_launch_info_provider);

  // Sessions can last for well over a day, so this check exists to cover that
  // corner case and clears the |session_packages_launched_| set so we can
  // start tracking unique packages again.
  // TODO(b/265172591): Optimize the reset to align with histogram uploads.
  if (session_packages_last_reset_ == base::TimeTicks() ||
      base::TimeTicks::Now() - session_packages_last_reset_ >=
          kPackageSetResetFrequency) {
    session_packages_launched_.clear();
    session_packages_last_reset_ = base::TimeTicks::Now();
  }

  if (!session_packages_launched_.contains(package_name)) {
    base::UmaHistogramCounts1000("Eche.UniqueAppsStreamed.PerDay", 1);
    session_packages_launched_.insert(package_name);
  }
}

}  // namespace eche_app
}  // namespace ash