Add more tests covering constraints usage in getDisplayMedia()

Bug: 326740
Change-Id: I923fb55c07424573d2a2829f8c5ef22fc4e28466
Reviewed-on: https://chromium-review.googlesource.com/c/1292371
Reviewed-by: Guido Urdaneta <guidou@chromium.org>
Reviewed-by: Henrik Boström <hbos@chromium.org>
Commit-Queue: Emircan Uysaler <emircan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#602709}
diff --git a/chrome/browser/media/webrtc/webrtc_getdisplaymedia_browsertest.cc b/chrome/browser/media/webrtc/webrtc_getdisplaymedia_browsertest.cc
index 1a6068f..0248cfe 100644
--- a/chrome/browser/media/webrtc/webrtc_getdisplaymedia_browsertest.cc
+++ b/chrome/browser/media/webrtc/webrtc_getdisplaymedia_browsertest.cc
@@ -56,12 +56,12 @@
 
 // Real desktop capture is flaky on below platforms.
 #if defined(OS_CHROMEOS) || defined(OS_WIN)
-#define MAYBE_MANUAL_GetDisplayMediaVideo DISABLED_MANUAL_GetDisplayMediaVideo
+#define MAYBE_GetDisplayMediaVideo DISABLED_GetDisplayMediaVideo
 #else
-#define MAYBE_MANUAL_GetDisplayMediaVideo MANUAL_GetDisplayMediaVideo
+#define MAYBE_GetDisplayMediaVideo GetDisplayMediaVideo
 #endif
 IN_PROC_BROWSER_TEST_F(WebRtcGetDisplayMediaBrowserTestWithPicker,
-                       MAYBE_MANUAL_GetDisplayMediaVideo) {
+                       MAYBE_GetDisplayMediaVideo) {
   ASSERT_TRUE(embedded_test_server()->Start());
 
   content::WebContents* tab = OpenTestPageInNewTab(kMainHtmlPage);
@@ -94,7 +94,7 @@
 };
 
 IN_PROC_BROWSER_TEST_P(WebRtcGetDisplayMediaBrowserTestWithFakeUI,
-                       MANUAL_GetDisplayMedia) {
+                       GetDisplayMedia) {
   ASSERT_TRUE(embedded_test_server()->Start());
 
   content::WebContents* tab = OpenTestPageInNewTab(kMainHtmlPage);
@@ -115,6 +115,28 @@
   EXPECT_EQ(result, test_config_.cursor);
 }
 
