Bug 1452536 - Test that key events for non-printable keys and interaction with editable elements don't unblock autoplay. r=masayuki
authorChris Pearce <cpearce@mozilla.com>
Wed, 11 Apr 2018 17:07:05 +1200
changeset 473204 9c2deb188bdf3065b8f871426fc4d640bd3ea6ea
parent 473203 2f2a7a27a90f45558b26f39b83e9b83c28d3f0fe
child 473205 65789d9edfe6037dfebc431d97892d38a5c7e05a
push id1728
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:12:27 +0000
treeherdermozilla-release@c296fde26f5f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmasayuki
bugs1452536
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1452536 - Test that key events for non-printable keys and interaction with editable elements don't unblock autoplay. r=masayuki MozReview-Commit-ID: 55TfHTUyJfz
dom/media/test/file_autoplay_policy_key_blacklist.html
dom/media/test/mochitest.ini
dom/media/test/test_autoplay_policy_key_blacklist.html
new file mode 100644
--- /dev/null
+++ b/dom/media/test/file_autoplay_policy_key_blacklist.html
@@ -0,0 +1,165 @@
+<!DOCTYPE HTML>
+<html>
+
+<head>
+  <title>Autoplay policy window</title>
+  <style>
+    video {
+      width: 50%;
+      height: 50%;
+    }
+    :focus {
+      background-color: blue;
+    }
+  </style>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <script type="text/javascript" src="manifest.js"></script>
+  <script type="text/javascript" src="AutoplayTestUtils.js"></script>
+</head>
+
+<body>
+  <div id="x">This is a div with id=x.</div>
+  <pre id="test">
+      <input type="text" id="text-input"/>
+      <script>
+
+        window.ok = window.opener.ok;
+        window.is = window.opener.is;
+        window.info = window.opener.info;
+
+        // Keys that are expected to be not considered interaction with the page, and
+        // so not gesture activate the document.
+        let blacklistKeyPresses = [
+          "Tab",
+          "CapsLock",
+          "NumLock",
+          "ScrollLock",
+          "FnLock",
+          "Meta",
+          "OS",
+          "Hyper",
+          "Super",
+          "ContextMenu",
+          "ArrowUp",
+          "ArrowDown",
+          "ArrowLeft",
+          "ArrowRight",
+          "PageUp",
+          "PageDown",
+          "Home",
+          "End",
+          "Backspace",
+          "Fn",
+          "Alt",
+          "AltGraph",
+          "Control",
+          "Shift",
+          "Escape",
+        ];
+
+        let modifiedKeys = [
+          { key: "c", modifiers: { ctrlKey: true } },
+          { key: "V", modifiers: { ctrlKey: true, shiftKey: true } },
+          { key: "a", modifiers: { altKey: true } },
+          { key: "KEY_ArrowRight", modifiers: { metaKey: true } },
+          { key: "KEY_ArrowRight", modifiers: { altKey: true } },
+        ];
+
+        async function sendInput(element, name, input) {
+          synthesizeMouseAtCenter(input, {});
+          let played = await element.play().then(() => true, () => false);
+          ok(!played, "Clicking " + name + " should not activate document and should not unblock play");
+
+          synthesizeCompositionChange({
+            composition: {
+              string: "\u30E9\u30FC\u30E1\u30F3",
+              clauses: [
+                { length: 4, attr: COMPOSITION_ATTR_RAW_CLAUSE }
+              ]
+            },
+            caret: { start: 4, length: 0 }
+          });
+          synthesizeComposition({ type: "compositioncommitasis" });
+          played = await element.play().then(() => true, () => false);
+          ok(!played, "Entering text to " + name + " via IME should not activate document and should not unblock play");
+
+          input.focus();
+          sendString("ascii text");
+          played = await element.play().then(() => true, () => false);
+          ok(!played, "Entering ASCII text into " + name + " should not activate document and should not unblock play");
+
+          input.blur();
+        }
+
+        async function testAutoplayKeyBlacklist(testCase, parent_window) {
+          let element = document.createElement("video");
+          element.preload = "auto";
+          element.src = "short.mp4";
+          document.body.appendChild(element);
+
+          await once(element, "loadedmetadata");
+
+          let played = await element.play().then(() => true, () => false);
+          is(played, false, "Document should start out not activated, with playback blocked.");
+
+          // Try pressing all the keys in the blacklist, then playing.
+          // Document should not be activated, so play should fail.
+
+          for (let key of blacklistKeyPresses) {
+            document.body.focus();
+            synthesizeKey("KEY_" + key);
+            played = await element.play().then(() => true, () => false);
+            is(played, false, "Key " + key + " should not activate document and should not unblock play");
+          }
+
+          // Try pressing some keys with modifiers.
+          let keyNames = (m) => Object.keys(m).join("+");
+          for (let x of modifiedKeys) {
+            document.body.focus();
+            synthesizeKey(x.key, x.modifiers);
+            played = await element.play().then(() => true, () => false);
+            is(played, false, "Key (" + x.key + "+" + keyNames(x.modifiers) + ") should not activate document and should not unblock play");
+          }
+
+          // Test that clicking/typing into an input element doesn't activate.
+          let input = document.getElementById("text-input");
+          await sendInput(element, "input", input);
+
+          // Test that clicking/typing into a contentEditable div element doesn't activate.
+          let div = document.getElementById("x");
+          div.contentEditable = "true";
+          await sendInput(element, "contentEditable div", div);
+          div.contentEditable = "false";
+
+          // Test that clicking/typing into a div inside a designMode document doesn't activate.
+          document.designMode = "on";
+          await sendInput(element, "div in designMode=on", div);
+          document.designMode = "off";
+
+          // Try pressing a key not in the blacklist, then playing.
+          // Document should be activated, and media should play.
+
+          is(document.activeElement, document.body, "Focus needs to be the document, not an editable or text control.");
+          synthesizeKey(" ");
+          played = await element.play().then(() => true, () => false);
+          is(played, true, "Space key should activate document and should unblock play");
+
+          removeNodeAndSource(element);
+        }
+
+        nextWindowMessage().then(
+          async (event) => {
+            try {
+              await testAutoplayKeyBlacklist(event.data, event.source);
+            } catch (e) {
+              ok(false, "Caught exception " + e + " " + e.message + " " + e.stackTrace);
+            }
+            event.source.postMessage("done", "*");
+          });
+
+      </script>
+    </pre>
+</body>
+
+</html>
--- a/dom/media/test/mochitest.ini
+++ b/dom/media/test/mochitest.ini
@@ -433,16 +433,17 @@ support-files =
   detodos-short.opus
   detodos-short.opus^headers^
   dirac.ogg
   dirac.ogg^headers^
   dynamic_resource.sjs
   eme.js
   file_access_controls.html
   file_autoplay_policy_eventdown_activation.html
