// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/tracing/background_tracing_rule.h"

#include <limits>
#include <optional>
#include <string>
#include <type_traits>

#include "base/functional/bind.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/metrics_hashes.h"
#include "base/metrics/statistics_recorder.h"
#include "base/rand_util.h"
#include "base/strings/safe_sprintf.h"
#include "base/strings/strcat.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "base/trace_event/histogram_scope.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/trace_id_helper.h"
#include "base/unguessable_token.h"
#include "components/variations/hashing.h"
#include "content/browser/tracing/background_tracing_manager_impl.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "services/tracing/public/cpp/perfetto/macros.h"
#include "services/tracing/public/mojom/background_tracing_agent.mojom.h"
#include "third_party/perfetto/protos/perfetto/trace/track_event/chrome_histogram_sample.pbzero.h"

namespace content {

BackgroundTracingRule::BackgroundTracingRule() = default;

BackgroundTracingRule::~BackgroundTracingRule() {
  DCHECK(!installed());
}

void BackgroundTracingRule::Install(RuleTriggeredCallback trigger_callback) {
  DCHECK(!installed());
  installed_ = true;
  trigger_callback_ = std::move(trigger_callback);
  if (activation_delay_) {
    activation_timer_.Start(FROM_HERE, *activation_delay_,
                            base::BindOnce(&BackgroundTracingRule::DoInstall,
                                           base::Unretained(this)));
  } else {
    DoInstall();
  }
}

void BackgroundTracingRule::Uninstall() {
  if (!installed()) {
    return;
  }
  installed_ = false;
  trigger_timer_.Stop();
  activation_timer_.Stop();
  trigger_callback_.Reset();
  DoUninstall();
}

bool BackgroundTracingRule::OnRuleTriggered(std::optional<int32_t> value,
                                            uint64_t flow_id) {
  if (!installed()) {
    return false;
  }
  DCHECK(trigger_callback_);
  if (trigger_chance_ < 1.0 && base::RandDouble() > trigger_chance_) {
    return false;
  }
  triggered_value_ = value;
  flow_id_ = flow_id;
  if (delay_) {
    trigger_timer_.Start(FROM_HERE, *delay_,
                         base::BindOnce(base::IgnoreResult(trigger_callback_),
                                        base::Unretained(this)));
    return true;
  } else {
    return trigger_callback_.Run(this);
  }
}

std::string BackgroundTracingRule::GetDefaultRuleName() const {
  return "trigger";
}

perfetto::protos::gen::TriggerRule BackgroundTracingRule::ToProtoForTesting()
    const {
  perfetto::protos::gen::TriggerRule config;
  if (trigger_chance_ < 1.0) {
    config.set_trigger_chance(trigger_chance_);
  }

  if (delay_) {
    config.set_delay_ms(delay_->InMilliseconds());
  }

  config.set_name(rule_name_);

  return config;
}

void BackgroundTracingRule::GenerateMetadataProto(
    BackgroundTracingRule::MetadataProto* out) const {
  uint32_t name_hash = variations::HashName(rule_name());
  out->set_name_hash(name_hash);
}

void BackgroundTracingRule::Setup(
    const perfetto::protos::gen::TriggerRule& config) {
  if (config.has_trigger_chance()) {
    trigger_chance_ = config.trigger_chance();
  }
  if (config.has_delay_ms()) {
    delay_ = base::Milliseconds(config.delay_ms());
  }
  if (config.has_activation_delay_ms()) {
    activation_delay_ = base::Milliseconds(config.activation_delay_ms());
  }
  if (config.has_name()) {
    rule_name_ = config.name();
  } else {
    rule_name_ = base::StrCat(
        {"org.chromium.background_tracing.", GetDefaultRuleName()});
  }
}

namespace {

class NamedTriggerRule : public BackgroundTracingRule {
 private:
  explicit NamedTriggerRule(const std::string& named_event)
      : named_event_(named_event) {}

 public:
  static std::unique_ptr<BackgroundTracingRule> Create(
      const perfetto::protos::gen::TriggerRule& config) {
    if (config.has_manual_trigger_name()) {
      return base::WrapUnique<BackgroundTracingRule>(
          new NamedTriggerRule(config.manual_trigger_name()));
    }
    return nullptr;
  }

