Bug 1264513 - Part 1: IPresentationSessionTransportBuilder.idl changes - necessary refactory in in-proc data channel handling, r=smaug

This commit is contained in:
Junior Hsu 2016-06-03 11:03:15 +08:00 коммит произвёл Liang-Heng Chen
Родитель ab4635f5a3
Коммит 60de51a4c5
8 изменённых файлов: 147 добавлений и 89 удалений

Просмотреть файл

@ -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;
},
};

Просмотреть файл

@ -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<nsISupports> isupports;
rv = enumerator->GetNext(getter_AddRefs(isupports));

Просмотреть файл

@ -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<nsIPresentationDataChannelSessionTransportBuilder>
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<nsIPresentationDataChannelSessionTransportBuilder>
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<nsIPresentationDataChannelSessionTransportBuilder>
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<nsIPresentationControlChannelListener> 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<nsIPresentationDataChannelSessionTransportBuilder>
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<nsIPresentationDataChannelSessionTransportBuilder>
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);

Просмотреть файл

@ -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<JS::Value> aValue) override;
void RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;

Просмотреть файл

@ -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()

Просмотреть файл

@ -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);
};

Просмотреть файл

@ -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;

Просмотреть файл

@ -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);
});
}