<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=545812

Test DOM fullscreen API.

-->
<head>
  <title>Test for Bug 545812</title>
  <script src="/tests/SimpleTest/SimpleTest.js"></script>
  <script src="/tests/SimpleTest/EventUtils.js"></script>
  <script type="application/javascript" src="file_fullscreen-utils.js"></script>
  <style>
  body {
    background-color: black;
  }
  </style>
</head>
<body>

<script type="application/javascript">

/** Test for Bug 545812 **/

function ok(condition, msg) {
  opener.ok(condition, "[denied] " + msg);
}

function is(a, b, msg) {
  opener.is(a, b, "[denied] " + msg);
}

const INNER_FILE = "file_fullscreen-denied-inner.html";
function setupForInnerTest(targetName, callback) {
  window.testTargetName = targetName;
  window.continueTest = () => {
    delete window.testTargetName;
    delete window.continueTest;
    callback();
  };
}

function begin() {
  document.addEventListener("fullscreenchange", () => {
    ok(false, "Should never receive " +
       "a fullscreenchange event in the main window.");
  });
  SimpleTest.executeSoon(testIFrameWithoutAllowFullscreen);
}

function testIFrameWithoutAllowFullscreen() {
  // Create an iframe without an allowfullscreen attribute, whose
  // contents request fullscreen. The request should be denied, and
  // we should not receive a fullscreenchange event in this document.
  var iframe = document.createElement("iframe");
  iframe.src = INNER_FILE;
  // The iframe is same-origin so when we use feature policy otherwise we'd hit
  // the "allowed" code-path (as intended). It is a bug that this test passes
  // without the allow attribute.
  iframe.allow = "fullscreen 'none'";
  setupForInnerTest("an iframe without allowfullscreen", () => {
    document.body.removeChild(iframe);
    SimpleTest.executeSoon(testFrameElement);
  });
  document.body.appendChild(iframe);
}

function testFrameElement() {
  var frameset = document.createElement("frameset");
  var frame = document.createElement("frame");
  frame.src = INNER_FILE;
  frameset.appendChild(frame);
  setupForInnerTest("a frame element", () => {
    document.documentElement.removeChild(frameset);
    SimpleTest.executeSoon(testObjectElement);
  });
  document.documentElement.appendChild(frameset);
}

function testObjectElement() {
  var objectElem = document.createElement("object");
  objectElem.data = INNER_FILE;
  setupForInnerTest("an object element", () => {
    document.body.removeChild(objectElem);
    // In the following tests we want to test trust context requirement
    // of fullscreen request, so temporary re-enable this pref.
    SpecialPowers.pushPrefEnv({
      "set":[["full-screen-api.allow-trusted-requests-only", true]]
    }, testNonTrustContext);
  });
  document.body.appendChild(objectElem);
}

function testNonTrustContext() {
  addFullscreenErrorContinuation(() => {
    ok(!document.fullscreenElement,
       "Should not grant request in non-trust context.");
    SimpleTest.executeSoon(testLongRunningEventHandler);
  });
  document.documentElement.requestFullscreen();
}

function testLongRunningEventHandler() {
  let timeout = SpecialPowers.getIntPref("dom.user_activation.transient.timeout") + 1000;

  function longRunningHandler() {
    window.removeEventListener("keypress", longRunningHandler);
    // Busy loop until transient useractivation is timed out, so our request for
    // fullscreen should be rejected.
    var end = (new Date()).getTime() + timeout;
    while ((new Date()).getTime() < end) {
      ; // Wait...
    }
    document.documentElement.requestFullscreen();
  }
  addFullscreenErrorContinuation(() => {
    ok(!document.fullscreenElement,
      "Should not grant request in long-running event handler.");
    SimpleTest.executeSoon(testFullscreenMouseBtn);
  });
  window.addEventListener("keypress", longRunningHandler);
  sendString("a");
}

function requestFullscreenMouseBtn(event, button) {
  let clickEl = document.createElement("p");
  clickEl.innerText = "Click Me";

  function eventHandler(evt) {
    document.body.requestFullscreen();
    evt.target.removeEventListener(evt, this);
  }

  clickEl.addEventListener(event, eventHandler);
  document.body.appendChild(clickEl);
  synthesizeMouseAtCenter(clickEl, { button });
}

async function testFullscreenMouseBtn(event, button, next) {
  await SpecialPowers.pushPrefEnv({
    "set": [["full-screen-api.mouse-event-allow-left-button-only", true]]
  });
  let fsRequestEvents = ["mousedown", "mouseup", "pointerdown", "pointerup"];
  let mouseButtons = [1, 2];

  for (let i = 0; i < fsRequestEvents.length; i++) {
    let evt = fsRequestEvents[i];
    for (let j = 0; j < mouseButtons.length; j++) {
      let mouseButton = mouseButtons[j];
      await new Promise(resolve => {
        addFullscreenErrorContinuation(resolve);
        requestFullscreenMouseBtn(evt, mouseButton);
      });
      ok(!document.fullscreenElement, `Should not grant request on '${evt}' triggered by mouse button ${mouseButton}`);
    }
  }
  // Restore the pref environment we changed before
  // entering testNonTrustContext.
  await SpecialPowers.popPrefEnv();
  await SpecialPowers.popPrefEnv();
  finish();
}

function finish() {
  opener.nextTest();
}

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