+  file_autoplay_policy_key_blacklist.html
   file_autoplay_policy_unmute_pauses.html
   file_autoplay_policy_activation_window.html
   file_autoplay_policy_activation_frame.html
   file_autoplay_policy_play_before_loadedmetadata.html
   flac-s24.flac
   flac-s24.flac^headers^
   flac-noheader-s16.flac
   flac-noheader-s16.flac^headers^
@@ -692,16 +693,18 @@ skip-if = true # bug 475110 - disabled s
 [test_autoplay_contentEditable.html]
 skip-if = android_version == '15' || android_version == '17' || android_version == '22' # android(bug 1232305, bug 1232318, bug 1372457)
 [test_autoplay_policy.html]
 skip-if = android_version == '23' # bug 1424903
 [test_autoplay_policy_activation.html]
 skip-if = android_version == '23' # bug 1424903
 [test_autoplay_policy_eventdown_activation.html]
 skip-if = android_version == '23' # bug 1424903
+[test_autoplay_policy_key_blacklist.html]
+skip-if = android_version == '23' # bug 1424903
 [test_autoplay_policy_unmute_pauses.html]
 skip-if = android_version == '23' # bug 1424903
 [test_autoplay_policy_play_before_loadedmetadata.html]
 skip-if = android_version == '23' # bug 1424903
 [test_buffered.html]
 skip-if = android_version == '15' || android_version == '22' # bug 1308388, android(bug 1232305)
 [test_bug448534.html]
 [test_bug463162.xhtml]
new file mode 100644
--- /dev/null
+++ b/dom/media/test/test_autoplay_policy_key_blacklist.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+
+<head>
+  <title>Autoplay policy test</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+  <script type="text/javascript" src="manifest.js"></script>
+  <script type="text/javascript" src="AutoplayTestUtils.js"></script>
+</head>
+
+<body>
+  <pre id="test">
+      <script>
+
+        // Tests that keypresses for non-printable characters,
+        // and mouse/keyboard interaction with editable elements,
+        // don't gesture activate documents, and don't unblock
+        // audible autoplay.
+
+        gTestPrefs.push(["media.autoplay.enabled", false],
+          ["media.autoplay.enabled.user-gestures-needed", true]);
+
+        SpecialPowers.pushPrefEnv({ 'set': gTestPrefs }, () => {
+          runTest();
+        });
+
+        let child_url = "file_autoplay_policy_key_blacklist.html";
+
+        async function runTest() {
+          // Run test in a new window, to ensure its user gesture
+          // activation state isn't tainted by preceeding tests.
+          let child = window.open(child_url, "", "width=500,height=500");
+          await once(child, "load");
+          child.postMessage("run test", window.origin);
+          let result = await nextWindowMessage();
+          child.close();
+          SimpleTest.finish();
+        }
+
+        SimpleTest.waitForExplicitFinish();
+
+      </script>
+    </pre>
+</body>
+
+</html>
\ No newline at end of file