Bug 1523351 - Part 2: Add tests for GamepadTouch and GamepadLightIndicator. r=baku

Differential Revision: https://phabricator.services.mozilla.com/D29289

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Daosheng Mu 2019-05-22 05:54:43 +00:00
parent fc365d059b
commit 8b44d0d2b9
15 changed files with 407 additions and 12 deletions

View File

@ -19,6 +19,8 @@ GamepadService.addGamepad(
GamepadService.noHand,
4, // buttons
2,
0,
0,
0).then((aIndex) => new Promise((aResolve) => {
// Press a button to make the gamepad visible to the page.
GamepadService.newButtonEvent(aIndex, 0, true, true);

View File

@ -90,14 +90,14 @@ void GamepadServiceTest::DestroyPBackgroundActor() {
already_AddRefed<Promise> GamepadServiceTest::AddGamepad(
const nsAString& aID, GamepadMappingType aMapping, GamepadHand aHand,
uint32_t aNumButtons, uint32_t aNumAxes, uint32_t aNumHaptics,
ErrorResult& aRv) {
uint32_t aNumLightIndicator, uint32_t aNumTouchEvents, ErrorResult& aRv) {
if (mShuttingDown) {
return nullptr;
}
// Only VR controllers has displayID, we give 0 to the general gamepads.
GamepadAdded a(nsString(aID), aMapping, aHand, 0, aNumButtons, aNumAxes,
aNumHaptics);
aNumHaptics, aNumLightIndicator, aNumTouchEvents);
GamepadChangeEventBody body(a);
GamepadChangeEvent e(0, GamepadServiceType::Standard, body);
@ -246,6 +246,40 @@ void GamepadServiceTest::NewPoseMove(
mChild->SendGamepadTestEvent(id, e);
}
void GamepadServiceTest::NewTouch(uint32_t aIndex, uint32_t aTouchArrayIndex,
uint32_t aTouchId, uint8_t aSurfaceId,
const Float32Array& aPos,
const Nullable<Float32Array>& aSurfDim) {
if (mShuttingDown) {
return;
}
GamepadTouchState touchState;
touchState.touchId = aTouchId;
touchState.surfaceId = aSurfaceId;
const Float32Array& value = aPos;
value.ComputeLengthAndData();
MOZ_ASSERT(value.Length() == 2);
touchState.position[0] = value.Data()[0];
touchState.position[1] = value.Data()[1];
if (!aSurfDim.IsNull()) {
const Float32Array& value = aSurfDim.Value();
value.ComputeLengthAndData();
MOZ_ASSERT(value.Length() == 2);
touchState.surfaceDimensions[0] = value.Data()[0];
touchState.surfaceDimensions[1] = value.Data()[1];
touchState.isSurfaceDimensionsValid = true;
}
GamepadTouchInformation a(aTouchArrayIndex, touchState);
GamepadChangeEventBody body(a);
GamepadChangeEvent e(aIndex, GamepadServiceType::Standard, body);
uint32_t id = ++mEventNumber;
mChild->SendGamepadTestEvent(id, e);
}
JSObject* GamepadServiceTest::WrapObject(JSContext* aCx,
JS::HandleObject aGivenProto) {
return GamepadServiceTest_Binding::Wrap(aCx, this, aGivenProto);

View File

@ -33,11 +33,10 @@ class GamepadServiceTest final : public DOMEventTargetHelper {
GamepadHand LeftHand() const { return GamepadHand::Left; }
GamepadHand RightHand() const { return GamepadHand::Right; }
already_AddRefed<Promise> AddGamepad(const nsAString& aID,
GamepadMappingType aMapping,
GamepadHand aHand, uint32_t aNumButtons,
uint32_t aNumAxes, uint32_t aNumHaptics,
ErrorResult& aRv);
already_AddRefed<Promise> AddGamepad(
const nsAString& aID, GamepadMappingType aMapping, GamepadHand aHand,
uint32_t aNumButtons, uint32_t aNumAxes, uint32_t aNumHaptics,
uint32_t aNumLightIndicator, uint32_t aNumTouchEvents, ErrorResult& aRv);
void RemoveGamepad(uint32_t aIndex);
void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed,
bool aTouched);
@ -50,6 +49,9 @@ class GamepadServiceTest final : public DOMEventTargetHelper {
const Nullable<Float32Array>& aAngAcceleration,
const Nullable<Float32Array>& aLinVelocity,
const Nullable<Float32Array>& aLinAcceleration);
void NewTouch(uint32_t aIndex, uint32_t aTouchArrayIndex, uint32_t aTouchId,
uint8_t aSurfaceId, const Float32Array& aPos,
const Nullable<Float32Array>& aSurfDim);
void Shutdown();
static already_AddRefed<GamepadServiceTest> CreateTestService(

View File

@ -26,7 +26,8 @@ mozilla::ipc::IPCResult GamepadTestChannelParent::RecvGamepadTestEvent(
LossyCopyUTF16toASCII(a.id(), gamepadID);
uint32_t index = service->AddGamepad(
gamepadID.get(), static_cast<GamepadMappingType>(a.mapping()), a.hand(),
a.num_buttons(), a.num_axes(), a.num_haptics());
a.num_buttons(), a.num_axes(), a.num_haptics(), a.num_lights(),
a.num_touches());
if (!mShuttingdown) {
Unused << SendReplyGamepadIndex(aID, index);
}
@ -52,6 +53,11 @@ mozilla::ipc::IPCResult GamepadTestChannelParent::RecvGamepadTestEvent(
service->NewPoseEvent(index, a.pose_state());
return IPC_OK();
}
if (body.type() == GamepadChangeEventBody::TGamepadTouchInformation) {
const GamepadTouchInformation& a = body.get_GamepadTouchInformation();
service->NewMultiTouchEvent(index, a.index(), a.touch_state());
return IPC_OK();
}
NS_WARNING("Unknown event type.");
return IPC_FAIL_NO_REASON(this);

View File

@ -12,9 +12,13 @@ support-files = test_gamepad_iframe.html
support-files = test_gamepad_connect_events_iframe.html
[test_gamepad_extensions.html]
support-files = test_gamepad_extensions_iframe.html
scheme = https
[test_gamepad_frame_state_sync.html]
support-files = test_gamepad_frame_state_sync_iframe.html
[test_gamepad_hidden_frame.html]
support-files = test_gamepad_hidden_frame_iframe.html
[test_gamepad_multitouch_crossorigin.html]
support-files = test_gamepad_multitouch_crossorigin_iframe.html
scheme = https
[test_navigator_gamepads.html]
support-files = test_navigator_gamepads_iframe.html

View File

@ -30,6 +30,8 @@ function checkTimestamp(){
GamepadService.noHand,
4,
2,
0,
0,
0).then(function(i) {
index = i;
// Press a button to make the gamepad visible

View File

@ -37,6 +37,8 @@ function startTests() {
GamepadService.noHand,
4, // buttons
2,
0,
0,
0).then(function(i) {
gamepad_index = i;
gamepad_connected()

View File

@ -17,7 +17,9 @@ let SpecialPowers = window.parent.SpecialPowers;
var tests = [
poseadd,
posecheck,
haptictest
touchadd,
touchcheck,
haptictest // Keep haptictest at the last because it will test removing gamepad from the service.
];
var gamepad_index = 0;
var testNum = 0;
@ -27,6 +29,8 @@ var poseAngVel = new Float32Array([-0.0008, 0.00147, 0.001]);
var poseAngAcc = new Float32Array([-0.494, 0.476, -0.241]);
var poseLinVel = new Float32Array([0.003,0.024,-0.068]);
var poseLinAcc = new Float32Array([-1.211,21.427,-2.348]);
var touchData = [{touchId: 0, surfaceId: 0, pos: new Float32Array([-0.5, 0.5]), surf: new Float32Array([100, 100])},
{touchId: 1, surfaceId: 0, pos: new Float32Array([-0.1, 1.0]), surf: new Float32Array([100, 100])}];
window.addEventListener("gamepadconnected", connecthandler);
window.addEventListener("gamepadbuttondown", function() {
@ -40,14 +44,19 @@ function pressButton() {
}
function startTest() {
SpecialPowers.pushPrefEnv({ "set": [["dom.gamepad.extensions.enabled", true]] });
SpecialPowers.pushPrefEnv({ "set": [
["dom.gamepad.extensions.enabled", true],
["dom.gamepad.extensions.lightindicator", true],
["dom.gamepad.extensions.multitouch", true]] });
// Add a gamepad
GamepadService.addGamepad("test gamepad", // id
GamepadService.standardMapping,
GamepadService.leftHand,
4,
2,
1).then(function(i) {
1,
1,
2).then(function(i) {
gamepad_index = i;
// Simulate button events on the gamepad we added
pressButton();
@ -64,6 +73,8 @@ function connecthandler(e) {
is(e.gamepad.buttons.length, 4, "correct number of buttons");
is(e.gamepad.axes.length, 2, "correct number of axes");
is(e.gamepad.hapticActuators.length, 1, "correct number of haptics");
is(e.gamepad.lightIndicators.length, 1, "correct number of light indicators");
is(e.gamepad.touchEvents.length, 2, "correct number of touches");
}
function checkValueInFloat32Array(array1, array2) {
@ -129,6 +140,41 @@ function haptictest() {
setFrameVisible(f1, false);
}
function touchadd() {
var count = 0;
touchData.forEach(function(touch) {
GamepadService.newTouch(gamepad_index, count, touch.touchId,
touch.surfaceId, touch.pos,
touch.surf);
++count;
});
pressButton();
}
function touchcheck() {
var gamepads = navigator.getGamepads();
var touches = gamepads[0].touchEvents;
is(touches.length, 2, " number of touches");
var count = 0;
touches.forEach(function(touch) {
is(touch.touchId, touchData[count].touchId,
"correct GamepadTouch touchId");
is(touch.surfaceId, touchData[count].surfaceId,
"correct GamepadTouch surfaceId");
is(checkValueInFloat32Array(touch.position, touchData[count].pos), true,
"correct touch position");
is(checkValueInFloat32Array(touch.surfaceDimensions, touchData[count].surf), true,
"correct touch surfaceDimensions");
++count;
});
pressButton();
}
</script>
<iframe id="f1" src="gamepad_frame_state.html" onload="runGamepadTest(startTest)"></iframe>
</body>

View File

@ -32,6 +32,8 @@ function startTest() {
GamepadService.noHand,
4, // buttons
2,
0,
0,
0).then(function(i) {
index = i;
gamepad_loaded();

View File

@ -39,6 +39,8 @@ function startTest() {
GamepadService.noHand,
4, // buttons
2,
0,
0,
0).then(function(i) {
index = i;
gamepad_loaded();

View File

@ -39,6 +39,8 @@ function startTest() {
GamepadService.noHand,
4,
2,
0,
0,
0).then(function(i) {
index = i;
// Simulate button events on the gamepad we added

View File

@ -0,0 +1,20 @@
<!-- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ -->
<!DOCTYPE HTML>
<html>
<head>
<title>Test hidden frames</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<script type="text/javascript" src="mock_gamepad.js"></script>
<script class="testbody" type="text/javascript">
// This test loads in an iframe, to ensure that the navigator instance is
// loaded with the correct value of the preference.
SimpleTest.waitForExplicitFinish();
setGamepadPreferenceAndCreateIframe("test_gamepad_multitouch_crossorigin_iframe.html");
</script>
</body>
</html>

View File

@ -0,0 +1,261 @@
<!-- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ -->
<!DOCTYPE HTML>
<html>
<head>
<title>Test gamepad</title>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<script type="text/javascript" src="mock_gamepad.js"></script>
<script class="testbody" type="text/javascript">
let ok = window.parent.ok;
let is = window.parent.is;
let SimpleTest = window.parent.SimpleTest;
let SpecialPowers = window.parent.SpecialPowers;
let tests = [
touchAdd,
touchcheck1,
touchAdd,
touchcheck2,
touchAdd,
touchcheck3
];
let gamepad_index;
let testNum = 0;
let touchData1 = [{touchId: 0, surfaceId: 0, pos: new Float32Array([-0.5, 0.5]), surf: new Float32Array([100, 100])},
{touchId: 1, surfaceId: 0, pos: new Float32Array([-0.1, 1.0]), surf: new Float32Array([100, 100])}];
let touchData2 = [{touchId: 2, surfaceId: 0, pos: new Float32Array([-0.2, 0.3]), surf: new Float32Array([120, 200])},
{touchId: 3, surfaceId: 0, pos: new Float32Array([-0.4, 0.7]), surf: new Float32Array([120, 200])}];
let touchData3 = [{touchId: 4, surfaceId: 0, pos: new Float32Array([-0.5, 0.6]), surf: new Float32Array([150, 100])},
{touchId: 5, surfaceId: 0, pos: new Float32Array([-0.3, 0.8]), surf: new Float32Array([150, 100])}];
let data = [
touchData1,
touchData2,
touchData3
];
let dataNum = 0;
window.addEventListener("gamepadconnected", connecthandler);
window.addEventListener("gamepadbuttondown", function() {
// Wait to ensure that all frames received the button press as well.
ok(true, "gamepadbuttondown");
SpecialPowers.executeSoon(tests[testNum++]);
});
function pressButton() {
GamepadService.newButtonEvent(gamepad_index, 0, true, true);
GamepadService.newButtonEvent(gamepad_index, 0, false, false);
}
let frames_loaded = 0;
function startTest() {
frames_loaded++;
SpecialPowers.pushPrefEnv({ "set": [
["dom.gamepad.extensions.enabled", true],
["dom.gamepad.extensions.lightindicator", true],
["dom.gamepad.extensions.multitouch", true]] });
if (frames_loaded == 2) {
// Add a gamepad
GamepadService.addGamepad("test gamepad", // id
GamepadService.standardMapping,
GamepadService.leftHand,
4,
2,
1,
1,
2).then(function(i) {
gamepad_index = i;
gamepad_loaded();
});
}
}
let f1, f2;
function gamepad_loaded() {
f1 = document.getElementById('f1');
f2 = document.getElementById('f2');
GamepadService.newButtonEvent(gamepad_index, 0, true, true);
}
function connecthandler(e) {
ok(e.gamepad.timestamp <= performance.now(),
"gamepad.timestamp should less than or equal to performance.now()");
is(e.gamepad.index, 0, "correct gamepad index");
is(e.gamepad.id, "test gamepad", "correct gamepad name");
is(e.gamepad.mapping, "standard", "standard mapping");
is(e.gamepad.hand, "left", "left hand");
is(e.gamepad.buttons.length, 4, "correct number of buttons");
is(e.gamepad.axes.length, 2, "correct number of axes");
is(e.gamepad.hapticActuators.length, 1, "correct number of haptics");
is(e.gamepad.lightIndicators.length, 1, "correct number of light indicators");
is(e.gamepad.touchEvents.length, 2, "correct number of touches");
}
function checkValueInFloat32Array(array1, array2) {
if (array1.length != array2.length) {
return false;
}
let index = 0;
while (index < array2.length) {
if (array1[index] != array2[index]) {
return false;
}
++index;
}
return true;
}
function setFrameVisible(f, visible) {
let Ci = SpecialPowers.Ci;
let docshell = SpecialPowers.wrap(f.contentWindow).docShell;
docshell.isActive = visible;
}
function touchAdd() {
let count = 0;
data[dataNum].forEach(function(touch) {
GamepadService.newTouch(gamepad_index, count, touch.touchId,
touch.surfaceId, touch.pos,
touch.surf);
++count;
});
++dataNum;
pressButton();
}
function touchcheck1() {
let touches = f1.contentWindow.gamepad.touchEvents;
is(touches.length, touchData1.length, "f1 number of touches");
let count = 0;
touches.forEach(function(touch) {
is(touch.touchId, data[0][count].touchId,
"correct GamepadTouch touchId");
is(touch.surfaceId, data[0][count].surfaceId,
"correct GamepadTouch surfaceId");
is(checkValueInFloat32Array(touch.position, data[0][count].pos), true,
"correct touch position");
is(checkValueInFloat32Array(touch.surfaceDimensions, data[0][count].surf), true,
"correct touch surfaceDimensions");
++count;
});
touches = f2.contentWindow.gamepad.touchEvents;
is(touches.length, data[0].length,"f2 number of touches");
count = 0;
touches.forEach(function(touch) {
is(touch.touchId, data[0][count].touchId,
"correct GamepadTouch touchId");
is(touch.surfaceId, data[0][count].surfaceId,
"correct GamepadTouch surfaceId");
is(checkValueInFloat32Array(touch.position, data[0][count].pos), true,
"correct touch position");
is(checkValueInFloat32Array(touch.surfaceDimensions, data[0][count].surf), true,
"correct touch surfaceDimensions");
++count;
});
// Making f2 to be at the background.
setFrameVisible(f2, false);
pressButton();
}
function touchcheck2() {
let touches = f1.contentWindow.gamepad.touchEvents;
is(touches.length, data[1].length, "f1 number of touches");
let count = 0;
touches.forEach(function(touch) {
is(touch.touchId, data[1][count].touchId,
"correct GamepadTouch touchId");
is(touch.surfaceId, data[1][count].surfaceId,
"correct GamepadTouch surfaceId");
is(checkValueInFloat32Array(touch.position, data[1][count].pos), true,
"correct touch position");
is(checkValueInFloat32Array(touch.surfaceDimensions, data[1][count].surf), true,
"correct touch surfaceDimensions");
++count;
});
touches = f2.contentWindow.gamepad.touchEvents;
is(touches.length, touchData1.length,"f2 number of touches");
// When f2 is at the background, it will use the previous status.
count = 0;
touches.forEach(function(touch) {
is(touch.touchId, data[0][count].touchId,
"correct GamepadTouch touchId");
is(touch.surfaceId, data[0][count].surfaceId,
"correct GamepadTouch surfaceId");
is(checkValueInFloat32Array(touch.position, data[0][count].pos), true,
"correct touch position");
is(checkValueInFloat32Array(touch.surfaceDimensions, data[0][count].surf), true,
"correct touch surfaceDimensions");
++count;
});
setFrameVisible(f2, true);
pressButton();
}
function touchcheck3() {
let touches = f1.contentWindow.gamepad.touchEvents;
is(touches.length, touchData3.length, "f1 number of touches");
let count = 0;
touches.forEach(function(touch) {
is(touch.touchId, data[2][count].touchId,
"correct GamepadTouch touchId");
is(touch.surfaceId, data[2][count].surfaceId,
"correct GamepadTouch surfaceId");
is(checkValueInFloat32Array(touch.position, data[2][count].pos), true,
"correct touch position");
is(checkValueInFloat32Array(touch.surfaceDimensions, data[2][count].surf), true,
"correct touch surfaceDimensions");
++count;
});
touches = f2.contentWindow.gamepad.touchEvents;
is(touches.length, touchData3.length,"f2 number of touches");
count = 0;
touches.forEach(function(touch) {
// f2 was at the background so doesn't add touch events from data[1].
is(touch.touchId, data[2][count].touchId - data[1].length,
"correct GamepadTouch touchId");
is(touch.surfaceId, data[2][count].surfaceId,
"correct GamepadTouch surfaceId");
is(checkValueInFloat32Array(touch.position, data[2][count].pos), true,
"correct touch position");
is(checkValueInFloat32Array(touch.surfaceDimensions, data[2][count].surf), true,
"correct touch surfaceDimensions");
++count;
});
SpecialPowers.executeSoon(cleanup);
}
function cleanup(){
SpecialPowers.executeSoon(function() {
GamepadService.removeGamepad(gamepad_index);
SimpleTest.finish();
});
}
</script>
<iframe id="f1" src="gamepad_frame_state.html" onload="runGamepadTest(startTest)"></iframe>
<iframe id="f2" src="gamepad_frame_state.html" onload="runGamepadTest(startTest)"></iframe>
</body>
</html>

View File

@ -48,6 +48,8 @@ function startTest() {
GamepadService.noHand,
4, // buttons
2,
0,
0,
0).then(function(index) {
internal_index1 = index;
// Press a button to make the gamepad visible to the page.
@ -73,6 +75,8 @@ function check_first_gamepad(e) {
GamepadService.noHand,
4, // buttons
2,
0,
0,
0).then(function(index) {
internal_index2 = index;
GamepadService.newButtonEvent(internal_index2, 0, true, true);

View File

@ -17,7 +17,9 @@ interface GamepadServiceTest
GamepadHand hand,
unsigned long numButtons,
unsigned long numAxes,
unsigned long numHaptics);
unsigned long numHaptics,
unsigned long numLightIndicator,
unsigned long numTouchEvents);
void removeGamepad(unsigned long index);
@ -42,4 +44,8 @@ interface GamepadServiceTest
Float32Array? angAcceleration,
Float32Array? linVelocity,
Float32Array? linAcceleration);
void newTouch(unsigned long index, unsigned long aTouchArrayIndex,
unsigned long touchId, octet surfaceId,
Float32Array position, Float32Array? surfaceDimension);
};