Browse Source

feat(Analytics): Multiple analytics handlers support

dev1
hristoterezov 9 years ago
parent
commit
986719bd97

+ 2
- 5
JitsiConference.js View File

@@ -12,7 +12,6 @@ var JitsiDTMFManager = require('./modules/DTMF/JitsiDTMFManager');
12 12
 import JitsiTrackError from "./JitsiTrackError";
13 13
 import * as JitsiTrackErrors from "./JitsiTrackErrors";
14 14
 import * as JitsiTrackEvents from "./JitsiTrackEvents";
15
-var Settings = require("./modules/settings/Settings");
16 15
 var ComponentsVersions = require("./modules/version/ComponentsVersions");
17 16
 var GlobalOnErrorHandler = require("./modules/util/GlobalOnErrorHandler");
18 17
 var JitsiConferenceEventManager = require("./JitsiConferenceEventManager");
@@ -41,7 +40,6 @@ function JitsiConference(options) {
41 40
         throw new Error(errmsg);
42 41
     }
43 42
     this.eventEmitter = new EventEmitter();
44
-    this.settings = new Settings();
45 43
     this.options = options;
46 44
     this.eventManager = new JitsiConferenceEventManager(this);
47 45
     this._init(options);
@@ -99,8 +97,7 @@ JitsiConference.prototype._init = function (options) {
99 97
         this.eventManager.setupXMPPListeners();
100 98
     }
101 99
 
102
-    this.room = this.xmpp.createRoom(this.options.name, this.options.config,
103
-        this.settings);
100
+    this.room = this.xmpp.createRoom(this.options.name, this.options.config);
104 101
 
105 102
     this.room.updateDeviceAvailability(RTC.getDeviceAvailability());
106 103
 
@@ -927,7 +924,7 @@ function (jingleSession, jingleOffer, now) {
927 924
     // do not wait for XMPPEvents.PEERCONNECTION_READY, as it may never
928 925
     // happen in case if user doesn't have or denied permission to
929 926
     // both camera and microphone.
930
-    this.statistics.startCallStats(jingleSession, this.settings);
927
+    this.statistics.startCallStats(jingleSession);
931 928
     this.statistics.startRemoteStats(jingleSession.peerconnection);
932 929
 };
933 930
 

+ 13
- 0
JitsiMeetJS.js View File

@@ -21,6 +21,7 @@ var Resolutions = require("./service/RTC/Resolutions");
21 21
 var ScriptUtil = require("./modules/util/ScriptUtil");
22 22
 var GlobalOnErrorHandler = require("./modules/util/GlobalOnErrorHandler");
23 23
 var RTCBrowserType = require("./modules/RTC/RTCBrowserType");
24
+import Settings from "./modules/settings/Settings";
24 25
 
25 26
 // The amount of time to wait until firing
26 27
 // JitsiMediaDevicesEvents.PERMISSION_PROMPT_IS_SHOWN event
