(core) Fix problem with localStorage in some cross-origin embed situations

Summary:
- Handle the possibility that any access to localStorage causes error.
- Move getStorage() and getSessionStorage() safe functions to a separate file.
- Use these safe functions in more places.

Test Plan:
Added a test case, using a webdriver instance that blocks third-party cookies,
to enforce third-party restrictions. Added to gristUtil a way to override the
webdriver instance.

Reviewers: jarek

Reviewed By: jarek

Differential Revision: https://phab.getgrist.com/D3719
This commit is contained in:
Dmitry S
2022-11-30 10:55:47 -05:00
parent 59942a23b6
commit 29a7eadb85
8 changed files with 93 additions and 75 deletions

View File

@@ -4,6 +4,7 @@
*/
import {safeJsonParse} from 'app/common/gutil';
import {IDisposableOwner, Observable} from 'grainjs';
import {getSessionStorage} from 'app/client/lib/storage';
export interface SessionObs<T> extends Observable<T> {
pauseSaving(yesNo: boolean): void;
@@ -45,14 +46,15 @@ export function createSessionObs<T>(
return value === _default || !isValid(value) ? null : JSON.stringify(value);
}
let _pauseSaving = false;
const obs = Observable.create<T>(owner, fromString(window.sessionStorage.getItem(key)));
const storage = getSessionStorage();
const obs = Observable.create<T>(owner, fromString(storage.getItem(key)));
obs.addListener((value: T) => {
if (_pauseSaving) { return; }
const stored = toString(value);
if (stored == null) {
window.sessionStorage.removeItem(key);
storage.removeItem(key);
} else {
window.sessionStorage.setItem(key, stored);
storage.setItem(key, stored);
}
});
return Object.assign(obs, {pauseSaving(yesNo: boolean) { _pauseSaving = yesNo; }});