diff --git a/openvidu-browser/src/OpenVidu/OpenVidu.ts b/openvidu-browser/src/OpenVidu/OpenVidu.ts index cdbf67ce..5c5ecb8e 100644 --- a/openvidu-browser/src/OpenVidu/OpenVidu.ts +++ b/openvidu-browser/src/OpenVidu/OpenVidu.ts @@ -404,7 +404,7 @@ export class OpenVidu { if (publisherProperties.videoSource === 'screen') { - if (platform.name !== 'Chrome' && platform.name !== 'Firefox') { + if (platform.name !== 'Chrome' && platform.name!.indexOf('Firefox') === -1) { const error = new OpenViduError(OpenViduErrorName.SCREEN_SHARING_NOT_SUPPORTED, 'You can only screen share in desktop Chrome and Firefox. Detected browser: ' + platform.name); console.error(error); reject(error); @@ -416,7 +416,7 @@ export class OpenVidu { const extensionId = this.advancedConfiguration.screenShareChromeExtension.split('/').pop()!!.trim(); screenSharing.getChromeExtensionStatus(extensionId, (status) => { - if (status === 'installed-enabled') { + if (status === 'installed-enabled' || (status === 'not-chrome' && platform.name!.indexOf('Firefox') !== -1)) { screenSharing.getScreenConstraints((error, screenConstraints) => { if (!!error && error === 'permission-denied') { const error = new OpenViduError(OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop'); diff --git a/openvidu-browser/src/OpenViduInternal/ScreenSharing/Screen-Capturing-Auto.js b/openvidu-browser/src/OpenViduInternal/ScreenSharing/Screen-Capturing-Auto.js index 3506b1ae..1d171e1d 100644 --- a/openvidu-browser/src/OpenViduInternal/ScreenSharing/Screen-Capturing-Auto.js +++ b/openvidu-browser/src/OpenViduInternal/ScreenSharing/Screen-Capturing-Auto.js @@ -1,4 +1,4 @@ -// Last time updated on December 13, 2017 +// Last time updated on June 08, 2018 // Latest file can be found here: https://cdn.webrtc-experiment.com/getScreenId.js @@ -14,14 +14,24 @@ getScreenId(function (error, sourceId, screen_constraints) { // error == null || 'permission-denied' || 'not-installed' || 'installed-disabled' || 'not-chrome' // sourceId == null || 'string' || 'firefox' - if(sourceId == 'firefox') { - navigator.mozGetUserMedia(screen_constraints, onSuccess, onFailure); + if(microsoftEdge) { + navigator.getDisplayMedia(screen_constraints).then(onSuccess, onFailure); } - else navigator.webkitGetUserMedia(screen_constraints, onSuccess, onFailure); -}); + else { + navigator.mediaDevices.getUserMedia(screen_constraints).then(onSuccess)catch(onFailure); + } +}, 'pass second parameter only if you want system audio'); */ -window.getScreenId = function (callback) { +window.getScreenId = function (callback, custom_parameter) { + if (navigator.userAgent.indexOf('Edge') !== -1 && (!!navigator.msSaveOrOpenBlob || !!navigator.msSaveBlob)) { + // microsoft edge => navigator.getDisplayMedia(screen_constraints).then(onSuccess, onFailure); + callback({ + video: true + }); + return; + } + // for Firefox: // sourceId == 'firefox' // screen_constraints = {...} @@ -44,7 +54,7 @@ window.getScreenId = function (callback) { if (event.data.chromeMediaSourceId === 'PermissionDeniedError') { callback('permission-denied'); } else { - callback(null, event.data.chromeMediaSourceId, getScreenConstraints(null, event.data.chromeMediaSourceId)); + callback(null, event.data.chromeMediaSourceId, getScreenConstraints(null, event.data.chromeMediaSourceId, event.data.canRequestAudioTrack)); } // this event listener is no more needed @@ -59,10 +69,17 @@ window.getScreenId = function (callback) { } } - setTimeout(postGetSourceIdMessage, 100); + if (!custom_parameter) { + setTimeout(postGetSourceIdMessage, 100); + } + else { + setTimeout(function () { + postGetSourceIdMessage(custom_parameter); + }, 100); + } }; -function getScreenConstraints(error, sourceId) { +function getScreenConstraints(error, sourceId, canRequestAudioTrack) { var screen_constraints = { audio: false, video: { @@ -75,31 +92,76 @@ function getScreenConstraints(error, sourceId) { } }; + if (!!canRequestAudioTrack) { + screen_constraints.audio = { + mandatory: { + chromeMediaSource: error ? 'screen' : 'desktop', + // echoCancellation: true + }, + optional: [] + }; + } + if (sourceId) { screen_constraints.video.mandatory.chromeMediaSourceId = sourceId; + + if (screen_constraints.audio && screen_constraints.audio.mandatory) { + screen_constraints.audio.mandatory.chromeMediaSourceId = sourceId; + } } return screen_constraints; } -var iframe; - -function postGetSourceIdMessage() { +function postGetSourceIdMessage(custom_parameter) { if (!iframe) { - loadIFrame(postGetSourceIdMessage); + loadIFrame(function () { + postGetSourceIdMessage(custom_parameter); + }); return; } if (!iframe.isLoaded) { - setTimeout(postGetSourceIdMessage, 100); + setTimeout(function () { + postGetSourceIdMessage(custom_parameter); + }, 100); return; } - iframe.contentWindow.postMessage({ - captureSourceId: true - }, '*'); + if (!custom_parameter) { + iframe.contentWindow.postMessage({ + captureSourceId: true + }, '*'); + } + else if (!!custom_parameter.forEach) { + iframe.contentWindow.postMessage({ + captureCustomSourceId: custom_parameter + }, '*'); + } + else { + iframe.contentWindow.postMessage({ + captureSourceIdWithAudio: true + }, '*'); + } } +var iframe; + +// this function is used in RTCMultiConnection v3 +window.getScreenConstraints = function (callback) { + loadIFrame(function () { + getScreenId(function (error, sourceId, screen_constraints) { + if (!screen_constraints) { + screen_constraints = { + video: true + }; + } + + callback(error, screen_constraints.video); + }); + }); +}; + function loadIFrame(loadCallback) { if (iframe) { loadCallback(); @@ -111,7 +173,7 @@ function loadIFrame(loadCallback) { iframe.isLoaded = true; loadCallback(); }; - iframe.src = 'https://www.webrtc-experiment.com/getSourceId/'; + iframe.src = 'https://www.webrtc-experiment.com/getSourceId/'; // https://wwww.yourdomain.com/getScreenId.html iframe.style.display = 'none'; (document.body || document.documentElement).appendChild(iframe); } @@ -130,10 +192,10 @@ window.getChromeExtensionStatus = function (callback) { if (event.data.chromeExtensionStatus) { callback(event.data.chromeExtensionStatus); - } - // this event listener is no more needed - window.removeEventListener('message', onIFrameCallback); + // this event listener is no more needed + window.removeEventListener('message', onIFrameCallback); + } } setTimeout(postGetChromeExtensionStatusMessage, 100); diff --git a/openvidu-browser/src/OpenViduInternal/ScreenSharing/Screen-Capturing.js b/openvidu-browser/src/OpenViduInternal/ScreenSharing/Screen-Capturing.js index ca45cc73..1ce32dae 100644 --- a/openvidu-browser/src/OpenViduInternal/ScreenSharing/Screen-Capturing.js +++ b/openvidu-browser/src/OpenViduInternal/ScreenSharing/Screen-Capturing.js @@ -1,5 +1,6 @@ // global variables var chromeMediaSource = 'screen'; +var sourceId; var screenCallback; var isFirefox = typeof window.InstallTrigger !== 'undefined'; var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0; @@ -28,24 +29,21 @@ function onMessageCallback(data) { } // extension shared temp sourceId if (data.sourceId && screenCallback) { - screenCallback(sourceId = data.sourceId); + screenCallback(sourceId = data.sourceId, data.canRequestAudioTrack === true); } } // this method can be used to check if chrome extension is installed & enabled. function isChromeExtensionAvailable(callback) { - if (isFirefox) - return callback(false); - if (chromeMediaSource == 'desktop') - return callback('isFirefox'); + if (!callback) return; + if (chromeMediaSource == 'desktop') return callback(true); + // ask extension if it is available window.postMessage('are-you-there', '*'); setTimeout(function () { if (chromeMediaSource == 'screen') { - callback('unavailable'); - } - else - callback('available'); + callback(false); + } else callback(true); }, 2000); } @@ -59,6 +57,28 @@ function getSourceId(callback) { window.postMessage('get-sourceId', '*'); } +// this function can be used to get "source-id" from the extension +function getCustomSourceId(arr, callback) { + if (!arr || !arr.forEach) throw '"arr" parameter is mandatory and it must be an array.'; + if (!callback) throw '"callback" parameter is mandatory.'; + + if (sourceId) return callback(sourceId); + + screenCallback = callback; + window.postMessage({ + 'get-custom-sourceId': arr + }, '*'); +} + +// this function can be used to get "source-id" from the extension +function getSourceIdWithAudio(callback) { + if (!callback) throw '"callback" parameter is mandatory.'; + if (sourceId) return callback(sourceId); + + screenCallback = callback; + window.postMessage('audio-plus-tab', '*'); +} + function getChromeExtensionStatus(extensionid, callback) { if (isFirefox) return callback('not-chrome'); @@ -73,9 +93,8 @@ function getChromeExtensionStatus(extensionid, callback) { window.postMessage('are-you-there', '*'); setTimeout(function () { if (chromeMediaSource == 'screen') { - callback(extensionid == extensionid ? 'installed-enabled' : 'installed-disabled'); - } - else + callback('installed-disabled'); + } else callback('installed-enabled'); }, 2000); }; @@ -84,9 +103,12 @@ function getChromeExtensionStatus(extensionid, callback) { }; } +function getScreenConstraintsWithAudio(callback) { + getScreenConstraints(callback, true); +} + // this function explains how to use above methods/objects -function getScreenConstraints(callback) { - sourceId = ''; +function getScreenConstraints(callback, captureSourceIdWithAudio) { var firefoxScreenConstraints = { mozMediaSource: 'window', mediaSource: 'window' @@ -107,21 +129,36 @@ function getScreenConstraints(callback) { // if installed and available then it will invoke extension API // otherwise it will fallback to command-line based screen capturing API if (chromeMediaSource == 'desktop' && !sourceId) { - getSourceId(function () { - screen_constraints.mandatory.chromeMediaSourceId = sourceId; - callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints); - }); + if (captureSourceIdWithAudio) { + getSourceIdWithAudio(function (sourceId, canRequestAudioTrack) { + screen_constraints.mandatory.chromeMediaSourceId = sourceId; + + if (canRequestAudioTrack) { + screen_constraints.canRequestAudioTrack = true; + } + callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints); + }); + } + else { + getSourceId(function (sourceId) { + screen_constraints.mandatory.chromeMediaSourceId = sourceId; + callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints); + }); + } return; } + // this statement sets gets 'sourceId" and sets "chromeMediaSourceId" if (chromeMediaSource == 'desktop') { screen_constraints.mandatory.chromeMediaSourceId = sourceId; } + // now invoking native getUserMedia API callback(null, screen_constraints); } exports.getScreenConstraints = getScreenConstraints; +exports.getScreenConstraintsWithAudio = getScreenConstraintsWithAudio; exports.isChromeExtensionAvailable = isChromeExtensionAvailable; exports.getChromeExtensionStatus = getChromeExtensionStatus; exports.getSourceId = getSourceId; \ No newline at end of file