chromium/chromeos/ash/components/report/device_metrics/actives/twenty_eight_day_impl.h

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROMEOS_ASH_COMPONENTS_REPORT_DEVICE_METRICS_ACTIVES_TWENTY_EIGHT_DAY_IMPL_H_
#define CHROMEOS_ASH_COMPONENTS_REPORT_DEVICE_METRICS_ACTIVES_TWENTY_EIGHT_DAY_IMPL_H_

#include "base/component_export.h"
#include "base/memory/weak_ptr.h"
#include "base/values.h"
#include "chromeos/ash/components/report/device_metrics/use_case/use_case.h"

namespace network {
class SimpleURLLoader;
}  // namespace network

namespace ash::report::device_metrics {

class COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_REPORT) TwentyEightDayImpl
    : public UseCase {
 public:
  explicit TwentyEightDayImpl(UseCaseParameters* params);
  TwentyEightDayImpl(const TwentyEightDayImpl&) = delete;
  TwentyEightDayImpl& operator=(const TwentyEightDayImpl&) = delete;
  ~TwentyEightDayImpl() override;

  // UseCase:
  void Run(base::OnceCallback<void()> callback) override;

  // Used by ReportController to destruct pending callbacks appropriately.
  base::WeakPtr<TwentyEightDayImpl> GetWeakPtr();

 protected:
  // UseCase:
  void CheckMembershipOprf() override;
  void OnCheckMembershipOprfComplete(
      std::unique_ptr<std::string> response_body) override;
  void CheckMembershipQuery(
      const private_membership::rlwe::PrivateMembershipRlweOprfResponse&
          oprf_response) override;
  void OnCheckMembershipQueryComplete(
      std::unique_ptr<std::string> response_body) override;
  void CheckIn() override;

  // 28DA use case passes the import request back to callback completion.
  void OnCheckInComplete(std::unique_ptr<std::string> response_body) override;
  void OnCheckInCompleteCustom(const FresnelImportDataRequest import_request,
                               std::unique_ptr<std::string> response_body);

  base::Time GetLastPingTimestamp() override;
  void SetLastPingTimestamp(base::Time ts) override;
  std::vector<private_membership::rlwe::RlwePlaintextId>
  GetPsmIdentifiersToQuery() override;
  std::optional<FresnelImportDataRequest> GenerateImportRequestBody() override;

 private:
  // Grant friend access for comprehensive testing of private/protected members.
  friend class TwentyEightDayImplBase;
  friend class TwentyEightDayImplDirectCheckIn;
  friend class TwentyEightDayImplDirectCheckMembership;

  // Check if the device needs to ping today.
  bool IsDevicePingRequired();

  // Load the 28 day actives cache ping history of the device.
  void LoadActivesCachePref();

  // Save the 28 day actives cache ping history of the device.
  // We call this method every time actives cache is updated to avoid retrying
  // across unexpected restarts and crashes.
  void SaveActivesCachePref();

  // Recalculate the |actives_cache_| to clear any old entries.
  void FilterActivesCache();

  // Find leftmost known membership in |actives_cache_|,
  // used in second phase.
  base::Time FindLeftMostKnownMembership();

  // Find rightmost known non-membership in |actives_cache_|,
  // used in second phase.
  base::Time FindRightMostKnownNonMembership();

  // First phase of check membership should be for day 0, 1, and 27.
  bool IsFirstPhaseComplete();
  std::vector<private_membership::rlwe::RlwePlaintextId>
  GetPsmIdentifiersToQueryPhaseOne();
  void CheckMembershipOprfFirstPhase();
  void OnCheckMembershipOprfCompleteFirstPhase(
      std::unique_ptr<std::string> response_body);
  void CheckMembershipQueryFirstPhase(
      const private_membership::rlwe::PrivateMembershipRlweOprfResponse&
          oprf_response);
  void OnCheckMembershipQueryCompleteFirstPhase(
      std::unique_ptr<std::string> response_body);

  // Second phase of check membership should binary search for a single
  // identifier between day 2 and 26.
  bool IsSecondPhaseComplete();
  std::vector<private_membership::rlwe::RlwePlaintextId>
  GetPsmIdentifiersToQueryPhaseTwo();
  void CheckMembershipOprfSecondPhase();
  void OnCheckMembershipOprfCompleteSecondPhase(
      std::unique_ptr<std::string> response_body);
  void CheckMembershipQuerySecondPhase(
      const private_membership::rlwe::PrivateMembershipRlweOprfResponse&
          oprf_response);
  void OnCheckMembershipQueryCompleteSecondPhase(
      std::unique_ptr<std::string> response_body);

  // Maintains callback that is executed once this use case is done running.
  base::OnceCallback<void()> callback_;

  // Manage Oprf, Query, and Import network requests on a single sequence.
  std::unique_ptr<network::SimpleURLLoader> url_loader_;

  // Pref to store the rolling history of 28 day actives.
  base::Value::Dict actives_cache_;

  // Automatically cancels callbacks when the referent of weakptr gets
  // destroyed.
  base::WeakPtrFactory<TwentyEightDayImpl> weak_factory_{this};
};

}  // namespace ash::report::device_metrics

#endif  // CHROMEOS_ASH_COMPONENTS_REPORT_DEVICE_METRICS_ACTIVES_TWENTY_EIGHT_DAY_IMPL_H_