2016-11-16 21:02:32 +00:00
|
|
|
/* global JitsiMeetJS, config, APP */
|
2017-04-21 10:00:50 +00:00
|
|
|
|
2016-11-16 21:02:32 +00:00
|
|
|
/**
|
|
|
|
* Load the integration of a third-party analytics API such as Google
|
|
|
|
* Analytics. Since we cannot guarantee the quality of the third-party service
|
|
|
|
* (e.g. their server may take noticeably long time to respond), it is in our
|
2017-07-05 21:07:16 +00:00
|
|
|
* best interest (in the sense that the integration of the analytics API is
|
2016-11-16 21:02:32 +00:00
|
|
|
* important to us but not enough to allow it to prevent people from joining
|
|
|
|
* a conference) to download the API asynchronously. Additionally, Google
|
|
|
|
* Analytics will download its implementation asynchronously anyway so it makes
|
|
|
|
* sense to append the loading on our side rather than prepend it.
|
|
|
|
* @param {string} url the url to be loaded
|
|
|
|
* @returns {Promise} resolved with no arguments when the script is loaded and
|
|
|
|
* rejected with the error from JitsiMeetJS.ScriptUtil.loadScript method
|
|
|
|
*/
|
|
|
|
function loadScript(url) {
|
|
|
|
return new Promise((resolve, reject) =>
|
|
|
|
JitsiMeetJS.util.ScriptUtil.loadScript(
|
|
|
|
url,
|
|
|
|
/* async */ true,
|
|
|
|
/* prepend */ false,
|
|
|
|
/* relativeURL */ false,
|
|
|
|
/* loadCallback */ () => resolve(),
|
|
|
|
/* errorCallback */ error => reject(error)));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handles the initialization of analytics.
|
|
|
|
*/
|
|
|
|
class Analytics {
|
|
|
|
constructor() {
|
|
|
|
this._scriptURLs = Array.isArray(config.analyticsScriptUrls)
|
|
|
|
? config.analyticsScriptUrls : [];
|
|
|
|
this._enabled = !!this._scriptURLs.length
|
|
|
|
&& !config.disableThirdPartyRequests;
|
|
|
|
window.analyticsHandlers = [];
|
|
|
|
const machineId = JitsiMeetJS.getMachineId();
|
|
|
|
this._handlerConstructorOptions = {
|
|
|
|
product: "lib-jitsi-meet",
|
|
|
|
version: JitsiMeetJS.version,
|
|
|
|
session: machineId,
|
|
|
|
user: "uid-" + machineId
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns whether analytics is enabled or not.
|
|
|
|
* @returns {boolean} whether analytics is enabled or not.
|
|
|
|
*/
|
|
|
|
isEnabled() {
|
|
|
|
return this._enabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Tries to load the scripts for the analytics handlers.
|
|
|
|
* @returns {Promise} resolves with the handlers that have been
|
|
|
|
* successfully loaded and rejects if there are no handlers loaded or the
|
|
|
|
* analytics is disabled.
|
|
|
|
*/
|
|
|
|
_loadHandlers() {
|
|
|
|
if(!this.isEnabled()) {
|
|
|
|
return Promise.reject(new Error("Analytics is disabled!"));
|
|
|
|
}
|
|
|
|
let handlersPromises = [];
|
|
|
|
this._scriptURLs.forEach(url =>
|
|
|
|
handlersPromises.push(
|
|
|
|
loadScript(url).then(
|
|
|
|
() => {
|
|
|
|
return {type: "success"};
|
|
|
|
},
|
|
|
|
error => {
|
|
|
|
return {type: "error", error, url};
|
|
|
|
}))
|
|
|
|
);
|
|
|
|
return new Promise((resolve, reject) =>
|
|
|
|
{
|
|
|
|
Promise.all(handlersPromises).then(values => {
|
|
|
|
values.forEach(el => {
|
|
|
|
if(el.type === "error") {
|
2017-07-05 21:07:16 +00:00
|
|
|
console.log("Failed to load " + el.url);
|
2016-11-16 21:02:32 +00:00
|
|
|
console.error(el.error);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
if(window.analyticsHandlers.length === 0) {
|
|
|
|
reject(new Error("No analytics handlers available"));
|
|
|
|
} else {
|
|
|
|
let handlerInstances = [];
|
|
|
|
window.analyticsHandlers.forEach(
|
|
|
|
Handler => handlerInstances.push(
|
|
|
|
new Handler(this._handlerConstructorOptions)));
|
|
|
|
resolve(handlerInstances);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Loads the analytics scripts and inits JitsiMeetJS.analytics by setting
|
|
|
|
* permanent properties and setting the handlers from the loaded scripts.
|
|
|
|
* NOTE: Has to be used after JitsiMeetJS.init. Otherwise analytics will be
|
|
|
|
* null.
|
|
|
|
*/
|
|
|
|
init() {
|
2017-04-21 10:00:50 +00:00
|
|
|
const { analytics } = JitsiMeetJS;
|
|
|
|
|
|
|
|
if (!this.isEnabled() || !analytics)
|
2016-11-16 21:02:32 +00:00
|
|
|
return;
|
|
|
|
|
2017-04-21 10:00:50 +00:00
|
|
|
this._loadHandlers().then(
|
|
|
|
handlers => {
|
|
|
|
const permanentProperties = {
|
|
|
|
roomName: APP.conference.roomName,
|
|
|
|
userAgent: navigator.userAgent
|
2016-11-16 21:02:32 +00:00
|
|
|
};
|
2017-04-21 10:00:50 +00:00
|
|
|
|
|
|
|
const { group, server } = APP.store.getState()['features/jwt'];
|
|
|
|
|
|
|
|
if (server) {
|
2016-11-16 21:02:32 +00:00
|
|
|
permanentProperties.server = server;
|
|
|
|
}
|
2017-04-21 10:00:50 +00:00
|
|
|
if (group) {
|
2016-11-16 21:02:32 +00:00
|
|
|
permanentProperties.group = group;
|
|
|
|
}
|
2017-07-05 21:07:16 +00:00
|
|
|
// optionally include local deployment information based on
|
|
|
|
// the contents of window.config.deploymentInfo
|
|
|
|
if (config.deploymentInfo) {
|
2017-07-05 21:31:50 +00:00
|
|
|
for (let key in config.deploymentInfo) {
|
|
|
|
if (config.deploymentInfo.hasOwnProperty(key)) {
|
|
|
|
permanentProperties[key]
|
|
|
|
= config.deploymentInfo[key];
|
|
|
|
}
|
2017-05-30 18:37:43 +00:00
|
|
|
}
|
|
|
|
}
|
2017-04-21 10:00:50 +00:00
|
|
|
|
2016-11-16 21:02:32 +00:00
|
|
|
analytics.addPermanentProperties(permanentProperties);
|
|
|
|
analytics.setAnalyticsHandlers(handlers);
|
2017-04-21 10:00:50 +00:00
|
|
|
},
|
|
|
|
error => analytics.dispose() && console.error(error));
|
2016-11-16 21:02:32 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export default new Analytics();
|