зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1276378 - Part 1: Add terminate command in control protocol. r=junior
MozReview-Commit-ID: BwfJKcXmN07 --HG-- extra : rebase_source : 7df8c968def5fa9640499257ce8b8814fe884388
This commit is contained in:
Родитель
faec6da232
Коммит
c8b67767f3
|
@ -14,6 +14,7 @@
|
|||
#include "nsIObserverService.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "PresentationSessionRequest.h"
|
||||
#include "PresentationTerminateRequest.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -239,6 +240,28 @@ PresentationDeviceManager::OnSessionRequest(nsIPresentationDevice* aDevice,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresentationDeviceManager::OnTerminateRequest(nsIPresentationDevice* aDevice,
|
||||
const nsAString& aPresentationId,
|
||||
nsIPresentationControlChannel* aControlChannel,
|
||||
bool aIsFromReceiver)
|
||||
{
|
||||
NS_ENSURE_ARG(aDevice);
|
||||
NS_ENSURE_ARG(aControlChannel);
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||
NS_ENSURE_TRUE(obs, NS_ERROR_FAILURE);
|
||||
|
||||
RefPtr<PresentationTerminateRequest> request =
|
||||
new PresentationTerminateRequest(aDevice, aPresentationId,
|
||||
aControlChannel, aIsFromReceiver);
|
||||
obs->NotifyObservers(request,
|
||||
PRESENTATION_TERMINATE_REQUEST_TOPIC,
|
||||
nullptr);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIObserver
|
||||
NS_IMETHODIMP
|
||||
PresentationDeviceManager::Observe(nsISupports *aSubject,
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#include "PresentationTerminateRequest.h"
|
||||
#include "nsIPresentationControlChannel.h"
|
||||
#include "nsIPresentationDevice.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_ISUPPORTS(PresentationTerminateRequest, nsIPresentationTerminateRequest)
|
||||
|
||||
PresentationTerminateRequest::PresentationTerminateRequest(
|
||||
nsIPresentationDevice* aDevice,
|
||||
const nsAString& aPresentationId,
|
||||
nsIPresentationControlChannel* aControlChannel,
|
||||
bool aIsFromReceiver)
|
||||
: mPresentationId(aPresentationId)
|
||||
, mDevice(aDevice)
|
||||
, mControlChannel(aControlChannel)
|
||||
, mIsFromReceiver(aIsFromReceiver)
|
||||
{
|
||||
}
|
||||
|
||||
PresentationTerminateRequest::~PresentationTerminateRequest()
|
||||
{
|
||||
}
|
||||
|
||||
// nsIPresentationTerminateRequest
|
||||
NS_IMETHODIMP
|
||||
PresentationTerminateRequest::GetDevice(nsIPresentationDevice** aRetVal)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aRetVal);
|
||||
|
||||
nsCOMPtr<nsIPresentationDevice> device = mDevice;
|
||||
device.forget(aRetVal);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresentationTerminateRequest::GetPresentationId(nsAString& aRetVal)
|
||||
{
|
||||
aRetVal = mPresentationId;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresentationTerminateRequest::GetControlChannel(
|
||||
nsIPresentationControlChannel** aRetVal)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aRetVal);
|
||||
|
||||
nsCOMPtr<nsIPresentationControlChannel> controlChannel = mControlChannel;
|
||||
controlChannel.forget(aRetVal);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresentationTerminateRequest::GetIsFromReceiver(bool* aRetVal)
|
||||
{
|
||||
*aRetVal = mIsFromReceiver;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,41 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_dom_PresentationTerminateRequest_h__
|
||||
#define mozilla_dom_PresentationTerminateRequest_h__
|
||||
|
||||
#include "nsIPresentationTerminateRequest.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class PresentationTerminateRequest final : public nsIPresentationTerminateRequest
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIPRESENTATIONTERMINATEREQUEST
|
||||
|
||||
PresentationTerminateRequest(nsIPresentationDevice* aDevice,
|
||||
const nsAString& aPresentationId,
|
||||
nsIPresentationControlChannel* aControlChannel,
|
||||
bool aIsFromReceiver);
|
||||
|
||||
private:
|
||||
virtual ~PresentationTerminateRequest();
|
||||
|
||||
nsString mPresentationId;
|
||||
nsCOMPtr<nsIPresentationDevice> mDevice;
|
||||
nsCOMPtr<nsIPresentationControlChannel> mControlChannel;
|
||||
bool mIsFromReceiver;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_dom_PresentationTerminateRequest_h__ */
|
||||
|
|
@ -18,6 +18,7 @@ XPIDL_SOURCES += [
|
|||
'nsIPresentationSessionRequest.idl',
|
||||
'nsIPresentationSessionTransport.idl',
|
||||
'nsIPresentationSessionTransportBuilder.idl',
|
||||
'nsIPresentationTerminateRequest.idl',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
|
||||
|
|
|
@ -110,6 +110,13 @@ interface nsIPresentationControlChannel: nsISupports
|
|||
*/
|
||||
void launch(in DOMString presentationId, in DOMString url);
|
||||
|
||||
/*
|
||||
* Terminate a presentation on remote endpoint.
|
||||
* @param presentationId The Id for representing this session.
|
||||
* @throws NS_ERROR_FAILURE on failure
|
||||
*/
|
||||
void terminate(in DOMString presentationId);
|
||||
|
||||
/*
|
||||
* Disconnect the control channel.
|
||||
* @param reason The reason of disconnecting channel; NS_OK represents normal.
|
||||
|
|
|
@ -45,6 +45,18 @@ interface nsIPresentationControlServerListener: nsISupports
|
|||
in DOMString aUrl,
|
||||
in DOMString aPresentationId,
|
||||
in nsIPresentationControlChannel aControlChannel);
|
||||
|
||||
/**
|
||||
* Callback while the remote host is requesting to terminate a presentation session.
|
||||
* @param aDeviceInfo The device information related to the remote host.
|
||||
* @param aPresentationId The Id for representing this session.
|
||||
* @param aControlChannel The control channel for this session.
|
||||
* @param aIsFromReceiver true if termination is initiated by receiver.
|
||||
*/
|
||||
void onTerminateRequest(in nsITCPDeviceInfo aDeviceInfo,
|
||||
in DOMString aPresentationId,
|
||||
in nsIPresentationControlChannel aControlChannel,
|
||||
in boolean aIsFromReceiver);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -32,6 +32,18 @@ interface nsIPresentationDeviceListener: nsISupports
|
|||
in DOMString url,
|
||||
in DOMString presentationId,
|
||||
in nsIPresentationControlChannel controlChannel);
|
||||
|
||||
/*
|
||||
* Callback while the remote device is requesting to terminate a presentation session.
|
||||
* @param device The remote device that sent session request.
|
||||
* @param presentationId The Id for representing this session.
|
||||
* @param controlChannel The control channel for this session.
|
||||
* @param aIsFromReceiver true if termination is initiated by receiver.
|
||||
*/
|
||||
void onTerminateRequest(in nsIPresentationDevice device,
|
||||
in DOMString presentationId,
|
||||
in nsIPresentationControlChannel controlChannel,
|
||||
in boolean aIsFromReceiver);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/* 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/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIPresentationDevice;
|
||||
interface nsIPresentationControlChannel;
|
||||
|
||||
%{C++
|
||||
#define PRESENTATION_TERMINATE_REQUEST_TOPIC "presentation-terminate-request"
|
||||
%}
|
||||
|
||||
/*
|
||||
* The event of a device requesting for terminating a presentation session. User can
|
||||
* monitor the terminate request on every device by observing "presentation-terminate-request".
|
||||
*/
|
||||
[scriptable, uuid(3ddbf3a4-53ee-4b70-9bbc-58ac90dce6b5)]
|
||||
interface nsIPresentationTerminateRequest: nsISupports
|
||||
{
|
||||
// The device which requesting to terminate presentation session.
|
||||
readonly attribute nsIPresentationDevice device;
|
||||
|
||||
// The Id for representing this session.
|
||||
readonly attribute DOMString presentationId;
|
||||
|
||||
// The control channel for this session.
|
||||
// Should only use this channel to complete session termination.
|
||||
readonly attribute nsIPresentationControlChannel controlChannel;
|
||||
|
||||
// True if termination is initiated by receiver.
|
||||
readonly attribute boolean isFromReceiver;
|
||||
};
|
|
@ -52,6 +52,7 @@ UNIFIED_SOURCES += [
|
|||
'PresentationSessionInfo.cpp',
|
||||
'PresentationSessionRequest.cpp',
|
||||
'PresentationTCPSessionTransport.cpp',
|
||||
'PresentationTerminateRequest.cpp',
|
||||
]
|
||||
|
||||
EXTRA_COMPONENTS += [
|
||||
|
|
|
@ -50,6 +50,12 @@ var handlers = [
|
|||
case CommandType.LAUNCH_ACK:
|
||||
stateMachine._notifyLaunch(command.presentationId);
|
||||
break;
|
||||
case CommandType.TERMINATE:
|
||||
stateMachine._notifyTerminate(command.presentationId);
|
||||
break;
|
||||
case CommandType.TERMINATE_ACK:
|
||||
stateMachine._notifyTerminate(command.presentationId);
|
||||
break;
|
||||
case CommandType.ANSWER:
|
||||
case CommandType.ICE_CANDIDATE:
|
||||
stateMachine._notifyChannelDescriptor(command);
|
||||
|
@ -87,6 +93,24 @@ ControllerStateMachine.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
terminate: function _terminate(presentationId) {
|
||||
if (this.state === State.CONNECTED) {
|
||||
this._sendCommand({
|
||||
type: CommandType.TERMINATE,
|
||||
presentationId: presentationId,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
terminateAck: function _terminateAck(presentationId) {
|
||||
if (this.state === State.CONNECTED) {
|
||||
this._sendCommand({
|
||||
type: CommandType.TERMINATE_ACK,
|
||||
presentationId: presentationId,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
sendOffer: function _sendOffer(offer) {
|
||||
if (this.state === State.CONNECTED) {
|
||||
this._sendCommand({
|
||||
|
@ -172,6 +196,10 @@ ControllerStateMachine.prototype = {
|
|||
this._channel.notifyLaunch(presentationId);
|
||||
},
|
||||
|
||||
_notifyTerminate: function _notifyTerminate(presentationId) {
|
||||
this._channel.notifyTerminate(presentationId);
|
||||
},
|
||||
|
||||
_notifyChannelDescriptor: function _notifyChannelDescriptor(command) {
|
||||
switch (command.type) {
|
||||
case CommandType.ANSWER:
|
||||
|
|
|
@ -405,6 +405,37 @@ DisplayDeviceProvider::OnSessionRequest(nsITCPDeviceInfo* aDeviceInfo,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DisplayDeviceProvider::OnTerminateRequest(nsITCPDeviceInfo* aDeviceInfo,
|
||||
const nsAString& aPresentationId,
|
||||
nsIPresentationControlChannel* aControlChannel,
|
||||
bool aIsFromReceiver)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aDeviceInfo);
|
||||
MOZ_ASSERT(aControlChannel);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIPresentationDeviceListener> listener;
|
||||
rv = GetListener(getter_AddRefs(listener));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!listener);
|
||||
|
||||
rv = listener->OnTerminateRequest(mDevice,
|
||||
aPresentationId,
|
||||
aControlChannel,
|
||||
aIsFromReceiver);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIObserver
|
||||
NS_IMETHODIMP
|
||||
DisplayDeviceProvider::Observe(nsISupports* aSubject,
|
||||
|
|
|
@ -231,6 +231,12 @@ LegacyTCPControlChannel.prototype = {
|
|||
this._sendInit();
|
||||
},
|
||||
|
||||
terminate: function() {
|
||||
// Legacy protocol doesn't support extra terminate protocol.
|
||||
// Trigger error handling for browser to shutdown all the resource locally.
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
sendOffer: function(aOffer) {
|
||||
let msg = {
|
||||
type: "requestSession:Offer",
|
||||
|
|
|
@ -917,6 +917,50 @@ MulticastDNSDeviceProvider::OnSessionRequest(nsITCPDeviceInfo* aDeviceInfo,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::OnTerminateRequest(nsITCPDeviceInfo* aDeviceInfo,
|
||||
const nsAString& aPresentationId,
|
||||
nsIPresentationControlChannel* aControlChannel,
|
||||
bool aIsFromReceiver)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsAutoCString address;
|
||||
Unused << aDeviceInfo->GetAddress(address);
|
||||
|
||||
LOG_I("OnTerminateRequest: %s", address.get());
|
||||
|
||||
RefPtr<Device> device;
|
||||
uint32_t index;
|
||||
if (FindDeviceByAddress(address, index)) {
|
||||
device = mDevices[index];
|
||||
} else {
|
||||
// Create a one-time device object for non-discoverable controller.
|
||||
// This device will not be in the list of available devices and cannot
|
||||
// be used for requesting session.
|
||||
nsAutoCString id;
|
||||
Unused << aDeviceInfo->GetId(id);
|
||||
uint16_t port;
|
||||
Unused << aDeviceInfo->GetPort(&port);
|
||||
|
||||
device = new Device(id,
|
||||
/* aName = */ id,
|
||||
/* aType = */ EmptyCString(),
|
||||
address,
|
||||
port,
|
||||
DeviceState::eActive,
|
||||
/* aProvider = */ nullptr);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPresentationDeviceListener> listener;
|
||||
if (NS_SUCCEEDED(GetListener(getter_AddRefs(listener))) && listener) {
|
||||
Unused << listener->OnTerminateRequest(device, aPresentationId,
|
||||
aControlChannel, aIsFromReceiver);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIObserver
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::Observe(nsISupports* aSubject,
|
||||
|
|
|
@ -166,6 +166,11 @@ PresentationControlService.prototype = {
|
|||
onSessionRequest: function(aDeviceInfo, aUrl, aPresentationId, aControlChannel) {
|
||||
DEBUG && log("PresentationControlService - onSessionRequest: " +
|
||||
aDeviceInfo.address + ":" + aDeviceInfo.port); // jshint ignore:line
|
||||
if (!this.listener) {
|
||||
this.releaseControlChannel(aControlChannel);
|
||||
return;
|
||||
}
|
||||
|
||||
this.listener.onSessionRequest(aDeviceInfo,
|
||||
aUrl,
|
||||
aPresentationId,
|
||||
|
@ -173,6 +178,21 @@ PresentationControlService.prototype = {
|
|||
this.releaseControlChannel(aControlChannel);
|
||||
},
|
||||
|
||||
onSessionTerminate: function(aDeviceInfo, aPresentationId, aControlChannel, aIsFromReceiver) {
|
||||
DEBUG && log("TCPPresentationServer - onSessionTerminate: " +
|
||||
aDeviceInfo.address + ":" + aDeviceInfo.port); // jshint ignore:line
|
||||
if (!this.listener) {
|
||||
this.releaseControlChannel(aControlChannel);
|
||||
return;
|
||||
}
|
||||
|
||||
this.listener.onTerminateRequest(aDeviceInfo,
|
||||
aPresentationId,
|
||||
aControlChannel,
|
||||
aIsFromReceiver);
|
||||
this.releaseControlChannel(aControlChannel);
|
||||
},
|
||||
|
||||
// nsIServerSocketListener (Triggered by nsIServerSocket.init)
|
||||
onSocketAccepted: function(aServerSocket, aClientSocket) {
|
||||
DEBUG && log("PresentationControlService - onSocketAccepted: " +
|
||||
|
@ -390,6 +410,16 @@ TCPControlChannel.prototype = {
|
|||
this._stateMachine.launch(aPresentationId, aUrl);
|
||||
},
|
||||
|
||||
terminate: function(aPresentationId) {
|
||||
if (!this._terminatingId) {
|
||||
this._terminatingId = aPresentationId;
|
||||
this._stateMachine.terminate(aPresentationId);
|
||||
} else {
|
||||
this._stateMachine.terminateAck(aPresentationId);
|
||||
delete this._terminatingId;
|
||||
}
|
||||
},
|
||||
|
||||
// may throw an exception
|
||||
_send: function(aMsg) {
|
||||
DEBUG && log("TCPControlChannel - Send: " + JSON.stringify(aMsg, null, 2)); // jshint ignore:line
|
||||
|
@ -650,6 +680,26 @@ TCPControlChannel.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
notifyTerminate: function(presentationId) {
|
||||
if (!this._terminatingId) {
|
||||
this._terminatingId = presentationId;
|
||||
this._presentationService.onSessionTerminate(this._deviceInfo,
|
||||
presentationId,
|
||||
this,
|
||||
this._direction === "sender");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._terminatingId !== presentationId) {
|
||||
// Requested presentation Id doesn't matched with the one in ACK.
|
||||
// Disconnect the control channel with error.
|
||||
DEBUG && log("TCPControlChannel - unmatched terminatingId: " + presentationId); // jshint ignore:line
|
||||
this.disconnect(Cr.NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
delete this._terminatingId;
|
||||
},
|
||||
|
||||
notifyOffer: function(offer) {
|
||||
this._onOffer(offer);
|
||||
},
|
||||
|
|
|
@ -58,6 +58,12 @@ var handlers = [
|
|||
presentationId: command.presentationId
|
||||
});
|
||||
break;
|
||||
case CommandType.TERMINATE:
|
||||
stateMachine._notifyTerminate(command.presentationId);
|
||||
break;
|
||||
case CommandType.TERMINATE_ACK:
|
||||
stateMachine._notifyTerminate(command.presentationId);
|
||||
break;
|
||||
case CommandType.OFFER:
|
||||
case CommandType.ICE_CANDIDATE:
|
||||
stateMachine._notifyChannelDescriptor(command);
|
||||
|
@ -89,6 +95,24 @@ ReceiverStateMachine.prototype = {
|
|||
debug("receiver shouldn't trigger launch");
|
||||
},
|
||||
|
||||
terminate: function _terminate(presentationId) {
|
||||
if (this.state === State.CONNECTED) {
|
||||
this._sendCommand({
|
||||
type: CommandType.TERMINATE,
|
||||
presentationId: presentationId,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
terminateAck: function _terminateAck(presentationId) {
|
||||
if (this.state === State.CONNECTED) {
|
||||
this._sendCommand({
|
||||
type: CommandType.TERMINATE_ACK,
|
||||
presentationId: presentationId,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
sendOffer: function _sendOffer() {
|
||||
// offer can only be sent by controlling UA.
|
||||
debug("receiver shouldn't generate offer");
|
||||
|
@ -171,6 +195,10 @@ ReceiverStateMachine.prototype = {
|
|||
this._channel.notifyLaunch(presentationId, url);
|
||||
},
|
||||
|
||||
_notifyTerminate: function _notifyTerminate(presentationId) {
|
||||
this._channel.notifyTerminate(presentationId);
|
||||
},
|
||||
|
||||
_notifyChannelDescriptor: function _notifyChannelDescriptor(command) {
|
||||
switch (command.type) {
|
||||
case CommandType.OFFER:
|
||||
|
|
|
@ -25,6 +25,8 @@ const CommandType = Object.freeze({
|
|||
// presentation session life cycle
|
||||
LAUNCH: "launch", // { presentationId: <string>, url: <string> }
|
||||
LAUNCH_ACK: "launch-ack", // { presentationId: <string> }
|
||||
TERMINATE: "terminate", // { presentationId: <string> }
|
||||
TERMINATE_ACK: "terminate-ack", // { presentationId: <string> }
|
||||
// session transport establishment
|
||||
OFFER: "offer", // { offer: <json> }
|
||||
ANSWER: "answer", // { answer: <json> }
|
||||
|
|
|
@ -23,6 +23,7 @@ TestPresentationControlChannel.prototype = {
|
|||
sendAnswer: function(answer) {},
|
||||
disconnect: function() {},
|
||||
launch: function() {},
|
||||
terminate: function() {},
|
||||
set listener(listener) {},
|
||||
get listener() {},
|
||||
};
|
||||
|
@ -139,6 +140,27 @@ function sessionRequest() {
|
|||
.onSessionRequest(testDevice, testUrl, testPresentationId, testControlChannel);
|
||||
}
|
||||
|
||||
function terminateRequest() {
|
||||
let testUrl = 'http://www.example.org/';
|
||||
let testPresentationId = 'test-presentation-id';
|
||||
let testControlChannel = new TestPresentationControlChannel();
|
||||
let testIsFromReceiver = true;
|
||||
Services.obs.addObserver(function observer(subject, topic, data) {
|
||||
Services.obs.removeObserver(observer, topic);
|
||||
|
||||
let request = subject.QueryInterface(Ci.nsIPresentationTerminateRequest);
|
||||
|
||||
Assert.equal(request.device.id, testDevice.id, 'expected device');
|
||||
Assert.equal(request.presentationId, testPresentationId, 'expected presentation Id');
|
||||
Assert.equal(request.isFromReceiver, testIsFromReceiver, 'expected isFromReceiver');
|
||||
|
||||
run_next_test();
|
||||
}, 'presentation-terminate-request', false);
|
||||
manager.QueryInterface(Ci.nsIPresentationDeviceListener)
|
||||
.onTerminateRequest(testDevice, testPresentationId,
|
||||
testControlChannel, testIsFromReceiver);
|
||||
}
|
||||
|
||||
function removeDevice() {
|
||||
Services.obs.addObserver(function observer(subject, topic, data) {
|
||||
Services.obs.removeObserver(observer, topic);
|
||||
|
@ -176,6 +198,7 @@ add_test(forceDiscovery);
|
|||
add_test(addDevice);
|
||||
add_test(updateDevice);
|
||||
add_test(sessionRequest);
|
||||
add_test(terminateRequest);
|
||||
add_test(removeDevice);
|
||||
add_test(removeProvider);
|
||||
|
||||
|
|
|
@ -78,6 +78,45 @@ function launch() {
|
|||
};
|
||||
}
|
||||
|
||||
function terminateByController() {
|
||||
Assert.equal(controllerState.state, State.CONNECTED, 'controller in connected state');
|
||||
Assert.equal(receiverState.state, State.CONNECTED, 'receiver in connected state');
|
||||
|
||||
controllerState.terminate(testPresentationId);
|
||||
mockReceiverChannel.notifyTerminate = function(presentationId) {
|
||||
Assert.equal(receiverState.state, State.CONNECTED, 'receiver in connected state');
|
||||
Assert.equal(presentationId, testPresentationId, 'expected presentationId received');
|
||||
|
||||
mockControllerChannel.notifyTerminate = function(presentationId) {
|
||||
Assert.equal(controllerState.state, State.CONNECTED, 'controller in connected state');
|
||||
Assert.equal(presentationId, testPresentationId, 'expected presentationId received from ack');
|
||||
|
||||
run_next_test();
|
||||
};
|
||||
|
||||
receiverState.terminateAck(presentationId);
|
||||
};
|
||||
}
|
||||
|
||||
function terminateByReceiver() {
|
||||
Assert.equal(controllerState.state, State.CONNECTED, 'controller in connected state');
|
||||
Assert.equal(receiverState.state, State.CONNECTED, 'receiver in connected state');
|
||||
|
||||
receiverState.terminate(testPresentationId);
|
||||
mockControllerChannel.notifyTerminate = function(presentationId) {
|
||||
Assert.equal(controllerState.state, State.CONNECTED, 'controller in connected state');
|
||||
Assert.equal(presentationId, testPresentationId, 'expected presentationId received');
|
||||
|
||||
mockReceiverChannel.notifyTerminate = function(presentationId) {
|
||||
Assert.equal(receiverState.state, State.CONNECTED, 'receiver in connected state');
|
||||
Assert.equal(presentationId, testPresentationId, 'expected presentationId received from ack');
|
||||
run_next_test();
|
||||
};
|
||||
|
||||
controllerState.terminateAck(presentationId);
|
||||
};
|
||||
}
|
||||
|
||||
function exchangeSDP() {
|
||||
Assert.equal(controllerState.state, State.CONNECTED, 'controller in connected state');
|
||||
Assert.equal(receiverState.state, State.CONNECTED, 'receiver in connected state');
|
||||
|
@ -185,6 +224,8 @@ function abnormalDisconnect() {
|
|||
|
||||
add_test(connect);
|
||||
add_test(launch);
|
||||
add_test(terminateByController);
|
||||
add_test(terminateByReceiver);
|
||||
add_test(exchangeSDP);
|
||||
add_test(disconnect);
|
||||
add_test(receiverDisconnect);
|
||||
|
|
|
@ -181,6 +181,175 @@ function testPresentationServer() {
|
|||
};
|
||||
}
|
||||
|
||||
function terminateRequest() {
|
||||
let yayFuncs = makeJointSuccess(['controllerControlChannelConnected',
|
||||
'controllerControlChannelDisconnected',
|
||||
'presenterControlChannelDisconnected']);
|
||||
let controllerControlChannel;
|
||||
|
||||
pcs.listener = {
|
||||
onTerminateRequest: function(deviceInfo, presentationId, controlChannel, isFromReceiverj) {
|
||||
controllerControlChannel = controlChannel;
|
||||
Assert.equal(deviceInfo.id, pcs.id, 'expected device id');
|
||||
Assert.equal(deviceInfo.address, '127.0.0.1', 'expected device address');
|
||||
Assert.equal(presentationId, 'testPresentationId', 'expected presentation id');
|
||||
Assert.equal(isFromReceiver, false, 'expected request from controller');
|
||||
|
||||
controllerControlChannel.listener = {
|
||||
notifyConnected: function() {
|
||||
Assert.ok(true, 'control channel notify connected');
|
||||
yayFuncs.controllerControlChannelConnected();
|
||||
},
|
||||
notifyDisconnected: function(aReason) {
|
||||
Assert.equal(aReason, CLOSE_CONTROL_CHANNEL_REASON, 'controllerControlChannel notify disconncted');
|
||||
yayFuncs.controllerControlChannelDisconnected();
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationControlChannelListener]),
|
||||
};
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITCPPresentationServerListener]),
|
||||
};
|
||||
|
||||
let presenterDeviceInfo = {
|
||||
id: 'presentatorID',
|
||||
address: '127.0.0.1',
|
||||
port: PRESENTER_CONTROL_CHANNEL_PORT,
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITCPDeviceInfo]),
|
||||
};
|
||||
|
||||
let presenterControlChannel = pcs.connect(presenterDeviceInfo);
|
||||
|
||||
presenterControlChannel.listener = {
|
||||
notifyConnected: function() {
|
||||
presenterControlChannel.terminate('testPresentationId', 'http://example.com');
|
||||
presenterControlChannel.disconnect(CLOSE_CONTROL_CHANNEL_REASON);
|
||||
},
|
||||
notifyDisconnected: function(aReason) {
|
||||
Assert.equal(aReason, CLOSE_CONTROL_CHANNEL_REASON, '4. presenterControlChannel notify disconnected');
|
||||
yayFuncs.presenterControlChannelDisconnected();
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationControlChannelListener]),
|
||||
};
|
||||
}
|
||||
|
||||
function terminateRequest() {
|
||||
let yayFuncs = makeJointSuccess(['controllerControlChannelConnected',
|
||||
'controllerControlChannelDisconnected',
|
||||
'presenterControlChannelDisconnected',
|
||||
'terminatedByController',
|
||||
'terminatedByReceiver']);
|
||||
let controllerControlChannel;
|
||||
let terminatePhase = 'controller';
|
||||
|
||||
pcs.listener = {
|
||||
onTerminateRequest: function(deviceInfo, presentationId, controlChannel, isFromReceiver) {
|
||||
Assert.equal(deviceInfo.address, '127.0.0.1', 'expected device address');
|
||||
Assert.equal(presentationId, 'testPresentationId', 'expected presentation id');
|
||||
controlChannel.terminate(presentationId); // Reply terminate ack.
|
||||
|
||||
if (terminatePhase === 'controller') {
|
||||
controllerControlChannel = controlChannel;
|
||||
Assert.equal(deviceInfo.id, pcs.id, 'expected controller device id');
|
||||
Assert.equal(isFromReceiver, false, 'expected request from controller');
|
||||
yayFuncs.terminatedByController();
|
||||
|
||||
controllerControlChannel.listener = {
|
||||
notifyConnected: function() {
|
||||
Assert.ok(true, 'control channel notify connected');
|
||||
yayFuncs.controllerControlChannelConnected();
|
||||
|
||||
terminatePhase = 'receiver';
|
||||
controllerControlChannel.terminate('testPresentationId');
|
||||
},
|
||||
notifyDisconnected: function(aReason) {
|
||||
Assert.equal(aReason, CLOSE_CONTROL_CHANNEL_REASON, 'controllerControlChannel notify disconncted');
|
||||
yayFuncs.controllerControlChannelDisconnected();
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationControlChannelListener]),
|
||||
};
|
||||
} else {
|
||||
Assert.equal(deviceInfo.id, presenterDeviceInfo.id, 'expected presenter device id');
|
||||
Assert.equal(isFromReceiver, true, 'expected request from receiver');
|
||||
yayFuncs.terminatedByReceiver();
|
||||
presenterControlChannel.disconnect(CLOSE_CONTROL_CHANNEL_REASON);
|
||||
}
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITCPPresentationServerListener]),
|
||||
};
|
||||
|
||||
let presenterDeviceInfo = {
|
||||
id: 'presentatorID',
|
||||
address: '127.0.0.1',
|
||||
port: PRESENTER_CONTROL_CHANNEL_PORT,
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITCPDeviceInfo]),
|
||||
};
|
||||
|
||||
let presenterControlChannel = pcs.connect(presenterDeviceInfo);
|
||||
|
||||
presenterControlChannel.listener = {
|
||||
notifyConnected: function() {
|
||||
presenterControlChannel.terminate('testPresentationId');
|
||||
},
|
||||
notifyDisconnected: function(aReason) {
|
||||
Assert.equal(aReason, CLOSE_CONTROL_CHANNEL_REASON, '4. presenterControlChannel notify disconnected');
|
||||
yayFuncs.presenterControlChannelDisconnected();
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationControlChannelListener]),
|
||||
};
|
||||
}
|
||||
|
||||
function terminateRequestAbnormal() {
|
||||
let yayFuncs = makeJointSuccess(['controllerControlChannelConnected',
|
||||
'controllerControlChannelDisconnected',
|
||||
'presenterControlChannelDisconnected']);
|
||||
let controllerControlChannel;
|
||||
|
||||
pcs.listener = {
|
||||
onTerminateRequest: function(deviceInfo, presentationId, controlChannel, isFromReceiver) {
|
||||
Assert.equal(deviceInfo.id, pcs.id, 'expected controller device id');
|
||||
Assert.equal(deviceInfo.address, '127.0.0.1', 'expected device address');
|
||||
Assert.equal(presentationId, 'testPresentationId', 'expected presentation id');
|
||||
Assert.equal(isFromReceiver, false, 'expected request from controller');
|
||||
controlChannel.terminate('unmatched-presentationId'); // Reply abnormal terminate ack.
|
||||
|
||||
controllerControlChannel = controlChannel;
|
||||
|
||||
controllerControlChannel.listener = {
|
||||
notifyConnected: function() {
|
||||
Assert.ok(true, 'control channel notify connected');
|
||||
yayFuncs.controllerControlChannelConnected();
|
||||
},
|
||||
notifyDisconnected: function(aReason) {
|
||||
Assert.equal(aReason, Cr.NS_ERROR_FAILURE, 'controllerControlChannel notify disconncted with error');
|
||||
yayFuncs.controllerControlChannelDisconnected();
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationControlChannelListener]),
|
||||
};
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITCPPresentationServerListener]),
|
||||
};
|
||||
|
||||
let presenterDeviceInfo = {
|
||||
id: 'presentatorID',
|
||||
address: '127.0.0.1',
|
||||
port: PRESENTER_CONTROL_CHANNEL_PORT,
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITCPDeviceInfo]),
|
||||
};
|
||||
|
||||
let presenterControlChannel = pcs.connect(presenterDeviceInfo);
|
||||
|
||||
presenterControlChannel.listener = {
|
||||
notifyConnected: function() {
|
||||
presenterControlChannel.terminate('testPresentationId');
|
||||
},
|
||||
notifyDisconnected: function(aReason) {
|
||||
Assert.equal(aReason, Cr.NS_ERROR_FAILURE, '4. presenterControlChannel notify disconnected with error');
|
||||
yayFuncs.presenterControlChannelDisconnected();
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationControlChannelListener]),
|
||||
};
|
||||
}
|
||||
|
||||
function setOffline() {
|
||||
pcs.listener = {
|
||||
onPortChange: function(aPort) {
|
||||
|
@ -225,6 +394,8 @@ function changeCloseReason() {
|
|||
}
|
||||
|
||||
add_test(loopOfferAnser);
|
||||
add_test(terminateRequest);
|
||||
add_test(terminateRequestAbnormal);
|
||||
add_test(setOffline);
|
||||
add_test(changeCloseReason);
|
||||
add_test(oneMoreLoop);
|
||||
|
|
Загрузка…
Ссылка в новой задаче