Bug 1452536 - Test that key events for non-printable keys and interaction with editable elements don't unblock autoplay. r=masayuki draft
authorChris Pearce <cpearce@mozilla.com>
Wed, 11 Apr 2018 17:07:05 +1200
changeset 789578 4607e548eb810cc6a124b908a299c9552952370d
parent 789577 b2267f5ae2c9f0f6626f622bc98e3c5f18faf8bb
child 789671 7467bf265f161a801b3e67f13ec0654ed0d1bb8e
push id108288
push userbmo:cpearce@mozilla.com
push dateSun, 29 Apr 2018 23:02:14 +0000
reviewersmasayuki
bugs1452536
milestone61.0a1
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