From a2c6ab66946d547e649276523f38270d373d7e64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5var=20Aamb=C3=B8=20Fosstveit?= Date: Sun, 4 Mar 2018 12:51:28 +0100 Subject: [PATCH] Added class to handle the differences in screen sharing between browsers. --- app/lib/ScreenShare.js | 197 +++++++++++++++++++++++++++++++++++++++++ app/lib/utils.js | 19 ++++ 2 files changed, 216 insertions(+) create mode 100644 app/lib/ScreenShare.js diff --git a/app/lib/ScreenShare.js b/app/lib/ScreenShare.js new file mode 100644 index 0000000..b598bc6 --- /dev/null +++ b/app/lib/ScreenShare.js @@ -0,0 +1,197 @@ +import { getBrowserType } from './utils'; + +class ChromeScreenShare +{ + constructor() + { + this._stream = null; + } + + start(options = { }) + { + const state = this; + + return new Promise((resolve, reject) => + { + window.addEventListener('message', _onExtensionMessage, false); + window.postMessage({ type: 'getStreamId' }, '*'); + + function _onExtensionMessage({ data }) + { + if (data.type !== 'gotStreamId') + { + return; + } + + const constraints = state._toConstraints(options, data.streamId); + + navigator.mediaDevices.getUserMedia(constraints) + .then((stream) => + { + window.removeEventListener('message', _onExtensionMessage); + + state._stream = stream; + resolve(stream); + }) + .catch((err) => + { + window.removeEventListener('message', _onExtensionMessage); + + reject(err); + }); + } + }); + } + + stop() + { + if (this._stream instanceof MediaStream === false) + { + return; + } + + this._stream.getTracks().forEach((track) => track.stop()); + this._stream = null; + } + + isScreenShareAvailable() + { + if ('__multipartyMeetingScreenShareExtensionAvailable__' in window) + { + return true; + } + + return false; + } + + _toConstraints(options, streamId) + { + const constraints = { + video : { + mandatory : { + chromeMediaSource : 'desktop', + chromeMediaSourceId : streamId + }, + optional : [ { + googTemporalLayeredScreencast : true + } ] + }, + audio : false + }; + + if (isFinite(options.width)) + { + constraints.video.mandatory.maxWidth = options.width; + constraints.video.mandatory.minWidth = options.width; + } + if (isFinite(options.height)) + { + constraints.video.mandatory.maxHeight = options.height; + constraints.video.mandatory.minHeight = options.height; + } + if (isFinite(options.frameRate)) + { + constraints.video.mandatory.maxFrameRate = options.frameRate; + constraints.video.mandatory.minFrameRate = options.frameRate; + } + + return constraints; + } +} + +class FirefoxScreenShare +{ + constructor() + { + this._stream = null; + } + + start(options = {}) + { + const constraints = this._toConstraints(options); + + return navigator.mediaDevices.getUserMedia(constraints) + .then((stream) => + { + this._stream = stream; + + return Promise.resolve(stream); + }); + } + + stop() + { + if (this._stream instanceof MediaStream === false) + { + return; + } + + this._stream.getTracks().forEach((track) => track.stop()); + this._stream = null; + } + + isScreenShareAvailable() + { + return true; + } + + _toConstraints(options) + { + const constraints = { + video : { + mediaSource : 'window' + }, + audio : false + }; + + if ('mediaSource' in options) + { + constraints.video.mediaSource = options.mediaSource; + } + if (isFinite(options.width)) + { + constraints.video.width = { + min : options.width, + max : options.width + }; + } + if (isFinite(options.height)) + { + constraints.video.height = { + min : options.height, + max : options.height + }; + } + if (isFinite(options.frameRate)) + { + constraints.video.frameRate = { + min : options.frameRate, + max : options.frameRate + }; + } + + return constraints; + } +} + +export default class ScreenShare +{ + static create() + { + switch (getBrowserType()) + { + case 'firefox': + { + return new FirefoxScreenShare(); + } + case 'chrome': + { + return new ChromeScreenShare(); + } + default: + { + return null; + } + } + } +} diff --git a/app/lib/utils.js b/app/lib/utils.js index b36c7d4..91c8768 100644 --- a/app/lib/utils.js +++ b/app/lib/utils.js @@ -18,3 +18,22 @@ export function isMobile() { return !mediaQueryDetectorElem.offsetParent; } + +export function getBrowserType() +{ + const ua = navigator.userAgent.toLowerCase(); + + // Firefox + if (ua.indexOf('firefox') !== -1) + { + return 'firefox'; + } + + // Chrome + if (ua.indexOf('chrome') !== -1 && ua.indexOf('edge') === -1) + { + return 'chrome'; + } + + return 'N/A'; +}