Index: tools/perf/page_sets/webrtc_cases/datatransfer.js |
diff --git a/tools/perf/page_sets/webrtc_cases/datatransfer.js b/tools/perf/page_sets/webrtc_cases/datatransfer.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..7c5050783943559ebc4cc3f6ac308ea19d19a1c7 |
--- /dev/null |
+++ b/tools/perf/page_sets/webrtc_cases/datatransfer.js |
@@ -0,0 +1,229 @@ |
+/* |
+ * Copyright 2017 The Chromium Authors. All rights reserved. |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+'use strict'; |
+ |
+var localConnection; |
+var remoteConnection; |
+var sendChannel; |
+var receiveChannel; |
+var pcConstraint; |
+var megsToSend = document.querySelector('input#megsToSend'); |
+var sendButton = document.querySelector('button#sendTheData'); |
+var orderedCheckbox = document.querySelector('input#ordered'); |
+var sendProgress = document.querySelector('progress#sendProgress'); |
+var receiveProgress = document.querySelector('progress#receiveProgress'); |
+var errorMessage = document.querySelector('div#errorMsg'); |
+ |
+var receivedSize = 0; |
+var bytesToSend = 0; |
+ |
+sendButton.onclick = createConnection; |
+ |
+// Prevent data sent to be set to 0. |
+megsToSend.addEventListener('change', function(e) { |
+ if (this.value <= 0) { |
+ sendButton.disabled = true; |
+ errorMessage.innerHTML = '<p>Please enter a number greater than zero.</p>'; |
+ } else { |
+ errorMessage.innerHTML = ''; |
+ sendButton.disabled = false; |
+ } |
+}); |
+ |
+function createConnection() { |
+ sendButton.disabled = true; |
+ megsToSend.disabled = true; |
+ var servers = null; |
+ pcConstraint = null; |
+ |
+ bytesToSend = Math.round(megsToSend.value) * 1024 * 1024; |
+ |
+ // Add localConnection to global scope to make it visible |
+ // from the browser console. |
+ window.localConnection = localConnection = new RTCPeerConnection(servers, |
+ pcConstraint); |
+ trace('Created local peer connection object localConnection'); |
+ |
+ var dataChannelParams = {ordered: false}; |
+ if (orderedCheckbox.checked) { |
+ dataChannelParams.ordered = true; |
+ } |
+ |
+ sendChannel = localConnection.createDataChannel( |
+ 'sendDataChannel', dataChannelParams); |
+ sendChannel.binaryType = 'arraybuffer'; |
+ trace('Created send data channel'); |
+ |
+ sendChannel.onopen = onSendChannelStateChange; |
+ sendChannel.onclose = onSendChannelStateChange; |
+ localConnection.onicecandidate = function(e) { |
+ onIceCandidate(localConnection, e); |
+ }; |
+ |
+ localConnection.createOffer().then( |
+ gotDescription1, |
+ onCreateSessionDescriptionError |
+ ); |
+ |
+ // Add remoteConnection to global scope to make it visible |
+ // from the browser console. |
+ window.remoteConnection = remoteConnection = new RTCPeerConnection(servers, |
+ pcConstraint); |
+ trace('Created remote peer connection object remoteConnection'); |
+ |
+ remoteConnection.onicecandidate = function(e) { |
+ onIceCandidate(remoteConnection, e); |
+ }; |
+ remoteConnection.ondatachannel = receiveChannelCallback; |
+} |
+ |
+function onCreateSessionDescriptionError(error) { |
+ trace('Failed to create session description: ' + error.toString()); |
+} |
+ |
+function randomAsciiString(length) { |
+ var result = ''; |
+ for (var i = 0; i < length; i++) { |
+ // Visible ASCII chars are between 33 and 126. |
+ result += String.fromCharCode(33 + Math.random() * 93); |
+ } |
+ return result; |
+} |
+ |
+function sendGeneratedData() { |
+ sendProgress.max = bytesToSend; |
+ receiveProgress.max = sendProgress.max; |
+ sendProgress.value = 0; |
+ receiveProgress.value = 0; |
+ |
+ var chunkSize = 16384; |
+ var stringToSendRepeatedly = randomAsciiString(chunkSize); |
+ var bufferFullThreshold = 5 * chunkSize; |
+ var usePolling = true; |
+ if (typeof sendChannel.bufferedAmountLowThreshold === 'number') { |
+ trace('Using the bufferedamountlow event for flow control'); |
+ usePolling = false; |
+ |
+ // Reduce the buffer fullness threshold, since we now have more efficient |
+ // buffer management. |
+ bufferFullThreshold = chunkSize / 2; |
+ |
+ // This is "overcontrol": our high and low thresholds are the same. |
+ sendChannel.bufferedAmountLowThreshold = bufferFullThreshold; |
+ } |
+ // Listen for one bufferedamountlow event. |
+ var listener = function() { |
+ sendChannel.removeEventListener('bufferedamountlow', listener); |
+ sendAllData(); |
+ }; |
+ var sendAllData = function() { |
+ // Try to queue up a bunch of data and back off when the channel starts to |
+ // fill up. We don't setTimeout after each send since this lowers our |
+ // throughput quite a bit (setTimeout(fn, 0) can take hundreds of milli- |
+ // seconds to execute). |
+ while (sendProgress.value < sendProgress.max) { |
+ if (sendChannel.bufferedAmount > bufferFullThreshold) { |
+ if (usePolling) { |
+ setTimeout(sendAllData, 250); |
+ } else { |
+ sendChannel.addEventListener('bufferedamountlow', listener); |
+ } |
+ return; |
+ } |
+ sendProgress.value += chunkSize; |
+ sendChannel.send(stringToSendRepeatedly); |
+ } |
+ }; |
+ setTimeout(sendAllData, 0); |
+} |
+ |
+function closeDataChannels() { |
+ trace('Closing data channels'); |
+ sendChannel.close(); |
+ trace('Closed data channel with label: ' + sendChannel.label); |
+ receiveChannel.close(); |
+ trace('Closed data channel with label: ' + receiveChannel.label); |
+ localConnection.close(); |
+ remoteConnection.close(); |
+ localConnection = null; |
+ remoteConnection = null; |
+ trace('Closed peer connections'); |
+} |
+ |
+function gotDescription1(desc) { |
+ localConnection.setLocalDescription(desc); |
+ trace('Offer from localConnection \n' + desc.sdp); |
+ remoteConnection.setRemoteDescription(desc); |
+ remoteConnection.createAnswer().then( |
+ gotDescription2, |
+ onCreateSessionDescriptionError |
+ ); |
+} |
+ |
+function gotDescription2(desc) { |
+ remoteConnection.setLocalDescription(desc); |
+ trace('Answer from remoteConnection \n' + desc.sdp); |
+ localConnection.setRemoteDescription(desc); |
+} |
+ |
+function getOtherPc(pc) { |
+ return (pc === localConnection) ? remoteConnection : localConnection; |
+} |
+ |
+function getName(pc) { |
+ return (pc === localConnection) ? 'localPeerConnection' : |
+ 'remotePeerConnection'; |
+} |
+ |
+function onIceCandidate(pc, event) { |
+ getOtherPc(pc).addIceCandidate(event.candidate) |
+ .then( |
+ function() { |
+ onAddIceCandidateSuccess(pc); |
+ }, |
+ function(err) { |
+ onAddIceCandidateError(pc, err); |
+ } |
+ ); |
+ trace(getName(pc) + ' ICE candidate: \n' + (event.candidate ? |
+ event.candidate.candidate : '(null)')); |
+} |
+ |
+function onAddIceCandidateSuccess() { |
+ trace('AddIceCandidate success.'); |
+} |
+ |
+function onAddIceCandidateError(error) { |
+ trace('Failed to add Ice Candidate: ' + error.toString()); |
+} |
+ |
+function receiveChannelCallback(event) { |
+ trace('Receive Channel Callback'); |
+ receiveChannel = event.channel; |
+ receiveChannel.binaryType = 'arraybuffer'; |
+ receiveChannel.onmessage = onReceiveMessageCallback; |
+ |
+ receivedSize = 0; |
+} |
+ |
+function onReceiveMessageCallback(event) { |
+ receivedSize += event.data.length; |
+ receiveProgress.value = receivedSize; |
+ |
+ if (receivedSize === bytesToSend) { |
+ closeDataChannels(); |
+ sendButton.disabled = false; |
+ megsToSend.disabled = false; |
+ } |
+} |
+ |
+function onSendChannelStateChange() { |
+ var readyState = sendChannel.readyState; |
+ trace('Send channel state is: ' + readyState); |
+ if (readyState === 'open') { |
+ sendGeneratedData(); |
+ } |
+} |