// Copyright 2018 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 "third_party/blink/renderer/core/frame/local_frame_ukm_aggregator.h"

#include "base/format_macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/rand_util.h"
#include "base/time/default_tick_clock.h"
#include "cc/metrics/begin_main_frame_metrics.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "third_party/blink/public/common/metrics/document_update_reason.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"

namespace blink {

LocalFrameUkmAggregator::ScopedUkmHierarchicalTimer::ScopedUkmHierarchicalTimer(
    scoped_refptr<LocalFrameUkmAggregator> aggregator,
    size_t metric_index,
    const base::TickClock* clock)
    : aggregator_(aggregator),
      metric_index_(metric_index),
      clock_(clock),
      start_time_(clock_->NowTicks()) {}

LocalFrameUkmAggregator::ScopedUkmHierarchicalTimer::ScopedUkmHierarchicalTimer(
    ScopedUkmHierarchicalTimer&& other)
    : aggregator_(other.aggregator_),
      metric_index_(other.metric_index_),
      clock_(other.clock_),
      start_time_(other.start_time_) {
  other.aggregator_ = nullptr;
}

LocalFrameUkmAggregator::ScopedUkmHierarchicalTimer::
    ~ScopedUkmHierarchicalTimer() {
  if (aggregator_ && base::TimeTicks::IsHighResolution()) {
    aggregator_->RecordSample(metric_index_, start_time_, clock_->NowTicks());
  }
}

void LocalFrameUkmAggregator::AbsoluteMetricRecord::reset() {
  interval_duration = base::TimeDelta();
  main_frame_duration = base::TimeDelta();
}

LocalFrameUkmAggregator::LocalFrameUkmAggregator(int64_t source_id,
                                                 ukm::UkmRecorder* recorder)
    : source_id_(source_id),
      recorder_(recorder),
      clock_(base::DefaultTickClock::GetInstance()),
      event_name_("Blink.UpdateTime") {
  // All of these are assumed to have one entry per sub-metric.
  DCHECK_EQ(base::size(absolute_metric_records_), metrics_data().size());
  DCHECK_EQ(base::size(current_sample_.sub_metrics_durations),
            metrics_data().size());
  DCHECK_EQ(base::size(current_sample_.sub_main_frame_durations),
            metrics_data().size());

  // Record average and worst case for the primary metric.
  primary_metric_.reset();

  // Define the UMA for the primary metric.
  primary_metric_.pre_fcp_uma_counter.reset(new CustomCountHistogram(
      "Blink.MainFrame.UpdateTime.PreFCP", 0, 10000000, 50));
  primary_metric_.post_fcp_uma_counter.reset(new CustomCountHistogram(
      "Blink.MainFrame.UpdateTime.PostFCP", 0, 10000000, 50));
  primary_metric_.uma_aggregate_counter.reset(new CustomCountHistogram(
      "Blink.MainFrame.UpdateTime.AggregatedPreFCP", 0, 10000000, 50));

  // Set up the substrings to create the UMA names
  const char* const uma_preamble = "Blink.";
  const char* const uma_postscript = ".UpdateTime";
  const char* const uma_prefcp_postscript = ".PreFCP";
  const char* const uma_postfcp_postscript = ".PostFCP";
  const char* const uma_pre_fcp_aggregated_postscript = ".AggregatedPreFCP";

  // Populate all the sub-metrics.
  size_t metric_index = 0;
  for (const MetricInitializationData& metric_data : metrics_data()) {
    // Absolute records report the absolute time for each metric per frame.
    // They also aggregate the time spent in each stage between navigation
    // (LocalFrameView resets) and First Contentful Paint.
    // They have an associated UMA too that we own and allocate here.
    auto& absolute_record = absolute_metric_records_[metric_index];
    absolute_record.reset();
    absolute_record.pre_fcp_aggregate = base::TimeDelta();
    if (metric_data.has_uma) {
      StringBuilder uma_name;
      uma_name.Append(uma_preamble);
      uma_name.Append(metric_data.name);
      uma_name.Append(uma_postscript);
      StringBuilder pre_fcp_uma_name;
      pre_fcp_uma_name.Append(uma_name);
      pre_fcp_uma_name.Append(uma_prefcp_postscript);
      absolute_record.pre_fcp_uma_counter.reset(new CustomCountHistogram(
          pre_fcp_uma_name.ToString().Utf8().c_str(), 0, 10000000, 50));
      StringBuilder post_fcp_uma_name;
      post_fcp_uma_name.Append(uma_name);
      post_fcp_uma_name.Append(uma_postfcp_postscript);
      absolute_record.post_fcp_uma_counter.reset(new CustomCountHistogram(
          post_fcp_uma_name.ToString().Utf8().c_str(), 0, 10000000, 50));
      StringBuilder aggregated_uma_name;
      aggregated_uma_name.Append(uma_name);
      aggregated_uma_name.Append(uma_pre_fcp_aggregated_postscript);
      absolute_record.uma_aggregate_counter.reset(new CustomCountHistogram(
          aggregated_uma_name.ToString().Utf8().c_str(), 0, 10000000, 50));
    }

    metric_index++;
  }
}

LocalFrameUkmAggregator::~LocalFrameUkmAggregator() {
  ReportUpdateTimeEvent();
}

LocalFrameUkmAggregator::ScopedUkmHierarchicalTimer
LocalFrameUkmAggregator::GetScopedTimer(size_t metric_index) {
  return ScopedUkmHierarchicalTimer(this, metric_index, clock_);
}

void LocalFrameUkmAggregator::BeginMainFrame() {
  DCHECK(!in_main_frame_update_);
  in_main_frame_update_ = true;
}

std::unique_ptr<cc::BeginMainFrameMetrics>
LocalFrameUkmAggregator::GetBeginMainFrameMetrics() {
  DCHECK(InMainFrameUpdate());

  // Use the main_frame_percentage_records_ because they are the ones that
  // only count time between the Begin and End of a main frame update.
  // Do not report hit testing because it is a sub-portion of the other
  // metrics and would result in double counting.
  std::unique_ptr<cc::BeginMainFrameMetrics> metrics_data =
      std::make_unique<cc::BeginMainFrameMetrics>();
  metrics_data->handle_input_events =
      absolute_metric_records_[static_cast<unsigned>(
                                   MetricId::kHandleInputEvents)]
          .main_frame_duration;
  metrics_data->animate =
      absolute_metric_records_[static_cast<unsigned>(MetricId::kAnimate)]
          .main_frame_duration;
  metrics_data->style_update =
      absolute_metric_records_[static_cast<unsigned>(MetricId::kStyle)]
          .main_frame_duration;
  metrics_data->layout_update =
      absolute_metric_records_[static_cast<unsigned>(MetricId::kLayout)]
          .main_frame_duration;
  metrics_data->prepaint =
      absolute_metric_records_[static_cast<unsigned>(MetricId::kPrePaint)]
          .main_frame_duration;
  metrics_data->compositing_assignments =
      absolute_metric_records_[static_cast<unsigned>(
                                   MetricId::kCompositingAssignments)]
          .main_frame_duration;
  metrics_data->compositing_inputs =
      absolute_metric_records_[static_cast<unsigned>(
                                   MetricId::kCompositingInputs)]
          .main_frame_duration;
  metrics_data->paint =
      absolute_metric_records_[static_cast<unsigned>(MetricId::kPaint)]
          .main_frame_duration;
  metrics_data->composite_commit =
      absolute_metric_records_[static_cast<unsigned>(
                                   MetricId::kCompositingCommit)]
          .main_frame_duration;
  metrics_data->should_measure_smoothness =
      (fcp_state_ >= kThisFrameReachedFCP);
  return metrics_data;
}

void LocalFrameUkmAggregator::SetTickClockForTesting(
    const base::TickClock* clock) {
  clock_ = clock;
}

void LocalFrameUkmAggregator::DidReachFirstContentfulPaint(
    bool are_painting_main_frame) {
  DCHECK(fcp_state_ != kHavePassedFCP);

  if (!are_painting_main_frame) {
    DCHECK(AllMetricsAreZero());
    return;
  }

  fcp_state_ = kThisFrameReachedFCP;
}

void LocalFrameUkmAggregator::RecordSample(size_t metric_index,
                                           base::TimeTicks start,
                                           base::TimeTicks end) {
  // Always use RecordForcedLayoutSample for the kForcedStyleAndLayout
  // metric id.
  DCHECK_NE(metric_index, static_cast<size_t>(kForcedStyleAndLayout));

  base::TimeDelta duration = end - start;
  bool is_pre_fcp = (fcp_state_ != kHavePassedFCP);

  // Accumulate for UKM and record the UMA
  DCHECK_LT(metric_index, base::size(absolute_metric_records_));
  auto& record = absolute_metric_records_[metric_index];
  record.interval_duration += duration;
  if (in_main_frame_update_)
    record.main_frame_duration += duration;
  if (is_pre_fcp)
    record.pre_fcp_aggregate += duration;
  // Record the UMA
  // ForcedStyleAndLayout happen so frequently on some pages that we overflow
  // the signed 32 counter for number of events in a 30 minute period. So
  // randomly record with probability 1/100.
  if (record.pre_fcp_uma_counter) {
    if (is_pre_fcp) {
      record.pre_fcp_uma_counter->CountMicroseconds(duration);
    } else {
      record.post_fcp_uma_counter->CountMicroseconds(duration);
    }
  }
}

void LocalFrameUkmAggregator::RecordForcedLayoutSample(
    DocumentUpdateReason reason,
    base::TimeTicks start,
    base::TimeTicks end) {
  base::TimeDelta duration = end - start;
  bool is_pre_fcp = (fcp_state_ != kHavePassedFCP);

  // Accumulate for UKM always, but only record the UMA for a subset of cases to
  // avoid overflowing the counters.
  bool should_report_uma_this_frame = !calls_to_next_forced_style_layout_uma_;
  if (should_report_uma_this_frame) {
    calls_to_next_forced_style_layout_uma_ =
        base::RandInt(0, mean_calls_between_forced_style_layout_uma_ * 2);
  } else {
    DCHECK_GT(calls_to_next_forced_style_layout_uma_, 0u);
    --calls_to_next_forced_style_layout_uma_;
  }

  auto& record =
      absolute_metric_records_[static_cast<size_t>(kForcedStyleAndLayout)];
  record.interval_duration += duration;
  if (in_main_frame_update_)
    record.main_frame_duration += duration;
  if (is_pre_fcp)
    record.pre_fcp_aggregate += duration;

  if (should_report_uma_this_frame) {
    if (is_pre_fcp)
      record.pre_fcp_uma_counter->CountMicroseconds(duration);
    else
      record.post_fcp_uma_counter->CountMicroseconds(duration);
  }

  // Record a variety of DocumentUpdateReasons as distinct metrics
  // Figure out which sub-metric, if any, we wish to report for UKM.
  MetricId sub_metric = kCount;
  switch (reason) {
    case DocumentUpdateReason::kContextMenu:
    case DocumentUpdateReason::kDragImage:
    case DocumentUpdateReason::kEditing:
    case DocumentUpdateReason::kFindInPage:
    case DocumentUpdateReason::kFocus:
    case DocumentUpdateReason::kForm:
    case DocumentUpdateReason::kInput:
    case DocumentUpdateReason::kInspector:
    case DocumentUpdateReason::kPrinting:
    case DocumentUpdateReason::kSelection:
    case DocumentUpdateReason::kSpatialNavigation:
    case DocumentUpdateReason::kTapHighlight:
      sub_metric = kUserDrivenDocumentUpdate;
      break;

    case DocumentUpdateReason::kAccessibility:
    case DocumentUpdateReason::kBaseColor:
    case DocumentUpdateReason::kDisplayLock:
    case DocumentUpdateReason::kIntersectionObservation:
    case DocumentUpdateReason::kOverlay:
    case DocumentUpdateReason::kPagePopup:
    case DocumentUpdateReason::kSizeChange:
    case DocumentUpdateReason::kSpellCheck:
      sub_metric = kServiceDocumentUpdate;
      break;

    case DocumentUpdateReason::kCanvas:
    case DocumentUpdateReason::kPlugin:
    case DocumentUpdateReason::kSVGImage:
      sub_metric = kContentDocumentUpdate;
      break;

    case DocumentUpdateReason::kScroll:
      sub_metric = kScrollDocumentUpdate;
      break;

    case DocumentUpdateReason::kHitTest:
      sub_metric = kHitTestDocumentUpdate;
      break;

    case DocumentUpdateReason::kJavaScript:
      sub_metric = kJavascriptDocumentUpdate;
      break;

    // Do not report main frame because we have it already from
    // in_main_frame_update_ above.
    case DocumentUpdateReason::kBeginMainFrame:
    // No metrics from testing.
    case DocumentUpdateReason::kTest:
    // Don't report if we don't know why.
    case DocumentUpdateReason::kUnknown:
      break;
  }

  if (sub_metric != kCount) {
    auto& sub_record =
        absolute_metric_records_[static_cast<size_t>(sub_metric)];
    sub_record.interval_duration += duration;
    if (in_main_frame_update_)
      sub_record.main_frame_duration += duration;
    if (is_pre_fcp)
      sub_record.pre_fcp_aggregate += duration;
    if (should_report_uma_this_frame) {
      if (is_pre_fcp)
        sub_record.pre_fcp_uma_counter->CountMicroseconds(duration);
      else
        sub_record.post_fcp_uma_counter->CountMicroseconds(duration);
    }
  }
}

void LocalFrameUkmAggregator::RecordImplCompositorSample(
    base::TimeTicks requested,
    base::TimeTicks started,
    base::TimeTicks completed) {
  // Record the time spent waiting for the commit based on requested
  // (which came from ProxyImpl::BeginMainFrame) and started as reported by
  // the impl thread. If started is zero, no time was spent
  // processing. This can only happen if the commit was aborted because there
  // was no change and we did not wait for the impl thread at all. Attribute
  // all time to the compositor commit so as to not imply that wait time was
  // consumed.
  if (started == base::TimeTicks()) {
    RecordSample(kImplCompositorCommit, requested, completed);
  } else {
    RecordSample(kWaitForCommit, requested, started);
    RecordSample(kImplCompositorCommit, started, completed);
  }
}

void LocalFrameUkmAggregator::RecordEndOfFrameMetrics(
    base::TimeTicks start,
    base::TimeTicks end,
    cc::ActiveFrameSequenceTrackers trackers) {
  const base::TimeDelta duration = end - start;
  const bool have_valid_metrics =
      // Any of the early outs in LocalFrameView::UpdateLifecyclePhases() will
      // mean we are not in a main frame update. Recording is triggered higher
      // in the stack, so we cannot know to avoid calling this method.
      in_main_frame_update_ &&
      // In tests it's possible to reach here with zero duration.
      (duration > base::TimeDelta());

  in_main_frame_update_ = false;
  if (!have_valid_metrics) {
    // Reset for the next frame to start the next recording period with
    // clear counters, even when we did not record anything this frame.
    ResetAllMetrics();
    return;
  }

  bool report_as_pre_fcp = (fcp_state_ != kHavePassedFCP);
  bool report_fcp_metrics = (fcp_state_ == kThisFrameReachedFCP);

  // Record UMA
  if (report_as_pre_fcp)
    primary_metric_.pre_fcp_uma_counter->CountMicroseconds(duration);
  else
    primary_metric_.post_fcp_uma_counter->CountMicroseconds(duration);

  // Record primary time information
  primary_metric_.interval_duration = duration;
  if (report_as_pre_fcp)
    primary_metric_.pre_fcp_aggregate += duration;

  UpdateEventTimeAndUpdateSampleIfNeeded(trackers);

  // Report the FCP metrics, if necessary, after updating the sample so that
  // the sample has been recorded for the frame that produced FCP.
  if (report_fcp_metrics) {
    ReportPreFCPEvent();
    ReportUpdateTimeEvent();
    // Update the state to prevent future reporting.
    fcp_state_ = kHavePassedFCP;
  }

  // Reset for the next frame.
  ResetAllMetrics();
}

void LocalFrameUkmAggregator::UpdateEventTimeAndUpdateSampleIfNeeded(
    cc::ActiveFrameSequenceTrackers trackers) {
  // Update the frame count first, because it must include this frame
  frames_since_last_report_++;

  // Regardless of test requests, always capture the first frame.
  if (frames_since_last_report_ == 1) {
    UpdateSample(trackers);
    return;
  }

  // Exit if in testing and we do not want to update this frame
  if (next_frame_sample_control_for_test_ == kMustNotChooseNextFrame)
    return;

  // Update the sample with probability 1/frames_since_last_report_, or if
  // testing demand is.
  if ((next_frame_sample_control_for_test_ == kMustChooseNextFrame) ||
      base::RandDouble() < 1 / static_cast<double>(frames_since_last_report_)) {
    UpdateSample(trackers);
  }
}

void LocalFrameUkmAggregator::UpdateSample(
    cc::ActiveFrameSequenceTrackers trackers) {
  current_sample_.primary_metric_duration = primary_metric_.interval_duration;
  for (size_t i = 0; i < metrics_data().size(); ++i) {
    current_sample_.sub_metrics_durations[i] =
        absolute_metric_records_[i].interval_duration;
    current_sample_.sub_main_frame_durations[i] =
        absolute_metric_records_[i].main_frame_duration;
  }
  current_sample_.trackers = trackers;
}

void LocalFrameUkmAggregator::ReportPreFCPEvent() {
#define CASE_FOR_ID(name)                                                  \
  case k##name:                                                            \
    builder.Set##name(absolute_record.pre_fcp_aggregate.InMicroseconds()); \
    break

  ukm::builders::Blink_PageLoad builder(source_id_);
  builder.SetMainFrame(primary_metric_.pre_fcp_aggregate.InMicroseconds());
  primary_metric_.uma_aggregate_counter->CountMicroseconds(
      primary_metric_.pre_fcp_aggregate);
  for (size_t i = 0; i < metrics_data().size(); ++i) {
    auto& absolute_record = absolute_metric_records_[i];
    if (absolute_record.uma_aggregate_counter) {
      absolute_record.uma_aggregate_counter->CountMicroseconds(
          absolute_record.pre_fcp_aggregate);
    }

    switch (static_cast<MetricId>(i)) {
      CASE_FOR_ID(CompositingAssignments);
      CASE_FOR_ID(CompositingCommit);
      CASE_FOR_ID(CompositingInputs);
      CASE_FOR_ID(ImplCompositorCommit);
      CASE_FOR_ID(IntersectionObservation);
      CASE_FOR_ID(Paint);
      CASE_FOR_ID(PrePaint);
      CASE_FOR_ID(Style);
      CASE_FOR_ID(Layout);
      CASE_FOR_ID(ForcedStyleAndLayout);
      CASE_FOR_ID(HandleInputEvents);
      CASE_FOR_ID(Animate);
      CASE_FOR_ID(UpdateLayers);
      CASE_FOR_ID(WaitForCommit);
      CASE_FOR_ID(DisplayLockIntersectionObserver);
      CASE_FOR_ID(JavascriptIntersectionObserver);
      CASE_FOR_ID(LazyLoadIntersectionObserver);
      CASE_FOR_ID(MediaIntersectionObserver);
      CASE_FOR_ID(UpdateViewportIntersection);
      CASE_FOR_ID(UserDrivenDocumentUpdate);
      CASE_FOR_ID(ServiceDocumentUpdate);
      CASE_FOR_ID(ContentDocumentUpdate);
      CASE_FOR_ID(ScrollDocumentUpdate);
      CASE_FOR_ID(HitTestDocumentUpdate);
      CASE_FOR_ID(JavascriptDocumentUpdate);
      case kCount:
      case kMainFrame:
        NOTREACHED();
        break;
    }
  }
  builder.Record(recorder_);
#undef CASE_FOR_ID
}

void LocalFrameUkmAggregator::ReportUpdateTimeEvent() {
  // Don't report if we haven't generated any samples.
  if (!frames_since_last_report_)
    return;

#define CASE_FOR_ID(name, index)                                               \
  case k##name:                                                                \
    builder                                                                    \
        .Set##name(                                                            \
            current_sample_.sub_metrics_durations[index].InMicroseconds())     \
        .Set##name##BeginMainFrame(                                            \
            current_sample_.sub_main_frame_durations[index].InMicroseconds()); \
    break

  ukm::builders::Blink_UpdateTime builder(source_id_);
  builder.SetMainFrame(
      current_sample_.primary_metric_duration.InMicroseconds());
  builder.SetMainFrameIsBeforeFCP(fcp_state_ != kHavePassedFCP);
  builder.SetMainFrameReasons(current_sample_.trackers);
  for (size_t i = 0; i < metrics_data().size(); ++i) {
    switch (static_cast<MetricId>(i)) {
      CASE_FOR_ID(CompositingAssignments, i);
      CASE_FOR_ID(CompositingCommit, i);
      CASE_FOR_ID(CompositingInputs, i);
      CASE_FOR_ID(ImplCompositorCommit, i);
      CASE_FOR_ID(IntersectionObservation, i);
      CASE_FOR_ID(Paint, i);
      CASE_FOR_ID(PrePaint, i);
      CASE_FOR_ID(Style, i);
      CASE_FOR_ID(Layout, i);
      CASE_FOR_ID(ForcedStyleAndLayout, i);
      CASE_FOR_ID(HandleInputEvents, i);
      CASE_FOR_ID(Animate, i);
      CASE_FOR_ID(UpdateLayers, i);
      CASE_FOR_ID(WaitForCommit, i);
      CASE_FOR_ID(DisplayLockIntersectionObserver, i);
      CASE_FOR_ID(JavascriptIntersectionObserver, i);
      CASE_FOR_ID(LazyLoadIntersectionObserver, i);
      CASE_FOR_ID(MediaIntersectionObserver, i);
      CASE_FOR_ID(UpdateViewportIntersection, i);
      CASE_FOR_ID(UserDrivenDocumentUpdate, i);
      CASE_FOR_ID(ServiceDocumentUpdate, i);
      CASE_FOR_ID(ContentDocumentUpdate, i);
      CASE_FOR_ID(ScrollDocumentUpdate, i);
      CASE_FOR_ID(HitTestDocumentUpdate, i);
      CASE_FOR_ID(JavascriptDocumentUpdate, i);
      case kCount:
      case kMainFrame:
        NOTREACHED();
        break;
    }
  }
  builder.Record(recorder_);
#undef CASE_FOR_ID

  // Reset the frames since last report to ensure correct sampling.
  frames_since_last_report_ = 0;
}

void LocalFrameUkmAggregator::ResetAllMetrics() {
  primary_metric_.reset();
  for (auto& record : absolute_metric_records_)
    record.reset();
}

bool LocalFrameUkmAggregator::AllMetricsAreZero() {
  if (!primary_metric_.interval_duration.is_zero())
    return false;
  for (auto& record : absolute_metric_records_) {
    if (!record.interval_duration.is_zero()) {
      return false;
    }
    if (!record.main_frame_duration.is_zero()) {
      return false;
    }
  }
  return true;
}

void LocalFrameUkmAggregator::ChooseNextFrameForTest() {
  next_frame_sample_control_for_test_ = kMustChooseNextFrame;
}

void LocalFrameUkmAggregator::DoNotChooseNextFrameForTest() {
  next_frame_sample_control_for_test_ = kMustNotChooseNextFrame;
}

}  // namespace blink
