fix(docs-infra): do not break when cookies are disabled in the browser (#33829)

Whenever cookies are disabled in the browser, `window.sessionStorage` is not avaialable to the app (i.e. even trying to access `window.sessionStorage` throws an error).

To avoid breaking the app, we use a no-op `Storage` implementation if `window.sessionStorage` is not available.

Fixes #33795

PR Close #33829
This commit is contained in:
ajitsinghkaler 2019-11-18 23:26:38 +05:30 committed by Alex Rickabaugh
parent 8555d51bc7
commit f69c6e204a
2 changed files with 38 additions and 6 deletions

View File

@ -94,6 +94,22 @@ describe('ScrollService', () => {
}
});
it('should not break when cookies are disabled in the browser', () => {
// Simulate `window.sessionStorage` being inaccessible, when cookies are disabled.
spyOnProperty(window, 'sessionStorage', 'get').and.throwError('The operation is insecure');
expect(() => {
const platformLoc = platformLocation as PlatformLocation;
const service = new ScrollService(document, platformLoc, viewportScrollerStub, location);
service.updateScrollLocationHref();
expect(service.getStoredScrollLocationHref()).toBeNull();
service.removeStoredScrollInfo();
expect(service.getStoredScrollPosition()).toBeNull();
}).not.toThrow();
});
describe('#topOffset', () => {
it('should query for the top-bar by CSS selector', () => {
expect(document.querySelector).not.toHaveBeenCalled();

View File

@ -19,6 +19,7 @@ export class ScrollService implements OnDestroy {
private _topOffset: number | null;
private _topOfPageElement: Element;
private onDestroy = new Subject<void>();
private storage: Storage;
// The scroll position which has to be restored, after a `popstate` event.
poppedStateScrollPosition: ScrollPosition | null = null;
@ -49,6 +50,21 @@ export class ScrollService implements OnDestroy {
private platformLocation: PlatformLocation,
private viewportScroller: ViewportScroller,
private location: Location) {
try {
this.storage = window.sessionStorage;
} catch {
// When cookies are disabled in the browser, even trying to access
// `window.sessionStorage` throws an error. Use a no-op storage.
this.storage = {
length: 0,
clear: () => undefined,
getItem: () => null,
key: () => null,
removeItem: () => undefined,
setItem: () => undefined
};
}
// On resize, the toolbar might change height, so "invalidate" the top offset.
fromEvent(window, 'resize')
.pipe(takeUntil(this.onDestroy))
@ -180,7 +196,7 @@ export class ScrollService implements OnDestroy {
}
updateScrollLocationHref(): void {
window.sessionStorage.setItem('scrollLocationHref', window.location.href);
this.storage.setItem('scrollLocationHref', window.location.href);
}
/**
@ -190,17 +206,17 @@ export class ScrollService implements OnDestroy {
if (this.supportManualScrollRestoration) {
const currentScrollPosition = this.viewportScroller.getScrollPosition();
this.location.replaceState(this.location.path(true), undefined, {scrollPosition: currentScrollPosition});
window.sessionStorage.setItem('scrollPosition', currentScrollPosition.join(','));
this.storage.setItem('scrollPosition', currentScrollPosition.join(','));
}
}
getStoredScrollLocationHref(): string | null {
const href = window.sessionStorage.getItem('scrollLocationHref');
const href = this.storage.getItem('scrollLocationHref');
return href || null;
}
getStoredScrollPosition(): ScrollPosition | null {
const position = window.sessionStorage.getItem('scrollPosition');
const position = this.storage.getItem('scrollPosition');
if (!position) { return null; }
const [x, y] = position.split(',');
@ -208,8 +224,8 @@ export class ScrollService implements OnDestroy {
}
removeStoredScrollInfo() {
window.sessionStorage.removeItem('scrollLocationHref');
window.sessionStorage.removeItem('scrollPosition');
this.storage.removeItem('scrollLocationHref');
this.storage.removeItem('scrollPosition');
}
/**