From b993d98483624ac3e27474a0391ed23dc43aef59 Mon Sep 17 00:00:00 2001 From: sisou Date: Thu, 22 Oct 2020 10:11:56 +0200 Subject: [PATCH] Handle blocked access to local/session storage --- client/src/PublicRequest.ts | 4 ++++ src/components/TabWidthSelector.js | 14 ++++++++++++-- src/lib/ErrorConstants.js | 4 ++++ src/lib/Errors.js | 9 +++++++++ src/lib/RpcServer.es.js | 20 ++++++++++++++------ src/request/import/ImportApi.js | 8 ++++++++ 6 files changed, 51 insertions(+), 8 deletions(-) diff --git a/client/src/PublicRequest.ts b/client/src/PublicRequest.ts index 023884e3a..7c907d5cd 100644 --- a/client/src/PublicRequest.ts +++ b/client/src/PublicRequest.ts @@ -230,6 +230,8 @@ export type KeyguardError = { CORE: 'Core', // used for internal keyguard Errors. KEYGUARD: 'Keyguard', + // used for errors caused by the browser and its configuration + BROWSER: 'Browser', // used for the remaining Errors which are not assigned an own type just yet. UNCLASSIFIED: 'Unclassified', }, @@ -246,5 +248,7 @@ export type KeyguardError = { KEY_NOT_FOUND: 'keyId not found', // network name does not exist INVALID_NETWORK_CONFIG: 'Invalid network config', + // when the browser prevents access to LocalStorage or SessionStorage (because of privacy settings) + NO_STORAGE_ACCESS: 'Cannot access browser storage because of privacy settings', }, }; diff --git a/src/components/TabWidthSelector.js b/src/components/TabWidthSelector.js index a776319fa..00107e790 100644 --- a/src/components/TabWidthSelector.js +++ b/src/components/TabWidthSelector.js @@ -12,7 +12,13 @@ class TabWidthSelector extends Nimiq.Observable { this.$el = TabWidthSelector._createElement($el); // Load last used width from localStorage. - this._tabWidth = localStorage.getItem(TabWidthSelector.LOCALSTORAGE_KEY) || TabWidthSelector.DEFAULT_TAB_WIDTH; + try { + /** @type {string} */ + this._tabWidth = localStorage.getItem(TabWidthSelector.LOCALSTORAGE_KEY) || ''; + } catch (error) { + // Ignore + } + this._tabWidth = this._tabWidth || TabWidthSelector.DEFAULT_TAB_WIDTH; this._updateClasses(); this.$width2Button = /** @type {HTMLButtonElement} */ (this.$el.querySelector('button[data-width="2"]')); @@ -67,7 +73,11 @@ class TabWidthSelector extends Nimiq.Observable { _updateWidth(width) { this._tabWidth = width; this._updateClasses(); - localStorage.setItem(TabWidthSelector.LOCALSTORAGE_KEY, this._tabWidth); + try { + localStorage.setItem(TabWidthSelector.LOCALSTORAGE_KEY, this._tabWidth); + } catch (error) { + // Ignore + } this.fire(TabWidthSelector.Events.INPUT, this._tabWidth); } diff --git a/src/lib/ErrorConstants.js b/src/lib/ErrorConstants.js index bb3b16b59..8a546f527 100644 --- a/src/lib/ErrorConstants.js +++ b/src/lib/ErrorConstants.js @@ -7,6 +7,8 @@ const ErrorConstants = { CORE: 'Core', // used for other internal keyguard Errors. KEYGUARD: 'Keyguard', + // used for errors caused by the browser and its configuration + BROWSER: 'Browser', // used for the remaining Errors which are not assigned an own type just yet. UNCLASSIFIED: 'Unclassified', }, @@ -23,6 +25,8 @@ const ErrorConstants = { KEY_NOT_FOUND: 'keyId not found', // network name does not exist INVALID_NETWORK_CONFIG: 'Invalid network config', + // when the browser prevents access to LocalStorage or SessionStorage (because of privacy settings) + NO_STORAGE_ACCESS: 'Cannot access browser storage because of privacy settings', }, }; diff --git a/src/lib/Errors.js b/src/lib/Errors.js index f2e1ebeca..b9ba765c3 100644 --- a/src/lib/Errors.js +++ b/src/lib/Errors.js @@ -54,6 +54,15 @@ Errors.KeyguardError = class extends Errors.BaseError { } }; +Errors.BrowserError = class extends Errors.BaseError { + /** + * @param {string|Error} [messageOrError] + */ + constructor(messageOrError) { + super(ErrorConstants.Types.BROWSER, messageOrError); + } +}; + Errors.UnclassifiedError = class extends Errors.BaseError { /** * @param {string|Error} [messageOrError] diff --git a/src/lib/RpcServer.es.js b/src/lib/RpcServer.es.js index e7a07fe28..a6ee3d920 100644 --- a/src/lib/RpcServer.es.js +++ b/src/lib/RpcServer.es.js @@ -250,11 +250,15 @@ class RpcServer { // eslint-disable-line no-unused-vars // Check for a stored request referenced by a URL 'id' parameter const searchParams = new URLSearchParams(window.location.search); if (searchParams.has(UrlRpcEncoder.URL_SEARCHPARAM_NAME)) { - const storedRequest = window.sessionStorage.getItem( - `request-${searchParams.get(UrlRpcEncoder.URL_SEARCHPARAM_NAME)}`, - ); - if (storedRequest) { - return this._receive(JsonUtils.parse(storedRequest), false); + try { + const storedRequest = window.sessionStorage.getItem( + `request-${searchParams.get(UrlRpcEncoder.URL_SEARCHPARAM_NAME)}`, + ); + if (storedRequest) { + return this._receive(JsonUtils.parse(storedRequest), false); + } + } catch (error) { + // Ignore SessionStorage access error } } @@ -292,7 +296,11 @@ class RpcServer { // eslint-disable-line no-unused-vars console.debug('RpcServer ACCEPT', state.data); if (persistMessage) { - sessionStorage.setItem(`request-${state.data.id}`, JsonUtils.stringify(state.toRequestObject())); + try { + sessionStorage.setItem(`request-${state.data.id}`, JsonUtils.stringify(state.toRequestObject())); + } catch (error) { + // Ignore SessionStorage access error + } } // Call method diff --git a/src/request/import/ImportApi.js b/src/request/import/ImportApi.js index 3d9610db5..036ecf98c 100644 --- a/src/request/import/ImportApi.js +++ b/src/request/import/ImportApi.js @@ -2,6 +2,7 @@ /* global ImportFile */ /* global ImportWords */ /* global Errors */ +/* global ErrorConstants */ /** @extends {TopLevelApi} */ class ImportApi extends TopLevelApi { @@ -14,6 +15,13 @@ class ImportApi extends TopLevelApi { throw new Errors.InvalidRequestError('request is required'); } + try { + sessionStorage.setItem('_test', 'write-access'); + sessionStorage.removeItem('_test'); + } catch (e) { + throw new Errors.BrowserError(ErrorConstants.Messages.NO_STORAGE_ACCESS); + } + const parsedRequest = {}; parsedRequest.appName = this.parseAppName(request.appName); parsedRequest.requestedKeyPaths = this.parsePathsArray(request.requestedKeyPaths, ' requestedKeyPaths');