浏览代码

[RN] Support JSON Web Token (JWT)

Make 'Add jwt module to react' work on mobile.
master
Lyubo Marinov 8 年前
父节点
当前提交
e6f6884c36

+ 2
- 4
connection_optimization/do_external_connect.js 查看文件

@@ -1,9 +1,7 @@
1 1
 /* global config, createConnectionExternally */
2 2
 
3
-import {
4
-    getRoomName,
5
-    parseURLParams
6
-} from '../react/features/base/config/functions';
3
+import getRoomName from '../react/features/base/config/getRoomName';
4
+import parseURLParams from '../react/features/base/config/parseURLParams';
7 5
 
8 6
 /**
9 7
  * Implements external connect using createConnectionExternally function defined

+ 8
- 4
modules/API/constants.js 查看文件

@@ -1,9 +1,13 @@
1
-declare var getConfigParamsFromUrl: Function;
1
+// XXX The function parseURLParams is exported by the feature base/config (as
2
+// defined in the terminology of react/). However, this file is (very likely)
3
+// bundled in external_api in addition to app.bundle and, consequently, it is
4
+// best to import as little as possible here (rather than the whole feature
5
+// base/config) in order to minimize the amount of source code bundled into
6
+// multiple bundles.
7
+import parseURLParams from '../../react/features/base/config/parseURLParams';
2 8
 
3 9
 /**
4 10
  * JitsiMeetExternalAPI id - unique for a webpage.
5 11
  */
6 12
 export const API_ID
7
-    = typeof getConfigParamsFromUrl === 'function'
8
-        ? getConfigParamsFromUrl().jitsi_meet_external_api_id
9
-        : undefined;
13
+    = parseURLParams(window.location).jitsi_meet_external_api_id;

+ 0
- 46
modules/config/BoshAddressChoice.js 查看文件

@@ -1,46 +0,0 @@
1
-const logger = require("jitsi-meet-logger").getLogger(__filename);
2
-
3
-var JSSHA = require('jssha');
4
-
5
-module.exports = {
6
-    /**
7
-     * Looks for a list of possible BOSH addresses in 'config.boshList' and
8
-     * sets the value of 'config.bosh' based on that list and 'roomName'.
9
-     * @param config the configuration object.
10
-     * @param roomName the name of the room/conference.
11
-     */
12
-    chooseAddress: function(config, roomName) {
13
-        if (!roomName || !config.boshList || !Array.isArray(config.boshList) ||
14
-            !config.boshList.length) {
15
-            return;
16
-        }
17
-
18
-        // This implements the actual choice of an entry in the list based on
19
-        // roomName. Please consider the implications for existing deployments
20
-        // before introducing changes.
21
-        var hash = (new JSSHA(roomName, 'TEXT')).getHash('SHA-1', 'HEX');
22
-        var n = parseInt("0x"+hash.substr(-6));
23
-        var idx = n % config.boshList.length;
24
-        var attemptFirstAddress;
25
-
26
-        config.bosh = config.boshList[idx];
27
-        logger.log('Setting config.bosh to ' + config.bosh +
28
-            ' (idx=' + idx + ')');
29
-
30
-        if (config.boshAttemptFirstList &&
31
-            Array.isArray(config.boshAttemptFirstList) &&
32
-            config.boshAttemptFirstList.length > 0) {
33
-
34
-            idx = n % config.boshAttemptFirstList.length;
35
-            attemptFirstAddress = config.boshAttemptFirstList[idx];
36
-
37
-            if (attemptFirstAddress != config.bosh) {
38
-                config.boshAttemptFirst = attemptFirstAddress;
39
-                logger.log('Setting config.boshAttemptFirst=' +
40
-                    attemptFirstAddress + ' (idx=' + idx + ')');
41
-            } else {
42
-                logger.log('Not setting boshAttemptFirst, address matches.');
43
-            }
44
-        }
45
-    }
46
-};

+ 0
- 52
modules/config/HttpConfigFetch.js 查看文件

@@ -1,52 +0,0 @@
1
-/* global $, config, interfaceConfig */
2
-const logger = require("jitsi-meet-logger").getLogger(__filename);
3
-
4
-var configUtil = require('./Util');
5
-
6
-var HttpConfig = {
7
-    /**
8
-     * Sends HTTP POST request to specified <tt>endpoint</tt>. In request
9
-     * the name of the room is included in JSON format:
10
-     * {
11
-     *   "rooomName": "someroom12345"
12
-     * }
13
-     * @param endpoint the name of HTTP endpoint to which HTTP POST request will
14
-     *                 be sent.
15
-     * @param roomName the name of the conference room for which config will be
16
-     *                 requested.
17
-     * @param complete
18
-     */
19
-    obtainConfig: function (endpoint, roomName, complete) {
20
-        logger.info(
21
-            "Send config request to " + endpoint + " for room: " + roomName);
22
-
23
-
24
-        $.ajax(
25
-            endpoint,
26
-            {
27
-                method: 'POST',
28
-                contentType: 'application/json',
29
-                data: JSON.stringify({"roomName": roomName}),
30
-                dataType: 'json',
31
-                error: function(jqXHR, textStatus, errorThrown) {
32
-                    logger.error("Get config error: ", jqXHR, errorThrown);
33
-                    var error = "Get config response status: " + textStatus;
34
-                    complete(false, error);
35
-                },
36
-                success: function(data) {
37
-                    try {
38
-                        configUtil.overrideConfigJSON(
39
-                            config, interfaceConfig, data);
40
-                        complete(true);
41
-                        return;
42
-                    } catch (exception) {
43
-                        logger.error("Parse config error: ", exception);
44
-                        complete(false, exception);
45
-                    }
46
-                }
47
-            }
48
-        );
49
-    }
50
-};
51
-
52
-module.exports = HttpConfig;

+ 0
- 93
modules/config/URLProcessor.js 查看文件

@@ -1,93 +0,0 @@
1
-/* global config, interfaceConfig, loggingConfig */
2
-
3
-import { parseURLParams } from '../../react/features/base/config';
4
-
5
-import configUtils from './Util';
6
-
7
-const logger = require("jitsi-meet-logger").getLogger(__filename);
8
-
9
-/**
10
- *  URL params with this prefix should be merged to config.
11
- */
12
-const CONFIG_PREFIX = 'config.';
13
-
14
-/**
15
- *  URL params with this prefix should be merged to interface config.
16
- */
17
-const INTERFACE_CONFIG_PREFIX = 'interfaceConfig.';
18
-
19
-/**
20
- * Config keys to be ignored.
21
- *
22
- * @type Set
23
- */
24
-const KEYS_TO_IGNORE = new Set([
25
-    'analyticsScriptUrls',
26
-    'callStatsCustomScriptUrl'
27
-]);
28
-
29
-/**
30
- *  URL params with this prefix should be merged to logging config.
31
- */
32
-const LOGGING_CONFIG_PREFIX = 'loggingConfig.';
33
-
34
-/**
35
- * Convert 'URL_PARAMS' to JSON object
36
- * We have:
37
- * {
38
- *      "config.disableAudioLevels": false,
39
- *      "config.channelLastN": -1,
40
- *      "interfaceConfig.APP_NAME": "Jitsi Meet"
41
- * }
42
- * We want to have:
43
- * {
44
- *      "config": {
45
- *          "disableAudioLevels": false,
46
- *          "channelLastN": -1
47
- *      },
48
- *      interfaceConfig: {
49
- *          "APP_NAME": "Jitsi Meet"
50
- *      }
51
- * }
52
- */
53
-export function setConfigParametersFromUrl() {
54
-    // Parsing config params from URL hash.
55
-    const params = parseURLParams(window.location);
56
-
57
-    const configJSON = {
58
-        config: {},
59
-        interfaceConfig: {},
60
-        loggingConfig: {}
61
-    };
62
-
63
-    for (const key in params) {
64
-        if (typeof key === 'string') {
65
-            let confObj = null;
66
-            let confKey;
67
-
68
-            if (key.indexOf(CONFIG_PREFIX) === 0) {
69
-                confObj = configJSON.config;
70
-                confKey = key.substr(CONFIG_PREFIX.length);
71
-
72
-            } else if (key.indexOf(INTERFACE_CONFIG_PREFIX) === 0) {
73
-                confObj = configJSON.interfaceConfig;
74
-                confKey
75
-                    = key.substr(INTERFACE_CONFIG_PREFIX.length);
76
-            } else if (key.indexOf(LOGGING_CONFIG_PREFIX) === 0) {
77
-                confObj = configJSON.loggingConfig;
78
-                confKey = key.substr(LOGGING_CONFIG_PREFIX.length);
79
-            }
80
-
81
-            // prevent passing some parameters which can inject scripts
82
-            if (confObj && !KEYS_TO_IGNORE.has(confKey)) {
83
-                confObj[confKey] = params[key];
84
-            }
85
-        } else {
86
-            logger.warn('Invalid config key: ', key);
87
-        }
88
-    }
89
-
90
-    configUtils.overrideConfigJSON(
91
-        config, interfaceConfig, loggingConfig,
92
-        configJSON);
93
-}

