| <!DOCTYPE html> |
| <html> |
| <head> |
| <title>RTCPeerConnection with AES-GCM ciphersuites (and SDES)</title> |
| <script src="../../resources/testharness.js"></script> |
| <script src="../../resources/testharnessreport.js"></script> |
| </head> |
| <body> |
| <script> |
| 'use strict' |
| const sdes_constraint = {mandatory: {DtlsSrtpKeyAgreement: false}}; |
| |
| function parseCrypto(line) { |
| var parts = line.substr(9).split(' '); |
| return { |
| tag: parseInt(parts[0], 10), |
| cryptoSuite: parts[1], |
| keyParams: parts[2], |
| sessionParams: parts.slice(3), |
| }; |
| }; |
| |
| function filterSuites(sdp, allowedSuites) { |
| return sdp.split('\r\n').filter(line => { |
| if (!line.startsWith('a=crypto:')) { |
| return true; |
| } |
| const crypto = parseCrypto(line); |
| return allowedSuites.includes(crypto.cryptoSuite); |
| }).join('\r\n'); |
| } |
| |
| // Note: (legacy) getStats-based tests don't work since srtpCipher is not set |
| // when using SDES. |
| ['AEAD_AES_256_GCM', 'AEAD_AES_128_GCM'].forEach(suite => { |
| promise_test(async t => { |
| const pc1 = new RTCPeerConnection(null, sdes_constraint); |
| t.add_cleanup(() => pc1.close()); |
| const pc2 = new RTCPeerConnection(null, sdes_constraint); |
| t.add_cleanup(() => pc2.close()); |
| pc1.onicecandidate = (e) => e.candidate && pc2.signalingState !== 'closed' && pc2.addIceCandidate(e.candidate); |
| pc2.onicecandidate = (e) => e.candidate && pc1.signalingState !== 'closed' && pc1.addIceCandidate(e.candidate); |
| |
| const loadedMetadata = new Promise(resolve => { |
| pc2.ontrack = (e) => { |
| const v = document.createElement('video'); |
| v.autoplay = true; |
| v.srcObject = e.streams[0]; |
| v.onloadedmetadata = () => resolve(); |
| }; |
| }); |
| |
| const stream = await navigator.mediaDevices.getUserMedia({video: true}); |
| const track = stream.getTracks()[0]; |
| pc1.addTrack(track, stream); |
| const offer = await pc1.createOffer(); |
| await pc1.setLocalDescription(offer); |
| const sdp = filterSuites(offer.sdp, [suite]); |
| await pc2.setRemoteDescription({type: 'offer', sdp}); |
| const answer = await pc2.createAnswer(); |
| await pc2.setLocalDescription(answer); |
| await pc1.setRemoteDescription(answer); |
| |
| return loadedMetadata; |
| }, 'Support for ' + suite + ' ciphersuite'); |
| }); |
| </script> |
| </body> |
| </html> |