<!doctype html>
<html>
  <head>
    <title>Notification permission behaviour in different contexts</title>
    <script src="../resources/permissions-helper.js"></script>
    <script src="../resources/testharness.js"></script>
    <script src="../resources/testharnessreport.js"></script>
  </head>
  <body>
    <script>
      const secondOrigin = 'http://127.0.0.1:8080';
      const secondOriginPath = 'http://127.0.0.1:8080/notifications/resources/iframe-permission-helper.html';

      // Creates an iframe to read the notification permission values. It will
      // return a Promise that will be resolved with them once ready. This
      // implementation works for both same-origin and cross-origin iframes, and
      // properly cleans up after itself.
      function GetPermissionValuesFromIframe(sameOrigin) {
        let resolver = null;

        function messageEventHandler(event) {
          window.removeEventListener('message', messageEventHandler);
          iframe.parentElement.removeChild(iframe);

          resolver(event.data);
        }

        window.addEventListener('message', messageEventHandler);

        const iframe = document.createElement('iframe');
        iframe.src = sameOrigin ? 'resources/iframe-permission-helper.html'
                                : secondOriginPath;

        // Start loading the iframe by adding it to the document.
        document.body.appendChild(iframe);

        return new Promise(resolve => { resolver = resolve; });
      }

      // TODO(peter): Remove `push-messaging` as a separate update here once we
      // treat that and `notifications` the same.
      function SetCurrentOriginPermission(value) {
        return Promise.all([
          PermissionsHelper.setPermission('notifications', value),
          PermissionsHelper.setPermission('push-messaging', value)
        ]);
      }

      function SetCrossOriginPermission(requestingOrigin, value) {
        for (const permission of ['notifications', 'push-messaging']) {
          testRunner.setPermission(permission, value, requestingOrigin, requestingOrigin);
          testRunner.setPermission(permission, value, requestingOrigin, location.origin);
        }
      }

      // Top-level document tests.

      promise_test(test => {
        return SetCurrentOriginPermission('granted')
          .then(() => Notification.requestPermission())
          .then(permission => assert_equals(permission, 'granted'))
          .then(() => assert_equals(Notification.permission, 'granted'))
          .then(() => navigator.permissions.query({ name: 'notifications' }))
          .then(permission => assert_equals(permission.state, 'granted'))
          .then(() => navigator.permissions.query({ name: 'push', userVisibleOnly: true }))
          .then(permission => assert_equals(permission.state, 'granted'));

      }, 'Top-level document notification `granted` permission behaviour');

      promise_test(test => {
        return SetCurrentOriginPermission('denied')
          .then(() => Notification.requestPermission())
          .then(permission => assert_equals(permission, 'denied'))
          .then(() => assert_equals(Notification.permission, 'denied'))
          .then(() => navigator.permissions.query({ name: 'notifications' }))
          .then(permission => assert_equals(permission.state, 'denied'))
          .then(() => navigator.permissions.query({ name: 'push', userVisibleOnly: true }))
          .then(permission => assert_equals(permission.state, 'denied'));

      }, 'Top-level document notification `denied` permission behaviour');

      promise_test(test => {
        return SetCurrentOriginPermission('prompt')
          .then(() => Notification.requestPermission())
          .then(permission => assert_equals(permission, 'default'))
          .then(() => assert_equals(Notification.permission, 'default'))
          .then(() => navigator.permissions.query({ name: 'notifications' }))
          .then(permission => assert_equals(permission.state, 'prompt'))
          .then(() => navigator.permissions.query({ name: 'push', userVisibleOnly: true }))
          .then(permission => assert_equals(permission.state, 'prompt'));

      }, 'Top-level document notification `default` permission behaviour');

      // Same-origin iframe tests.

      promise_test(test => {
        return SetCurrentOriginPermission('granted')
          .then(() => GetPermissionValuesFromIframe(true /* sameOrigin */))
          .then(values => {
            assert_equals(values.notificationPermission, 'granted');
            assert_equals(values.notificationRequestPermission, 'granted');
            assert_equals(values.permissionApiNotificationPermission, 'granted');
            assert_equals(values.permissionApiPushPermission, 'granted');
          });
      }, 'Same-origin iframe notification `granted` permission behaviour');

      promise_test(test => {
        return SetCurrentOriginPermission('denied')
          .then(() => GetPermissionValuesFromIframe(true /* sameOrigin */))
          .then(values => {
            assert_equals(values.notificationPermission, 'denied');
            assert_equals(values.notificationRequestPermission, 'denied');
            assert_equals(values.permissionApiNotificationPermission, 'denied');
            assert_equals(values.permissionApiPushPermission, 'denied');
          });
      }, 'Same-origin iframe notification `denied` permission behaviour');

      promise_test(test => {
        return SetCurrentOriginPermission('prompt')
          .then(() => GetPermissionValuesFromIframe(true /* sameOrigin */))
          .then(values => {
            assert_equals(values.notificationPermission, 'default');
            assert_equals(values.notificationRequestPermission, 'default');
            assert_equals(values.permissionApiNotificationPermission, 'prompt');
            assert_equals(values.permissionApiPushPermission, 'prompt');
          });
      }, 'Same-origin iframe notification `default` permission behaviour');

      // Cross-origin iframe tests.

      promise_test(test => {
        SetCrossOriginPermission(secondOrigin, 'granted');

        return GetPermissionValuesFromIframe(false /* sameOrigin */)
          .then(values => {
            assert_equals(values.notificationPermission, 'granted');
            assert_equals(values.notificationRequestPermission, 'granted');
            assert_equals(values.permissionApiNotificationPermission, 'granted');
            assert_equals(values.permissionApiPushPermission, 'granted');
          });
      }, 'Cross-origin iframe notification `granted` permission behaviour');

      promise_test(test => {
        SetCrossOriginPermission(secondOrigin, 'denied');

        return GetPermissionValuesFromIframe(false /* sameOrigin */)
          .then(values => {
            assert_equals(values.notificationPermission, 'denied');
            assert_equals(values.notificationRequestPermission, 'denied');
            assert_equals(values.permissionApiNotificationPermission, 'denied');
            assert_equals(values.permissionApiPushPermission, 'denied');
          });
      }, 'Cross-origin iframe notification `denied` permission behaviour');

      promise_test(test => {
        SetCrossOriginPermission(secondOrigin, 'prompt');

        return GetPermissionValuesFromIframe(false /* sameOrigin */)
          .then(values => {
            assert_equals(values.notificationPermission, 'denied');
            assert_equals(values.notificationRequestPermission, 'denied');
            assert_equals(values.permissionApiNotificationPermission, 'denied');
            assert_equals(values.permissionApiPushPermission, 'denied');
          });
      }, 'Cross-origin iframe notification `default` permission behaviour');
    </script>
  </body>
</html>
