From 63919befd0aad8772507765a382feb7f6a6e9e27 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 15 Nov 2017 10:49:29 +0000 Subject: [PATCH] Catch call failures due to unknown devices And show a specific dialog that you can then launch the UDD from (although currently with a 'Send Anyway' button which makes little sense for VoIP) --- src/CallHandler.js | 27 ++++++++++++++- src/components/structures/RoomStatusBar.js | 30 +++-------------- src/cryptodevices.js | 39 ++++++++++++++++++++++ src/i18n/strings/en_EN.json | 5 ++- 4 files changed, 73 insertions(+), 28 deletions(-) create mode 100644 src/cryptodevices.js diff --git a/src/CallHandler.js b/src/CallHandler.js index e2241a4955..66a84bafa7 100644 --- a/src/CallHandler.js +++ b/src/CallHandler.js @@ -59,6 +59,7 @@ import sdk from './index'; import { _t } from './languageHandler'; import Matrix from 'matrix-js-sdk'; import dis from './dispatcher'; +import { getUnknownDevicesForRoom } from './cryptodevices'; global.mxCalls = { //room_id: MatrixCall @@ -104,6 +105,31 @@ function _setCallListeners(call) { console.error(err.stack); call.hangup(); _setCallState(undefined, call.roomId, "ended"); + if (err.code === 'unknown_devices') { + const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); + + Modal.createTrackedDialog('Call Failed', '', QuestionDialog, { + title: _t('Call Failed'), + description: _t( + "There are unknown devices in this room: "+ + "if you proceed without verifying them, it will be "+ + "possible for someone to eavesdrop on your call" + ), + button: _t('Review Devices'), + onFinished: function(confirmed) { + if (confirmed) { + const room = MatrixClientPeg.get().getRoom(call.roomId); + getUnknownDevicesForRoom(MatrixClientPeg.get(), room).then((unknownDevices) => { + const UnknownDeviceDialog = sdk.getComponent('dialogs.UnknownDeviceDialog'); + Modal.createTrackedDialog('Unknown Device Dialog', '', UnknownDeviceDialog, { + room: room, + devices: unknownDevices, + }, 'mx_Dialog_unknownDevice'); + }); + } + }, + }); + } }); call.on("hangup", function() { _setCallState(undefined, call.roomId, "ended"); @@ -171,7 +197,6 @@ function _setCallState(call, roomId, status) { function _onAction(payload) { function placeCall(newCall) { _setCallListeners(newCall); - _setCallState(newCall, newCall.roomId, "ringback"); if (payload.type === 'voice') { newCall.placeVoiceCall(); } else if (payload.type === 'video') { diff --git a/src/components/structures/RoomStatusBar.js b/src/components/structures/RoomStatusBar.js index 30f6f3ee2a..4c45fd09a4 100644 --- a/src/components/structures/RoomStatusBar.js +++ b/src/components/structures/RoomStatusBar.js @@ -24,6 +24,7 @@ import MatrixClientPeg from '../../MatrixClientPeg'; import MemberAvatar from '../views/avatars/MemberAvatar'; import Resend from '../../Resend'; import Modal from '../../Modal'; +import { getUnknownDevicesForRoom } from '../../cryptodevices'; const HIDE_DEBOUNCE_MS = 10000; const STATUS_BAR_HIDDEN = 0; @@ -157,7 +158,9 @@ module.exports = React.createClass({ }, _onShowDevicesClick: function() { - this._getUnknownDevices().then((unknownDevices) => { + getUnknownDevicesForRoom(MatrixClientPeg.get(), this.props.room).then((unknownDevices) => { + if (this._unmounted) return; + const UnknownDeviceDialog = sdk.getComponent('dialogs.UnknownDeviceDialog'); Modal.createTrackedDialog('Unknown Device Dialog', '', UnknownDeviceDialog, { room: this.props.room, @@ -166,31 +169,6 @@ module.exports = React.createClass({ }); }, - _getUnknownDevices: function() { - const roomMembers = this.props.room.getJoinedMembers().map((m) => { - return m.userId; - }); - return MatrixClientPeg.get().downloadKeys(roomMembers, false).then((devices) => { - if (this._unmounted) return; - - const unknownDevices = {}; - // This is all devices in this room, so find the unknown ones. - Object.keys(devices).forEach((userId) => { - Object.keys(devices[userId]).map((deviceId) => { - const device = devices[userId][deviceId]; - - if (device.isUnverified() && !device.isKnown()) { - if (unknownDevices[userId] === undefined) { - unknownDevices[userId] = {}; - } - unknownDevices[userId][deviceId] = device; - } - }); - }); - return unknownDevices; - }); - }, - onRoomLocalEchoUpdated: function(event, room, oldEventId, oldStatus) { if (room.roomId !== this.props.room.roomId) return; diff --git a/src/cryptodevices.js b/src/cryptodevices.js new file mode 100644 index 0000000000..d580e6f7f2 --- /dev/null +++ b/src/cryptodevices.js @@ -0,0 +1,39 @@ +/* +Copyright 2017 New Vector Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +export function getUnknownDevicesForRoom(matrixClient, room) { + const roomMembers = room.getJoinedMembers().map((m) => { + return m.userId; + }); + return matrixClient.downloadKeys(roomMembers, false).then((devices) => { + const unknownDevices = {}; + // This is all devices in this room, so find the unknown ones. + Object.keys(devices).forEach((userId) => { + Object.keys(devices[userId]).map((deviceId) => { + const device = devices[userId][deviceId]; + + if (device.isUnverified() && !device.isKnown()) { + if (unknownDevices[userId] === undefined) { + unknownDevices[userId] = {}; + } + unknownDevices[userId][deviceId] = device; + } + }); + }); + return unknownDevices; + }); +} + diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index b83600ffb6..28ac9281f4 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2,6 +2,9 @@ "This email address is already in use": "This email address is already in use", "This phone number is already in use": "This phone number is already in use", "Failed to verify email address: make sure you clicked the link in the email": "Failed to verify email address: make sure you clicked the link in the email", + "Call Failed": "Call Failed", + "There are unknown devices in this room: if you proceed without verifying them, it will be possible for someone to eavesdrop on your call": "There are unknown devices in this room: if you proceed without verifying them, it will be possible for someone to eavesdrop on your call", + "Review Devices": "Review Devices", "Call Timeout": "Call Timeout", "The remote side failed to pick up": "The remote side failed to pick up", "Unable to capture screen": "Unable to capture screen", @@ -150,7 +153,6 @@ "%(widgetName)s widget modified by %(senderName)s": "%(widgetName)s widget modified by %(senderName)s", "%(widgetName)s widget added by %(senderName)s": "%(widgetName)s widget added by %(senderName)s", "%(widgetName)s widget removed by %(senderName)s": "%(widgetName)s widget removed by %(senderName)s", - "Communities": "Communities", "Message Pinning": "Message Pinning", "%(displayName)s is typing": "%(displayName)s is typing", "%(names)s and %(count)s others are typing|other": "%(names)s and %(count)s others are typing", @@ -524,6 +526,7 @@ "Unverify": "Unverify", "Verify...": "Verify...", "No results": "No results", + "Communities": "Communities", "Home": "Home", "Integrations Error": "Integrations Error", "Could not connect to the integration server": "Could not connect to the integration server",