1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <string>
6 
7 #include "base/strings/stringprintf.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
10 #include "chrome/browser/media/webrtc/webrtc_browsertest_base.h"
11 #include "content/public/browser/web_contents.h"
12 #include "content/public/common/content_switches.h"
13 #include "content/public/test/browser_test.h"
14 #include "content/public/test/browser_test_utils.h"
15 #include "media/base/media_switches.h"
16 
17 namespace {
18 
19 struct PermissionTestConfig {
20   const char* constraints;
21   const char* expected_microphone;
22   const char* expected_camera;
23   const char* expected_pan_tilt_zoom;
24 };
25 
26 struct TrackTestConfig {
27   const char* constraints;
28   const double expected_pan;
29   const double expected_tilt;
30   const double expected_zoom;
31   const char* expected_constraints;
32 };
33 
34 static const char kMainHtmlPage[] = "/webrtc/webrtc_pan_tilt_zoom_test.html";
35 
36 }  // namespace
37 
38 class WebRtcPanTiltZoomPermissionBrowserTest
39     : public WebRtcTestBase,
40       public testing::WithParamInterface<PermissionTestConfig> {
41  public:
SetUpCommandLine(base::CommandLine * command_line)42   void SetUpCommandLine(base::CommandLine* command_line) override {
43     command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures,
44                                     "MediaCapturePanTilt");
45   }
46 
SetUpInProcessBrowserTestFixture()47   void SetUpInProcessBrowserTestFixture() override {
48     DetectErrorsInJavaScript();
49   }
50 };
51 
IN_PROC_BROWSER_TEST_P(WebRtcPanTiltZoomPermissionBrowserTest,TestRequestPanTiltZoomPermission)52 IN_PROC_BROWSER_TEST_P(WebRtcPanTiltZoomPermissionBrowserTest,
53                        TestRequestPanTiltZoomPermission) {
54   ASSERT_TRUE(embedded_test_server()->Start());
55   content::WebContents* tab = OpenTestPageInNewTab(kMainHtmlPage);
56 
57   std::string result;
58   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
59       tab->GetMainFrame(),
60       base::StringPrintf("runGetUserMedia(%s);", GetParam().constraints),
61       &result));
62   EXPECT_EQ(result, "runGetUserMedia-success");
63 
64   std::string microphone;
65   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
66       tab->GetMainFrame(), "getMicrophonePermission();", &microphone));
67   EXPECT_EQ(microphone, GetParam().expected_microphone);
68 
69   std::string camera;
70   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
71       tab->GetMainFrame(), "getCameraPermission();", &camera));
72   EXPECT_EQ(camera, GetParam().expected_camera);
73 
74   std::string pan_tilt_zoom;
75   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
76       tab->GetMainFrame(), "getPanTiltZoomPermission();", &pan_tilt_zoom));
77   EXPECT_EQ(pan_tilt_zoom, GetParam().expected_pan_tilt_zoom);
78 }
79 
80 INSTANTIATE_TEST_SUITE_P(
81     RequestPanTiltZoomPermission,
82     WebRtcPanTiltZoomPermissionBrowserTest,
83     testing::Values(
84         // no pan, tilt, zoom in audio and video constraints
85         PermissionTestConfig{"{ video: true }", "prompt", "granted", "prompt"},
86         PermissionTestConfig{"{ audio: true }", "granted", "prompt", "prompt"},
87         PermissionTestConfig{"{ audio: true, video: true }", "granted",
88                              "granted", "prompt"},
89         // pan, tilt, zoom in audio constraints
90         PermissionTestConfig{"{ audio: { pan : false } }", "granted", "prompt",
91                              "prompt"},
92         PermissionTestConfig{"{ audio: { tilt : false } }", "granted", "prompt",
93                              "prompt"},
94         PermissionTestConfig{"{ audio: { zoom : false } }", "granted", "prompt",
95                              "prompt"},
96         PermissionTestConfig{"{ audio: { pan : {} } }", "granted", "prompt",
97                              "prompt"},
98         PermissionTestConfig{"{ audio: { tilt : {} } }", "granted", "prompt",
99                              "prompt"},
100         PermissionTestConfig{"{ audio: { zoom : {} } }", "granted", "prompt",
101                              "prompt"},
102         PermissionTestConfig{"{ audio: { pan : 1 } }", "granted", "prompt",
103                              "prompt"},
104         PermissionTestConfig{"{ audio: { tilt : 1 } }", "granted", "prompt",
105                              "prompt"},
106         PermissionTestConfig{"{ audio: { zoom : 1 } }", "granted", "prompt",
107                              "prompt"},
108         PermissionTestConfig{"{ audio: { pan : true } }", "granted", "prompt",
109                              "prompt"},
110         PermissionTestConfig{"{ audio: { tilt : true } }", "granted", "prompt",
111                              "prompt"},
112         PermissionTestConfig{"{ audio: { zoom : true } }", "granted", "prompt",
113                              "prompt"},
114         // pan, tilt, zoom in basic video constraints if no audio
115         PermissionTestConfig{"{ video: { pan : false } }", "prompt", "granted",
116                              "prompt"},
117         PermissionTestConfig{"{ video: { tilt : false } }", "prompt", "granted",
118                              "prompt"},
119         PermissionTestConfig{"{ video: { zoom : false } }", "prompt", "granted",
120                              "prompt"},
121         PermissionTestConfig{"{ video: { pan : {} } }", "prompt", "granted",
122                              "granted"},
123         PermissionTestConfig{"{ video: { tilt : {} } }", "prompt", "granted",
124                              "granted"},
125         PermissionTestConfig{"{ video: { zoom : {} } }", "prompt", "granted",
126                              "granted"},
127         PermissionTestConfig{"{ video: { pan : 1 } }", "prompt", "granted",
128                              "granted"},
129         PermissionTestConfig{"{ video: { tilt : 1 } }", "prompt", "granted",
130                              "granted"},
131         PermissionTestConfig{"{ video: { zoom : 1 } }", "prompt", "granted",
132                              "granted"},
133         PermissionTestConfig{"{ video: { pan : true } }", "prompt", "granted",
134                              "granted"},
135         PermissionTestConfig{"{ video: { tilt : true } }", "prompt", "granted",
136                              "granted"},
137         PermissionTestConfig{"{ video: { zoom : true } }", "prompt", "granted",
138                              "granted"},
139         // pan, tilt, zoom in advanced video constraints if no audio
140         PermissionTestConfig{"{ video: { advanced: [{ pan : false }] } }",
141                              "prompt", "granted", "prompt"},
142         PermissionTestConfig{"{ video: { advanced: [{ tilt : false }] } }",
143                              "prompt", "granted", "prompt"},
144         PermissionTestConfig{"{ video: { advanced: [{ zoom : false }] } }",
145                              "prompt", "granted", "prompt"},
146         PermissionTestConfig{"{ video: { advanced: [{ pan : {} }] } }",
147                              "prompt", "granted", "granted"},
148         PermissionTestConfig{"{ video: { advanced: [{ tilt : {} }] } }",
149                              "prompt", "granted", "granted"},
150         PermissionTestConfig{"{ video: { advanced: [{ zoom : {} }] } }",
151                              "prompt", "granted", "granted"},
152         PermissionTestConfig{"{ video: { advanced: [{ pan : 1 }] } }", "prompt",
153                              "granted", "granted"},
154         PermissionTestConfig{"{ video: { advanced: [{ tilt : 1 }] } }",
155                              "prompt", "granted", "granted"},
156         PermissionTestConfig{"{ video: { advanced: [{ zoom : 1 }] } }",
157                              "prompt", "granted", "granted"},
158         PermissionTestConfig{"{ video: { advanced: [{ pan : true }] } }",
159                              "prompt", "granted", "granted"},
160         PermissionTestConfig{"{ video: { advanced: [{ tilt : true }] } }",
161                              "prompt", "granted", "granted"},
162         PermissionTestConfig{"{ video: { advanced: [{ zoom : true }] } }",
163                              "prompt", "granted", "granted"},
164         // pan, tilt, zoom in basic video constraints if audio
165         PermissionTestConfig{"{ audio: true, video: { pan : false } }",
166                              "granted", "granted", "prompt"},
167         PermissionTestConfig{"{ audio: true, video: { tilt : false } }",
168                              "granted", "granted", "prompt"},
169         PermissionTestConfig{"{ audio: true, video: { zoom : false } }",
170                              "granted", "granted", "prompt"},
171         PermissionTestConfig{"{ audio: true, video: { pan : {} } }", "granted",
172                              "granted", "granted"},
173         PermissionTestConfig{"{ audio: true, video: { tilt : {} } }", "granted",
174                              "granted", "granted"},
175         PermissionTestConfig{"{ audio: true, video: { zoom : {} } }", "granted",
176                              "granted", "granted"},
177         PermissionTestConfig{"{ audio: true, video: { pan : 1 } }", "granted",
178                              "granted", "granted"},
179         PermissionTestConfig{"{ audio: true, video: { tilt : 1 } }", "granted",
180                              "granted", "granted"},
181         PermissionTestConfig{"{ audio: true, video: { zoom : 1 } }", "granted",
182                              "granted", "granted"},
183         PermissionTestConfig{"{ audio: true, video: { pan : true } }",
184                              "granted", "granted", "granted"},
185         PermissionTestConfig{"{ audio: true, video: { tilt : true } }",
186                              "granted", "granted", "granted"},
187         PermissionTestConfig{"{ audio: true, video: { zoom : true } }",
188                              "granted", "granted", "granted"},
189         // pan, tilt, zoom in advanced video constraints if audio
190         PermissionTestConfig{
191             "{ audio: true, video: { advanced: [{ pan : false }] } }",
192             "granted", "granted", "prompt"},
193         PermissionTestConfig{
194             "{ audio: true, video: { advanced: [{ tilt : false }] } }",
195             "granted", "granted", "prompt"},
196         PermissionTestConfig{
197             "{ audio: true, video: { advanced: [{ zoom : false }] } }",
198             "granted", "granted", "prompt"},
199         PermissionTestConfig{
200             "{ audio: true, video: { advanced: [{ pan : {} }] } }", "granted",
201             "granted", "granted"},
202         PermissionTestConfig{
203             "{ audio: true, video: { advanced: [{ tilt : {} }] } }", "granted",
204             "granted", "granted"},
205         PermissionTestConfig{
206             "{ audio: true, video: { advanced: [{ zoom : {} }] } }", "granted",
207             "granted", "granted"},
208         PermissionTestConfig{
209             "{ audio: true, video: { advanced: [{ pan : 1 }] } }", "granted",
210             "granted", "granted"},
211         PermissionTestConfig{
212             "{ audio: true, video: { advanced: [{ tilt : 1 }] } }", "granted",
213             "granted", "granted"},
214         PermissionTestConfig{
215             "{ audio: true, video: { advanced: [{ zoom : 1 }] } }", "granted",
216             "granted", "granted"},
217         PermissionTestConfig{
218             "{ audio: true, video: { advanced: [{ pan : true }] } }", "granted",
219             "granted", "granted"},
220         PermissionTestConfig{
221             "{ audio: true, video: { advanced: [{ tilt : true }] } }",
222             "granted", "granted", "granted"},
223         PermissionTestConfig{
224             "{ audio: true, video: { advanced: [{ zoom : true }] } }",
225             "granted", "granted", "granted"}));
226 
227 class WebRtcPanTiltZoomTrackBrowserTest
228     : public WebRtcTestBase,
229       public testing::WithParamInterface<TrackTestConfig> {
230  public:
SetUpInProcessBrowserTestFixture()231   void SetUpInProcessBrowserTestFixture() override {
232     DetectErrorsInJavaScript();
233   }
234 };
235 
IN_PROC_BROWSER_TEST_P(WebRtcPanTiltZoomTrackBrowserTest,TestTrackFromGetUserMedia)236 IN_PROC_BROWSER_TEST_P(WebRtcPanTiltZoomTrackBrowserTest,
237                        TestTrackFromGetUserMedia) {
238   ASSERT_TRUE(embedded_test_server()->Start());
239   content::WebContents* tab = OpenTestPageInNewTab(kMainHtmlPage);
240 
241   std::string result;
242   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
243       tab->GetMainFrame(),
244       base::StringPrintf("runGetUserMedia(%s);", GetParam().constraints),
245       &result));
246   EXPECT_EQ(result, "runGetUserMedia-success");
247 
248   std::string pan_tilt_zoom;
249   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
250       tab->GetMainFrame(), "getPanTiltZoomPermission();", &pan_tilt_zoom));
251   EXPECT_EQ(pan_tilt_zoom, "granted");
252 
253   double pan;
254   EXPECT_TRUE(content::ExecuteScriptAndExtractDouble(
255       tab->GetMainFrame(), "getTrackSetting('pan');", &pan));
256   EXPECT_EQ(pan, GetParam().expected_pan);
257 
258   double tilt;
259   EXPECT_TRUE(content::ExecuteScriptAndExtractDouble(
260       tab->GetMainFrame(), "getTrackSetting('tilt');", &tilt));
261   EXPECT_EQ(tilt, GetParam().expected_tilt);
262 
263   double zoom;
264   EXPECT_TRUE(content::ExecuteScriptAndExtractDouble(
265       tab->GetMainFrame(), "getTrackSetting('zoom');", &zoom));
266   EXPECT_EQ(zoom, GetParam().expected_zoom);
267 
268   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
269       tab->GetMainFrame(),
270       base::StringPrintf("checkConstraints(%s);",
271                          GetParam().expected_constraints),
272       &result));
273   EXPECT_EQ(result, "checkConstraints-success");
274 }
275 
276 // Default PTZ value is 100, min is 100, max is 400 as defined in fake video
277 // capture config at media/capture/video/fake_video_capture_device.cc and
278 // media/capture/video/fake_video_capture_device_factory.cc
279 INSTANTIATE_TEST_SUITE_P(
280     TrackFromGetUserMedia,
281     WebRtcPanTiltZoomTrackBrowserTest,
282     testing::Values(
283         // pan, tilt, zoom in basic video constraints with valid values
284         TrackTestConfig{"{ video: { pan : 101 } }", 101, 100, 100,
285                         "{ pan : 101 }"},
286         TrackTestConfig{"{ video: { tilt : 102 } }", 100, 102, 100,
287                         "{ tilt : 102 }"},
288         TrackTestConfig{"{ video: { zoom : 103 } }", 100, 100, 103,
289                         "{ zoom : 103 }"},
290         TrackTestConfig{"{ video: { pan: 101, tilt: 102, zoom: 103 } }", 101,
291                         102, 103, "{ pan: 101, tilt: 102, zoom: 103 }"},
292         // pan, tilt, zoom in advanced video constraints with valid values
293         TrackTestConfig{"{ video: { advanced: [{ pan : 101 }] } }", 101, 100,
294                         100, "{ advanced: [{ pan : 101 }] }"},
295         TrackTestConfig{"{ video: { advanced: [{ tilt : 102 }] } }", 100, 102,
296                         100, "{ advanced: [{ tilt : 102 }] }"},
297         TrackTestConfig{"{ video: { advanced: [{ zoom : 103 }] } }", 100, 100,
298                         103, "{ advanced: [{ zoom : 103 }] }"},
299         TrackTestConfig{
300             "{ video: { advanced: [{ pan : 101, tilt : 102, zoom : 103 }] } }",
301             101, 102, 103,
302             "{ advanced: [{ pan: 101, tilt: 102, zoom: 103 }] }"},
303         // pan, tilt, zoom in basic video constraints with invalid values
304         TrackTestConfig{"{ video: { pan : 99 } }", 100, 100, 100,
305                         "{ pan: 99 }"},
306         TrackTestConfig{"{ video: { tilt : 99 } }", 100, 100, 100,
307                         "{ tilt: 99 }"},
308         TrackTestConfig{"{ video: { zoom : 99 } }", 100, 100, 100,
309                         "{ zoom: 99 }"},
310         TrackTestConfig{"{ video: { pan : 401 } }", 100, 100, 100,
311                         "{ pan: 401 }"},
312         TrackTestConfig{"{ video: { tilt : 401 } }", 100, 100, 100,
313                         "{ tilt: 401 }"},
314         TrackTestConfig{"{ video: { zoom : 401 } }", 100, 100, 100,
315                         "{ zoom: 401 }"},
316         // pan, tilt, zoom in advanced video constraints with invalid values
317         TrackTestConfig{"{ video: { advanced: [{ pan : 99 }] } }", 100, 100,
318                         100, "{ advanced: [{ pan : 99 }] }"},
319         TrackTestConfig{"{ video: { advanced: [{ tilt : 99 }] } }", 100, 100,
320                         100, "{ advanced: [{ tilt : 99 }] }"},
321         TrackTestConfig{"{ video: { advanced: [{ zoom : 99 }] } }", 100, 100,
322                         100, "{ advanced: [{ zoom : 99 }] }"},
323         TrackTestConfig{"{ video: { advanced: [{ pan : 401 }] } }", 100, 100,
324                         100, "{ advanced: [{ pan : 401 }] }"},
325         TrackTestConfig{"{ video: { advanced: [{ tilt : 401 }] } }", 100, 100,
326                         100, "{ advanced: [{ tilt : 401 }] }"},
327         TrackTestConfig{"{ video: { advanced: [{ zoom : 401 }] } }", 100, 100,
328                         100, "{ advanced: [{ zoom : 401 }] }"}));
329 
330 class WebRtcPanTiltZoomConstraintsBrowserTest
331     : public WebRtcTestBase,
332       public ::testing::WithParamInterface<std::string> {
333  public:
Constraint()334   const char* Constraint() { return GetParam().c_str(); }
335 
SetUpInProcessBrowserTestFixture()336   void SetUpInProcessBrowserTestFixture() override {
337     DetectErrorsInJavaScript();
338   }
339 };
340 
IN_PROC_BROWSER_TEST_P(WebRtcPanTiltZoomConstraintsBrowserTest,TestConstraintsFromGetUserMedia)341 IN_PROC_BROWSER_TEST_P(WebRtcPanTiltZoomConstraintsBrowserTest,
342                        TestConstraintsFromGetUserMedia) {
343   ASSERT_TRUE(embedded_test_server()->Start());
344   content::WebContents* tab = OpenTestPageInNewTab(kMainHtmlPage);
345 
346   std::string result;
347   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
348       tab->GetMainFrame(),
349       base::StringPrintf("runGetUserMedia({ video: { width: 640, %s: 101 } });",
350                          Constraint()),
351       &result));
352   EXPECT_EQ(result, "runGetUserMedia-success");
353 
354   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
355       tab->GetMainFrame(),
356       base::StringPrintf("checkConstraints({ width: 640, %s: 101 });",
357                          Constraint()),
358       &result));
359   EXPECT_EQ(result, "checkConstraints-success");
360 
361   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
362       tab->GetMainFrame(),
363       base::StringPrintf("applyConstraints({ advanced: [{ %s: 102 }] });",
364                          Constraint()),
365       &result));
366   EXPECT_EQ(result, "applyConstraints-success");
367 
368   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
369       tab->GetMainFrame(),
370       base::StringPrintf("checkConstraints({ advanced: [{ %s: 102 }] });",
371                          Constraint()),
372       &result));
373   EXPECT_EQ(result, "checkConstraints-success");
374 }
375 
IN_PROC_BROWSER_TEST_P(WebRtcPanTiltZoomConstraintsBrowserTest,TestUnconstrainedConstraintsFromGetUserMedia)376 IN_PROC_BROWSER_TEST_P(WebRtcPanTiltZoomConstraintsBrowserTest,
377                        TestUnconstrainedConstraintsFromGetUserMedia) {
378   ASSERT_TRUE(embedded_test_server()->Start());
379   content::WebContents* tab = OpenTestPageInNewTab(kMainHtmlPage);
380 
381   std::string result;
382   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
383       tab->GetMainFrame(),
384       base::StringPrintf("runGetUserMedia({ video: { width: 640, %s: 101 } });",
385                          Constraint()),
386       &result));
387   EXPECT_EQ(result, "runGetUserMedia-success");
388 
389   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
390       tab->GetMainFrame(),
391       base::StringPrintf("checkConstraints({ width: 640, %s: 101 });",
392                          Constraint()),
393       &result));
394   EXPECT_EQ(result, "checkConstraints-success");
395 
396   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
397       tab->GetMainFrame(),
398       base::StringPrintf("runGetUserMedia({ video: { %s: true } });",
399                          Constraint()),
400       &result));
401   EXPECT_EQ(result, "runGetUserMedia-success");
402 
403   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
404       tab->GetMainFrame(), "checkConstraints({});", &result));
405   EXPECT_EQ(result, "checkConstraints-success");
406 }
407 
408 INSTANTIATE_TEST_SUITE_P(ConstraintsFromGetUserMedia,
409                          WebRtcPanTiltZoomConstraintsBrowserTest,
410                          testing::Values("pan", "tilt", "zoom"));
411 
412 class WebRtcPanTiltZoomPermissionRequestBrowserTest
413     : public WebRtcTestBase,
414       public ::testing::WithParamInterface<
415           bool /* IsPanTiltZoomSupported() */> {
416  public:
SetUpCommandLine(base::CommandLine * command_line)417   void SetUpCommandLine(base::CommandLine* command_line) override {
418     command_line->AppendSwitchASCII(
419         switches::kEnableBlinkFeatures,
420         "MediaCapturePanTilt,PermissionsRequestRevoke");
421   }
422 
IsPanTiltZoomSupported() const423   bool IsPanTiltZoomSupported() const { return GetParam(); }
424 
SetUpOnMainThread()425   void SetUpOnMainThread() override {
426     WebRtcTestBase::SetUpOnMainThread();
427 
428     media::VideoCaptureControlSupport control_support;
429     control_support.pan = IsPanTiltZoomSupported();
430     control_support.tilt = IsPanTiltZoomSupported();
431     control_support.zoom = IsPanTiltZoomSupported();
432     blink::MediaStreamDevices video_devices;
433     blink::MediaStreamDevice fake_video_device(
434         blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE, "fake_video_dev",
435         "Fake Video Device", control_support, media::MEDIA_VIDEO_FACING_NONE,
436         base::nullopt);
437     video_devices.push_back(fake_video_device);
438     MediaCaptureDevicesDispatcher::GetInstance()->SetTestVideoCaptureDevices(
439         video_devices);
440   }
441 
SetUpInProcessBrowserTestFixture()442   void SetUpInProcessBrowserTestFixture() override {
443     DetectErrorsInJavaScript();
444   }
445 };
446 
IN_PROC_BROWSER_TEST_P(WebRtcPanTiltZoomPermissionRequestBrowserTest,TestRequestPanTiltZoomPermission)447 IN_PROC_BROWSER_TEST_P(WebRtcPanTiltZoomPermissionRequestBrowserTest,
448                        TestRequestPanTiltZoomPermission) {
449   ASSERT_TRUE(embedded_test_server()->Start());
450   content::WebContents* tab = OpenTestPageInNewTab(kMainHtmlPage);
451 
452   std::string result;
453   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
454       tab->GetMainFrame(), "runRequestPanTiltZoom();", &result));
455   EXPECT_EQ(result, "runRequestPanTiltZoom-success");
456 
457   std::string camera;
458   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
459       tab->GetMainFrame(), "getCameraPermission();", &camera));
460   EXPECT_EQ(camera, "granted");
461 
462   std::string pan_tilt_zoom;
463   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
464       tab->GetMainFrame(), "getPanTiltZoomPermission();", &pan_tilt_zoom));
465   EXPECT_EQ(pan_tilt_zoom, IsPanTiltZoomSupported() ? "granted" : "prompt");
466 }
467 
468 INSTANTIATE_TEST_SUITE_P(RequestPanTiltZoomPermission,
469                          WebRtcPanTiltZoomPermissionRequestBrowserTest,
470                          ::testing::Bool() /* IsPanTiltZoomSupported() */);
471 
472 class WebRtcPanTiltZoomCameraDevicesBrowserTest : public WebRtcTestBase {
473  public:
SetUpCommandLine(base::CommandLine * command_line)474   void SetUpCommandLine(base::CommandLine* command_line) override {
475     command_line->AppendSwitchASCII(
476         switches::kEnableBlinkFeatures,
477         "MediaCapturePanTilt,PermissionsRequestRevoke");
478   }
479 
SetVideoCaptureDevice(bool pan_supported,bool tilt_supported,bool zoom_supported)480   void SetVideoCaptureDevice(bool pan_supported,
481                              bool tilt_supported,
482                              bool zoom_supported) {
483     blink::MediaStreamDevices video_devices;
484     blink::MediaStreamDevice fake_video_device(
485         blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE, "fake_video_dev",
486         "Fake Video Device", {pan_supported, tilt_supported, zoom_supported},
487         media::MEDIA_VIDEO_FACING_NONE, base::nullopt);
488     video_devices.push_back(fake_video_device);
489     MediaCaptureDevicesDispatcher::GetInstance()->SetTestVideoCaptureDevices(
490         video_devices);
491   }
492 
SetUpInProcessBrowserTestFixture()493   void SetUpInProcessBrowserTestFixture() override {
494     DetectErrorsInJavaScript();
495   }
496 };
497 
IN_PROC_BROWSER_TEST_F(WebRtcPanTiltZoomCameraDevicesBrowserTest,TestCameraPanTiltZoomPermissionIsNotGrantedAfterCamera)498 IN_PROC_BROWSER_TEST_F(WebRtcPanTiltZoomCameraDevicesBrowserTest,
499                        TestCameraPanTiltZoomPermissionIsNotGrantedAfterCamera) {
500   ASSERT_TRUE(embedded_test_server()->Start());
501   content::WebContents* tab = OpenTestPageInNewTab(kMainHtmlPage);
502 
503   // Simulate camera device with no PTZ support and request PTZ camera
504   // permission.
505   SetVideoCaptureDevice(/*pan_supported=*/false, /*tilt_supported=*/false,
506                         /*zoom_supported=*/false);
507   std::string result;
508   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
509       tab->GetMainFrame(), "runRequestPanTiltZoom();", &result));
510   EXPECT_EQ(result, "runRequestPanTiltZoom-success");
511 
512   // Camera permission should be granted.
513   std::string camera;
514   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
515       tab->GetMainFrame(), "getCameraPermission();", &camera));
516   EXPECT_EQ(camera, "granted");
517 
518   // Camera PTZ permission should not be granted.
519   std::string pan_tilt_zoom;
520   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
521       tab->GetMainFrame(), "getPanTiltZoomPermission();", &pan_tilt_zoom));
522   EXPECT_EQ(pan_tilt_zoom, "prompt");
523 
524   // Simulate camera device with PTZ support.
525   SetVideoCaptureDevice(/*pan_supported=*/true, /*tilt_supported=*/true,
526                         /*zoom_supported=*/true);
527 
528   // Camera PTZ permission should still not be granted.
529   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
530       tab->GetMainFrame(), "getPanTiltZoomPermission();", &pan_tilt_zoom));
531   EXPECT_EQ(pan_tilt_zoom, "prompt");
532 }
533 
IN_PROC_BROWSER_TEST_F(WebRtcPanTiltZoomCameraDevicesBrowserTest,TestCameraPanTiltZoomPermissionPersists)534 IN_PROC_BROWSER_TEST_F(WebRtcPanTiltZoomCameraDevicesBrowserTest,
535                        TestCameraPanTiltZoomPermissionPersists) {
536   ASSERT_TRUE(embedded_test_server()->Start());
537   content::WebContents* tab = OpenTestPageInNewTab(kMainHtmlPage);
538 
539   // Simulate camera device with PTZ support and request PTZ camera permission.
540   SetVideoCaptureDevice(/*pan_supported=*/true, /*tilt_supported=*/true,
541                         /*zoom_supported=*/true);
542   std::string result;
543   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
544       tab->GetMainFrame(), "runRequestPanTiltZoom();", &result));
545   EXPECT_EQ(result, "runRequestPanTiltZoom-success");
546 
547   // Camera permission should be granted.
548   std::string camera;
549   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
550       tab->GetMainFrame(), "getCameraPermission();", &camera));
551   EXPECT_EQ(camera, "granted");
552 
553   // Camera PTZ permission should be granted.
554   std::string pan_tilt_zoom;
555   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
556       tab->GetMainFrame(), "getPanTiltZoomPermission();", &pan_tilt_zoom));
557   EXPECT_EQ(pan_tilt_zoom, "granted");
558 
559   // Simulate camera device with no PTZ support.
560   SetVideoCaptureDevice(/*pan_supported=*/false, /*tilt_supported=*/false,
561                         /*zoom_supported=*/false);
562 
563   // Camera PTZ permission should still be granted.
564   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
565       tab->GetMainFrame(), "getPanTiltZoomPermission();", &pan_tilt_zoom));
566   EXPECT_EQ(pan_tilt_zoom, "granted");
567 }
568 
569 class WebRtcPanTiltZoomFakeCameraDevicesBrowserTest : public WebRtcTestBase {
570  public:
SetUpCommandLine(base::CommandLine * command_line)571   void SetUpCommandLine(base::CommandLine* command_line) override {
572     command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
573   }
574 
SetUpInProcessBrowserTestFixture()575   void SetUpInProcessBrowserTestFixture() override {
576     DetectErrorsInJavaScript();
577   }
578 };
579 
IN_PROC_BROWSER_TEST_F(WebRtcPanTiltZoomFakeCameraDevicesBrowserTest,TestPageVisible)580 IN_PROC_BROWSER_TEST_F(WebRtcPanTiltZoomFakeCameraDevicesBrowserTest,
581                        TestPageVisible) {
582   ASSERT_TRUE(embedded_test_server()->Start());
583   content::WebContents* tab = OpenTestPageInNewTab(kMainHtmlPage);
584 
585   // Access PTZ camera.
586   std::string result;
587   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
588       tab->GetMainFrame(),
589       "runGetUserMedia({ video: { pan: true, tilt: true, zoom: true } });",
590       &result));
591   EXPECT_EQ(result, "runGetUserMedia-success");
592 
593   // Hide page.
594   tab->WasHidden();
595   base::string16 expected_title = base::ASCIIToUTF16("hidden");
596   EXPECT_EQ(expected_title,
597             content::TitleWatcher(tab, expected_title).WaitAndGetTitle());
598 
599   // Pan can't be set when page is hidden.
600   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
601       tab->GetMainFrame(), "applyConstraints({ advanced: [{ pan: 102 }] });",
602       &result));
603   EXPECT_EQ(result, "applyConstraints-failure-SecurityError");
604 
605   // Tilt can't be set when page is hidden.
606   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
607       tab->GetMainFrame(), "applyConstraints({ advanced: [{ tilt: 102 }] });",
608       &result));
609   EXPECT_EQ(result, "applyConstraints-failure-SecurityError");
610 
611   // Zoom can't be set when page is hidden.
612   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
613       tab->GetMainFrame(), "applyConstraints({ advanced: [{ zoom: 102 }] });",
614       &result));
615   EXPECT_EQ(result, "applyConstraints-failure-SecurityError");
616 
617   // Show page.
618   tab->WasShown();
619   expected_title = base::ASCIIToUTF16("visible");
620   EXPECT_EQ(expected_title,
621             content::TitleWatcher(tab, expected_title).WaitAndGetTitle());
622 
623   // Pan can be set when page is shown again.
624   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
625       tab->GetMainFrame(), "applyConstraints({ advanced: [{ pan: 102 }] });",
626       &result));
627   EXPECT_EQ(result, "applyConstraints-success");
628 
629   // Tilt can be set when page is shown again.
630   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
631       tab->GetMainFrame(), "applyConstraints({ advanced: [{ tilt: 102 }] });",
632       &result));
633   EXPECT_EQ(result, "applyConstraints-success");
634 
635   // Zoom can be set when page is shown again.
636   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
637       tab->GetMainFrame(), "applyConstraints({ advanced: [{ zoom: 102 }] });",
638       &result));
639   EXPECT_EQ(result, "applyConstraints-success");
640 }
641