@@ -95,7 +96,11 @@ var LibJitsiMeet = {
95 96
     init: function (options) {
96 97
         let logObject, attr;
97 98
         Statistics.init(options);
99
+
98 100
         this.analytics = Statistics.analytics;
101
+        if(options.enableAnalyticsLogging === true) {
102
+            this.analytics.init(RTCBrowserType.getBrowserName());
103
+        }
99 104
 
100 105
         if (options.enableWindowOnErrorHandler) {
101 106
             GlobalOnErrorHandler.addHandler(
@@ -339,6 +344,14 @@ var LibJitsiMeet = {
339 344
         Statistics.reportGlobalError(error);
340 345
     },
341 346
 
347
+    /**
348
+     * Returns current machine id saved from the local storage.
349
+     * @returns {string} the machine id
350
+     */
351
+    getMachineId: function() {
352
+        return Settings.getMachineId();
353
+    },
354
+
342 355
     /**
343 356
      * Represents a hub/namespace for utility functionality which may be of
344 357
      * interest to LibJitsiMeet clients.

+ 2
- 2
doc/API.md View File

@@ -51,8 +51,8 @@ The ```options``` parameter is JS object with the following properties:
51 51
     10. disableSimulcast - boolean property. Enables/disables simulcast.
52 52
     11. enableWindowOnErrorHandler - boolean property (default false). Enables/disables attaching global onerror handler (window.onerror).
53 53
     12. disableThirdPartyRequests - if true - callstats will be disabled and the callstats API won't be included.
54
-    13. analyticsScriptUrl - (optional) custom url to search for the analytics lib, if missing js file will be expected to be next to the library file (the location it is sourced from)
55
-    14. callStatsCustomScriptUrl - (optional) custom url to access callstats client script 
54
+    13. enableAnalyticsLogging - boolean property (default false). Enables/disables analytics logging.
55
+    14. callStatsCustomScriptUrl - (optional) custom url to access callstats client script
56 56
     15. callStatsConfIDNamespace - (optional) a namespace to prepend the callstats conference ID with. Defaults to the window.location.hostname
57 57
 
58 58
 * ```JitsiMeetJS.JitsiConnection``` - the ```JitsiConnection``` constructor. You can use that to create new server connection.

+ 84
- 79
modules/settings/Settings.js View File

@@ -1,5 +1,7 @@
1
-var logger = require("jitsi-meet-logger").getLogger(__filename);
2
-var UsernameGenerator = require('../util/UsernameGenerator');
1
+import {getLogger} from "jitsi-meet-logger";
2
+const logger = getLogger(__filename);
3
+
4
+import UsernameGenerator from "../util/UsernameGenerator";
3 5
 
4 6
 /**
5 7
  * Gets the localStorage of the browser. (Technically, gets the localStorage of
@@ -8,14 +10,15 @@ var UsernameGenerator = require('../util/UsernameGenerator');
8 10
  * @returns {Storage} the local Storage object (if any)
9 11
  */
10 12
 function getLocalStorage() {
11
-    var global = typeof window == 'undefined' ? this : window;
13
+    let global = typeof window == 'undefined' ? this : window;
12 14
     return global.localStorage;
13 15
 }
14 16
 
17
+function _p8() {
18
+    return (Math.random().toString(16) + "000000000").substr(2, 8);
19
+}
20
+
15 21
 function generateUniqueId() {
16
-    function _p8() {
17
-        return (Math.random().toString(16) + "000000000").substr(2, 8);
18
-    }
19 22
     return _p8() + _p8() + _p8() + _p8();
20 23
 }
21 24
 
@@ -24,7 +27,7 @@ function generateUniqueId() {
24 27
  * @returns {string} random unique id
25 28
  */
26 29
 function generateJitsiMeetId() {
27
-    var jitsiMeetId = generateUniqueId();
30
+    let jitsiMeetId = generateUniqueId();
28 31
     logger.log("generated id", jitsiMeetId);
29 32
 
30 33
     return jitsiMeetId;
@@ -35,90 +38,92 @@ function generateJitsiMeetId() {
35 38
  * @returns {string} fake random username
36 39
  */
37 40
 function generateCallStatsUsername() {
38
-    var username = UsernameGenerator.generateUsername();
41
+    let username = UsernameGenerator.generateUsername();
39 42
     logger.log('generated callstats uid', username);
40 43
 
41 44
     return username;
42 45
 }
43 46
 
44
-function Settings() {
45
-    this.userId;
46
-    this.callStatsUserName;
47
-
48
-    var localStorage = getLocalStorage();
49
-    if (localStorage) {
50
-        this.userId
51
-            = localStorage.getItem('jitsiMeetId') || generateJitsiMeetId();
52
-        this.callStatsUserName
53
-            = localStorage.getItem('callStatsUserName')
54
-                || generateCallStatsUsername();
55
-
56
-        this.save();
57
-    } else {
58
-        logger.log("localStorage is not supported");
59
-        this.userId = generateJitsiMeetId();
60
-        this.callStatsUserName = generateCallStatsUsername();
47
+class Settings {
48
+    constructor() {
49
+        this.userId;
50
+        this.callStatsUserName;
51
+
52
+        var localStorage = getLocalStorage();
53
+        if (localStorage) {
54
+            this.userId
55
+                = localStorage.getItem('jitsiMeetId') || generateJitsiMeetId();
56
+            this.callStatsUserName
57
+                = localStorage.getItem('callStatsUserName')
58
+                    || generateCallStatsUsername();
59
+
60
+            this.save();
61
+        } else {
62
+            logger.log("localStorage is not supported");
63
+            this.userId = generateJitsiMeetId();
64
+            this.callStatsUserName = generateCallStatsUsername();
65
+        }
61 66
     }
62
-}
63 67
 
64
-/**
65
- * Save settings to localStorage if browser supports that.
66
- */
67
-Settings.prototype.save = function () {
68
-    var localStorage = getLocalStorage();
69
-    if (localStorage) {
70
-        localStorage.setItem('jitsiMeetId', this.userId);
71
-        localStorage.setItem('callStatsUserName', this.callStatsUserName);
68
+    /**
69
+     * Save settings to localStorage if browser supports that.
70
+     */
71
+    save () {
72
+        var localStorage = getLocalStorage();
73
+        if (localStorage) {
74
+            localStorage.setItem('jitsiMeetId', this.userId);
75
+            localStorage.setItem('callStatsUserName', this.callStatsUserName);
76
+        }
72 77
     }
73
-};
74 78
 
75
-/**
76
- * Returns current user id.
77
- * @returns {string} user id
78
- */
79
-Settings.prototype.getUserId = function () {
80
-    return this.userId;
81
-};
79
+    /**
80
+     * Returns current machine id.
81
+     * @returns {string} machine id
82
+     */
83
+    getMachineId () {
84
+        return this.userId;
85
+    }
82 86
 
83
-/**
84
- * Returns fake username for callstats
85
- * @returns {string} fake username for callstats
86
- */
87
-Settings.prototype.getCallStatsUserName = function () {
88
-    return this.callStatsUserName;
89
-};
87
+    /**
88
+     * Returns fake username for callstats
89
+     * @returns {string} fake username for callstats
90
+     */
91
+    getCallStatsUserName () {
92
+        return this.callStatsUserName;
93
+    }
90 94
 
91
-/**
92
- * Save current session id.
93
- * @param {string} sessionId session id
94
- */
95
-Settings.prototype.setSessionId = function (sessionId) {
96
-    var localStorage = getLocalStorage();
97
-    if (localStorage) {
98
-        if (sessionId) {
99
-            localStorage.setItem('sessionId', sessionId);
100
-        } else {
101
-            localStorage.removeItem('sessionId');
95
+    /**
96
+     * Save current session id.
97
+     * @param {string} sessionId session id
98
+     */
99
+    setSessionId (sessionId) {
100
+        let localStorage = getLocalStorage();
101
+        if (localStorage) {
102
+            if (sessionId) {
103
+                localStorage.setItem('sessionId', sessionId);
104
+            } else {
105
+                localStorage.removeItem('sessionId');
106
+            }
102 107
         }
103 108
     }
104
-};
105 109
 
106
-/**
107
- * Clear current session id.
108
- */
109
-Settings.prototype.clearSessionId = function () {
110
-    this.setSessionId(undefined);
111
-};
110
+    /**
111
+     * Clear current session id.
112
+     */
113
+    clearSessionId () {
114
+        this.setSessionId(undefined);
115
+    }
112 116
 
113
-/**
114
- * Returns current session id.
115
- * @returns {string} current session id
116
- */
117
-Settings.prototype.getSessionId = function () {
118
-    // We may update sessionId in localStorage from another JitsiConference
119
-    // instance and that's why we should always re-read it.
120
-    var localStorage = getLocalStorage();
121
-    return localStorage ? localStorage.getItem('sessionId') : undefined;
122
-};
123
-
124
-module.exports = Settings;
117
+    /**
118
+     * Returns current session id.
119
+     * @returns {string} current session id
120
+     */
121
+    getSessionId () {
122
+        // We may update sessionId in localStorage from another JitsiConference
123
+        // instance and that's why we should always re-read it.
124
+        let localStorage = getLocalStorage();
125
+        return localStorage ? localStorage.getItem('sessionId') : undefined;
126
+    }
127
+}
128
+
129
+export default new Settings();

+ 92
- 82
modules/statistics/AnalyticsAdapter.js View File

@@ -1,100 +1,110 @@
1
-var RTCBrowserType = require("../RTC/RTCBrowserType");
1
+/**
2
+ * Interface for analytics handlers.
3
+ */
4
+class AnalyticsAbstract {
5
+    sendEvent() {}
6
+}
7
+
8
+/**
9
+ * Handler that caches all the events.
10
+ * @extends AnalyticsAbstract
11
+ */
12
+class CacheAnalytics extends AnalyticsAbstract {
13
+    constructor() {
14
+        super();
15
+        // some events may happen before init or implementation script download
16
+        // in this case we accumulate them in this array and send them on init
17
+        this.eventCache = [];
18
+    }
2 19
 
3
-function NoopAnalytics() {}
4
-NoopAnalytics.prototype.sendEvent = function () {};
20
+    /**
21
+     * Cache analytics event.
22
+     * @param {String} action the name of the event
23
+     * @param {Object} data can be any JSON object
24
+     */
25
+    sendEvent(action, data = {}) {
26
+        this.eventCache.push({
27
+            action: action,
28
+            data: data
29
+        });
30
+    }
5 31
 
6
-function AnalyticsAdapter() {
7
-    this.browserName = RTCBrowserType.getBrowserName();
8 32
     /**
9
-     * Map of properties that will be added to every event
33
+     * Clears the cached events.
34
+     * @returns {Array} with the cached events.
10 35
      */
11
-    this.permanentProperties = {};
36
+    drainCachedEvents() {
37
+        let eventCacheCopy = this.eventCache.slice();
38
+        this.eventCache = [];
39
+        return eventCacheCopy;
40
+    }
41
+
12 42
 }
13 43
 
14
-// some events may happen before init or implementation script download
15
-// in this case we accumulate them in this array and send them on init
16
-AnalyticsAdapter.eventsQueue = [];
44
+let cacheAnalytics = new CacheAnalytics();
17 45
 
18 46
 /**
19
- * Sends analytics event.
20
- * @param {String} action the name of the event
21
- * @param {Object} data can be any JSON object
47
+ * This class will store and manage the handlers that are going to be used.
22 48
  */
23
-AnalyticsAdapter.prototype.sendEvent = function (action, data = {}) {
24
-    if(this._checkAnalyticsAndMaybeCacheEvent(action, data)) {
25
-        data.browserName = this.browserName;
26
-        try {
27
-            this.analytics.sendEvent(action,
28
-                Object.assign({}, this.permanentProperties, data));
29
-        } catch (ignored) { // eslint-disable-line no-empty
30
-        }
31
-    }
32
-};
49
+class AnalyticsAdapter {
50
+    constructor() {
51
+        this.analyticsHandlers = new Set();
33 52
 
34
-/**
35
- * Since we asynchronously load the integration of the analytics API and the
36
- * analytics API may asynchronously load its implementation (e.g. Google
37
- * Analytics), we cannot make the decision with respect to which analytics
38
- * implementation we will use here and we have to postpone it i.e. we will make
39
- * a lazy decision, will wait for loaded or dispose methods to be called.
40
- * in the meantime we accumulate any events received. We should call this
41
- * method before trying to send the event.
42
- * @param action
43
- * @param data
44
- */
45
-AnalyticsAdapter.prototype._checkAnalyticsAndMaybeCacheEvent
46
-= function (action, data) {
47
-    if (this.analytics === null || typeof this.analytics === 'undefined') {
48
-        // missing this.analytics but have window implementation, let's use it
49
-        if (window.Analytics) {
50
-            this.loaded();
51
-        }
52
-        else {
53
-            AnalyticsAdapter.eventsQueue.push({
54
-                action: action,
55
-                data: data
56
-            });
57
-            // stored, lets break here
58
-            return false;
59
-        }
53
+        /**
54
+         * Map of properties that will be added to every event
55
+         */
56
+        this.permanentProperties = Object.create(null);
60 57
     }
61
-    return true;
62
-};
63 58
 
59
+    /**
60
+     * Initializes the AnalyticsAdapter. Adds the cacheAnalytics handler to
61
+     * cache all the events until we have other handlers that are going to send
62
+     * them.
63
+     */
64
+    init(browserName) {
65
+        this.browserName = browserName;
66
+        this.analyticsHandlers.add(cacheAnalytics);
67
+    }
64 68
 
65
-/**
66
- * Dispose analytics. Clears any available queue element and sets
67
- * NoopAnalytics to be used.
68
- */
69
-AnalyticsAdapter.prototype.dispose = function () {
70
-    this.analytics = new NoopAnalytics();
71
-    AnalyticsAdapter.eventsQueue.length = 0;
72
-};
73
-
74
-/**
75
- * Adds map of properties that will be added to every event.
76
- * @param {Object} properties the map of properties
77
- */
78
-AnalyticsAdapter.prototype.addPermanentProperties = function (properties) {
79
-    this.permanentProperties
80
-        = Object.assign(this.permanentProperties, properties);
81
-};
69
+    /**
70
+     * Sends analytics event.
71
+     * @param {String} action the name of the event
72
+     * @param {Object} data can be any JSON object
73
+     */
74
+    sendEvent(action, data = {}) {
75
+        let modifiedData = Object.assign(
76
+            {browserName: this.browserName}, this.permanentProperties, data);
77
+        this.analyticsHandlers.forEach(
78
+            analytics => analytics.sendEvent(action, modifiedData));
79
+    }
82 80
 
83
-/**
84
- * Loaded analytics script. Sens queued events.
85
- */
86
-AnalyticsAdapter.prototype.loaded = function () {
87
-    var AnalyticsImpl = window.Analytics || NoopAnalytics;
81
+    /**
82
+     * Dispose analytics. Clears all handlers.
83
+     */
84
+    dispose() {
85
+        cacheAnalytics.drainCachedEvents();
86
+        this.analyticsHandlers.clear();
87
+    }
88 88
 
89
-    this.analytics = new AnalyticsImpl();
89
+    /**
90
+     * Sets the handlers that are going to be used to send analytics and send
91
+     * the cached events.
92
+     * @param {Array} handlers the handlers
93
+     */
94
+    setAnalyticsHandlers (handlers) {
95
+        this.analyticsHandlers = new Set(handlers);
96
+        cacheAnalytics.drainCachedEvents().forEach(
97
+            ev => this.sendEvent(ev.action, ev.data));
98
+    }
90 99
 
91
-    // new analytics lets send all events if any
92
-    if (AnalyticsAdapter.eventsQueue.length) {
93
-        AnalyticsAdapter.eventsQueue.forEach(function (event) {
94
-            this.sendEvent(event.action, event.data);
95
-        }.bind(this));
96
-        AnalyticsAdapter.eventsQueue.length = 0;
100
+    /**
101
+     * Adds map of properties that will be added to every event.
102
+     * @param {Object} properties the map of properties
103
+     */
104
+    addPermanentProperties (properties) {
105
+        this.permanentProperties
106
+            = Object.assign(this.permanentProperties, properties);
97 107
     }
98
-};
108
+}
99 109
 
100
-module.exports = new AnalyticsAdapter();
110
+export default new AnalyticsAdapter();

+ 3
- 4
modules/statistics/CallStats.js View File

@@ -1,6 +1,7 @@
1 1
 /* global $, Strophe, callstats */
2 2
 var logger = require("jitsi-meet-logger").getLogger(__filename);
3 3
 var GlobalOnErrorHandler = require("../util/GlobalOnErrorHandler");
4
+import Settings from "../settings/Settings";
4 5
 
5 6
 var jsSHA = require('jssha');
6 7
 var io = require('socket.io-client');
@@ -138,11 +139,9 @@ function _try_catch (f) {
138 139
 /**
139 140
  * Creates new CallStats instance that handles all callstats API calls.
140 141
  * @param peerConnection {JingleSessionPC} the session object
141
- * @param Settings {Settings} the settings instance. Declared in
142
- * /modules/settings/Settings.js
143 142
  * @param options {object} credentials for callstats.
144 143
  */
145
-var CallStats = _try_catch(function(jingleSession, Settings, options) {
144
+var CallStats = _try_catch(function(jingleSession, options) {
146 145
     try{
147 146
         CallStats.feedbackEnabled = false;
148 147
         callStats = new callstats($, io, jsSHA); // eslint-disable-line new-cap
@@ -153,7 +152,7 @@ var CallStats = _try_catch(function(jingleSession, Settings, options) {
153 152
             aliasName: Strophe.getResourceFromJid(jingleSession.room.myroomjid),
154 153
             userName: Settings.getCallStatsUserName()
155 154
         };
156
-        
155
+
157 156
         // The confID is case sensitive!!!
158 157
         this.confID = options.callStatsConfIDNamespace + "/" + options.roomName;
159 158
 

+ 4
- 34
modules/statistics/statistics.js View File

@@ -1,5 +1,5 @@
1 1
 /* global require */
2
-var AnalyticsAdapter = require("./AnalyticsAdapter");
2
+import analytics from "./AnalyticsAdapter";
3 3
 var CallStats = require("./CallStats");
4 4
 var EventEmitter = require("events");
5 5
 import JitsiTrackError from "../../JitsiTrackError";
@@ -34,30 +34,6 @@ function loadCallStatsAPI(customScriptUrl) {
34 34
     // have loaded by the time we needed it (i.e. CallStats.init is invoked).
35 35
 }
36 36
 
37
-// Load the integration of a third-party analytics API such as Google Analytics.
38
-// Since we cannot guarantee the quality of the third-party service (e.g. their
39
-// server may take noticeably long time to respond), it is in our best interest
40
-// (in the sense that the intergration of the analytics API is important to us
41
-// but not enough to allow it to prevent people from joining a conference) to
42
-// download the API asynchronously. Additionally, Google Analytics will download
43
-// its implementation asynchronously anyway so it makes sense to append the
44
-// loading on our side rather than prepend it.
45
-function loadAnalytics(customScriptUrl) {
46
-    // if we have a custom script url passed as parameter we don't want to
47
-    // search it relatively near the library
48
-    ScriptUtil.loadScript(
49
-        customScriptUrl ? customScriptUrl : 'analytics.js',
50
-        /* async */ true,
51
-        /* prepend */ false,
52
-        /* relativeURL */ customScriptUrl ? false : true,
53
-        /* loadCallback */ function () {
54
-            Statistics.analytics.loaded();
55
-        },
56
-        /* errorCallback */ function () {
57
-            Statistics.analytics.dispose();
58
-        });
59
-}
60
-
61 37
 /**
62 38
  * callstats strips any additional fields from Error except for "name", "stack",
63 39
  * "message" and "constraintName". So we need to bundle additional information
@@ -100,10 +76,6 @@ Statistics.init = function (options) {
100 76
 
101 77
     Statistics.disableThirdPartyRequests = options.disableThirdPartyRequests;
102 78
 
103
-    if (Statistics.disableThirdPartyRequests !== true)
104
-        loadAnalytics(options.analyticsScriptUrl);
105
-    else // if not enable make sure we dispose any event that goes in the queue
106
-        Statistics.analytics.dispose();
107 79
 };
108 80
 
109 81
 function Statistics(xmpp, options) {
@@ -127,7 +99,7 @@ function Statistics(xmpp, options) {
127 99
 Statistics.audioLevelsEnabled = false;
128 100
 Statistics.audioLevelsInterval = 200;
129 101
 Statistics.disableThirdPartyRequests = false;
130
-Statistics.analytics = AnalyticsAdapter;
102
+Statistics.analytics = analytics;
131 103
 
132 104
 /**
133 105
  * Array of callstats instances. Used to call Statistics static methods and
@@ -222,14 +194,12 @@ Statistics.prototype.stopRemoteStats = function () {
222 194
 /**
223 195
  * Initializes the callstats.io API.
224 196
  * @param peerConnection {JingleSessionPC} the session object
225
- * @param Settings {Settings} the settings instance. Declared in
226
- * /modules/settings/Settings.js
227 197
  */
228
-Statistics.prototype.startCallStats = function (session, settings) {
198
+Statistics.prototype.startCallStats = function (session) {
229 199
     if(this.callStatsIntegrationEnabled && !this.callStatsStarted) {
230 200
         // Here we overwrite the previous instance, but it must be bound to
231 201
         // the new PeerConnection
232
-        this.callstats = new CallStats(session, settings, this.options);
202
+        this.callstats = new CallStats(session, this.options);
233 203
         Statistics.callsStatsInstances.push(this.callstats);
234 204
         this.callStatsStarted = true;
235 205
     }

+ 2
- 2
modules/xmpp/ChatRoom.js View File

@@ -61,7 +61,7 @@ function filterNodeFromPresenceJSON(pres, nodeName){
61 61
     return res;
62 62
 }
63 63
 
64
-function ChatRoom(connection, jid, password, XMPP, options, settings) {
64
+function ChatRoom(connection, jid, password, XMPP, options) {
65 65
     this.eventEmitter = new EventEmitter();
66 66
     this.xmpp = XMPP;
67 67
     this.connection = connection;
@@ -78,7 +78,7 @@ function ChatRoom(connection, jid, password, XMPP, options, settings) {
78 78
     this.noBridgeAvailable = false;
79 79
     this.options = options || {};
80 80
     this.moderator = new Moderator(this.roomjid, this.xmpp, this.eventEmitter,
81
-        settings, {connection: this.xmpp.options, conference: this.options});
81
+        {connection: this.xmpp.options, conference: this.options});
82 82
     this.initPresenceMap();
83 83
     this.session = null;
84 84
     this.lastPresences = {};

+ 32
- 50
modules/xmpp/moderator.js View File

@@ -5,6 +5,7 @@ var XMPPEvents = require("../../service/xmpp/XMPPEvents");
5 5
 var AuthenticationEvents
6 6
     = require("../../service/authentication/AuthenticationEvents");
7 7
 var GlobalOnErrorHandler = require("../util/GlobalOnErrorHandler");
8
+import Settings from "../settings/Settings";
8 9
 
9 10
 function createExpBackoffTimer(step) {
10 11
     var count = 1;
@@ -21,14 +22,13 @@ function createExpBackoffTimer(step) {
21 22
     };
22 23
 }
23 24
 
24
-function Moderator(roomName, xmpp, emitter, settings, options) {
25
+function Moderator(roomName, xmpp, emitter, options) {
25 26
     this.roomName = roomName;
26 27
     this.xmppService = xmpp;
27 28
     this.getNextTimeout = createExpBackoffTimer(1000);
28 29
     this.getNextErrorTimeout = createExpBackoffTimer(1000);
29 30
     // External authentication stuff
30 31
     this.externalAuthEnabled = false;
31
-    this.settings = settings;
32 32
     this.options = options;
33 33
 
34 34
     // Sip gateway can be enabled by configuring Jigasi host in config.js or
@@ -50,7 +50,7 @@ function Moderator(roomName, xmpp, emitter, settings, options) {
50 50
                     event.origin);
51 51
                 return;
52 52
             }
53
-            settings.setSessionId(event.data.sessionId);
53
+            Settings.setSessionId(event.data.sessionId);
54 54
             // After popup is closed we will authenticate
55 55
         }
56 56
     }
@@ -109,8 +109,8 @@ Moderator.prototype.createConferenceIq =  function () {
109 109
     var elem = $iq({to: this.getFocusComponent(), type: 'set'});
110 110
 
111 111
     // Session Id used for authentication
112
-    var sessionId = this.settings.getSessionId();
113
-    var machineUID = this.settings.getUserId();
112
+    var sessionId = Settings.getSessionId();
113
+    var machineUID = Settings.getMachineId();
114 114
 
115 115
     logger.info(
116 116
             "Session ID: " + sessionId + " machine UID: " + machineUID);
@@ -251,7 +251,7 @@ Moderator.prototype.parseSessionId =  function (resultIq) {
251 251
     var sessionId = $(resultIq).find('conference').attr('session-id');
252 252
     if (sessionId) {
253 253
         logger.info('Received sessionId:  ' + sessionId);
254
-        this.settings.setSessionId(sessionId);
254
+        Settings.setSessionId(sessionId);
255 255
     }
256 256
 };
257 257
 
@@ -307,15 +307,10 @@ Moderator.prototype.allocateConferenceFocus =  function (callback) {
307 307
     // Try to use focus user JID from the config
308 308
     this.setFocusUserJid(this.options.connection.focusUserJid);
309 309
     // Send create conference IQ
310
-    var self = this;
311 310
     this.connection.sendIQ(
312 311
         this.createConferenceIq(),
313
-        function (result) {
314
-            self._allocateConferenceFocusSuccess(result, callback);
315
-        },
316
-        function (error) {
317
-            self._allocateConferenceFocusError(error, callback);
318
-        });
312
+        result => this._allocateConferenceFocusSuccess(result, callback),
313
+        error => this._allocateConferenceFocusError(error, callback));
319 314
     // XXX We're pressed for time here because we're beginning a complex and/or
320 315
     // lengthy conference-establishment process which supposedly involves
321 316
     // multiple RTTs. We don't have the time to wait for Strophe to decide to
@@ -333,17 +328,15 @@ Moderator.prototype.allocateConferenceFocus =  function (callback) {
333 328
  * successful allocation of the conference focus
334 329
  */
335 330
 Moderator.prototype._allocateConferenceFocusError = function (error, callback) {
336
-    var self = this;
337
-
338 331
     // If the session is invalid, remove and try again without session ID to get
339 332
     // a new one
340 333
     var invalidSession = $(error).find('>error>session-invalid').length;
341 334
     if (invalidSession) {
342 335
         logger.info("Session expired! - removing");
343
-        self.settings.clearSessionId();
336
+        Settings.clearSessionId();
344 337
     }
345 338
     if ($(error).find('>error>graceful-shutdown').length) {
346
-        self.eventEmitter.emit(XMPPEvents.GRACEFUL_SHUTDOWN);
339
+        this.eventEmitter.emit(XMPPEvents.GRACEFUL_SHUTDOWN);
347 340
         return;
348 341
     }
349 342
     // Check for error returned by the reservation system
@@ -356,7 +349,7 @@ Moderator.prototype._allocateConferenceFocusError = function (error, callback) {
356 349
         if (errorTextNode) {
357 350
             errorMsg = errorTextNode.text();
358 351
         }
359
-        self.eventEmitter.emit(
352
+        this.eventEmitter.emit(
360 353
                 XMPPEvents.RESERVATION_ERROR, errorCode, errorMsg);
361 354
         return;
362 355
     }
@@ -364,43 +357,37 @@ Moderator.prototype._allocateConferenceFocusError = function (error, callback) {
364 357
     if ($(error).find('>error>not-authorized').length) {
365 358
         logger.warn("Unauthorized to start the conference", error);
366 359
         var toDomain = Strophe.getDomainFromJid(error.getAttribute('to'));
367
-        if (toDomain !== self.options.connection.hosts.anonymousdomain) {
360
+        if (toDomain !== this.options.connection.hosts.anonymousdomain) {
368 361
             //FIXME "is external" should come either from the focus or config.js
369
-            self.externalAuthEnabled = true;
362
+            this.externalAuthEnabled = true;
370 363
         }
371
-        self.eventEmitter.emit(
364
+        this.eventEmitter.emit(
372 365
                 XMPPEvents.AUTHENTICATION_REQUIRED,
373
-                function () {
374
-                    self.allocateConferenceFocus(callback);
375
-                });
366
+                () => this.allocateConferenceFocus(callback));
376 367
         return;
377 368
     }
378 369
     if(this.retries >= this.maxRetries) {
379
-        self.eventEmitter.emit(
370
+        this.eventEmitter.emit(
380 371
                 XMPPEvents.ALLOCATE_FOCUS_MAX_RETRIES_ERROR);
381 372
         return;
382 373
     }
383 374
     this.retries++;
384
-    var waitMs = self.getNextErrorTimeout();
375
+    var waitMs = this.getNextErrorTimeout();
385 376
     var errmsg = "Focus error, retry after "+ waitMs;
386 377
     GlobalOnErrorHandler.callErrorHandler(new Error(errmsg));
387 378
     logger.error(errmsg, error);
388 379
     // Show message
389
-    var focusComponent = self.getFocusComponent();
380
+    var focusComponent = this.getFocusComponent();
390 381
     var retrySec = waitMs / 1000;
391 382
     //FIXME: message is duplicated ? Do not show in case of session invalid
392 383
     // which means just a retry
393 384
     if (!invalidSession) {
394
-        self.eventEmitter.emit(
385
+        this.eventEmitter.emit(
395 386
                 XMPPEvents.FOCUS_DISCONNECTED, focusComponent, retrySec);
396 387
     }
397 388
     // Reset response timeout
398
-    self.getNextTimeout(true);
399
-    window.setTimeout(
400
-            function () {
401
-                self.allocateConferenceFocus(callback);
402
-            },
403
-            waitMs);
389
+    this.getNextTimeout(true);
390
+    window.setTimeout( () => this.allocateConferenceFocus(callback), waitMs);
404 391
 };
405 392
 
406 393
 /**
@@ -428,24 +415,19 @@ Moderator.prototype._allocateConferenceFocusSuccess = function (
428 415
     } else {
429 416
         var waitMs = this.getNextTimeout();
430 417
         logger.info("Waiting for the focus... " + waitMs);
431
-        var self = this;
432
-        window.setTimeout(
433
-                function () {
434
-                    self.allocateConferenceFocus(callback);
435
-                },
436
-                waitMs);
418
+        window.setTimeout(() => this.allocateConferenceFocus(callback),
419
+            waitMs);
437 420
     }
438 421
 };
439 422
 
440 423
 Moderator.prototype.authenticate = function () {
441
-    var self = this;
442
-    return new Promise(function (resolve, reject) {
443
-        self.connection.sendIQ(
444
-            self.createConferenceIq(),
445
-            function (result) {
446
-                self.parseSessionId(result);
424
+    return new Promise((resolve, reject) => {
425
+        this.connection.sendIQ(
426
+            this.createConferenceIq(),
427
+            result => {
428
+                this.parseSessionId(result);
447 429
                 resolve();
448
-            }, function (error) {
430
+            }, error => {
449 431
                 var code = $(error).find('>error').attr('code');
450 432
                 reject(error, code);
451 433
             }
@@ -469,7 +451,7 @@ Moderator.prototype._getLoginUrl = function (popup, urlCb, failureCb) {
469 451
     var attrs = {
470 452
         xmlns: 'http://jitsi.org/protocol/focus',
471 453
         room: this.roomName,
472
-        'machine-uid': this.settings.getUserId()
454
+        'machine-uid': Settings.getMachineId()
473 455
     };
474 456
     var str = 'auth url'; // for logger
475 457
     if (popup) {
@@ -511,7 +493,7 @@ Moderator.prototype.getPopupLoginUrl = function (urlCallback, failureCallback) {
511 493
 
512 494
 Moderator.prototype.logout =  function (callback) {
513 495
     var iq = $iq({to: this.getFocusComponent(), type: 'set'});
514
-    var sessionId = this.settings.getSessionId();
496
+    var sessionId = Settings.getSessionId();
515 497
     if (!sessionId) {
516 498
         callback();
517 499
         return;
@@ -528,7 +510,7 @@ Moderator.prototype.logout =  function (callback) {
528 510
                 logoutUrl = decodeURIComponent(logoutUrl);
529 511
             }
530 512
             logger.info("Log out OK, url: " + logoutUrl, result);
531
-            this.settings.clearSessionId();
513
+            Settings.clearSessionId();
532 514
             callback(logoutUrl);
533 515
         }.bind(this),
534 516
         function (error) {

+ 2
- 2
modules/xmpp/strophe.emuc.js View File

@@ -31,7 +31,7 @@ class MucConnectionPlugin extends ConnectionPlugin {
31 31
             'http://jitsi.org/jitmeet/audio', 'iq', 'set',null,null);
32 32
     }
33 33
 
34
-    createRoom (jid, password, options, settings) {
34
+    createRoom (jid, password, options) {
35 35
         const roomJid = Strophe.getBareJidFromJid(jid);
36 36
         if (this.rooms[roomJid]) {
37 37
             const errmsg = "You are already in the room!";
@@ -39,7 +39,7 @@ class MucConnectionPlugin extends ConnectionPlugin {
39 39
             throw new Error(errmsg);
40 40
         }
41 41
         this.rooms[roomJid] = new ChatRoom(this.connection, jid,
42
-            password, this.xmpp, options, settings);
42
+            password, this.xmpp, options);
43 43
         return this.rooms[roomJid];
44 44
     }
45 45
 

+ 2
- 3
modules/xmpp/xmpp.js View File

@@ -251,7 +251,7 @@ export default class XMPP {
251 251
         return this._connect(jid, password);
252 252
     }
253 253
 
254
-    createRoom (roomName, options, settings) {
254
+    createRoom (roomName, options) {
255 255
         // By default MUC nickname is the resource part of the JID
256 256
         let mucNickname = Strophe.getNodeFromJid(this.connection.jid);
257 257
         let roomjid = roomName  + "@" + this.options.hosts.muc + "/";
@@ -273,8 +273,7 @@ export default class XMPP {
273 273
 
274 274
         roomjid += mucNickname;
275 275
 
276
-        return this.connection.emuc.createRoom(roomjid, null, options,
277
-            settings);
276
+        return this.connection.emuc.createRoom(roomjid, null, options);
278 277
     }
279 278
 
280 279
     addListener (type, listener) {

Loading…
Cancel
Save