blob: 11c91f89f9d4c7f80cb5bfb9e611ae6e189bf74b [file] [log] [blame]
// Copyright 2014 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.
#include <stdint.h>
#include <map>
#include <memory>
#include <string>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/threading/thread_checker.h"
#include "base/timer/timer.h"
#include "components/metrics/daily_event.h"
#include "components/rappor/public/rappor_parameters.h"
#include "components/rappor/public/rappor_service.h"
#include "components/rappor/public/sample.h"
#include "components/rappor/sampler.h"
class PrefRegistrySimple;
class PrefService;
namespace network {
class SharedURLLoaderFactory;
namespace rappor {
class LogUploaderInterface;
class RapporMetric;
class RapporReports;
// This class provides an interface for recording samples for rappor metrics,
// and periodically generates and uploads reports based on the collected data.
class RapporServiceImpl : public RapporService {
// Constructs a RapporServiceImpl.
// Calling code is responsible for ensuring that the lifetime of
// |pref_service| is longer than the lifetime of RapporServiceImpl.
// |is_incognito_callback| will be called to test if incognito mode is active.
RapporServiceImpl(PrefService* pref_service,
const base::Callback<bool(void)> is_incognito_callback);
virtual ~RapporServiceImpl();
// Add an observer for collecting daily metrics.
void AddDailyObserver(
std::unique_ptr<metrics::DailyEvent::Observer> observer);
// Initializes the rappor service, including loading the cohort and secret
// preferences from disk.
void Initialize(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
// Updates the settings for metric recording and uploading.
// The RapporServiceImpl must be initialized before this method is called.
// If |may_record| is true, data will be recorded and periodic reports will
// be generated and queued for upload.
// If |may_upload| is true, reports will be uploaded from the queue.
void Update(bool may_record, bool may_upload);
// Constructs a Sample object for the caller to record fields in.
std::unique_ptr<Sample> CreateSample(RapporType) override;
// Records a Sample of rappor metric specified by |metric_name|.
// example:
// std::unique_ptr<Sample> sample =
// rappor_service->CreateSample(MY_METRIC_TYPE);
// sample->SetStringField("Field1", "some string");
// sample->SetFlagsValue("Field2", SOME|FLAGS);
// rappor_service->RecordSample("MyMetric", std::move(sample));
// This will result in a report setting two metrics "MyMetric.Field1" and
// "MyMetric.Field2", and they will both be generated from the same sample,
// to allow for correlations to be computed.
void RecordSample(const std::string& metric_name,
std::unique_ptr<Sample> sample) override;
// Records a sample of the rappor metric specified by |metric_name|.
// Creates and initializes the metric, if it doesn't yet exist.
void RecordSampleString(const std::string& metric_name,
RapporType type,
const std::string& sample) override;
// Registers the names of all of the preferences used by RapporServiceImpl in
// the provided PrefRegistry. This should be called before calling Start().
static void RegisterPrefs(PrefRegistrySimple* registry);
// Initializes the state of the RapporServiceImpl.
void InitializeInternal(std::unique_ptr<LogUploaderInterface> uploader,
int32_t cohort,
const std::string& secret);
// Cancels the next call to OnLogInterval.
virtual void CancelNextLogRotation();
// Schedules the next call to OnLogInterval.
virtual void ScheduleNextLogRotation(base::TimeDelta interval);
// Logs all of the collected metrics to the reports proto message and clears
// the internal map. Exposed for tests. Returns true if any metrics were
// recorded.
bool ExportMetrics(RapporReports* reports);
// Records a sample of the rappor metric specified by |parameters|.
// Creates and initializes the metric, if it doesn't yet exist.
// Exposed for tests.
void RecordSampleInternal(const std::string& metric_name,
const RapporParameters& parameters,
const std::string& sample);
// Checks if the service has been started successfully.
bool IsInitialized() const;
// Called whenever the logging interval elapses to generate a new log of
// reports and pass it to the uploader.
void OnLogInterval();
// Check if recording of the metric is allowed, given it's parameters.
// This will check that we are not in incognito mode, and that the
// appropriate recording group is enabled.
bool RecordingAllowed(const RapporParameters& parameters);
// Finds a metric in the metrics_map_, creating it if it doesn't already
// exist.
RapporMetric* LookUpMetric(const std::string& metric_name,
const RapporParameters& parameters);
// A weak pointer to the PrefService used to read and write preferences.
PrefService* pref_service_;
// A callback for testing if incognito mode is active;
const base::Callback<bool(void)> is_incognito_callback_;
// Client-side secret used to generate fake bits.
std::string secret_;
// The cohort this client is assigned to. -1 is uninitialized.
int32_t cohort_;
// Timer which schedules calls to OnLogInterval().
base::OneShotTimer log_rotation_timer_;
// A daily event for collecting metrics once a day.
metrics::DailyEvent daily_event_;
// A private LogUploader instance for sending reports to the server.
std::unique_ptr<LogUploaderInterface> uploader_;
// Whether new data can be recorded.
bool recording_enabled_;
// We keep all registered metrics in a map, from name to metric.
std::map<std::string, std::unique_ptr<RapporMetric>> metrics_map_;
internal::Sampler sampler_;
base::ThreadChecker thread_checker_;
} // namespace rappor