+IN_PROC_BROWSER_TEST_P(WebRtcGetDisplayMediaBrowserTestWithFakeUI,
+                       GetDisplayMediaWithConstraints) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+
+  content::WebContents* tab = OpenTestPageInNewTab(kMainHtmlPage);
+  const int kMaxWidth = 200;
+  const int kMaxFrameRate = 6;
+  const std::string& constraints =
+      base::StringPrintf("{video: {width: {max: %d}, frameRate: {max: %d}}}",
+                         kMaxWidth, kMaxFrameRate);
+  RunGetDisplayMedia(tab, constraints);
+
+  std::string result;
+  EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+      tab->GetMainFrame(), "getWidthSetting();", &result));
+  EXPECT_EQ(result, base::StringPrintf("%d", kMaxWidth));
+
+  EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+      tab->GetMainFrame(), "getFrameRateSetting();", &result));
+  EXPECT_EQ(result, base::StringPrintf("%d", kMaxFrameRate));
+}
+
 INSTANTIATE_TEST_CASE_P(,
                         WebRtcGetDisplayMediaBrowserTestWithFakeUI,
                         testing::Values(TestConfig{"monitor", "true", "never"},
diff --git a/chrome/test/data/webrtc/webrtc_getdisplaymedia_test.html b/chrome/test/data/webrtc/webrtc_getdisplaymedia_test.html
index c124a82..e936818 100644
--- a/chrome/test/data/webrtc/webrtc_getdisplaymedia_test.html
+++ b/chrome/test/data/webrtc/webrtc_getdisplaymedia_test.html
@@ -38,6 +38,14 @@
   function getCursorSetting() {
     returnToTest(settings.cursor);
   }
+
+  function getWidthSetting() {
+    returnToTest(settings.width.toString());
+  }
+
+  function getFrameRateSetting() {
+    returnToTest(settings.frameRate.toString());
+  }
   </script>
 </head>
 <body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/screen-capture/getdisplaymedia.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/screen-capture/getdisplaymedia.https-expected.txt
index 0f2d8d8..d73ca783 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/screen-capture/getdisplaymedia.https-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/screen-capture/getdisplaymedia.https-expected.txt
@@ -4,10 +4,12 @@
 PASS getDisplayMedia() with video false
 PASS getDisplayMedia() with audio false
 FAIL getDisplayMedia() with audio true promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getDisplayMedia' on 'Navigator': Audio capture is not supported"
-PASS getDisplayMedia() call with advanced constraint
-PASS getDisplayMedia() call with min constraint
-PASS getDisplayMedia() call with exact constraint
-PASS getDisplayMedia() call with max constraint
+PASS getDisplayMedia() with advanced constraint
+PASS getDisplayMedia() with min constraint
+PASS getDisplayMedia() with exact constraint
+PASS getDisplayMedia() with max constraint
+PASS getDisplayMedia() with constraints applied
+PASS getDisplayMedia() overconstrained
 PASS getDisplayMedia() with getSettings
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/screen-capture/getdisplaymedia.https.html b/third_party/WebKit/LayoutTests/external/wpt/screen-capture/getdisplaymedia.https.html
index f5edab5..06ab72d2 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/screen-capture/getdisplaymedia.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/screen-capture/getdisplaymedia.https.html
@@ -6,115 +6,150 @@
 <script>
   'use strict';
 
-promise_test(function() {
+promise_test(async t => {
   assert_idl_attribute(navigator, 'getDisplayMedia');
-
-  return navigator.getDisplayMedia({video: true}).then(function(s) {
-    assert_equals(s.getVideoTracks().length, 1);
-    assert_equals(s.getAudioTracks().length, 0);
-  });
+  const stream = await navigator.getDisplayMedia({video: true});
+  const [track] = stream.getTracks();
+  t.add_cleanup(() => track.stop());
+  assert_equals(stream.getTracks().length, 1);
+  assert_equals(stream.getVideoTracks().length, 1);
+  assert_equals(stream.getAudioTracks().length, 0);
 }, 'getDisplayMedia() with video true');
 
 // Empty constraint parameter and boolean values of false defaults to
-// {video: true}.
-promise_test(function() {
+// {video: true}. This is described in items 3-4 of section 5.1, see
+// https://w3c.github.io/mediacapture-screen-share/#navigator-additions.
+// Note that this results in some non-intuitive cases returning a video track,
+// i.e. {video: false}.
+promise_test(async t => {
   assert_idl_attribute(navigator, 'getDisplayMedia');
-
-  return navigator.getDisplayMedia().then(function(s) {
-    assert_equals(s.getVideoTracks().length, 1);
-    assert_equals(s.getAudioTracks().length, 0);
-  });
+  const stream = await navigator.getDisplayMedia();
+  const [track] = stream.getTracks();
+  t.add_cleanup(() => track.stop());
+  assert_equals(stream.getTracks().length, 1);
+  assert_equals(stream.getVideoTracks().length, 1);
+  assert_equals(stream.getAudioTracks().length, 0);
 }, 'getDisplayMedia() with no constraints');
 
-promise_test(function() {
+promise_test(async t => {
   assert_idl_attribute(navigator, 'getDisplayMedia');
-
-  return navigator.getDisplayMedia({video: false}).then(function(s) {
-    assert_equals(s.getVideoTracks().length, 1);
-    assert_equals(s.getAudioTracks().length, 0);
-  });
+  const stream = await navigator.getDisplayMedia({video: false});
+  const [track] = stream.getTracks();
+  t.add_cleanup(() => track.stop());
+  assert_equals(stream.getTracks().length, 1);
+  assert_equals(stream.getVideoTracks().length, 1);
+  assert_equals(stream.getAudioTracks().length, 0);
 }, 'getDisplayMedia() with video false');
 
-promise_test(function() {
+promise_test(async t => {
   assert_idl_attribute(navigator, 'getDisplayMedia');
-
-  return navigator.getDisplayMedia({audio: false}).then(function(s) {
-    assert_equals(s.getVideoTracks().length, 1);
-    assert_equals(s.getAudioTracks().length, 0);
-  });
+  const stream = await navigator.getDisplayMedia({audio: false});
+  const [track] = stream.getTracks();
+  t.add_cleanup(() => track.stop());
+  assert_equals(stream.getTracks().length, 1);
+  assert_equals(stream.getVideoTracks().length, 1);
+  assert_equals(stream.getAudioTracks().length, 0);
 }, 'getDisplayMedia() with audio false');
 
-promise_test(function() {
+promise_test(async t => {
   assert_idl_attribute(navigator, 'getDisplayMedia');
-
-  return navigator.getDisplayMedia({audio: true}).then(function(s) {
-    assert_equals(s.getVideoTracks().length, 0);
-    assert_equals(s.getAudioTracks().length, 1);
-  });
+  const stream = await navigator.getDisplayMedia({audio: true});
+  const [track] = stream.getTracks();
+  t.add_cleanup(() => track.stop());
+  assert_equals(stream.getTracks().length, 1);
+  assert_equals(stream.getVideoTracks().length, 0);
+  assert_equals(stream.getAudioTracks().length, 1);
 }, 'getDisplayMedia() with audio true');
 
-promise_test(function() {
+promise_test(async t => {
   assert_idl_attribute(navigator, 'getDisplayMedia');
+  try {
+    const stream =
+        await navigator.getDisplayMedia({video: {advanced: [{zoom: 1}]}});
+  } catch (err) {
+    assert_equals(err.name, 'TypeError');
+    return;
+  }
+  assert_unreached('getDisplayMedia should have failed');
+}, 'getDisplayMedia() with advanced constraint');
 
-  return navigator
-      .getDisplayMedia({video: {advanced: [{zoom: 1}]}})
-      .then(function(s) {
-        fail('getDisplayMedia should have failed');
-      })
-      .catch(function(e) {
-        assert_equals(e.name, 'TypeError');
-      });
-}, 'getDisplayMedia() call with advanced constraint');
-
-promise_test(function() {
+promise_test(async t => {
   assert_idl_attribute(navigator, 'getDisplayMedia');
+  try {
+    const stream =
+        await navigator.getDisplayMedia({video: {width: {min: 360}}});
+  } catch (err) {
+    assert_equals(err.name, 'TypeError');
+    return;
+  }
+  assert_unreached('getDisplayMedia should have failed');
+}, 'getDisplayMedia() with min constraint');
 
-  return navigator
-      .getDisplayMedia({video: {width: {min: 360}}})
-      .then(function(s) {
-        fail('getDisplayMedia should have failed');
-      })
-      .catch(function(e) {
-        assert_equals(e.name, 'TypeError');
-      });
-}, 'getDisplayMedia() call with min constraint');
-
-promise_test(function() {
+promise_test(async t => {
   assert_idl_attribute(navigator, 'getDisplayMedia');
+  try {
+    const stream =
+        await navigator.getDisplayMedia({video: {width: {exact: 360}}});
+  } catch (err) {
+    assert_equals(err.name, 'TypeError');
+    return;
+  }
+  assert_unreached('getDisplayMedia should have failed');
+}, 'getDisplayMedia() with exact constraint');
 
-  return navigator
-      .getDisplayMedia({video: {width: {exact: 360}}})
-      .then(function(s) {
-        fail('getDisplayMedia should have failed');
-      })
-      .catch(function(e) {
-        assert_equals(e.name, 'TypeError');
-      });
-}, 'getDisplayMedia() call with exact constraint');
-
-promise_test(function() {
+promise_test(async t => {
   assert_idl_attribute(navigator, 'getDisplayMedia');
+  const maxWidth = 360;
+  const stream =
+      await navigator.getDisplayMedia({video: {width: {max: maxWidth}}});
+  const [track] = stream.getTracks();
+  t.add_cleanup(() => track.stop());
+  assert_equals(stream.getVideoTracks().length, 1);
+  assert_equals(stream.getAudioTracks().length, 0);
+  assert_less_than_equal(
+      stream.getVideoTracks()[0].getSettings().width, maxWidth);
+}, 'getDisplayMedia() with max constraint');
 
-  return navigator
-      .getDisplayMedia({video: {width: {max: 360}}})
-      .then(function(s) {
-        assert_equals(s.getVideoTracks().length, 1);
-        assert_equals(s.getAudioTracks().length, 0);
-      });
-}, 'getDisplayMedia() call with max constraint');
+promise_test(async t => {
+  assert_idl_attribute(navigator, 'getDisplayMedia');
+  const maxWidth = 360;
+  const maxFrameRate = 4;
+  const stream = await navigator.getDisplayMedia(
+      {video: {width: {max: maxWidth}, frameRate: {max: maxFrameRate}}});
+  const [track] = stream.getTracks();
+  t.add_cleanup(() => track.stop());
+  assert_equals(stream.getVideoTracks().length, 1);
+  assert_equals(stream.getAudioTracks().length, 0);
+  const settings = stream.getVideoTracks()[0].getSettings();
+  assert_less_than_equal(settings.width, maxWidth);
+  assert_less_than_equal(settings.frameRate, maxFrameRate);
+}, 'getDisplayMedia() with constraints applied');
+
+promise_test(async t => {
+  assert_idl_attribute(navigator, 'getDisplayMedia');
+  try {
+    const stream = await navigator.getDisplayMedia({video: {width: {max: 0}}});
+  } catch (err) {
+    assert_equals(err.name, 'OverconstrainedError');
+    return;
+  }
+  assert_unreached('getDisplayMedia should have failed');
+}, 'getDisplayMedia() overconstrained');
 
 // Content shell picks a fake desktop device by default.
-promise_test(function() {
+promise_test(async t => {
   assert_idl_attribute(navigator, 'getDisplayMedia');
-
-  return navigator.getDisplayMedia({video: true}).then(function(s) {
-    assert_equals(s.getVideoTracks().length, 1);
-    assert_equals(s.getAudioTracks().length, 0);
-    var settings = s.getVideoTracks()[0].getSettings();
-    assert_equals(settings.displaySurface, "monitor");
-    assert_equals(settings.logicalSurface, true);
-    assert_equals(settings.cursor, "never");
-  });
+  const stream = await navigator.getDisplayMedia({video: true});
+  const [track] = stream.getTracks();
+  t.add_cleanup(() => track.stop());
+  assert_equals(stream.getVideoTracks().length, 1);
+  assert_equals(stream.getAudioTracks().length, 0);
+  const settings = stream.getVideoTracks()[0].getSettings();
+  assert_any(
+      assert_equals, settings.displaySurface,
+      ['monitor', 'window', 'application', 'browser']);
+  assert_any(assert_equals, settings.logicalSurface, [true, false]);
+  assert_any(assert_equals, settings.cursor, ['never', 'always', 'motion']);
 }, 'getDisplayMedia() with getSettings');
 
 </script>