  void DoInstall() override {
    BackgroundTracingManagerImpl::GetInstance().AddNamedTriggerObserver(
        named_event_, this);
  }

  void DoUninstall() override {
    BackgroundTracingManagerImpl::GetInstance().RemoveNamedTriggerObserver(
        named_event_, this);
  }

  perfetto::protos::gen::TriggerRule ToProtoForTesting() const override {
    perfetto::protos::gen::TriggerRule config =
        BackgroundTracingRule::ToProtoForTesting();
    config.set_manual_trigger_name(named_event_);
    return config;
  }

  void GenerateMetadataProto(
      BackgroundTracingRule::MetadataProto* out) const override {
    DCHECK(out);
    BackgroundTracingRule::GenerateMetadataProto(out);
    out->set_trigger_type(MetadataProto::MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED);
  }

 protected:
  std::string GetDefaultRuleName() const override { return named_event_; }

 private:
  std::string named_event_;
};

class HistogramRule : public BackgroundTracingRule,
                      public BackgroundTracingManagerImpl::AgentObserver {
 private:
  HistogramRule(const std::string& histogram_name,
                int histogram_lower_value,
                int histogram_upper_value)
      : histogram_name_(histogram_name),
        rule_id_(base::UnguessableToken::Create().ToString()),
        histogram_lower_value_(histogram_lower_value),
        histogram_upper_value_(histogram_upper_value) {}

 public:
  static std::unique_ptr<BackgroundTracingRule> Create(
      const perfetto::protos::gen::TriggerRule& config) {
    DCHECK(config.has_histogram());

    if (!config.histogram().has_histogram_name()) {
      return nullptr;
    }
    int histogram_lower_value = 0;
    if (config.histogram().has_min_value()) {
      histogram_lower_value = config.histogram().min_value();
    }
    int histogram_upper_value = std::numeric_limits<int>::max();
    if (config.histogram().has_max_value()) {
      histogram_upper_value = config.histogram().max_value();
    }
    if (histogram_lower_value > histogram_upper_value) {
      return nullptr;
    }

    return base::WrapUnique(
        new HistogramRule(config.histogram().histogram_name(),
                          histogram_lower_value, histogram_upper_value));
  }

  ~HistogramRule() override = default;

  // BackgroundTracingRule implementation
  void DoInstall() override {
    histogram_sample_callback_.emplace(
        histogram_name_,
        base::BindRepeating(&HistogramRule::OnHistogramChangedCallback,
                            base::Unretained(this), histogram_lower_value_,
                            histogram_upper_value_));
    BackgroundTracingManagerImpl::GetInstance().AddNamedTriggerObserver(
        rule_id_, this);
    BackgroundTracingManagerImpl::GetInstance().AddAgentObserver(this);
  }

  void DoUninstall() override {
    histogram_sample_callback_.reset();
    BackgroundTracingManagerImpl::GetInstance().RemoveAgentObserver(this);
    BackgroundTracingManagerImpl::GetInstance().RemoveNamedTriggerObserver(
        rule_id_, this);
  }

  perfetto::protos::gen::TriggerRule ToProtoForTesting() const override {
    perfetto::protos::gen::TriggerRule config =
        BackgroundTracingRule::ToProtoForTesting();
    auto* histogram = config.mutable_histogram();
    histogram->set_histogram_name(histogram_name_);
    histogram->set_min_value(histogram_lower_value_);
    histogram->set_max_value(histogram_upper_value_);
    return config;
  }

  void GenerateMetadataProto(
      BackgroundTracingRule::MetadataProto* out) const override {
    DCHECK(out);
    BackgroundTracingRule::GenerateMetadataProto(out);
    out->set_trigger_type(
        MetadataProto::MONITOR_AND_DUMP_WHEN_SPECIFIC_HISTOGRAM_AND_VALUE);
    auto* rule = out->set_histogram_rule();
    rule->set_histogram_name_hash(base::HashMetricName(histogram_name_));
    rule->set_histogram_min_trigger(histogram_lower_value_);
    rule->set_histogram_max_trigger(histogram_upper_value_);
  }

  // BackgroundTracingManagerImpl::AgentObserver implementation
  void OnAgentAdded(tracing::mojom::BackgroundTracingAgent* agent) override {
    agent->SetUMACallback(tracing::mojom::BackgroundTracingRule::New(rule_id_),
                          histogram_name_, histogram_lower_value_,
                          histogram_upper_value_);
  }

  void OnAgentRemoved(tracing::mojom::BackgroundTracingAgent* agent) override {
    agent->ClearUMACallback(
        tracing::mojom::BackgroundTracingRule::New(rule_id_));
  }

  void OnHistogramChangedCallback(
      base::Histogram::Sample32 reference_lower_value,
      base::Histogram::Sample32 reference_upper_value,
      std::optional<uint64_t> event_id,
      std::string_view histogram_name,
      uint64_t name_hash,
      base::Histogram::Sample32 actual_value) {
    DCHECK_EQ(histogram_name, histogram_name_);
    if (reference_lower_value > actual_value ||
        reference_upper_value < actual_value) {
      return;
    }

    uint64_t flow_id =
        event_id.value_or(base::trace_event::GetNextGlobalTraceId());

    // Add the histogram name and its corresponding value to the trace.
    const auto trace_details = [&](perfetto::EventContext& ctx) {
      perfetto::protos::pbzero::ChromeHistogramSample* new_sample =
          ctx.event()->set_chrome_histogram_sample();
      new_sample->set_name_hash(base::HashMetricName(histogram_name));
      new_sample->set_sample(actual_value);
      perfetto::Flow::Global(flow_id)(ctx);
    };
    auto track = perfetto::NamedTrack("HistogramSamples");
    TRACE_EVENT_INSTANT("tracing.background", "HistogramSampleTrigger", track,
                        trace_details);
    OnRuleTriggered(actual_value, flow_id);
  }

 protected:
  std::string GetDefaultRuleName() const override { return histogram_name_; }

 private:
  std::string histogram_name_;
  std::string rule_id_;
  int histogram_lower_value_;
  int histogram_upper_value_;
  std::optional<base::StatisticsRecorder::ScopedHistogramSampleObserver>
      histogram_sample_callback_;
};

class TimerRule : public BackgroundTracingRule {
 private:
  explicit TimerRule() = default;

