chromium/ash/app_list/app_list_feature_usage_metrics.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/app_list/app_list_feature_usage_metrics.h"

#include <memory>

#include "ash/app_list/app_list_controller_impl.h"
#include "ash/constants/ash_features.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h"
#include "chromeos/ash/components/feature_usage/feature_usage_metrics.h"

namespace ash {
namespace {

// Feature name for clamshell mode launcher.
constexpr char kClamshellLauncher[] = "ClamshellLauncher";

// Feature name for tablet mode launcher.
constexpr char kTabletLauncher[] = "TabletLauncher";

// Supplies eligibility information for clamshell launcher.
class ClamshellDelegate : public feature_usage::FeatureUsageMetrics::Delegate {
 public:
  ClamshellDelegate() = default;
  ClamshellDelegate(const ClamshellDelegate&) = delete;
  ClamshellDelegate& operator=(const ClamshellDelegate&) = delete;
  ~ClamshellDelegate() override = default;

  // feature_usage::FeatureUsageMetrics::Delegate:
  bool IsEligible() const override {
    // Kiosk app sessions cannot use the launcher.
    return !Shell::Get()->session_controller()->IsRunningInAppMode();
  }

  bool IsEnabled() const override {
    // The launcher is always enabled for eligible sessions.
    return IsEligible();
  }
};

// Supplies eligibility information for tablet launcher.
class TabletDelegate : public feature_usage::FeatureUsageMetrics::Delegate {
 public:
  TabletDelegate() = default;
  TabletDelegate(const TabletDelegate&) = delete;
  TabletDelegate& operator=(const TabletDelegate&) = delete;
  ~TabletDelegate() override = default;

  // feature_usage::FeatureUsageMetrics::Delegate:
  bool IsEligible() const override {
    // Kiosk app sessions cannot use the launcher.
    if (Shell::Get()->session_controller()->IsRunningInAppMode())
      return false;

    // If the device cannot enter tablet mode, the tablet mode launcher is not
    // available.
    return Shell::Get()->tablet_mode_controller()->CanEnterTabletMode();
  }

  bool IsEnabled() const override {
    // The launcher is always enabled for eligible sessions.
    return IsEligible();
  }
};

}  // namespace

AppListFeatureUsageMetrics::AppListFeatureUsageMetrics()
    : clamshell_delegate_(std::make_unique<ClamshellDelegate>()),
      clamshell_metrics_(kClamshellLauncher, clamshell_delegate_.get()),
      tablet_delegate_(std::make_unique<TabletDelegate>()),
      tablet_metrics_(kTabletLauncher, tablet_delegate_.get()) {
  Shell::Get()->app_list_controller()->AddObserver(this);
}

AppListFeatureUsageMetrics::~AppListFeatureUsageMetrics() {
  Shell::Get()->app_list_controller()->RemoveObserver(this);
}

void AppListFeatureUsageMetrics::OnAppListVisibilityChanged(
    bool shown,
    int64_t display_id) {
  if (shown) {
    OnAppListShown();
  } else {
    OnAppListHidden();
  }
}

void AppListFeatureUsageMetrics::OnAppListShown() {
  if (Shell::Get()->IsInTabletMode()) {
    StartTabletUsage();
  } else {
    StartClamshellUsage();
  }
}

void AppListFeatureUsageMetrics::OnAppListHidden() {
  StopTabletUsage();
  StopClamshellUsage();
}

void AppListFeatureUsageMetrics::StartClamshellUsage() {
  if (is_using_clamshell_)
    return;
  DCHECK(clamshell_delegate_->IsEligible());
  clamshell_metrics_.RecordUsage(true);
  clamshell_metrics_.StartSuccessfulUsage();
  is_using_clamshell_ = true;
}

void AppListFeatureUsageMetrics::StopClamshellUsage() {
  if (!is_using_clamshell_)
    return;
  clamshell_metrics_.StopSuccessfulUsage();
  is_using_clamshell_ = false;
}

void AppListFeatureUsageMetrics::StartTabletUsage() {
  if (is_using_tablet_)
    return;

  // Ignore users on ineligible devices who have forced tablet mode via flags
  // or debug shortcut keys. FeatureUsageMetrics requires that RecordUsage()
  // is never called when IsEligible() is false.
  if (!tablet_delegate_->IsEligible())
    return;

  tablet_metrics_.RecordUsage(true);
  tablet_metrics_.StartSuccessfulUsage();
  is_using_tablet_ = true;
}

void AppListFeatureUsageMetrics::StopTabletUsage() {
  if (!is_using_tablet_)
    return;
  tablet_metrics_.StopSuccessfulUsage();
  is_using_tablet_ = false;
}

}  // namespace ash