+ 0
- 54
modules/config/Util.js 查看文件

@@ -1,54 +0,0 @@
1
-const logger = require("jitsi-meet-logger").getLogger(__filename);
2
-
3
-var ConfigUtil = {
4
-    /**
5
-     * Method overrides JSON properties in <tt>config</tt> and
6
-     * <tt>interfaceConfig</tt> Objects with the values from <tt>newConfig</tt>
7
-     * @param config the config object for which we'll be overriding properties
8
-     * @param interfaceConfig the interfaceConfig object for which we'll be
9
-     *                        overriding properties.
10
-     * @param loggingConfig the logging config object for which we'll be
11
-     *        overriding properties.
12
-     * @param newConfig object containing configuration properties. Destination
13
-     *        object is selected based on root property name:
14
-     *        {
15
-     *          config: {
16
-     *             // config.js properties to be
17
-     *          },
18
-     *          interfaceConfig: {
19
-     *             // interface_config.js properties here
20
-     *          },
21
-     *          loggingConfig: {
22
-     *             // logging_config.js properties here
23
-     *          }
24
-     *        }
25
-     */
26
-    overrideConfigJSON: function (config,
27
-                                  interfaceConfig, loggingConfig, newConfig) {
28
-        var configRoot, key, value, confObj;
29
-        for (configRoot in newConfig) {
30
-            confObj = null;
31
-            if (configRoot == "config") {
32
-                confObj = config;
33
-            } else if (configRoot == "interfaceConfig") {
34
-                confObj = interfaceConfig;
35
-            } else if (configRoot == "loggingConfig") {
36
-                confObj = loggingConfig;
37
-            } else {
38
-                continue;
39
-            }
40
-
41
-            for (key in newConfig[configRoot]) {
42
-                value = newConfig[configRoot][key];
43
-                if (confObj[key] && typeof confObj[key] !== typeof value) {
44
-                    logger.log("Overriding a " + configRoot +
45
-                        " property with a property of different type.");
46
-                }
47
-                logger.info("Overriding " + key + " with: " + value);
48
-                confObj[key] = value;
49
-            }
50
-        }
51
-    }
52
-};
53
-
54
-module.exports = ConfigUtil;

+ 6
- 7
react/features/app/actions.js 查看文件

@@ -18,7 +18,8 @@ import {
18 18
  * @returns {Function}
19 19
  */
20 20
 export function appInit() {
21
-    return (dispatch, getState) => init(getState());
21
+    return (dispatch: Dispatch<*>, getState: Function) =>
22
+        init(getState());
22 23
 }
23 24
 
24 25
 /**
@@ -31,7 +32,7 @@ export function appInit() {
31 32
  * @returns {Function}
32 33
  */
33 34
 export function appNavigate(uri) {
34
-    return (dispatch, getState) => {
35
+    return (dispatch: Dispatch<*>, getState: Function) => {
35 36
         const state = getState();
36 37
         const oldDomain = getDomain(state);
37 38
         const defaultURL = state['features/app'].app._getDefaultURL();
@@ -43,14 +44,12 @@ export function appNavigate(uri) {
43 44
         // If the specified URI does not identify a domain, use the app's
44 45
         // default.
45 46
         if (typeof domain === 'undefined') {
46
-            domain
47
-                = _parseURIString(defaultURL)
48
-                    .domain;
47
+            domain = _parseURIString(defaultURL).domain;
49 48
         }
50 49
 
51 50
         if (room) {
52
-            const splitUrl = uri.split(domain);
53
-            const urlWithoutDomain = splitUrl[splitUrl.length - 1];
51
+            const splitURL = uri.split(domain);
52
+            const urlWithoutDomain = splitURL[splitURL.length - 1];
54 53
 
55 54
             urlObject = new URL(urlWithoutDomain, `https://${domain}`);
56 55
         }

+ 228
- 53
react/features/base/config/functions.js 查看文件

@@ -1,72 +1,247 @@
1 1
 /* @flow */
2 2
 
3
-declare var config: Object;
3
+import JSSHA from 'jssha';
4
+
5
+import parseURLParams from './parseURLParams';
6
+
7
+declare var $: Object;
8
+
9
+/**
10
+ * The config keys to ignore because, for example, their values identify scripts
11
+ * and it is not desireable to inject these through URL params.
12
+ *
13
+ * @private
14
+ * @type Array
15
+ */
16
+const _KEYS_TO_IGNORE = [
17
+    'analyticsScriptUrls',
18
+    'callStatsCustomScriptUrl'
19
+];
20
+
21
+const logger = require('jitsi-meet-logger').getLogger(__filename);
22
+
23
+// XXX The functions getRoomName and parseURLParams are split out of
24
+// functions.js because they are bundled in both app.bundle and
25
+// do_external_connect, webpack 1 does not support tree shaking, and we don't
26
+// want all functions to be bundled in do_external_connect.
27
+export { default as getRoomName } from './getRoomName';
28
+export { parseURLParams };
29
+
30
+/* eslint-disable no-shadow */
4 31
 
5 32
 /**
6
- * Builds and returns the room name.
33
+ * Looks for a list of possible BOSH addresses in {@code config.boshList} and
34
+ * sets the value of {@code config.bosh} based on that list and
35
+ * {@code roomName}.
7 36
  *
8
- * @returns {string}
37
+ * @param {Object} config - The configuration object.
38
+ * @param {string} roomName - The name of the room/conference.
39
+ * @returns {void}
9 40
  */
10
-export function getRoomName(): ?string {
11
-    const { getroomnode } = config;
12
-    const path = window.location.pathname;
13
-    let roomName;
14
-
15
-    // Determine the room node from the URL.
16
-    if (getroomnode && typeof getroomnode === 'function') {
17
-        roomName = getroomnode.call(config, path);
18
-    } else {
19
-        // Fall back to the default strategy of making assumptions about how the
20
-        // URL maps to the room (name). It currently assumes a deployment in
21
-        // which the last non-directory component of the path (name) is the
22
-        // room.
23
-        roomName
24
-            = path.substring(path.lastIndexOf('/') + 1).toLowerCase()
25
-                || undefined;
41
+export function chooseBOSHAddress(config: Object, roomName: string) {
42
+    if (!roomName) {
43
+        return;
44
+    }
45
+
46
+    const { boshList } = config;
47
+
48
+    if (!boshList || !Array.isArray(boshList) || !boshList.length) {
49
+        return;
26 50
     }
27 51
 
28
-    return roomName;
52
+    // This implements the actual choice of an entry in the list based on
53
+    // roomName. Please consider the implications for existing deployments
54
+    // before introducing changes.
55
+    const hash = (new JSSHA(roomName, 'TEXT')).getHash('SHA-1', 'HEX');
56
+    const n = parseInt(hash.substr(-6), 16);
57
+    let idx = n % boshList.length;
58
+
59
+    config.bosh = boshList[idx];
60
+    logger.log(`Setting config.bosh to ${config.bosh} (idx=${idx})`);
61
+
62
+    const { boshAttemptFirstList } = config;
63
+
64
+    if (boshAttemptFirstList
65
+            && Array.isArray(boshAttemptFirstList)
66
+            && boshAttemptFirstList.length > 0) {
67
+        idx = n % boshAttemptFirstList.length;
68
+
69
+        const attemptFirstAddress = boshAttemptFirstList[idx];
70
+
71
+        if (attemptFirstAddress === config.bosh) {
72
+            logger.log('Not setting config.boshAttemptFirst, address matches.');
73
+        } else {
74
+            config.boshAttemptFirst = attemptFirstAddress;
75
+            logger.log(
76
+                `Setting config.boshAttemptFirst=${attemptFirstAddress} (idx=${
77
+                    idx})`);
78
+        }
79
+    }
80
+}
81
+
82
+/* eslint-enable no-shadow */
83
+
84
+/**
85
+ * Sends HTTP POST request to specified <tt>endpoint</tt>. In request the name
86
+ * of the room is included in JSON format:
87
+ * {
88
+ *     "rooomName": "someroom12345"
89
+ * }.
90
+ *
91
+ * @param {string} endpoint - The name of HTTP endpoint to which to send
92
+ * the HTTP POST request.
93
+ * @param {string} roomName - The name of the conference room for which config
94
+ * is requested.
95
+ * @param {Function} complete - The callback to invoke upon success or failure.
96
+ * @returns {void}
97
+ */
98
+export function obtainConfig(
99
+        endpoint: string,
100
+        roomName: string,
101
+        complete: Function) {
102
+    logger.info(`Send config request to ${endpoint} for room: ${roomName}`);
103
+    $.ajax(
104
+        endpoint,
105
+        {
106
+            contentType: 'application/json',
107
+            data: JSON.stringify({ roomName }),
108
+            dataType: 'json',
109
+            method: 'POST',
110
+
111
+            error(jqXHR, textStatus, errorThrown) {
112
+                logger.error('Get config error: ', jqXHR, errorThrown);
113
+                complete(false, `Get config response status: ${textStatus}`);
114
+            },
115
+            success(data) {
116
+                const { config, interfaceConfig, loggingConfig } = window;
117
+
118
+                try {
119
+                    overrideConfigJSON(
120
+                        config, interfaceConfig, loggingConfig,
121
+                        data);
122
+                    complete(true);
123
+                } catch (e) {
124
+                    logger.error('Parse config error: ', e);
125
+                    complete(false, e);
126
+                }
127
+            }
128
+        }
129
+    );
29 130
 }
30 131
 
132
+/* eslint-disable max-params, no-shadow */
133
+
31 134
 /**
32
- * Parses the parameters from the URL and returns them as a JS object.
135
+ * Overrides JSON properties in {@code config} and
136
+ * {@code interfaceConfig} Objects with the values from {@code newConfig}.
33 137
  *
34
- * @param {string} url - URL to parse.
35
- * @param {boolean} dontParse - If false or undefined some transformations
36
- * (for parsing the value as JSON) are going to be executed.
37
- * @param {string} source - Values - "hash"/"search" if "search" the parameters
38
- * will parsed from location.search otherwise from location.hash.
39
- * @returns {Object}
138
+ * @param {Object} config - The config Object in which we'll be overriding
139
+ * properties.
140
+ * @param {Object} interfaceConfig - The interfaceConfig Object in which we'll
141
+ * be overriding properties.
142
+ * @param {Object} loggingConfig - The loggingConfig Object in which we'll be
143
+ * overriding properties.
144
+ * @param {Object} json - Object containing configuration properties.
145
+ * Destination object is selected based on root property name:
146
+ * {
147
+ *     config: {
148
+ *         // config.js properties here
149
+ *     },
150
+ *     interfaceConfig: {
151
+ *         // interface_config.js properties here
152
+ *     },
153
+ *     loggingConfig: {
154
+ *         // logging_config.js properties here
155
+ *     }
156
+ * }.
157
+ * @returns {void}
40 158
  */
41
-export function parseURLParams(
42
-        url: URL,
43
-        dontParse: boolean = false,
44
-        source: string = 'hash'): Object {
45
-    const paramStr = source === 'search' ? url.search : url.hash;
46
-    const params = {};
47
-
48
-    // eslint-disable-next-line newline-per-chained-call
49
-    paramStr && paramStr.substr(1).split('&').forEach(part => {
50
-        const param = part.split('=');
51
-        let value;
52
-
53
-        try {
54
-            value = param[1];
55
-            if (!dontParse) {
56
-                value
57
-                    = JSON.parse(
58
-                        decodeURIComponent(param[1]).replace(/\\&/, '&'));
159
+export function overrideConfigJSON(
160
+        config: Object, interfaceConfig: Object, loggingConfig: Object,
161
+        json: Object) {
162
+    for (const configName of Object.keys(json)) {
163
+        let configObj;
164
+
165
+        if (configName === 'config') {
166
+            configObj = config;
167
+        } else if (configName === 'interfaceConfig') {
168
+            configObj = interfaceConfig;
169
+        } else if (configName === 'loggingConfig') {
170
+            configObj = loggingConfig;
171
+        }
172
+        if (configObj) {
173
+            const configJSON = json[configName];
174
+
175
+            for (const key of Object.keys(configJSON)) {
176
+                const oldValue = configObj[key];
177
+                const newValue = configJSON[key];
178
+
179
+                if (oldValue && typeof oldValue !== typeof newValue) {
180
+                    logger.log(
181
+                        `Overriding a ${configName
182
+                            } property with a property of different type.`);
183
+                }
184
+                logger.info(`Overriding ${key} with: ${newValue}`);
185
+                configObj[key] = newValue;
59 186
             }
60
-        } catch (e) {
61
-            const msg = `Failed to parse URL parameter value: ${String(value)}`;
187
+        }
188
+    }
189
+}
190
+
191
+/* eslint-enable max-params, no-shadow */
192
+
193
+/**
194
+ * Converts 'URL_PARAMS' to JSON object.
195
+ * We have:
196
+ * {
197
+ *      "config.disableAudioLevels": false,
198
+ *      "config.channelLastN": -1,
199
+ *      "interfaceConfig.APP_NAME": "Jitsi Meet"
200
+ * }.
201
+ * We want to have:
202
+ * {
203
+ *      "config": {
204
+ *          "disableAudioLevels": false,
205
+ *          "channelLastN": -1
206
+ *      },
207
+ *      interfaceConfig: {
208
+ *          "APP_NAME": "Jitsi Meet"
209
+ *      }
210
+ * }.
211
+ *
212
+ * @returns {void}
213
+ */
214
+export function setConfigFromURLParams() {
215
+    const params = parseURLParams(window.location);
62 216
 
63
-            console.warn(msg, e);
64
-            window.onerror && window.onerror(msg, null, null, null, e);
217
+    const { config, interfaceConfig, loggingConfig } = window;
218
+    const json = {};
65 219
 
66
-            return;
220
+    // TODO We're still in the middle ground between old Web with config,
221
+    // interfaceConfig, and loggingConfig used via global variables and new Web
222
+    // and mobile reading the respective values from the redux store. On React
223
+    // Native there's no interfaceConfig at all yet and loggingConfig is not
224
+    // loaded but there's a default value in the redux store.
225
+    config && (json.config = {});
226
+    interfaceConfig && (json.interfaceConfig = {});
227
+    loggingConfig && (json.loggingConfig = {});
228
+
229
+    for (const param of Object.keys(params)) {
230
+        const objEnd = param.indexOf('.');
231
+
232
+        if (objEnd !== -1) {
233
+            const obj = param.substring(0, objEnd);
234
+
235
+            if (json.hasOwnProperty(obj)) {
236
+                const key = param.substring(objEnd + 1);
237
+
238
+                // Prevent passing some parameters which can inject scripts.
239
+                if (key && _KEYS_TO_IGNORE.indexOf(key) === -1) {
240
+                    json[obj][key] = params[param];
241
+                }
242
+            }
67 243
         }
68
-        params[param[0]] = value;
69
-    });
244
+    }
70 245
 
71
-    return params;
246
+    overrideConfigJSON(config, interfaceConfig, loggingConfig, json);
72 247
 }

+ 29
- 0
react/features/base/config/getRoomName.js 查看文件

@@ -0,0 +1,29 @@
1
+/* @flow */
2
+
3
+declare var config: Object;
4
+
5
+/**
6
+ * Builds and returns the room name.
7
+ *
8
+ * @returns {string}
9
+ */
10
+export default function getRoomName(): ?string {
11
+    const { getroomnode } = config;
12
+    const path = window.location.pathname;
13
+    let roomName;
14
+
15
+    // Determine the room node from the URL.
16
+    if (getroomnode && typeof getroomnode === 'function') {
17
+        roomName = getroomnode.call(config, path);
18
+    } else {
19
+        // Fall back to the default strategy of making assumptions about how the
20
+        // URL maps to the room (name). It currently assumes a deployment in
21
+        // which the last non-directory component of the path (name) is the
22
+        // room.
23
+        roomName
24
+            = path.substring(path.lastIndexOf('/') + 1).toLowerCase()
25
+                || undefined;
26
+    }
27
+
28
+    return roomName;
29
+}

+ 49
- 0
react/features/base/config/parseURLParams.js 查看文件

@@ -0,0 +1,49 @@
1
+/* @flow */
2
+
3
+/**
4
+ * Parses the parameters from the URL and returns them as a JS object.
5
+ *
6
+ * @param {string} url - URL to parse.
7
+ * @param {boolean} dontParse - If false or undefined some transformations
8
+ * (for parsing the value as JSON) are going to be executed.
9
+ * @param {string} source - Values - "hash"/"search" if "search" the parameters
10
+ * will parsed from location.search otherwise from location.hash.
11
+ * @returns {Object}
12
+ */
13
+export default function parseURLParams(
14
+        url: URL,
15
+        dontParse: boolean = false,
16
+        source: string = 'hash'): Object {
17
+    const paramStr = source === 'search' ? url.search : url.hash;
18
+    const params = {};
19
+
20
+    // eslint-disable-next-line newline-per-chained-call
21
+    paramStr && paramStr.substr(1).split('&').forEach(part => {
22
+        const param = part.split('=');
23
+        const key = param[0];
24
+
25
+        if (!key) {
26
+            return;
27
+        }
28
+
29
+        let value;
30
+
31
+        try {
32
+            value = param[1];
33
+            if (!dontParse) {
34
+                value
35
+                    = JSON.parse(decodeURIComponent(value).replace(/\\&/, '&'));
36
+            }
37
+        } catch (e) {
38
+            const msg = `Failed to parse URL parameter value: ${String(value)}`;
39
+
40
+            console.warn(msg, e);
41
+            window.onerror && window.onerror(msg, null, null, null, e);
42
+
43
+            return;
44
+        }
45
+        params[key] = value;
46
+    });
47
+
48
+    return params;
49
+}

+ 2
- 1
react/features/base/connection/actions.native.js 查看文件

@@ -21,11 +21,12 @@ export function connect() {
21 21
     return (dispatch: Dispatch<*>, getState: Function) => {
22 22
         const state = getState();
23 23
         const { options } = state['features/base/connection'];
24
+        const { issuer, jwt } = state['features/jwt'];
24 25
         const { room } = state['features/base/conference'];
25 26
         const connection
26 27
             = new JitsiMeetJS.JitsiConnection(
27 28
                 options.appId,
28
-                options.token,
29
+                jwt && issuer && issuer !== 'anonymous' ? jwt : undefined,
29 30
                 {
30 31
                     ...options,
31 32
                     bosh:

+ 58
- 50
react/features/base/lib-jitsi-meet/functions.js 查看文件

@@ -1,8 +1,7 @@
1
-import { loadScript } from '../../base/util';
1
+/* @flow */
2 2
 
3
-import {
4
-    setConfigParametersFromUrl
5
-} from '../../../../modules/config/URLProcessor';
3
+import { setConfigFromURLParams } from '../../base/config';
4
+import { loadScript } from '../../base/util';
6 5
 
7 6
 import JitsiMeetJS from './_';
8 7
 
@@ -10,6 +9,28 @@ declare var APP: Object;
10 9
 
11 10
 const JitsiConnectionErrors = JitsiMeetJS.errors.connection;
12 11
 
12
+/**
13
+ * Creates a JitsiLocalTrack model from the given device id.
14
+ *
15
+ * @param {string} type - The media type of track being created. Expected values
16
+ * are "video" or "audio".
17
+ * @param {string} deviceId - The id of the target media source.
18
+ * @returns {Promise<JitsiLocalTrack>}
19
+ */
20
+export function createLocalTrack(type: string, deviceId: string) {
21
+    return (
22
+        JitsiMeetJS.createLocalTracks({
23
+            cameraDeviceId: deviceId,
24
+            devices: [ type ],
25
+
26
+            // eslint-disable-next-line camelcase
27
+            firefox_fake_device:
28
+                window.config && window.config.firefox_fake_device,
29
+            micDeviceId: deviceId
30
+        })
31
+            .then(([ jitsiLocalTrack ]) => jitsiLocalTrack));
32
+}
33
+
13 34
 /**
14 35
  * Determines whether a specific JitsiConnectionErrors instance indicates a
15 36
  * fatal JitsiConnection error.
@@ -38,56 +59,43 @@ export function isFatalJitsiConnectionError(error: string) {
38 59
  * @returns {Promise<Object>}
39 60
  */
40 61
 export function loadConfig(host: string, path: string = '/config.js') {
41
-    // Returns config.js file from global scope. We can't use the version that's
42
-    // being used for the React Native app because the old/current Web app uses
43
-    // config from the global scope.
44
-    if (typeof APP !== 'undefined') {
45
-        // FIXME The following call to setConfigParametersFromUrl is bad design
46
-        // but URLProcessor still deals with the global variables config,
47
-        // interfaceConfig, and loggingConfig and loadConfig. As the latter will
48
-        // surely change in the future, so will the former then.
49
-        setConfigParametersFromUrl();
50
-
51
-        return Promise.resolve(window.config);
52
-    }
62
+    let promise;
53 63
 
54
-    return loadScript(new URL(path, host).toString())
55
-        .then(() => {
56
-            const config = window.config;
64
+    if (typeof APP === 'undefined') {
65
+        promise
66
+            = loadScript(new URL(path, host).toString())
67
+                .then(() => {
68
+                    const { config } = window;
57 69
 
58
-            // We don't want to pollute global scope.
59
-            window.config = undefined;
70
+                    // We don't want to pollute global scope.
71
+                    window.config = undefined;
60 72
 
61
-            if (typeof config !== 'object') {
62
-                throw new Error('window.config is not an object');
63
-            }
73
+                    if (typeof config !== 'object') {
74
+                        throw new Error('window.config is not an object');
75
+                    }
64 76
 
65
-            return config;
66
-        })
67
-        .catch(err => {
68
-            console.error(`Failed to load ${path} from ${host}`, err);
77
+                    return config;
78
+                })
79
+                .catch(err => {
80
+                    console.error(`Failed to load ${path} from ${host}`, err);
69 81
 
70
-            throw err;
71
-        });
72
-}
82
+                    throw err;
83
+                });
84
+    } else {
85
+        // Return config.js file from global scope. We can't use the version
86
+        // that's being used for the React Native app because the old/current
87
+        // Web app uses config from the global scope.
88
+        promise = Promise.resolve(window.config);
89
+    }
73 90
 
74
-/**
75
- * Creates a JitsiLocalTrack model from the given device id.
76
- *
77
- * @param {string} type - The media type of track being created. Expected values
78
- * are "video" or "audio".
79
- * @param {string} deviceId - The id of the target media source.
80
- * @returns {Promise<JitsiLocalTrack>}
81
- */
82
-export function createLocalTrack(type, deviceId) {
83
-    return JitsiMeetJS.createLocalTracks({
84
-        cameraDeviceId: deviceId,
85
-        devices: [ type ],
86
-
87
-        // eslint-disable-next-line camelcase
88
-        firefox_fake_device:
89
-            window.config && window.config.firefox_fake_device,
90
-        micDeviceId: deviceId
91
-    })
92
-        .then(([ jitsiLocalTrack ]) => jitsiLocalTrack);
91
+    // FIXME It's neither here nor there at the time of this writing where
92
+    // config, interfaceConfig, and loggingConfig should be overwritten by URL
93
+    // params.
94
+    promise = promise.then(value => {
95
+        setConfigFromURLParams();
96
+
97
+        return value;
98
+    });
99
+
100
+    return promise;
93 101
 }

+ 7
- 12
react/features/conference/route.js 查看文件

@@ -1,9 +1,8 @@
1 1
 /* global APP, config */
2 2
 
3
-import BoshAddressChoice from '../../../modules/config/BoshAddressChoice';
4
-import HttpConfigFetch from '../../../modules/config/HttpConfigFetch';
5 3
 import ConferenceUrl from '../../../modules/URL/ConferenceUrl';
6 4
 
5
+import { chooseBOSHAddress, obtainConfig } from '../base/config';
7 6
 import { RouteRegistry } from '../base/react';
8 7
 
9 8
 import { Conference } from './components';
@@ -47,15 +46,11 @@ function _initConference() {
47 46
  * @returns {Promise}
48 47
  */
49 48
 function _obtainConfig(location, room) {
50
-    return new Promise((resolve, reject) => {
51
-        HttpConfigFetch.obtainConfig(location, room, (success, error) => {
52
-            if (success) {
53
-                resolve();
54
-            } else {
55
-                reject(error);
56
-            }
57
-        });
58
-    });
49
+    return new Promise((resolve, reject) =>
50
+        obtainConfig(location, room, (success, error) => {
51
+            success ? resolve() : reject(error);
52
+        })
53
+    );
59 54
 }
60 55
 
61 56
 /**
@@ -87,7 +82,7 @@ function _obtainConfigAndInit() {
87 82
                         null, 'dialog.connectError', err);
88 83
                 });
89 84
         } else {
90
-            BoshAddressChoice.chooseAddress(config, room);
85
+            chooseBOSHAddress(config, room);
91 86
             _initConference();
92 87
         }
93 88
     }

正在加载...
取消
保存