Files
gerrit/polygerrit-ui/app/elements/shared/gr-storage/gr-storage.js
Dave Borowitz 8cdc76ba4c Add @license tags to PG HTML and JS assets
These tags are preserved by the Closure compiler and vulcanize in order
to serve the license notices embedded in the outputs. In a standalone
Gerrit server, these license are also covered in the LICENSES.txt served
with the documentation. When serving PG assets from a CDN, it's less
obvious what the corresponding LICENSES.txt file is, since the CDN is
not directly linked to a running Gerrit server. Safer to embed the
licenses in the assets themselves.

Change-Id: Id1add1451fad1baa7916882a6bda02c326ccc988
2018-03-26 10:47:55 -04:00

150 lines
3.9 KiB
JavaScript

/**
* @license
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function() {
'use strict';
// Date cutoff is one day:
const CLEANUP_MAX_AGE = 24 * 60 * 60 * 1000;
// Clean up old entries no more frequently than one day.
const CLEANUP_THROTTLE_INTERVAL = 24 * 60 * 60 * 1000;
const CLEANUP_PREFIXES = [
'draft:',
'editablecontent:',
];
Polymer({
is: 'gr-storage',
properties: {
_lastCleanup: Number,
/** @type {?Storage} */
_storage: {
type: Object,
value() {
return window.localStorage;
},
},
_exceededQuota: {
type: Boolean,
value: false,
},
},
getDraftComment(location) {
this._cleanupItems();
return this._getObject(this._getDraftKey(location));
},
setDraftComment(location, message) {
const key = this._getDraftKey(location);
this._setObject(key, {message, updated: Date.now()});
},
eraseDraftComment(location) {
const key = this._getDraftKey(location);
this._storage.removeItem(key);
},
getEditableContentItem(key) {
this._cleanupItems();
return this._getObject(this._getEditableContentKey(key));
},
setEditableContentItem(key, message) {
this._setObject(this._getEditableContentKey(key),
{message, updated: Date.now()});
},
eraseEditableContentItem(key) {
this._storage.removeItem(key);
},
getPreferences() {
return this._getObject('localPrefs');
},
savePreferences(localPrefs) {
this._setObject('localPrefs', localPrefs || null);
},
_getDraftKey(location) {
const range = location.range ?
`${location.range.start_line}-${location.range.start_character}` +
`-${location.range.end_character}-${location.range.end_line}` :
null;
let key = ['draft', location.changeNum, location.patchNum, location.path,
location.line || ''].join(':');
if (range) {
key = key + ':' + range;
}
return key;
},
_getEditableContentKey(key) {
return `editablecontent:${key}`;
},
_cleanupItems() {
// Throttle cleanup to the throttle interval.
if (this._lastCleanup &&
Date.now() - this._lastCleanup < CLEANUP_THROTTLE_INTERVAL) {
return;
}
this._lastCleanup = Date.now();
let item;
for (const key in this._storage) {
if (!this._storage.hasOwnProperty(key)) { continue; }
for (const prefix of CLEANUP_PREFIXES) {
if (key.startsWith(prefix)) {
item = this._getObject(key);
if (Date.now() - item.updated > CLEANUP_MAX_AGE) {
this._storage.removeItem(key);
}
break;
}
}
}
},
_getObject(key) {
const serial = this._storage.getItem(key);
if (!serial) { return null; }
return JSON.parse(serial);
},
_setObject(key, obj) {
if (this._exceededQuota) { return; }
try {
this._storage.setItem(key, JSON.stringify(obj));
} catch (exc) {
// Catch for QuotaExceededError and disable writes on local storage the
// first time that it occurs.
if (exc.code === 22) {
this._exceededQuota = true;
console.warn('Local storage quota exceeded: disabling');
return;
} else {
throw exc;
}
}
},
});
})();