Revision b55e29597d92ab89063673f031151e2bdb4b9479 authored by Joe Downing on 22 March 2018, 07:35:35 UTC, committed by Chromium WPT Sync on 22 March 2018, 07:35:35 UTC
This change moves the KeyboardLock API methods to a 'keyboard'
namespace on the Navigator object.  We are doing this work now as
there has been a request for additional keyboard functionality that
would also be placed on the new keyboard object and we wanted to
move the KeyboardLock methods there for consistency before we launch.

KeyboardLock API Spec is here:
https://w3c.github.io/keyboard-lock/#API

Old calling pattern:
Navigator.keyboardLock();
Navigator.keyboardUnlock();

New calling pattern:
Navigator.keyboard.lock();
Navigator.keyboard.unlock();

Note: The main logic in the KeyboardLock.cpp class and tests is the
same as it was, however the file changed enough that git does not
recognize it as a file move.

BUG=680809

Change-Id: I234b2ab12d5ecd44c894ed5103863fd96fd548d4
Reviewed-on: https://chromium-review.googlesource.com/969656
Reviewed-by: Philip Jägenstedt <foolip@chromium.org>
Reviewed-by: Gary Kacmarcik <garykac@chromium.org>
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#544996}
1 parent 1a8c195
Raw File
RTCPeerConnection-ontrack.https.html
<!doctype html>
<meta charset=utf-8>
<title>RTCPeerConnection.prototype.ontrack</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="RTCPeerConnection-helper.js"></script>
<script>
  'use strict';

  // Test is based on the following editor draft:
  // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html

  // The following helper functions are called from RTCPeerConnection-helper.js:
  //   getTrackFromUserMedia

  /*
    4.3.1.6.  Set the RTCSessionSessionDescription
      2.2.8.  If description is set as a remote description, then run the following
              steps for each media description in description:
        3.  Set transceiver's mid value to the mid of the corresponding media
            description. If the media description has no MID, and transceiver's
            mid is unset, generate a random value as described in [JSEP] (section 5.9.).
        4.  If the direction of the media description is sendrecv or sendonly, and
            transceiver.receiver.track has not yet been fired in a track event,
            process the remote track for the media description, given transceiver.

    5.1.1. Processing Remote MediaStreamTracks
      To process the remote track for an incoming media description [JSEP]
      (section 5.9.) given RTCRtpTransceiver transceiver, the user agent MUST
      run the following steps:

      1.  Let connection be the RTCPeerConnection object associated with transceiver.
      2.  Let streams be a list of MediaStream objects that the media description
          indicates the MediaStreamTrack belongs to.
      3.  Add track to all MediaStream objects in streams.
      4.  Queue a task to fire an event named track with transceiver, track, and
          streams at the connection object.

    5.7.  RTCTrackEvent
      [Constructor(DOMString type, RTCTrackEventInit eventInitDict)]
      interface RTCTrackEvent : Event {
        readonly attribute RTCRtpReceiver           receiver;
        readonly attribute MediaStreamTrack         track;
        [SameObject]
        readonly attribute FrozenArray<MediaStream> streams;
        readonly attribute RTCRtpTransceiver        transceiver;
      };

    [mediacapture-main]
    4.2.  MediaStream
      interface MediaStream : EventTarget {
        readonly attribute DOMString    id;
        sequence<MediaStreamTrack> getTracks();
        ...
      };

    [mediacapture-main]
    4.3.  MediaStreamTrack
      interface MediaStreamTrack : EventTarget {
        readonly attribute DOMString             kind;
        readonly attribute DOMString             id;
        ...
      };
   */

  function validateTrackEvent(trackEvent) {
    const { receiver, track, streams, transceiver } = trackEvent;

    assert_true(track instanceof MediaStreamTrack,
      'Expect track to be instance of MediaStreamTrack');

    assert_true(Array.isArray(streams),
      'Expect streams to be an array');

    for(const mediaStream of streams) {
      assert_true(mediaStream instanceof MediaStream,
        'Expect elements in streams to be instance of MediaStream');

      assert_true(mediaStream.getTracks().includes(track),
        'Expect each mediaStream to have track as one of their tracks');
    }

    assert_true(receiver instanceof RTCRtpReceiver,
      'Expect trackEvent.receiver to be defined and is instance of RTCRtpReceiver');

    assert_equals(receiver.track, track,
      'Expect trackEvent.receiver.track to be the same as trackEvent.track');

    assert_true(transceiver instanceof RTCRtpTransceiver,
      'Expect trackEvent.transceiver to be defined and is instance of RTCRtpTransceiver');

    assert_equals(transceiver.receiver, receiver,
      'Expect trackEvent.transceiver.receiver to be the same as trackEvent.receiver');
  }

  // tests that ontrack is called and parses the msid information from the SDP and creates
  // the streams with matching identifiers.
  async_test(t => {
    const pc = new RTCPeerConnection();

    // Fail the test if the ontrack event handler is not implemented
    assert_idl_attribute(pc, 'ontrack', 'Expect pc to have ontrack event handler attribute');

    const sdp = `v=0
o=- 166855176514521964 2 IN IP4 127.0.0.1
s=-
t=0 0
a=msid-semantic:WMS *
m=audio 9 UDP/TLS/RTP/SAVPF 111
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:someufrag
a=ice-pwd:somelongpwdwithenoughrandomness
a=fingerprint:sha-256 8C:71:B3:8D:A5:38:FD:8F:A4:2E:A2:65:6C:86:52:BC:E0:6E:94:F2:9F:7C:4D:B5:DF:AF:AA:6F:44:90:8D:F4
a=setup:actpass
a=rtcp-mux
a=mid:mid1
a=sendonly
a=rtpmap:111 opus/48000/2
a=msid:stream1 track1
a=ssrc:1001 cname:some
`;

    pc.ontrack = t.step_func(trackEvent => {
      const { streams, track, transceiver } = trackEvent;

      assert_equals(streams.length, 1,
        'the track belongs to one MediaStream');

      const [stream] = streams;
      assert_equals(stream.id, 'stream1',
        'Expect stream.id to be the same as specified in the a=msid line');

      assert_equals(track.kind, 'audio',
        'Expect track.kind to be audio');

      validateTrackEvent(trackEvent);

      assert_equals(transceiver.direction, 'recvonly',
        'Expect transceiver.direction to be reverse of sendonly (recvonly)');

      t.done();
    });

    pc.setRemoteDescription({ type: 'offer', sdp })
    .catch(t.step_func(err => {
      assert_unreached('Error ' + err.name + ': ' + err.message);
    }));
  }, 'setRemoteDescription should trigger ontrack event when the MSID of the stream is is parsed.');

  async_test(t => {
    const pc = new RTCPeerConnection();

    assert_idl_attribute(pc, 'ontrack', 'Expect pc to have ontrack event handler attribute');

    const sdp = `v=0
o=- 166855176514521964 2 IN IP4 127.0.0.1
s=-
t=0 0
a=msid-semantic:WMS *
m=audio 9 UDP/TLS/RTP/SAVPF 111
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:someufrag
a=ice-pwd:somelongpwdwithenoughrandomness
a=fingerprint:sha-256 8C:71:B3:8D:A5:38:FD:8F:A4:2E:A2:65:6C:86:52:BC:E0:6E:94:F2:9F:7C:4D:B5:DF:AF:AA:6F:44:90:8D:F4
a=setup:actpass
a=rtcp-mux
a=mid:mid1
a=recvonly
a=rtpmap:111 opus/48000/2
a=msid:stream1 track1
a=ssrc:1001 cname:some
`;

    pc.ontrack = t.unreached_func('ontrack event should not fire for track with recvonly direction');

    pc.setRemoteDescription({ type: 'offer', sdp })
    .catch(t.step_func(err => {
      assert_unreached('Error ' + err.name + ': ' + err.message);
    }))
    .then(t.step_func(() => {
      t.step_timeout(t.step_func_done(), 100);
    }));

  }, 'setRemoteDescription() with m= line of recvonly direction should not trigger track event');

  async_test(t => {
    const pc1 = new RTCPeerConnection();
    const pc2 = new RTCPeerConnection();

    pc2.ontrack = t.step_func(trackEvent => {
      const { track } = trackEvent;

      assert_equals(track.kind, 'audio',
        'Expect track.kind to be audio');

      validateTrackEvent(trackEvent);

      t.done();
    });

    return getTrackFromUserMedia('audio')
    .then(([track, mediaStream]) => {
      pc1.addTrack(track, mediaStream);

      return pc1.createOffer()
      .then(offer => pc2.setRemoteDescription(offer));
    })
    .catch(t.step_func(err => {
      assert_unreached('Error ' + err.name + ': ' + err.message);
    }));

  }, 'addTrack() should cause remote connection to fire ontrack when setRemoteDescription()');

  async_test(t => {
    const pc1 = new RTCPeerConnection();
    const pc2 = new RTCPeerConnection();

    pc2.ontrack = t.step_func(trackEvent => {
      const { track } = trackEvent;

      assert_equals(track.kind, 'video',
        'Expect track.kind to be video');

      validateTrackEvent(trackEvent);

      t.done();
    });

    pc1.addTransceiver('video');

    return pc1.createOffer()
    .then(offer => pc2.setRemoteDescription(offer))
    .catch(t.step_func(err => {
      assert_unreached('Error ' + err.name + ': ' + err.message);
    }));

  }, `addTransceiver('video') should cause remote connection to fire ontrack when setRemoteDescription()`);

  async_test(t => {
    const pc1 = new RTCPeerConnection();
    const pc2 = new RTCPeerConnection();

    pc2.ontrack = t.step_func(trackEvent => {
      const { track } = trackEvent;

      assert_equals(track.kind, 'video',
        'Expect track.kind to be video');

      validateTrackEvent(trackEvent);

      t.done();
    });

    pc1.addTransceiver('audio', { direction: 'inactive' });
    pc2.ontrack = t.unreached_func('ontrack event should not fire for track with inactive direction');

    return pc1.createOffer()
    .then(offer => pc2.setRemoteDescription(offer))
    .catch(t.step_func(err => {
      assert_unreached('Error ' + err.name + ': ' + err.message);
    }))
    .then(t.step_func(() => {
      t.step_timeout(t.step_func_done(), 100);
    }));

  }, `addTransceiver() with inactive direction should not cause remote connection to fire ontrack when setRemoteDescription()`);

</script>
back to top