chromium/third_party/blink/renderer/core/timing/performance.cc

/*
 * Copyright (C) 2010 Google Inc. All rights reserved.
 * Copyright (C) 2012 Intel Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "third_party/blink/renderer/core/timing/performance.h"

#include <algorithm>
#include <optional>

#include "base/containers/contains.h"
#include "base/metrics/histogram_macros.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/default_clock.h"
#include "base/time/default_tick_clock.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "third_party/blink/public/mojom/permissions_policy/document_policy_feature.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_performance_mark_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_performance_measure_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_profiler_init_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_double_string.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_performancemeasureoptions_string.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/document_timing.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/event_target_names.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/loader/document_load_timing.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/timing/back_forward_cache_restoration.h"
#include "third_party/blink/renderer/core/timing/background_tracing_helper.h"
#include "third_party/blink/renderer/core/timing/dom_window_performance.h"
#include "third_party/blink/renderer/core/timing/largest_contentful_paint.h"
#include "third_party/blink/renderer/core/timing/layout_shift.h"
#include "third_party/blink/renderer/core/timing/measure_memory/measure_memory_controller.h"
#include "third_party/blink/renderer/core/timing/performance_element_timing.h"
#include "third_party/blink/renderer/core/timing/performance_entry.h"
#include "third_party/blink/renderer/core/timing/performance_event_timing.h"
#include "third_party/blink/renderer/core/timing/performance_long_task_timing.h"
#include "third_party/blink/renderer/core/timing/performance_mark.h"
#include "third_party/blink/renderer/core/timing/performance_measure.h"
#include "third_party/blink/renderer/core/timing/performance_observer.h"
#include "third_party/blink/renderer/core/timing/performance_resource_timing.h"
#include "third_party/blink/renderer/core/timing/performance_server_timing.h"
#include "third_party/blink/renderer/core/timing/performance_user_timing.h"
#include "third_party/blink/renderer/core/timing/profiler.h"
#include "third_party/blink/renderer/core/timing/profiler_group.h"
#include "third_party/blink/renderer/core/timing/soft_navigation_entry.h"
#include "third_party/blink/renderer/core/timing/time_clamper.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_timing.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_timing_utils.h"
#include "third_party/blink/renderer/platform/network/http_parsers.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "v8/include/v8-metrics.h"

namespace blink {

namespace {

// LongTask API can be a source of many events. Filter on Performance object
// level before reporting to UKM to smooth out recorded events over all pages.
constexpr size_t kLongTaskUkmSampleInterval =;

const char kSwapsPerInsertionHistogram[] =;

bool IsMeasureOptionsEmpty(const PerformanceMeasureOptions& options) {}

base::TimeDelta GetUnixAtZeroMonotonic(const base::Clock* clock,
                                       const base::TickClock* tick_clock) {}

void RecordLongTaskUkm(ExecutionContext* execution_context,
                       base::TimeDelta start_time,
                       base::TimeDelta duration) {}

PerformanceEntry::EntryType kDroppableEntryTypes[] =;

void SwapEntries(PerformanceEntryVector& entries,
                 int leftIndex,
                 int rightIndex) {}

inline bool CheckName(const PerformanceEntry* entry,
                      const AtomicString& maybe_name) {}

// |output_entries| either gets reassigned to or is appended to.
// Therefore, it must point to a valid PerformanceEntryVector.
void FilterEntriesTriggeredBySoftNavigationIfNeeded(
    PerformanceEntryVector& input_entries,
    PerformanceEntryVector** output_entries,
    bool include_soft_navigation_observations) {}

}  // namespace

PerformanceEntryVector MergePerformanceEntryVectors(
    const PerformanceEntryVector& first_entry_vector,
    const PerformanceEntryVector& second_entry_vector,
    const AtomicString& maybe_name) {}

PerformanceObserverVector;

constexpr size_t kDefaultResourceTimingBufferSize =;
constexpr size_t kDefaultEventTimingBufferSize =;
constexpr size_t kDefaultElementTimingBufferSize =;
constexpr size_t kDefaultLayoutShiftBufferSize =;
constexpr size_t kDefaultLargestContenfulPaintSize =;
constexpr size_t kDefaultLongTaskBufferSize =;
constexpr size_t kDefaultLongAnimationFrameBufferSize =;
constexpr size_t kDefaultBackForwardCacheRestorationBufferSize =;
constexpr size_t kDefaultSoftNavigationBufferSize =;
// Paint timing entries is more than twice as much as the soft navigation buffer
// size, as there can be 2 paint entries for each soft navigation, plus 2
// entries for the initial navigation.
constexpr size_t kDefaultPaintEntriesBufferSize =;

Performance::Performance(
    base::TimeTicks time_origin,
    bool cross_origin_isolated_capability,
    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
    ExecutionContext* context)
    :{}

Performance::~Performance() = default;

const AtomicString& Performance::InterfaceName() const {}

PerformanceTiming* Performance::timing() const {}

PerformanceNavigation* Performance::navigation() const {}

MemoryInfo* Performance::memory(ScriptState*) const {}

EventCounts* Performance::eventCounts() {}

ScriptPromise<MemoryMeasurement> Performance::measureUserAgentSpecificMemory(
    ScriptState* script_state,
    ExceptionState& exception_state) const {}

DOMHighResTimeStamp Performance::timeOrigin() const {}

PerformanceEntryVector Performance::getEntries() {}

PerformanceEntryVector Performance::getEntries(
    ScriptState* script_state,
    PerformanceEntryFilterOptions* options) {}

PerformanceEntryVector Performance::GetEntriesForCurrentFrame(
    const AtomicString& maybe_name) {}

PerformanceEntryVector Performance::getBufferedEntriesByType(
    const AtomicString& entry_type,
    bool include_soft_navigation_observations) {}

PerformanceEntryVector Performance::getEntriesByType(
    const AtomicString& entry_type) {}

PerformanceEntryVector Performance::GetEntriesByTypeForCurrentFrame(
    const AtomicString& entry_type,
    const AtomicString& maybe_name) {}

PerformanceEntryVector Performance::getEntriesByTypeInternal(
    PerformanceEntry::EntryType type,
    const AtomicString& maybe_name,
    bool include_soft_navigation_observations) {}

PerformanceEntryVector Performance::getEntriesByName(
    const AtomicString& name,
    const AtomicString& entry_type) {}

PerformanceEntryVector Performance::GetEntriesWithChildFrames(
    ScriptState* script_state,
    const AtomicString& maybe_type,
    const AtomicString& maybe_name) {}

void Performance::clearResourceTimings() {}

void Performance::setResourceTimingBufferSize(unsigned size) {}

void Performance::setBackForwardCacheRestorationBufferSizeForTest(
    unsigned size) {}

void Performance::setEventTimingBufferSizeForTest(unsigned size) {}

void Performance::AddResourceTiming(mojom::blink::ResourceTimingInfoPtr info,
                                    const AtomicString& initiator_type) {}

// Called after loadEventEnd happens.
void Performance::NotifyNavigationTimingToObservers() {}

bool Performance::IsElementTimingBufferFull() const {}

bool Performance::IsEventTimingBufferFull() const {}

bool Performance::IsLongAnimationFrameBufferFull() const {}

void Performance::CopySecondaryBuffer() {}

void Performance::FireResourceTimingBufferFull(TimerBase*) {}

void Performance::AddToElementTimingBuffer(PerformanceElementTiming& entry) {}

void Performance::AddToEventTimingBuffer(PerformanceEventTiming& entry) {}

void Performance::AddToLayoutShiftBuffer(LayoutShift& entry) {}

void Performance::AddLargestContentfulPaint(LargestContentfulPaint* entry) {}

void Performance::AddSoftNavigationToPerformanceTimeline(
    SoftNavigationEntry* entry) {}

void Performance::AddFirstPaintTiming(base::TimeTicks start_time,
                                      bool is_triggered_by_soft_navigation) {}

void Performance::AddFirstContentfulPaintTiming(
    base::TimeTicks start_time,
    bool is_triggered_by_soft_navigation) {}

void Performance::AddPaintTiming(PerformancePaintTiming::PaintType type,
                                 base::TimeTicks start_time,
                                 bool is_triggered_by_soft_navigation) {}

bool Performance::CanAddResourceTimingEntry() {}

void Performance::AddLongTaskTiming(base::TimeTicks start_time,
                                    base::TimeTicks end_time,
                                    const AtomicString& name,
                                    const AtomicString& container_type,
                                    const AtomicString& container_src,
                                    const AtomicString& container_id,
                                    const AtomicString& container_name) {}

void Performance::AddBackForwardCacheRestoration(
    base::TimeTicks start_time,
    base::TimeTicks pageshow_start_time,
    base::TimeTicks pageshow_end_time) {}

UserTiming& Performance::GetUserTiming() {}

PerformanceMark* Performance::mark(ScriptState* script_state,
                                   const AtomicString& mark_name,
                                   PerformanceMarkOptions* mark_options,
                                   ExceptionState& exception_state) {}

void Performance::ProcessUserFeatureMark(
    const PerformanceMarkOptions* mark_options) {}

void Performance::clearMarks(const AtomicString& mark_name) {}

PerformanceMeasure* Performance::measure(ScriptState* script_state,
                                         const AtomicString& measure_name,
                                         ExceptionState& exception_state) {}

PerformanceMeasure* Performance::measure(
    ScriptState* script_state,
    const AtomicString& measure_name,
    const V8UnionPerformanceMeasureOptionsOrString* start_or_options,
    ExceptionState& exception_state) {}

PerformanceMeasure* Performance::measure(
    ScriptState* script_state,
    const AtomicString& measure_name,
    const V8UnionPerformanceMeasureOptionsOrString* start_or_options,
    const String& end,
    ExceptionState& exception_state) {}

// |MeasureInternal| exists to unify the arguments from different
// `performance.measure()` overloads into a consistent form, then delegate to
// |MeasureWithDetail|.
//
// |start_or_options| is either a String or a dictionary of options. When it's
// a String, it represents a starting performance mark. When it's a dictionary,
// the allowed fields are 'start', 'duration', 'end' and 'detail'. However,
// there are some combinations of fields and parameters which must raise
// errors. Specifically, the spec (https://https://w3c.github.io/user-timing/)
// requires errors to thrown in the following cases:
//  - If |start_or_options| is a dictionary and 'end_mark' is passed.
//  - If an options dictionary contains neither a 'start' nor an 'end' field.
//  - If an options dictionary contains all of 'start', 'duration' and 'end'.
//
// |end_mark| will be std::nullopt unless the `performance.measure()` overload
// specified an end mark.
PerformanceMeasure* Performance::MeasureInternal(
    ScriptState* script_state,
    const AtomicString& measure_name,
    const V8UnionPerformanceMeasureOptionsOrString* start_or_options,
    std::optional<String> end_mark,
    ExceptionState& exception_state) {}

PerformanceMeasure* Performance::MeasureWithDetail(
    ScriptState* script_state,
    const AtomicString& measure_name,
    const V8UnionDoubleOrString* start,
    const std::optional<double>& duration,
    const V8UnionDoubleOrString* end,
    const ScriptValue& detail,
    ExceptionState& exception_state) {}

void Performance::clearMeasures(const AtomicString& measure_name) {}

void Performance::RegisterPerformanceObserver(PerformanceObserver& observer) {}

void Performance::UnregisterPerformanceObserver(
    PerformanceObserver& old_observer) {}

void Performance::UpdatePerformanceObserverFilterOptions() {}

void Performance::NotifyObserversOfEntry(PerformanceEntry& entry) const {}

bool Performance::HasObserverFor(
    PerformanceEntry::EntryType filter_type) const {}

void Performance::ActivateObserver(PerformanceObserver& observer) {}

void Performance::SuspendObserver(PerformanceObserver& observer) {}

void Performance::DeliverObservationsTimerFired(TimerBase*) {}

int Performance::GetDroppedEntriesForTypes(PerformanceEntryTypeMask types) {}

// static
DOMHighResTimeStamp Performance::ClampTimeResolution(
    base::TimeDelta time,
    bool cross_origin_isolated_capability) {}

// static
DOMHighResTimeStamp Performance::MonotonicTimeToDOMHighResTimeStamp(
    base::TimeTicks time_origin,
    base::TimeTicks monotonic_time,
    bool allow_negative_value,
    bool cross_origin_isolated_capability) {}

DOMHighResTimeStamp Performance::MonotonicTimeToDOMHighResTimeStamp(
    base::TimeTicks monotonic_time) const {}

DOMHighResTimeStamp Performance::now() const {}

// static
bool Performance::CanExposeNode(Node* node) {}

ScriptValue Performance::toJSONForBinding(ScriptState* script_state) const {}

void Performance::BuildJSONValue(V8ObjectBuilder& builder) const {}

// Insert entry in PerformanceEntryVector while maintaining sorted order (via
// Bubble Sort). We assume that the order of insertion roughly corresponds to
// the order of the StartTime, hence the sort beginning from the tail-end.
void Performance::InsertEntryIntoSortedBuffer(PerformanceEntryVector& entries,
                                              PerformanceEntry& entry,
                                              Metrics record) {}

void Performance::Trace(Visitor* visitor) const {}

void Performance::SetClocksForTesting(const base::Clock* clock,
                                      const base::TickClock* tick_clock) {}

void Performance::ResetTimeOriginForTesting(base::TimeTicks time_origin) {}

// TODO(https://crbug.com/1457049): remove this once visited links are
// partitioned.
bool Performance::softNavPaintMetricsSupported() const {}

}  // namespace blink