diff --git a/dom/presentation/PresentationDataChannelSessionTransport.js b/dom/presentation/PresentationDataChannelSessionTransport.js index 5da306d7e3e1..1adbad694dc5 100644 --- a/dom/presentation/PresentationDataChannelSessionTransport.js +++ b/dom/presentation/PresentationDataChannelSessionTransport.js @@ -49,11 +49,10 @@ PresentationTransportBuilder.prototype = { classID: PRESENTATIONTRANSPORTBUILDER_CID, contractID: PRESENTATIONTRANSPORTBUILDER_CONTRACTID, QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDataChannelSessionTransportBuilder, - Ci.nsIPresentationControlChannelListener, Ci.nsITimerCallback]), - buildDataChannelTransport: function(aRole, aWindow, aControlChannel, aListener) { - if (!aRole || !aWindow || !aControlChannel || !aListener) { + buildDataChannelTransport: function(aRole, aWindow, aListener) { + if (!aRole || !aWindow || !aListener) { log("buildDataChannelTransport with illegal parameters"); throw Cr.NS_ERROR_ILLEGAL_VALUE; } @@ -66,23 +65,21 @@ PresentationTransportBuilder.prototype = { log("buildDataChannelTransport with role " + aRole); this._role = aRole; this._window = aWindow; - this._controlChannel = aControlChannel.QueryInterface(Ci.nsIPresentationControlChannel); - this._controlChannel.listener = this; this._listener = aListener.QueryInterface(Ci.nsIPresentationSessionTransportBuilderListener); // TODO bug 1227053 set iceServers from |nsIPresentationDevice| this._peerConnection = new this._window.RTCPeerConnection(); - // |this._controlChannel == null| will throw since the control channel is + // |this._listener == null| will throw since the control channel is // abnormally closed. this._peerConnection.onicecandidate = aEvent => aEvent.candidate && - this._controlChannel.sendIceCandidate(JSON.stringify(aEvent.candidate)); + this._listener.sendIceCandidate(JSON.stringify(aEvent.candidate)); this._peerConnection.onnegotiationneeded = () => { log("onnegotiationneeded with role " + this._role); this._peerConnection.createOffer() .then(aOffer => this._peerConnection.setLocalDescription(aOffer)) - .then(() => this._controlChannel + .then(() => this._listener .sendOffer(new PresentationDataChannelDescription(this._peerConnection.localDescription))) .catch(e => this._reportError(e)); } @@ -169,11 +166,6 @@ PresentationTransportBuilder.prototype = { this._role = null; this._window = null; - if (this._controlChannel) { - this._controlChannel.close(aReason); - this._controlChannel = null; - } - this._listener = null; this._sessionTransport = null; @@ -202,7 +194,7 @@ PresentationTransportBuilder.prototype = { .then(aAnswer => this._peerConnection.setLocalDescription(aAnswer)) .then(() => { this._isControlChannelNeeded = false; - this._controlChannel + this._listener .sendAnswer(new PresentationDataChannelDescription(this._peerConnection.localDescription)) }).catch(e => this._reportError(e)); }, @@ -229,10 +221,6 @@ PresentationTransportBuilder.prototype = { this._peerConnection.addIceCandidate(candidate).catch(e => this._reportError(e)); }, - notifyOpened: function() { - log("notifyOpened, should be opened beforehand"); - }, - notifyClosed: function(aReason) { log("notifyClosed reason: " + aReason); @@ -241,7 +229,6 @@ PresentationTransportBuilder.prototype = { } else if (this._isControlChannelNeeded) { this._cleanup(Cr.NS_ERROR_FAILURE); } - this._controlChannel = null; }, }; diff --git a/dom/presentation/PresentationService.cpp b/dom/presentation/PresentationService.cpp index 9bda51417ab5..54cdd07db291 100644 --- a/dom/presentation/PresentationService.cpp +++ b/dom/presentation/PresentationService.cpp @@ -453,7 +453,7 @@ PresentationService::StartSession(const nsAString& aUrl, NS_ConvertUTF16toUTF8 utf8DeviceId(aDeviceId); bool hasMore; - while(NS_SUCCEEDED(enumerator->HasMoreElements(&hasMore)) && hasMore){ + while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMore)) && hasMore) { nsCOMPtr isupports; rv = enumerator->GetNext(getter_AddRefs(isupports)); diff --git a/dom/presentation/PresentationSessionInfo.cpp b/dom/presentation/PresentationSessionInfo.cpp index 6618bd6f6318..7513b98d69bd 100644 --- a/dom/presentation/PresentationSessionInfo.cpp +++ b/dom/presentation/PresentationSessionInfo.cpp @@ -433,6 +433,30 @@ PresentationSessionInfo::OnError(nsresult reason) return ReplyError(reason); } +NS_IMETHODIMP +PresentationSessionInfo::SendOffer(nsIPresentationChannelDescription* aOffer) +{ + return mControlChannel->SendOffer(aOffer); +} + +NS_IMETHODIMP +PresentationSessionInfo::SendAnswer(nsIPresentationChannelDescription* aAnswer) +{ + return mControlChannel->SendAnswer(aAnswer); +} + +NS_IMETHODIMP +PresentationSessionInfo::SendIceCandidate(const nsAString& candidate) +{ + return mControlChannel->SendIceCandidate(candidate); +} + +NS_IMETHODIMP +PresentationSessionInfo::Close(nsresult reason) +{ + return mControlChannel->Close(reason); +} + /** * Implementation of PresentationControllingInfo * @@ -580,8 +604,18 @@ PresentationControllingInfo::GetAddress() NS_IMETHODIMP PresentationControllingInfo::OnIceCandidate(const nsAString& aCandidate) { - MOZ_ASSERT(false, "Should not receive ICE candidates."); - return NS_ERROR_FAILURE; + if (mTransportType != nsIPresentationChannelDescription::TYPE_DATACHANNEL) { + return NS_ERROR_FAILURE; + } + + if (NS_WARN_IF(!mBuilder)) { + return NS_ERROR_FAILURE; + } + + nsCOMPtr + builder = do_QueryInterface(mBuilder); + + return builder->OnIceCandidate(aCandidate); } nsresult @@ -612,6 +646,16 @@ PresentationControllingInfo::OnOffer(nsIPresentationChannelDescription* aDescrip NS_IMETHODIMP PresentationControllingInfo::OnAnswer(nsIPresentationChannelDescription* aDescription) { + if (mTransportType == nsIPresentationChannelDescription::TYPE_DATACHANNEL) { + + if (NS_WARN_IF(!mBuilder)) { + return NS_ERROR_FAILURE; + } + nsCOMPtr + builder = do_QueryInterface(mBuilder); + return builder->OnAnswer(aDescription); + } + mIsResponderReady = true; // Close the control channel since it's no longer needed. @@ -651,7 +695,6 @@ PresentationControllingInfo::NotifyOpened() return builder->BuildDataChannelTransport(nsIPresentationService::ROLE_CONTROLLER, GetWindow(), - mControlChannel, this); } @@ -661,6 +704,16 @@ PresentationControllingInfo::NotifyClosed(nsresult aReason) { MOZ_ASSERT(NS_IsMainThread()); + if (mTransportType == nsIPresentationChannelDescription::TYPE_DATACHANNEL) { + if (NS_WARN_IF(!mBuilder)) { + return NS_ERROR_FAILURE; + } + nsCOMPtr + builder = do_QueryInterface(mBuilder); + + NS_WARN_IF(NS_FAILED(builder->NotifyClosed(aReason))); + } + // Unset control channel here so it won't try to re-close it in potential // subsequent |Shutdown| calls. SetControlChannel(nullptr); @@ -823,12 +876,6 @@ PresentationPresentingInfo::OnSessionTransport(nsIPresentationSessionTransport* return NS_OK; } -NS_IMETHODIMP -PresentationPresentingInfo::OnError(nsresult reason) -{ - return PresentationSessionInfo::OnError(reason); -} - nsresult PresentationPresentingInfo::InitTransportAndSendAnswer() { @@ -869,20 +916,13 @@ PresentationPresentingInfo::InitTransportAndSendAnswer() mTransportType = nsIPresentationChannelDescription::TYPE_DATACHANNEL; rv = builder->BuildDataChannelTransport(nsIPresentationService::ROLE_RECEIVER, GetWindow(), - mControlChannel, this); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } // delegate |onOffer| to builder - nsCOMPtr listener(do_QueryInterface(builder)); - - if (NS_WARN_IF(!listener)) { - return NS_ERROR_NOT_AVAILABLE; - } - - return listener->OnOffer(mRequesterDescription); + return builder->OnOffer(mRequesterDescription); } MOZ_ASSERT(false, "Unknown nsIPresentationChannelDescription type!"); @@ -971,8 +1011,14 @@ PresentationPresentingInfo::OnAnswer(nsIPresentationChannelDescription* aDescrip NS_IMETHODIMP PresentationPresentingInfo::OnIceCandidate(const nsAString& aCandidate) { - MOZ_ASSERT(false, "Should not receive ICE candidates."); - return NS_ERROR_FAILURE; + if (NS_WARN_IF(!mBuilder)) { + return NS_ERROR_FAILURE; + } + + nsCOMPtr + builder = do_QueryInterface(mBuilder); + + return builder->OnIceCandidate(aCandidate); } NS_IMETHODIMP @@ -987,6 +1033,16 @@ PresentationPresentingInfo::NotifyClosed(nsresult aReason) { MOZ_ASSERT(NS_IsMainThread()); + if (mTransportType == nsIPresentationChannelDescription::TYPE_DATACHANNEL) { + if (NS_WARN_IF(!mBuilder)) { + return NS_ERROR_FAILURE; + } + nsCOMPtr + builder = do_QueryInterface(mBuilder); + + NS_WARN_IF(NS_FAILED(builder->NotifyClosed(aReason))); + } + // Unset control channel here so it won't try to re-close it in potential // subsequent |Shutdown| calls. SetControlChannel(nullptr); diff --git a/dom/presentation/PresentationSessionInfo.h b/dom/presentation/PresentationSessionInfo.h index f7ac2d24c467..ffc810cacdac 100644 --- a/dom/presentation/PresentationSessionInfo.h +++ b/dom/presentation/PresentationSessionInfo.h @@ -208,7 +208,6 @@ class PresentationPresentingInfo final : public PresentationSessionInfo public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIPRESENTATIONCONTROLCHANNELLISTENER - NS_DECL_NSIPRESENTATIONSESSIONTRANSPORTBUILDERLISTENER NS_DECL_NSITIMERCALLBACK PresentationPresentingInfo(const nsAString& aUrl, @@ -226,6 +225,8 @@ public: nsresult NotifyResponderReady(); + NS_IMETHODIMP OnSessionTransport(nsIPresentationSessionTransport* transport) override; + void ResolvedCallback(JSContext* aCx, JS::Handle aValue) override; void RejectedCallback(JSContext* aCx, JS::Handle aValue) override; diff --git a/dom/presentation/PresentationTCPSessionTransport.cpp b/dom/presentation/PresentationTCPSessionTransport.cpp index 111242f4d7c4..56b13e22f295 100644 --- a/dom/presentation/PresentationTCPSessionTransport.cpp +++ b/dom/presentation/PresentationTCPSessionTransport.cpp @@ -68,12 +68,13 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(PresentationTCPSessionTransport) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PresentationTCPSessionTransport) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPresentationSessionTransport) - NS_INTERFACE_MAP_ENTRY(nsIPresentationSessionTransport) - NS_INTERFACE_MAP_ENTRY(nsITransportEventSink) - NS_INTERFACE_MAP_ENTRY(nsIPresentationTCPSessionTransportBuilder) NS_INTERFACE_MAP_ENTRY(nsIInputStreamCallback) - NS_INTERFACE_MAP_ENTRY(nsIStreamListener) + NS_INTERFACE_MAP_ENTRY(nsIPresentationSessionTransport) + NS_INTERFACE_MAP_ENTRY(nsIPresentationSessionTransportBuilder) + NS_INTERFACE_MAP_ENTRY(nsIPresentationTCPSessionTransportBuilder) NS_INTERFACE_MAP_ENTRY(nsIRequestObserver) + NS_INTERFACE_MAP_ENTRY(nsIStreamListener) + NS_INTERFACE_MAP_ENTRY(nsITransportEventSink) NS_INTERFACE_MAP_END PresentationTCPSessionTransport::PresentationTCPSessionTransport() diff --git a/dom/presentation/interfaces/nsIPresentationSessionTransportBuilder.idl b/dom/presentation/interfaces/nsIPresentationSessionTransportBuilder.idl index 1418eb909608..feb4e93f729f 100644 --- a/dom/presentation/interfaces/nsIPresentationSessionTransportBuilder.idl +++ b/dom/presentation/interfaces/nsIPresentationSessionTransportBuilder.idl @@ -15,8 +15,12 @@ interface nsIPresentationSessionTransportBuilderListener : nsISupports { // Should set |transport.callback| in |onSessionTransport|. void onSessionTransport(in nsIPresentationSessionTransport transport); - void onError(in nsresult reason); + + void sendOffer(in nsIPresentationChannelDescription offer); + void sendAnswer(in nsIPresentationChannelDescription answer); + void sendIceCandidate(in DOMString candidate); + void close(in nsresult reason); }; [scriptable, uuid(2fdbe67d-80f9-48dc-8237-5bef8fa19801)] @@ -55,8 +59,13 @@ interface nsIPresentationDataChannelSessionTransportBuilder : nsIPresentationSes * |aControlChannel| should be called before calling * |buildDataChannelTransport|. */ - void buildDataChannelTransport(in uint8_t aType, + void buildDataChannelTransport(in uint8_t aRole, in mozIDOMWindow aWindow, - in nsIPresentationControlChannel aControlChannel, in nsIPresentationSessionTransportBuilderListener aListener); + + // Bug 1275150 - Merge TCP builder with the following APIs + void onOffer(in nsIPresentationChannelDescription offer); + void onAnswer(in nsIPresentationChannelDescription answer); + void onIceCandidate(in DOMString candidate); + void notifyClosed(in nsresult reason); }; diff --git a/dom/presentation/tests/mochitest/PresentationSessionChromeScript.js b/dom/presentation/tests/mochitest/PresentationSessionChromeScript.js index 21d16746f468..711999d07d85 100644 --- a/dom/presentation/tests/mochitest/PresentationSessionChromeScript.js +++ b/dom/presentation/tests/mochitest/PresentationSessionChromeScript.js @@ -256,7 +256,7 @@ const mockedSessionTransport = { }, 0); }, // in-process case - buildDataChannelTransport: function(role, window, controlChannel, listener) { + buildDataChannelTransport: function(role, window, listener) { this._listener = listener; this._role = role; diff --git a/dom/presentation/tests/mochitest/test_presentation_datachannel_sessiontransport.html b/dom/presentation/tests/mochitest/test_presentation_datachannel_sessiontransport.html index fd61521baccc..918edc13526a 100644 --- a/dom/presentation/tests/mochitest/test_presentation_datachannel_sessiontransport.html +++ b/dom/presentation/tests/mochitest/test_presentation_datachannel_sessiontransport.html @@ -26,8 +26,6 @@ var clientBuilder; var serverBuilder; var clientTransport; var serverTransport; -var clientControlChannel; -var serverControlChannel; const clientMessage = "Client Message"; const serverMessage = "Server Message"; @@ -36,36 +34,6 @@ const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; const { XPCOMUtils } = Cu.import("resource://gre/modules/XPCOMUtils.jsm"); const { Services } = Cu.import("resource://gre/modules/Services.jsm"); -function TestControlChannel() { - this._listener = null; -} - -TestControlChannel.prototype = { - QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationControlChannel]), - set listener(aListener) { - this._listener = aListener; - }, - get listener() { - return this._listener; - }, - sendOffer: function(aOffer) { - setTimeout(()=>this._remote.listener.onOffer(aOffer), 0); - }, - sendAnswer: function(aAnswer) { - setTimeout(()=>this._remote.listener.onAnswer(aAnswer), 0); - }, - sendIceCandidate: function(aCandidate) { - setTimeout(()=>this._remote.listener.onIceCandidate(aCandidate), 0); - }, - close: function(aReason) { - setTimeout(()=>this._listener.notifyClosed(aReason), 0); - setTimeout(()=>this._remote.listener.notifyClosed(aReason), 0); - }, - set remote(aRemote) { - this._remote = aRemote; - }, -}; - var isClientReady = false; var isServerReady = false; var isClientClosed = false; @@ -131,7 +99,26 @@ const clientListener = { }, onError: function(aError) { ok(false, "client's builder reports error " + aError); - } + }, + sendOffer: function(aOffer) { + setTimeout(()=>this._remoteBuilder.onOffer(aOffer), 0); + }, + sendAnswer: function(aAnswer) { + setTimeout(()=>this._remoteBuilder.onAnswer(aAnswer), 0); + }, + sendIceCandidate: function(aCandidate) { + setTimeout(()=>this._remoteBuilder.onIceCandidate(aCandidate), 0); + }, + close: function(aReason) { + setTimeout(()=>this._localBuilder.notifyClosed(aReason), 0); + setTimeout(()=>this._remoteBuilder.notifyClosed(aReason), 0); + }, + set remoteBuilder(aRemoteBuilder) { + this._remoteBuilder = aRemoteBuilder; + }, + set localBuilder(aLocalBuilder) { + this._localBuilder = aLocalBuilder; + }, } const serverListener = { @@ -144,7 +131,26 @@ const serverListener = { }, onError: function(aError) { ok(false, "server's builder reports error " + aError); - } + }, + sendOffer: function(aOffer) { + setTimeout(()=>this._remoteBuilder.onOffer(aOffer), 0); + }, + sendAnswer: function(aAnswer) { + setTimeout(()=>this._remoteBuilder.onAnswer(aAnswer), 0); + }, + sendIceCandidate: function(aCandidate) { + setTimeout(()=>this._remoteBuilder.onIceCandidate(aCandidate), 0); + }, + close: function(aReason) { + setTimeout(()=>this._localBuilder.notifyClosed(aReason), 0); + setTimeout(()=>this._remoteBuilder.notifyClosed(aReason), 0); + }, + set remoteBuilder(aRemoteBuilder) { + this._remoteBuilder = aRemoteBuilder; + }, + set localBuilder(aLocalBuilder) { + this._localBuilder = aLocalBuilder; + }, } function testBuilder() { @@ -152,26 +158,24 @@ function testBuilder() { gResolve = aResolve; gReject = aReject; - clientControlChannel = new TestControlChannel(); - serverControlChannel = new TestControlChannel(); - clientControlChannel.remote = serverControlChannel; - serverControlChannel.remote = clientControlChannel; - clientBuilder = Cc["@mozilla.org/presentation/datachanneltransportbuilder;1"] .createInstance(Ci.nsIPresentationDataChannelSessionTransportBuilder); serverBuilder = Cc["@mozilla.org/presentation/datachanneltransportbuilder;1"] .createInstance(Ci.nsIPresentationDataChannelSessionTransportBuilder); + clientListener.localBuilder = clientBuilder; + clientListener.remoteBuilder = serverBuilder; + serverListener.localBuilder = serverBuilder; + serverListener.remoteBuilder = clientBuilder; + clientBuilder .buildDataChannelTransport(Ci.nsIPresentationService.ROLE_CONTROLLER, window, - clientControlChannel, clientListener); serverBuilder .buildDataChannelTransport(Ci.nsIPresentationService.ROLE_RECEIVER, window, - serverControlChannel, serverListener); }); }