Implements HTTP POST query for fetching app configuration.

This commit is contained in:
paweldomas 2015-08-21 14:33:05 +02:00
parent 7b35dd89bb
commit a7048fba06
10 changed files with 226 additions and 64 deletions

33
app.js
View File

@ -16,6 +16,7 @@ var APP =
this.settings = require("./modules/settings/Settings");
this.DTMF = require("./modules/DTMF/DTMF");
this.members = require("./modules/members/MemberList");
this.configFetch = require("./modules/config/HttpConfigFetch");
}
};
@ -30,10 +31,38 @@ function init() {
APP.members.start();
}
/**
* If we have HTTP endpoint for getting confgi.json configured we're going to
* read it and override properties from config.js and interfaceConfig.js.
* If there is no endpoint we'll just continue with initialization.
* Keep in mind that if the endpoint has been configured and we fail to obtain
* the config for any reason then the conference won't start and error message
* will be displayed to the user.
*/
function obtainConfigAndInit() {
if (config.configLocation) {
APP.configFetch.obtainConfig(
config.configLocation, APP.UI.getRoomNode(),
// Get config result callback
function(success, error) {
if (success) {
init();
} else {
// Show obtain config error,
// pass the error object for report
APP.UI.messageHandler.openReportDialog(
null, "dialog.connectError", error);
}
});
} else {
init();
}
}
$(document).ready(function () {
var URLProcessor = require("./modules/URLProcessor/URLProcessor");
var URLProcessor = require("./modules/config/URLProcessor");
URLProcessor.setConfigParametersFromUrl();
APP.init();
@ -42,7 +71,7 @@ $(document).ready(function () {
if(APP.API.isEnabled())
APP.API.init();
APP.UI.start(init);
APP.UI.start(obtainConfigAndInit);
});

View File

@ -1,4 +1,5 @@
var config = {
// configLocation: './config.json', // see ./modules/HttpConfigFetch.js
hosts: {
domain: 'jitsi-meet.example.com',
//anonymousdomain: 'guest.example.com',

View File

@ -33,6 +33,7 @@ var UIEvents = require("../../service/UI/UIEvents");
var MemberEvents = require("../../service/members/Events");
var eventEmitter = new EventEmitter();
var roomNode = null;
var roomName = null;
@ -684,17 +685,16 @@ UI.getLargeVideoResource = function () {
return VideoLayout.getLargeVideoResource();
};
UI.generateRoomName = function() {
if(roomName)
return roomName;
var roomnode = null;
UI.getRoomNode = function () {
if (roomNode)
return roomNode;
var path = window.location.pathname;
// determinde the room node from the url
// TODO: just the roomnode or the whole bare jid?
if (config.getroomnode && typeof config.getroomnode === 'function') {
// custom function might be responsible for doing the pushstate
roomnode = config.getroomnode(path);
roomNode = config.getroomnode(path);
} else {
/* fall back to default strategy
* this is making assumptions about how the URL->room mapping happens.
@ -705,17 +705,22 @@ UI.generateRoomName = function() {
}
*/
if (path.length > 1) {
roomnode = path.substr(1).toLowerCase();
roomNode = path.substr(1).toLowerCase();
} else {
var word = RoomNameGenerator.generateRoomWithoutSeparator();
roomnode = word.toLowerCase();
roomNode = word.toLowerCase();
window.history.pushState('VideoChat',
'Room: ' + word, window.location.pathname + word);
'Room: ' + word, window.location.pathname + word);
}
}
return roomNode;
};
roomName = roomnode + '@' + config.hosts.muc;
UI.generateRoomName = function () {
if (roomName)
return roomName;
var roomNode = UI.getRoomNode();
roomName = roomNode + '@' + config.hosts.muc;
return roomName;
};

View File

@ -1,50 +0,0 @@
/* global $, $iq, config, interfaceConfig */
var params = {};
function getConfigParamsFromUrl() {
if(!location.hash)
return {};
var hash = location.hash.substr(1);
var result = {};
hash.split("&").forEach(function(part) {
var item = part.split("=");
result[item[0]] = JSON.parse(
decodeURIComponent(item[1]).replace(/\\&/, "&"));
});
return result;
}
params = getConfigParamsFromUrl();
var URLProcessor = {
setConfigParametersFromUrl: function () {
for(var key in params) {
if(typeof key !== "string")
continue;
var confObj = null, confKey;
if (key.indexOf("config.") === 0) {
confObj = config;
confKey = key.substr("config.".length);
} else if (key.indexOf("interfaceConfig.") === 0) {
confObj = interfaceConfig;
confKey = key.substr("interfaceConfig.".length);
}
if (!confObj)
continue;
var value = params[key];
if (confObj[confKey] && typeof confObj[confKey] !== typeof value)
{
console.warn("The type of " + key +
" is wrong. That parameter won't be updated in config.js.");
continue;
}
confObj[confKey] = value;
}
}
};
module.exports = URLProcessor;

View File

@ -0,0 +1,55 @@
/* global $, $iq, config, interfaceConfig */
var configUtil = require('./Util');
var HttpConfig = {
/**
* Sends HTTP POST request to specified <tt>endpoint</tt>. In request
* the name of the room is included in JSON format:
* {
* "rooomName": "someroom12345"
* }
* @param endpoint the name of HTTP endpoint to which HTTP POST request will
* be sent.
* @param roomName the name of the conference room for which config will be
* requested.
* @param complete
*/
obtainConfig: function (endpoint, roomName, complete) {
console.info(
"Send config request to " + endpoint + " for room: " + roomName);
var request = new XMLHttpRequest();
var error = null;
request.onreadystatechange = function (aEvt) {
if (request.readyState == 4) {
var status = request.status;
if (status === 200) {
try {
var data = JSON.parse(request.responseText);
configUtil.overrideConfigJSON(
config, interfaceConfig, data);
complete(true);
return;
} catch (exception) {
console.error("Parse config error: ", exception);
error = exception;
}
} else {
console.error("Get config error: ", request, status);
error = "Get config response status: " + status;
}
complete(false, error);
}
};
request.open("POST", endpoint, true);
request.setRequestHeader(
"Content-Type", "application/json;charset=UTF-8");
request.send({ "roomName": roomName });
}
};
module.exports = HttpConfig;

View File

@ -0,0 +1,65 @@
/* global $, $iq, config, interfaceConfig */
var configUtils = require('./Util');
var params = {};
function getConfigParamsFromUrl() {
if (!location.hash)
return {};
var hash = location.hash.substr(1);
var result = {};
hash.split("&").forEach(function (part) {
var item = part.split("=");
result[item[0]] = JSON.parse(
decodeURIComponent(item[1]).replace(/\\&/, "&"));
});
return result;
}
params = getConfigParamsFromUrl();
var URLProcessor = {
setConfigParametersFromUrl: function () {
// Convert 'params' to JSON object
// We have:
// {
// "config.disableAudioLevels": false,
// "config.channelLastN": -1,
// "interfaceConfig.APP_NAME": "Jitsi Meet"
// }
// We want to have:
// {
// "config": {
// "disableAudioLevels": false,
// "channelLastN": -1
// },
// interfaceConfig: {
// APP_NAME: "Jitsi Meet"
// }
// }
var configJSON = {
config: {},
interfaceConfig: {}
};
for (var key in params) {
if (typeof key !== "string") {
console.warn("Invalid config key: ", key);
continue;
}
var confObj = null, confKey;
if (key.indexOf("config.") === 0) {
confObj = configJSON.config;
confKey = key.substr("config.".length);
} else if (key.indexOf("interfaceConfig.") === 0) {
confObj = configJSON.interfaceConfig;
confKey = key.substr("interfaceConfig.".length);
}
if (!confObj)
continue;
confObj[confKey] = params[key];
}
configUtils.overrideConfigJSON(config, interfaceConfig, configJSON);
}
};
module.exports = URLProcessor;

49
modules/config/Util.js Normal file
View File

@ -0,0 +1,49 @@
/* global $ */
var ConfigUtil = {
/**
* Method overrides JSON properties in <tt>config</tt> and
* <tt>interfaceConfig</tt> Objects with the values from <tt>newConfig</tt>
* @param config the config object for which we'll be overriding properties
* @param interfaceConfig the interfaceConfig object for which we'll be
* overriding properties.
* @param newConfig object containing configuration properties. Destination
* object is selected based on root property name:
* {
* config: {
* // config.js properties to be
* },
* interfaceConfig: {
* // interfaceConfig.js properties here
* }
* }
*/
overrideConfigJSON: function (config, interfaceConfig, newConfig) {
for (var configRoot in newConfig) {
var confObj = null;
if (configRoot == "config") {
confObj = config;
} else if (configRoot == "interfaceConfig") {
confObj = interfaceConfig;
} else {
continue;
}
for (var key in newConfig[configRoot]) {
var value = newConfig[configRoot][key];
if (confObj[key] && typeof confObj[key] !== typeof value)
{
console.warn(
"The type of " + key +
" is wrong. That parameter won't be updated in: ",
confObj);
continue;
}
console.info("Overriding " + key + " with: " + value);
confObj[key] = value;
}
}
}
};
module.exports = ConfigUtil;

View File

@ -35,7 +35,7 @@ var externalAuthEnabled = false;
// Sip gateway can be enabled by configuring Jigasi host in config.js or
// it will be enabled automatically if focus detects the component through
// service discovery.
var sipGatewayEnabled = config.hosts.call_control !== undefined;
var sipGatewayEnabled;
var eventEmitter = null;
@ -65,6 +65,9 @@ var Moderator = {
this.xmppService = xmpp;
eventEmitter = emitter;
sipGatewayEnabled =
config.hosts && config.hosts.call_control !== undefined;
// Message listener that talks to POPUP window
function listener(event) {
if (event.data && event.data.sessionId) {

View File

@ -10,7 +10,7 @@ var recordingEnabled;
* Whether to use a jirecon component for recording, or use the videobridge
* through COLIBRI.
*/
var useJirecon = (typeof config.hosts.jirecon != "undefined");
var useJirecon;
/**
* The ID of the jirecon recording session. Jirecon generates it when we
@ -109,6 +109,10 @@ function setRecording(state, token, callback, connection) {
}
var Recording = {
init: function () {
useJirecon = config.hosts &&
(typeof config.hosts.jirecon != "undefined");
},
toggleRecording: function (tokenEmptyCallback, recordingStateChangeCallback, connection) {
if (!Moderator.isModerator()) {
console.log(

View File

@ -270,6 +270,7 @@ var XMPP = {
initStrophePlugins();
registerListeners();
Moderator.init(this, eventEmitter);
Recording.init();
var configDomain = config.hosts.anonymousdomain || config.hosts.domain;
// Force authenticated domain if room is appended with '?login=true'
if (config.hosts.anonymousdomain &&