chromium/chrome/browser/metrics/structured/lacros_structured_metrics_delegate.h

// 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.

#ifndef CHROME_BROWSER_METRICS_STRUCTURED_LACROS_STRUCTURED_METRICS_DELEGATE_H_
#define CHROME_BROWSER_METRICS_STRUCTURED_LACROS_STRUCTURED_METRICS_DELEGATE_H_

#include <vector>

#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "base/task/sequenced_task_runner.h"
#include "components/metrics/structured/event.h"
#include "components/metrics/structured/structured_metrics_client.h"

namespace metrics::structured {

// Structured metrics recording delegate for Lacros. This class forwards all
// events to Ash Chrome, where the main service to validate and persist events
// is.
//
// This recorder is thread-safe. Any calls to |this| not on the dedicated
// sequence will be forwarded to the dedicated sequence set by |SetSequence|.
class LacrosStructuredMetricsDelegate
    : public StructuredMetricsClient::RecordingDelegate {
 public:
  LacrosStructuredMetricsDelegate();
  ~LacrosStructuredMetricsDelegate() override;

  LacrosStructuredMetricsDelegate(
      const LacrosStructuredMetricsDelegate& recorder) = delete;
  LacrosStructuredMetricsDelegate& operator=(
      const LacrosStructuredMetricsDelegate& recorder) = delete;

  // Assigns a sequence for which events will be recorded. Should be called
  // before any calls to Record. This sequence should be the affine sequence.
  void SetSequence(
      const scoped_refptr<base::SequencedTaskRunner> sequence_task_runner);

  // RecordingDelegate:
  void RecordEvent(Event&& event) override;
  bool IsReadyToRecord() const override;

 private:
  friend class LacrosStructuredMetricsDelegateTest;

  // For testing.
  class Observer : public base::CheckedObserver {
   public:
    // Called on every call of |RecordEvent|.
    virtual void OnRecord(const Event& event) = 0;

    // Called when |enqueued_events_| is flushed.
    virtual void OnFlush() = 0;
  };

  void AddObserver(Observer* observer);
  void RemoveObserver(Observer* observer);

  scoped_refptr<base::SequencedTaskRunner> sequence_task_runner_;

  // Lacros service may not be ready by the time some metrics need to be
  // recorded. Enqueue those events in memory until the service is ready.
  //
  // TODO(jongahn): Think about having |this| own a remote and expose an API in
  // LacrosService to allow arbitrary receivers be bound. This could allow other
  // processes utilize Structured Metrics.
  std::vector<Event> enqueued_events_;

  base::ObserverList<Observer> observers_;

  base::WeakPtrFactory<LacrosStructuredMetricsDelegate> weak_ptr_factory_{this};
};

}  // namespace metrics::structured

#endif  // CHROME_BROWSER_METRICS_STRUCTURED_LACROS_STRUCTURED_METRICS_DELEGATE_H_