 public:
  static std::unique_ptr<BackgroundTracingRule> Create(
      const perfetto::protos::gen::TriggerRule& config) {
    return base::WrapUnique<TimerRule>(new TimerRule());
  }

  void DoInstall() override {
    OnRuleTriggered(std::nullopt, base::trace_event::GetNextGlobalTraceId());
  }
  void DoUninstall() override {}

  void GenerateMetadataProto(
      BackgroundTracingRule::MetadataProto* out) const override {
    DCHECK(out);
    BackgroundTracingRule::GenerateMetadataProto(out);
    out->set_trigger_type(MetadataProto::TRIGGER_UNSPECIFIED);
  }

 protected:
  std::string GetDefaultRuleName() const override { return "timer"; }
};

class RepeatingIntervalRule : public BackgroundTracingRule {
 private:
  RepeatingIntervalRule(base::TimeDelta period, bool randomized)
      : period_(period),
        randomized_(randomized),
        interval_phase_(base::TimeTicks::Now()) {}

 public:
  static std::unique_ptr<BackgroundTracingRule> Create(
      const perfetto::protos::gen::TriggerRule& config) {
    DCHECK(config.has_repeating_interval());

    const auto& interval = config.repeating_interval();
    if (!interval.has_period_ms()) {
      return nullptr;
    }
    return base::WrapUnique<RepeatingIntervalRule>(new RepeatingIntervalRule(
        base::Milliseconds(interval.period_ms()), interval.randomized()));
  }

  void DoInstall() override { ScheduleNextTick(); }
  void DoUninstall() override { timer_.Stop(); }

