chromium/chrome/browser/ash/policy/status_collector/activity_storage.h

// Copyright 2019 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_ASH_POLICY_STATUS_COLLECTOR_ACTIVITY_STORAGE_H_
#define CHROME_BROWSER_ASH_POLICY_STATUS_COLLECTOR_ACTIVITY_STORAGE_H_

#include <stdint.h>

#include <map>
#include <string>
#include <vector>

#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
#include "components/policy/proto/device_management_backend.pb.h"

class PrefService;

namespace policy {

// Base class for storing activity time periods, needed for status reporting.
// Derived classes like ChildActivityStorage and EnterpriseActivityStorage
// handle specific use cases.
class ActivityStorage {
 public:
  using Activities = std::vector<enterprise_management::TimePeriod>;

  // Creates activity storage. Activity data will be stored in the given
  // |pref_service| under |pref_name| preference. Activity data are aggregated
  // by day. |day_start_offset| adds this offset to |GetBeginningOfDay|.
  ActivityStorage(PrefService* pref_service,
                  const std::string& pref_name,
                  base::TimeDelta day_start_offset);
  ActivityStorage(const ActivityStorage&) = delete;
  ActivityStorage& operator=(const ActivityStorage&) = delete;
  virtual ~ActivityStorage();

  // Returns when the day starts. An offset for this value can be provided
  // through the constructor.
  base::Time GetBeginningOfDay(base::Time timestamp) const;

  // Clears stored activity periods outside of storage range defined by
  // |max_past_activity_interval| and |max_future_activity_interval| from
  // |base_time|. If |max_past_activity_interval| and
  // |max_future_activity_interval| are not passed, all past data will be
  // removed.
  void PruneActivityPeriods(
      base::Time base_time,
      base::TimeDelta max_past_activity_interval = base::Days(0),
      base::TimeDelta max_future_activity_interval = base::TimeDelta::Max());

  // Trims the stored activity periods to only retain data within the
  // [|min_day_key|, |max_day_key|).
  void TrimActivityPeriods(int64_t min_day_key, int64_t max_day_key);

  // Trims the stored activity periods to ensure all intervals do not overlap.
  void RemoveOverlappingActivityPeriods();

  // Retrieves all activity periods that occurred up to |end_time| that are in
  // the pref keys that can be parsed by |ParseActivityPeriodPrefKey|. The map
  // is keyed by activity IDs.
  const std::map<std::string, Activities> GetActivityPeriods(
      base::Time end_time = base::Time::Max()) const;

  // Retrieves all activity periods that occurred up to |end_time| that are in
  // the pref keys that can be parsed by |ParseActivityPeriodPrefKey| where
  // there is no ID.
  const Activities GetActivityPeriodsWithNoId(
      base::Time end_time = base::Time::Max()) const;

  // Adds an activity period. Accepts empty |activity_id| if it should not
  // be stored.
  void AddActivityPeriod(base::Time start,
                         base::Time end,
                         const std::string& activity_id = "");

 protected:
  // Determine the day key (milliseconds since epoch for corresponding
  // |GetBeginningOfDay()| in UTC) for a given |timestamp|.
  int64_t LocalTimeToUtcDayStart(base::Time timestamp) const;

  // Creates the key that will be used to store an ActivityPeriod in the prefs.
  // If |activity_id| is empty, the key will be |start|. Otherwise it will
  // contain both values, which can retrieved using the
  // |ParseActivityPeriodPrefKey|.
  static std::string MakeActivityPeriodPrefKey(int64_t start,
                                               const std::string& activity_id);

  // Tries to parse a pref key, returning true if succeeded (see
  // base::StringToInt64 and base::Base64Decode for conditions). Also
  // retrieves the values that are encoded in the pref key. |activity_id| will
  // only be filled if it was provided when making the key (see
  // |MakeActivityPeriodPrefKey|).
  static bool ParseActivityPeriodPrefKey(const std::string& key,
                                         int64_t* start_timestamp,
                                         std::string* activity_id);

  void SetActivityPeriods(
      const std::map<std::string, Activities>& new_activity_periods);

  // Retrieves all activity periods that are in the pref keys that can be parsed
  // by |ParseActivityPeriodPrefKey|.
  void ForEachActivityPeriodFromPref(
      const base::RepeatingCallback<
          void(const int64_t, const int64_t, const std::string&)>& f) const;

  const raw_ptr<PrefService> pref_service_ = nullptr;
  const std::string pref_name_;

  // Distance from midnight. |GetBeginningOfDay| uses this, as some
  // implementations might have a different beginning of day from others.
  base::TimeDelta day_start_offset_;
};

}  // namespace policy

#endif  // CHROME_BROWSER_ASH_POLICY_STATUS_COLLECTOR_ACTIVITY_STORAGE_H_