Skip to content

Commit 95c95ff

Browse files
Ravjit Uppalchromium-wpt-export-bot
authored andcommitted
[CE] Support gUM constraints in <usermedia> element
Type attribute takes precedence over setConstraints. The CL also updates the error attribute to match the gUM JS API. If the constraints don't match the type of the usermedia element or are undefined/false, a type error is throwm. Bug: 494481412 Change-Id: Ifb0229cbf82f3cc219043d4ef076922771f195f1 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7738744 Reviewed-by: Guido Urdaneta <guidou@chromium.org> Commit-Queue: Ravjit Uppal <ravjit@chromium.org> Cr-Commit-Position: refs/heads/main@{#1615696}
1 parent 7a8c4c3 commit 95c95ff

File tree

1 file changed

+112
-0
lines changed

1 file changed

+112
-0
lines changed
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
<!doctype html>
2+
<meta charset="utf-8" />
3+
<meta name="timeout" content="long">
4+
<title>HTMLUserMediaElement setConstraints() behavior combinations</title>
5+
<script src="/resources/testharness.js"></script>
6+
<script src="/resources/testharnessreport.js"></script>
7+
<script src="/resources/testdriver.js"></script>
8+
<script src="/resources/testdriver-vendor.js"></script>
9+
<body>
10+
<script>
11+
const testCases = [
12+
// type="camera"
13+
{ type: 'camera', video: undefined, audio: undefined, expVideo: 0, expAudio: 0 },
14+
{ type: 'camera', video: true, audio: undefined, expVideo: 1, expAudio: 0 },
15+
{ type: 'camera', video: true, audio: false, expVideo: 1, expAudio: 0 },
16+
{ type: 'camera', video: true, audio: true, expVideo: 1, expAudio: 0 },
17+
{ type: 'camera', video: false, audio: undefined, expVideo: 0, expAudio: 0 },
18+
{ type: 'camera', video: false, audio: false, expVideo: 0, expAudio: 0 },
19+
{ type: 'camera', video: false, audio: true, expVideo: 0, expAudio: 0 },
20+
{ type: 'camera', video: undefined, audio: false, expVideo: 0, expAudio: 0 },
21+
{ type: 'camera', video: undefined, audio: true, expVideo: 0, expAudio: 0 },
22+
23+
// type="microphone"
24+
{ type: 'microphone', video: undefined, audio: undefined, expVideo: 0, expAudio: 0 },
25+
{ type: 'microphone', video: undefined, audio: true, expVideo: 0, expAudio: 1 },
26+
{ type: 'microphone', video: false, audio: true, expVideo: 0, expAudio: 1 },
27+
{ type: 'microphone', video: true, audio: true, expVideo: 0, expAudio: 1 },
28+
{ type: 'microphone', video: undefined, audio: false, expVideo: 0, expAudio: 0 },
29+
{ type: 'microphone', video: false, audio: false, expVideo: 0, expAudio: 0 },
30+
{ type: 'microphone', video: true, audio: false, expVideo: 0, expAudio: 0 },
31+
{ type: 'microphone', video: false, audio: undefined, expVideo: 0, expAudio: 0 },
32+
{ type: 'microphone', video: true, audio: undefined, expVideo: 0, expAudio: 0 },
33+
34+
// type="camera microphone"
35+
{ type: "camera microphone", video: undefined, audio: undefined, expVideo: 0, expAudio: 0 },
36+
{ type: "camera microphone", video: true, audio: undefined, expVideo: 1, expAudio: 0 },
37+
{ type: "camera microphone", video: true, audio: false, expVideo: 1, expAudio: 0 },
38+
{ type: "camera microphone", video: true, audio: true, expVideo: 1, expAudio: 1 },
39+
{ type: "camera microphone", video: false, audio: true, expVideo: 0, expAudio: 1 },
40+
{ type: "camera microphone", video: false, audio: undefined, expVideo: 0, expAudio: 0 },
41+
{ type: "camera microphone", video: false, audio: false, expVideo: 0, expAudio: 0 },
42+
{ type: "camera microphone", video: undefined, audio: true, expVideo: 0, expAudio: 1 },
43+
{ type: "camera microphone", video: undefined, audio: false, expVideo: 0, expAudio: 0 },
44+
45+
// No type attribute (null)
46+
{ type: null, video: undefined, audio: undefined, expVideo: 0, expAudio: 0 },
47+
{ type: null, video: true, audio: undefined, expVideo: 1, expAudio: 0 },
48+
{ type: null, video: true, audio: false, expVideo: 1, expAudio: 0 },
49+
{ type: null, video: true, audio: true, expVideo: 1, expAudio: 1 },
50+
{ type: null, video: false, audio: true, expVideo: 0, expAudio: 1 },
51+
{ type: null, video: false, audio: undefined, expVideo: 0, expAudio: 0 },
52+
{ type: null, video: false, audio: false, expVideo: 0, expAudio: 0 },
53+
{ type: null, video: undefined, audio: true, expVideo: 0, expAudio: 1 },
54+
{ type: null, video: undefined, audio: false, expVideo: 0, expAudio: 0 },
55+
];
56+
57+
promise_test(async (t) => {
58+
await test_driver.set_permission({ name: "camera" }, "granted");
59+
await test_driver.set_permission({ name: "microphone" }, "granted");
60+
61+
for (let i = 0; i < testCases.length; i++) {
62+
const testCase = testCases[i];
63+
const { type, video, audio, expVideo, expAudio } = testCase;
64+
const testName = `Case ${i}: type='${type}', video=${video}, audio=${audio}`;
65+
66+
const usermedia = document.createElement("usermedia");
67+
if (type !== null) {
68+
usermedia.setAttribute("type", type);
69+
}
70+
document.body.appendChild(usermedia);
71+
72+
const stream_promise = new Promise((resolve) => {
73+
usermedia.onstream = resolve;
74+
});
75+
76+
usermedia.setConstraints({ video: video, audio: audio });
77+
78+
// should_trigger is true if the element has at least one permission descriptor.
79+
const should_trigger = (type !== null) || (video === true) || (audio === true);
80+
81+
// Wait for PEPC registration
82+
await new Promise(r => t.step_timeout(r, 100));
83+
84+
if (should_trigger) {
85+
await test_driver.bless("click", () => usermedia.click());
86+
await stream_promise;
87+
} else {
88+
await test_driver.bless("click", () => usermedia.click());
89+
// Wait a bit to ensure no stream event is fired
90+
await new Promise(r => t.step_timeout(r, 200));
91+
}
92+
93+
const stream = usermedia.stream;
94+
if (expVideo || expAudio) {
95+
assert_true(stream instanceof MediaStream, `${testName}: stream type check`);
96+
assert_equals(stream.getVideoTracks().length, expVideo, `${testName}: video tracks mismatch`);
97+
assert_equals(stream.getAudioTracks().length, expAudio, `${testName}: audio tracks mismatch`);
98+
} else {
99+
assert_equals(stream, null, `${testName}: stream should be null`);
100+
if (should_trigger) {
101+
assert_true(usermedia.error !== null && usermedia.error !== undefined, `${testName}: error attribute should be set`);
102+
}
103+
}
104+
105+
if (stream) {
106+
stream.getTracks().forEach(track => track.stop());
107+
}
108+
document.body.removeChild(usermedia);
109+
}
110+
}, "HTMLUserMediaElement setConstraints() combinations consolidated");
111+
</script>
112+
</body>

0 commit comments

Comments
 (0)