Commit d11fd1ac authored by Ella Ge's avatar Ella Ge Committed by Commit Bot

Add event detail to inspector EventDispatch trace data

To support replay input events (crrev.com/c/1944333).

This CL adds input event's detail information (coordinates, modifiers,
button to trace data, when "devtools.timeline.inputs" category is
enabled.

Change-Id: I73cad86a9922e0a7b494ac0a01f8817e53cf7e26
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1943179Reviewed-by: default avatarMathias Bynens <mathias@chromium.org>
Reviewed-by: default avatarEric Seckler <eseckler@chromium.org>
Reviewed-by: default avatarYang Guo <yangguo@chromium.org>
Commit-Queue: Ella Ge <eirage@chromium.org>
Cr-Commit-Position: refs/heads/master@{#726582}
parent 9b4fc16e
...@@ -171,6 +171,7 @@ ...@@ -171,6 +171,7 @@
X(TRACE_DISABLED_BY_DEFAULT("devtools.screenshot")) \ X(TRACE_DISABLED_BY_DEFAULT("devtools.screenshot")) \
X(TRACE_DISABLED_BY_DEFAULT("devtools.timeline")) \ X(TRACE_DISABLED_BY_DEFAULT("devtools.timeline")) \
X(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.frame")) \ X(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.frame")) \
X(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.inputs")) \
X(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.invalidationTracking")) \ X(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.invalidationTracking")) \
X(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.layers")) \ X(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.layers")) \
X(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.picture")) \ X(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.picture")) \
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
#include "third_party/blink/renderer/core/css/invalidation/invalidation_set.h" #include "third_party/blink/renderer/core/css/invalidation/invalidation_set.h"
#include "third_party/blink/renderer/core/css/style_change_reason.h" #include "third_party/blink/renderer/core/css/style_change_reason.h"
#include "third_party/blink/renderer/core/dom/events/event.h" #include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/events/keyboard_event.h"
#include "third_party/blink/renderer/core/events/wheel_event.h"
#include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h" #include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/html/html_frame_owner_element.h" #include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
...@@ -74,6 +76,20 @@ std::unique_ptr<TracedValue> GetNavigationTracingData(Document* document) { ...@@ -74,6 +76,20 @@ std::unique_ptr<TracedValue> GetNavigationTracingData(Document* document) {
IdentifiersFactory::LoaderId(document->Loader())); IdentifiersFactory::LoaderId(document->Loader()));
return data; return data;
} }
int GetModifierFromEvent(const UIEventWithKeyState& event) {
int modifier = 0;
if (event.altKey())
modifier |= 1;
if (event.ctrlKey())
modifier |= 2;
if (event.metaKey())
modifier |= 4;
if (event.shiftKey())
modifier |= 8;
return modifier;
}
} // namespace } // namespace
String ToHexString(const void* p) { String ToHexString(const void* p) {
...@@ -1284,6 +1300,37 @@ std::unique_ptr<TracedValue> inspector_event_dispatch_event::Data( ...@@ -1284,6 +1300,37 @@ std::unique_ptr<TracedValue> inspector_event_dispatch_event::Data(
const Event& event) { const Event& event) {
auto value = std::make_unique<TracedValue>(); auto value = std::make_unique<TracedValue>();
value->SetString("type", event.type()); value->SetString("type", event.type());
bool record_input_enabled;
TRACE_EVENT_CATEGORY_GROUP_ENABLED(
TRACE_DISABLED_BY_DEFAULT("devtools.timeline.inputs"),
&record_input_enabled);
if (record_input_enabled) {
if (event.IsKeyboardEvent()) {
const KeyboardEvent& keyboard_event = ToKeyboardEvent(event);
value->SetInteger("modifier", GetModifierFromEvent(keyboard_event));
value->SetDouble(
"timestamp",
keyboard_event.PlatformTimeStamp().since_origin().InMicroseconds());
value->SetString("code", keyboard_event.code());
value->SetString("key", keyboard_event.key());
}
if (event.IsMouseEvent() || event.IsWheelEvent()) {
const MouseEvent& mouse_event = ToMouseEvent(event);
value->SetDouble("x", mouse_event.x());
value->SetDouble("y", mouse_event.y());
value->SetInteger("modifier", GetModifierFromEvent(mouse_event));
value->SetDouble(
"timestamp",
mouse_event.PlatformTimeStamp().since_origin().InMicroseconds());
value->SetInteger("button", mouse_event.button());
value->SetInteger("buttons", mouse_event.buttons());
value->SetInteger("clickCount", mouse_event.detail());
if (event.IsWheelEvent()) {
value->SetDouble("deltaX", ToWheelEvent(mouse_event).deltaX());
value->SetDouble("deltaY", ToWheelEvent(mouse_event).deltaY());
}
}
}
SetCallStack(value.get()); SetCallStack(value.get());
return value; return value;
} }
......
Test tracing recording input events detail
Tracing started
Tracing complete
mousedown at 100,100
mousemove at 150,50
mouseup at 150,50
Event sanity test done
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
(async function() {
TestRunner.addResult(`Test tracing recording input events detail\n`);
await TestRunner.loadModule('performance_test_runner');
await TestRunner.loadHTML(`
<style>
div#test {
display: none;
background-color: blue;
width: 100px;
height: 100px;
}
</style>
<div id="test">
</div>
`);
await TestRunner.evaluateInPagePromise(`
function doWork()
{
var element = document.getElementById("test");
element.style.display = "block";
var unused = element.clientWidth;
}
`);
var TracingManagerClient = function(callback) {
this._completionCallback = callback;
this._tracingModel = new SDK.TracingModel(new Bindings.TempFileBackingStorage("tracing"));
}
TracingManagerClient.prototype = {
traceEventsCollected: function(events)
{
this._tracingModel.addEvents(events);
},
tracingComplete: function()
{
TestRunner.addResult("Tracing complete");
this._tracingModel.tracingComplete();
this._completionCallback(this._tracingModel);
},
tracingBufferUsage: function(usage) { },
eventsRetrievalProgress: function(progress) { }
};
var tracingClient = new TracingManagerClient(runEventsSanityCheck);
var tracingManager = TestRunner.tracingManager;
tracingManager.start(tracingClient, 'disabled-by-default-devtools.timeline.inputs', '').then(() => {
TestRunner.addResult('Tracing started');
sendMouseEventToPage('mousePressed', 100, 100).then(function() {
sendMouseEventToPage('mouseMoved', 150, 50)
}).then(function(){
sendMouseEventToPage('mouseReleased', 150, 50)
}).then(
// Wait for roughly 2 frame for event to dispatch.
setTimeout(tracingManager.stop.bind(tracingManager), 32)
);
});
// Simulate a mouse click on point.
function sendMouseEventToPage(type, x, y) {
return TestRunner.InputAgent.invoke_dispatchMouseEvent({
type: type,
x: x,
y: y,
button: "left",
});
}
function runEventsSanityCheck(tracingModel) {
var events = [];
var inputEventCount = 0;
tracingModel.sortedProcesses().forEach(function(process) {
process.sortedThreads().forEach(function(thread) {
events = events.concat(thread.events());
});
});
for (var i = 0; i < events.length; ++i) {
var event = events[i];
if (event.name === 'EventDispatch') {
const mouseEventTypes = new Set(["mousedown", "mouseup", "mousemove"]);
if (mouseEventTypes.has(event.args.data.type)) {
++inputEventCount;
TestRunner.addResult(event.args.data.type + " at " + event.args.data.x + "," + event.args.data.y);
}
}
}
TestRunner.assertGreaterOrEqual(events.length, 100, 'Too few trace events recorded');
TestRunner.assertGreaterOrEqual(inputEventCount, 3, 'Too few input events recorded');
TestRunner.addResult('Event sanity test done');
TestRunner.completeTest();
}
})();
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