1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-11-25 05:23:13 +03:00

webrtc/call: Fall back to recvonly if camera/mic access is denied

Users of MatrixCall will need to present some sensible UX for this.
This commit is contained in:
Robert Swain
2017-04-05 15:24:54 +02:00
parent 2c15bdae04
commit b33dcfe6ff

View File

@@ -409,12 +409,12 @@ MatrixCall.prototype.answer = function() {
if (!this.localAVStream && !this.waitForLocalAVStream) {
this.webRtc.getUserMedia(
_getUserMediaVideoContraints(this.type),
hookCallback(self, self._gotUserMediaForAnswer),
hookCallback(self, self._getUserMediaFailed),
hookCallback(self, self._maybeGotUserMediaForAnswer),
hookCallback(self, self._maybeGotUserMediaForAnswer),
);
setState(this, 'wait_local_media');
} else if (this.localAVStream) {
this._gotUserMediaForAnswer(this.localAVStream);
this._maybeGotUserMediaForAnswer(this.localAVStream);
} else if (this.waitForLocalAVStream) {
setState(this, 'wait_local_media');
}
@@ -433,11 +433,11 @@ MatrixCall.prototype._replacedBy = function(newCall) {
newCall.waitForLocalAVStream = true;
} else if (this.state == 'create_offer') {
debuglog("Handing local stream to new call");
newCall._gotUserMediaForAnswer(this.localAVStream);
newCall._maybeGotUserMediaForAnswer(this.localAVStream);
delete(this.localAVStream);
} else if (this.state == 'invite_sent') {
debuglog("Handing local stream to new call");
newCall._gotUserMediaForAnswer(this.localAVStream);
newCall._maybeGotUserMediaForAnswer(this.localAVStream);
delete(this.localAVStream);
}
newCall.localVideoElement = this.localVideoElement;
@@ -523,22 +523,27 @@ MatrixCall.prototype.isMicrophoneMuted = function() {
* @private
* @param {Object} stream
*/
MatrixCall.prototype._gotUserMediaForInvite = function(stream) {
MatrixCall.prototype._maybeGotUserMediaForInvite = function(stream) {
if (this.successor) {
this.successor._gotUserMediaForAnswer(stream);
this.successor._maybeGotUserMediaForAnswer(stream);
return;
}
if (this.state == 'ended') {
return;
}
debuglog("_gotUserMediaForInvite -> " + this.type);
debuglog("_maybeGotUserMediaForInvite -> " + this.type);
const self = this;
const error = stream;
let constraints = null;
if (stream instanceof MediaStream) {
const videoEl = this.getLocalVideoElement();
if (videoEl && this.type == 'video') {
videoEl.autoplay = true;
if (this.screenSharingStream) {
debuglog("Setting screen sharing stream to the local video element");
debuglog("Setting screen sharing stream to the local video" +
" element");
this.assignElement(videoEl, this.screenSharingStream, "localVideo");
} else {
this.assignElement(videoEl, stream, "localVideo");
@@ -562,9 +567,26 @@ MatrixCall.prototype._gotUserMediaForInvite = function(stream) {
setTracksEnabled(stream.getAudioTracks(), true);
this.peerConn = _createPeerConnection(this);
this.peerConn.addStream(stream);
} else if (error.name === 'PermissionDeniedError') {
debuglog('User denied access to camera/microphone.' +
' Or possibly you are using an insecure domain. Receiving only.');
constraints = {
'mandatory': {
'OfferToReceiveAudio': true,
'OfferToReceiveVideo': self.type == 'video',
},
};
this.peerConn = _createPeerConnection(this);
} else {
debuglog('Failed to getUserMedia.');
this._getUserMediaFailed(error);
return;
}
this.peerConn.createOffer(
hookCallback(self, self._gotLocalOffer),
hookCallback(self, self._getLocalOfferFailed),
constraints,
);
setState(self, 'create_offer');
};
@@ -574,11 +596,14 @@ MatrixCall.prototype._gotUserMediaForInvite = function(stream) {
* @private
* @param {Object} stream
*/
MatrixCall.prototype._gotUserMediaForAnswer = function(stream) {
MatrixCall.prototype._maybeGotUserMediaForAnswer = function(stream) {
const self = this;
if (self.state == 'ended') {
return;
}
const error = stream;
if (stream instanceof MediaStream) {
const localVidEl = self.getLocalVideoElement();
if (localVidEl && self.type == 'video') {
@@ -596,6 +621,14 @@ MatrixCall.prototype._gotUserMediaForAnswer = function(stream) {
self.localAVStream = stream;
setTracksEnabled(stream.getAudioTracks(), true);
self.peerConn.addStream(stream);
} else if (error.name === 'PermissionDeniedError') {
debuglog('User denied access to camera/microphone.' +
' Or possibly you are using an insecure domain. Receiving only.');
} else {
debuglog('Failed to getUserMedia.');
this._getUserMediaFailed(error);
return;
}
const constraints = {
'mandatory': {
@@ -1126,8 +1159,8 @@ const _placeCallWithConstraints = function(self, constraints) {
self.client.callList[self.callId] = self;
self.webRtc.getUserMedia(
constraints,
hookCallback(self, self._gotUserMediaForInvite),
hookCallback(self, self._getUserMediaFailed),
hookCallback(self, self._maybeGotUserMediaForInvite),
hookCallback(self, self._maybeGotUserMediaForInvite),
);
setState(self, 'wait_local_media');
self.direction = 'outbound';