Commit c9e1e0da authored by Nicolas Pena's avatar Nicolas Pena Committed by Commit Bot

EventTiming: create at most one firstInput entry

This CL introduces a bool |first_input_detected_| to make sure that we do not
create more than one PerformanceEventTiming entry of type 'firstInput'. Before,
there could be many entries of this type dispatched to PerformanceObservers when
the first input occurred after onload and |first_input_timing_| would never be
set.

Bug: 841224, 851484
Change-Id: I293d3de1ac052eaab9297d725ce0211f242aaf5a
Reviewed-on: https://chromium-review.googlesource.com/1111914Reviewed-by: default avatarTimothy Dresser <tdresser@chromium.org>
Reviewed-by: default avatarDave Tapuska <dtapuska@chromium.org>
Commit-Queue: Nicolás Peña Moreno <npm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#569727}
parent 9a4e07f0
<!DOCTYPE html>
<html>
<meta charset=utf-8 />
<title>Event Timing: buffer long-latency events before onload</title>
<button id='button' onclick='1'>Generate a 'click' event</button>
<script src=../../resources/testharness.js></script>
<script src=../../resources/testharnessreport.js></script>
<script src=./resources/event-timing-support.js></script>
<script>
/* Timeline:
Onload
PerformanceObserver is registered
Click 1
Click 2
PerformanceObserver should observe only one firstInput entry.
(Dispatch and Process Click 2 - not buffered)
*/
async_test(function(t) {
let numFirstInputObserved = 0;
let numEventsObserved = 0;
new PerformanceObserver(t.step_func((entryList, obs) => {
const observedEntries = entryList.getEntries();
numEventsObserved += observedEntries.filter(entry =>
entry.entryType == 'event').length;
numFirstInputObserved += observedEntries.filter(entry =>
entry.entryType == 'firstInput').length;
if (numEventsObserved >= 2) {
assert_equals(performance.getEntriesByType('event').length, 0,
"There should be no buffered event entries.");
assert_equals(performance.getEntriesByType('firstInput').length, 0,
"There should be no buffered firstInput entries.");
// There should be 2 event entries and one firstInput entry.
assert_equals(numEventsObserved, 2,
"There should be 2 observed event entries.");
assert_equals(numFirstInputObserved, 1,
"There should be only 1 observed firstInput entry.");
t.done();
}
})).observe({ entryTypes: ['event', 'firstInput'] });
on_event(window, 'load', () => {
clickAndBlockMain('button').then(wait).then(() => {
clickAndBlockMain('button').then(wait);
});
});
},
"Event Timing: check firstInput after onload, observer, click, click."
);
</script>
</html>
...@@ -356,7 +356,7 @@ void WindowPerformance::ReportEventTimings(WebLayerTreeView::SwapResult result, ...@@ -356,7 +356,7 @@ void WindowPerformance::ReportEventTimings(WebLayerTreeView::SwapResult result,
for (const auto& entry : event_timings_) { for (const auto& entry : event_timings_) {
int duration_in_ms = std::ceil((end_time - entry->startTime()) / 8) * 8; int duration_in_ms = std::ceil((end_time - entry->startTime()) / 8) * 8;
entry->SetDuration(duration_in_ms); entry->SetDuration(duration_in_ms);
if (!first_input_timing_) { if (!first_input_detected_) {
if (entry->name() == "pointerdown") { if (entry->name() == "pointerdown") {
first_pointer_down_event_timing_ = first_pointer_down_event_timing_ =
PerformanceEventTiming::CreateFirstInputTiming(entry); PerformanceEventTiming::CreateFirstInputTiming(entry);
...@@ -383,6 +383,7 @@ void WindowPerformance::ReportEventTimings(WebLayerTreeView::SwapResult result, ...@@ -383,6 +383,7 @@ void WindowPerformance::ReportEventTimings(WebLayerTreeView::SwapResult result,
void WindowPerformance::DispatchFirstInputTiming( void WindowPerformance::DispatchFirstInputTiming(
PerformanceEventTiming* entry) { PerformanceEventTiming* entry) {
DCHECK(OriginTrials::eventTimingEnabled(GetExecutionContext())); DCHECK(OriginTrials::eventTimingEnabled(GetExecutionContext()));
first_input_detected_ = true;
if (!entry) if (!entry)
return; return;
......
...@@ -111,6 +111,10 @@ class CORE_EXPORT WindowPerformance final : public Performance, ...@@ -111,6 +111,10 @@ class CORE_EXPORT WindowPerformance final : public Performance,
// dispatch has been completed but the swap promise used to determine // dispatch has been completed but the swap promise used to determine
// |duration| has not been resolved. // |duration| has not been resolved.
HeapVector<Member<PerformanceEventTiming>> event_timings_; HeapVector<Member<PerformanceEventTiming>> event_timings_;
// We use a bool separate from |first_input_timing_| because if the first
// input does not happen before onload then |first_input_timing_| will never
// be populated since it should not be accessible from the performance buffer.
bool first_input_detected_ = false;
Member<PerformanceEventTiming> first_pointer_down_event_timing_; Member<PerformanceEventTiming> first_pointer_down_event_timing_;
mutable Member<PerformanceNavigation> navigation_; mutable Member<PerformanceNavigation> navigation_;
mutable Member<PerformanceTiming> timing_; mutable Member<PerformanceTiming> timing_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment