blob: 3c0701f9b82530e6d471c25852e0e76c9005de1d [file] [log] [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_USER_EDUCATION_RECENT_SESSION_POLICY_H_
#define CHROME_BROWSER_UI_USER_EDUCATION_RECENT_SESSION_POLICY_H_
#include <optional>
#include <utility>
#include <vector>
#include "base/time/time.h"
#include "chrome/browser/user_education/browser_user_education_storage_service.h"
// Class that defines policy for handling recent sessions.
// Allows recording of metrics and possibly modifying promo behavior.
class RecentSessionPolicy {
public:
virtual ~RecentSessionPolicy() = default;
// Records any metrics associated with tracking recent usage.
virtual void RecordRecentUsageMetrics(
const RecentSessionData& recent_sessions) = 0;
// Determines whether low usage should be taken into account when choosing
// whether to show promos.
virtual bool ShouldEnableLowUsagePromoMode(
const RecentSessionData& recent_sessions) const = 0;
};
// Uses a series of thresholds to determine if this is a high- or low-usage
// profile/installation. Default is to follow guidance from UX research, but the
// parameters are adjustable via trade study parameters.
class RecentSessionPolicyImpl : public RecentSessionPolicy {
public:
// Represents one element of a logging and/or low-usage-detection policy.
class Constraint {
public:
virtual ~Constraint() = default;
// Analyzes `recent_sessions` and returns a count.
// If there is insufficient data to produce a count, returns std::nullopt.
virtual std::optional<int> GetCount(
const RecentSessionData& recent_sessions) const = 0;
// Returns whether recording of metrics and sessions should be skipped
// because e.g. the metric would have been recorded already during the
// current calendar day. Default is false.
virtual bool ShouldSkipRecording(
const RecentSessionData& recent_sessions) const;
};
// Counts the number of sessions in the given number of `days`. Does not
// care about calendar days; this is just 24-hour periods.
class SessionCountConstraint : public Constraint {
public:
explicit SessionCountConstraint(int days) : days_(days) {}
~SessionCountConstraint() override = default;
std::optional<int> GetCount(
const RecentSessionData& recent_sessions) const override;
private:
const int days_;
};
// Represents a constraint that should only be recorded daily.
class DailyConstraint : public Constraint {
public:
bool ShouldSkipRecording(
const RecentSessionData& recent_sessions) const override;
};
// Counts the number of active weeks in the past number of `weeks`. Uses the
// last seven calendar days (including today).
class ActiveWeeksConstraint : public DailyConstraint {
public:
explicit ActiveWeeksConstraint(int weeks, int active_days)
: weeks_(weeks), active_days_(active_days) {}
~ActiveWeeksConstraint() override = default;
std::optional<int> GetCount(
const RecentSessionData& recent_sessions) const override;
private:
const int weeks_;
const int active_days_;
};
// Counts the number of active days in the past number of `days`. Uses
// calendar days, including today.
class ActiveDaysConstraint : public DailyConstraint {
public:
explicit ActiveDaysConstraint(int days) : days_(days) {}
~ActiveDaysConstraint() override = default;
std::optional<int> GetCount(
const RecentSessionData& recent_sessions) const override;
private:
const int days_;
};
// Contains data about the various constraints.
struct ConstraintInfo {
ConstraintInfo();
ConstraintInfo(std::unique_ptr<Constraint> constraint,
std::string histogram_name,
std::optional<int> histogram_max,
std::optional<int> low_usage_max);
ConstraintInfo(ConstraintInfo&&) noexcept;
ConstraintInfo& operator=(ConstraintInfo&&) noexcept;
~ConstraintInfo();
// The constraint itself.
std::unique_ptr<Constraint> constraint;
// The histogram to log, if any.
std::string histogram_name;
// The max of the histogram; if zero, a default value is used.
std::optional<int> histogram_max;
// The threshold above which the current user is not eligible for low usage
// promo mode. If not specified, only histograms will be emitted.
std::optional<int> low_usage_max;
};
using ConstraintInfos = std::vector<ConstraintInfo>;
// Creates a policy with the given constraints.
explicit RecentSessionPolicyImpl(
ConstraintInfos constraints = GetDefaultConstraints());
RecentSessionPolicyImpl(const RecentSessionPolicyImpl&) = delete;
void operator=(const RecentSessionPolicyImpl&) = delete;
~RecentSessionPolicyImpl() override;
// RecentSessionPolicy:
void RecordRecentUsageMetrics(
const RecentSessionData& recent_sessions) override;
bool ShouldEnableLowUsagePromoMode(
const RecentSessionData& recent_sessions) const override;
void set_constraints_for_testing(ConstraintInfos constraints) {
CHECK(!constraints.empty());
constraints_ = std::move(constraints);
}
private:
// Gets a set of constraints with parameters read from the feature flag, or
// sensible defaults.
static ConstraintInfos GetDefaultConstraints();
ConstraintInfos constraints_;
};
#endif // CHROME_BROWSER_UI_USER_EDUCATION_RECENT_SESSION_POLICY_H_