| 79 | } |
| 80 | |
| 81 | class LimitedCacheStorage { |
| 82 | // TODO: remove type cast after dependency update |
| 83 | private static readonly QUOTA_BYTES = ((!__TEST__ && (navigator as any).deviceMemory) || 4) * 16 * 1024 * 1024; |
| 84 | private static readonly TTL = getDuration({minutes: 10}); |
| 85 | private static readonly ALARM_NAME = 'network'; |
| 86 | |
| 87 | private bytesInUse = 0; |
| 88 | private records = new Map<string, CacheRecord>(); |
| 89 | private static alarmIsActive = false; |
| 90 | |
| 91 | constructor() { |
| 92 | chrome.alarms.onAlarm.addListener(async (alarm) => { |
| 93 | if (alarm.name === LimitedCacheStorage.ALARM_NAME) { |
| 94 | // We schedule only one-time alarms, so once it goes off, |
| 95 | // there are no more alarms scheduled. |
| 96 | LimitedCacheStorage.alarmIsActive = false; |
| 97 | this.removeExpiredRecords(); |
| 98 | } |
| 99 | }); |
| 100 | } |
| 101 | |
| 102 | private static ensureAlarmIsScheduled(){ |
| 103 | if (!this.alarmIsActive) { |
| 104 | chrome.alarms.create(LimitedCacheStorage.ALARM_NAME, {delayInMinutes: 1}); |
| 105 | this.alarmIsActive = true; |
| 106 | } |
| 107 | } |
| 108 | |
| 109 | has(url: string) { |
| 110 | return this.records.has(url); |
| 111 | } |
| 112 | |
| 113 | get(url: string) { |
| 114 | if (this.records.has(url)) { |
| 115 | const record = this.records.get(url)!; |
| 116 | record.expires = Date.now() + LimitedCacheStorage.TTL; |
| 117 | this.records.delete(url); |
| 118 | this.records.set(url, record); |
| 119 | return record.value; |
| 120 | } |
| 121 | return null; |
| 122 | } |
| 123 | |
| 124 | set(url: string, value: string) { |
| 125 | LimitedCacheStorage.ensureAlarmIsScheduled(); |
| 126 | |
| 127 | const size = getStringSize(value); |
| 128 | if (size > LimitedCacheStorage.QUOTA_BYTES) { |
| 129 | return; |
| 130 | } |
| 131 | |
| 132 | for (const [url, record] of this.records) { |
| 133 | if (this.bytesInUse + size > LimitedCacheStorage.QUOTA_BYTES) { |
| 134 | this.records.delete(url); |
| 135 | this.bytesInUse -= record.size; |
| 136 | } else { |
| 137 | break; |
| 138 | } |
nothing calls this directly
no test coverage detected