  perfetto::protos::gen::TriggerRule ToProtoForTesting() const override {
    perfetto::protos::gen::TriggerRule config =
        BackgroundTracingRule::ToProtoForTesting();
    auto* histogram = config.mutable_repeating_interval();
    histogram->set_period_ms(period_.InMilliseconds());
    histogram->set_randomized(randomized_);
    return config;
  }

  void GenerateMetadataProto(
      BackgroundTracingRule::MetadataProto* out) const override {
    DCHECK(out);
    BackgroundTracingRule::GenerateMetadataProto(out);
    out->set_trigger_type(MetadataProto::TRIGGER_UNSPECIFIED);
  }

 protected:
  std::string GetDefaultRuleName() const override {
    return "repeating_interval";
  }

 private:
  base::TimeTicks GetFireTimeForInterval(base::TimeTicks interval_start) const {
    if (randomized_) {
      return interval_start +
             base::Microseconds(base::RandGenerator(period_.InMicroseconds()));
    }
    return interval_start;
  }
  base::TimeTicks GetNextIntervalStart(base::TimeTicks now) const {
    base::TimeTicks next_interval_start =
        now.SnappedToNextTick(interval_phase_, period_);
    if (next_interval_start == now) {
      return next_interval_start + period_;
    }
    return next_interval_start;
  }
  void UpdateNextFireTime(base::TimeTicks now) {
    base::TimeTicks next_interval_start = GetNextIntervalStart(now);
    base::TimeTicks prev_interval_start = next_interval_start - period_;
    // If the previously scheduled fire time is in a past interval, the current
    // interval can still fire. Compute a new fire time for the current
    // interval and keep it if it hasn't passed, otherwise move on to the next
    // interval.
    if (randomized_ && (scheduled_fire_time_ < prev_interval_start)) {
      scheduled_fire_time_ = GetFireTimeForInterval(prev_interval_start);
      if (scheduled_fire_time_ >= now) {
        return;
      }
    }
    scheduled_fire_time_ = GetFireTimeForInterval(next_interval_start);
  }

  void ScheduleNextTick() {
    base::TimeTicks now = base::TimeTicks::Now();
    // Update the next fire time only if it's in the past.
    if (scheduled_fire_time_ <= now) {
      UpdateNextFireTime(now);
    }

    timer_.Start(
        FROM_HERE, scheduled_fire_time_,
        base::BindOnce(&RepeatingIntervalRule::OnTick, base::Unretained(this)),
        base::subtle::DelayPolicy::kFlexibleNoSooner);
  }

  void OnTick() {
    OnRuleTriggered(std::nullopt, base::trace_event::GetNextGlobalTraceId());
    ScheduleNextTick();
  }

  const base::TimeDelta period_;
  const bool randomized_;
  const base::TimeTicks interval_phase_;
  base::TimeTicks scheduled_fire_time_;
  base::DeadlineTimer timer_;
};

}  // namespace

std::unique_ptr<BackgroundTracingRule> BackgroundTracingRule::Create(
    const perfetto::protos::gen::TriggerRule& config) {
  std::unique_ptr<BackgroundTracingRule> tracing_rule;
  if (config.has_manual_trigger_name()) {
    tracing_rule = NamedTriggerRule::Create(config);
  } else if (config.has_histogram()) {
    tracing_rule = HistogramRule::Create(config);
  } else if (config.has_repeating_interval()) {
    tracing_rule = RepeatingIntervalRule::Create(config);
  } else if (config.has_delay_ms()) {
    tracing_rule = TimerRule::Create(config);
  } else {
    return nullptr;
  }
  if (tracing_rule) {
    tracing_rule->Setup(config);
  }
  return tracing_rule;
}

bool BackgroundTracingRule::Append(
    const std::vector<perfetto::protos::gen::TriggerRule>& configs,
    std::vector<std::unique_ptr<BackgroundTracingRule>>& rules) {
  for (const auto& rule_config : configs) {
    auto rule = BackgroundTracingRule::Create(rule_config);
    if (!rule) {
      return false;
    }
    rules.push_back(std::move(rule));
  }
  return true;
}

}  // namespace content
