// Copyright 2015 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/dom/performance.h"

#include <string>

#include "base/time/default_clock.h"
#include "base/time/time.h"
#include "cobalt/browser/stack_size_constants.h"
#include "cobalt/dom/memory_info.h"
#include "cobalt/dom/performance_entry.h"
#include "cobalt/dom/performance_mark.h"
#include "cobalt/dom/performance_measure.h"
#include "cobalt/web/dom_exception.h"

namespace cobalt {
namespace dom {

namespace {

base::TimeDelta GetUnixAtZeroMonotonic(const base::Clock* clock,
                                       const base::TickClock* tick_clock) {
  base::TimeDelta unix_time_now = clock->Now() - base::Time::UnixEpoch();
  base::TimeDelta time_since_origin = tick_clock->NowTicks().since_origin();
  return unix_time_now - time_since_origin;
}

bool IsNamePerformanceTimingAttribute(const std::string& name) {
  return name == "navigationStart";
}

DOMHighResTimeStamp ConvertNameToTimestamp(
    const std::string& name, script::ExceptionState* exception_state) {
  // The algorithm of ConvertNameToTimestamp() follows these steps:
  //   https://www.w3.org/TR/user-timing/#convert-a-name-to-a-timestamp
  // 1. If the global object is not a Window object, throw a SyntaxError.
  // 2. If name is navigationStart, return 0.
  if (name == "navigationStart") {
    return 0.0;
  }

  // 3. Let startTime be the value of navigationStart in the PerformanceTiming
  // interface.
  // 4. Let endTime be the value of name in the PerformanceTiming interface.
  // 5. If endTime is 0, throw an InvalidAccessError.
  // 6. Return result of subtracting startTime from endTime.

  // Note that we only support navigationStart in the PerformanceTiming
  // interface. We return 0.0 instead of the result of subtracting
  // startTime from endTime.
  web::DOMException::Raise(web::DOMException::kSyntaxErr,
                           "Cannot convert a name that is not a public "
                           "attribute of PerformanceTiming to a timestamp",
                           exception_state);
  return 0.0;
}

}  // namespace

Performance::Performance(script::EnvironmentSettings* settings,
                         const scoped_refptr<base::BasicClock>& clock)
    : web::EventTarget(settings),
      time_origin_(base::TimeTicks::Now()),
      tick_clock_(base::DefaultTickClock::GetInstance()),
      timing_(new PerformanceTiming(
          clock,
          (time_origin_ - base::TimeTicks::UnixEpoch()).InMilliseconds())),
      memory_(new MemoryInfo()),
      resource_timing_buffer_size_limit_(
          Performance::kMaxResourceTimingBufferSize),
      resource_timing_buffer_current_size_(0),
      resource_timing_buffer_full_event_pending_flag_(false),
      resource_timing_secondary_buffer_current_size_(0),
      performance_observer_task_queued_flag_(false),
      add_to_performance_entry_buffer_flag_(false) {
  unix_at_zero_monotonic_ =
      GetUnixAtZeroMonotonic(base::DefaultClock::GetInstance(), tick_clock_);
  lifecycle_timing_ = base::MakeRefCounted<PerformanceLifecycleTiming>(
      "lifecycle timing", time_origin());
  // Queue lifecycle timing.
  QueuePerformanceEntry(lifecycle_timing_);
  // Add lifecycle timing to the performance entry buffer.
  performance_entry_buffer_.push_back(lifecycle_timing_);
}

// static
DOMHighResTimeStamp Performance::MonotonicTimeToDOMHighResTimeStamp(
    base::TimeTicks time_origin, base::TimeTicks monotonic_time) {
  if (monotonic_time.is_null() || time_origin.is_null()) return 0.0;
  DOMHighResTimeStamp clamped_time =
      ClampTimeStampMinimumResolution(
          monotonic_time,
          Performance::kPerformanceTimerMinResolutionInMicroseconds) -
      ClampTimeStampMinimumResolution(
          time_origin,
          Performance::kPerformanceTimerMinResolutionInMicroseconds);

  return clamped_time;
}

DOMHighResTimeStamp Performance::MonotonicTimeToDOMHighResTimeStamp(
    base::TimeTicks monotonic_time) const {
  return Performance::MonotonicTimeToDOMHighResTimeStamp(time_origin_,
                                                         monotonic_time);
}

DOMHighResTimeStamp Performance::Now() const {
  // Now stores the current high resolution time.
  //   https://www.w3.org/TR/2019/REC-hr-time-2-20191121/#dfn-current-high-resolution-time
  return MonotonicTimeToDOMHighResTimeStamp(tick_clock_->NowTicks());
}

scoped_refptr<PerformanceTiming> Performance::timing() const { return timing_; }

scoped_refptr<MemoryInfo> Performance::memory() const { return memory_; }

DOMHighResTimeStamp Performance::time_origin() const {
  // The algorithm for calculating time origin timestamp.
  //   https://www.w3.org/TR/2019/REC-hr-time-2-20191121/#dfn-time-origin-timestamp
  // Assert that global's time origin is not undefined.
  DCHECK(!time_origin_.is_null());

  // Let t1 be the DOMHighResTimeStamp representing the high resolution
  // time at which the global monotonic clock is zero.
  base::TimeDelta t1 = unix_at_zero_monotonic_;

  // Let t2 be the DOMHighResTimeStamp representing the high resolution
  // time value of the global monotonic clock at global's time origin.
  base::TimeDelta t2 = time_origin_ - base::TimeTicks();

  // Return the sum of t1 and t2.
  return ClampTimeStampMinimumResolution(
      t1 + t2, Performance::kPerformanceTimerMinResolutionInMicroseconds);
}

void Performance::Mark(const std::string& mark_name,
                       script::ExceptionState* exception_state) {
  // The algorithm for mark() follows these steps:
  //   https://www.w3.org/TR/2019/REC-user-timing-2-20190226/#mark-method
  // 1. If the global object is a Window object and markName uses the same name
  // as a read only attribute in the PerformanceTiming interface, throw a
  // SyntaxError.
  if (IsNamePerformanceTimingAttribute(mark_name)) {
    web::DOMException::Raise(
        web::DOMException::kSyntaxErr,
        "Cannot create a mark with the same name as a read-only attribute in "
        "the PerformanceTiming interface",
        exception_state);
  }

  // 2. Create a new PerformanceMark object (entry).
  // 3. Set entry's name attribute to markName.
  // 4. Set entry's entryType attribute to DOMString "mark".
  // 5. Set entry's startTime attribute to the value that would be returned by
  // the Performance object's now() method.
  // 6. Set entry's duration attribute to 0.
  scoped_refptr<PerformanceMark> entry =
      base::MakeRefCounted<PerformanceMark>(mark_name, Now());

  // 7. Queue entry.
  QueuePerformanceEntry(entry);

  // 8. Add entry to the performance entry buffer.
  performance_entry_buffer_.push_back(entry);

  // 9. Return undefined
}

void Performance::ClearMarks(const std::string& mark_name) {
  // The algorithm for clearMarks follows these steps:
  //   https://www.w3.org/TR/2019/REC-user-timing-2-20190226/#clearmarks-method
  // 1. If markName is omitted, remove all PerformanceMark objects from the
  // performance entry buffer.
  // 2. Otherwise, remove all PerformanceMark objects listed in the performance
  // entry buffer whose name matches markName.
  PerformanceEntryList retained_performance_entry_buffer;
  for (const auto& entry : performance_entry_buffer_) {
    bool should_remove_entry =
        PerformanceEntry::ToEntryTypeEnum(entry->entry_type()) ==
            PerformanceEntry::kMark &&
        (mark_name.empty() || entry->name() == mark_name);
    if (!should_remove_entry) {
      retained_performance_entry_buffer.push_back(entry);
    }
  }
  performance_entry_buffer_.swap(retained_performance_entry_buffer);

  // 3. Return undefined.
}

void Performance::Measure(const std::string& measure_name,
                          const std::string& start_mark,
                          const std::string& end_mark,
                          script::ExceptionState* exception_state) {
  // The algorithm for measure() follows these steps:
  //   https://www.w3.org/TR/2019/REC-user-timing-2-20190226/#measure-method
  // 1. Let end time be 0.
  DOMHighResTimeStamp end_time = 0.0;

  // 2. If endMark is omitted, let end time be the value that would be returned
  // by the Performance object's now() method.
  if (end_mark.empty()) {
    end_time = Now();
  } else if (IsNamePerformanceTimingAttribute(end_mark)) {
    // 2.1. Otherwise, if endMark has the same name as a read only attribute in
    // the PerformanceTiming interface, let end time be the value returned by
    // running the convert a name to a timestamp algorithm with name set to the
    // value of endMark.
    end_time = ConvertNameToTimestamp(end_mark, exception_state);
  } else {
    // 2.2. Otherwise let end time be the value of the startTime attribute from
    // the most recent occurrence of a PerformanceMark object in the performance
    // entry buffer whose name matches the value of endMark. If no matching
    // entry is found, throw a SyntaxError.
    PerformanceEntryList list = GetEntriesByName(end_mark, "mark");
    if (list.empty()) {
      web::DOMException::Raise(
          web::DOMException::kSyntaxErr,
          "Cannot create measure; no mark found with name: " + end_mark + ".",
          exception_state);
      return;
    }
    end_time = list.at(list.size() - 1)->start_time();
  }

  DOMHighResTimeStamp start_time;
  // 3. If startMark is omitted, let start time be 0.
  if (start_mark.empty()) {
    start_time = 0.0;
  } else if (IsNamePerformanceTimingAttribute(start_mark)) {
    // 3.1. If startMark has the same name as a read only attribute in the
    // PerformanceTiming interface, let start time be the value returned by
    // running the convert a name to a timestamp algorithm with name set to
    // startMark.
    start_time = ConvertNameToTimestamp(start_mark, exception_state);
  } else {
    // 3.2. Otherwise let start time be the value of the startTime attribute
    // from the most recent occurrence of a PerformanceMark object in the
    // performance entry buffer whose name matches the value of startMark. If no
    // matching entry is found, throw a SyntaxError.
    PerformanceEntryList list = GetEntriesByName(start_mark, "mark");
    if (list.empty()) {
      web::DOMException::Raise(
          web::DOMException::kSyntaxErr,
          "Cannot create measure; no mark found with name: " + start_mark + ".",
          exception_state);
      return;
    }
    start_time = list.at(list.size() - 1)->start_time();
  }

  // 4. Create a new PerformanceMeasure object (entry).
  // 5. Set entry's name attribute to measureName.
  // 6. Set entry's entryType attribute to DOMString "measure".
  // 7. Set entry's startTime attribute to start time.
  // 8. Set entry's duration attribute to the duration from start time to end
  // time. The resulting duration value MAY be negative.
  scoped_refptr<PerformanceMeasure> entry =
      base::MakeRefCounted<PerformanceMeasure>(measure_name, start_time,
                                               end_time);

  // 9. Queue entry.
  QueuePerformanceEntry(entry);

  // 10. Add entry to the performance entry buffer.
  performance_entry_buffer_.push_back(entry);

  // 11. Return undefined.
}

void Performance::ClearMeasures(const std::string& measure_name) {
  // The algorithm for clearMeasures follows these steps:
  //   https://www.w3.org/TR/2019/REC-user-timing-2-20190226/#clearmeasures-method
  // 1. If measureName is omitted, remove all PerformanceMeasure objects in the
  // performance entry buffer.
  // 2. Otherwise remove all PerformanceMeasure objects listed in the
  // performance entry buffer whose name matches measureName.
  PerformanceEntryList performance_entry_buffer;
  for (const auto& entry : performance_entry_buffer_) {
    bool shouldRemoveEntry =
        PerformanceEntry::ToEntryTypeEnum(entry->entry_type()) ==
            PerformanceEntry::kMeasure &&
        (measure_name.empty() || entry->name() == measure_name);
    if (!shouldRemoveEntry) {
      performance_entry_buffer.push_back(entry);
    }
  }
  performance_entry_buffer_.swap(performance_entry_buffer);

  // 3. Return undefined.
}

void Performance::UnregisterPerformanceObserver(
    const scoped_refptr<PerformanceObserver>& old_observer) {
  auto iter = registered_performance_observers_.begin();
  while (iter != registered_performance_observers_.end()) {
    if (iter->observer == old_observer) {
      iter = registered_performance_observers_.erase(iter);
    } else {
      ++iter;
    }
  }
}

void Performance::RegisterPerformanceObserver(
    const scoped_refptr<PerformanceObserver>& observer,
    const PerformanceObserverInit& options) {
  std::list<PerformanceObserverInit> options_list;
  options_list.push_back(options);
  registered_performance_observers_.emplace_back(observer, options_list);
}

void Performance::ReplaceRegisteredPerformanceObserverOptionsList(
    const scoped_refptr<PerformanceObserver>& observer,
    const PerformanceObserverInit& options) {
  auto iter = registered_performance_observers_.begin();
  while (iter != registered_performance_observers_.end()) {
    if (iter->observer == observer) {
      iter->options_list.clear();
      iter->options_list.push_back(options);
    }
    ++iter;
  }
}

void Performance::UpdateRegisteredPerformanceObserverOptionsList(
    const scoped_refptr<PerformanceObserver>& observer,
    const PerformanceObserverInit& options) {
  auto iter = registered_performance_observers_.begin();
  while (iter != registered_performance_observers_.end()) {
    if (iter->observer == observer) {
      bool is_replaced = false;
      for (auto& registered_options : iter->options_list) {
        if (registered_options.type() == options.type()) {
          registered_options = options;
          is_replaced = true;
        }
      }
      if (!is_replaced) iter->options_list.push_back(options);
    }
    ++iter;
  }
}

void Performance::TraceMembers(script::Tracer* tracer) {
  tracer->Trace(timing_);
  tracer->Trace(memory_);
  tracer->Trace(lifecycle_timing_);
}

PerformanceEntryList Performance::GetEntries() {
  return PerformanceEntryListImpl::GetEntries(performance_entry_buffer_);
}

PerformanceEntryList Performance::GetEntriesByType(
    const std::string& entry_type) {
  return PerformanceEntryListImpl::GetEntriesByType(performance_entry_buffer_,
                                                    entry_type);
}

PerformanceEntryList Performance::GetEntriesByName(
    const std::string& name, const base::StringPiece& type) {
  return PerformanceEntryListImpl::GetEntriesByName(performance_entry_buffer_,
                                                    name, type);
}

void Performance::ClearResourceTimings() {
  // The method clearResourceTimings runs the following steps:
  //   https://www.w3.org/TR/2021/WD-resource-timing-2-20210414/#dom-performance-clearresourcetimings
  // 1. Remove all PerformanceResourceTiming objects in the performance
  // entry buffer.
  PerformanceEntryList performance_entry_buffer;
  for (const auto& entry : performance_entry_buffer_) {
    bool should_be_removed =
        PerformanceEntry::ToEntryTypeEnum(entry->entry_type()) ==
        PerformanceEntry::kResource;
    if (!should_be_removed) {
      performance_entry_buffer.push_back(entry);
    }
  }
  performance_entry_buffer_.swap(performance_entry_buffer);

  // 2. Set resource timing buffer current size to 0.
  resource_timing_buffer_current_size_ = 0;
}

void Performance::SetResourceTimingBufferSize(
    unsigned long max_size) {  // NOLINT(runtime/int)
  // The method runs the following steps:
  //   https://www.w3.org/TR/2021/WD-resource-timing-2-20210414/#dom-performance-setresourcetimingbuffersize
  // 1. Set resource timing buffer size limit to the maxSize parameter.
  // If the maxSize parameter is less than resource timing buffer current
  // size, no PerformanceResourceTiming objects are to be removed from
  // the performance entry buffer.
  resource_timing_buffer_size_limit_ = max_size;
}

bool Performance::CanAddResourceTimingEntry() {
  // THe method runs the following steps:
  //   https://www.w3.org/TR/2021/WD-resource-timing-2-20210414/#dfn-can-add-resource-timing-entry
  // 1. If resource timing buffer current size is smaller than resource
  // timing buffer size limit, return true.
  // 2. Return false.
  return resource_timing_buffer_current_size_ <
         resource_timing_buffer_size_limit_;
}

void Performance::CopySecondaryBuffer() {
  //   https://www.w3.org/TR/2021/WD-resource-timing-2-20210414/#dfn-copy-secondary-buffer
  // While resource timing secondary buffer is not empty and can add
  // resource timing entry returns true, run the following substeps:
  PerformanceEntryList entry_list;
  while (!resource_timing_secondary_buffer_.empty() &&
         CanAddResourceTimingEntry()) {
    // 1. Let entry be the oldest PerformanceResourceTiming in resource timing
    // secondary buffer.
    scoped_refptr<PerformanceResourceTiming> entry =
        resource_timing_secondary_buffer_.front();
    // 2. Add entry to the end of performance entry buffer.
    DCHECK(entry);
    performance_entry_buffer_.push_back(entry);
    // 3. Increment resource timing buffer current size by 1.
    resource_timing_buffer_current_size_++;
    // 4. Remove entry from resource timing secondary buffer.
    resource_timing_secondary_buffer_.pop_front();
    // 5. Decrement resource timing secondary buffer current size by 1.
    resource_timing_secondary_buffer_current_size_--;
  }
}

void Performance::set_onresourcetimingbufferfull(
    const web::EventTarget::EventListenerScriptValue& event_listener) {
  SetAttributeEventListener(base::Tokens::resourcetimingbufferfull(),
                            event_listener);
}

const web::EventTarget::EventListenerScriptValue*
Performance::onresourcetimingbufferfull() const {
  return GetAttributeEventListener(base::Tokens::resourcetimingbufferfull());
}

void Performance::FireResourceTimingBufferFullEvent() {
  //   https://www.w3.org/TR/2021/WD-resource-timing-2-20210414/#dfn-fire-a-buffer-full-event
  // 1. While resource timing secondary buffer is not empty, run the
  // following substeps:
  while (!resource_timing_secondary_buffer_.empty()) {
    // 1.1 Let number of excess entries before be resource timing secondary
    // buffer current size.
    unsigned long excess_entries_before =  // NOLINT(runtime/int)
        resource_timing_secondary_buffer_current_size_;
    // 1.2 If can add resource timing entry returns false, then fire an event
    // named resourcetimingbufferfull at the Performance object.
    if (!CanAddResourceTimingEntry()) {
      DispatchEvent(new web::Event(base::Tokens::resourcetimingbufferfull()));
    }
    // 1.3 Run copy secondary buffer.
    CopySecondaryBuffer();
    // 1.4 Let number of excess entries after be resource timing secondary
    // buffer current size.
    unsigned long excess_entries_after =  // NOLINT(runtime/int)
        resource_timing_secondary_buffer_current_size_;
    // 1.5 If number of excess entries before is lower than or equals number of
    // excess entries after, then remove all entries from resource timing
    // secondary buffer, set resource timing secondary buffer current size to 0,
    // and abort these steps.
    if (excess_entries_before <= excess_entries_after) {
      resource_timing_secondary_buffer_.clear();
      resource_timing_secondary_buffer_current_size_ = 0;
      break;
    }
  }

  // 2. Set resource timing buffer full event pending flag to false.
  resource_timing_buffer_full_event_pending_flag_ = false;
}

void Performance::AddPerformanceResourceTimingEntry(
    const scoped_refptr<PerformanceResourceTiming>& resource_timing_entry) {
  //   https://www.w3.org/TR/2021/WD-resource-timing-2-20210414/#dfn-add-a-performanceresourcetiming-entry
  // To add a PerformanceResourceTiming entry into the performance entry buffer,
  // run the following steps:
  // 1. Let new entry be the input PerformanceEntry to be added.
  // 2. If can add resource timing entry returns true and resource timing buffer
  // full event pending flag is false, run the following substeps:
  if (CanAddResourceTimingEntry() &&
      !resource_timing_buffer_full_event_pending_flag_) {
    // 2.1 Add new entry to the performance entry buffer.
    performance_entry_buffer_.push_back(resource_timing_entry);
    // 2.2 Increase resource timing buffer current size by 1.
    resource_timing_buffer_current_size_++;
    // 2.3 Return.
    return;
  }

  // 3. If resource timing buffer full event pending flag is false, run the
  // following substeps:
  if (!resource_timing_buffer_full_event_pending_flag_) {
    // 3.1 Set resource timing buffer full event pending flag to true.
    resource_timing_buffer_full_event_pending_flag_ = true;
    // 3.2 Queue a task on the performance timeline task source to run fire
    // a buffer full event.
    FireResourceTimingBufferFullEvent();
  }
  // 4. Add new entry to the resource timing secondary buffer.
  resource_timing_secondary_buffer_.push_back(resource_timing_entry);
  // 5. Increase resource timing secondary buffer current size by 1.
  resource_timing_secondary_buffer_current_size_++;
  DCHECK_EQ(resource_timing_secondary_buffer_current_size_,
            resource_timing_secondary_buffer_.size());
}

void Performance::QueuePerformanceEntry(
    const scoped_refptr<PerformanceEntry>& entry) {
  // To queue a PerformanceEntry (new entry) with an optional add to
  // performance entry buffer flag, which is unset by default, run these steps:
  //   https://www.w3.org/TR/2019/WD-performance-timeline-2-20191024/#queue-a-performanceentry
  // 1. Let interested observers be an initially empty set of
  // PerformanceObserver objects.
  std::list<scoped_refptr<PerformanceObserver>> interested_observers;
  // 2. Let entryType be new entry’s entryType value.
  const std::string entry_type = entry->entry_type();
  // 3. For each registered performance observer (regObs):
  for (const auto& reg_obs : registered_performance_observers_) {
    // 3.1 If regObs's options list contains a PerformanceObserverInit item
    // whose entryTypes member include entryType or whose type member equals to
    // entryType, append regObs's observer to interested observers.
    for (const auto& item : reg_obs.options_list) {
      if (item.has_type() && item.type() == entry_type) {
        interested_observers.push_back(reg_obs.observer);
      }
      if (item.has_entry_types()) {
        for (const auto& type : item.entry_types()) {
          if (type == entry_type) {
            interested_observers.push_back(reg_obs.observer);
          }
        }
      }
    }
  }
  // 4. For each observer in interested observers:
  for (const auto& observer : interested_observers) {
    // 4.1 Append new entry to observer's observer buffer.
    observer->EnqueuePerformanceEntry(entry);
  }
  // 5. If the add to performance entry buffer flag is set, add new entry to the
  // performance entry buffer.
  if (add_to_performance_entry_buffer_flag_) {
    performance_entry_buffer_.push_back(entry);
  }
  // 6. If the performance observer task queued flag is set, terminate these
  // steps.
  if (performance_observer_task_queued_flag_) return;
  // 7. Set performance observer task queued flag.
  performance_observer_task_queued_flag_ = true;
  // 8. Queue a task that consists of running the following substeps.
  // The task source for the queued task is the performance timeline task
  // source.
  QueuePerformanceTimelineTask();
}

void Performance::QueuePerformanceTimelineTask() {
  // 8.1 Unset performance observer task queued flag for the relevant global
  // object.
  performance_observer_task_queued_flag_ = false;
  // 8.2 Let notify list be a copy of relevant global object's list of
  // registered performance observer objects.
  RegisteredPerformanceObserverList notify_list =
      registered_performance_observers_;
  // 8.3 For each PerformanceObserver object po in notify list, run these steps:
  for (const auto& reg_obs : notify_list) {
    // 8.3.1 Let entries be a copy of po’s observer buffer.
    scoped_refptr<PerformanceObserver> po = reg_obs.observer;
    PerformanceEntryList entries = po->GetObserverBuffer();
    // 8.3.2 Empty po’s observer buffer.
    po->EmptyObserverBuffer();
    // If entries is non-empty, call po’s callback with entries as first
    // argument and po as the second argument and callback this value. If this
    // throws an exception, report the exception.
    if (!entries.empty()) {
      scoped_refptr<PerformanceObserverEntryList> observer_entry_list(
          new PerformanceObserverEntryList(entries));
      po->GetPerformanceObserverCallback()->RunCallback(observer_entry_list,
                                                        po);
    }
  }
}

void Performance::CreatePerformanceResourceTiming(
    const net::LoadTimingInfo& timing_info, const std::string& initiator_type,
    const std::string& requested_url) {
  // To mark resource timing given a fetch timing info timingInfo, a DOMString
  // requestedURL, a DOMString initiatorType a global object global, and a
  // string cacheMode, perform the following steps:
  //   https://www.w3.org/TR/2021/WD-resource-timing-2-20210414/#marking-resource-timing
  // 1. Create a PerformanceResourceTiming object entry in global's realm.
  // 2.Setup the resource timing entry for entry, given initiatorType,
  // requestedURL, timingInfo, and cacheMode.
  scoped_refptr<PerformanceResourceTiming> resource_timing(
      new PerformanceResourceTiming(timing_info, initiator_type, requested_url,
                                    this, time_origin_));
  // 2. Queue entry.
  QueuePerformanceEntry(resource_timing);
  // 3. Add entry to global's performance entry buffer.
  AddPerformanceResourceTimingEntry(resource_timing);
}

void Performance::SetApplicationState(base::ApplicationState state,
                                      SbTimeMonotonic timestamp) {
  lifecycle_timing_->SetApplicationState(state, timestamp);
}

void Performance::SetApplicationStartOrPreloadTimestamp(
    bool is_preload, SbTimeMonotonic timestamp) {
  lifecycle_timing_->SetApplicationStartOrPreloadTimestamp(is_preload,
                                                           timestamp);
}

void Performance::SetDeepLinkTimestamp(SbTimeMonotonic timestamp) {
  lifecycle_timing_->SetDeepLinkTimestamp(timestamp);
}

}  // namespace dom
}  // namespace cobalt
