Bug 1428722 - part3 : add tests. draft
authorAlastor Wu <alwu@mozilla.com>
Thu, 11 Jan 2018 17:27:08 +0800
changeset 720214 7c8f71b8f0ea8854b69ed83f4d76ba4366d32485
parent 720213 088dfff9856d86b4ec4d41269f21736b3b6cec35
child 746006 9ad3b4a4edf1c3164f5cc98d39b173b62905dc1e
push id95482
push userbmo:alwu@mozilla.com
push dateMon, 15 Jan 2018 03:52:14 +0000
bugs1428722
milestone59.0a1
Bug 1428722 - part3 : add tests. MozReview-Commit-ID: 4WfADcQinuQ
toolkit/content/tests/browser/browser.ini
toolkit/content/tests/browser/browser_autoplay_policy_iframe_hierarchy.js
toolkit/content/tests/browser/file_autoplay_three_layers_frame1.html
toolkit/content/tests/browser/file_autoplay_three_layers_frame2.html
toolkit/content/tests/browser/file_autoplay_two_layers_frame1.html
toolkit/content/tests/browser/file_autoplay_two_layers_frame2.html
--- a/toolkit/content/tests/browser/browser.ini
+++ b/toolkit/content/tests/browser/browser.ini
@@ -25,16 +25,24 @@ support-files =
   silentAudioTrack.webm
   doggy.png
   firebird.png
 
 [browser_audioCompeting.js]
 tags = audiochannel
 [browser_audioCompeting_onlyForActiveAgent.js]
 tags = audiochannel
+[browser_autoplay_policy_iframe_hierarchy.js]
+support-files =
+  file_autoplay_three_layers_frame1.html
+  file_autoplay_three_layers_frame2.html
+  file_autoplay_two_layers_frame1.html
+  file_autoplay_two_layers_frame2.html
+  file_video.html
+  gizmo.mp4
 [browser_autoplay_policy_play_twice.js]
 support-files =
   gizmo.mp4
   file_video.html
 [browser_autoplay_policy_user_gestures.js]
 support-files =
   gizmo.mp4
   file_video.html
new file mode 100644
--- /dev/null
+++ b/toolkit/content/tests/browser/browser_autoplay_policy_iframe_hierarchy.js
@@ -0,0 +1,168 @@
+/**
+ * Test whether the autoplay permission can be transfer well through different
+ * frame hierarchy. When the target frame has been interacted with the user
+ * gesture, it would has the autoplay permission, then the permission would be
+ * propagated to its parent and child frames.
+ *
+ * In this test, I use A/B/C to indicate different domain frames, and the number
+ * after the name is which layer the frame is in.
+ * Ex. A1 -> B2 -> A3,
+ * Top frame and grandchild frame is in the domain A, and child frame is in the
+ * domain B.
+ *
+ * Child frames could get permission if they have same origin as target frame's
+ * Parent frames could get permission if they have same origin as target frame's
+ * or the frame is in the top level.
+ * Ex. A1 -> B2 -> B3,
+ * A1 will always be activated no matter which level frame user activates with,
+ * since it's in the top level.
+ * B2/B3 will only be activated when user activates frame B2 or B3.
+ */
+const PAGE_A1_A2 = "https://example.com/browser/toolkit/content/tests/browser/file_autoplay_two_layers_frame1.html";
+const PAGE_A1_B2 = "https://example.com/browser/toolkit/content/tests/browser/file_autoplay_two_layers_frame2.html";
+const PAGE_A1_B2_C3 = "https://test1.example.org/browser/toolkit/content/tests/browser/file_autoplay_three_layers_frame1.html";
+const PAGE_A1_B2_A3 = "https://example.org/browser/toolkit/content/tests/browser/file_autoplay_three_layers_frame1.html";
+const PAGE_A1_B2_B3 = "https://example.org/browser/toolkit/content/tests/browser/file_autoplay_three_layers_frame2.html";
+const PAGE_A1_A2_A3 = "https://example.com/browser/toolkit/content/tests/browser/file_autoplay_three_layers_frame2.html";
+const PAGE_A1_A2_B3 = "https://example.com/browser/toolkit/content/tests/browser/file_autoplay_three_layers_frame1.html";
+
+function setup_test_preference() {
+  return SpecialPowers.pushPrefEnv({"set": [
+    ["media.autoplay.enabled", false],
+    ["media.autoplay.enabled.user-gestures-needed", true]
+  ]});
+}
+
+var frameTestArray = [
+  { name: "A1_A2",    layersNum: 2, src: PAGE_A1_A2 },
+  { name: "A1_B2",    layersNum: 2, src: PAGE_A1_B2 },
+  { name: "A1_B2_C3", layersNum: 3, src: PAGE_A1_B2_C3 },
+  { name: "A1_B2_A3", layersNum: 3, src: PAGE_A1_B2_A3 },
+  { name: "A1_B2_B3", layersNum: 3, src: PAGE_A1_B2_B3 },
+  { name: "A1_A2_A3", layersNum: 3, src: PAGE_A1_A2_A3 },
+  { name: "A1_A2_B3", layersNum: 3, src: PAGE_A1_A2_B3 }
+];
+
+async function test_permission_propagation(testName, testSrc, layersNum) {
+  info(`- start test for ${testName} -`);
+  for (let layerIdx = 1; layerIdx <= layersNum; layerIdx++) {
+    info("- open new tab -");
+    let tab = await BrowserTestUtils.openNewForegroundTab(window.gBrowser,
+                                                          "about:blank");
+    tab.linkedBrowser.loadURI(testSrc);
+    await BrowserTestUtils.browserLoaded(tab.linkedBrowser);
+
+    // If the frame isn't activated, the video play will fail.
+    async function playing_video_should_fail(layersNum) {
+      for (let layerIdx = 1; layerIdx <= layersNum; layerIdx++) {
+        let doc;
+        if (layerIdx == 1) {
+          doc = content.document;
+        } else {
+          doc = layerIdx == 2 ? content.frames[0].document :
+                                content.frames[0].frames[0].document;
+        }
+        await doc.getElementById("v").play().catch(function() {
+          ok(true, `video in layer ${layerIdx} can't start play without user input.`);
+        });
+      }
+    }
+    await ContentTask.spawn(tab.linkedBrowser, layersNum,
+                            playing_video_should_fail);
+
+    function activate_frame(testInfo) {
+      let layerIdx = testInfo[0];
+      info(`- activate frame in layer ${layerIdx} (${testInfo[1]}) -`);
+      let doc;
+      if (layerIdx == 1) {
+        doc = content.document;
+      } else {
+        doc = layerIdx == 2 ? content.frames[0].document :
+                              content.frames[0].frames[0].document;
+      }
+      doc.notifyUserActivation();
+    }
+    await ContentTask.spawn(tab.linkedBrowser, [layerIdx, testName],
+                            activate_frame);
+
+    // If frame is activated, the video play will succeed.
+    async function playing_video_may_success(testInfo) {
+      let activeLayerIdx = testInfo[0];
+      let testName = testInfo[1];
+      let layersNum = testInfo[2];
+      for (let layerIdx = 1; layerIdx <= layersNum; layerIdx++) {
+        let doc;
+        if (layerIdx == 1) {
+          doc = content.document;
+        } else {
+          doc = layerIdx == 2 ? content.frames[0].document :
+                                content.frames[0].frames[0].document;
+        }
+        let video = doc.getElementById("v");
+        let shouldSuccess = false;
+        let isActiveLayer = layerIdx == activeLayerIdx;
+        switch (testName) {
+          case "A1_A2":
+          case "A1_A2_A3":
+            // always success to play.
+            shouldSuccess = true;
+            break;
+          case "A1_B2":
+            shouldSuccess = layerIdx == 1 ||
+                            (layerIdx == 2 && isActiveLayer);
+            break;
+          case "A1_B2_C3":
+            shouldSuccess = layerIdx == 1 ||
+                            (layerIdx >= 2 && isActiveLayer);
+            break;
+          case "A1_B2_A3":
+            shouldSuccess = layerIdx != 2 ||
+                            (layerIdx == 2 && isActiveLayer);
+            break;
+          case "A1_B2_B3":
+            shouldSuccess = layerIdx == 1 ||
+                            (layerIdx >= 2 && activeLayerIdx != 1);
+            break;
+          case "A1_A2_B3":
+            shouldSuccess = layerIdx <= 2 ||
+                            (layerIdx == 3 && isActiveLayer);
+            break;
+          default:
+            ok(false, "wrong test name.");
+            break;
+        }
+        try {
+          await video.play();
+          ok(shouldSuccess, `video in layer ${layerIdx} starts playing.`);
+        } catch (e) {
+          ok(!shouldSuccess, `video in layer ${layerIdx} fails to start.`);
+        }
+      }
+    }
+    await ContentTask.spawn(tab.linkedBrowser,
+                            [layerIdx, testName, layersNum],
+                            playing_video_may_success);
+
+    info("- remove tab -");
+    await BrowserTestUtils.removeTab(tab);
+  }
+}
+
+add_task(async function start_test() {
+  info("- setup test preference -");
+  await setup_test_preference();
+  requestLongerTimeout(2);
+
+  info("- test permission propagation in different frame hierarchy -");
+  for (let testIdx = 0; testIdx < frameTestArray.length; testIdx++) {
+    let testInfo = frameTestArray[testIdx];
+    let testName = testInfo.name;
+    let testSrc = testInfo.src;
+    let layersNum = testInfo.layersNum;
+    if (layersNum > 3) {
+      ok(false, "Not support more than 3 layers frame yet.");
+    } else {
+      await test_permission_propagation(testName, testSrc, layersNum);
+    }
+  }
+});
new file mode 100644
--- /dev/null
+++ b/toolkit/content/tests/browser/file_autoplay_three_layers_frame1.html
@@ -0,0 +1,16 @@
+<html>
+<head>
+  <title>three frame layers structure 1</title>
+</head>
+<body>
+<!--
+Embed an iframe which has two layers frames, top frame is on domain "example.com",
+child frame is on domain "example.org".
+-->
+</body>
+<video id="v" src="gizmo.mp4" controls loop></video>
+<iframe id="i" src="https://example.com/browser/toolkit/content/tests/browser/file_autoplay_two_layers_frame2.html"
+        height="600" width="800"></iframe></br>
+<script type="text/javascript">
+</script>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/toolkit/content/tests/browser/file_autoplay_three_layers_frame2.html
@@ -0,0 +1,16 @@
+<html>
+<head>
+  <title>three frame layers structure 2</title>
+</head>
+<body>
+<!--
+Embed an iframe which has two layers frames, both frames are in the domain
+"example.com".
+-->
+</body>
+<video id="v" src="gizmo.mp4" controls loop></video>
+<iframe id="i" src="https://example.com/browser/toolkit/content/tests/browser/file_autoplay_two_layers_frame1.html"
+        height="600" width="800"></iframe></br>
+<script type="text/javascript">
+</script>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/toolkit/content/tests/browser/file_autoplay_two_layers_frame1.html
@@ -0,0 +1,15 @@
+<html>
+<head>
+  <title>two frame layers structure1</title>
+</head>
+<body>
+<!--
+Embed an iframe which would always in the same domain as this frame.
+-->
+</body>
+<video id="v" src="gizmo.mp4" controls loop></video>
+<iframe id="i" src="file_video.html"
+        height="600" width="800"></iframe></br>
+<script type="text/javascript">
+</script>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/toolkit/content/tests/browser/file_autoplay_two_layers_frame2.html
@@ -0,0 +1,17 @@
+<html>
+<head>
+  <title>two frame layers structure2</title>
+</head>
+<body>
+<!--
+Embed an iframe which is from domain "example.org". This file doesn't guarantee
+all frames would be in the same domain, it depend on what domain we put this file
+on.
+-->
+</body>
+<video id="v" src="gizmo.mp4" controls loop></video>
+<iframe id="i" src="https://example.org/browser/toolkit/content/tests/browser/file_video.html"
+        height="600" width="800"></iframe></br>
+<script type="text/javascript">
+</script>
+</html>
\ No newline at end of file