[RN] Support JSON Web Token (JWT)
Make 'Add jwt module to react' work on mobile.
This commit is contained in:
parent
ab5c2e9ded
commit
e6f6884c36
|
@ -1,9 +1,7 @@
|
|||
/* global config, createConnectionExternally */
|
||||
|
||||
import {
|
||||
getRoomName,
|
||||
parseURLParams
|
||||
} from '../react/features/base/config/functions';
|
||||
import getRoomName from '../react/features/base/config/getRoomName';
|
||||
import parseURLParams from '../react/features/base/config/parseURLParams';
|
||||
|
||||
/**
|
||||
* Implements external connect using createConnectionExternally function defined
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
declare var getConfigParamsFromUrl: Function;
|
||||
// XXX The function parseURLParams is exported by the feature base/config (as
|
||||
// defined in the terminology of react/). However, this file is (very likely)
|
||||
// bundled in external_api in addition to app.bundle and, consequently, it is
|
||||
// best to import as little as possible here (rather than the whole feature
|
||||
// base/config) in order to minimize the amount of source code bundled into
|
||||
// multiple bundles.
|
||||
import parseURLParams from '../../react/features/base/config/parseURLParams';
|
||||
|
||||
/**
|
||||
* JitsiMeetExternalAPI id - unique for a webpage.
|
||||
*/
|
||||
export const API_ID
|
||||
= typeof getConfigParamsFromUrl === 'function'
|
||||
? getConfigParamsFromUrl().jitsi_meet_external_api_id
|
||||
: undefined;
|
||||
= parseURLParams(window.location).jitsi_meet_external_api_id;
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
const logger = require("jitsi-meet-logger").getLogger(__filename);
|
||||
|
||||
var JSSHA = require('jssha');
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Looks for a list of possible BOSH addresses in 'config.boshList' and
|
||||
* sets the value of 'config.bosh' based on that list and 'roomName'.
|
||||
* @param config the configuration object.
|
||||
* @param roomName the name of the room/conference.
|
||||
*/
|
||||
chooseAddress: function(config, roomName) {
|
||||
if (!roomName || !config.boshList || !Array.isArray(config.boshList) ||
|
||||
!config.boshList.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// This implements the actual choice of an entry in the list based on
|
||||
// roomName. Please consider the implications for existing deployments
|
||||
// before introducing changes.
|
||||
var hash = (new JSSHA(roomName, 'TEXT')).getHash('SHA-1', 'HEX');
|
||||
var n = parseInt("0x"+hash.substr(-6));
|
||||
var idx = n % config.boshList.length;
|
||||
var attemptFirstAddress;
|
||||
|
||||
config.bosh = config.boshList[idx];
|
||||
logger.log('Setting config.bosh to ' + config.bosh +
|
||||
' (idx=' + idx + ')');
|
||||
|
||||
if (config.boshAttemptFirstList &&
|
||||
Array.isArray(config.boshAttemptFirstList) &&
|
||||
config.boshAttemptFirstList.length > 0) {
|
||||
|
||||
idx = n % config.boshAttemptFirstList.length;
|
||||
attemptFirstAddress = config.boshAttemptFirstList[idx];
|
||||
|
||||
if (attemptFirstAddress != config.bosh) {
|
||||
config.boshAttemptFirst = attemptFirstAddress;
|
||||
logger.log('Setting config.boshAttemptFirst=' +
|
||||
attemptFirstAddress + ' (idx=' + idx + ')');
|
||||
} else {
|
||||
logger.log('Not setting boshAttemptFirst, address matches.');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
|
@ -1,52 +0,0 @@
|
|||
/* global $, config, interfaceConfig */
|
||||
const logger = require("jitsi-meet-logger").getLogger(__filename);
|
||||
|
||||
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) {
|
||||
logger.info(
|
||||
"Send config request to " + endpoint + " for room: " + roomName);
|
||||
|
||||
|
||||
$.ajax(
|
||||
endpoint,
|
||||
{
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({"roomName": roomName}),
|
||||
dataType: 'json',
|
||||
error: function(jqXHR, textStatus, errorThrown) {
|
||||
logger.error("Get config error: ", jqXHR, errorThrown);
|
||||
var error = "Get config response status: " + textStatus;
|
||||
complete(false, error);
|
||||
},
|
||||
success: function(data) {
|
||||
try {
|
||||
configUtil.overrideConfigJSON(
|
||||
config, interfaceConfig, data);
|
||||
complete(true);
|
||||
return;
|
||||
} catch (exception) {
|
||||
logger.error("Parse config error: ", exception);
|
||||
complete(false, exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = HttpConfig;
|
|
@ -1,93 +0,0 @@
|
|||
/* global config, interfaceConfig, loggingConfig */
|
||||
|
||||
import { parseURLParams } from '../../react/features/base/config';
|
||||
|
||||
import configUtils from './Util';
|
||||
|
||||
const logger = require("jitsi-meet-logger").getLogger(__filename);
|
||||
|
||||
/**
|
||||
* URL params with this prefix should be merged to config.
|
||||
*/
|
||||
const CONFIG_PREFIX = 'config.';
|
||||
|
||||
/**
|
||||
* URL params with this prefix should be merged to interface config.
|
||||
*/
|
||||
const INTERFACE_CONFIG_PREFIX = 'interfaceConfig.';
|
||||
|
||||
/**
|
||||
* Config keys to be ignored.
|
||||
*
|
||||
* @type Set
|
||||
*/
|
||||
const KEYS_TO_IGNORE = new Set([
|
||||
'analyticsScriptUrls',
|
||||
'callStatsCustomScriptUrl'
|
||||
]);
|
||||
|
||||
/**
|
||||
* URL params with this prefix should be merged to logging config.
|
||||
*/
|
||||
const LOGGING_CONFIG_PREFIX = 'loggingConfig.';
|
||||
|
||||
/**
|
||||
* Convert 'URL_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"
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
export function setConfigParametersFromUrl() {
|
||||
// Parsing config params from URL hash.
|
||||
const params = parseURLParams(window.location);
|
||||
|
||||
const configJSON = {
|
||||
config: {},
|
||||
interfaceConfig: {},
|
||||
loggingConfig: {}
|
||||
};
|
||||
|
||||
for (const key in params) {
|
||||
if (typeof key === 'string') {
|
||||
let confObj = null;
|
||||
let confKey;
|
||||
|
||||
if (key.indexOf(CONFIG_PREFIX) === 0) {
|
||||
confObj = configJSON.config;
|
||||
confKey = key.substr(CONFIG_PREFIX.length);
|
||||
|
||||
} else if (key.indexOf(INTERFACE_CONFIG_PREFIX) === 0) {
|
||||
confObj = configJSON.interfaceConfig;
|
||||
confKey
|
||||
= key.substr(INTERFACE_CONFIG_PREFIX.length);
|
||||
} else if (key.indexOf(LOGGING_CONFIG_PREFIX) === 0) {
|
||||
confObj = configJSON.loggingConfig;
|
||||
confKey = key.substr(LOGGING_CONFIG_PREFIX.length);
|
||||
}
|
||||
|
||||
// prevent passing some parameters which can inject scripts
|
||||
if (confObj && !KEYS_TO_IGNORE.has(confKey)) {
|
||||
confObj[confKey] = params[key];
|
||||
}
|
||||
} else {
|
||||
logger.warn('Invalid config key: ', key);
|
||||
}
|
||||
}
|
||||
|
||||
configUtils.overrideConfigJSON(
|
||||
config, interfaceConfig, loggingConfig,
|
||||
configJSON);
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
const logger = require("jitsi-meet-logger").getLogger(__filename);
|
||||
|
||||
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 loggingConfig the logging config 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: {
|
||||
* // interface_config.js properties here
|
||||
* },
|
||||
* loggingConfig: {
|
||||
* // logging_config.js properties here
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
overrideConfigJSON: function (config,
|
||||
interfaceConfig, loggingConfig, newConfig) {
|
||||
var configRoot, key, value, confObj;
|
||||
for (configRoot in newConfig) {
|
||||
confObj = null;
|
||||
if (configRoot == "config") {
|
||||
confObj = config;
|
||||
} else if (configRoot == "interfaceConfig") {
|
||||
confObj = interfaceConfig;
|
||||
} else if (configRoot == "loggingConfig") {
|
||||
confObj = loggingConfig;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (key in newConfig[configRoot]) {
|
||||
value = newConfig[configRoot][key];
|
||||
if (confObj[key] && typeof confObj[key] !== typeof value) {
|
||||
logger.log("Overriding a " + configRoot +
|
||||
" property with a property of different type.");
|
||||
}
|
||||
logger.info("Overriding " + key + " with: " + value);
|
||||
confObj[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = ConfigUtil;
|
|
@ -18,7 +18,8 @@ import {
|
|||
* @returns {Function}
|
||||
*/
|
||||
export function appInit() {
|
||||
return (dispatch, getState) => init(getState());
|
||||
return (dispatch: Dispatch<*>, getState: Function) =>
|
||||
init(getState());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -31,7 +32,7 @@ export function appInit() {
|
|||
* @returns {Function}
|
||||
*/
|
||||
export function appNavigate(uri) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch: Dispatch<*>, getState: Function) => {
|
||||
const state = getState();
|
||||
const oldDomain = getDomain(state);
|
||||
const defaultURL = state['features/app'].app._getDefaultURL();
|
||||
|
@ -43,14 +44,12 @@ export function appNavigate(uri) {
|
|||
// If the specified URI does not identify a domain, use the app's
|
||||
// default.
|
||||
if (typeof domain === 'undefined') {
|
||||
domain
|
||||
= _parseURIString(defaultURL)
|
||||
.domain;
|
||||
domain = _parseURIString(defaultURL).domain;
|
||||
}
|
||||
|
||||
if (room) {
|
||||
const splitUrl = uri.split(domain);
|
||||
const urlWithoutDomain = splitUrl[splitUrl.length - 1];
|
||||
const splitURL = uri.split(domain);
|
||||
const urlWithoutDomain = splitURL[splitURL.length - 1];
|
||||
|
||||
urlObject = new URL(urlWithoutDomain, `https://${domain}`);
|
||||
}
|
||||
|
|
|
@ -1,72 +1,247 @@
|
|||
/* @flow */
|
||||
|
||||
declare var config: Object;
|
||||
import JSSHA from 'jssha';
|
||||
|
||||
import parseURLParams from './parseURLParams';
|
||||
|
||||
declare var $: Object;
|
||||
|
||||
/**
|
||||
* Builds and returns the room name.
|
||||
* The config keys to ignore because, for example, their values identify scripts
|
||||
* and it is not desireable to inject these through URL params.
|
||||
*
|
||||
* @returns {string}
|
||||
* @private
|
||||
* @type Array
|
||||
*/
|
||||
export function getRoomName(): ?string {
|
||||
const { getroomnode } = config;
|
||||
const path = window.location.pathname;
|
||||
let roomName;
|
||||
const _KEYS_TO_IGNORE = [
|
||||
'analyticsScriptUrls',
|
||||
'callStatsCustomScriptUrl'
|
||||
];
|
||||
|
||||
// Determine the room node from the URL.
|
||||
if (getroomnode && typeof getroomnode === 'function') {
|
||||
roomName = getroomnode.call(config, path);
|
||||
} else {
|
||||
// Fall back to the default strategy of making assumptions about how the
|
||||
// URL maps to the room (name). It currently assumes a deployment in
|
||||
// which the last non-directory component of the path (name) is the
|
||||
// room.
|
||||
roomName
|
||||
= path.substring(path.lastIndexOf('/') + 1).toLowerCase()
|
||||
|| undefined;
|
||||
const logger = require('jitsi-meet-logger').getLogger(__filename);
|
||||
|
||||
// XXX The functions getRoomName and parseURLParams are split out of
|
||||
// functions.js because they are bundled in both app.bundle and
|
||||
// do_external_connect, webpack 1 does not support tree shaking, and we don't
|
||||
// want all functions to be bundled in do_external_connect.
|
||||
export { default as getRoomName } from './getRoomName';
|
||||
export { parseURLParams };
|
||||
|
||||
/* eslint-disable no-shadow */
|
||||
|
||||
/**
|
||||
* Looks for a list of possible BOSH addresses in {@code config.boshList} and
|
||||
* sets the value of {@code config.bosh} based on that list and
|
||||
* {@code roomName}.
|
||||
*
|
||||
* @param {Object} config - The configuration object.
|
||||
* @param {string} roomName - The name of the room/conference.
|
||||
* @returns {void}
|
||||
*/
|
||||
export function chooseBOSHAddress(config: Object, roomName: string) {
|
||||
if (!roomName) {
|
||||
return;
|
||||
}
|
||||
|
||||
return roomName;
|
||||
const { boshList } = config;
|
||||
|
||||
if (!boshList || !Array.isArray(boshList) || !boshList.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// This implements the actual choice of an entry in the list based on
|
||||
// roomName. Please consider the implications for existing deployments
|
||||
// before introducing changes.
|
||||
const hash = (new JSSHA(roomName, 'TEXT')).getHash('SHA-1', 'HEX');
|
||||
const n = parseInt(hash.substr(-6), 16);
|
||||
let idx = n % boshList.length;
|
||||
|
||||
config.bosh = boshList[idx];
|
||||
logger.log(`Setting config.bosh to ${config.bosh} (idx=${idx})`);
|
||||
|
||||
const { boshAttemptFirstList } = config;
|
||||
|
||||
if (boshAttemptFirstList
|
||||
&& Array.isArray(boshAttemptFirstList)
|
||||
&& boshAttemptFirstList.length > 0) {
|
||||
idx = n % boshAttemptFirstList.length;
|
||||
|
||||
const attemptFirstAddress = boshAttemptFirstList[idx];
|
||||
|
||||
if (attemptFirstAddress === config.bosh) {
|
||||
logger.log('Not setting config.boshAttemptFirst, address matches.');
|
||||
} else {
|
||||
config.boshAttemptFirst = attemptFirstAddress;
|
||||
logger.log(
|
||||
`Setting config.boshAttemptFirst=${attemptFirstAddress} (idx=${
|
||||
idx})`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* eslint-enable no-shadow */
|
||||
|
||||
/**
|
||||
* Parses the parameters from the URL and returns them as a JS object.
|
||||
* Sends HTTP POST request to specified <tt>endpoint</tt>. In request the name
|
||||
* of the room is included in JSON format:
|
||||
* {
|
||||
* "rooomName": "someroom12345"
|
||||
* }.
|
||||
*
|
||||
* @param {string} url - URL to parse.
|
||||
* @param {boolean} dontParse - If false or undefined some transformations
|
||||
* (for parsing the value as JSON) are going to be executed.
|
||||
* @param {string} source - Values - "hash"/"search" if "search" the parameters
|
||||
* will parsed from location.search otherwise from location.hash.
|
||||
* @returns {Object}
|
||||
* @param {string} endpoint - The name of HTTP endpoint to which to send
|
||||
* the HTTP POST request.
|
||||
* @param {string} roomName - The name of the conference room for which config
|
||||
* is requested.
|
||||
* @param {Function} complete - The callback to invoke upon success or failure.
|
||||
* @returns {void}
|
||||
*/
|
||||
export function parseURLParams(
|
||||
url: URL,
|
||||
dontParse: boolean = false,
|
||||
source: string = 'hash'): Object {
|
||||
const paramStr = source === 'search' ? url.search : url.hash;
|
||||
const params = {};
|
||||
export function obtainConfig(
|
||||
endpoint: string,
|
||||
roomName: string,
|
||||
complete: Function) {
|
||||
logger.info(`Send config request to ${endpoint} for room: ${roomName}`);
|
||||
$.ajax(
|
||||
endpoint,
|
||||
{
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({ roomName }),
|
||||
dataType: 'json',
|
||||
method: 'POST',
|
||||
|
||||
// eslint-disable-next-line newline-per-chained-call
|
||||
paramStr && paramStr.substr(1).split('&').forEach(part => {
|
||||
const param = part.split('=');
|
||||
let value;
|
||||
error(jqXHR, textStatus, errorThrown) {
|
||||
logger.error('Get config error: ', jqXHR, errorThrown);
|
||||
complete(false, `Get config response status: ${textStatus}`);
|
||||
},
|
||||
success(data) {
|
||||
const { config, interfaceConfig, loggingConfig } = window;
|
||||
|
||||
try {
|
||||
value = param[1];
|
||||
if (!dontParse) {
|
||||
value
|
||||
= JSON.parse(
|
||||
decodeURIComponent(param[1]).replace(/\\&/, '&'));
|
||||
try {
|
||||
overrideConfigJSON(
|
||||
config, interfaceConfig, loggingConfig,
|
||||
data);
|
||||
complete(true);
|
||||
} catch (e) {
|
||||
logger.error('Parse config error: ', e);
|
||||
complete(false, e);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
const msg = `Failed to parse URL parameter value: ${String(value)}`;
|
||||
|
||||
console.warn(msg, e);
|
||||
window.onerror && window.onerror(msg, null, null, null, e);
|
||||
|
||||
return;
|
||||
}
|
||||
params[param[0]] = value;
|
||||
});
|
||||
|
||||
return params;
|
||||
);
|
||||
}
|
||||
|
||||
/* eslint-disable max-params, no-shadow */
|
||||
|
||||
/**
|
||||
* Overrides JSON properties in {@code config} and
|
||||
* {@code interfaceConfig} Objects with the values from {@code newConfig}.
|
||||
*
|
||||
* @param {Object} config - The config Object in which we'll be overriding
|
||||
* properties.
|
||||
* @param {Object} interfaceConfig - The interfaceConfig Object in which we'll
|
||||
* be overriding properties.
|
||||
* @param {Object} loggingConfig - The loggingConfig Object in which we'll be
|
||||
* overriding properties.
|
||||
* @param {Object} json - Object containing configuration properties.
|
||||
* Destination object is selected based on root property name:
|
||||
* {
|
||||
* config: {
|
||||
* // config.js properties here
|
||||
* },
|
||||
* interfaceConfig: {
|
||||
* // interface_config.js properties here
|
||||
* },
|
||||
* loggingConfig: {
|
||||
* // logging_config.js properties here
|
||||
* }
|
||||
* }.
|
||||
* @returns {void}
|
||||
*/
|
||||
export function overrideConfigJSON(
|
||||
config: Object, interfaceConfig: Object, loggingConfig: Object,
|
||||
json: Object) {
|
||||
for (const configName of Object.keys(json)) {
|
||||
let configObj;
|
||||
|
||||
if (configName === 'config') {
|
||||
configObj = config;
|
||||
} else if (configName === 'interfaceConfig') {
|
||||
configObj = interfaceConfig;
|
||||
} else if (configName === 'loggingConfig') {
|
||||
configObj = loggingConfig;
|
||||
}
|
||||
if (configObj) {
|
||||
const configJSON = json[configName];
|
||||
|
||||
for (const key of Object.keys(configJSON)) {
|
||||
const oldValue = configObj[key];
|
||||
const newValue = configJSON[key];
|
||||
|
||||
if (oldValue && typeof oldValue !== typeof newValue) {
|
||||
logger.log(
|
||||
`Overriding a ${configName
|
||||
} property with a property of different type.`);
|
||||
}
|
||||
logger.info(`Overriding ${key} with: ${newValue}`);
|
||||
configObj[key] = newValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* eslint-enable max-params, no-shadow */
|
||||
|
||||
/**
|
||||
* Converts 'URL_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"
|
||||
* }
|
||||
* }.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
export function setConfigFromURLParams() {
|
||||
const params = parseURLParams(window.location);
|
||||
|
||||
const { config, interfaceConfig, loggingConfig } = window;
|
||||
const json = {};
|
||||
|
||||
// TODO We're still in the middle ground between old Web with config,
|
||||
// interfaceConfig, and loggingConfig used via global variables and new Web
|
||||
// and mobile reading the respective values from the redux store. On React
|
||||
// Native there's no interfaceConfig at all yet and loggingConfig is not
|
||||
// loaded but there's a default value in the redux store.
|
||||
config && (json.config = {});
|
||||
interfaceConfig && (json.interfaceConfig = {});
|
||||
loggingConfig && (json.loggingConfig = {});
|
||||
|
||||
for (const param of Object.keys(params)) {
|
||||
const objEnd = param.indexOf('.');
|
||||
|
||||
if (objEnd !== -1) {
|
||||
const obj = param.substring(0, objEnd);
|
||||
|
||||
if (json.hasOwnProperty(obj)) {
|
||||
const key = param.substring(objEnd + 1);
|
||||
|
||||
// Prevent passing some parameters which can inject scripts.
|
||||
if (key && _KEYS_TO_IGNORE.indexOf(key) === -1) {
|
||||
json[obj][key] = params[param];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
overrideConfigJSON(config, interfaceConfig, loggingConfig, json);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/* @flow */
|
||||
|
||||
declare var config: Object;
|
||||
|
||||
/**
|
||||
* Builds and returns the room name.
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
export default function getRoomName(): ?string {
|
||||
const { getroomnode } = config;
|
||||
const path = window.location.pathname;
|
||||
let roomName;
|
||||
|
||||
// Determine the room node from the URL.
|
||||
if (getroomnode && typeof getroomnode === 'function') {
|
||||
roomName = getroomnode.call(config, path);
|
||||
} else {
|
||||
// Fall back to the default strategy of making assumptions about how the
|
||||
// URL maps to the room (name). It currently assumes a deployment in
|
||||
// which the last non-directory component of the path (name) is the
|
||||
// room.
|
||||
roomName
|
||||
= path.substring(path.lastIndexOf('/') + 1).toLowerCase()
|
||||
|| undefined;
|
||||
}
|
||||
|
||||
return roomName;
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/* @flow */
|
||||
|
||||
/**
|
||||
* Parses the parameters from the URL and returns them as a JS object.
|
||||
*
|
||||
* @param {string} url - URL to parse.
|
||||
* @param {boolean} dontParse - If false or undefined some transformations
|
||||
* (for parsing the value as JSON) are going to be executed.
|
||||
* @param {string} source - Values - "hash"/"search" if "search" the parameters
|
||||
* will parsed from location.search otherwise from location.hash.
|
||||
* @returns {Object}
|
||||
*/
|
||||
export default function parseURLParams(
|
||||
url: URL,
|
||||
dontParse: boolean = false,
|
||||
source: string = 'hash'): Object {
|
||||
const paramStr = source === 'search' ? url.search : url.hash;
|
||||
const params = {};
|
||||
|
||||
// eslint-disable-next-line newline-per-chained-call
|
||||
paramStr && paramStr.substr(1).split('&').forEach(part => {
|
||||
const param = part.split('=');
|
||||
const key = param[0];
|
||||
|
||||
if (!key) {
|
||||
return;
|
||||
}
|
||||
|
||||
let value;
|
||||
|
||||
try {
|
||||
value = param[1];
|
||||
if (!dontParse) {
|
||||
value
|
||||
= JSON.parse(decodeURIComponent(value).replace(/\\&/, '&'));
|
||||
}
|
||||
} catch (e) {
|
||||
const msg = `Failed to parse URL parameter value: ${String(value)}`;
|
||||
|
||||
console.warn(msg, e);
|
||||
window.onerror && window.onerror(msg, null, null, null, e);
|
||||
|
||||
return;
|
||||
}
|
||||
params[key] = value;
|
||||
});
|
||||
|
||||
return params;
|
||||
}
|
|
@ -21,11 +21,12 @@ export function connect() {
|
|||
return (dispatch: Dispatch<*>, getState: Function) => {
|
||||
const state = getState();
|
||||
const { options } = state['features/base/connection'];
|
||||
const { issuer, jwt } = state['features/jwt'];
|
||||
const { room } = state['features/base/conference'];
|
||||
const connection
|
||||
= new JitsiMeetJS.JitsiConnection(
|
||||
options.appId,
|
||||
options.token,
|
||||
jwt && issuer && issuer !== 'anonymous' ? jwt : undefined,
|
||||
{
|
||||
...options,
|
||||
bosh:
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import { loadScript } from '../../base/util';
|
||||
/* @flow */
|
||||
|
||||
import {
|
||||
setConfigParametersFromUrl
|
||||
} from '../../../../modules/config/URLProcessor';
|
||||
import { setConfigFromURLParams } from '../../base/config';
|
||||
import { loadScript } from '../../base/util';
|
||||
|
||||
import JitsiMeetJS from './_';
|
||||
|
||||
|
@ -10,6 +9,28 @@ declare var APP: Object;
|
|||
|
||||
const JitsiConnectionErrors = JitsiMeetJS.errors.connection;
|
||||
|
||||
/**
|
||||
* Creates a JitsiLocalTrack model from the given device id.
|
||||
*
|
||||
* @param {string} type - The media type of track being created. Expected values
|
||||
* are "video" or "audio".
|
||||
* @param {string} deviceId - The id of the target media source.
|
||||
* @returns {Promise<JitsiLocalTrack>}
|
||||
*/
|
||||
export function createLocalTrack(type: string, deviceId: string) {
|
||||
return (
|
||||
JitsiMeetJS.createLocalTracks({
|
||||
cameraDeviceId: deviceId,
|
||||
devices: [ type ],
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
firefox_fake_device:
|
||||
window.config && window.config.firefox_fake_device,
|
||||
micDeviceId: deviceId
|
||||
})
|
||||
.then(([ jitsiLocalTrack ]) => jitsiLocalTrack));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a specific JitsiConnectionErrors instance indicates a
|
||||
* fatal JitsiConnection error.
|
||||
|
@ -38,56 +59,43 @@ export function isFatalJitsiConnectionError(error: string) {
|
|||
* @returns {Promise<Object>}
|
||||
*/
|
||||
export function loadConfig(host: string, path: string = '/config.js') {
|
||||
// Returns config.js file from global scope. We can't use the version that's
|
||||
// being used for the React Native app because the old/current Web app uses
|
||||
// config from the global scope.
|
||||
if (typeof APP !== 'undefined') {
|
||||
// FIXME The following call to setConfigParametersFromUrl is bad design
|
||||
// but URLProcessor still deals with the global variables config,
|
||||
// interfaceConfig, and loggingConfig and loadConfig. As the latter will
|
||||
// surely change in the future, so will the former then.
|
||||
setConfigParametersFromUrl();
|
||||
let promise;
|
||||
|
||||
return Promise.resolve(window.config);
|
||||
if (typeof APP === 'undefined') {
|
||||
promise
|
||||
= loadScript(new URL(path, host).toString())
|
||||
.then(() => {
|
||||
const { config } = window;
|
||||
|
||||
// We don't want to pollute global scope.
|
||||
window.config = undefined;
|
||||
|
||||
if (typeof config !== 'object') {
|
||||
throw new Error('window.config is not an object');
|
||||
}
|
||||
|
||||
return config;
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(`Failed to load ${path} from ${host}`, err);
|
||||
|
||||
throw err;
|
||||
});
|
||||
} else {
|
||||
// Return config.js file from global scope. We can't use the version
|
||||
// that's being used for the React Native app because the old/current
|
||||
// Web app uses config from the global scope.
|
||||
promise = Promise.resolve(window.config);
|
||||
}
|
||||
|
||||
return loadScript(new URL(path, host).toString())
|
||||
.then(() => {
|
||||
const config = window.config;
|
||||
// FIXME It's neither here nor there at the time of this writing where
|
||||
// config, interfaceConfig, and loggingConfig should be overwritten by URL
|
||||
// params.
|
||||
promise = promise.then(value => {
|
||||
setConfigFromURLParams();
|
||||
|
||||
// We don't want to pollute global scope.
|
||||
window.config = undefined;
|
||||
return value;
|
||||
});
|
||||
|
||||
if (typeof config !== 'object') {
|
||||
throw new Error('window.config is not an object');
|
||||
}
|
||||
|
||||
return config;
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(`Failed to load ${path} from ${host}`, err);
|
||||
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JitsiLocalTrack model from the given device id.
|
||||
*
|
||||
* @param {string} type - The media type of track being created. Expected values
|
||||
* are "video" or "audio".
|
||||
* @param {string} deviceId - The id of the target media source.
|
||||
* @returns {Promise<JitsiLocalTrack>}
|
||||
*/
|
||||
export function createLocalTrack(type, deviceId) {
|
||||
return JitsiMeetJS.createLocalTracks({
|
||||
cameraDeviceId: deviceId,
|
||||
devices: [ type ],
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
firefox_fake_device:
|
||||
window.config && window.config.firefox_fake_device,
|
||||
micDeviceId: deviceId
|
||||
})
|
||||
.then(([ jitsiLocalTrack ]) => jitsiLocalTrack);
|
||||
return promise;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
/* global APP, config */
|
||||
|
||||
import BoshAddressChoice from '../../../modules/config/BoshAddressChoice';
|
||||
import HttpConfigFetch from '../../../modules/config/HttpConfigFetch';
|
||||
import ConferenceUrl from '../../../modules/URL/ConferenceUrl';
|
||||
|
||||
import { chooseBOSHAddress, obtainConfig } from '../base/config';
|
||||
import { RouteRegistry } from '../base/react';
|
||||
|
||||
import { Conference } from './components';
|
||||
|
@ -47,15 +46,11 @@ function _initConference() {
|
|||
* @returns {Promise}
|
||||
*/
|
||||
function _obtainConfig(location, room) {
|
||||
return new Promise((resolve, reject) => {
|
||||
HttpConfigFetch.obtainConfig(location, room, (success, error) => {
|
||||
if (success) {
|
||||
resolve();
|
||||
} else {
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
});
|
||||
return new Promise((resolve, reject) =>
|
||||
obtainConfig(location, room, (success, error) => {
|
||||
success ? resolve() : reject(error);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -87,7 +82,7 @@ function _obtainConfigAndInit() {
|
|||
null, 'dialog.connectError', err);
|
||||
});
|
||||
} else {
|
||||
BoshAddressChoice.chooseAddress(config, room);
|
||||
chooseBOSHAddress(config, room);
|
||||
_initConference();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue