浏览代码

[RN] If base/config knows a domain, then the app knows it

Knowledge is power, man!

The config.js cache predates the feature base/known-domains.
Technically, it's also able to recall more domains that the feature
recent-list can (because the latter limits its entries).
master
Lyubo Marinov 7 年前
父节点
当前提交
75fe3e3b9d

+ 60
- 72
react/features/app/actions.js 查看文件

1
 /* @flow */
1
 /* @flow */
2
 
2
 
3
 import { setRoom } from '../base/conference';
3
 import { setRoom } from '../base/conference';
4
-import { configWillLoad, loadConfigError, setConfig } from '../base/config';
4
+import {
5
+    configWillLoad,
6
+    loadConfigError,
7
+    restoreConfig,
8
+    setConfig,
9
+    storeConfig
10
+} from '../base/config';
5
 import { setLocationURL } from '../base/connection';
11
 import { setLocationURL } from '../base/connection';
6
 import { loadConfig } from '../base/lib-jitsi-meet';
12
 import { loadConfig } from '../base/lib-jitsi-meet';
7
 import { parseURIString } from '../base/util';
13
 import { parseURIString } from '../base/util';
24
         _appNavigateToOptionalLocation(dispatch, getState, parseURIString(uri));
30
         _appNavigateToOptionalLocation(dispatch, getState, parseURIString(uri));
25
 }
31
 }
26
 
32
 
27
-/**
28
- * Redirects to another page generated by replacing the path in the original URL
29
- * with the given path.
30
- *
31
- * @param {(string)} pathname - The path to navigate to.
32
- * @returns {Function}
33
- */
34
-export function redirectWithStoredParams(pathname: string) {
35
-    return (dispatch: Dispatch<*>, getState: Function) => {
36
-        const { locationURL } = getState()['features/base/connection'];
37
-        const newLocationURL = new URL(locationURL.href);
38
-
39
-        newLocationURL.pathname = pathname;
40
-        window.location.assign(newLocationURL.toString());
41
-    };
42
-}
43
-
44
-/**
45
- * Reloads the page by restoring the original URL.
46
- *
47
- * @returns {Function}
48
- */
49
-export function reloadWithStoredParams() {
50
-    return (dispatch: Dispatch<*>, getState: Function) => {
51
-        const { locationURL } = getState()['features/base/connection'];
52
-        const windowLocation = window.location;
53
-        const oldSearchString = windowLocation.search;
54
-
55
-        windowLocation.replace(locationURL.toString());
56
-
57
-        if (window.self !== window.top
58
-            && locationURL.search === oldSearchString) {
59
-            // NOTE: Assuming that only the hash or search part of the URL will
60
-            // be changed!
61
-            // location.reload will not trigger redirect/reload for iframe when
62
-            // only the hash params are changed. That's why we need to call
63
-            // reload in addition to replace.
64
-            windowLocation.reload();
65
-        }
66
-    };
67
-}
68
-
69
 /**
33
 /**
70
  * Triggers an in-app navigation to a specific location URI.
34
  * Triggers an in-app navigation to a specific location URI.
71
  *
35
  *
89
     dispatch(configWillLoad(newLocation));
53
     dispatch(configWillLoad(newLocation));
90
 
54
 
91
     return (
55
     return (
92
-        _loadConfig(newLocation)
56
+        _loadConfig(dispatch, getState, newLocation)
93
             .then(
57
             .then(
94
                 config => loadConfigSettled(/* error */ undefined, config),
58
                 config => loadConfigSettled(/* error */ undefined, config),
95
                 error => loadConfigSettled(error, /* config */ undefined))
59
                 error => loadConfigSettled(error, /* config */ undefined))
214
 /**
178
 /**
215
  * Loads config.js from a specific host.
179
  * Loads config.js from a specific host.
216
  *
180
  *
181
+ * @param {Dispatch} dispatch - The redux {@code dispatch} function.
182
+ * @param {Function} getState - The redux {@code getState} function.
217
  * @param {Object} location - The location URI which specifies the host to load
183
  * @param {Object} location - The location URI which specifies the host to load
218
  * the config.js from.
184
  * the config.js from.
219
  * @private
185
  * @private
220
  * @returns {Promise<Object>}
186
  * @returns {Promise<Object>}
221
  */
187
  */
222
-function _loadConfig({ contextRoot, host, protocol, room }) {
188
+function _loadConfig(
189
+        dispatch: Dispatch<*>,
190
+        getState: Function,
191
+        { contextRoot, host, protocol, room }) {
223
     // XXX As the mobile/React Native app does not employ config on the
192
     // XXX As the mobile/React Native app does not employ config on the
224
     // WelcomePage, do not download config.js from the deployment when
193
     // WelcomePage, do not download config.js from the deployment when
225
     // navigating to the WelcomePage - the perceived/visible navigation will be
194
     // navigating to the WelcomePage - the perceived/visible navigation will be
246
 
215
 
247
     /* eslint-enable no-param-reassign */
216
     /* eslint-enable no-param-reassign */
248
 
217
 
249
-    const key = `config.js/${baseURL}`;
250
-
251
     return loadConfig(url).then(
218
     return loadConfig(url).then(
252
         /* onFulfilled */ config => {
219
         /* onFulfilled */ config => {
253
-            // Try to store the configuration in localStorage. If the deployment
254
-            // specified 'getroom' as a function, for example, it does not make
255
-            // sense to and it will not be stored.
256
-            try {
257
-                if (typeof window.config === 'undefined'
258
-                        || window.config !== config) {
259
-                    window.localStorage.setItem(key, JSON.stringify(config));
260
-                }
261
-            } catch (e) {
262
-                // Ignore the error because the caching is optional.
263
-            }
220
+            dispatch(storeConfig(baseURL, config));
264
 
221
 
265
             return config;
222
             return config;
266
         },
223
         },
268
             // XXX The (down)loading of config failed. Try to use the last
225
             // XXX The (down)loading of config failed. Try to use the last
269
             // successfully fetched for that deployment. It may not match the
226
             // successfully fetched for that deployment. It may not match the
270
             // shard.
227
             // shard.
271
-            let storage;
228
+            const config = restoreConfig(baseURL);
272
 
229
 
273
-            try {
274
-                // XXX Even reading the property localStorage of window may
275
-                // throw an error (which is user agent-specific behavior).
276
-                storage = window.localStorage;
277
-
278
-                const config = storage.getItem(key);
279
-
280
-                if (config) {
281
-                    return JSON.parse(config);
282
-                }
283
-            } catch (e) {
284
-                // Somehow incorrect data ended up in the storage. Clean it up.
285
-                storage && storage.removeItem(key);
230
+            if (config) {
231
+                return config;
286
             }
232
             }
287
 
233
 
288
             throw error;
234
             throw error;
289
         });
235
         });
290
 }
236
 }
237
+
238
+/**
239
+ * Redirects to another page generated by replacing the path in the original URL
240
+ * with the given path.
241
+ *
242
+ * @param {(string)} pathname - The path to navigate to.
243
+ * @returns {Function}
244
+ */
245
+export function redirectWithStoredParams(pathname: string) {
246
+    return (dispatch: Dispatch<*>, getState: Function) => {
247
+        const { locationURL } = getState()['features/base/connection'];
248
+        const newLocationURL = new URL(locationURL.href);
249
+
250
+        newLocationURL.pathname = pathname;
251
+        window.location.assign(newLocationURL.toString());
252
+    };
253
+}
254
+
255
+/**
256
+ * Reloads the page by restoring the original URL.
257
+ *
258
+ * @returns {Function}
259
+ */
260
+export function reloadWithStoredParams() {
261
+    return (dispatch: Dispatch<*>, getState: Function) => {
262
+        const { locationURL } = getState()['features/base/connection'];
263
+        const windowLocation = window.location;
264
+        const oldSearchString = windowLocation.search;
265
+
266
+        windowLocation.replace(locationURL.toString());
267
+
268
+        if (window.self !== window.top
269
+                && locationURL.search === oldSearchString) {
270
+            // NOTE: Assuming that only the hash or search part of the URL will
271
+            // be changed!
272
+            // location.reload will not trigger redirect/reload for iframe when
273
+            // only the hash params are changed. That's why we need to call
274
+            // reload in addition to replace.
275
+            windowLocation.reload();
276
+        }
277
+    };
278
+}

+ 45
- 0
react/features/base/config/actions.js 查看文件

2
 
2
 
3
 import type { Dispatch } from 'redux';
