Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error messages #36

Merged
merged 2 commits into from
Apr 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion static/js/getUserMediaPolyfill.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,33 @@
};
} else {
navigator.mediaDevices.getUserMedia = function() {
// A missing `getUserMedia` seemingly can mean one of two things:
//
// 1) WebRTC is unsupported or disabled on this browser
// 2) This is an insecure connection
// * This handling of insecure connections happens only on certain browsers.
// It was observed in Chromium 80 and Firefox 75, but not Firefox 68. I suspect it's the new behavior.
// * In other browsers, it handles insecure connections by throwing `NotAllowedError`.
// We still handle this case in the calling function.
// * See: https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia
// As of this writing, this claims that the browser does *both* of these things for
// insecure connections, which is of course impossible and thus confusing.
//
// We will attempt to distinguish these two cases by checking for various webrtc-related fields on
// `window` (inspired by github.com/muaz-khan/DetectRTC). If none of those fields exist, we assume
// that WebRTC is not supported on this browser.
return new Promise(function(resolve, reject) {
reject("getUserMedia is not supported in this browser.");
if (!(window.RTCPeerConnection || window.webkitRTCPeerConnection || window.mozRTCPeerConnection || window.RTCIceGatherer)) {
var e = new Error("getUserMedia is not supported in this browser.");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this text was ever getting seen. In fact, I think that we were returning this for SSL errors and accidentally correctly reporting them to the user as such.

// I'd use NotSupportedError but I'm afraid they'll change the spec on us again
e.name = 'CustomNotSupportedError';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Best option I could think of at the time, but I'm open to other things. Perhaps just a better name.

reject(e);
} else {
var e = new Error("insecure connection");
// I'd use NotAllowedError but I'm afraid they'll change the spec on us again
e.name = 'CustomSecureConnectionError';
reject(e);
}
});
};
}
Expand Down
98 changes: 57 additions & 41 deletions static/js/webrtc.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks");

var rtc = (function() {
var isActive = false;
var isSupported = true;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a TODO to remove it (see below) and it's always set to true.

var pc_config = {};
var pc_constraints = {
optional: [
Expand Down Expand Up @@ -101,12 +100,48 @@ var rtc = (function() {
show: function() {
$("#rtcbox").css('display', 'flex');
},
showNotSupported: function() {
showUserMediaError: function(err) { // show an error returned from getUserMedia
var reason
// For reference on standard errors returned by getUserMedia:
// https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia
// However keep in mind that we add our own errors in getUserMediaPolyfill
switch(err.name) {
case "CustomNotSupportedError":
reason = "Sorry, your browser does not support WebRTC. (or you have it disabled in your settings).<br><br>" +
"To participate in this audio/video chat you have to user a browser with WebRTC support like Chrome, Firefox or Opera." +
'<a href="http://www.webrtc.org/" target="_new">Find out more</a>'
break;
case "CustomSecureConnectionError":
reason = "Sorry, you need to install SSL certificates for your Etherpad instance to use WebRTC"
break;
case "NotAllowedError":
// For certain (I suspect older) browsers, `NotAllowedError` indicates either an insecure connection or the user rejecting camera permissions.
// The error for both cases appears to be identical, so our best guess at telling them apart is to guess whether we are in a secure context.
// (webrtc is considered secure for https connections or on localhost)
if (location.protocol === "https:" || location.hostname === "localhost" || location.hostname === "127.0.0.1") {
reason = "Sorry, you need to give us permission to use your camera and microphone"
} else {
reason = "Sorry, you need to install SSL certificates for your Etherpad instance to use WebRTC"
}
break;
case "NotFoundError":
reason = "Sorry, we couldnt't find a suitable camera on your device. If you have a camera, make sure it set up correctly and refresh this website to retry."
break;
case "NotReadableError":
// `err.message` might give useful info to the user (not necessarily useful for other error messages)
reason = "Sorry, a hardware error occurred that prevented access to your camera and/or microphone:<br><br>" + err.message
break;
case "AbortError":
// `err.message` might give useful info to the user (not necessarily useful for other error messages)
reason = "Sorry, an error occurred (probably not hardware related) that prevented access to your camera and/or microphone:<br><br>" + err.message
break;
default:
// `err` as a string might give useful info to the user (not necessarily useful for other error messages)
reason = "Sorry, there was an unknown Error:<br><br>" + err
}
$.gritter.add({
title: "Error",
text: "Sorry, your browser does not support WebRTC.<br><br>" +
"To participate in this audio/video chat you have to user a browser with WebRTC support like Chrome, Firefox or Opera." +
'<a href="http://www.webrtc.org/" target="_new">Find out more</a>',
text: reason,
sticky: true,
class_name: "error"
})
Expand All @@ -119,35 +154,29 @@ var rtc = (function() {
$("#options-enablertc").prop("checked", true);
if (isActive) return;
self.show();
if (isSupported) {
padcookie.setPref("rtcEnabled", true);
self.getUserMedia();
} else {
self.showNotSupported();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless isSupported is getting set somewhere outside of this module, this function wasn't getting called.

}
padcookie.setPref("rtcEnabled", true);
self.getUserMedia();
isActive = true;
},
deactivate: function() {
$("#options-enablertc").prop("checked", false);
if (!isActive) return;
self.hide();
if (isSupported) {
padcookie.setPref("rtcEnabled", false);
self.hangupAll();
if (localStream) {
var videoTrack = localStream.getVideoTracks()[0];
var audioTrack = localStream.getAudioTracks()[0];
self.setStream(self._pad.getUserId(), "");
if (videoTrack.stop === undefined) {
// deprecated in 2015, probably disabled by 2020
// https://developers.google.com/web/updates/2015/07/mediastream-deprecations
localStream.stop();
} else {
videoTrack.stop();
audioTrack.stop();
}
localStream = null;
padcookie.setPref("rtcEnabled", false);
self.hangupAll();
if (localStream) {
var videoTrack = localStream.getVideoTracks()[0];
var audioTrack = localStream.getAudioTracks()[0];
self.setStream(self._pad.getUserId(), "");
if (videoTrack.stop === undefined) {
// deprecated in 2015, probably disabled by 2020
// https://developers.google.com/web/updates/2015/07/mediastream-deprecations
localStream.stop();
} else {
videoTrack.stop();
audioTrack.stop();
}
localStream = null;
}
isActive = false;
},
Expand Down Expand Up @@ -478,18 +507,7 @@ var rtc = (function() {
}
});
})
.catch(function(err) {
var reason = "Sorry, we couldnt't find a suitable camera on your device. If you have a camera, make sure it set up correctly and refresh this website to retry.";
if(err.name !== "NotFoundError") reason = "Sorry, you need to install SSL certificates for your Etherpad instance to use WebRTC";

$.gritter.add({
title: "Error",
text: reason,
sticky: true,
class_name: "error"
})
self.hide();
});
.catch(function(err) {self.showUserMediaError(err)})
},
avInURL: function() {
if (window.location.search.indexOf("av=YES") > -1) {
Expand Down Expand Up @@ -551,8 +569,6 @@ var rtc = (function() {
};
var webrtcDetectedBrowser = "chrome";

isSupported = true; // TODO: remove me

// Set Opus as the default audio codec if it's present.
function preferOpus(sdp) {
var sdpLines = sdp.split("\r\n");
Expand Down