Enforce user gesture for getUserMedia in case a previous getUserMedia call was denied
[WebKit-https.git] / LayoutTests / http / tests / media / media-stream / get-display-media-prompt.html
1 <!DOCTYPE html>
2 <html>
3     <head>
4         <title>getDisplayMedia prompt</title>
5         <script src="../../../../resources/js-test-pre.js"></script>
6     </head>
7     <body>
8     <p id="description"></p>
9     <div id="console"></div>
10
11 <script>
12     let stream;
13     let err;
14     
15     function callGetDisplayMedia(options)
16     {
17         let promise;
18         window.internals.withUserGesture(() => {
19             promise = navigator.mediaDevices.getDisplayMedia(options);
20         });
21         return promise;
22     }
23
24     function numberOfTimesGetUserMediaPromptHasBeenCalled() {
25         return testRunner.userMediaPermissionRequestCountForOrigin(document.location.href, document.location.href);
26     }
27     
28     async function promptForAudioOnly() {
29         debug("<br>** Request an audio-only stream, the user should not be prompted **");
30         stream = await callGetDisplayMedia({ audio: true })
31             .catch((e) => { err = e; });
32         shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "0");
33         shouldBeUndefined("stream");
34         shouldBeTrue("err instanceof Error ");
35         shouldBeEqualToString("err.name", "TypeError");
36     }
37
38     async function promptForVideoOnly() {
39         debug("<br>** Request an video-only stream, the user should be prompted **");
40         stream = await callGetDisplayMedia({ video: true });
41         shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "1");
42         shouldBe("stream.getAudioTracks().length", "0");
43         shouldBe("stream.getVideoTracks().length", "1");
44     }
45
46     async function promptForAudioAndVideo() {
47         debug("<br>** Request a stream with audio and video, the user should be prompted but no audio track should be created **");
48         stream = await callGetDisplayMedia({ video: true, audio: true });
49         shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "2");
50         shouldBe("stream.getAudioTracks().length", "0");
51         shouldBe("stream.getVideoTracks().length", "1");
52     }
53     
54     async function promptWithExactVideoConstraints() {
55         debug("<br>** Request a stream with 'max' constraints, the user should not be prompted **");
56
57         stream = null;
58         stream = await callGetDisplayMedia({ video: {width: {exact: 640}, height: {exact: 480}} })
59             .catch((e) => { err = e; });
60         
61         shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "2");
62         shouldBeUndefined("stream");
63         shouldBeTrue("err instanceof Error ");
64         shouldBeEqualToString("err.name", "TypeError");
65     }
66
67     async function promptWithMinVideoConstraints() {
68         debug("<br>** Request a stream with 'min' constraints, the user should not be prompted **");
69
70         stream = null;
71         stream = await callGetDisplayMedia({ video: {width: {min: 640}, height: {min: 480}} })
72             .catch((e) => { err = e; });
73         shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "2");
74         shouldBeUndefined("stream");
75         shouldBeTrue("err instanceof Error ");
76         shouldBeEqualToString("err.name", "TypeError");
77     }
78
79     async function promptWithAdvancedVideoConstraints() {
80         debug("<br>** Request a stream with 'advanced' constraints, the user should not be prompted **");
81
82         stream = null;
83         stream = await callGetDisplayMedia({ video: { width: 640, height: 480, advanced: [ { width: 1920, height: 1280 } ] } })
84             .catch((e) => { err = e; });
85         shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "2");
86         shouldBeUndefined("stream");
87         shouldBeTrue("err instanceof Error ");
88         shouldBeEqualToString("err.name", "TypeError");
89     }
90
91     async function promptWithValidVideoConstraints() {
92         debug("<br>** Request a stream with valid constraints, the user should be prompted **");
93
94         stream = null;
95         stream = await callGetDisplayMedia({ video: {width: 640, height: 480} })
96             .catch((e) => { err = e; });
97         
98         shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "3");
99         shouldBe("stream.getAudioTracks().length", "0");
100         shouldBe("stream.getVideoTracks().length", "1");
101     }
102
103     async function promptWithInvalidAudioConstraint() {
104         debug("<br>** Request a stream with an exact audio constraint, it should be ignored **");
105
106         stream = null;
107         stream = await callGetDisplayMedia({ video: true, audio: { volume: { exact: 0.5 } } });
108         shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "4");
109         shouldBe("stream.getAudioTracks().length", "0");
110         shouldBe("stream.getVideoTracks().length", "1");
111     }
112     
113     (async function() {
114         description('Test basic getDisplayMedia prompting behavior');
115         jsTestIsAsync = true;
116
117         testRunner.resetUserMediaPermissionRequestCountForOrigin(document.location.href, document.location.href);
118         window.internals.settings.setScreenCaptureEnabled(true);
119
120         shouldBe("numberOfTimesGetUserMediaPromptHasBeenCalled()", "0");
121
122         await promptForAudioOnly();
123         await promptForVideoOnly();
124         await promptForAudioAndVideo();
125         await promptWithExactVideoConstraints();
126         await promptWithMinVideoConstraints();
127         await promptWithAdvancedVideoConstraints();
128         await promptWithValidVideoConstraints();
129         await promptWithInvalidAudioConstraint();
130
131         debug("");
132         finishJSTest();
133     })()
134
135 </script>
136 <script src="../../../../resources/js-test-post.js"></script>
137 </body>
138 </html>