Bug 1858434 - Expose getCoalescedEvents only on SecureContext, r=edgar

Differential Revision: https://phabricator.services.mozilla.com/D190740
This commit is contained in:
Olli Pettay 2023-10-13 09:55:37 +00:00
parent 3198f78df5
commit 6235c7d4f9
22 changed files with 237 additions and 38 deletions

View File

@ -11,8 +11,10 @@
#include "mozilla/dom/PointerEventBinding.h"
#include "mozilla/dom/PointerEventHandler.h"
#include "mozilla/MouseEvents.h"
#include "mozilla/StaticPrefs_dom.h"
#include "nsContentUtils.h"
#include "prtime.h"
#include "jsfriendapi.h"
namespace mozilla::dom {
@ -205,6 +207,12 @@ int32_t PointerEvent::Twist() {
bool PointerEvent::IsPrimary() { return mEvent->AsPointerEvent()->mIsPrimary; }
bool PointerEvent::EnableGetCoalescedEvents(JSContext* aCx, JSObject* aGlobal) {
return !StaticPrefs::
dom_w3c_pointer_events_getcoalescedevents_only_in_securecontext() ||
JS::GetIsSecureContext(js::GetContextRealm(aCx));
}
void PointerEvent::GetCoalescedEvents(
nsTArray<RefPtr<PointerEvent>>& aPointerEvents) {
WidgetPointerEvent* widgetEvent = mEvent->AsPointerEvent();

View File

@ -48,6 +48,7 @@ class PointerEvent : public MouseEvent {
int32_t Twist();
bool IsPrimary();
void GetPointerType(nsAString& aPointerType);
static bool EnableGetCoalescedEvents(JSContext* aCx, JSObject* aGlobal);
void GetCoalescedEvents(nsTArray<RefPtr<PointerEvent>>& aPointerEvents);
void GetPredictedEvents(nsTArray<RefPtr<PointerEvent>>& aPointerEvents);

View File

@ -1,5 +1,9 @@
[DEFAULT]
prefs = ["gfx.font_loader.delay=0"]
prefs = [
"gfx.font_loader.delay=0",
"dom.w3c_pointer_events.getcoalescedevents_only_in_securecontext=false"
]
support-files = [
"iframe.html",
"mochitest_support_external.js",

View File

@ -26,6 +26,8 @@ interface PointerEvent : MouseEvent
readonly attribute DOMString pointerType;
readonly attribute boolean isPrimary;
[Func="mozilla::dom::PointerEvent::EnableGetCoalescedEvents"]
sequence<PointerEvent> getCoalescedEvents();
sequence<PointerEvent> getPredictedEvents();
};

View File

@ -4430,6 +4430,11 @@
value: true
mirror: always
- name: dom.w3c_pointer_events.getcoalescedevents_only_in_securecontext
type: bool
value: @IS_NIGHTLY_BUILD@
mirror: always
# In case Touch API is enabled, this pref controls whether to support
# ontouch* event handlers, document.createTouch, document.createTouchList and
# document.createEvent("TouchEvent").

View File

@ -1,2 +1,4 @@
lsan-disabled: true
leak-threshold: [default:153600, tab:307200]
prefs: [dom.w3c_pointer_events.getcoalescedevents_only_in_securecontext:true]

View File

@ -1,4 +1,4 @@
[coalesced_events_attributes.html?pen]
[coalesced_events_attributes.https.html?pen]
[Coalesced list in pointerdown/move/up events]
expected: FAIL
@ -9,7 +9,7 @@
expected: FAIL
[coalesced_events_attributes.html?touch]
[coalesced_events_attributes.https.html?touch]
expected: TIMEOUT
[Coalesced list in pointerdown/move/up events]
expected: FAIL
@ -18,6 +18,6 @@
expected: TIMEOUT
[coalesced_events_attributes.html?mouse]
[coalesced_events_attributes.https.html?mouse]
[Coalesced list in pointerdown/move/up events]
expected: FAIL

View File

@ -1,13 +1,13 @@
[coalesced_events_attributes_under_load.html?touch]
[coalesced_events_attributes_under_load.https.html?touch]
[Coalesced pointermoves under load]
expected: FAIL
[coalesced_events_attributes_under_load.html?pen]
[coalesced_events_attributes_under_load.https.html?pen]
[Coalesced pointermoves under load]
expected: FAIL
[coalesced_events_attributes_under_load.html?mouse]
[coalesced_events_attributes_under_load.https.html?mouse]
[Coalesced pointermoves under load]
expected: FAIL

View File

@ -1,4 +1,4 @@
[idlharness.window.html]
[idlharness.https.window.html]
[Document interface: attribute onpointerrawupdate]
expected: FAIL

View File

@ -1,4 +1,4 @@
[pointerevent_pointerrawupdate.html]
[pointerevent_pointerrawupdate.https.html]
[pointerrawupdate event received]
expected: FAIL

View File

@ -1,4 +1,4 @@
[pointerevent_getCoalescedEvents_when_pointerlocked.html]
[pointerevent_getCoalescedEvents_when_pointerlocked.https.html]
[mouse pointermove getCoalescedEvents when lock test]
expected:
if (os == "linux") and (processor == "x86_64") and fission and debug and not swgl: [FAIL, PASS]

View File

@ -1,4 +1,4 @@
[pointerevent_pointerrawupdate_in_pointerlock.html]
[pointerevent_pointerrawupdate_in_pointerlock.https.html]
expected:
if (os == "win") and debug and (processor == "x86_64") and not swgl: [OK, TIMEOUT]
if (os == "linux"): [OK, TIMEOUT]

View File

@ -329,6 +329,7 @@ GENERATE_TESTS: mediacapture-fromelement/creation.html
GENERATE_TESTS: mediacapture-fromelement/ended.html
GENERATE_TESTS: html/canvas/offscreen/manual/filter/offscreencanvas.filter.html
GENERATE_TESTS: pointerevents/pointerevent_constructor.html
GENERATE_TESTS: pointerevents/pointerevent_constructor.https.html
GENERATE_TESTS: pointerevents/extension/pointerevent_constructor.html
GENERATE_TESTS: selection/collapse.js
GENERATE_TESTS: shadow-dom/leaktests/html-collection.html

View File

@ -18,42 +18,22 @@
// set values for non-default constructor
on_event(target0, "pointermove", this.step_func(function(event) {
generate_tests(assert_equals, [
["getCoalescedEvents().length", event.getCoalescedEvents().length, 2],
["getCoalescedEvents in event", "getCoalescedEvents" in event, false],
["getPredictedEvents().length", event.getPredictedEvents().length, 2],
["event.target", event.target, target0],
["event.currentTarget", event.currentTarget, target0],
["event.eventPhase", event.eventPhase, Event.AT_TARGET],
["event.clientX", event.clientX, 310],
["event.pointerType", event.pointerType, "pen"],
["getCoalescedEvents()[0].clientX", event.getCoalescedEvents()[0].clientX, 300],
["getCoalescedEvents()[1].clientX", event.getCoalescedEvents()[1].clientX, 310],
["getPredictedEvents()[0].clientX", event.getPredictedEvents()[0].clientX, 320],
["getPredictedEvents()[1].clientX", event.getPredictedEvents()[1].clientX, 330],
]);
for (var i=0; i<event.getCoalescedEvents().length; i++) {
var coalescedEvent = event.getCoalescedEvents()[i];
generate_tests(assert_equals, [
["getCoalescedEvents()[" + i + "].pointerId", coalescedEvent.pointerId, event.pointerId],
["getCoalescedEvents()[" + i + "].pointerType", coalescedEvent.pointerType, event.pointerType],
["getCoalescedEvents()[" + i + "].isPrimary", coalescedEvent.isPrimary, event.isPrimary],
["getCoalescedEvents()[" + i + "].getCoalescedEvents().length", coalescedEvent.getCoalescedEvents().length, 0],
["getCoalescedEvents()[" + i + "].getPredictedEvents().length", coalescedEvent.getPredictedEvents().length, 0],
["getCoalescedEvents()[" + i + "].target", coalescedEvent.target, null],
["getCoalescedEvents()[" + i + "].currentTarget", coalescedEvent.currentTarget, null],
["getCoalescedEvents()[" + i + "].eventPhase", coalescedEvent.eventPhase, Event.NONE],
["getCoalescedEvents()[" + i + "].cancelable", coalescedEvent.cancelable, false],
["getCoalescedEvents()[" + i + "].bubbles", coalescedEvent.bubbles, false],
["getCoalescedEvents()[" + i + "].offsetX", coalescedEvent.offsetX, 310 + (i==0?-10:0)],
["getCoalescedEvents()[" + i + "].offsetY", coalescedEvent.offsetY, 0],
]);
}
for (var i=0; i<event.getPredictedEvents().length; i++) {
var predictedEvent = event.getPredictedEvents()[i];
generate_tests(assert_equals, [
["getPredictedEvents()[" + i + "].pointerId", predictedEvent.pointerId, event.pointerId],
["getPredictedEvents()[" + i + "].pointerType", predictedEvent.pointerType, event.pointerType],
["getPredictedEvents()[" + i + "].isPrimary", predictedEvent.isPrimary, event.isPrimary],
["getPredictedEvents()[" + i + "].getCoalescedEvents().length", predictedEvent.getCoalescedEvents().length, 0],
["getPredictedEvents()[" + i + "].getPredictedEvents().length", predictedEvent.getPredictedEvents().length, 0],
["getPredictedEvents()[" + i + "].target", predictedEvent.target, null],
["getPredictedEvents()[" + i + "].currentTarget", predictedEvent.currentTarget, null],
@ -68,7 +48,6 @@
on_event(target0, "pointerout", this.step_func(function(event) {
generate_tests(assert_equals, [
["default event.pointerType", event.pointerType, ""],
["default getCoalescedEvents().length", event.getCoalescedEvents().length, 0],
["default getPredictedEvents().length", event.getPredictedEvents().length, 0],
]);
}));

View File

@ -0,0 +1,118 @@
<!doctype html>
<html>
<head>
<title>PointerEvent: Constructor test</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<!-- Additional helper script for common checks across event types -->
</head>
<body>
<h1>PointerEvent: Dispatch custom event</h1>
<h4>Test Description: This test checks if PointerEvent constructor works properly.</h4>
<div id="target0"></div>
<script>
async_test(function() {
var target0 = document.getElementById("target0");
// set values for non-default constructor
on_event(target0, "pointermove", this.step_func(function(event) {
generate_tests(assert_equals, [
["getCoalescedEvents().length", event.getCoalescedEvents().length, 2],
["getPredictedEvents().length", event.getPredictedEvents().length, 2],
["event.target", event.target, target0],
["event.currentTarget", event.currentTarget, target0],
["event.eventPhase", event.eventPhase, Event.AT_TARGET],
["event.clientX", event.clientX, 310],
["event.pointerType", event.pointerType, "pen"],
["getCoalescedEvents()[0].clientX", event.getCoalescedEvents()[0].clientX, 300],
["getCoalescedEvents()[1].clientX", event.getCoalescedEvents()[1].clientX, 310],
["getPredictedEvents()[0].clientX", event.getPredictedEvents()[0].clientX, 320],
["getPredictedEvents()[1].clientX", event.getPredictedEvents()[1].clientX, 330],
]);
for (var i=0; i<event.getCoalescedEvents().length; i++) {
var coalescedEvent = event.getCoalescedEvents()[i];
generate_tests(assert_equals, [
["getCoalescedEvents()[" + i + "].pointerId", coalescedEvent.pointerId, event.pointerId],
["getCoalescedEvents()[" + i + "].pointerType", coalescedEvent.pointerType, event.pointerType],
["getCoalescedEvents()[" + i + "].isPrimary", coalescedEvent.isPrimary, event.isPrimary],
["getCoalescedEvents()[" + i + "].getCoalescedEvents().length", coalescedEvent.getCoalescedEvents().length, 0],
["getCoalescedEvents()[" + i + "].getPredictedEvents().length", coalescedEvent.getPredictedEvents().length, 0],
["getCoalescedEvents()[" + i + "].target", coalescedEvent.target, null],
["getCoalescedEvents()[" + i + "].currentTarget", coalescedEvent.currentTarget, null],
["getCoalescedEvents()[" + i + "].eventPhase", coalescedEvent.eventPhase, Event.NONE],
["getCoalescedEvents()[" + i + "].cancelable", coalescedEvent.cancelable, false],
["getCoalescedEvents()[" + i + "].bubbles", coalescedEvent.bubbles, false],
["getCoalescedEvents()[" + i + "].offsetX", coalescedEvent.offsetX, 310 + (i==0?-10:0)],
["getCoalescedEvents()[" + i + "].offsetY", coalescedEvent.offsetY, 0],
]);
}
for (var i=0; i<event.getPredictedEvents().length; i++) {
var predictedEvent = event.getPredictedEvents()[i];
generate_tests(assert_equals, [
["getPredictedEvents()[" + i + "].pointerId", predictedEvent.pointerId, event.pointerId],
["getPredictedEvents()[" + i + "].pointerType", predictedEvent.pointerType, event.pointerType],
["getPredictedEvents()[" + i + "].isPrimary", predictedEvent.isPrimary, event.isPrimary],
["getPredictedEvents()[" + i + "].getCoalescedEvents().length", predictedEvent.getCoalescedEvents().length, 0],
["getPredictedEvents()[" + i + "].getPredictedEvents().length", predictedEvent.getPredictedEvents().length, 0],
["getPredictedEvents()[" + i + "].target", predictedEvent.target, null],
["getPredictedEvents()[" + i + "].currentTarget", predictedEvent.currentTarget, null],
["getPredictedEvents()[" + i + "].eventPhase", predictedEvent.eventPhase, Event.NONE],
["getPredictedEvents()[" + i + "].cancelable", predictedEvent.cancelable, false],
["getPredictedEvents()[" + i + "].bubbles", predictedEvent.bubbles, false],
["getPredictedEvents()[" + i + "].offsetX", predictedEvent.offsetX, 310 + (i==0?10:20)],
["getPredictedEvents()[" + i + "].offsetY", predictedEvent.offsetY, 0],
]);
}
}));
on_event(target0, "pointerout", this.step_func(function(event) {
generate_tests(assert_equals, [
["default event.pointerType", event.pointerType, ""],
["default getCoalescedEvents().length", event.getCoalescedEvents().length, 0],
["default getPredictedEvents().length", event.getPredictedEvents().length, 0],
]);
}));
on_event(target0, "pointerup", this.step_func(function(event) {
generate_tests(assert_equals, [
["type event.pointerType", event.pointerType, "foo"],
]);
}));
on_event(window, "load", this.step_func_done(function() {
assert_not_equals(window.PointerEvent, undefined);
var pointerEventInitDict =
{
pointerId: 42,
pointerType: "pen",
isPrimary: true,
clientX: 300,
};
var p1 = new PointerEvent("pointermove", pointerEventInitDict);
pointerEventInitDict.clientX += 10;
var p2 = new PointerEvent("pointermove", pointerEventInitDict);
pointerEventInitDict.clientX += 10;
var p3 = new PointerEvent("pointermove", pointerEventInitDict);
pointerEventInitDict.clientX += 10;
var p4 = new PointerEvent("pointermove", pointerEventInitDict);
pointerEventInitDict.coalescedEvents = [p1, p2];
pointerEventInitDict.predictedEvents = [p3, p4];
pointerEventInitDict.clientX = 310;
var event = new PointerEvent("pointermove", pointerEventInitDict);
target0.dispatchEvent(event);
var pointerEventDefault = new PointerEvent("pointerout");
target0.dispatchEvent(pointerEventDefault);
var pointerEventType = new PointerEvent("pointerup", { pointerType: "foo" } );
target0.dispatchEvent(pointerEventType);
}, "PointerEvent constructor"));
})
</script>
<div id="complete-notice">
<p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
</div>
<div id="log"></div>
</body>
</html>

View File

@ -14,7 +14,7 @@
</head>
<body onload="run()">
<h2>pointerrawupdate</h2>
<h4>Test Description: This test checks if pointerrawupdate is dispatched correctly. </h4>
<h4>Test Description: This test checks that pointerrawupdate is not dispatched on non-SecureContext. </h4>
<p>Move your mouse within the black box.</p>
<p>Press left button down and then press middle button while holding down left button. Then release the buttons</p>
<div id="target0"></div>
@ -36,8 +36,8 @@
});
on_event(target0, "pointermove", function (event) {
test_pointerrawupdate.step(function() {
assert_true(pointerrawupdateReceived,
"Pointerrawupdate event should have been received before pointermove.");
assert_false(pointerrawupdateReceived,
"Pointerrawupdate event should not have been received before pointermove.");
}, "Pointerrawupdate event should have been received before pointermove.");
});
on_event(target0, "pointerdown", function (event) {
@ -45,9 +45,19 @@
});
on_event(target0, "pointerup", function (event) {
test_pointerrawupdate.step(function() {
assert_true(pointerrawupdateFromButtonChangeReceived,
"Pointerrawupdate event should have been received from chorded button changes.");
assert_false(pointerrawupdateFromButtonChangeReceived,
"Pointerrawupdate event should not have been received from chorded button changes.");
}, "Pointerrawupdate event should have been received from chorded button changes.");
test_pointerrawupdate.step(function() {
assert_false("onpointerrawupdate" in window,
"Window should not have event handler onpointerrawupdate");
assert_false("onpointerrawupdate" in window.document,
"Document should not have event handler onpointerrawupdate");
assert_false("onpointerrawupdate" in window.document.documentElement,
"Element should not have event handler onpointerrawupdate");
}, "onpointerrawupdate should be exposed only in SecureContext");
// Make sure the test finishes after all the input actions are completed.
actions_promise.then( () => {
test_pointerrawupdate.done();

View File

@ -0,0 +1,69 @@
<!doctype html>
<html>
<head>
<title>pointerrawupdate</title>
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-actions.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<!-- Additional helper script for common checks across event types -->
<script type="text/javascript" src="pointerevent_support.js"></script>
</head>
<body onload="run()">
<h2>pointerrawupdate</h2>
<h4>Test Description: This test checks if pointerrawupdate is dispatched correctly. </h4>
<p>Move your mouse within the black box.</p>
<p>Press left button down and then press middle button while holding down left button. Then release the buttons</p>
<div id="target0"></div>
<script>
var test_pointerrawupdate = async_test("pointerrawupdate event received");
var actions_promise;
var pointerrawupdateReceived = false;
var pointerdownReceived = false;
var pointerrawupdateFromButtonChangeReceived = false;
function run() {
var target0 = document.getElementById("target0");
on_event(target0, "pointerrawupdate", function (event) {
pointerrawupdateReceived = true;
if (pointerdownReceived && event.button != -1)
pointerrawupdateFromButtonChangeReceived = true;
});
on_event(target0, "pointermove", function (event) {
test_pointerrawupdate.step(function() {
assert_true(pointerrawupdateReceived,
"Pointerrawupdate event should have been received before pointermove.");
}, "Pointerrawupdate event should have been received before pointermove.");
});
on_event(target0, "pointerdown", function (event) {
pointerdownReceived = true;
});
on_event(target0, "pointerup", function (event) {
test_pointerrawupdate.step(function() {
assert_true(pointerrawupdateFromButtonChangeReceived,
"Pointerrawupdate event should have been received from chorded button changes.");
}, "Pointerrawupdate event should have been received from chorded button changes.");
// Make sure the test finishes after all the input actions are completed.
actions_promise.then( () => {
test_pointerrawupdate.done();
});
});
var actions = new test_driver.Actions();
actions_promise = actions.pointerMove(0, 0, {origin: target0, button: actions.ButtonType.LEFT})
.pointerDown({button: actions.ButtonType.LEFT})
.pointerDown({button: actions.ButtonType.MIDDLE})
.pointerUp({button: actions.ButtonType.MIDDLE})
.pointerUp({button: actions.ButtonType.LEFT})
.send();
}
</script>
<div id="complete-notice">
</div>
</body>
</html>