Fix participant type change with external signaling server

The external signaling server expects to receive a "participants"
message from the backend notifier when the participants in a room
change. This message is in turn sent as a participants update signaling
message to the clients, and the WebUI updates the list of participants
whenever that message is received.

However, when the type of a participant changes the backend notifier
sent an "update" message instead, which is in turn sent as a room list
update signaling message to the clients, but it does not trigger any
update in the participants list of the WebUI.

Now a "participants" message is sent too by the backend notifier when
the participants in a room change, so the WebUI updates the list of
participants when handling the participants update signaling message;
the WebUI could have been modified to rely on the room list update
signaling message instead, but using the other message seemed more
appropriate.

Note that the already existing "update" message sent by the backend
notifier is kept for now, as removing it may break the clients in
unexpected ways (although it should go away in the future).

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
This commit is contained in:
Daniel Calviño Sánchez 2020-03-04 18:06:33 +01:00
Родитель 5974d13bc3
Коммит 174bffd845
2 изменённых файлов: 139 добавлений и 0 удалений

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

@ -137,7 +137,27 @@ class Listener {
$dispatcher->addListener(Room::EVENT_AFTER_TYPE_SET, $listener);
$dispatcher->addListener(Room::EVENT_AFTER_READONLY_SET, $listener);
$dispatcher->addListener(Room::EVENT_AFTER_LOBBY_STATE_SET, $listener);
// TODO remove handler with "roomModified" in favour of handler with
// "participantsModified" once the clients no longer expect a
// "roomModified" message for participant type changes.
$dispatcher->addListener(Room::EVENT_AFTER_PARTICIPANT_TYPE_SET, $listener);
$dispatcher->addListener(Room::EVENT_AFTER_PARTICIPANT_TYPE_SET, static function(ModifyParticipantEvent $event) {
if (self::isUsingInternalSignaling()) {
return;
}
/** @var BackendNotifier $notifier */
$notifier = \OC::$server->query(BackendNotifier::class);
$sessionIds = [];
// If the participant is not active in the room the "participants"
// request will be sent anyway, although with an empty "changed"
// property.
if ($event->getParticipant()->getSessionId()) {
$sessionIds[] = $event->getParticipant()->getSessionId();
}
$notifier->participantsModified($event->getRoom(), $sessionIds);
});
$dispatcher->addListener(Room::EVENT_BEFORE_ROOM_DELETE, static function(RoomEvent $event) {
if (self::isUsingInternalSignaling()) {
return;

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

@ -543,4 +543,123 @@ class BackendNotifierTest extends \Test\TestCase {
], $bodies);
}
public function testParticipantsTypeChanged() {
$room = $this->manager->createPublicRoom();
$userSession = 'user-session';
$room->addUsers([
'userId' => $this->userId,
'sessionId' => $userSession,
]);
$participant = $room->getParticipantBySession($userSession);
$room->setParticipantType($participant, Participant::MODERATOR);
$requests = $this->controller->getRequests();
$bodies = array_map(function($request) use ($room) {
return json_decode($this->validateBackendRequest($this->baseUrl . '/api/v1/room/' . $room->getToken(), $request), true);
}, $requests);
$this->assertContains([
'type' => 'participants',
'participants' => [
'changed' => [
[
'inCall' => 0,
'lastPing' => 0,
'sessionId' => $userSession,
'participantType' => Participant::MODERATOR,
'userId' => $this->userId,
],
],
'users' => [
[
'inCall' => 0,
'lastPing' => 0,
'sessionId' => $userSession,
'participantType' => Participant::MODERATOR,
'userId' => $this->userId,
],
],
],
], $bodies);
$this->controller->clearRequests();
$guestSession = $room->joinRoomGuest('');
$guestParticipant = $room->getParticipantBySession($guestSession);
$room->setParticipantType($guestParticipant, Participant::GUEST_MODERATOR);
$requests = $this->controller->getRequests();
$bodies = array_map(function($request) use ($room) {
return json_decode($this->validateBackendRequest($this->baseUrl . '/api/v1/room/' . $room->getToken(), $request), true);
}, $requests);
$this->assertContains([
'type' => 'participants',
'participants' => [
'changed' => [
[
'inCall' => 0,
'lastPing' => 0,
'sessionId' => $guestSession,
'participantType' => Participant::GUEST_MODERATOR,
],
],
'users' => [
[
'inCall' => 0,
'lastPing' => 0,
'sessionId' => $userSession,
'participantType' => Participant::MODERATOR,
'userId' => $this->userId,
],
[
'inCall' => 0,
'lastPing' => 0,
'sessionId' => $guestSession,
'participantType' => Participant::GUEST_MODERATOR,
],
],
],
], $bodies);
$this->controller->clearRequests();
$notJoinedUserId = 'not-joined-user-id';
$room->addUsers([
'userId' => $notJoinedUserId,
]);
$participant = $room->getParticipant($notJoinedUserId);
$room->setParticipantType($participant, Participant::MODERATOR);
$requests = $this->controller->getRequests();
$bodies = array_map(function($request) use ($room) {
return json_decode($this->validateBackendRequest($this->baseUrl . '/api/v1/room/' . $room->getToken(), $request), true);
}, $requests);
$this->assertContains([
'type' => 'participants',
'participants' => [
'changed' => [
],
'users' => [
[
'inCall' => 0,
'lastPing' => 0,
'sessionId' => $userSession,
'participantType' => Participant::MODERATOR,
'userId' => $this->userId,
],
[
'inCall' => 0,
'lastPing' => 0,
'sessionId' => 0,
'participantType' => Participant::MODERATOR,
'userId' => $notJoinedUserId,
],
[
'inCall' => 0,
'lastPing' => 0,
'sessionId' => $guestSession,
'participantType' => Participant::GUEST_MODERATOR,
],
],
],
], $bodies);
}
}