fix: prevent silent failure when DOM storage quota exceeded (#20899)
* test: update DOM storage quota limits test * fix: update dom_storage_limits.patch (fixes #13465) The previous version of this patch did not include changes required to circumvent the quota enforcement performed by StorageAreaImpl. Consequently when the quota was exceeded, things still "appeared to work" at first but then would later fail silently. That is, the cache would be updated but the backing store would not. This could be fixed by disabling the code below (from `content/browser/dom_storage/storage_area_impl.cc`) ``` // Only check quota if the size is increasing, this allows // shrinking changes to pre-existing maps that are over budget. if (new_item_size > old_item_size && new_storage_used > max_size_) { if (map_state_ == MapState::LOADED_KEYS_ONLY) { receivers_.ReportBadMessage( "The quota in browser cannot exceed when there is only one " "renderer."); } else { std::move(callback).Run(false); } return; } ``` However, since this seems to have some unintended side-effects (see updated notes in dom_storage_limits.patch) it seems more prudent to simply increase the quota to a larger yet still reasonable size rather than attempt to circumvent the storage quota altogether.
This commit is contained in:
parent
745363959a
commit
a7c2f79a94
2 changed files with 66 additions and 74 deletions
|
@ -371,16 +371,42 @@ describe('chromium feature', () => {
|
|||
})
|
||||
|
||||
describe('storage', () => {
|
||||
describe('DOM storage quota override', () => {
|
||||
describe('DOM storage quota increase', () => {
|
||||
['localStorage', 'sessionStorage'].forEach((storageName) => {
|
||||
it(`allows saving at least 50MiB in ${storageName}`, () => {
|
||||
const storage = window[storageName]
|
||||
const testKeyName = '_electronDOMStorageQuotaOverrideTest'
|
||||
// 25 * 2^20 UTF-16 characters will require 50MiB
|
||||
const arraySize = 25 * Math.pow(2, 20)
|
||||
storage[testKeyName] = new Array(arraySize).fill('X').join('')
|
||||
expect(storage[testKeyName]).to.have.lengthOf(arraySize)
|
||||
delete storage[testKeyName]
|
||||
const storage = window[storageName]
|
||||
it(`allows saving at least 40MiB in ${storageName}`, (done) => {
|
||||
// Although JavaScript strings use UTF-16, the underlying
|
||||
// storage provider may encode strings differently, muddling the
|
||||
// translation between character and byte counts. However,
|
||||
// a string of 40 * 2^20 characters will require at least 40MiB
|
||||
// and presumably no more than 80MiB, a size guaranteed to
|
||||
// to exceed the original 10MiB quota yet stay within the
|
||||
// new 100MiB quota.
|
||||
// Note that both the key name and value affect the total size.
|
||||
const testKeyName = '_electronDOMStorageQuotaIncreasedTest'
|
||||
const length = 40 * Math.pow(2, 20) - testKeyName.length
|
||||
storage.setItem(testKeyName, 'X'.repeat(length))
|
||||
// Wait at least one turn of the event loop to help avoid false positives
|
||||
// Although not entirely necessary, the previous version of this test case
|
||||
// failed to detect a real problem (perhaps related to DOM storage data caching)
|
||||
// wherein calling `getItem` immediately after `setItem` would appear to work
|
||||
// but then later (e.g. next tick) it would not.
|
||||
setTimeout(() => {
|
||||
expect(storage.getItem(testKeyName)).to.have.lengthOf(length)
|
||||
storage.removeItem(testKeyName)
|
||||
done()
|
||||
}, 1)
|
||||
})
|
||||
it(`throws when attempting to use more than 128MiB in ${storageName}`, () => {
|
||||
expect(() => {
|
||||
const testKeyName = '_electronDOMStorageQuotaStillEnforcedTest'
|
||||
const length = 128 * Math.pow(2, 20) - testKeyName.length
|
||||
try {
|
||||
storage.setItem(testKeyName, 'X'.repeat(length))
|
||||
} finally {
|
||||
storage.removeItem(testKeyName)
|
||||
}
|
||||
}).to.throw()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue