text: // Copyright 2019 The Chromium Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  #ifndef CHROME_BROWSER_CHROMEOS_POLICY_STATUS_COLLECTOR_ACTIVITY_STORAGE_H_
  #define CHROME_BROWSER_CHROMEOS_POLICY_STATUS_COLLECTOR_ACTIVITY_STORAGE_H_
  
  #include <stdint.h>
  
  #include <map>
  #include <string>
  #include <vector>
  
  #include "base/callback_forward.h"
  #include "base/optional.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::TimeDelta::FromDays(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(
        base::RepeatingCallback<
            void(const int64_t, const int64_t, const std::string&)> f) const;
  
    PrefService* const 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_CHROMEOS_POLICY_STATUS_COLLECTOR_ACTIVITY_STORAGE_H_
  