3
 import type { Dispatch } from 'redux';
4
 
4
 
5
+import { addKnownDomains } from '../known-domains';
6
+import { parseURIString } from '../util';
7
+
5
 import {
8
 import {
6
     CONFIG_WILL_LOAD,
9
     CONFIG_WILL_LOAD,
7
     LOAD_CONFIG_ERROR,
10
     LOAD_CONFIG_ERROR,
8
     SET_CONFIG
11
     SET_CONFIG
9
 } from './actionTypes';
12
 } from './actionTypes';
13
+import { _CONFIG_STORE_PREFIX } from './constants';
10
 import { setConfigFromURLParams } from './functions';
14
 import { setConfigFromURLParams } from './functions';
11
 
15
 
12
 /**
16
 /**
87
         });
91
         });
88
     };
92
     };
89
 }
93
 }
94
+
95
+/**
96
+ * Stores a specific Jitsi Meet config.js object into {@code localStorage}.
97
+ *
98
+ * @param {string} baseURL - The base URL from which the config.js was
99
+ * downloaded.
100
+ * @param {Object} config - The Jitsi Meet config.js to store.
101
+ * @returns {Function}
102
+ */
103
+export function storeConfig(baseURL: string, config: Object) {
104
+    return (dispatch: Dispatch<*>) => {
105
+        // Try to store the configuration in localStorage. If the deployment
106
+        // specified 'getroom' as a function, for example, it does not make
107
+        // sense to and it will not be stored.
108
+        let b = false;
109
+
110
+        try {
111
+            if (typeof window.config === 'undefined'
112
+                    || window.config !== config) {
113
+                window.localStorage.setItem(
114
+                    `${_CONFIG_STORE_PREFIX}/${baseURL}`,
115
+                    JSON.stringify(config));
116
+                b = true;
117
+            }
118
+        } catch (e) {
119
+            // Ignore the error because the caching is optional.
120
+        }
121
+
122
+        // If base/config knows a domain, then the app knows it.
123
+        if (b) {
124
+            try {
125
+                dispatch(addKnownDomains(parseURIString(baseURL).host));
126
+            } catch (e) {
127
+                // Ignore the error because the fiddling with "known domains" is
128
+                // a side effect here.
129
+            }
130
+        }
131
+
132
+        return b;
133
+    };
134
+}

+ 8
- 0
react/features/base/config/constants.js 查看文件

1
+/**
2
+ * The prefix of the {@code localStorage} key into which {@link storeConfig}
3
+ * stores and from which {@link restoreConfig} restores.
4
+ *
5
+ * @protected
6
+ * @type string
7
+ */
8
+export const _CONFIG_STORE_PREFIX = 'config.js';

+ 34
- 0
react/features/base/config/functions.js 查看文件

2
 
2
 
3
 import _ from 'lodash';
3
 import _ from 'lodash';
4
 
4
 
5
+import { _CONFIG_STORE_PREFIX } from './constants';
5
 import parseURLParams from './parseURLParams';
6
 import parseURLParams from './parseURLParams';
6
 
7
 
7
 declare var $: Object;
8
 declare var $: Object;
238
     return _.pick(configJSON, WHITELISTED_KEYS);
239
     return _.pick(configJSON, WHITELISTED_KEYS);
239
 }
240
 }
240
 
241
 
242
+/**
243
+ * Restores a Jitsi Meet config.js from {@code localStorage} if it was
244
+ * previously downloaded from a specific {@code baseURL} and stored with
245
+ * {@link storeConfig}.
246
+ *
247
+ * @param {string} baseURL - The base URL from which the config.js was
248
+ * previously downloaded and stored with {@code storeConfig}.
249
+ * @returns {?Object} The Jitsi Meet config.js which was previously downloaded
250
+ * from {@code baseURL} and stored with {@code storeConfig} if it was restored;
251
+ * otherwise, {@code undefined}.
252
+ */
253
+export function restoreConfig(baseURL: string): ?Object {
254
+    let storage;
255
+    const key = `${_CONFIG_STORE_PREFIX}/${baseURL}`;
256
+
257
+    try {
258
+        // XXX Even reading the property localStorage of window may throw an
259
+        // error (which is user agent-specific behavior).
260
+        storage = window.localStorage;
261
+
262
+        const config = storage.getItem(key);
263
+
264
+        if (config) {
265
+            return JSON.parse(config) || undefined;
266
+        }
267
+    } catch (e) {
268
+        // Somehow incorrect data ended up in the storage. Clean it up.
269
+        storage && storage.removeItem(key);
270
+    }
271
+
272
+    return undefined;
273
+}
274
+
241
 /* eslint-disable max-params */
