[27105] Guard access to localStorage in case of NS_ERROR_FILE_CORRUPTED (#6161)

Firefox may end up with a corrupted localStorage database that will
raise exceptions on each getItem/setItem. Since this is a browser error
and there's nothing we can do, we can shield the user from these errors
instead.

https://community.openproject.com/wp/27105

[ci skip]
pull/6162/head
Oliver Günther 7 years ago committed by GitHub
parent 5a4389eaad
commit 33718cbba1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 12
      app/assets/javascripts/members_form.js
  2. 4
      frontend/app/components/table-pagination/pagination-service.ts
  3. 6
      frontend/app/components/wp-resizer/wp-resizer.directive.ts
  4. 25
      frontend/app/globals/openproject.ts
  5. 6
      frontend/app/globals/top-shelf.ts
  6. 7
      frontend/app/typings/shims.d.ts

@ -35,13 +35,13 @@ jQuery(document).ready(function($) {
});
// Show/Hide content when page is loaded
if (localStorage.getItem("showFilter") === "true") {
if (window.OpenProject.guardedLocalStorage("showFilter") === "true") {
showFilter(filter = findFilter());
}
else {
hideFilter(filter = findFilter());
// In case showFilter is not set yet
localStorage.setItem("showFilter", 'false')
window.OpenProject.guardedLocalStorage("showFilter", 'false')
}
// show member form only when there's an error
@ -55,13 +55,13 @@ jQuery(document).ready(function($) {
});
function toggleMemberFilter() {
if (localStorage.getItem("showFilter") === "true") {
localStorage.setItem("showFilter", 'false');
if (window.OpenProject.guardedLocalStorage("showFilter") === "true") {
window.OpenProject.guardedLocalStorage("showFilter", 'false');
hideFilter(filter);
jQuery('#filter-member-button').removeClass('-active');
}
else {
localStorage.setItem("showFilter", 'true');
window.OpenProject.guardedLocalStorage("showFilter", 'true');
showFilter(filter);
jQuery('#filter-member-button').addClass('-active');
hideAddMemberForm();
@ -74,7 +74,7 @@ function showAddMemberForm() {
jQuery('#members_add_form #principal_search').focus();
hideFilter(filter = findFilter());
jQuery('#filter-member-button').removeClass('-active');
localStorage.setItem("showFilter", 'false');
window.OpenProject.guardedLocalStorage("showFilter", 'false');
jQuery('#add-member-button').prop('disabled', true);
}

@ -67,7 +67,7 @@ export class PaginationService {
}
public getCachedPerPage(initialPageOptions:number[]):number {
const value = window.localStorage.getItem('pagination.perPage');
const value = window.OpenProject.guardedLocalStorage('pagination.perPage');
const perPage = parseInt(value!, 10);
if (perPage > 0) {
@ -98,7 +98,7 @@ export class PaginationService {
}
public setPerPage(perPage:number) {
window.localStorage.setItem('pagination.perPage', perPage.toString());
window.OpenProject.guardedLocalStorage('pagination.perPage', perPage.toString());
this.paginationOptions.perPage = perPage;
}

@ -46,7 +46,7 @@ export class WorkPackageResizerController {
this.resizingElement = <HTMLElement>document.getElementsByClassName(this.elementClass)[0];
// Get inital width from local storage and apply
let localStorageValue = localStorage.getItem(this.localStorageKey);
let localStorageValue = window.OpenProject.guardedLocalStorage(this.localStorageKey);
this.elementFlex = localStorageValue ? parseInt(localStorageValue, 10) : this.resizingElement.offsetWidth;
// This case only happens when the timeline is loaded but not displayed.
@ -96,7 +96,7 @@ export class WorkPackageResizerController {
// Take care at the end that the elemntFlex-Value is the same as the acutal value
// When the mouseup is outside the container these values will differ
// which will cause problems at the next movement start
let localStorageValue = localStorage.getItem(this.localStorageKey);
let localStorageValue = window.OpenProject.guardedLocalStorage(this.localStorageKey);
if (localStorageValue) {
this.elementFlex = parseInt(localStorageValue, 10);
}
@ -120,7 +120,7 @@ export class WorkPackageResizerController {
let newValue = this.elementFlex < 480 ? 480 : this.elementFlex;
// Store item in local storage
localStorage.setItem(this.localStorageKey, String(newValue));
window.OpenProject.guardedLocalStorage(this.localStorageKey, String(newValue));
// Apply two column layout
element.classList.toggle('-columns-2', newValue > 700);

@ -62,6 +62,29 @@ export class OpenProject {
return jQuery('meta[name=openproject_initializer]').data('environment');
}
/**
* Guard access to reads and writes to the localstorage due to corrupted local databases
* in Firefox happening in one larger client.
*
* NS_ERROR_FILE_CORRUPTED
*
* @param {string} key
* @param {string} newValue
* @returns {string | undefined}
*/
public guardedLocalStorage(key:string, newValue?:string):string|void {
try {
if (newValue !== undefined) {
window.localStorage.setItem(key, newValue);
} else {
const value = window.localStorage.getItem(key)
return value === null ? undefined : value;
}
} catch (e) {
console.error('Failed to access your browsers local storage. Is your local database corrupted?');
}
}
public get Helpers() {
return {
Angular: new OpenProjectAngularHelpers()
@ -69,5 +92,5 @@ export class OpenProject {
}
}
window.OpenProject = new OpenProject();
(window as any).OpenProject = new OpenProject();

@ -28,6 +28,8 @@
import {OpenProject} from 'core-app/globals/openproject';
(function($:JQueryStatic) {
function mergeOptions(options:any) {
@ -43,13 +45,13 @@
var topShelf = $("<div/>").addClass(opts.className);
var link = $("<a/>").append(' ' + opts.link).attr({"href": opts.url});
if (window.localStorage.getItem(opts.id)) {
if (window.OpenProject.guardedLocalStorage(opts.id)) {
return;
}
var closeLink = $("<a/>").append(opts.close);
closeLink.click(function() {
window.localStorage.setItem(opts.id, '1');
window.OpenProject.guardedLocalStorage(opts.id, '1');
topShelf.remove();
});

@ -9,6 +9,7 @@ import * as TLodash from 'lodash';
import * as TAngular from 'angular';
import * as TSinon from 'sinon';
import * as TMoment from 'moment';
import {OpenProject} from 'core-app/globals/openproject';
declare global {
const _:typeof TLodash;
@ -18,4 +19,10 @@ declare global {
const bowser:any;
}
declare global {
interface Window {
OpenProject:OpenProject;
}
}
export {};

Loading…
Cancel
Save