Explorar el Código

Implements screen sharing for firefox, using a jidesha extension.

Renames some fields in config.js.
master
Boris Grozev hace 9 años
padre
commit
995b3be6e7

+ 25
- 4
config.js Ver fichero

@@ -17,10 +17,31 @@ var config = {
17 17
     clientNode: 'http://jitsi.org/jitsimeet', // The name of client node advertised in XEP-0115 'c' stanza
18 18
     //focusUserJid: 'focus@auth.jitsi-meet.example.com', // The real JID of focus participant - can be overridden here
19 19
     //defaultSipNumber: '', // Default SIP number
20
-    desktopSharing: 'ext', // Desktop sharing method. Can be set to 'ext', 'webrtc' or false to disable.
21
-    chromeExtensionId: 'diibjkoicjeejcmhdnailmkgecihlobk', // Id of desktop streamer Chrome extension
22
-    desktopSharingSources: ['screen', 'window'],
23
-    minChromeExtVersion: '0.1', // Required version of Chrome extension
20
+
21
+    // Desktop sharing method. Can be set to 'ext', 'webrtc' or false to disable.
22
+    desktopSharingChromeMethod: 'ext',
23
+    // The ID of the jidesha extension for Chrome.
24
+    desktopSharingChromeExtId: 'diibjkoicjeejcmhdnailmkgecihlobk',
25
+    // The media sources to use when using screen sharing with the Chrome
26
+    // extension.
27
+    desktopSharingChromeSources: ['screen', 'window'],
28
+    // Required version of Chrome extension
29
+    desktopSharingChromeMinExtVersion: '0.1',
30
+
31
+    // The ID of the jidesha extension for Firefox. If null, we assume that no
32
+    // extension is required.
33
+    desktopSharingFirefoxExtId: null,
34
+    // Whether desktop sharing should be disabled on Firefox.
35
+    desktopSharingFirefoxDisabled: true,
36
+    // The maximum version of Firefox which requires a jidesha extension.
37
+    // Example: if set to 41, we will require the extension for Firefox versions
38
+    // up to and including 41. On Firefox 42 and higher, we will run without the
39
+    // extension.
40
+    // If set to -1, an extension will be required for all versions of Firefox.
41
+    desktopSharingFirefoxMaxVersionExtRequired: -1,
42
+    // The URL to the Firefox extension for desktop sharing.
43
+    desktopSharingFirefoxExtensionURL: null,
44
+
24 45
     openSctp: true, // Toggle to enable/disable SCTP channels
25 46
     disableStats: false,
26 47
     disableAudioLevels: false,

+ 3
- 3
index.html Ver fichero

@@ -11,7 +11,7 @@
11 11
     <meta itemprop="image" content="/images/jitsilogo.png"/>
12 12
     <script src="https://api.callstats.io/static/callstats.min.js"></script>
13 13
     <script src="libs/jquery-2.1.1.min.js"></script>
14
-    <script src="config.js?v=12"></script><!-- adapt to your needs, i.e. set hosts and bosh path -->
14
+    <script src="config.js?v=13"></script><!-- adapt to your needs, i.e. set hosts and bosh path -->
15 15
     <script src="libs/strophe/strophe.min.js?v=2"></script>
16 16
     <script src="libs/strophe/strophe.disco.min.js?v=1"></script>
17 17
     <script src="libs/strophe/strophe.caps.jsonly.min.js?v=1"></script>
@@ -20,12 +20,12 @@
20 20
     <script src="libs/popover.js?v=1"></script><!-- bootstrap tooltip lib -->
21 21
     <script src="libs/toastr.js?v=1"></script><!-- notifications lib -->
22 22
     <script src="interface_config.js?v=5"></script>
23
-    <script src="libs/app.bundle.js?v=134"></script>
23
+    <script src="libs/app.bundle.js?v=131"></script>
24 24
     <script src="analytics.js?v=1"></script><!-- google analytics plugin -->
25 25
     <link rel="stylesheet" href="css/font.css?v=7"/>
26 26
     <link rel="stylesheet" href="css/toastr.css?v=1">
27 27
     <link rel="stylesheet" type="text/css" media="screen" href="css/main.css?v=31"/>
28
-    <link rel="stylesheet" type="text/css" media="screen" href="css/videolayout_default.css?v=21" id="videolayout_default"/>
28
+    <link rel="stylesheet" type="text/css" media="screen" href="css/videolayout_default.css?v=20" id="videolayout_default"/>
29 29
     <link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
30 30
     <link rel="stylesheet" href="css/jquery-impromptu.css?v=4">
31 31
     <link rel="stylesheet" href="css/modaldialog.css?v=3">

+ 3
- 1
lang/main.json Ver fichero

@@ -194,7 +194,9 @@
194 194
         "password": "password",
195 195
         "userPassword": "user password",
196 196
         "token": "token",
197
-        "displayNameRequired": "Please enter your display name:"
197
+        "displayNameRequired": "Please enter your display name:",
198
+        "extensionRequired": "Extension required:",
199
+        "firefoxExtensionPrompt": "You need to install a Firefox extension in order to use screen sharing. Please try again after you <a href='__url__'>get it from here</a>!"
198 200
     },
