diff options
Diffstat (limited to 'dom/presentation/PresentationDataChannelSessionTransport.js')
-rw-r--r-- | dom/presentation/PresentationDataChannelSessionTransport.js | 378 |
1 files changed, 0 insertions, 378 deletions
diff --git a/dom/presentation/PresentationDataChannelSessionTransport.js b/dom/presentation/PresentationDataChannelSessionTransport.js deleted file mode 100644 index 9af6213cb..000000000 --- a/dom/presentation/PresentationDataChannelSessionTransport.js +++ /dev/null @@ -1,378 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public -* License, v. 2.0. If a copy of the MPL was not distributed with this file, -* You can obtain one at http://mozilla.org/MPL/2.0/. */ - -"use strict"; - -const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); - -// Bug 1228209 - plan to remove this eventually -function log(aMsg) { - //dump("-*- PresentationDataChannelSessionTransport.js : " + aMsg + "\n"); -} - -const PRESENTATIONTRANSPORT_CID = Components.ID("{dd2bbf2f-3399-4389-8f5f-d382afb8b2d6}"); -const PRESENTATIONTRANSPORT_CONTRACTID = "mozilla.org/presentation/datachanneltransport;1"; - -const PRESENTATIONTRANSPORTBUILDER_CID = Components.ID("{215b2f62-46e2-4004-a3d1-6858e56c20f3}"); -const PRESENTATIONTRANSPORTBUILDER_CONTRACTID = "mozilla.org/presentation/datachanneltransportbuilder;1"; - -function PresentationDataChannelDescription(aDataChannelSDP) { - this._dataChannelSDP = JSON.stringify(aDataChannelSDP); -} - -PresentationDataChannelDescription.prototype = { - QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationChannelDescription]), - get type() { - return Ci.nsIPresentationChannelDescription.TYPE_DATACHANNEL; - }, - get tcpAddress() { - return null; - }, - get tcpPort() { - return null; - }, - get dataChannelSDP() { - return this._dataChannelSDP; - } -}; - -function PresentationTransportBuilder() { - log("PresentationTransportBuilder construct"); - this._isControlChannelNeeded = true; -} - -PresentationTransportBuilder.prototype = { - classID: PRESENTATIONTRANSPORTBUILDER_CID, - contractID: PRESENTATIONTRANSPORTBUILDER_CONTRACTID, - QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationSessionTransportBuilder, - Ci.nsIPresentationDataChannelSessionTransportBuilder, - Ci.nsITimerCallback]), - - buildDataChannelTransport: function(aRole, aWindow, aListener) { - if (!aRole || !aWindow || !aListener) { - log("buildDataChannelTransport with illegal parameters"); - throw Cr.NS_ERROR_ILLEGAL_VALUE; - } - - if (this._window) { - log("buildDataChannelTransport has started."); - throw Cr.NS_ERROR_UNEXPECTED; - } - - log("buildDataChannelTransport with role " + aRole); - this._role = aRole; - this._window = aWindow; - this._listener = aListener.QueryInterface(Ci.nsIPresentationSessionTransportBuilderListener); - - // TODO bug 1227053 set iceServers from |nsIPresentationDevice| - this._peerConnection = new this._window.RTCPeerConnection(); - - // |this._listener == null| will throw since the control channel is - // abnormally closed. - this._peerConnection.onicecandidate = aEvent => aEvent.candidate && - this._listener.sendIceCandidate(JSON.stringify(aEvent.candidate)); - - this._peerConnection.onnegotiationneeded = () => { - log("onnegotiationneeded with role " + this._role); - if (!this._peerConnection) { - log("ignoring negotiationneeded without PeerConnection"); - return; - } - this._peerConnection.createOffer() - .then(aOffer => this._peerConnection.setLocalDescription(aOffer)) - .then(() => this._listener - .sendOffer(new PresentationDataChannelDescription(this._peerConnection.localDescription))) - .catch(e => this._reportError(e)); - } - - switch (this._role) { - case Ci.nsIPresentationService.ROLE_CONTROLLER: - this._dataChannel = this._peerConnection.createDataChannel("presentationAPI"); - this._setDataChannel(); - break; - - case Ci.nsIPresentationService.ROLE_RECEIVER: - this._peerConnection.ondatachannel = aEvent => { - this._dataChannel = aEvent.channel; - // Ensure the binaryType of dataChannel is blob. - this._dataChannel.binaryType = "blob"; - this._setDataChannel(); - } - break; - default: - throw Cr.NS_ERROR_ILLEGAL_VALUE; - } - - // TODO bug 1228235 we should have a way to let device providers customize - // the time-out duration. - let timeout = Services.prefs.getIntPref("presentation.receiver.loading.timeout", 10000); - - // The timer is to check if the negotiation finishes on time. - this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); - this._timer.initWithCallback(this, timeout, this._timer.TYPE_ONE_SHOT); - }, - - notify: function() { - if (!this._sessionTransport) { - this._cleanup(Cr.NS_ERROR_NET_TIMEOUT); - } - }, - - _reportError: function(aError) { - log("report Error " + aError.name + ":" + aError.message); - this._cleanup(Cr.NS_ERROR_FAILURE); - }, - - _setDataChannel: function() { - this._dataChannel.onopen = () => { - log("data channel is open, notify the listener, role " + this._role); - - // Handoff the ownership of _peerConnection and _dataChannel to - // _sessionTransport - this._sessionTransport = new PresentationTransport(); - this._sessionTransport.init(this._peerConnection, this._dataChannel, this._window); - this._peerConnection.onicecandidate = null; - this._peerConnection.onnegotiationneeded = null; - this._peerConnection = this._dataChannel = null; - - this._listener.onSessionTransport(this._sessionTransport); - this._sessionTransport.callback.notifyTransportReady(); - - this._cleanup(Cr.NS_OK); - }; - - this._dataChannel.onerror = aError => { - log("data channel onerror " + aError.name + ":" + aError.message); - this._cleanup(Cr.NS_ERROR_FAILURE); - } - }, - - _cleanup: function(aReason) { - if (aReason != Cr.NS_OK) { - this._listener.onError(aReason); - } - - if (this._dataChannel) { - this._dataChannel.close(); - this._dataChannel = null; - } - - if (this._peerConnection) { - this._peerConnection.close(); - this._peerConnection = null; - } - - this._role = null; - this._window = null; - - this._listener = null; - this._sessionTransport = null; - - if (this._timer) { - this._timer.cancel(); - this._timer = null; - } - }, - - // nsIPresentationControlChannelListener - onOffer: function(aOffer) { - if (this._role !== Ci.nsIPresentationService.ROLE_RECEIVER || - this._sessionTransport) { - log("onOffer status error"); - this._cleanup(Cr.NS_ERROR_FAILURE); - } - - log("onOffer: " + aOffer.dataChannelSDP + " with role " + this._role); - - let offer = new this._window - .RTCSessionDescription(JSON.parse(aOffer.dataChannelSDP)); - - this._peerConnection.setRemoteDescription(offer) - .then(() => this._peerConnection.signalingState == "stable" || - this._peerConnection.createAnswer()) - .then(aAnswer => this._peerConnection.setLocalDescription(aAnswer)) - .then(() => { - this._isControlChannelNeeded = false; - this._listener - .sendAnswer(new PresentationDataChannelDescription(this._peerConnection.localDescription)) - }).catch(e => this._reportError(e)); - }, - - onAnswer: function(aAnswer) { - if (this._role !== Ci.nsIPresentationService.ROLE_CONTROLLER || - this._sessionTransport) { - log("onAnswer status error"); - this._cleanup(Cr.NS_ERROR_FAILURE); - } - - log("onAnswer: " + aAnswer.dataChannelSDP + " with role " + this._role); - - let answer = new this._window - .RTCSessionDescription(JSON.parse(aAnswer.dataChannelSDP)); - - this._peerConnection.setRemoteDescription(answer).catch(e => this._reportError(e)); - this._isControlChannelNeeded = false; - }, - - onIceCandidate: function(aCandidate) { - log("onIceCandidate: " + aCandidate + " with role " + this._role); - if (!this._window || !this._peerConnection) { - log("ignoring ICE candidate after connection"); - return; - } - let candidate = new this._window.RTCIceCandidate(JSON.parse(aCandidate)); - this._peerConnection.addIceCandidate(candidate).catch(e => this._reportError(e)); - }, - - notifyDisconnected: function(aReason) { - log("notifyDisconnected reason: " + aReason); - - if (aReason != Cr.NS_OK) { - this._cleanup(aReason); - } else if (this._isControlChannelNeeded) { - this._cleanup(Cr.NS_ERROR_FAILURE); - } - }, -}; - -function PresentationTransport() { - this._messageQueue = []; - this._closeReason = Cr.NS_OK; -} - -PresentationTransport.prototype = { - classID: PRESENTATIONTRANSPORT_CID, - contractID: PRESENTATIONTRANSPORT_CONTRACTID, - QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationSessionTransport]), - - init: function(aPeerConnection, aDataChannel, aWindow) { - log("initWithDataChannel"); - this._enableDataNotification = false; - this._dataChannel = aDataChannel; - this._peerConnection = aPeerConnection; - this._window = aWindow; - - this._dataChannel.onopen = () => { - log("data channel reopen. Should never touch here"); - }; - - this._dataChannel.onclose = () => { - log("data channel onclose"); - if (this._callback) { - this._callback.notifyTransportClosed(this._closeReason); - } - this._cleanup(); - } - - this._dataChannel.onmessage = aEvent => { - log("data channel onmessage " + aEvent.data); - - if (!this._enableDataNotification || !this._callback) { - log("queue message"); - this._messageQueue.push(aEvent.data); - return; - } - this._doNotifyData(aEvent.data); - }; - - this._dataChannel.onerror = aError => { - log("data channel onerror " + aError.name + ":" + aError.message); - if (this._callback) { - this._callback.notifyTransportClosed(Cr.NS_ERROR_FAILURE); - } - this._cleanup(); - } - }, - - // nsIPresentationTransport - get selfAddress() { - throw NS_ERROR_NOT_AVAILABLE; - }, - - get callback() { - return this._callback; - }, - - set callback(aCallback) { - this._callback = aCallback; - }, - - send: function(aData) { - log("send " + aData); - this._dataChannel.send(aData); - }, - - sendBinaryMsg: function(aData) { - log("sendBinaryMsg"); - - let array = new Uint8Array(aData.length); - for (let i = 0; i < aData.length; i++) { - array[i] = aData.charCodeAt(i); - } - - this._dataChannel.send(array); - }, - - sendBlob: function(aBlob) { - log("sendBlob"); - - this._dataChannel.send(aBlob); - }, - - enableDataNotification: function() { - log("enableDataNotification"); - if (this._enableDataNotification) { - return; - } - - if (!this._callback) { - throw NS_ERROR_NOT_AVAILABLE; - } - - this._enableDataNotification = true; - - this._messageQueue.forEach(aData => this._doNotifyData(aData)); - this._messageQueue = []; - }, - - close: function(aReason) { - this._closeReason = aReason; - - this._dataChannel.close(); - }, - - _cleanup: function() { - this._dataChannel = null; - - if (this._peerConnection) { - this._peerConnection.close(); - this._peerConnection = null; - } - this._callback = null; - this._messageQueue = []; - this._window = null; - }, - - _doNotifyData: function(aData) { - if (!this._callback) { - throw NS_ERROR_NOT_AVAILABLE; - } - - if (aData instanceof this._window.Blob) { - let reader = new this._window.FileReader(); - reader.addEventListener("load", (aEvent) => { - this._callback.notifyData(aEvent.target.result, true); - }); - reader.readAsBinaryString(aData); - } else { - this._callback.notifyData(aData, false); - } - }, -}; - -this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PresentationTransportBuilder, - PresentationTransport]); |