Browse Source

fix(localStorage): exception when disabled.

master
Hristo Terezov 5 years ago
parent
commit
1ffd75c0a6

+ 2
- 1
connection.js View File

1
 /* global APP, JitsiMeetJS, config */
1
 /* global APP, JitsiMeetJS, config */
2
 
2
 
3
+import { jitsiLocalStorage } from 'js-utils';
4
+
3
 import AuthHandler from './modules/UI/authentication/AuthHandler';
5
 import AuthHandler from './modules/UI/authentication/AuthHandler';
4
-import jitsiLocalStorage from './modules/util/JitsiLocalStorage';
5
 
6
 
6
 import {
7
 import {
7
     connectionEstablished,
8
     connectionEstablished,

+ 1
- 1
modules/UI/util/MessageHandler.js View File

1
 /* global $, APP */
1
 /* global $, APP */
2
 const logger = require('jitsi-meet-logger').getLogger(__filename);
2
 const logger = require('jitsi-meet-logger').getLogger(__filename);
3
 
3
 
4
-import jitsiLocalStorage from '../../util/JitsiLocalStorage';
4
+import { jitsiLocalStorage } from 'js-utils';
5
 
5
 
6
 import {
6
 import {
7
     NOTIFICATION_TIMEOUT,
7
     NOTIFICATION_TIMEOUT,

+ 0
- 77
modules/util/JitsiLocalStorage.js View File

1
-import Logger from 'jitsi-meet-logger';
2
-
3
-const logger = Logger.getLogger(__filename);
4
-
5
-/**
6
- * Dummy implementation of Storage interface with empty methods.
7
- */
8
-class DummyLocalStorage {
9
-    /* eslint-disable no-empty-function */
10
-    /**
11
-     * Empty function
12
-     */
13
-    getItem() { }
14
-
15
-    /**
16
-     * Empty function
17
-     */
18
-    setItem() { }
19
-
20
-    /**
21
-     * Empty function
22
-     */
23
-    removeItem() { }
24
-    /* eslint-enable no-empty-function */
25
-}
26
-
27
-/**
28
- * Wrapper class for browser's local storage object.
29
- */
30
-class JitsiLocalStorage extends DummyLocalStorage {
31
-    /**
32
-     * @constructor
33
-     * @param {Storage} storage browser's local storage object.
34
-     */
35
-    constructor() {
36
-        super();
37
-        let storage;
38
-
39
-        try {
40
-            storage = window.localStorage;
41
-        } catch (error) {
42
-            logger.error(error);
43
-        }
44
-        this.storage = storage || new DummyLocalStorage();
45
-    }
46
-
47
-    /**
48
-     * Returns that passed key's value.
49
-     * @param {string} keyName the name of the key you want to retrieve
50
-     * the value of.
51
-     * @returns {String|null} the value of the key. If the key does not exist,
52
-     * null is returned.
53
-     */
54
-    getItem(keyName) {
55
-        return this.storage.getItem(keyName);
56
-    }
57
-
58
-    /**
59
-     * Adds a key to the storage, or update key's value if it already exists.
60
-     * @param {string} keyName the name of the key you want to create/update.
61
-     * @param {string} keyValue the value you want to give the key you are
62
-     * creating/updating.
63
-     */
64
-    setItem(keyName, keyValue) {
65
-        return this.storage.setItem(keyName, keyValue);
66
-    }
67
-
68
-    /**
69
-     * Remove a key from the storage.
70
-     * @param {string} keyName the name of the key you want to remove.
71
-     */
72
-    removeItem(keyName) {
73
-        return this.storage.removeItem(keyName);
74
-    }
75
-}
76
-
77
-export default new JitsiLocalStorage();

+ 18
- 2
package-lock.json View File

10594
       "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls="
10594
       "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls="
10595
     },
10595
     },
10596
     "js-utils": {
10596
     "js-utils": {
10597
-      "version": "github:jitsi/js-utils#df68966e3c65b5c57fcd2670da1326a2c77518d1",
10598
-      "from": "github:jitsi/js-utils#df68966e3c65b5c57fcd2670da1326a2c77518d1",
10597
+      "version": "github:jitsi/js-utils#efb02828785b2b532097d96f4b32a101847ba58b",
10598
+      "from": "github:jitsi/js-utils#efb02828785b2b532097d96f4b32a101847ba58b",
10599
       "requires": {
10599
       "requires": {
10600
         "bowser": "2.7.0",
10600
         "bowser": "2.7.0",
10601
         "js-md5": "0.7.3",
10601
         "js-md5": "0.7.3",
10809
         "strophejs-plugin-disco": "0.0.2",
10809
         "strophejs-plugin-disco": "0.0.2",
10810
         "strophejs-plugin-stream-management": "github:jitsi/strophejs-plugin-stream-management#e719a02b4f83856c1530882084a4b048ee622d45",
10810
         "strophejs-plugin-stream-management": "github:jitsi/strophejs-plugin-stream-management#e719a02b4f83856c1530882084a4b048ee622d45",
10811
         "webrtc-adapter": "7.5.0"
10811
         "webrtc-adapter": "7.5.0"
10812
+      },
10813
+      "dependencies": {
10814
+        "js-md5": {
10815
+          "version": "0.7.3",
10816
+          "resolved": "https://registry.npmjs.org/js-md5/-/js-md5-0.7.3.tgz",
10817
+          "integrity": "sha512-ZC41vPSTLKGwIRjqDh8DfXoCrdQIyBgspJVPXHBGu4nZlAEvG3nf+jO9avM9RmLiGakg7vz974ms99nEV0tmTQ=="
10818
+        },
10819
+        "js-utils": {
10820
+          "version": "github:jitsi/js-utils#df68966e3c65b5c57fcd2670da1326a2c77518d1",
10821
+          "from": "github:jitsi/js-utils#df68966e3c65b5c57fcd2670da1326a2c77518d1",
10822
+          "requires": {
10823
+            "bowser": "2.7.0",
10824
+            "js-md5": "0.7.3",
10825
+            "postis": "2.2.0"
10826
+          }
10827
+        }
10812
       }
10828
       }
10813
     },
10829
     },
10814
     "libflacjs": {
10830
     "libflacjs": {

+ 1
- 1
package.json View File

53
     "jquery-contextmenu": "2.4.5",
53
     "jquery-contextmenu": "2.4.5",
54
     "jquery-i18next": "1.2.1",
54
     "jquery-i18next": "1.2.1",
55
     "js-md5": "0.6.1",
55
     "js-md5": "0.6.1",
56
-    "js-utils": "github:jitsi/js-utils#df68966e3c65b5c57fcd2670da1326a2c77518d1",
56
+    "js-utils": "github:jitsi/js-utils#efb02828785b2b532097d96f4b32a101847ba58b",
57
     "jsrsasign": "8.0.12",
57
     "jsrsasign": "8.0.12",
58
     "jwt-decode": "2.2.0",
58
     "jwt-decode": "2.2.0",
59
     "lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#dffe94f270f692c7421412bbbc597279e4a2d805",
59
     "lib-jitsi-meet": "github:jitsi/lib-jitsi-meet#dffe94f270f692c7421412bbbc597279e4a2d805",

+ 2
- 2
react/features/base/app/components/BaseApp.js View File

1
 // @flow
1
 // @flow
2
 
2
 
3
+import { jitsiLocalStorage } from 'js-utils';
3
 import _ from 'lodash';
4
 import _ from 'lodash';
4
 import React, { Component, Fragment } from 'react';
5
 import React, { Component, Fragment } from 'react';
5
 import { I18nextProvider } from 'react-i18next';
6
 import { I18nextProvider } from 'react-i18next';
15
 } from '../../redux';
16
 } from '../../redux';
16
 import { SoundCollection } from '../../sounds';
17
 import { SoundCollection } from '../../sounds';
17
 import { PersistenceRegistry } from '../../storage';
18
 import { PersistenceRegistry } from '../../storage';
18
-
19
 import { appWillMount, appWillUnmount } from '../actions';
19
 import { appWillMount, appWillUnmount } from '../actions';
20
 import logger from '../logger';
20
 import logger from '../logger';
21
 
21
 
110
      * @returns {Promise}
110
      * @returns {Promise}
111
      */
111
      */
112
     _initStorage(): Promise<*> {
112
     _initStorage(): Promise<*> {
113
-        const { _initializing } = window.localStorage;
113
+        const _initializing = jitsiLocalStorage.getItem('_initializing');
114
 
114
 
115
         return _initializing || Promise.resolve();
115
         return _initializing || Promise.resolve();
116
     }
116
     }

+ 3
- 5
react/features/base/config/actions.js View File

1
 // @flow
1
 // @flow
2
 
2
 
3
+import { jitsiLocalStorage } from 'js-utils';
3
 import type { Dispatch } from 'redux';
4
 import type { Dispatch } from 'redux';
4
 
5
 
5
 import { addKnownDomains } from '../known-domains';
6
 import { addKnownDomains } from '../known-domains';
109
         let b = false;
110
         let b = false;
110
 
111
 
111
         try {
112
         try {
112
-            if (typeof window.config === 'undefined'
113
-                    || window.config !== config) {
114
-                window.localStorage.setItem(
115
-                    `${_CONFIG_STORE_PREFIX}/${baseURL}`,
116
-                    JSON.stringify(config));
113
+            if (typeof window.config === 'undefined' || window.config !== config) {
114
+                jitsiLocalStorage.setItem(`${_CONFIG_STORE_PREFIX}/${baseURL}`, JSON.stringify(config));
117
                 b = true;
115
                 b = true;
118
             }
116
             }
119
         } catch (e) {
117
         } catch (e) {

+ 7
- 12
react/features/base/config/functions.any.js View File

1
 // @flow
1
 // @flow
2
 
2
 
3
+import { jitsiLocalStorage } from 'js-utils';
3
 import _ from 'lodash';
4
 import _ from 'lodash';
4
 
5
 
5
 import CONFIG_WHITELIST from './configWhitelist';
6
 import CONFIG_WHITELIST from './configWhitelist';
136
  * otherwise, {@code undefined}.
137
  * otherwise, {@code undefined}.
137
  */
138
  */
138
 export function restoreConfig(baseURL: string): ?Object {
139
 export function restoreConfig(baseURL: string): ?Object {
139
-    let storage;
140
     const key = `${_CONFIG_STORE_PREFIX}/${baseURL}`;
140
     const key = `${_CONFIG_STORE_PREFIX}/${baseURL}`;
141
+    const config = jitsiLocalStorage.getItem(key);
141
 
142
 
142
-    try {
143
-        // XXX Even reading the property localStorage of window may throw an
144
-        // error (which is user agent-specific behavior).
145
-        storage = window.localStorage;
146
-
147
-        const config = storage.getItem(key);
148
-
149
-        if (config) {
143
+    if (config) {
144
+        try {
150
             return JSON.parse(config) || undefined;
145
             return JSON.parse(config) || undefined;
146
+        } catch (e) {
147
+            // Somehow incorrect data ended up in the storage. Clean it up.
148
+            jitsiLocalStorage.removeItem(key);
151
         }
149
         }
152
-    } catch (e) {
153
-        // Somehow incorrect data ended up in the storage. Clean it up.
154
-        storage && storage.removeItem(key);
155
     }
150
     }
156
 
151
 
157
     return undefined;
152
     return undefined;

+ 16
- 17
react/features/base/config/middleware.js View File

1
 // @flow
1
 // @flow
2
 
2
 
3
+import { jitsiLocalStorage } from 'js-utils';
4
+
3
 import { APP_WILL_MOUNT } from '../app';
5
 import { APP_WILL_MOUNT } from '../app';
4
 import { addKnownDomains } from '../known-domains';
6
 import { addKnownDomains } from '../known-domains';
5
 import { MiddlewareRegistry } from '../redux';
7
 import { MiddlewareRegistry } from '../redux';
51
     // consequently, the feature known-domains, it's possible for the feature
53
     // 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
54
     // base/config to know of domains which the feature known-domains is yet to
53
     // discover.
55
     // discover.
54
-    const { localStorage } = window;
55
 
56
 
56
-    if (localStorage) {
57
-        const prefix = `${_CONFIG_STORE_PREFIX}/`;
58
-        const knownDomains = [];
57
+    const prefix = `${_CONFIG_STORE_PREFIX}/`;
58
+    const knownDomains = [];
59
 
59
 
60
-        for (let i = 0; /* localStorage.key(i) */; ++i) {
61
-            const key = localStorage.key(i);
60
+    for (let i = 0; /* localStorage.key(i) */; ++i) {
61
+        const key = jitsiLocalStorage.key(i);
62
 
62
 
63
-            if (key) {
64
-                let baseURL;
63
+        if (key) {
64
+            let baseURL;
65
 
65
 
66
-                if (key.startsWith(prefix)
67
-                        && (baseURL = key.substring(prefix.length))) {
68
-                    const uri = parseURIString(baseURL);
69
-                    let host;
66
+            if (key.startsWith(prefix)
67
+                    && (baseURL = key.substring(prefix.length))) {
68
+                const uri = parseURIString(baseURL);
69
+                let host;
70
 
70
 
71
-                    uri && (host = uri.host) && knownDomains.push(host);
72
-                }
73
-            } else {
74
-                break;
71
+                uri && (host = uri.host) && knownDomains.push(host);
75
             }
72
             }
73
+        } else {
74
+            break;
76
         }
75
         }
77
-        knownDomains.length && store.dispatch(addKnownDomains(knownDomains));
78
     }
76
     }
77
+    knownDomains.length && store.dispatch(addKnownDomains(knownDomains));
79
 
78
 
80
     return result;
79
     return result;
81
 }
80
 }

+ 9
- 12
react/features/base/settings/reducer.js View File

1
 // @flow
1
 // @flow
2
 
2
 
3
+import { jitsiLocalStorage } from 'js-utils';
3
 import { randomHexString } from 'js-utils/random';
4
 import { randomHexString } from 'js-utils/random';
4
 import _ from 'lodash';
5
 import _ from 'lodash';
5
 
6
 
86
  * @returns {Object}
87
  * @returns {Object}
87
  */
88
  */
88
 function _getLegacyProfile() {
89
 function _getLegacyProfile() {
89
-    let persistedProfile
90
-        = window.localStorage.getItem('features/base/profile');
90
+    let persistedProfile = jitsiLocalStorage.getItem('features/base/profile');
91
 
91
 
92
     if (persistedProfile) {
92
     if (persistedProfile) {
93
         try {
93
         try {
123
     // FIXME: jibri uses old settings.js local storage values to set its display
123
     // FIXME: jibri uses old settings.js local storage values to set its display
124
     // name and email. Provide another way for jibri to set these values, update
124
     // name and email. Provide another way for jibri to set these values, update
125
     // jibri, and remove the old settings.js values.
125
     // jibri, and remove the old settings.js values.
126
-    const savedDisplayName = window.localStorage.getItem('displayname');
127
-    const savedEmail = window.localStorage.getItem('email');
128
-    let avatarID = _.escape(window.localStorage.getItem('avatarId'));
126
+    const savedDisplayName = jitsiLocalStorage.getItem('displayname');
127
+    const savedEmail = jitsiLocalStorage.getItem('email');
128
+    let avatarID = _.escape(jitsiLocalStorage.getItem('avatarId'));
129
 
129
 
130
     // The helper _.escape will convert null to an empty strings. The empty
130
     // The helper _.escape will convert null to an empty strings. The empty
131
     // string will be saved in settings. On app re-load, because an empty string
131
     // string will be saved in settings. On app re-load, because an empty string
149
 
149
 
150
     if (!browser.isReactNative()) {
150
     if (!browser.isReactNative()) {
151
         // Browser only
151
         // Browser only
152
-        const localFlipX
153
-            = JSON.parse(window.localStorage.getItem('localFlipX') || 'true');
154
-        const cameraDeviceId
155
-            = window.localStorage.getItem('cameraDeviceId') || '';
156
-        const micDeviceId = window.localStorage.getItem('micDeviceId') || '';
152
+        const localFlipX = JSON.parse(jitsiLocalStorage.getItem('localFlipX') || 'true');
153
+        const cameraDeviceId = jitsiLocalStorage.getItem('cameraDeviceId') || '';
154
+        const micDeviceId = jitsiLocalStorage.getItem('micDeviceId') || '';
157
 
155
 
158
         // Currently audio output device change is supported only in Chrome and
156
         // Currently audio output device change is supported only in Chrome and
159
         // default output always has 'default' device ID
157
         // default output always has 'default' device ID
160
-        const audioOutputDeviceId
161
-            = window.localStorage.getItem('audioOutputDeviceId') || 'default';
158
+        const audioOutputDeviceId = jitsiLocalStorage.getItem('audioOutputDeviceId') || 'default';
162
 
159
 
163
         settings = assignIfDefined({
160
         settings = assignIfDefined({
164
             audioOutputDeviceId,
161
             audioOutputDeviceId,

+ 7
- 13
react/features/base/storage/PersistenceRegistry.js View File

1
 // @flow
1
 // @flow
2
 
2
 
3
 import md5 from 'js-md5';
3
 import md5 from 'js-md5';
4
+import { jitsiLocalStorage } from 'js-utils';
4
 
5
 
5
 import logger from './logger';
6
 import logger from './logger';
6
 
7
 
63
 
64
 
64
         // legacy
65
         // legacy
65
         if (Object.keys(filteredPersistedState).length === 0) {
66
         if (Object.keys(filteredPersistedState).length === 0) {
66
-            const { localStorage } = window;
67
-            let persistedState = localStorage.getItem(PERSISTED_STATE_NAME);
67
+            let persistedState = jitsiLocalStorage.getItem(PERSISTED_STATE_NAME);
68
 
68
 
69
             if (persistedState) {
69
             if (persistedState) {
70
                 try {
70
                 try {
82
                 // Store into the new format and delete the old format so that
82
                 // Store into the new format and delete the old format so that
83
                 // it's not used again.
83
                 // it's not used again.
84
                 this.persistState(filteredPersistedState);
84
                 this.persistState(filteredPersistedState);
85
-                localStorage.removeItem(PERSISTED_STATE_NAME);
85
+                jitsiLocalStorage.removeItem(PERSISTED_STATE_NAME);
86
             }
86
             }
87
         }
87
         }
88
 
88
 
110
         if (checksum !== this._checksum) {
110
         if (checksum !== this._checksum) {
111
             for (const subtreeName of Object.keys(filteredState)) {
111
             for (const subtreeName of Object.keys(filteredState)) {
112
                 try {
112
                 try {
113
-                    window.localStorage.setItem(
114
-                        subtreeName,
115
-                        JSON.stringify(filteredState[subtreeName]));
113
+                    jitsiLocalStorage.setItem(subtreeName, JSON.stringify(filteredState[subtreeName]));
116
                 } catch (error) {
114
                 } catch (error) {
117
-                    logger.error(
118
-                        'Error persisting redux subtree',
119
-                        subtreeName,
120
-                        error);
115
+                    logger.error('Error persisting redux subtree', subtreeName, error);
121
                 }
116
                 }
122
             }
117
             }
123
-            logger.info(
124
-                `redux state persisted. ${this._checksum} -> ${checksum}`);
118
+            logger.info(`redux state persisted. ${this._checksum} -> ${checksum}`);
125
             this._checksum = checksum;
119
             this._checksum = checksum;
126
         }
120
         }
127
     }
121
     }
225
      * @returns {Object}
219
      * @returns {Object}
226
      */
220
      */
227
     _getPersistedSubtree(subtreeName, subtreeConfig, subtreeDefaults) {
221
     _getPersistedSubtree(subtreeName, subtreeConfig, subtreeDefaults) {
228
-        let persistedSubtree = window.localStorage.getItem(subtreeName);
222
+        let persistedSubtree = jitsiLocalStorage.getItem(subtreeName);
229
 
223
 
230
         if (persistedSubtree) {
224
         if (persistedSubtree) {
231
             try {
225
             try {

+ 13
- 8
react/features/chrome-extension-banner/components/ChromeExtensionBanner.web.js View File

1
 // @flow
1
 // @flow
2
+
3
+import { jitsiLocalStorage } from 'js-utils';
2
 import React, { PureComponent } from 'react';
4
 import React, { PureComponent } from 'react';
3
-import { connect } from '../../base/redux';
5
+
6
+import {
7
+    createChromeExtensionBannerEvent,
8
+    sendAnalytics
9
+} from '../../analytics';
10
+import { getCurrentConference } from '../../base/conference/functions';
4
 import { Icon, IconClose } from '../../base/icons';
11
 import { Icon, IconClose } from '../../base/icons';
5
 import { translate } from '../../base/i18n';
12
 import { translate } from '../../base/i18n';
6
-import { getCurrentConference } from '../../base/conference/functions';
7
 import { browser } from '../../base/lib-jitsi-meet';
13
 import { browser } from '../../base/lib-jitsi-meet';
14
+import { connect } from '../../base/redux';
8
 import {
15
 import {
9
     checkChromeExtensionsInstalled,
16
     checkChromeExtensionsInstalled,
10
     isMobileBrowser
17
     isMobileBrowser
11
 } from '../../base/environment/utils';
18
 } from '../../base/environment/utils';
19
+
12
 import logger from '../logger';
20
 import logger from '../logger';
13
-import {
14
-    createChromeExtensionBannerEvent,
15
-    sendAnalytics
16
-} from '../../analytics';
21
+
17
 
22
 
18
 declare var interfaceConfig: Object;
23
 declare var interfaceConfig: Object;
19
 
24
 
182
             return true;
187
             return true;
183
         }
188
         }
184
 
189
 
185
-        const dontShowAgain = localStorage.getItem(DONT_SHOW_AGAIN_CHECKED) === 'true';
190
+        const dontShowAgain = jitsiLocalStorage.getItem(DONT_SHOW_AGAIN_CHECKED) === 'true';
186
 
191
 
187
         return !this.props.bannerCfg.url
192
         return !this.props.bannerCfg.url
188
             || dontShowAgain
193
             || dontShowAgain
212
     render() {
217
     render() {
213
         if (this._shouldNotRender()) {
218
         if (this._shouldNotRender()) {
214
             if (this.state.dontShowAgainChecked) {
219
             if (this.state.dontShowAgainChecked) {
215
-                localStorage.setItem(DONT_SHOW_AGAIN_CHECKED, 'true');
220
+                jitsiLocalStorage.setItem(DONT_SHOW_AGAIN_CHECKED, 'true');
216
             }
221
             }
217
 
222
 
218
             return null;
223
             return null;

+ 1
- 1
react/features/local-recording/session/SessionManager.js View File

1
 /* @flow */
1
 /* @flow */
2
 
2
 
3
-import jitsiLocalStorage from '../../../../modules/util/JitsiLocalStorage';
3
+import { jitsiLocalStorage } from 'js-utils';
4
 
4
 
5
 import logger from '../logger';
5
 import logger from '../logger';
6
 
6
 

+ 9
- 5
react/features/recent-list/reducer.js View File

1
 // @flow
1
 // @flow
2
+
3
+import { jitsiLocalStorage } from 'js-utils';
4
+
2
 import { APP_WILL_MOUNT } from '../base/app';
5
 import { APP_WILL_MOUNT } from '../base/app';
3
 import { getURLWithoutParamsNormalized } from '../base/connection';
6
 import { getURLWithoutParamsNormalized } from '../base/connection';
4
 import { ReducerRegistry } from '../base/redux';
7
 import { ReducerRegistry } from '../base/redux';
119
  * @returns {Array<Object>}
122
  * @returns {Array<Object>}
120
  */
123
  */
121
 function _getLegacyRecentRoomList(): Array<Object> {
124
 function _getLegacyRecentRoomList(): Array<Object> {
122
-    try {
123
-        const str = window.localStorage.getItem(LEGACY_STORAGE_KEY);
125
+    const str = jitsiLocalStorage.getItem(LEGACY_STORAGE_KEY);
124
 
126
 
125
-        if (str) {
127
+    if (str) {
128
+        try {
126
             return JSON.parse(str);
129
             return JSON.parse(str);
130
+        } catch (error) {
131
+            logger.warn('Failed to parse legacy recent-room list!');
127
         }
132
         }
128
-    } catch (error) {
129
-        logger.warn('Failed to parse legacy recent-room list!');
130
     }
133
     }
131
 
134
 
135
+
132
     return [];
136
     return [];
133
 }
137
 }
134
 
138
 

Loading…
Cancel
Save