<!DOCTYPE html>
<meta charset="utf-8">
<title>Presentation API - controlling ua - sandboxing</title>
<link rel="author" title="Francois Daoust" href="https://www.w3.org/People/#fd">
<link rel="author" title="Tomoyuki Shimizu" href="https://github.com/tomoyukilabs/">
<link rel="help" href="http://w3c.github.io/presentation-api/#dom-presentationrequest-start">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../common.js"></script>
<script>
    add_completion_callback((tests, status) => {
      // remove unserializable attributes, then send the result to the parent window
      // note: a single test result is supposed to appear here.
      parent.window.postMessage(JSON.parse(JSON.stringify({
        type: 'presentation-api', test: tests[0], status: status
      })), '*');
    });

    // disable timeout for manual tests
    setup({explicit_timeout: true});

    window.onmessage = function (ev) {
      try {
        // Presentation URLs are relative to the "controlling-ua" folder,
        // update relative URLs for this folder
        var urls = presentationUrls.map(function (url) {
          if (/:\/\//.test(url)) {
            return url;
          }
          else {
            return '../' + url;
          }
        });
        var request = null;
        if (ev.data === 'create') {
          try {
            request = new PresentationRequest(urls);
            parent.window.postMessage('success', '*');
          }
          catch (err) {
            parent.window.postMessage(err.name, '*');
          }
        }
        else if (ev.data === 'start') {
          request = new PresentationRequest(urls);
          request.start()
            .then(function () {
              parent.window.postMessage('success', '*');
            })
            .catch(function (err) {
              if ((err.name === 'NotFoundError') ||
                  (err.name === 'NotAllowedError')) {
                // These errors either mean that the user dismissed the dialog
                // box or that the UA could not find any available or suitable
                // screen. This is equivalent of succeeding for the purpose of
                // iframe tests.
                parent.window.postMessage('success', '*');
              }
              else {
                parent.window.postMessage(err.name, '*');
              }
            });
        }
        else if (ev.data === 'reconnect') {
          request = new PresentationRequest(urls);
          request.reconnect('someid')
            .then(function () {
              parent.window.postMessage('success', '*');
            })
            .catch(function (err) {
              parent.window.postMessage(err.name, '*');
            });
        }
        else if (ev.data.match(/^reconnect\?id=(.*)$/)) {
          promise_test(function (t) {
            var presentationId = RegExp.$1;
            var phase = -1, actual = -1, connection, waitConnection;
            var description = [
              "Phase #1: Promise is resolved",
              "Phase #2: 'connectionavailable' event fired",
              "Phase #3: 'connect' event fired"
            ].map(d => { return '(Reconnecting in a nested browsing context) ' + d; });

            var count = function(evt) { actual++; return evt; };
            var checkPhase = function(evt) {
              phase++;
              assert_equals(description[actual], description[phase], 'Event order is incorrect.');
              return evt;
            };

            request = new PresentationRequest(urls);

            var eventWatcher = new EventWatcher(t, request, 'connectionavailable');
            var waitConnectionavailable = eventWatcher.wait_for('connectionavailable').then(count).then(function (evt) {
              connection = connection || evt.connection; return evt;
            });

            return request.reconnect(presentationId).then(count).then(checkPhase).then(function (c) {
              // Reconnecting Phase #1: Promise is resolved
              connection = c;
              assert_equals(connection.state, 'connecting', 'Check the initial state of the presentation connection.');
              assert_equals(connection.id, presentationId, "The same presentation ID is set to the newly created presentation connection.");
              assert_true(connection instanceof PresentationConnection, 'The connection is an instance of PresentationConnection.');

              var eventWatcher = new EventWatcher(t, connection, 'connect');
              waitConnect = eventWatcher.wait_for('connect').then(count);

              // Reconnecting Phase #2: "connectionavailable" event is fired
              return waitConnectionavailable;
            }).then(checkPhase).then(function (evt) {
              assert_true(evt instanceof PresentationConnectionAvailableEvent, 'An event using PresentationConnectionAvailableEvent is fired.');
              assert_true(evt.isTrusted, 'The event is a trusted event.');
              assert_false(evt.bubbles, 'The event does not bubbles.');
              assert_false(evt.cancelable, 'The event is not cancelable.');
              assert_equals(evt.type, 'connectionavailable', 'The event name is "connectionavailable".');
              assert_equals(evt.target, request, 'event.target is the presentation request.');
              assert_true(evt.connection instanceof PresentationConnection, 'event.connection is a presentation connection.');
              assert_equals(evt.connection, connection, 'event.connection is set to the presentation which the promise is resolved with.');

              // Reconnecting Phase #3: "connect" event is fired
              return waitConnect;
            }).then(checkPhase).then(function (evt) {
              assert_true(evt.isTrusted && !evt.bubbles && !evt.cancelable && evt instanceof Event, 'A simple event is fired.');
              assert_equals(evt.type, 'connect', 'The event name is "connect".');
              assert_equals(evt.target, connection, 'event.target is the presentation connection.');
              assert_equals(connection.state, 'connected', 'The presentation connection state is set to "connected".');
              parent.window.postMessage({ type: 'presentation-api', test: { status: 0 } }, '*');
              var terminateWatcher = new EventWatcher(t, connection, 'terminate');

              // "terminate" event is fired
              return terminateWatcher.wait_for('terminate');
            }).then(function (evt) {
              assert_true(evt.isTrusted && !evt.bubbles && !evt.cancelable && evt instanceof Event, 'A simple event is fired.');
              assert_equals(evt.type, 'terminate', 'The event name is "terminate".');
              assert_equals(evt.target, connection, 'event.target is the presentation connection.');
              assert_equals(connection.state, 'terminated', 'The presentation connection state is set to "terminated".');
            });
          });
        }
        else if (ev.data.match(/^terminate\?id=(.*)$/)) {
          var presentationId = RegExp.$1;
          request = new PresentationRequest(urls);
          request.reconnect(presentationId)
            .then(function (c) {
              parent.window.postMessage('reconnected', '*');
              c.onterminate = function(evt) {
                parent.window.postMessage({
                  isSimpleEvent: evt.isTrusted && !evt.bubbles && !evt.cancelable && evt instanceof Event,
                  type: evt.type,
                  checkConnection: evt.target === c,
                  state: c.state
                }, '*');
              };
            })
            .catch(function (err) {
              parent.window.postMessage(err.name, '*');
            });
        }
        else if (ev.data === 'getAvailability') {
          request = new PresentationRequest(urls);
          request.getAvailability()
            .then(function () {
              parent.window.postMessage('success', '*');
            })
            .catch(function (err) {
              if (err.name === 'NotSupportedError') {
                parent.window.postMessage('success', '*');
              }
              else {
                parent.window.postMessage(err.name, '*');
              }
            });
        }
      }
      catch (err) {
        parent.window.postMessage('Could not create PresentationRequest', '*');
      }
    }
    parent.window.postMessage('ready', '*');
</script>