199 201
     "email":
200 202
     {

+ 10
- 0
modules/UI/UI.js Ver fichero

@@ -199,6 +199,16 @@ function registerListeners() {
199 199
     APP.desktopsharing.addListener(
200 200
         DesktopSharingEventTypes.SWITCHING_DONE,
201 201
         Toolbar.changeDesktopSharingButtonState);
202
+    APP.desktopsharing.addListener(
203
+        DesktopSharingEventTypes.FIREFOX_EXTENSION_NEEDED,
204
+        function (url) {
205
+            APP.UI.messageHandler.openMessageDialog(
206
+                "dialog.extensionRequired",
207
+                null,
208
+                null,
209
+                APP.translation.generateTranslationHTML(
210
+                    "dialog.firefoxExtensionPrompt", {url: url}));
211
+        });
202 212
     APP.connectionquality.addListener(CQEvents.LOCALSTATS_UPDATED,
203 213
         VideoLayout.updateLocalConnectionStats);
204 214
     APP.connectionquality.addListener(CQEvents.REMOTESTATS_UPDATED,

+ 14
- 6
modules/UI/util/MessageHandler.js Ver fichero

@@ -11,15 +11,23 @@ var messageHandler = (function(my) {
11 11
     /**
12 12
      * Shows a message to the user.
13 13
      *
14
-     * @param titleKey the title of the message
15
-     * @param messageKey the text of the message
14
+     * @param titleKey the key used to find the translation of the title of the
15
+     * message, if a message title is not provided.
16
+     * @param messageKey the key used to find the translation of the message,
17
+     * if a message is not provided.
18
+     * @param title the title of the message. If a falsy value is provided,
19
+     * titleKey will be used to get a title via the translation API.
20
+     * @param message the message to show. If a falsy value is provided,
21
+     * messageKey will be used to get a message via the translation API.
16 22
      */
17
-    my.openMessageDialog = function(titleKey, messageKey) {
18
-        var title = null;
19
-        if(titleKey) {
23
+    my.openMessageDialog = function(titleKey, messageKey, title, message) {
24
+        if (!title) {
20 25
             title = APP.translation.generateTranslationHTML(titleKey);
21 26
         }
22
-        var message = APP.translation.generateTranslationHTML(messageKey);
27
+        if (!message) {
28
+            message = APP.translation.generateTranslationHTML(messageKey);
29
+        }
30
+
23 31
         $.prompt(message,
24 32
             {title: title, persistent: false}
25 33
         );

+ 156
- 15
modules/desktopsharing/ScreenObtainer.js Ver fichero

@@ -2,12 +2,15 @@
2 2
 /* jshint -W003 */
3 3
 var RTCBrowserType = require("../RTC/RTCBrowserType");
4 4
 var AdapterJS = require("../RTC/adapter.screenshare");
5
+var DesktopSharingEventTypes
6
+    = require("../../service/desktopsharing/DesktopSharingEventTypes");
5 7
 
6 8
 /**
7 9
  * Indicates whether the Chrome desktop sharing extension is installed.
8 10
  * @type {boolean}
9 11
  */
10 12
 var chromeExtInstalled = false;
13
+
11 14
 /**
12 15
  * Indicates whether an update of the Chrome desktop sharing extension is
13 16
  * required.
@@ -15,27 +18,54 @@ var chromeExtInstalled = false;
15 18
  */
16 19
 var chromeExtUpdateRequired = false;
17 20
 
21
+/**
22
+ * Whether the jidesha extension for firefox is installed for the domain on
23
+ * which we are running. Null designates an unknown value.
24
+ * @type {null}
25
+ */
26
+var firefoxExtInstalled = null;
27
+
28
+/**
29
+ * If set to true, detection of an installed firefox extension will be started
30
+ * again the next time obtainScreenOnFirefox is called (e.g. next time the
31
+ * user tries to enable screen sharing).
32
+ */
33
+var reDetectFirefoxExtension = false;
34
+
18 35
 /**
19 36
  * Handles obtaining a stream from a screen capture on different browsers.
20 37
  */
21 38
 function ScreenObtainer(){
22 39
 }
23 40
 
41
+/**
42
+ * The EventEmitter to use to emit events.
43
+ * @type {null}
44
+ */
45
+ScreenObtainer.prototype.eventEmitter = null;
46
+
24 47
 /**
25 48
  * Initializes the function used to obtain a screen capture (this.obtainStream).
26 49
  *
27
- * If the browser is Chrome, it uses the value of 'config.desktopSharing' to
28
- * decide whether to use the a Chrome extension (if the value is 'ext'), use
29
- * the "screen" media source (if the value is 'webrtc'), or disable screen
30
- * capture (if the value is other).
50
+ * If the browser is Chrome, it uses the value of
51
+ * 'config.desktopSharingChromeMethod' (or 'config.desktopSharing') to * decide
52
+ * whether to use the a Chrome extension (if the value is 'ext'), use the
53
+ * "screen" media source (if the value is 'webrtc'), or disable screen capture
54
+ * (if the value is other).
31 55
  * Note that for the "screen" media source to work the
32 56
  * 'chrome://flags/#enable-usermedia-screen-capture' flag must be set.
33 57
  */
34
-ScreenObtainer.prototype.init = function() {
58
+ScreenObtainer.prototype.init = function(eventEmitter) {
59
+    this.eventEmitter = eventEmitter;
35 60
     var obtainDesktopStream = null;
36 61
 
37
-    // When TemasysWebRTC plugin is used we always use getUserMedia, so we don't
38
-    // care about the value of config.desktopSharing.
62
+    if (RTCBrowserType.isFirefox())
63
+        initFirefoxExtensionDetection();
64
+
65
+    // TODO remove this, config.desktopSharing is deprecated.
66
+    var chromeMethod =
67
+        (config.desktopSharingChromeMethod || config.desktopSharing);
68
+
39 69
     if (RTCBrowserType.isTemasysPluginUsed()) {
40 70
         if (!AdapterJS.WebRTCPlugin.plugin.HasScreensharingFeature) {
41 71
             console.info("Screensharing not supported by this plugin version");
@@ -47,7 +77,7 @@ ScreenObtainer.prototype.init = function() {
47 77
             console.info("Using Temasys plugin for desktop sharing");
48 78
         }
49 79
     } else if (RTCBrowserType.isChrome()) {
50
-        if (config.desktopSharing == "ext") {
80
+        if (chromeMethod == "ext") {
51 81
             if (RTCBrowserType.getChromeVersion() >= 34) {
52 82
                 obtainDesktopStream = obtainScreenFromExtension;
53 83
                 console.info("Using Chrome extension for desktop sharing");
@@ -55,19 +85,28 @@ ScreenObtainer.prototype.init = function() {
55 85
             } else {
56 86
                 console.info("Chrome extension not supported until ver 34");
57 87
             }
58
-        } else if (config.desktopSharing == "webrtc") {
88
+        } else if (chromeMethod == "webrtc") {
59 89
             obtainDesktopStream = obtainWebRTCScreen;
60 90
             console.info("Using Chrome WebRTC for desktop sharing");
61 91
         }
62 92
     } else if (RTCBrowserType.isFirefox()) {
63
-        obtainDesktopStream = obtainWebRTCScreen;
93
+        if (config.desktopSharingFirefoxDisabled) {
94
+            obtainDesktopStream = null;
95
+        } else if (window.location.protocol === "http:"){
96
+            console.log("Screen sharing is not supported over HTTP. Use of " +
97
+                "HTTPS is required.");
98
+            obtainDesktopStream = null;
99
+        } else {
100
+            obtainDesktopStream = this.obtainScreenOnFirefox;
101
+        }
102
+
64 103
     }
65 104
 
66 105
     if (!obtainDesktopStream) {
67 106
         console.info("Desktop sharing disabled");
68 107
     }
69 108
 
70
-    ScreenObtainer.prototype.obtainStream = obtainDesktopStream.bind(this);
109
+    ScreenObtainer.prototype.obtainStream = obtainDesktopStream;
71 110
 };
72 111
 
73 112
 ScreenObtainer.prototype.obtainStream = null;
@@ -105,8 +144,9 @@ function obtainWebRTCScreen(streamCallback, failCallback) {
105 144
  */
106 145
 function getWebStoreInstallUrl()
107 146
 {
147
+    //TODO remove chromeExtensionId (deprecated)
108 148
     return "https://chrome.google.com/webstore/detail/" +
109
-        config.chromeExtensionId;
149
+        (config.desktopSharingChromeExtId || config.chromeExtensionId);
110 150
 }
111 151
 
112 152
 /**
@@ -156,7 +196,8 @@ function checkChromeExtInstalled(callback) {
156 196
         return;
157 197
     }
158 198
     chrome.runtime.sendMessage(
159
-        config.chromeExtensionId,
199
+        //TODO: remove chromeExtensionId (deprecated)
200
+        (config.desktopSharingChromeExtId || config.chromeExtensionId),
160 201
         { getVersion: true },
161 202
         function (response) {
162 203
             if (!response || !response.version) {
@@ -169,8 +210,12 @@ function checkChromeExtInstalled(callback) {
169 210
             // Check installed extension version
170 211
             var extVersion = response.version;
171 212
             console.log('Extension version is: ' + extVersion);
213
+            //TODO: remove minChromeExtVersion (deprecated)
172 214
             var updateRequired
173
-                = isUpdateRequired(config.minChromeExtVersion, extVersion);
215
+                = isUpdateRequired(
216
+                    (config.desktopSharingChromeMinExtVersion ||
217
+                        config.minChromeExtVersion),
218
+                    extVersion);
174 219
             callback(!updateRequired, updateRequired);
175 220
         }
176 221
     );
@@ -181,7 +226,12 @@ function doGetStreamFromExtension(streamCallback, failCallback) {
181 226
     // Extension id must be defined in the config.
182 227
     chrome.runtime.sendMessage(
183 228
         config.chromeExtensionId,
184
-        { getStream: true, sources: config.desktopSharingSources },
229
+        {
230
+            getStream: true,
231
+            //TODO: remove desktopSharingSources (deprecated).
232
+            sources: (config.desktopSharingChromeSources ||
233
+                config.desktopSharingSources)
234
+        },
185 235
         function (response) {
186 236
             if (!response) {
187 237
                 failCallback(chrome.runtime.lastError);
@@ -261,5 +311,96 @@ function initChromeExtension() {
261 311
     });
262 312
 }
263 313
 
314
+/**
315
+ * Obtains a screen capture stream on Firefox.
316
+ * @param callback
317
+ * @param errorCallback
318
+ */
319
+ScreenObtainer.prototype.obtainScreenOnFirefox =
320
+       function (callback, errorCallback) {
321
+    var self = this;
322
+    var extensionRequired = false;
323
+    if (config.desktopSharingFirefoxMaxVersionExtRequired === -1 ||
324
+        (config.desktopSharingFirefoxMaxVersionExtRequired >= 0 &&
325
+            RTCBrowserType.getFirefoxVersion() <=
326
+                config.desktopSharingFirefoxMaxVersionExtRequired)) {
327
+        extensionRequired = true;
328
+        console.log("Jidesha extension required on firefox version " +
329
+            RTCBrowserType.getFirefoxVersion());
330
+    }
331
+
332
+    if (!extensionRequired || firefoxExtInstalled === true) {
333
+        obtainWebRTCScreen(callback, errorCallback);
334
+        return;
335
+    }
336
+
337
+    if (reDetectFirefoxExtension) {
338
+        reDetectFirefoxExtension = false;
339
+        initFirefoxExtensionDetection();
340
+    }
341
+
342
+    // Give it some (more) time to initialize, and assume lack of extension if
343
+    // it hasn't.
344
+    if (firefoxExtInstalled === null) {
345
+        window.setTimeout(
346
+            function() {
347
+                if (firefoxExtInstalled === null)
348
+                    firefoxExtInstalled = false;
349
+                self.obtainScreenOnFirefox(callback, errorCallback);
350
+            },
351
+            300
352
+        );
353
+        console.log("Waiting for detection of jidesha on firefox to finish.");
354
+        return;
355
+    }
356
+
357
+    // We need an extension and it isn't installed.
358
+
359
+    // Make sure we check for the extension when the user clicks again.
360
+    firefoxExtInstalled = null;
361
+    reDetectFirefoxExtension = true;
362
+
363
+    // Prompt the user to install the extension
364
+    this.eventEmitter.emit(DesktopSharingEventTypes.FIREFOX_EXTENSION_NEEDED,
365
+                           config.desktopSharingFirefoxExtensionURL);
366
+
367
+    // Make sure desktopsharing knows that we failed, so that it doesn't get
368
+    // stuck in 'switching' mode.
369
+    errorCallback('Firefox extension required.');
370
+};
371
+
372
+/**
373
+ * Starts the detection of an installed jidesha extension for firefox.
374
+ */
375
+function initFirefoxExtensionDetection() {
376
+    if (config.desktopSharingFirefoxDisabled) {
377
+        return;
378
+    }
379
+    if (firefoxExtInstalled === false || firefoxExtInstalled === true)
380
+        return;
381
+    if (!config.desktopSharingFirefoxExtId) {
382
+        firefoxExtInstalled = false;
383
+        return;
384
+    }
385
+
386
+    var img = document.createElement('img');
387
+    img.onload = function(){
388
+        console.log("Detected firefox screen sharing extension.");
389
+        firefoxExtInstalled = true;
390
+    };
391
+    img.onerror = function(){
392
+        console.log("Detected lack of firefox screen sharing extension.");
393
+        firefoxExtInstalled = false;
394
+    };
395
+
396
+    // The jidesha extension exposes an empty image file under the url:
397
+    // "chrome://EXT_ID/content/DOMAIN.png"
398
+    // Where EXT_ID is the ID of the extension with "@" replaced by ".", and
399
+    // DOMAIN is a domain whitelisted by the extension.
400
+    var src = "chrome://" +
401
+        (config.desktopSharingFirefoxExtId.replace('@', '.')) +
402
+        "/content/" + document.location.hostname + ".png";
403
+    img.setAttribute('src', src);
404
+}
264 405
 
265 406
 module.exports = ScreenObtainer;

+ 12
- 8
modules/desktopsharing/desktopsharing.js Ver fichero

@@ -62,12 +62,6 @@ function onEndedHandler(stream) {
62 62
     }
63 63
 }
64 64
 
65
-// Called when RTC finishes initialization
66
-function onWebRtcReady() {
67
-    screenObtainer.init();
68
-    eventEmitter.emit(DesktopSharingEventTypes.INIT);
69
-}
70
-
71 65
 module.exports = {
72 66
     isUsingScreenStream: function () {
73 67
         return isUsingScreenStream;
@@ -82,7 +76,12 @@ module.exports = {
82 76
     },
83 77
     
84 78
     init: function () {
85
-        APP.RTC.addListener(RTCEvents.RTC_READY, onWebRtcReady);
79
+        // Called when RTC finishes initialization
80
+        APP.RTC.addListener(RTCEvents.RTC_READY,
81
+            function() {
82
+                screenObtainer.init(eventEmitter);
83
+                eventEmitter.emit(DesktopSharingEventTypes.INIT);
84
+            });
86 85
     },
87 86
 
88 87
     addListener: function (type, listener) {
@@ -139,6 +138,11 @@ module.exports = {
139 138
                 getVideoStreamFailed, config.resolution || '360'
140 139
             );
141 140
         }
142
-    }
141
+    },
142
+    /*
143
+     * Exports the event emitter to allow use by ScreenObtainer. Not for outside
144
+     * use.
145
+     */
146
+    eventEmitter: eventEmitter
143 147
 };
144 148
 

+ 7
- 1
service/desktopsharing/DesktopSharingEventTypes.js Ver fichero

@@ -3,7 +3,13 @@ var DesktopSharingEventTypes = {
3 3
 
4 4
     SWITCHING_DONE: "ds.switching_done",
5 5
 
6
-    NEW_STREAM_CREATED: "ds.new_stream_created"
6
+    NEW_STREAM_CREATED: "ds.new_stream_created",
7
+
8
+    /**
9
+     * An event which indicates that the jidesha extension for Firefox is
10
+     * needed to proceed with screen sharing, and that it is not installed.
11
+     */
12
+    FIREFOX_EXTENSION_NEEDED: "ds.firefox_extension_needed"
7 13
 };
8 14
 
9 15
 module.exports = DesktopSharingEventTypes;

Loading…
Cancelar
Guardar