275
 /* eslint-disable max-params */
242
 
276
 
243
 /**
277
 /**

+ 60
- 0
react/features/base/config/middleware.js 查看文件

1
 // @flow
1
 // @flow
2
 
2
 
3
+import { APP_WILL_MOUNT } from '../../app';
4
+import { addKnownDomains } from '../known-domains';
3
 import { MiddlewareRegistry } from '../redux';
5
 import { MiddlewareRegistry } from '../redux';
6
+import { parseURIString } from '../util';
4
 
7
 
5
 import { SET_CONFIG } from './actionTypes';
8
 import { SET_CONFIG } from './actionTypes';
9
+import { _CONFIG_STORE_PREFIX } from './constants';
6
 
10
 
7
 /**
11
 /**
8
  * The middleware of the feature {@code base/config}.
12
  * The middleware of the feature {@code base/config}.
13
  */
17
  */
14
 MiddlewareRegistry.register(store => next => action => {
18
 MiddlewareRegistry.register(store => next => action => {
15
     switch (action.type) {
19
     switch (action.type) {
20
+    case APP_WILL_MOUNT:
21
+        return _appWillMount(store, next, action);
22
+
16
     case SET_CONFIG:
23
     case SET_CONFIG:
17
         return _setConfig(store, next, action);
24
         return _setConfig(store, next, action);
18
     }
25
     }
20
     return next(action);
27
     return next(action);
21
 });
28
 });
22
 
29
 
30
+/**
31
+ * Notifies the feature {@code base/config} that the {@link APP_WILL_MOUNT}
32
+ * redux action is being {@code dispatch}ed in a specific redux store.
33
+ *
34
+ * @param {Store} store - The redux store in which the specified {@code action}
35
+ * is being dispatched.
36
+ * @param {Dispatch} next - The redux {@code dispatch} function to dispatch the
37
+ * specified {@code action} in the specified {@code store}.
38
+ * @param {Action} action - The redux action which is being {@code dispatch}ed
39
+ * in the specified {@code store}.
40
+ * @private
41
+ * @returns {*} The return value of {@code next(action)}.
42
+ */
43
+function _appWillMount(store, next, action) {
44
+    const result = next(action);
45
+
46
+    // It's an opportune time to transfer the feature base/config's knowledge
47
+    // about "known domains" (which is local to the feature) to the feature
48
+    // base/known-domains (which is global to the app).
49
+    //
50
+    // XXX Since the feature base/config predates the feature calendar-sync and,
51
+    // consequently, the feature known-domains, it's possible for the feature
52
+    // base/config to know of domains which the feature known-domains is yet to
53
+    // discover.
54
+    const { localStorage } = window;
55
+
56
+    if (localStorage) {
57
+        const prefix = `${_CONFIG_STORE_PREFIX}/`;
58
+        const knownDomains = [];
59
+
60
+        for (let i = 0; /* localStorage.key(i) */; ++i) {
61
+            const key = localStorage.key(i);
62
+
63
+            if (key) {
64
+                let baseURL;
65
+
66
+                if (key.startsWith(prefix)
67
+                        && (baseURL = key.substring(prefix.length))) {
68
+                    const uri = parseURIString(baseURL);
69
+                    let host;
70
+
71
+                    uri && (host = uri.host) && knownDomains.push(host);
72
+                }
73
+            } else {
74
+                break;
75
+            }
76
+        }
77
+        knownDomains.length && store.dispatch(addKnownDomains(knownDomains));
78
+    }
79
+
80
+    return result;
81
+}
82
+
23
 /**
83
 /**
24
  * Notifies the feature {@code base/config} that the {@link SET_CONFIG} redux
84
  * Notifies the feature {@code base/config} that the {@link SET_CONFIG} redux
25
  * action is being {@code dispatch}ed in a specific redux store.
85
  * action is being {@code dispatch}ed in a specific redux store.

正在加载...
取消
保存