[Event Timing] Post launch cleanup for 2 Experiments
* Remove EventTimingKeypressAndCompositionInteractionId flag * Remove EventTimingFallbackToModalDialogStart flag * Update Key_interaction_state_machine doc * Fix FlushKeydown to cover key_code_to_interaction_info_map_ Preview of the state machine doc: https://chromium.googlesource.com/chromium/src/+/refs/changes/50/5854350/3/third_party/blink/renderer/core/timing/Key_interaction_state_machine.md Bug: 1435448,1456384 Change-Id: I862d444a2adcd5dc0d77e09ed49cc660e0b3e86d Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5854350 Commit-Queue: Aoyuan Zuo <zuoaoyuan@chromium.org> Reviewed-by: Michal Mocny <mmocny@chromium.org> Reviewed-by: Kentaro Hara <haraken@chromium.org> Cr-Commit-Position: refs/heads/main@{#1354832}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
e80fa82591
commit
97db5bc75e
android_webview/java/src/org/chromium/android_webview/common
docs/images
third_party/blink
@ -876,13 +876,6 @@ public final class ProductionSupportedFlagList {
|
||||
Flag.baseFeature(
|
||||
BlinkFeatures.BACK_FORWARD_CACHE_SEND_NOT_RESTORED_REASONS,
|
||||
"Expose NotRestoredReasons via PerformanceNavigationTiming API."),
|
||||
Flag.baseFeature(
|
||||
BlinkFeatures.EVENT_TIMING_FALLBACK_TO_MODAL_DIALOG_START,
|
||||
"Enable reporting the modal dialog start time as an alternative end time for"
|
||||
+ " duration measurement in performance event timing."),
|
||||
Flag.baseFeature(
|
||||
BlinkFeatures.EVENT_TIMING_KEYPRESS_AND_COMPOSITION_INTERACTION_ID,
|
||||
"Exposes Event Timing keyboard InteractionId of composition and keypress events."),
|
||||
Flag.baseFeature("SkipUnnecessaryThreadHopsForParseHeaders"),
|
||||
Flag.commandLine(
|
||||
AwSwitches.WEBVIEW_FPS_COMPONENT,
|
||||
|
BIN
docs/images/Key_interaction_state_machine_diagram.png
Normal file
BIN
docs/images/Key_interaction_state_machine_diagram.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 182 KiB |
File diff suppressed because one or more lines are too long
Before (image error) Size: 12 KiB |
12
third_party/blink/common/features.cc
vendored
12
third_party/blink/common/features.cc
vendored
@ -786,12 +786,6 @@ BASE_FEATURE(kEstablishGpuChannelAsync,
|
||||
#endif
|
||||
);
|
||||
|
||||
// Exposes Event Timing keyboard InteractionId of composition and keypress
|
||||
// events.
|
||||
BASE_FEATURE(kEventTimingKeypressAndCompositionInteractionId,
|
||||
"EventTimingKeypressAndCompositionInteractionId",
|
||||
base::FEATURE_ENABLED_BY_DEFAULT);
|
||||
|
||||
// Enables unload handler deprecation via Permissions-Policy.
|
||||
// https://crbug.com/1324111
|
||||
BASE_FEATURE(kDeprecateUnload,
|
||||
@ -816,12 +810,6 @@ BASE_FEATURE(kDeprecateUnloadByAllowList,
|
||||
const base::FeatureParam<std::string> kDeprecateUnloadAllowlist{
|
||||
&kDeprecateUnloadByAllowList, "allowlist", ""};
|
||||
|
||||
// Enable reporting the modal dialog start time as an alternative end time for
|
||||
// duration measurement in performance event timing.
|
||||
BASE_FEATURE(kEventTimingFallbackToModalDialogStart,
|
||||
"EventTimingFallbackToModalDialogStart",
|
||||
base::FEATURE_ENABLED_BY_DEFAULT);
|
||||
|
||||
// Enable not reporting orphan pointerup (pointerup not accompanied by
|
||||
// pointerdown) as an interaction in performance event timing.
|
||||
BASE_FEATURE(kEventTimingHandleOrphanPointerup,
|
||||
|
8
third_party/blink/public/common/features.h
vendored
8
third_party/blink/public/common/features.h
vendored
@ -458,11 +458,6 @@ BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kDropInputEventsBeforeFirstPaint);
|
||||
// layer tree frame sink.
|
||||
BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kEstablishGpuChannelAsync);
|
||||
|
||||
// Exposes Event Timing interactionId of keypress/keyboard events under
|
||||
// composition.
|
||||
BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(
|
||||
kEventTimingKeypressAndCompositionInteractionId);
|
||||
|
||||
BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kDeprecateUnload);
|
||||
BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kDeprecateUnloadByAllowList);
|
||||
BLINK_COMMON_EXPORT extern const base::FeatureParam<int>
|
||||
@ -471,9 +466,6 @@ BLINK_COMMON_EXPORT extern const base::FeatureParam<int> kDeprecateUnloadBucket;
|
||||
BLINK_COMMON_EXPORT extern const base::FeatureParam<std::string>
|
||||
kDeprecateUnloadAllowlist;
|
||||
|
||||
BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(
|
||||
kEventTimingFallbackToModalDialogStart);
|
||||
|
||||
BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kEventTimingHandleOrphanPointerup);
|
||||
|
||||
BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kExcludeLowEntropyImagesFromLCP);
|
||||
|
@ -1,15 +1,18 @@
|
||||
# Event Timing - Key Interaction State Machine
|
||||
Patricija Cerkaite, May 29 2023
|
||||
|
||||
Patricija Cerkaite, created on May 29 2023
|
||||
|
||||
Aoyuan Zuo, updated on Sept. 09 2024
|
||||
|
||||
[TOC]
|
||||
|
||||
## Background
|
||||
A keyboard interaction is a group of event handlers that fire when pressing a key on a keyboard. For example, A single "key pressed" interaction should include set order of events, such as `keydown`, `input`, and `keyup`. [EventTiming](https://w3c.github.io/event-timing/) group up certain events as interactions by assigning the same & non-trivial [interactionId](https://www.w3.org/TR/2022/WD-event-timing-20220524/#dom-performanceeventtiming-interactionid) following a state machine logic located in [`responsiveness_metrics.cc -> ResponsivenessMetrics::SetKeyIdAndRecordLatency()`](https://chromium.googlesource.com/chromium/src/+/main/third_party/blink/renderer/core/timing/responsiveness_metrics.cc#327). This doc visualizes this state machine to help people understand its logic.
|
||||
A keyboard interaction is a group of event handlers that fire when pressing a key on a keyboard. For example, A single "key pressed" interaction should include set order of events, such as `keydown`, `keypress`, `input`, and `keyup`. [EventTiming](https://w3c.github.io/event-timing/) group up certain events as interactions by assigning the same & non-trivial [interactionId](https://www.w3.org/TR/2022/WD-event-timing-20220524/#dom-performanceeventtiming-interactionid) following a state machine logic located in [`responsiveness_metrics.cc -> ResponsivenessMetrics::SetKeyIdAndRecordLatency()`](https://chromium.googlesource.com/chromium/src/+/main/third_party/blink/renderer/core/timing/responsiveness_metrics.cc#327). This doc visualizes this state machine to help people understand its logic.
|
||||
- - - -
|
||||
|
||||
## Diagram
|
||||
|
||||

|
||||

|
||||
|
||||
*** note
|
||||
### Note:
|
||||
@ -21,46 +24,92 @@ A keyboard interaction is a group of event handlers that fire when pressing a ke
|
||||
|
||||
## States
|
||||
|
||||
### `[1]` No entry
|
||||
The initial state. Either no entry of the key_code has been seen or previous ones have been cancelled.
|
||||
`key_code_entry_map_` does not contain any entry with a key equal to key_code.
|
||||
### `[1]` Non Composition
|
||||
The initial state. No entry of the key_code has been seen. `key_code_to_interaction_info_map_` does not contain any entry with a key equal to key_code.
|
||||
|
||||
### `[2]` Have keydown entry
|
||||
An intermediate state. In this state, we have seen the `keydown` entry for the current interaction, and are waiting for the matching `keyup` entry.
|
||||
`key_code_entry_map_` currently contains the `keydown` entry of the interaction that this state machine represent. In this state, `keydown` entry waiting for a **matching** `keyup` entry to finish the current interaction.
|
||||
### `[2]` Have Keydown
|
||||
An intermediate state. In this state, we have seen the `keydown` entry for the current interaction, and are waiting for potentially `keypress` or `contextmenu` events, and a matching `keyup` entry.
|
||||
`key_code_to_interaction_info_map_` and `sequence_based_keyboard_interaction_info_` currently contains the `keydown` entry.
|
||||
|
||||
### `[3]` Composition Event
|
||||
The state indicates that `keydown` has initiated the composition. Since the composition events are not part of the keyboard interactions this intermediate state holds until the interactionId is produced.
|
||||
### `[3]` Have Keypress
|
||||
An intermediate state. In this state, we have seen the `keydown` and `keypress` entries for the current interaction, and are waiting for the matching `keyup` entry.
|
||||
`key_code_to_interaction_info_map_` currently contains the timestamps of both `keydown` and `keypress` entries of the interaction that this state machine represent. In this state, we are waiting for the **matching** `keyup` entry to finish the current interaction.
|
||||
|
||||
### `[4]` Interaction finished
|
||||
This is the end of an interaction lifecycle. The `keydown` entry was paired with the corresponding `keyup` entry and the key_code from the `key_code_entry_map_` was errased.
|
||||
### `[4]` Have Contextmenu
|
||||
When pressing the menu key on a keyboard, a `contextmenu` event would get dispatched right after the `keydown` event. This is a valid user interaction, but the `keyup` event could possibly be dropped due to the showing of contextmenu overlay. Thus, while we waiting for the potentially coming `keyup` event, we also setup a 1 second timer to wrap up this interaction in case `keyup` is not coming.
|
||||
|
||||
### `[5]` Composition Continue Ongoing Interaction
|
||||
The state indicates that `compositionstart` has initiated the composition. Since the composition events (`compositionstart`, `compositionupdate`, `compositionend`) are not part of the keyboard interactions this intermediate state holds until the interactionId is produced.
|
||||
|
||||
### `[6]` Composition Start New Interaction On Keydown
|
||||
This state means we're currently under composition, and we're ready to start recording a new interaction upon next `keydown`.
|
||||
|
||||
### `[7]` Composition Start New Interaction On Input
|
||||
This state means we're currently under composition, and we have not seen `keydown` thus no interactionId has been generated yet for the current interaction. As a result, we will generate one on `input`.
|
||||
|
||||
### `[8]` End Composition On Keydown
|
||||
We have get out of the composition session, but are still waiting for potentially coming `keyup`s to wrap up the last interaction in composition.
|
||||
|
||||
### `[9]` Interaction finished
|
||||
This is the end of an interaction lifecycle. The `keydown` entry was paired with the corresponding `keyup` entry and the key_code from the `key_code_to_interaction_info_map_` was erased.
|
||||
|
||||
- - - -
|
||||
|
||||
## Transitions
|
||||
|
||||
### `[5]` keydown
|
||||
### `[10]` Keydown
|
||||
Generate a new interactionId. Assign it to the `keydown` entry. Save the `keydown`'s key_code, interactionId, timestamps into `key_code_to_interaction_info_map_` for UKM reporting later once the interaction is fully finished..
|
||||
|
||||
Save the `keydown` key_code value to the `key_code_entry_map_`.
|
||||
### `[11]` Key Holding
|
||||
When holding a key down for an extended period. A serious of `keydown` events with the same key_code will be dispatched. We treat each individual `keydown` event as a valid interaction and assign a unique interactionId. Only the last one will be matched with `keyup`.
|
||||
|
||||
### `[6]` keydown
|
||||
### `[12]` Keypress
|
||||
A `keypress` event following a `keydown` event belongs to the same interaction as the `keydown`. We assign them the same interactionId and also save `keypress`'s timestamp into `key_code_to_interaction_info_map_` for UKM reporting later.
|
||||
|
||||
If key_code value is not equal to 229, then generate a new interactionId for the [`|previous_entry|`](https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:third_party/blink/renderer/core/timing/responsiveness_metrics.cc;l=329;drc=2425fac374aaa944c34b2340b8f53c9c7fc49533#:~:text=if%20(key_code_entry_map_.Contains(*key_code))%20%7B). This transition could be triggered by holding a key down for an extended period.
|
||||
### `[13]` Keyup
|
||||
A `keyup` event always finish up an interaction by assigning the same interactionId as `keydown`'s and report interaction duration calculated by all events belongs to the interaction to UKM. The `key_code` will be removed from `key_code_to_interaction_info_map_` after reporting, and `sequence_based_keyboard_interaction_info_` will be cleared.
|
||||
|
||||
### `[7]` compositionstart
|
||||
The keydown event initiates the composition session. The `isComposition` parameter is set to true.
|
||||
### `[14]` Contextmenu
|
||||
When pressing the menu key on a keyboard, a `contextmenu` event would get dispatched right after the `keydown` event. This is a valid user interaction, but the `keyup` event could possibly be dropped due to the showing of contextmenu overlay. Thus, while we waiting for the potentially coming `keyup` event, we also setup a 1 second timer to wrap up this interaction in case `keyup` is not coming.
|
||||
|
||||
### `[8]` input
|
||||
The input event within the composition finishes the interaction and produces the interactionId.
|
||||
### `[15]` Keyup (after contextmenu)
|
||||
A `keyup` after contextmenu stops the timer and wraps up the interaction immediately, which means getting the same interactionId assigned; reporting the interaction to UKM; erasing the interaction info from `key_code_to_interaction_info_map_` and clears `sequence_based_keyboard_interaction_info_`.
|
||||
|
||||
### `[9]` [keyup key_code = keydown key_code] keyup
|
||||
### `[16]` Compositionstart
|
||||
The `compositionstart` event following a `keydown` event initiates the composition session.
|
||||
|
||||
The transition occurs if the keyup event is fired and there is a matching key_code of a keydown event. In this transition the following steps are executed:
|
||||
1. Generate a new interactionId for the keydown-keyup pair (`keydown` and `keyup`).
|
||||
2. Delete the key_code of the pair from the `key_code_entry_map_`.
|
||||
### `[17]` Keydown (under composition)
|
||||
Some IME (Input Method Editor) could repeatedly dispatch keydowns for the same user interaction. When it happens, we will assign the same interactionId to all of them.
|
||||
|
||||
### `[10]` MaybeFlushKeyboardEntries
|
||||
[MaybeFlushKeyboardEntries](https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:third_party/blink/renderer/core/timing/window_performance.cc;l=677;drc=66941d1f0cfe9155b400aef887fe39a403c1f518;bpv=1;bpt=1) free up `keydown` entries stuck in `key_code_entry_map_` upon the first event timing entry after 500ms. `Keydown` gets stuck in the map for reasons like [crbug/1428603](https://bugs.chromium.org/p/chromium/issues/detail?id=1428603). This flush mechanism has a known [issue](https://bugs.chromium.org/p/chromium/issues/detail?id=1420716).
|
||||
### `[18]` Compositionupdate
|
||||
`Compositionupdate` is the center of a keyboard user interaction under composition. Once we see it, we'll start wrapping up this interaction with matching the interactionId to the rest of events including `Input` and `keyup`.
|
||||
|
||||
### `[19]` Compositionstart
|
||||
This is an edge case that exists for some IMEs where `keydown` events are missing. `Compositionstart` would initiate the composition session without a `keydown`.
|
||||
|
||||
### `[20]` Compositionupdate (keydown missing)
|
||||
This is an edge case that exists for some IMEs where `keydown` events are missing. Since interactionIds are usually generated with `keydown` events, we'll fallback to generate a new interactionId on `input` to make sure we can still capture and report this interaction.
|
||||
|
||||
### `[21]` Input (keydown missing)
|
||||
A new interactionId is generated since one wasn't generated before due to the missing `keydown`.
|
||||
|
||||
### `[22]` Input
|
||||
Assign the current interactionId (previously generated from `keydown`) to the `input` event.
|
||||
|
||||
### `[23]` Keyup
|
||||
Assign the current interactionId (previously generated from `keydown`) to the `keyup` event.
|
||||
|
||||
### `[24]` Keydown (next interaction)
|
||||
Under composition session, we interpret a new keydown as the start of a new discrete user interaction on a keyboard, which also marks the end of the current interaction.
|
||||
|
||||
### `[25]` Compositionend
|
||||
`Compositionend` marks the end of an user interaction under composition through a one second timer, in case when more than one `keyup` events are dispatched we can still group them up into the same user interaction, which could happen to some IMEs as an edge case.
|
||||
|
||||
### `[26]` Keyup
|
||||
A `keyup` from the same user interaction could come after `compositionend`, and it will get the same interactionId assigned.
|
||||
|
||||
### `[27]` Keydown (next interaction) / timer
|
||||
Either after 1 second by a timer, or the next `keydown` event coming in before the timer times up, we'll wrap up the current interaction and report to UKM.
|
||||
- - - -
|
||||
|
||||
## Mermaid diagram source file
|
||||
@ -77,18 +126,35 @@ date as well.
|
||||
```
|
||||
stateDiagram-v2
|
||||
|
||||
no_entry : No entry [1]
|
||||
have_key_down : Have keydown entry [2]
|
||||
have_composition : Composition Event [3]
|
||||
interaction_finished: Interaction finished [4]
|
||||
non_composition : Non Composition [1]
|
||||
have_keydown : Have keydown [2]
|
||||
have_keypress : Have Keypress [3]
|
||||
have_contextmenu : Have Contextmenu [4]
|
||||
composition_continue_ongoing_interaction : Composition Continue Ongoing Interaction [5]
|
||||
composition_start_new_interaction_on_keydown : Composition Start New Interaction On Keydown [6]
|
||||
composition_start_new_interaction_on_input : Composition Start New Interaction On Input [7]
|
||||
end_composition_on_keydown : End Composition On Keydown [8]
|
||||
interaction_finished: Interaction finished [9]
|
||||
|
||||
[*] --> no_entry
|
||||
no_entry --> have_key_down : keydown [5]
|
||||
have_key_down --> have_key_down : keydown [6]
|
||||
no_entry --> have_composition: compositionstart [7]
|
||||
have_composition --> interaction_finished : input [8]
|
||||
have_key_down --> interaction_finished : [keyup key_code = keydown key_code] keyup [9]
|
||||
have_key_down --> interaction_finished : MaybeFlushKeyboardEntries [10]
|
||||
[*] --> non_composition
|
||||
non_composition --> have_keydown : Keydown [10]
|
||||
have_keydown --> have_keydown : Key Holding [11]
|
||||
have_keydown --> have_keypress : Keypress [12]
|
||||
have_keypress --> interaction_finished : Keyup [13]
|
||||
have_keydown --> have_contextmenu : Contextmenu [14]
|
||||
have_contextmenu --> interaction_finished : Keyup [15]
|
||||
have_keydown --> composition_continue_ongoing_interaction : Compositionstart [16]
|
||||
composition_continue_ongoing_interaction --> composition_continue_ongoing_interaction : Keydown [17]
|
||||
composition_continue_ongoing_interaction --> composition_start_new_interaction_on_keydown : Compositionupdate [18]
|
||||
non_composition --> composition_continue_ongoing_interaction : Compositionstart [19]
|
||||
composition_continue_ongoing_interaction --> composition_start_new_interaction_on_input : Compositionupdate (keydown missing) [20]
|
||||
composition_start_new_interaction_on_input --> composition_start_new_interaction_on_keydown : Input [21]
|
||||
composition_start_new_interaction_on_keydown --> composition_start_new_interaction_on_keydown : Input [22]
|
||||
composition_start_new_interaction_on_keydown --> composition_start_new_interaction_on_keydown : Keyup [23]
|
||||
composition_start_new_interaction_on_keydown --> interaction_finished : Keydown (next interaction) [24]
|
||||
composition_start_new_interaction_on_keydown --> end_composition_on_keydown : Compositionend [25]
|
||||
end_composition_on_keydown --> end_composition_on_keydown : Keyup [26]
|
||||
end_composition_on_keydown --> interaction_finished : Keydown (next interaction) / timer [27]
|
||||
interaction_finished --> [*]
|
||||
|
||||
```
|
@ -48,9 +48,6 @@ constexpr uint32_t kMaxFirstInteractionID = 10000;
|
||||
// interactions. This is consistent with the spec, which allows the increasing
|
||||
// the user interaction value by a small number chosen by the user agent.
|
||||
constexpr uint32_t kInteractionIdIncrement = 7;
|
||||
// The maximum tap delay we can handle for assigning interaction id.
|
||||
constexpr blink::DOMHighResTimeStamp kMaxDelayForEntries =
|
||||
blink::DOMHighResTimeStamp(500);
|
||||
// The length of the timer to flush entries from the time pointerup occurs.
|
||||
constexpr base::TimeDelta kFlushTimerLength = base::Seconds(1);
|
||||
// The name for the histogram which records interaction timings, and the names
|
||||
@ -440,9 +437,7 @@ bool ResponsivenessMetrics::SetPointerIdAndRecordLatency(
|
||||
}
|
||||
}
|
||||
|
||||
if (base::FeatureList::IsEnabled(
|
||||
features::kEventTimingKeypressAndCompositionInteractionId) &&
|
||||
RuntimeEnabledFeaturesBase::
|
||||
if (RuntimeEnabledFeaturesBase::
|
||||
EventTimingHandleKeyboardEventSimulatedClickEnabled()) {
|
||||
// Try handle keyboard event simulated click.
|
||||
if (TryHandleKeyboardEventSimulatedClick(entry, pointer_id)) {
|
||||
@ -529,112 +524,7 @@ void ResponsivenessMetrics::RecordKeyboardUKM(
|
||||
// (https://chromium.googlesource.com/chromium/src/+/main/third_party/blink/renderer/core/timing/Key_interaction_state_machine.md)
|
||||
// to help understand the logic below that how event timing group up keyboard
|
||||
// events as interactions.
|
||||
bool ResponsivenessMetrics::SetKeyIdAndRecordLatency(
|
||||
PerformanceEventTiming* entry,
|
||||
EventTimestamps event_timestamps) {
|
||||
if (base::FeatureList::IsEnabled(
|
||||
features::kEventTimingKeypressAndCompositionInteractionId)) {
|
||||
return SetKeyIdAndRecordLatencyExperimental(entry, event_timestamps);
|
||||
}
|
||||
|
||||
last_pointer_id_ = std::nullopt;
|
||||
auto event_type = entry->name();
|
||||
if (event_type == event_type_names::kKeydown) {
|
||||
// If we were waiting for matching pointerup/keyup after a contextmenu, they
|
||||
// won't show up at this point.
|
||||
if (contextmenu_flush_timer_.IsActive()) {
|
||||
contextmenu_flush_timer_.Stop();
|
||||
FlushPointerdownAndPointerup();
|
||||
FlushKeydown();
|
||||
}
|
||||
// During compositions, we ignore keydowns/keyups and look at input events.
|
||||
if (composition_started_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
DCHECK(entry->GetEventTimingReportingInfo()->key_code.has_value());
|
||||
auto key_code = entry->GetEventTimingReportingInfo()->key_code.value();
|
||||
if (key_code_entry_map_.Contains(key_code)) {
|
||||
auto* previous_entry = key_code_entry_map_.at(key_code);
|
||||
// Ignore repeat IME keydowns. See
|
||||
// https://w3c.github.io/uievents/#determine-keydown-keyup-keyCode.
|
||||
// Reasoning: we cannot ignore all IME keydowns because on Android in
|
||||
// some languages the events received are 'keydown', 'input', 'keyup',
|
||||
// and since we are not composing then the 'input' event is ignored, so
|
||||
// we must consider the key events with 229 keyCode as the user
|
||||
// interaction. Besides this, we cannot consider repeat 229 keydowns
|
||||
// because we may get those on ChromeOS when we should ignore them. This
|
||||
// may be related to crbug.com/1252856.
|
||||
if (key_code != 229) {
|
||||
// Generate a new interaction id for |previous_entry|. This case could
|
||||
// be caused by keeping a key pressed for a while.
|
||||
UpdateInteractionId();
|
||||
previous_entry->GetEntry()->SetInteractionIdAndOffset(
|
||||
GetCurrentInteractionId(), GetInteractionCount());
|
||||
RecordKeyboardUKM(window_performance_->DomWindow(),
|
||||
{previous_entry->GetTimeStamps()},
|
||||
previous_entry->GetEntry()->interactionOffset());
|
||||
}
|
||||
window_performance_->NotifyAndAddEventTimingBuffer(
|
||||
previous_entry->GetEntry());
|
||||
}
|
||||
key_code_entry_map_.Set(
|
||||
key_code, KeyboardEntryAndTimestamps::Create(entry, event_timestamps));
|
||||
// Similar to pointerdown, we need to wait a bit before knowing the
|
||||
// interactionId of keydowns.
|
||||
return false;
|
||||
} else if (event_type == event_type_names::kKeyup) {
|
||||
if (contextmenu_flush_timer_.IsActive()) {
|
||||
contextmenu_flush_timer_.Stop();
|
||||
}
|
||||
DCHECK(entry->GetEventTimingReportingInfo()->key_code.has_value());
|
||||
auto key_code = entry->GetEventTimingReportingInfo()->key_code.value();
|
||||
if (composition_started_ || !key_code_entry_map_.Contains(key_code)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
auto* previous_entry = key_code_entry_map_.at(key_code);
|
||||
// Generate a new interaction id for the keydown-keyup pair.
|
||||
UpdateInteractionId();
|
||||
previous_entry->GetEntry()->SetInteractionIdAndOffset(
|
||||
GetCurrentInteractionId(), GetInteractionCount());
|
||||
window_performance_->NotifyAndAddEventTimingBuffer(
|
||||
previous_entry->GetEntry());
|
||||
if (previous_entry->GetEntry()->HasKnownInteractionID()) {
|
||||
entry->SetInteractionIdAndOffset(
|
||||
previous_entry->GetEntry()->interactionId(),
|
||||
previous_entry->GetEntry()->interactionOffset());
|
||||
}
|
||||
RecordKeyboardUKM(window_performance_->DomWindow(),
|
||||
{previous_entry->GetTimeStamps(), event_timestamps},
|
||||
entry->interactionOffset());
|
||||
key_code_entry_map_.erase(key_code);
|
||||
} else if (event_type == event_type_names::kCompositionstart) {
|
||||
composition_started_ = true;
|
||||
for (auto key_entry : key_code_entry_map_.Values()) {
|
||||
window_performance_->NotifyAndAddEventTimingBuffer(key_entry->GetEntry());
|
||||
}
|
||||
key_code_entry_map_.clear();
|
||||
} else if (event_type == event_type_names::kCompositionend) {
|
||||
composition_started_ = false;
|
||||
} else if (event_type == event_type_names::kInput) {
|
||||
if (!composition_started_) {
|
||||
return true;
|
||||
}
|
||||
// We are in the case of a text input event while compositing with
|
||||
// non-trivial data, so we want to increase interactionId.
|
||||
// TODO(crbug.com/1252856): fix counts in ChromeOS due to duplicate
|
||||
// events.
|
||||
UpdateInteractionId();
|
||||
entry->SetInteractionIdAndOffset(GetCurrentInteractionId(),
|
||||
GetInteractionCount());
|
||||
RecordKeyboardUKM(window_performance_->DomWindow(), {event_timestamps},
|
||||
entry->interactionOffset());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ResponsivenessMetrics::SetKeyIdAndRecordLatencyExperimental(
|
||||
void ResponsivenessMetrics::SetKeyIdAndRecordLatency(
|
||||
PerformanceEventTiming* entry,
|
||||
EventTimestamps event_timestamps) {
|
||||
last_pointer_id_ = std::nullopt;
|
||||
@ -685,7 +575,7 @@ bool ResponsivenessMetrics::SetKeyIdAndRecordLatencyExperimental(
|
||||
CHECK(entry->GetEventTimingReportingInfo()->key_code.has_value());
|
||||
auto key_code = entry->GetEventTimingReportingInfo()->key_code.value();
|
||||
if (!key_code_to_interaction_info_map_.Contains(key_code)) {
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Match the keydown entry with the keyup entry using keycode.
|
||||
@ -734,7 +624,7 @@ bool ResponsivenessMetrics::SetKeyIdAndRecordLatencyExperimental(
|
||||
} else if (event_type == event_type_names::kInput) {
|
||||
// Expose interactionId for Input events only under composition
|
||||
if (composition_state_ == kNonComposition) {
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
// Update Interaction Id when input is selected using IME suggestion without
|
||||
// pressing a key. In this case Input event starts and finishes interaction
|
||||
@ -759,44 +649,18 @@ bool ResponsivenessMetrics::SetKeyIdAndRecordLatencyExperimental(
|
||||
}
|
||||
last_keydown_keycode_info_.reset();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ResponsivenessMetrics::FlushExpiredKeydown(
|
||||
DOMHighResTimeStamp current_time) {
|
||||
if (base::FeatureList::IsEnabled(
|
||||
features::kEventTimingKeypressAndCompositionInteractionId)) {
|
||||
// Do nothing. Experimenting not cleaning up keydown/keypress that was not
|
||||
// successfully paired with a keyup thus get stuck in the map.
|
||||
} else {
|
||||
// We cannot delete from a HashMap while iterating.
|
||||
Vector<int> key_codes_to_remove;
|
||||
for (const auto& entry : key_code_entry_map_) {
|
||||
PerformanceEventTiming* key_down = entry.value->GetEntry();
|
||||
if (current_time - key_down->processingEnd() > kMaxDelayForEntries) {
|
||||
window_performance_->NotifyAndAddEventTimingBuffer(key_down);
|
||||
key_codes_to_remove.push_back(entry.key);
|
||||
}
|
||||
}
|
||||
key_code_entry_map_.RemoveAll(key_codes_to_remove);
|
||||
}
|
||||
}
|
||||
|
||||
void ResponsivenessMetrics::FlushKeydown() {
|
||||
for (const auto& entry : key_code_entry_map_) {
|
||||
PerformanceEventTiming* key_down = entry.value->GetEntry();
|
||||
for (auto& entry : key_code_to_interaction_info_map_) {
|
||||
// Keydowns triggered contextmenu, though missing pairing keyups due to a
|
||||
// known issue - https://github.com/w3c/pointerevents/issues/408, should
|
||||
// still be counted as a valid interaction and get a valid id assigned.
|
||||
UpdateInteractionId();
|
||||
key_down->SetInteractionIdAndOffset(GetCurrentInteractionId(),
|
||||
GetInteractionCount());
|
||||
window_performance_->NotifyAndAddEventTimingBuffer(key_down);
|
||||
// still be counted as a valid interaction and get reported to UKM.
|
||||
RecordKeyboardUKM(window_performance_->DomWindow(),
|
||||
{entry.value->GetTimeStamps()},
|
||||
key_down->interactionOffset());
|
||||
entry.value.GetTimeStamps(),
|
||||
entry.value.GetInteractionOffset());
|
||||
}
|
||||
key_code_entry_map_.clear();
|
||||
key_code_to_interaction_info_map_.clear();
|
||||
}
|
||||
|
||||
void ResponsivenessMetrics::FlushAllEventsAtPageHidden() {
|
||||
@ -958,7 +822,6 @@ void ResponsivenessMetrics::Trace(Visitor* visitor) const {
|
||||
visitor->Trace(pointer_id_entry_map_);
|
||||
visitor->Trace(pointer_flush_timer_);
|
||||
visitor->Trace(contextmenu_flush_timer_);
|
||||
visitor->Trace(key_code_entry_map_);
|
||||
visitor->Trace(composition_end_flush_timer_);
|
||||
}
|
||||
|
||||
|
@ -43,8 +43,7 @@ class CORE_EXPORT ResponsivenessMetrics
|
||||
};
|
||||
|
||||
// Wrapper class to store interactionId, interaction offset, and timestamps
|
||||
// of an entry on a HashMap. It is optimized and used only in the experimental
|
||||
// SetKeyIdAndRecordLatency function. (SetKeyIdAndRecordLatencyExperimental)
|
||||
// of an entry on a HashMap.
|
||||
class InteractionInfo {
|
||||
public:
|
||||
InteractionInfo(uint32_t interaction_id,
|
||||
@ -167,21 +166,12 @@ class CORE_EXPORT ResponsivenessMetrics
|
||||
|
||||
// Assigns interactionId and records interaction latency for keyboard events.
|
||||
// We care about input, compositionstart, and compositionend events, so
|
||||
// |key_code| will be std::nullopt in those cases. Returns true if the entry
|
||||
// would be ready to be surfaced in PerformanceObservers and the Performance
|
||||
// Timeline.
|
||||
bool SetKeyIdAndRecordLatency(PerformanceEventTiming* entry,
|
||||
// |key_code| will be std::nullopt in those cases.
|
||||
void SetKeyIdAndRecordLatency(PerformanceEventTiming* entry,
|
||||
EventTimestamps event_timestamps);
|
||||
|
||||
// Experimental function that in addition to SetKeyIdAndRecordLatency()
|
||||
// exposes interactionId for keypress and keyup/keydown under composition.
|
||||
bool SetKeyIdAndRecordLatencyExperimental(PerformanceEventTiming* entry,
|
||||
EventTimestamps event_timestamps);
|
||||
|
||||
// Clear keydowns in |key_codes_to_remove| if we have stored them for a while.
|
||||
void FlushExpiredKeydown(DOMHighResTimeStamp end_time);
|
||||
// Clears all keydowns in |key_codes_to_remove| no matter how long we have
|
||||
// stored them.
|
||||
// Clears all keydowns in |key_code_to_interaction_info_map_| and report to
|
||||
// UKM.
|
||||
void FlushKeydown();
|
||||
|
||||
uint32_t GetInteractionCount() const;
|
||||
@ -266,12 +256,6 @@ class CORE_EXPORT ResponsivenessMetrics
|
||||
HashMap<int, InteractionInfo, IntWithZeroKeyHashTraits<int>>
|
||||
key_code_to_interaction_info_map_;
|
||||
|
||||
// Map from keyCodes to keydown entries and keydown timestamps.
|
||||
HeapHashMap<int,
|
||||
Member<KeyboardEntryAndTimestamps>,
|
||||
IntWithZeroKeyHashTraits<int>>
|
||||
key_code_entry_map_;
|
||||
|
||||
// Whether we are composing or not. When we are not composing, we set
|
||||
// interactionId for keydown and keyup events. When we are composing, we set
|
||||
// interactionId for input events.
|
||||
|
@ -627,11 +627,6 @@ void WindowPerformance::OnPresentationPromiseResolved(
|
||||
pending_event_presentation_time_map_.Set(presentation_index,
|
||||
presentation_timestamp);
|
||||
ReportEventTimings();
|
||||
|
||||
// Use |end_time| as a proxy for the current time to flush expired keydowns.
|
||||
DOMHighResTimeStamp end_time =
|
||||
MonotonicTimeToDOMHighResTimeStamp(presentation_timestamp);
|
||||
responsiveness_metrics_->FlushExpiredKeydown(end_time);
|
||||
}
|
||||
|
||||
void WindowPerformance::FlushEventTimingsOnPageHidden() {
|
||||
@ -941,10 +936,7 @@ void WindowPerformance::SetFallbackTime(PerformanceEventTiming* entry) {
|
||||
if (!show_modal_dialog_timestamps_.empty() &&
|
||||
show_modal_dialog_timestamps_.front() <
|
||||
entry->GetEventTimingReportingInfo()->presentation_time) {
|
||||
if (base::FeatureList::IsEnabled(
|
||||
features::kEventTimingFallbackToModalDialogStart)) {
|
||||
fallback_end_time_to_dialog_time = true;
|
||||
}
|
||||
fallback_end_time_to_dialog_time = true;
|
||||
first_modal_dialog_timestamp = show_modal_dialog_timestamps_.front();
|
||||
}
|
||||
|
||||
@ -982,8 +974,8 @@ bool WindowPerformance::SetInteractionIdAndRecordLatency(
|
||||
return responsiveness_metrics_->SetPointerIdAndRecordLatency(
|
||||
entry, event_timestamps);
|
||||
}
|
||||
return responsiveness_metrics_->SetKeyIdAndRecordLatency(entry,
|
||||
event_timestamps);
|
||||
responsiveness_metrics_->SetKeyIdAndRecordLatency(entry, event_timestamps);
|
||||
return true;
|
||||
}
|
||||
|
||||
void WindowPerformance::ReportLongAnimationFrameTiming(
|
||||
|
@ -13,7 +13,6 @@
|
||||
|
||||
#include "base/numerics/safe_conversions.h"
|
||||
#include "base/test/metrics/histogram_tester.h"
|
||||
#include "base/test/scoped_feature_list.h"
|
||||
#include "base/test/test_mock_time_task_runner.h"
|
||||
#include "base/test/trace_event_analyzer.h"
|
||||
#include "base/time/time.h"
|
||||
@ -67,14 +66,9 @@ base::TimeTicks GetTimeStamp(int64_t time) {
|
||||
|
||||
} // namespace
|
||||
|
||||
class WindowPerformanceTest : public testing::Test,
|
||||
public ::testing::WithParamInterface<bool> {
|
||||
class WindowPerformanceTest : public testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
if (GetParam()) {
|
||||
features_.InitAndEnableFeature(
|
||||
blink::features::kEventTimingKeypressAndCompositionInteractionId);
|
||||
}
|
||||
test_task_runner_ = base::MakeRefCounted<base::TestMockTimeTaskRunner>();
|
||||
ResetPerformance();
|
||||
}
|
||||
@ -220,10 +214,9 @@ class WindowPerformanceTest : public testing::Test,
|
||||
scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner_;
|
||||
ScopedFakeUkmRecorder scoped_fake_ukm_recorder_;
|
||||
base::HistogramTester histogram_tester_;
|
||||
base::test::ScopedFeatureList features_;
|
||||
};
|
||||
|
||||
TEST_P(WindowPerformanceTest, SanitizedLongTaskName) {
|
||||
TEST_F(WindowPerformanceTest, SanitizedLongTaskName) {
|
||||
// Unable to attribute, when no execution contents are available.
|
||||
EXPECT_EQ("unknown", SanitizedAttribution(nullptr, false, GetFrame()));
|
||||
|
||||
@ -235,7 +228,7 @@ TEST_P(WindowPerformanceTest, SanitizedLongTaskName) {
|
||||
SanitizedAttribution(GetWindow(), true, GetFrame()));
|
||||
}
|
||||
|
||||
TEST_P(WindowPerformanceTest, SanitizedLongTaskName_CrossOrigin) {
|
||||
TEST_F(WindowPerformanceTest, SanitizedLongTaskName_CrossOrigin) {
|
||||
// Create another dummy page holder and pretend it is an iframe.
|
||||
DummyPageHolder another_page(gfx::Size(400, 300));
|
||||
another_page.GetDocument().SetURL(KURL("https://iframed.com/bar"));
|
||||
@ -252,7 +245,7 @@ TEST_P(WindowPerformanceTest, SanitizedLongTaskName_CrossOrigin) {
|
||||
// https://crbug.com/706798: Checks that after navigation that have replaced the
|
||||
// window object, calls to not garbage collected yet WindowPerformance belonging
|
||||
// to the old window do not cause a crash.
|
||||
TEST_P(WindowPerformanceTest, NavigateAway) {
|
||||
TEST_F(WindowPerformanceTest, NavigateAway) {
|
||||
AddLongTaskObserver();
|
||||
|
||||
// Simulate navigation commit.
|
||||
@ -307,7 +300,7 @@ TEST(PerformanceLifetimeTest, SurviveContextSwitch) {
|
||||
|
||||
// Make sure the output entries with the same timestamps follow the insertion
|
||||
// order. (http://crbug.com/767560)
|
||||
TEST_P(WindowPerformanceTest, EnsureEntryListOrder) {
|
||||
TEST_F(WindowPerformanceTest, EnsureEntryListOrder) {
|
||||
// Need to have an active V8 context for ScriptValues to operate.
|
||||
v8::HandleScope handle_scope(GetScriptState()->GetIsolate());
|
||||
v8::Local<v8::Context> context = GetScriptState()->GetContext();
|
||||
@ -340,7 +333,7 @@ TEST_P(WindowPerformanceTest, EnsureEntryListOrder) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(WindowPerformanceTest, EventTimingEntryBuffering) {
|
||||
TEST_F(WindowPerformanceTest, EventTimingEntryBuffering) {
|
||||
EXPECT_TRUE(page_holder_->GetFrame().Loader().GetDocumentLoader());
|
||||
|
||||
base::TimeTicks start_time = GetTimeOrigin() + base::Seconds(1.1);
|
||||
@ -377,7 +370,7 @@ TEST_P(WindowPerformanceTest, EventTimingEntryBuffering) {
|
||||
.size());
|
||||
}
|
||||
|
||||
TEST_P(WindowPerformanceTest, Expose100MsEvents) {
|
||||
TEST_F(WindowPerformanceTest, Expose100MsEvents) {
|
||||
base::TimeTicks start_time = GetTimeOrigin() + base::Seconds(1);
|
||||
base::TimeTicks processing_start = start_time + base::Milliseconds(10);
|
||||
base::TimeTicks processing_end = processing_start + base::Milliseconds(10);
|
||||
@ -399,7 +392,7 @@ TEST_P(WindowPerformanceTest, Expose100MsEvents) {
|
||||
EXPECT_EQ(event_type_names::kMousedown, entries.at(0)->name());
|
||||
}
|
||||
|
||||
TEST_P(WindowPerformanceTest, EventTimingDuration) {
|
||||
TEST_F(WindowPerformanceTest, EventTimingDuration) {
|
||||
base::TimeTicks start_time = GetTimeOrigin() + base::Milliseconds(1000);
|
||||
base::TimeTicks processing_start = GetTimeOrigin() + base::Milliseconds(1001);
|
||||
base::TimeTicks processing_end = GetTimeOrigin() + base::Milliseconds(1002);
|
||||
@ -434,7 +427,7 @@ TEST_P(WindowPerformanceTest, EventTimingDuration) {
|
||||
|
||||
// Test the case where multiple events are registered and then their
|
||||
// presentation promise is resolved.
|
||||
TEST_P(WindowPerformanceTest, MultipleEventsThenPresent) {
|
||||
TEST_F(WindowPerformanceTest, MultipleEventsThenPresent) {
|
||||
size_t num_events = 10;
|
||||
for (size_t i = 0; i < num_events; ++i) {
|
||||
base::TimeTicks start_time = GetTimeOrigin() + base::Seconds(i);
|
||||
@ -458,7 +451,7 @@ TEST_P(WindowPerformanceTest, MultipleEventsThenPresent) {
|
||||
|
||||
// Test the case where commit finish timestamps are recorded on all pending
|
||||
// EventTimings.
|
||||
TEST_P(WindowPerformanceTest,
|
||||
TEST_F(WindowPerformanceTest,
|
||||
CommitFinishTimeRecordedOnAllPendingEventTimings) {
|
||||
size_t num_events = 3;
|
||||
for (size_t i = 0; i < num_events; ++i) {
|
||||
@ -484,7 +477,7 @@ TEST_P(WindowPerformanceTest,
|
||||
|
||||
// Test the case where a new commit finish timestamps does not affect previous
|
||||
// EventTiming who has already seen a commit finish.
|
||||
TEST_P(WindowPerformanceTest, NewCommitNotOverwritePreviousEventTimings) {
|
||||
TEST_F(WindowPerformanceTest, NewCommitNotOverwritePreviousEventTimings) {
|
||||
base::TimeTicks start_time = GetTimeOrigin() + base::Seconds(1);
|
||||
base::TimeTicks processing_start = start_time + base::Milliseconds(100);
|
||||
base::TimeTicks processing_end = start_time + base::Milliseconds(200);
|
||||
@ -512,7 +505,7 @@ TEST_P(WindowPerformanceTest, NewCommitNotOverwritePreviousEventTimings) {
|
||||
}
|
||||
|
||||
// Test for existence of 'first-input' given different types of first events.
|
||||
TEST_P(WindowPerformanceTest, FirstInput) {
|
||||
TEST_F(WindowPerformanceTest, FirstInput) {
|
||||
struct {
|
||||
AtomicString event_type;
|
||||
bool should_report;
|
||||
@ -546,7 +539,7 @@ TEST_P(WindowPerformanceTest, FirstInput) {
|
||||
|
||||
// Test that the 'first-input' is populated after some irrelevant events are
|
||||
// ignored.
|
||||
TEST_P(WindowPerformanceTest, FirstInputAfterIgnored) {
|
||||
TEST_F(WindowPerformanceTest, FirstInputAfterIgnored) {
|
||||
AtomicString several_events[] = {event_type_names::kMouseover,
|
||||
event_type_names::kMousedown,
|
||||
event_type_names::kPointerup};
|
||||
@ -567,7 +560,7 @@ TEST_P(WindowPerformanceTest, FirstInputAfterIgnored) {
|
||||
}
|
||||
|
||||
// Test that pointerdown followed by pointerup works as a 'firstInput'.
|
||||
TEST_P(WindowPerformanceTest, FirstPointerUp) {
|
||||
TEST_F(WindowPerformanceTest, FirstPointerUp) {
|
||||
base::TimeTicks start_time = GetTimeStamp(0);
|
||||
base::TimeTicks processing_start = GetTimeStamp(1);
|
||||
base::TimeTicks processing_end = GetTimeStamp(2);
|
||||
@ -593,7 +586,7 @@ TEST_P(WindowPerformanceTest, FirstPointerUp) {
|
||||
|
||||
// When the pointerdown is optimized out, the mousedown works as a
|
||||
// 'first-input'.
|
||||
TEST_P(WindowPerformanceTest, PointerdownOptimizedOut) {
|
||||
TEST_F(WindowPerformanceTest, PointerdownOptimizedOut) {
|
||||
base::TimeTicks start_time = GetTimeStamp(0);
|
||||
base::TimeTicks processing_start = GetTimeStamp(1);
|
||||
base::TimeTicks processing_end = GetTimeStamp(2);
|
||||
@ -613,7 +606,7 @@ TEST_P(WindowPerformanceTest, PointerdownOptimizedOut) {
|
||||
|
||||
// Test that pointerdown followed by mousedown, pointerup works as a
|
||||
// 'first-input'.
|
||||
TEST_P(WindowPerformanceTest, PointerdownOnDesktop) {
|
||||
TEST_F(WindowPerformanceTest, PointerdownOnDesktop) {
|
||||
base::TimeTicks start_time = GetTimeStamp(0);
|
||||
base::TimeTicks processing_start = GetTimeStamp(1);
|
||||
base::TimeTicks processing_end = GetTimeStamp(2);
|
||||
@ -643,7 +636,7 @@ TEST_P(WindowPerformanceTest, PointerdownOnDesktop) {
|
||||
.size());
|
||||
}
|
||||
|
||||
TEST_P(WindowPerformanceTest, OneKeyboardInteraction) {
|
||||
TEST_F(WindowPerformanceTest, OneKeyboardInteraction) {
|
||||
base::TimeTicks keydown_timestamp = GetTimeStamp(0);
|
||||
// Keydown
|
||||
base::TimeTicks processing_start_keydown = GetTimeStamp(1);
|
||||
@ -693,7 +686,7 @@ TEST_P(WindowPerformanceTest, OneKeyboardInteraction) {
|
||||
"Blink.Responsiveness.UserInteraction.MaxEventDuration.Drag", 0);
|
||||
}
|
||||
|
||||
TEST_P(WindowPerformanceTest, HoldingDownAKey) {
|
||||
TEST_F(WindowPerformanceTest, HoldingDownAKey) {
|
||||
auto entries = GetUkmRecorder()->GetEntriesByName(
|
||||
ukm::builders::Responsiveness_UserInteraction::kEntryName);
|
||||
EXPECT_EQ(0u, entries.size());
|
||||
@ -773,7 +766,7 @@ TEST_P(WindowPerformanceTest, HoldingDownAKey) {
|
||||
"Blink.Responsiveness.UserInteraction.MaxEventDuration.Drag", 0);
|
||||
}
|
||||
|
||||
TEST_P(WindowPerformanceTest, PressMultipleKeys) {
|
||||
TEST_F(WindowPerformanceTest, PressMultipleKeys) {
|
||||
auto entries = GetUkmRecorder()->GetEntriesByName(
|
||||
ukm::builders::Responsiveness_UserInteraction::kEntryName);
|
||||
EXPECT_EQ(0u, entries.size());
|
||||
@ -847,7 +840,7 @@ TEST_P(WindowPerformanceTest, PressMultipleKeys) {
|
||||
// Test a real world scenario, where keydown got presented first but its
|
||||
// callback got invoked later than keyup's due to multi processes & threading
|
||||
// overhead.
|
||||
TEST_P(WindowPerformanceTest, KeyupFinishLastButCallbackInvokedFirst) {
|
||||
TEST_F(WindowPerformanceTest, KeyupFinishLastButCallbackInvokedFirst) {
|
||||
// Arbitrary keycode picked for testing from
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode#value_of_keycode
|
||||
int digit_1_key_code = 0x31;
|
||||
@ -908,7 +901,7 @@ TEST_P(WindowPerformanceTest, KeyupFinishLastButCallbackInvokedFirst) {
|
||||
"Blink.Responsiveness.UserInteraction.MaxEventDuration.Drag", 0);
|
||||
}
|
||||
|
||||
TEST_P(WindowPerformanceTest, TapOrClick) {
|
||||
TEST_F(WindowPerformanceTest, TapOrClick) {
|
||||
// Pointerdown
|
||||
base::TimeTicks pointerdown_timestamp = GetTimeOrigin();
|
||||
base::TimeTicks processing_start_pointerdown = GetTimeStamp(1);
|
||||
@ -968,7 +961,7 @@ TEST_P(WindowPerformanceTest, TapOrClick) {
|
||||
"Blink.Responsiveness.UserInteraction.MaxEventDuration.Drag", 0);
|
||||
}
|
||||
|
||||
TEST_P(WindowPerformanceTest, PageVisibilityChanged) {
|
||||
TEST_F(WindowPerformanceTest, PageVisibilityChanged) {
|
||||
// Pointerdown
|
||||
base::TimeTicks pointerdown_timestamp = GetTimeOrigin();
|
||||
base::TimeTicks processing_start_pointerdown = GetTimeStamp(1);
|
||||
@ -1033,7 +1026,7 @@ TEST_P(WindowPerformanceTest, PageVisibilityChanged) {
|
||||
EXPECT_EQ(1ul, performance_->interactionCount());
|
||||
}
|
||||
|
||||
TEST_P(WindowPerformanceTest, Drag) {
|
||||
TEST_F(WindowPerformanceTest, Drag) {
|
||||
// Pointerdown
|
||||
base::TimeTicks pointerdwon_timestamp = GetTimeOrigin();
|
||||
base::TimeTicks processing_start_pointerdown = GetTimeStamp(1);
|
||||
@ -1095,7 +1088,7 @@ TEST_P(WindowPerformanceTest, Drag) {
|
||||
"Blink.Responsiveness.UserInteraction.MaxEventDuration.Drag", 1);
|
||||
}
|
||||
|
||||
TEST_P(WindowPerformanceTest, Scroll) {
|
||||
TEST_F(WindowPerformanceTest, Scroll) {
|
||||
// Pointerdown
|
||||
base::TimeTicks pointerdown_timestamp = GetTimeOrigin();
|
||||
base::TimeTicks processing_start_keydown = GetTimeStamp(1);
|
||||
@ -1135,7 +1128,7 @@ TEST_P(WindowPerformanceTest, Scroll) {
|
||||
"Blink.Responsiveness.UserInteraction.MaxEventDuration.Drag", 0);
|
||||
}
|
||||
|
||||
TEST_P(WindowPerformanceTest, TouchesWithoutClick) {
|
||||
TEST_F(WindowPerformanceTest, TouchesWithoutClick) {
|
||||
base::TimeTicks pointerdown_timestamp = GetTimeOrigin();
|
||||
// First Pointerdown
|
||||
base::TimeTicks processing_start_pointerdown = GetTimeStamp(1);
|
||||
@ -1170,7 +1163,7 @@ TEST_P(WindowPerformanceTest, TouchesWithoutClick) {
|
||||
// Test artificial pointerup and click on MacOS fall back to use processingEnd
|
||||
// as event duration ending time.
|
||||
// See crbug.com/1321819
|
||||
TEST_P(WindowPerformanceTest, ArtificialPointerupOrClick) {
|
||||
TEST_F(WindowPerformanceTest, ArtificialPointerupOrClick) {
|
||||
// Arbitrary pointerId picked for testing
|
||||
PointerId pointer_id = 4;
|
||||
|
||||
@ -1235,7 +1228,7 @@ TEST_P(WindowPerformanceTest, ArtificialPointerupOrClick) {
|
||||
|
||||
// The trace_analyzer does not work on platforms on which the migration of
|
||||
// tracing into Perfetto has not completed.
|
||||
TEST_P(WindowPerformanceTest, PerformanceMarkTraceEvent) {
|
||||
TEST_F(WindowPerformanceTest, PerformanceMarkTraceEvent) {
|
||||
v8::HandleScope handle_scope(GetScriptState()->GetIsolate());
|
||||
v8::Local<v8::Context> context = GetScriptState()->GetContext();
|
||||
v8::Context::Scope context_scope(context);
|
||||
@ -1270,7 +1263,7 @@ TEST_P(WindowPerformanceTest, PerformanceMarkTraceEvent) {
|
||||
ASSERT_TRUE(navigation_id);
|
||||
}
|
||||
|
||||
TEST_P(WindowPerformanceTest, ElementTimingTraceEvent) {
|
||||
TEST_F(WindowPerformanceTest, ElementTimingTraceEvent) {
|
||||
using trace_analyzer::Query;
|
||||
trace_analyzer::Start("*");
|
||||
// |element| needs to be non-null to prevent a crash.
|
||||
@ -1311,7 +1304,7 @@ TEST_P(WindowPerformanceTest, ElementTimingTraceEvent) {
|
||||
EXPECT_EQ(*url, "url");
|
||||
}
|
||||
|
||||
TEST_P(WindowPerformanceTest, EventTimingTraceEvents) {
|
||||
TEST_F(WindowPerformanceTest, EventTimingTraceEvents) {
|
||||
using trace_analyzer::Query;
|
||||
trace_analyzer::Start("*");
|
||||
base::TimeTicks start_time = GetTimeOrigin() + base::Seconds(1);
|
||||
@ -1410,7 +1403,7 @@ TEST_P(WindowPerformanceTest, EventTimingTraceEvents) {
|
||||
EXPECT_FALSE(click_begin->other_event->HasDictArg("data"));
|
||||
}
|
||||
|
||||
TEST_P(WindowPerformanceTest, SlowInteractionToNextPaintTraceEvents) {
|
||||
TEST_F(WindowPerformanceTest, SlowInteractionToNextPaintTraceEvents) {
|
||||
using trace_analyzer::Query;
|
||||
trace_analyzer::Start("*");
|
||||
|
||||
@ -1528,7 +1521,7 @@ TEST_P(WindowPerformanceTest, SlowInteractionToNextPaintTraceEvents) {
|
||||
EXPECT_EQ(base::ClampRound(events[2]->GetAbsTimeToOtherEvent()), 600000);
|
||||
}
|
||||
|
||||
TEST_P(WindowPerformanceTest, InteractionID) {
|
||||
TEST_F(WindowPerformanceTest, InteractionID) {
|
||||
// Keyboard with max duration 25, total duration 40.
|
||||
PerformanceEventTiming* keydown_entry =
|
||||
CreatePerformanceEventTiming(event_type_names::kKeydown, 1, std::nullopt,
|
||||
@ -1618,8 +1611,6 @@ TEST_P(WindowPerformanceTest, InteractionID) {
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(All, WindowPerformanceTest, ::testing::Bool());
|
||||
|
||||
class InteractionIdTest : public WindowPerformanceTest {
|
||||
public:
|
||||
struct EventForInteraction {
|
||||
@ -1693,7 +1684,7 @@ class InteractionIdTest : public WindowPerformanceTest {
|
||||
};
|
||||
|
||||
// Tests English typing.
|
||||
TEST_P(InteractionIdTest, InputOutsideComposition) {
|
||||
TEST_F(InteractionIdTest, InputOutsideComposition) {
|
||||
// Insert "a" with a max duration of 50 and total of 50.
|
||||
std::vector<EventForInteraction> events1 = {
|
||||
{event_type_names::kKeydown, 65, std::nullopt, GetTimeStamp(100),
|
||||
@ -1745,7 +1736,7 @@ TEST_P(InteractionIdTest, InputOutsideComposition) {
|
||||
}
|
||||
|
||||
// Tests Japanese on Mac.
|
||||
TEST_P(InteractionIdTest, CompositionSingleKeydown) {
|
||||
TEST_F(InteractionIdTest, CompositionSingleKeydown) {
|
||||
// Insert "a" with a duration of 20.
|
||||
std::vector<EventForInteraction> events1 = {
|
||||
{event_type_names::kKeydown, 229, std::nullopt, GetTimeStamp(100),
|
||||
@ -1770,49 +1761,31 @@ TEST_P(InteractionIdTest, CompositionSingleKeydown) {
|
||||
{event_type_names::kCompositionend, std::nullopt, std::nullopt}};
|
||||
std::vector<uint32_t> ids2 = SimulateInteractionIds(events2);
|
||||
|
||||
if (base::FeatureList::IsEnabled(
|
||||
features::kEventTimingKeypressAndCompositionInteractionId)) {
|
||||
performance_->GetResponsivenessMetrics().FlushAllEventsForTesting();
|
||||
performance_->GetResponsivenessMetrics().FlushAllEventsForTesting();
|
||||
|
||||
EXPECT_GT(ids1[0], 0u) << "Keydown interactionId was nonzero";
|
||||
EXPECT_EQ(ids1[1], 0u) << "Compositionstart interactionId was zero";
|
||||
EXPECT_GT(ids1[3], 0u) << "Input interactionId was nonzero";
|
||||
EXPECT_GT(ids1[4], 0u) << "Keyup interactionId was nonzero";
|
||||
EXPECT_EQ(ids1[0], ids1[3])
|
||||
<< "Keydown and Input have the same interactionIds";
|
||||
EXPECT_GT(ids1[0], 0u) << "Keydown interactionId was nonzero";
|
||||
EXPECT_EQ(ids1[1], 0u) << "Compositionstart interactionId was zero";
|
||||
EXPECT_GT(ids1[3], 0u) << "Input interactionId was nonzero";
|
||||
EXPECT_GT(ids1[4], 0u) << "Keyup interactionId was nonzero";
|
||||
EXPECT_EQ(ids1[0], ids1[3])
|
||||
<< "Keydown and Input have the same interactionIds";
|
||||
|
||||
EXPECT_GT(ids2[0], 0u) << "Second keydown interactionId was nonzero";
|
||||
EXPECT_GT(ids2[2], 0u) << "Second input interactionId was nonzero";
|
||||
EXPECT_GT(ids2[3], 0u) << "Second keyup interactionId was non zero";
|
||||
EXPECT_EQ(ids2[4], 0u) << "Compositionend interactionId was zero";
|
||||
EXPECT_EQ(ids2[0], ids2[2])
|
||||
<< "Keydown and Input have the same interactionIds";
|
||||
EXPECT_NE(ids1[3], ids2[2])
|
||||
<< "First and second inputs have different interactionIds";
|
||||
EXPECT_GT(ids2[0], 0u) << "Second keydown interactionId was nonzero";
|
||||
EXPECT_GT(ids2[2], 0u) << "Second input interactionId was nonzero";
|
||||
EXPECT_GT(ids2[3], 0u) << "Second keyup interactionId was non zero";
|
||||
EXPECT_EQ(ids2[4], 0u) << "Compositionend interactionId was zero";
|
||||
EXPECT_EQ(ids2[0], ids2[2])
|
||||
<< "Keydown and Input have the same interactionIds";
|
||||
EXPECT_NE(ids1[3], ids2[2])
|
||||
<< "First and second inputs have different interactionIds";
|
||||
|
||||
CheckUKMValues({{100, 120, UserInteractionType::kKeyboard},
|
||||
{100, 170, UserInteractionType::kKeyboard}});
|
||||
} else {
|
||||
EXPECT_EQ(ids1[0], 0u) << "Keydown interactionId was zero";
|
||||
EXPECT_EQ(ids1[1], 0u) << "Compositionstart interactionId was zero";
|
||||
EXPECT_GT(ids1[3], 0u) << "Input interactionId was nonzero";
|
||||
EXPECT_EQ(ids1[4], 0u) << "Keyup interactionId was zero";
|
||||
|
||||
EXPECT_EQ(ids2[0], 0u) << "Second keydown interactionId was zero";
|
||||
EXPECT_GT(ids2[2], 0u) << "Second input interactionId was nonzero";
|
||||
EXPECT_EQ(ids2[3], 0u) << "Second keyup interactionId was zero";
|
||||
EXPECT_EQ(ids2[4], 0u) << "Compositionend interactionId was zero";
|
||||
EXPECT_NE(ids1[3], ids2[2])
|
||||
<< "First and second inputs have different interactionIds";
|
||||
|
||||
CheckUKMValues({{20, 20, UserInteractionType::kKeyboard},
|
||||
{30, 30, UserInteractionType::kKeyboard}});
|
||||
}
|
||||
CheckUKMValues({{100, 120, UserInteractionType::kKeyboard},
|
||||
{100, 170, UserInteractionType::kKeyboard}});
|
||||
}
|
||||
|
||||
// Tests Chinese on Mac. Windows is similar, but has more keyups inside the
|
||||
// composition.
|
||||
TEST_P(InteractionIdTest, CompositionToFinalInput) {
|
||||
TEST_F(InteractionIdTest, CompositionToFinalInput) {
|
||||
// Insert "a" with a duration of 25.
|
||||
std::vector<EventForInteraction> events1 = {
|
||||
{event_type_names::kKeydown, 229, std::nullopt, GetTimeStamp(100),
|
||||
@ -1854,22 +1827,15 @@ TEST_P(InteractionIdTest, CompositionToFinalInput) {
|
||||
EXPECT_NE(ids2[2], ids3[1])
|
||||
<< "Second and third inputs have different interactionIds";
|
||||
|
||||
if (base::FeatureList::IsEnabled(
|
||||
features::kEventTimingKeypressAndCompositionInteractionId)) {
|
||||
performance_->GetResponsivenessMetrics().FlushAllEventsForTesting();
|
||||
performance_->GetResponsivenessMetrics().FlushAllEventsForTesting();
|
||||
|
||||
CheckUKMValues({{90, 90, UserInteractionType::kKeyboard},
|
||||
{90, 90, UserInteractionType::kKeyboard},
|
||||
{140, 140, UserInteractionType::kKeyboard}});
|
||||
} else {
|
||||
CheckUKMValues({{25, 25, UserInteractionType::kKeyboard},
|
||||
{35, 35, UserInteractionType::kKeyboard},
|
||||
{140, 140, UserInteractionType::kKeyboard}});
|
||||
}
|
||||
CheckUKMValues({{90, 90, UserInteractionType::kKeyboard},
|
||||
{90, 90, UserInteractionType::kKeyboard},
|
||||
{140, 140, UserInteractionType::kKeyboard}});
|
||||
}
|
||||
|
||||
// Tests Chinese on Windows.
|
||||
TEST_P(InteractionIdTest, CompositionToFinalInputMultipleKeyUps) {
|
||||
TEST_F(InteractionIdTest, CompositionToFinalInputMultipleKeyUps) {
|
||||
// Insert "a" with a duration of 66.
|
||||
std::vector<EventForInteraction> events1 = {
|
||||
{event_type_names::kKeydown, 229, std::nullopt, GetTimeStamp(0),
|
||||
@ -1905,52 +1871,29 @@ TEST_P(InteractionIdTest, CompositionToFinalInputMultipleKeyUps) {
|
||||
{event_type_names::kCompositionend, std::nullopt, std::nullopt}};
|
||||
std::vector<uint32_t> ids3 = SimulateInteractionIds(events3);
|
||||
|
||||
if (base::FeatureList::IsEnabled(
|
||||
features::kEventTimingKeypressAndCompositionInteractionId)) {
|
||||
performance_->GetResponsivenessMetrics().FlushAllEventsForTesting();
|
||||
EXPECT_GT(ids1[3], 0u) << "First input nonzero";
|
||||
EXPECT_GT(ids1[4], 0u) << "First keyup has nonzero interactionId";
|
||||
EXPECT_GT(ids1[5], 0u) << "Second keyup has nonzero interactionId";
|
||||
performance_->GetResponsivenessMetrics().FlushAllEventsForTesting();
|
||||
EXPECT_GT(ids1[3], 0u) << "First input nonzero";
|
||||
EXPECT_GT(ids1[4], 0u) << "First keyup has nonzero interactionId";
|
||||
EXPECT_GT(ids1[5], 0u) << "Second keyup has nonzero interactionId";
|
||||
|
||||
EXPECT_GT(ids2[2], 0u) << "Second input nonzero";
|
||||
EXPECT_NE(ids1[3], ids2[2])
|
||||
<< "First and second input have different interactionIds";
|
||||
EXPECT_GT(ids2[3], 0u) << "Third keyup has nonzero interactionId";
|
||||
EXPECT_GT(ids2[4], 0u) << "Fourth keyup has nonzero interactionId";
|
||||
EXPECT_GT(ids2[2], 0u) << "Second input nonzero";
|
||||
EXPECT_NE(ids1[3], ids2[2])
|
||||
<< "First and second input have different interactionIds";
|
||||
EXPECT_GT(ids2[3], 0u) << "Third keyup has nonzero interactionId";
|
||||
EXPECT_GT(ids2[4], 0u) << "Fourth keyup has nonzero interactionId";
|
||||
|
||||
EXPECT_GT(ids3[1], 0u) << "Third input has nonzero interactionId";
|
||||
EXPECT_NE(ids1[3], ids3[1])
|
||||
<< "First and third inputs have different interactionIds";
|
||||
EXPECT_NE(ids2[2], ids3[1])
|
||||
<< "Second and third inputs have different interactionIds";
|
||||
CheckUKMValues({{100, 100, UserInteractionType::kKeyboard},
|
||||
{100, 100, UserInteractionType::kKeyboard},
|
||||
{85, 85, UserInteractionType::kKeyboard}});
|
||||
} else {
|
||||
EXPECT_GT(ids1[3], 0u) << "First input nonzero";
|
||||
EXPECT_EQ(ids1[4], 0u) << "First keyup has zero interactionId";
|
||||
EXPECT_EQ(ids1[5], 0u) << "Second keyup has zero interactionId";
|
||||
|
||||
EXPECT_GT(ids2[2], 0u) << "Second input nonzero";
|
||||
EXPECT_NE(ids1[3], ids2[2])
|
||||
<< "First and second input have different interactionIds";
|
||||
EXPECT_EQ(ids2[3], 0u) << "Third keyup has zero interactionId";
|
||||
EXPECT_EQ(ids2[4], 0u) << "Fourth keyup has zero interactionId";
|
||||
|
||||
EXPECT_GT(ids3[1], 0u) << "Third input has nonzero interactionId";
|
||||
EXPECT_NE(ids1[3], ids3[1])
|
||||
<< "First and third inputs have different interactionIds";
|
||||
EXPECT_NE(ids2[2], ids3[1])
|
||||
<< "Second and third inputs have different interactionIds";
|
||||
|
||||
CheckUKMValues({{66, 66, UserInteractionType::kKeyboard},
|
||||
{51, 51, UserInteractionType::kKeyboard},
|
||||
{85, 85, UserInteractionType::kKeyboard}});
|
||||
}
|
||||
EXPECT_GT(ids3[1], 0u) << "Third input has nonzero interactionId";
|
||||
EXPECT_NE(ids1[3], ids3[1])
|
||||
<< "First and third inputs have different interactionIds";
|
||||
EXPECT_NE(ids2[2], ids3[1])
|
||||
<< "Second and third inputs have different interactionIds";
|
||||
CheckUKMValues({{100, 100, UserInteractionType::kKeyboard},
|
||||
{100, 100, UserInteractionType::kKeyboard},
|
||||
{85, 85, UserInteractionType::kKeyboard}});
|
||||
}
|
||||
|
||||
// Tests Android smart suggestions (similar to Android Chinese).
|
||||
TEST_P(InteractionIdTest, SmartSuggestion) {
|
||||
TEST_F(InteractionIdTest, SmartSuggestion) {
|
||||
// Insert "A" with a duration of 9.
|
||||
std::vector<EventForInteraction> events1 = {
|
||||
{event_type_names::kKeydown, 229, std::nullopt, GetTimeStamp(0),
|
||||
@ -1982,42 +1925,24 @@ TEST_P(InteractionIdTest, SmartSuggestion) {
|
||||
GetTimeStamp(270)}};
|
||||
std::vector<uint32_t> ids3 = SimulateInteractionIds(events3);
|
||||
|
||||
if (base::FeatureList::IsEnabled(
|
||||
features::kEventTimingKeypressAndCompositionInteractionId)) {
|
||||
performance_->GetResponsivenessMetrics().FlushAllEventsForTesting();
|
||||
EXPECT_GT(ids1[3], 0u) << "First input nonzero";
|
||||
EXPECT_EQ(ids1[0], ids1[3]) << "Keydown and input have the same id";
|
||||
EXPECT_EQ(ids1[0], ids1[3]) << "Keydown and keyup have the same id";
|
||||
performance_->GetResponsivenessMetrics().FlushAllEventsForTesting();
|
||||
EXPECT_GT(ids1[3], 0u) << "First input nonzero";
|
||||
EXPECT_EQ(ids1[0], ids1[3]) << "Keydown and input have the same id";
|
||||
EXPECT_EQ(ids1[0], ids1[3]) << "Keydown and keyup have the same id";
|
||||
|
||||
EXPECT_GT(ids2[1], 0u) << "Second input nonzero";
|
||||
EXPECT_NE(ids1[3], ids2[1])
|
||||
<< "First and second input have different interactionIds";
|
||||
EXPECT_GT(ids3[0], 0u) << "Keydown nonzero";
|
||||
EXPECT_EQ(ids3[0], ids3[2]) << "Keydown and keyup have some id";
|
||||
EXPECT_EQ(ids3[1], 0u) << "Third input has zero id";
|
||||
EXPECT_GT(ids2[1], 0u) << "Second input nonzero";
|
||||
EXPECT_NE(ids1[3], ids2[1])
|
||||
<< "First and second input have different interactionIds";
|
||||
EXPECT_GT(ids3[0], 0u) << "Keydown nonzero";
|
||||
EXPECT_EQ(ids3[0], ids3[2]) << "Keydown and keyup have some id";
|
||||
EXPECT_EQ(ids3[1], 0u) << "Third input has zero id";
|
||||
|
||||
CheckUKMValues({{16, 16, UserInteractionType::kKeyboard},
|
||||
{14, 14, UserInteractionType::kKeyboard},
|
||||
{43, 70, UserInteractionType::kKeyboard}});
|
||||
|
||||
} else {
|
||||
EXPECT_GT(ids1[3], 0u) << "First input nonzero";
|
||||
|
||||
EXPECT_GT(ids2[1], 0u) << "Second input nonzero";
|
||||
EXPECT_NE(ids1[3], ids2[1])
|
||||
<< "First and second input have different interactionIds";
|
||||
|
||||
EXPECT_GT(ids3[0], 0u) << "Keydown nonzero";
|
||||
EXPECT_EQ(ids3[0], ids3[2]) << "Keydown and keyup have some id";
|
||||
EXPECT_EQ(ids3[1], 0u) << "Third input has zero id";
|
||||
|
||||
CheckUKMValues({{9, 9, UserInteractionType::kKeyboard},
|
||||
{14, 14, UserInteractionType::kKeyboard},
|
||||
{43, 70, UserInteractionType::kKeyboard}});
|
||||
}
|
||||
CheckUKMValues({{16, 16, UserInteractionType::kKeyboard},
|
||||
{14, 14, UserInteractionType::kKeyboard},
|
||||
{43, 70, UserInteractionType::kKeyboard}});
|
||||
}
|
||||
|
||||
TEST_P(InteractionIdTest, TapWithoutClick) {
|
||||
TEST_F(InteractionIdTest, TapWithoutClick) {
|
||||
std::vector<EventForInteraction> events = {
|
||||
{event_type_names::kPointerdown, std::nullopt, 1, GetTimeStamp(100),
|
||||
GetTimeStamp(140)},
|
||||
@ -2038,7 +1963,7 @@ TEST_P(InteractionIdTest, TapWithoutClick) {
|
||||
CheckUKMValues({{40, 50, UserInteractionType::kTapOrClick}});
|
||||
}
|
||||
|
||||
TEST_P(InteractionIdTest, PointerupClick) {
|
||||
TEST_F(InteractionIdTest, PointerupClick) {
|
||||
std::vector<EventForInteraction> events = {
|
||||
{event_type_names::kPointerup, std::nullopt, 1, GetTimeStamp(100),
|
||||
GetTimeStamp(140)},
|
||||
@ -2052,7 +1977,7 @@ TEST_P(InteractionIdTest, PointerupClick) {
|
||||
CheckUKMValues({{30, 30, UserInteractionType::kTapOrClick}});
|
||||
}
|
||||
|
||||
TEST_P(InteractionIdTest, JustClick) {
|
||||
TEST_F(InteractionIdTest, JustClick) {
|
||||
// Hitting enter on a keyboard may cause just a trusted click event.
|
||||
std::vector<EventForInteraction> events = {
|
||||
{event_type_names::kClick, std::nullopt, 0, GetTimeStamp(120),
|
||||
@ -2064,7 +1989,7 @@ TEST_P(InteractionIdTest, JustClick) {
|
||||
CheckUKMValues({{30, 30, UserInteractionType::kTapOrClick}});
|
||||
}
|
||||
|
||||
TEST_P(InteractionIdTest, PointerdownClick) {
|
||||
TEST_F(InteractionIdTest, PointerdownClick) {
|
||||
// Contextmenus may cause us to only see pointerdown and click (no pointerup).
|
||||
std::vector<EventForInteraction> events = {
|
||||
{event_type_names::kPointerdown, std::nullopt, 1, GetTimeStamp(100),
|
||||
@ -2079,7 +2004,7 @@ TEST_P(InteractionIdTest, PointerdownClick) {
|
||||
CheckUKMValues({{40, 50, UserInteractionType::kTapOrClick}});
|
||||
}
|
||||
|
||||
TEST_P(InteractionIdTest, MultiTouch) {
|
||||
TEST_F(InteractionIdTest, MultiTouch) {
|
||||
// In multitouch, we report an interaction per pointerId. We do not see
|
||||
// clicks.
|
||||
std::vector<EventForInteraction> events = {
|
||||
@ -2104,7 +2029,7 @@ TEST_P(InteractionIdTest, MultiTouch) {
|
||||
{50, 60, UserInteractionType::kTapOrClick}});
|
||||
}
|
||||
|
||||
TEST_P(InteractionIdTest, ClickIncorrectPointerId) {
|
||||
TEST_F(InteractionIdTest, ClickIncorrectPointerId) {
|
||||
// On mobile, in cases where touchstart is skipped, click does not get the
|
||||
// correct pointerId. See crbug.com/1264930 for more details.
|
||||
// TODO crbug.com/359679950: remove this test and event timing workaround
|
||||
@ -2122,6 +2047,4 @@ TEST_P(InteractionIdTest, ClickIncorrectPointerId) {
|
||||
CheckUKMValues({{40, 40, UserInteractionType::kTapOrClick}});
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(All, InteractionIdTest, ::testing::Bool());
|
||||
|
||||
} // namespace blink
|
||||
|
Reference in New Issue
Block a user