<!DOCTYPE html>
<title>Service Worker: postMessage</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<script>
promise_test(t => {
    var script = 'resources/postmessage-worker.js';
    var scope = 'resources/blank.html';
    var registration;
    var worker;
    var port;

    return service_worker_unregister_and_register(t, script, scope)
      .then(r => {
          t.add_cleanup(() => r.unregister());
          registration = r;
          worker = registration.installing;

          var messageChannel = new MessageChannel();
          port = messageChannel.port1;
          return new Promise(resolve => {
              port.onmessage = resolve;
              worker.postMessage({port: messageChannel.port2},
                                 [messageChannel.port2]);
              worker.postMessage({value: 1});
              worker.postMessage({value: 2});
              worker.postMessage({done: true});
            });
        })
      .then(e => {
          assert_equals(e.data, 'Acking value: 1');
          return new Promise(resolve => { port.onmessage = resolve; });
        })
      .then(e => {
          assert_equals(e.data, 'Acking value: 2');
          return new Promise(resolve => { port.onmessage = resolve; });
        })
      .then(e => {
          assert_equals(e.data, 'quit');
          return registration.unregister(scope);
        });
  }, 'postMessage to a ServiceWorker (and back via MessagePort)');

promise_test(t => {
    var script = 'resources/postmessage-transferables-worker.js';
    var scope = 'resources/blank.html';
    var sw = navigator.serviceWorker;

    var message = 'Hello, world!';
    var text_encoder = new TextEncoder;
    var text_decoder = new TextDecoder;

    return service_worker_unregister_and_register(t, script, scope)
      .then(r => {
          t.add_cleanup(() => r.unregister());

          var ab = text_encoder.encode(message);
          assert_equals(ab.byteLength, message.length);
          r.installing.postMessage(ab, [ab.buffer]);
          assert_equals(text_decoder.decode(ab), '');
          assert_equals(ab.byteLength, 0);

          return new Promise(resolve => { sw.onmessage = resolve; });
        })
      .then(e => {
          // Verify the integrity of the transferred array buffer.
          assert_equals(e.data.content, message);
          assert_equals(e.data.byteLength, message.length);
          return new Promise(resolve => { sw.onmessage = resolve; });
        })
      .then(e => {
          // Verify the integrity of the array buffer sent back from
          // ServiceWorker via Client.postMessage.
          assert_equals(text_decoder.decode(e.data), message);
          assert_equals(e.data.byteLength, message.length);
          return new Promise(resolve => { sw.onmessage = resolve; });
        })
      .then(e => {
          // Verify that the array buffer on ServiceWorker is neutered.
          assert_equals(e.data.content, '');
          assert_equals(e.data.byteLength, 0);
        });
  }, 'postMessage a transferable ArrayBuffer between ServiceWorker and Client');

promise_test(t => {
    var script = 'resources/postmessage-transferables-worker.js';
    var scope = 'resources/blank.html';
    var message = 'Hello, world!';
    var text_encoder = new TextEncoder;
    var text_decoder = new TextDecoder;
    var port;

    return service_worker_unregister_and_register(t, script, scope)
      .then(r => {
          t.add_cleanup(() => r.unregister());

          var channel = new MessageChannel;
          port = channel.port1;
          r.installing.postMessage(undefined, [channel.port2]);

          var ab = text_encoder.encode(message);
          assert_equals(ab.byteLength, message.length);
          port.postMessage(ab, [ab.buffer]);
          assert_equals(text_decoder.decode(ab), '');
          assert_equals(ab.byteLength, 0);

          return new Promise(resolve => { port.onmessage = resolve; });
        })
      .then(e => {
          // Verify the integrity of the transferred array buffer.
          assert_equals(e.data.content, message);
          assert_equals(e.data.byteLength, message.length);
          return new Promise(resolve => { port.onmessage = resolve; });
        })
      .then(e => {
          // Verify the integrity of the array buffer sent back from
          // ServiceWorker via Client.postMessage.
          assert_equals(text_decoder.decode(e.data), message);
          assert_equals(e.data.byteLength, message.length);
          return new Promise(resolve => { port.onmessage = resolve; });
        })
      .then(e => {
          // Verify that the array buffer on ServiceWorker is neutered.
          assert_equals(e.data.content, '');
          assert_equals(e.data.byteLength, 0);
        });
  }, 'postMessage a transferable ArrayBuffer between ServiceWorker and Client' +
     ' over MessagePort');

  promise_test(t => {
    var script = 'resources/postmessage-dictionary-transferables-worker.js';
    var scope = 'resources/blank.html';
    var sw = navigator.serviceWorker;

    var message = 'Hello, world!';
    var text_encoder = new TextEncoder;
    var text_decoder = new TextDecoder;

    return service_worker_unregister_and_register(t, script, scope)
      .then(r => {
          t.add_cleanup(() => r.unregister());

          var ab = text_encoder.encode(message);
          assert_equals(ab.byteLength, message.length);
          r.installing.postMessage(ab, {transfer: [ab.buffer]});
          assert_equals(text_decoder.decode(ab), '');
          assert_equals(ab.byteLength, 0);

          return new Promise(resolve => { sw.onmessage = resolve; });
        })
      .then(e => {
          // Verify the integrity of the transferred array buffer.
          assert_equals(e.data.content, message);
          assert_equals(e.data.byteLength, message.length);
          return new Promise(resolve => { sw.onmessage = resolve; });
        })
      .then(e => {
          // Verify the integrity of the array buffer sent back from
          // ServiceWorker via Client.postMessage.
          assert_equals(text_decoder.decode(e.data), message);
          assert_equals(e.data.byteLength, message.length);
          return new Promise(resolve => { sw.onmessage = resolve; });
        })
      .then(e => {
          // Verify that the array buffer on ServiceWorker is neutered.
          assert_equals(e.data.content, '');
          assert_equals(e.data.byteLength, 0);
        });
  }, 'postMessage with dictionary a transferable ArrayBuffer between ServiceWorker and Client');

  promise_test(async t => {
    const firstScript = 'resources/postmessage-echo-worker.js?one';
    const secondScript = 'resources/postmessage-echo-worker.js?two';
    const scope = 'resources/';

    const registration = await service_worker_unregister_and_register(t, firstScript, scope);
    t.add_cleanup(() => registration.unregister());
    const firstWorker = registration.installing;

    const messagePromise = new Promise(resolve => {
      navigator.serviceWorker.addEventListener('message', (event) => {
        resolve(event.data);
      }, {once: true});
    });

    await wait_for_state(t, firstWorker, 'activated');
    await navigator.serviceWorker.register(secondScript, {scope});
    const secondWorker = registration.installing;
    await wait_for_state(t, firstWorker, 'redundant');

    // postMessage() to a redundant worker should be dropped silently.
    // Historically, this threw an exception.
    firstWorker.postMessage('firstWorker');

    // To test somewhat that it was not received, send a message to another
    // worker and check that we get a reply for that one.
    secondWorker.postMessage('secondWorker');
    const data = await messagePromise;
    assert_equals(data, 'secondWorker');
  }, 'postMessage to a redundant worker');
</script>
