@daily-co/daily-js
Version:
**🚨Our docs have moved! 🚨**
282 lines (258 loc) • 8.26 kB
JavaScript
// This method should be used instead of window.navigator.userAgent, which
// is not defined in React Native and results in an error.
// (Actually, if it *is* defined in React Native, it's not meant for us, but
// for our customer's code; that's why we don't just simply override it globally).
export function getUserAgent() {
if (
!isReactNative() &&
typeof window !== 'undefined' &&
window.navigator &&
window.navigator.userAgent
) {
return window.navigator.userAgent;
}
return '';
}
export function isReactNative() {
return (
typeof navigator !== 'undefined' &&
navigator.product &&
navigator.product === 'ReactNative'
);
}
export function isIOS() {
const userAgent = getUserAgent();
return !!userAgent.match(/iPad|iPhone|iPod/i);
}
// Only valid if cam/mic are accessible from browser
export function isUserMediaAccessible() {
return (
navigator && navigator.mediaDevices && navigator.mediaDevices.getUserMedia
);
}
// Returns whether we should allow screen sharing from this browser.
//
// Note: technically we *could* try to support screen sharing from any browser where
// isDisplayMediaAccessible() is true (PeerToPeer.js is mostly set up to do so).
// However, limiting screen sharing to only those that support the Unified Plan SDP
// format lets us simplify code paths on the receiving end of screen shares: in order
// to check whether to always expect a single inbound video track, we simply have to
// check whether we're a browser that only supports the older Plan B SDP format (see below).
// Additionally, limiting screen sharing this way reduces our test matrix.
export function isScreenSharingSupported() {
return isDisplayMediaAccessible() && canUnifiedPlan();
}
const supportedBrowsersForVideoProcessors = ['Chrome', 'Firefox'];
export function isVideoProcessingSupported() {
if (isReactNative()) return false;
if (browserMobile_p()) return false;
return supportedBrowsersForVideoProcessors.includes(getBrowserName());
}
export function isSfuSupported() {
if (isReactNative()) return true;
return browserVideoSupported_p();
}
export function canUnifiedPlan() {
return browserCanUnifiedPlan(getBrowserName(), getBrowserVersion());
}
export function browserCanUnifiedPlan(browserName, browserVersion) {
if (!(browserName && browserVersion)) {
return false;
}
switch (browserName) {
case 'Chrome':
return browserVersion.major >= 75;
case 'Safari':
// This is the check that Apple suggests in https://webkit.org/blog/8672/on-the-road-to-webrtc-1-0-including-vp8/,
// plus a workaround that was already in place here for a Safari 13.0.0 bug, forcing it into Plan B.
return (
RTCRtpTransceiver.prototype.hasOwnProperty('currentDirection') &&
!(
browserVersion.major === 13 &&
browserVersion.minor === 0 &&
browserVersion.point === 0
)
);
// Note: We now only support Firefox 80+ so this should always be true
case 'Firefox':
return browserVersion.major >= 67;
}
return false;
}
export function browserVideoSupported_p() {
return isUserMediaAccessible() && !browserNeedsUpgrade();
}
export function isAndroidApp() {
return getUserAgent().match(/DailyAnd\//);
}
export function isAndroidWeb() {
return getUserAgent().match(/Linux; Android/);
}
export function browserMobile_p() {
const userAgent = getUserAgent();
if (userAgent.match(/Mobi/) || userAgent.match(/Android/)) {
return true;
}
if (isAndroidApp()) {
return true;
}
}
export function browserNeedsUpgrade() {
let browser = getBrowserName(),
ua = getUserAgent(),
version;
if (!ua) {
return true;
}
switch (browser) {
case 'Chrome':
// Includes Chromium-based browsers
version = getChromeVersion();
return version.major && version.major > 0 && version.major < 61;
case 'Firefox':
version = getFirefoxVersion();
return version.major < 78;
case 'Safari':
version = getSafariVersion();
return version.major < 12;
default:
return true;
}
}
export function getBrowserName() {
if (typeof window !== 'undefined') {
const userAgent = getUserAgent();
// Treat supported WKWebView as Safari. Check for this first just in case
// 3rd-party browsers on iOS decide to customize their user agent strings to
// match the other conditions.
if (isSupportedIOSEnvironment()) {
return 'Safari';
} else if (userAgent.indexOf('Edge') > -1) {
// Note: check will (purposefully) fail for chromium-based Edge
// since the user-agent for chromium-based Edge reports `Edg`
// (or EdgA (android) or EdgiOS)
// Also note: getBrowserName is primarily used for internal
// logic, so this should go away eventually. However, it is used
// in the old prebuilt UI for some upgrade messaging so leaving
// it in until Edge or the old prebuilt is really no longer a thing
return 'Edge';
// } else if (userAgent.indexOf('OPR') > -1 ||
// userAgent.indexOf('Opera') > -1) {
// return 'Opera';
} else if (userAgent.match(/Chrome\//)) {
// Includes Chromium-based browsers
return 'Chrome';
} else if (userAgent.indexOf('Safari') > -1) {
return 'Safari';
} else if (userAgent.indexOf('Firefox') > -1) {
return 'Firefox';
} else if (
userAgent.indexOf('MSIE') > -1 ||
userAgent.indexOf('.NET') > -1
) {
return 'IE';
} else {
return 'Unknown Browser';
}
}
}
export function getBrowserVersion() {
let name = getBrowserName();
switch (name) {
case 'Chrome':
// Includes Chromium-based browsers
return getChromeVersion();
case 'Safari':
return getSafariVersion();
case 'Firefox':
return getFirefoxVersion();
case 'Edge':
return getEdgeVersion();
}
}
export function getChromeVersion() {
let major = 0,
minor = 0,
build = 0,
patch = 0,
opera = false;
if (typeof window !== 'undefined') {
const userAgent = getUserAgent(),
match = userAgent.match(/Chrome\/(\d+).(\d+).(\d+).(\d+)/);
if (match) {
try {
major = parseInt(match[1]);
minor = parseInt(match[2]);
build = parseInt(match[3]);
patch = parseInt(match[4]);
opera = userAgent.indexOf('OPR/') > -1;
} catch (e) {}
}
}
return { major, minor, build, patch, opera };
}
// Mobile Safari or WKWebView on iOS/iPadOS >= 14.3
export function isSupportedIOSEnvironment() {
return isIOS() && isUserMediaAccessible();
}
function isDisplayMediaAccessible() {
return !!(
navigator &&
navigator.mediaDevices &&
navigator.mediaDevices.getDisplayMedia
);
}
function getSafariVersion() {
let major = 0,
minor = 0,
point = 0;
if (typeof window !== 'undefined') {
const userAgent = getUserAgent(),
match = userAgent.match(/Version\/(\d+).(\d+)(.(\d+))?/);
if (match) {
try {
major = parseInt(match[1]);
minor = parseInt(match[2]);
point = parseInt(match[4]);
} catch (e) {}
} else if (isSupportedIOSEnvironment()) {
// Hack: treat supported WKWebView like Safari 14.0.3 (no need to be
// precise; just needs to be new enough to appear supported, and this was
// the Safari version around the time WKWebView WebRTC support was added)
major = 14;
minor = 0;
point = 3;
}
}
return { major, minor, point };
}
function getFirefoxVersion() {
let major = 0,
minor = 0;
if (typeof window !== 'undefined') {
const userAgent = getUserAgent(),
match = userAgent.match(/Firefox\/(\d+).(\d+)/);
if (match) {
try {
major = parseInt(match[1]);
minor = parseInt(match[2]);
} catch (e) {}
}
}
return { major, minor };
}
function getEdgeVersion() {
let major = 0,
minor = 0;
if (typeof window !== 'undefined') {
const userAgent = getUserAgent(),
match = userAgent.match(/Edge\/(\d+).(\d+)/);
if (match) {
try {
major = parseInt(match[1]);
minor = parseInt(match[2]);
} catch (e) {}
}
}
return { major, minor };
}