// 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/time.h"
#include "base/time/default_clock.h"
#include "cobalt/browser/stack_size_constants.h"
#include "cobalt/dom/dom_exception.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"

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.
  dom::DOMException::Raise(dom::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)
    : EventTarget(settings),
      time_origin_(base::TimeTicks::Now()),
      tick_clock_(base::DefaultTickClock::GetInstance()),
      timing_(new PerformanceTiming(clock, time_origin_)),
      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)) {
    dom::DOMException::Raise(
        dom::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()) {
      dom::DOMException::Raise(
          dom::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()) {
      dom::DOMException::Raise(
          dom::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 EventTarget::EventListenerScriptValue& event_listener) {
  SetAttributeEventListener(base::Tokens::resourcetimingbufferfull(),
                            event_listener);
}

const 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 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
