| 
				
			 | 
			
			
				
				@@ -5,8 +5,15 @@ import { Icon, IconClose } from '../../base/icons'; 
			 | 
		
		
	
		
			
			| 
				5
			 | 
			
				5
			 | 
			
			
				
				 import { translate } from '../../base/i18n'; 
			 | 
		
		
	
		
			
			| 
				6
			 | 
			
				6
			 | 
			
			
				
				 import { getCurrentConference } from '../../base/conference/functions'; 
			 | 
		
		
	
		
			
			| 
				7
			 | 
			
				7
			 | 
			
			
				
				 import { browser } from '../../base/lib-jitsi-meet'; 
			 | 
		
		
	
		
			
			| 
				8
			 | 
			
				
			 | 
			
			
				
				-import { isMobileBrowser } from '../../base/environment/utils'; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				8
			 | 
			
			
				
				+import { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				9
			 | 
			
			
				
				+    checkChromeExtensionsInstalled, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				10
			 | 
			
			
				
				+    isMobileBrowser 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				11
			 | 
			
			
				
				+} from '../../base/environment/utils'; 
			 | 
		
		
	
		
			
			| 
				9
			 | 
			
				12
			 | 
			
			
				
				 import logger from '../logger'; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				13
			 | 
			
			
				
				+import { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				14
			 | 
			
			
				
				+    createChromeExtensionBannerEvent, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				15
			 | 
			
			
				
				+    sendAnalytics 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				16
			 | 
			
			
				
				+} from '../../analytics'; 
			 | 
		
		
	
		
			
			| 
				10
			 | 
			
				17
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				11
			 | 
			
				18
			 | 
			
			
				
				 declare var interfaceConfig: Object; 
			 | 
		
		
	
		
			
			| 
				12
			 | 
			
				19
			 | 
			
			
				
				  
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -23,19 +30,14 @@ const DONT_SHOW_AGAIN_CHECKED = 'hide_chrome_extension_banner'; 
			 | 
		
		
	
		
			
			| 
				23
			 | 
			
				30
			 | 
			
			
				
				 type Props = { 
			 | 
		
		
	
		
			
			| 
				24
			 | 
			
				31
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				25
			 | 
			
				32
			 | 
			
			
				
				     /** 
			 | 
		
		
	
		
			
			| 
				26
			 | 
			
				
			 | 
			
			
				
				-     * Conference data, if any 
			 | 
		
		
	
		
			
			| 
				27
			 | 
			
				
			 | 
			
			
				
				-     */ 
			 | 
		
		
	
		
			
			| 
				28
			 | 
			
				
			 | 
			
			
				
				-    conference: Object, 
			 | 
		
		
	
		
			
			| 
				29
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				30
			 | 
			
				
			 | 
			
			
				
				-    /** 
			 | 
		
		
	
		
			
			| 
				31
			 | 
			
				
			 | 
			
			
				
				-     * The url of the chrome extension 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				33
			 | 
			
			
				
				+     * Contains info about installed/to be installed chrome extension(s). 
			 | 
		
		
	
		
			
			| 
				32
			 | 
			
				34
			 | 
			
			
				
				      */ 
			 | 
		
		
	
		
			
			| 
				33
			 | 
			
				
			 | 
			
			
				
				-    chromeExtensionUrl: string, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				35
			 | 
			
			
				
				+    bannerCfg: Object, 
			 | 
		
		
	
		
			
			| 
				34
			 | 
			
				36
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				35
			 | 
			
				37
			 | 
			
			
				
				     /** 
			 | 
		
		
	
		
			
			| 
				36
			 | 
			
				
			 | 
			
			
				
				-     * An array containing info for identifying a chrome extension 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				38
			 | 
			
			
				
				+     * Conference data, if any 
			 | 
		
		
	
		
			
			| 
				37
			 | 
			
				39
			 | 
			
			
				
				      */ 
			 | 
		
		
	
		
			
			| 
				38
			 | 
			
				
			 | 
			
			
				
				-    chromeExtensionsInfo: Array<Object>, 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				40
			 | 
			
			
				
				+    conference: Object, 
			 | 
		
		
	
		
			
			| 
				39
			 | 
			
				41
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				40
			 | 
			
				42
			 | 
			
			
				
				     /** 
			 | 
		
		
	
		
			
			| 
				41
			 | 
			
				43
			 | 
			
			
				
				      * Whether I am the current recorder. 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -91,7 +93,6 @@ class ChromeExtensionBanner extends PureComponent<Props, State> { 
			 | 
		
		
	
		
			
			| 
				91
			 | 
			
				93
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				92
			 | 
			
				94
			 | 
			
			
				
				         this._onClosePressed = this._onClosePressed.bind(this); 
			 | 
		
		
	
		
			
			| 
				93
			 | 
			
				95
			 | 
			
			
				
				         this._onInstallExtensionClick = this._onInstallExtensionClick.bind(this); 
			 | 
		
		
	
		
			
			| 
				94
			 | 
			
				
			 | 
			
			
				
				-        this._checkExtensionsInstalled = this._checkExtensionsInstalled.bind(this); 
			 | 
		
		
	
		
			
			| 
				95
			 | 
			
				96
			 | 
			
			
				
				         this._shouldNotRender = this._shouldNotRender.bind(this); 
			 | 
		
		
	
		
			
			| 
				96
			 | 
			
				97
			 | 
			
			
				
				         this._onDontShowAgainChange = this._onDontShowAgainChange.bind(this); 
			 | 
		
		
	
		
			
			| 
				97
			 | 
			
				98
			 | 
			
			
				
				     } 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -107,15 +108,18 @@ class ChromeExtensionBanner extends PureComponent<Props, State> { 
			 | 
		
		
	
		
			
			| 
				107
			 | 
			
				108
			 | 
			
			
				
				             return; 
			 | 
		
		
	
		
			
			| 
				108
			 | 
			
				109
			 | 
			
			
				
				         } 
			 | 
		
		
	
		
			
			| 
				109
			 | 
			
				110
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				110
			 | 
			
				
			 | 
			
			
				
				-        if (this.props.chromeExtensionUrl && !prevProps.chromeExtensionUrl) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				111
			 | 
			
			
				
				+        const { bannerCfg } = this.props; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				112
			 | 
			
			
				
				+        const prevBannerCfg = prevProps.bannerCfg; 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				113
			 | 
			
			
				
				+ 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				114
			 | 
			
			
				
				+        if (bannerCfg.url && !prevBannerCfg.url) { 
			 | 
		
		
	
		
			
			| 
				111
			 | 
			
				115
			 | 
			
			
				
				             logger.info('Chrome extension URL found.'); 
			 | 
		
		
	
		
			
			| 
				112
			 | 
			
				116
			 | 
			
			
				
				         } 
			 | 
		
		
	
		
			
			| 
				113
			 | 
			
				117
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				114
			 | 
			
				
			 | 
			
			
				
				-        if (this.props.chromeExtensionsInfo.length && !prevProps.chromeExtensionsInfo.length) { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				118
			 | 
			
			
				
				+        if ((bannerCfg.chromeExtensionsInfo || []).length && !(prevBannerCfg.chromeExtensionsInfo || []).length) { 
			 | 
		
		
	
		
			
			| 
				115
			 | 
			
				119
			 | 
			
			
				
				             logger.info('Chrome extension(s) info found.'); 
			 | 
		
		
	
		
			
			| 
				116
			 | 
			
				120
			 | 
			
			
				
				         } 
			 | 
		
		
	
		
			
			| 
				117
			 | 
			
				121
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				118
			 | 
			
				
			 | 
			
			
				
				-        const hasExtensions = await this._checkExtensionsInstalled(); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				122
			 | 
			
			
				
				+        const hasExtensions = await checkChromeExtensionsInstalled(this.props.bannerCfg); 
			 | 
		
		
	
		
			
			| 
				119
			 | 
			
				123
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				120
			 | 
			
				124
			 | 
			
			
				
				         if ( 
			 | 
		
		
	
		
			
			| 
				121
			 | 
			
				125
			 | 
			
			
				
				             hasExtensions 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -147,6 +151,7 @@ class ChromeExtensionBanner extends PureComponent<Props, State> { 
			 | 
		
		
	
		
			
			| 
				147
			 | 
			
				151
			 | 
			
			
				
				      * @returns {void} 
			 | 
		
		
	
		
			
			| 
				148
			 | 
			
				152
			 | 
			
			
				
				      */ 
			 | 
		
		
	
		
			
			| 
				149
			 | 
			
				153
			 | 
			
			
				
				     _onClosePressed() { 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				154
			 | 
			
			
				
				+        sendAnalytics(createChromeExtensionBannerEvent(false)); 
			 | 
		
		
	
		
			
			| 
				150
			 | 
			
				155
			 | 
			
			
				
				         this.setState({ closePressed: true }); 
			 | 
		
		
	
		
			
			| 
				151
			 | 
			
				156
			 | 
			
			
				
				     } 
			 | 
		
		
	
		
			
			| 
				152
			 | 
			
				157
			 | 
			
			
				
				  
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -158,36 +163,11 @@ class ChromeExtensionBanner extends PureComponent<Props, State> { 
			 | 
		
		
	
		
			
			| 
				158
			 | 
			
				163
			 | 
			
			
				
				      * @returns {void} 
			 | 
		
		
	
		
			
			| 
				159
			 | 
			
				164
			 | 
			
			
				
				      */ 
			 | 
		
		
	
		
			
			| 
				160
			 | 
			
				165
			 | 
			
			
				
				     _onInstallExtensionClick() { 
			 | 
		
		
	
		
			
			| 
				161
			 | 
			
				
			 | 
			
			
				
				-        window.open(this.props.chromeExtensionUrl); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				166
			 | 
			
			
				
				+        sendAnalytics(createChromeExtensionBannerEvent(true)); 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				167
			 | 
			
			
				
				+        window.open(this.props.bannerCfg.url); 
			 | 
		
		
	
		
			
			| 
				162
			 | 
			
				168
			 | 
			
			
				
				         this.setState({ closePressed: true }); 
			 | 
		
		
	
		
			
			| 
				163
			 | 
			
				169
			 | 
			
			
				
				     } 
			 | 
		
		
	
		
			
			| 
				164
			 | 
			
				170
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				165
			 | 
			
				
			 | 
			
			
				
				-    _checkExtensionsInstalled: () => Promise<*>; 
			 | 
		
		
	
		
			
			| 
				166
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				167
			 | 
			
				
			 | 
			
			
				
				-    /** 
			 | 
		
		
	
		
			
			| 
				168
			 | 
			
				
			 | 
			
			
				
				-     * Checks whether the chrome extensions defined in the config file are installed or not. 
			 | 
		
		
	
		
			
			| 
				169
			 | 
			
				
			 | 
			
			
				
				-     * 
			 | 
		
		
	
		
			
			| 
				170
			 | 
			
				
			 | 
			
			
				
				-     * @returns {Promise[]} 
			 | 
		
		
	
		
			
			| 
				171
			 | 
			
				
			 | 
			
			
				
				-     */ 
			 | 
		
		
	
		
			
			| 
				172
			 | 
			
				
			 | 
			
			
				
				-    _checkExtensionsInstalled() { 
			 | 
		
		
	
		
			
			| 
				173
			 | 
			
				
			 | 
			
			
				
				-        const isExtensionInstalled = info => new Promise(resolve => { 
			 | 
		
		
	
		
			
			| 
				174
			 | 
			
				
			 | 
			
			
				
				-            const img = new Image(); 
			 | 
		
		
	
		
			
			| 
				175
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				176
			 | 
			
				
			 | 
			
			
				
				-            img.src = `chrome-extension://${info.id}/${info.path}`; 
			 | 
		
		
	
		
			
			| 
				177
			 | 
			
				
			 | 
			
			
				
				-            img.onload = function() { 
			 | 
		
		
	
		
			
			| 
				178
			 | 
			
				
			 | 
			
			
				
				-                resolve(true); 
			 | 
		
		
	
		
			
			| 
				179
			 | 
			
				
			 | 
			
			
				
				-            }; 
			 | 
		
		
	
		
			
			| 
				180
			 | 
			
				
			 | 
			
			
				
				-            img.onerror = function() { 
			 | 
		
		
	
		
			
			| 
				181
			 | 
			
				
			 | 
			
			
				
				-                resolve(false); 
			 | 
		
		
	
		
			
			| 
				182
			 | 
			
				
			 | 
			
			
				
				-            }; 
			 | 
		
		
	
		
			
			| 
				183
			 | 
			
				
			 | 
			
			
				
				-        }); 
			 | 
		
		
	
		
			
			| 
				184
			 | 
			
				
			 | 
			
			
				
				-        const extensionInstalledFunction = info => isExtensionInstalled(info); 
			 | 
		
		
	
		
			
			| 
				185
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				186
			 | 
			
				
			 | 
			
			
				
				-        return Promise.all( 
			 | 
		
		
	
		
			
			| 
				187
			 | 
			
				
			 | 
			
			
				
				-            this.props.chromeExtensionsInfo.map(info => extensionInstalledFunction(info)) 
			 | 
		
		
	
		
			
			| 
				188
			 | 
			
				
			 | 
			
			
				
				-        ); 
			 | 
		
		
	
		
			
			| 
				189
			 | 
			
				
			 | 
			
			
				
				-    } 
			 | 
		
		
	
		
			
			| 
				190
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				191
			 | 
			
				171
			 | 
			
			
				
				     _shouldNotRender: () => boolean; 
			 | 
		
		
	
		
			
			| 
				192
			 | 
			
				172
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				193
			 | 
			
				173
			 | 
			
			
				
				     /** 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -202,7 +182,7 @@ class ChromeExtensionBanner extends PureComponent<Props, State> { 
			 | 
		
		
	
		
			
			| 
				202
			 | 
			
				182
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				203
			 | 
			
				183
			 | 
			
			
				
				         const dontShowAgain = localStorage.getItem(DONT_SHOW_AGAIN_CHECKED) === 'true'; 
			 | 
		
		
	
		
			
			| 
				204
			 | 
			
				184
			 | 
			
			
				
				  
			 | 
		
		
	
		
			
			| 
				205
			 | 
			
				
			 | 
			
			
				
				-        return !this.props.chromeExtensionUrl 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				185
			 | 
			
			
				
				+        return !this.props.bannerCfg.url 
			 | 
		
		
	
		
			
			| 
				206
			 | 
			
				186
			 | 
			
			
				
				             || dontShowAgain 
			 | 
		
		
	
		
			
			| 
				207
			 | 
			
				187
			 | 
			
			
				
				             || this.state.closePressed 
			 | 
		
		
	
		
			
			| 
				208
			 | 
			
				188
			 | 
			
			
				
				             || !this.state.shouldShow 
			 | 
		
		
	
	
		
			
			| 
				
			 | 
			
			
				
				@@ -290,11 +270,8 @@ class ChromeExtensionBanner extends PureComponent<Props, State> { 
			 | 
		
		
	
		
			
			| 
				290
			 | 
			
				270
			 | 
			
			
				
				  * @returns {Object} 
			 | 
		
		
	
		
			
			| 
				291
			 | 
			
				271
			 | 
			
			
				
				  */ 
			 | 
		
		
	
		
			
			| 
				292
			 | 
			
				272
			 | 
			
			
				
				 const _mapStateToProps = state => { 
			 | 
		
		
	
		
			
			| 
				293
			 | 
			
				
			 | 
			
			
				
				-    const bannerCfg = state['features/base/config'].chromeExtensionBanner || {}; 
			 | 
		
		
	
		
			
			| 
				294
			 | 
			
				
			 | 
			
			
				
				- 
			 | 
		
		
	
		
			
			| 
				295
			 | 
			
				273
			 | 
			
			
				
				     return { 
			 | 
		
		
	
		
			
			| 
				296
			 | 
			
				
			 | 
			
			
				
				-        chromeExtensionUrl: bannerCfg.url, 
			 | 
		
		
	
		
			
			| 
				297
			 | 
			
				
			 | 
			
			
				
				-        chromeExtensionsInfo: bannerCfg.chromeExtensionsInfo || [], 
			 | 
		
		
	
		
			
			| 
				
			 | 
			
				274
			 | 
			
			
				
				+        bannerCfg: state['features/base/config'].chromeExtensionBanner || {}, 
			 | 
		
		
	
		
			
			| 
				298
			 | 
			
				275
			 | 
			
			
				
				         conference: getCurrentConference(state), 
			 | 
		
		
	
		
			
			| 
				299
			 | 
			
				276
			 | 
			
			
				
				         iAmRecorder: state['features/base/config'].iAmRecorder 
			 | 
		
		
	
		
			
			| 
				300
			 | 
			
				277
			 | 
			
			
				
				     }; 
			 |