diff --git a/connection_optimization/do_external_connect.js b/connection_optimization/do_external_connect.js index c1d32c988..2ce15f02d 100644 --- a/connection_optimization/do_external_connect.js +++ b/connection_optimization/do_external_connect.js @@ -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 diff --git a/modules/API/constants.js b/modules/API/constants.js index 6f2c592da..600dfc323 100644 --- a/modules/API/constants.js +++ b/modules/API/constants.js @@ -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; diff --git a/modules/config/BoshAddressChoice.js b/modules/config/BoshAddressChoice.js deleted file mode 100644 index 1a4ec4b95..000000000 --- a/modules/config/BoshAddressChoice.js +++ /dev/null @@ -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.'); - } - } - } -}; diff --git a/modules/config/HttpConfigFetch.js b/modules/config/HttpConfigFetch.js deleted file mode 100644 index 0c7a59884..000000000 --- a/modules/config/HttpConfigFetch.js +++ /dev/null @@ -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 endpoint. 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; diff --git a/modules/config/URLProcessor.js b/modules/config/URLProcessor.js deleted file mode 100644 index 23c0c40e8..000000000 --- a/modules/config/URLProcessor.js +++ /dev/null @@ -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); -} diff --git a/modules/config/Util.js b/modules/config/Util.js deleted file mode 100644 index 7d7065f56..000000000 --- a/modules/config/Util.js +++ /dev/null @@ -1,54 +0,0 @@ -const logger = require("jitsi-meet-logger").getLogger(__filename); - -var ConfigUtil = { - /** - * Method overrides JSON properties in config and - * interfaceConfig Objects with the values from newConfig - * @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; diff --git a/react/features/app/actions.js b/react/features/app/actions.js index fac887a23..376ebbc08 100644 --- a/react/features/app/actions.js +++ b/react/features/app/actions.js @@ -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}`); } diff --git a/react/features/base/config/functions.js b/react/features/base/config/functions.js index 39d84b85e..e2c615ec1 100644 --- a/react/features/base/config/functions.js +++ b/react/features/base/config/functions.js @@ -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 endpoint. 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); } diff --git a/react/features/base/config/getRoomName.js b/react/features/base/config/getRoomName.js new file mode 100644 index 000000000..d89a928bd --- /dev/null +++ b/react/features/base/config/getRoomName.js @@ -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; +} diff --git a/react/features/base/config/parseURLParams.js b/react/features/base/config/parseURLParams.js new file mode 100644 index 000000000..11951a911 --- /dev/null +++ b/react/features/base/config/parseURLParams.js @@ -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; +} diff --git a/react/features/base/connection/actions.native.js b/react/features/base/connection/actions.native.js index e3d298321..4c2573ba6 100644 --- a/react/features/base/connection/actions.native.js +++ b/react/features/base/connection/actions.native.js @@ -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: diff --git a/react/features/base/lib-jitsi-meet/functions.js b/react/features/base/lib-jitsi-meet/functions.js index a5eb353d4..80a3f0aad 100644 --- a/react/features/base/lib-jitsi-meet/functions.js +++ b/react/features/base/lib-jitsi-meet/functions.js @@ -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} + */ +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} */ 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} - */ -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; } diff --git a/react/features/conference/route.js b/react/features/conference/route.js index 86036a3f5..cd22a3d46 100644 --- a/react/features/conference/route.js +++ b/react/features/conference/route.js @@ -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(); } }