<!DOCTYPE HTML>
<html>
  <head>
    <title>GV Autoplay policy test</title>
    <script 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>
<script>

/**
 * On GeckoView, we have a different autoplay policy check than the one on other
 * platforms, which would send a request to the embedding app to ask if the
 * media can be allowed to play. We use a testing pref to simulate the response
 * from the request.
 *
 * The request has two types, audible and inaudible request. The result of the
 * audible request would only take effect on audible media, and the result of
 * inaudible request would only take effect on inaudible media.
 *
 * User activation policy still work on GeckoView, so once the page has been
 * activated, then we won't have to send the request and would allow all media
 * in that page to play.
 *
 * The following test cases contain the information which would be applied in
 * test, and the expected result of the test. For example, the following info
 * indicates that, play an [inaudible] media in the environment with [allowed]
 * [audible] request, and we expect to see it plays successfully.
 *  - muted: false,
 *  - requestType: "audible",
 *  - requestResult: "allowed",
 *  - expectedPlayResult: true,
 */
const testCases = [
  // (1) testing audible playback
  {
    name: "[audible] playback and [allowed audible request] -> allowed",
    muted: false,
    requestType: "audible",
    requestResult: "allowed",
    expectedPlayResult: true,
  },
  {
    name: "[audible] playback and [denied audible request] -> blocked",
    muted: false,
    requestType: "audible",
    requestResult: "denied",
    expectedPlayResult: false,
  },
  {
    name: "[audible] playback and [allowed inaudible request] -> blocked",
    muted: false,
    requestType: "inaudible",
    requestResult: "allowed",
    expectedPlayResult: false,
  },
  {
    name: "[audible] playback and [denied inaudible request] -> blocked",
    muted: false,
    requestType: "inaudible",
    requestResult: "denied",
    expectedPlayResult: false,
  },
  {
    name: "[audible] playback with [pending request] in [activated document] -> allowed",
    muted: false,
    requestType: "all",
    requestResult: "pending",
    activatedDocument: true,
    expectedPlayResult: true,
  },
  {
    name: "[audible] playback with [denied audible request] in [activated document] -> allowed",
    muted: false,
    requestType: "audible",
    requestResult: "allowed",
    activatedDocument: true,
    expectedPlayResult: true,
  },
  {
    name: "[audible] playback with [pending request] in [unactivated document] -> blocked",
    muted: false,
    requestType: "all",
    requestResult: "pending",
    expectedPlayResult: false,
  },
  // (2) testing inaudible playback
  {
    name: "[inaudible] playback and [allowed audible request] -> blocked",
    muted: true,
    requestType: "audible",
    requestResult: "allowed",
    expectedPlayResult: false,
  },
  {
    name: "[inaudible] playback and [denied audible request] -> blocked",
    muted: true,
    requestType: "audible",
    requestResult: "denied",
    expectedPlayResult: false,
  },
  {
    name: "[inaudible] playback and [allowed inaudible request] -> allowed",
    muted: true,
    requestType: "inaudible",
    requestResult: "allowed",
    expectedPlayResult: true,
  },
  {
    name: "[inaudible] playback and [denied inaudible request] -> blocked",
    muted: true,
    requestType: "inaudible",
    requestResult: "denied",
    expectedPlayResult: false,
  },
  {
    name: "[inaudible] playback without [pending request] in [activated document] -> allowed",
    muted: true,
    requestType: "all",
    requestResult: "pending",
    activatedDocument: true,
    expectedPlayResult: true,
  },
  {
    name: "[inaudible] playback without [denied inaudible request] in [activated document] -> allowed",
    muted: true,
    requestType: "inaudible",
    requestResult: "denied",
    activatedDocument: true,
    expectedPlayResult: true,
  },
  {
    name: "[inaudible] playback without [pending request] in [unactivated document] -> blocked",
    muted: true,
    requestType: "all",
    requestResult: "pending",
    expectedPlayResult: false,
  },
  // (3) testing playback from iframe
  {
    name: "playback from [same origin] iframe and [allowed all request]-> allowed",
    requestType: "all",
    requestResult: "allowed",
    iframe: "same-origin",
    expectedPlayResult: true,
  },
  {
    name: "playback from [same origin] iframe and [denied all request]-> blocked",
    requestType: "all",
    requestResult: "denied",
    iframe: "same-origin",
    expectedPlayResult: false,
  },
  {
    name: "playback from [cross origin] iframe and [allowed all request]-> allowed",
    requestType: "all",
    requestResult: "allowed",
    iframe: "cross-origin",
    expectedPlayResult: true,
  },
  {
    name: "playback from [cross origin] iframe and [denied all request]-> blocked",
    requestType: "all",
    requestResult: "denied",
    iframe: "cross-origin",
    expectedPlayResult: false,
  },
];

const pageURL = "file_autoplay_gv_play_request_window.html";

SimpleTest.waitForExplicitFinish();

(async function startTest() {
  for (const testCase of testCases) {
    info(`- start running test '${testCase.name}'-`);
    await setTestingPrefs(testCase);

    // Run each test in a new window to ensure they won't interfere each other
    const testPage = window.open(pageURL, "", "width=500,height=500");
    await once(testPage, "load");
    testPage.postMessage(testCase, window.origin);
    let result = await nextWindowMessage();
    is(result.data.allowedToPlay, testCase.expectedPlayResult, `allowed - ${testCase.name}`);
    is(result.data.played, testCase.expectedPlayResult, `played - ${testCase.name}`);
    testPage.close();
  }
  SimpleTest.finish();
})();

/**
 * This function would set which type of request would be explicitly allowed,
 * and the type of request we don't mention about would be pending forever.
 * E.g. `setTestingPrefs({"audible", "allow"})` will allow the audible request
 * and leave the inaudible request pending forever.
 */
async function setTestingPrefs({requestType, requestResult}) {
  let prefVal = 0;
  if (requestType == "all") {
    if (requestResult == "pending") {
      prefVal = 7;
    } else {
      prefVal = requestResult == "allowed" ? 1 : 2;
    }
  } else if (requestType == "audible") {
    prefVal = requestResult == "allowed" ? 3 : 4;
  } else if (requestType == "inaudible") {
    prefVal = requestResult == "allowed" ? 5 : 6;
  }
  info(`set testing pref to ${prefVal}`);
  await SpecialPowers.pushPrefEnv({
    set: [["media.geckoview.autoplay.request.testing", prefVal],
          ["media.geckoview.autoplay.request", true]],
  });
}

</script>
</body>
</html>
