| // 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: | 
 |   var DRAFT_MAX_AGE = 24 * 60 * 60 * 1000; | 
 |  | 
 |   // Clean up old entries no more frequently than one day. | 
 |   var CLEANUP_THROTTLE_INTERVAL = 24 * 60 * 60 * 1000; | 
 |  | 
 |   Polymer({ | 
 |     is: 'gr-storage', | 
 |  | 
 |     properties: { | 
 |       _lastCleanup: Number, | 
 |       _storage: { | 
 |         type: Object, | 
 |         value: function() { | 
 |           return window.localStorage; | 
 |         }, | 
 |       }, | 
 |       _exceededQuota: { | 
 |         type: Boolean, | 
 |         value: false, | 
 |       }, | 
 |     }, | 
 |  | 
 |     getDraftComment: function(location) { | 
 |       this._cleanupDrafts(); | 
 |       return this._getObject(this._getDraftKey(location)); | 
 |     }, | 
 |  | 
 |     setDraftComment: function(location, message) { | 
 |       var key = this._getDraftKey(location); | 
 |       this._setObject(key, {message: message, updated: Date.now()}); | 
 |     }, | 
 |  | 
 |     eraseDraftComment: function(location) { | 
 |       var key = this._getDraftKey(location); | 
 |       this._storage.removeItem(key); | 
 |     }, | 
 |  | 
 |     getPreferences: function() { | 
 |       return this._getObject('localPrefs'); | 
 |     }, | 
 |  | 
 |     savePreferences: function(localPrefs) { | 
 |       this._setObject('localPrefs', localPrefs || null); | 
 |     }, | 
 |  | 
 |     _getDraftKey: function(location) { | 
 |       var range = location.range ? location.range.start_line + '-' + | 
 |           location.range.start_character + '-' + location.range.end_character + | 
 |           '-' + location.range.end_line : null; | 
 |       var key = ['draft', location.changeNum, location.patchNum, location.path, | 
 |           location.line || ''].join(':'); | 
 |       if (range) { | 
 |         key = key + ':' + range; | 
 |       } | 
 |       return key; | 
 |     }, | 
 |  | 
 |     _cleanupDrafts: function() { | 
 |       // Throttle cleanup to the throttle interval. | 
 |       if (this._lastCleanup && | 
 |           Date.now() - this._lastCleanup < CLEANUP_THROTTLE_INTERVAL) { | 
 |         return; | 
 |       } | 
 |       this._lastCleanup = Date.now(); | 
 |  | 
 |       var draft; | 
 |       for (var key in this._storage) { | 
 |         if (key.indexOf('draft:') === 0) { | 
 |           draft = this._getObject(key); | 
 |           if (Date.now() - draft.updated > DRAFT_MAX_AGE) { | 
 |             this._storage.removeItem(key); | 
 |           } | 
 |         } | 
 |       } | 
 |     }, | 
 |  | 
 |     _getObject: function(key) { | 
 |       var serial = this._storage.getItem(key); | 
 |       if (!serial) { return null; } | 
 |       return JSON.parse(serial); | 
 |     }, | 
 |  | 
 |     _setObject: function(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; | 
 |         } | 
 |       } | 
 |     }, | 
 |   }); | 
 | })(); |