Changeset 276689 in webkit
- Timestamp:
- Apr 27, 2021 9:43:38 PM (15 months ago)
- Location:
- trunk
- Files:
-
- 8 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/storage/domstorage/quota.html (modified) (1 diff)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/storage/StorageMap.cpp (modified) (8 diffs)
-
Source/WebCore/storage/StorageMap.h (modified) (2 diffs)
-
Source/WebKit/ChangeLog (modified) (1 diff)
-
Source/WebKit/NetworkProcess/WebStorage/LocalStorageDatabase.cpp (modified) (4 diffs)
-
Source/WebKit/NetworkProcess/WebStorage/LocalStorageDatabase.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r276688 r276689 1 2021-04-27 Chris Dumez <cdumez@apple.com> 2 3 Improve local storage size estimation for quota limitation 4 https://bugs.webkit.org/show_bug.cgi?id=225123 5 6 Reviewed by Alex Christensen. 7 8 Update test to use unicode in the Strings so that the file reaches the quota without 9 changing the test too much. The test was using ASCII and was thus able to store all 10 the strings without reaching the quota due to our updated String size calculation. 11 12 * storage/domstorage/quota.html: 13 1 14 2021-04-27 Wenson Hsieh <wenson_hsieh@apple.com> 2 15 -
trunk/LayoutTests/storage/domstorage/quota.html
r217390 r276689 23 23 24 24 debug("Creating 'data' which contains 64K of data"); 25 data = " X";25 data = "\u03BB"; 26 26 for (var i=0; i<16; i++) 27 27 data += data; -
trunk/Source/WebCore/ChangeLog
r276688 r276689 1 2021-04-27 Chris Dumez <cdumez@apple.com> 2 3 Improve local storage size estimation for quota limitation 4 https://bugs.webkit.org/show_bug.cgi?id=225123 5 6 Reviewed by Alex Christensen. 7 8 Improve local storage size estimation for quota limitation: 9 - Rely on String::sizeInBytes() to compute the String size, instead of using 10 String::length() * sizeof(UChar) 11 - Make estimation consistent between StorageMap & LocalStorageDatabase 12 13 * storage/StorageMap.cpp: 14 (WebCore::StorageMap::setItem): 15 (WebCore::StorageMap::setItemIgnoringQuota): 16 (WebCore::StorageMap::removeItem): 17 (WebCore::StorageMap::clear): 18 (WebCore::StorageMap::importItems): 19 (WebCore::StorageMap::Impl::copy const): 20 * storage/StorageMap.h: 21 1 22 2021-04-27 Wenson Hsieh <wenson_hsieh@apple.com> 2 23 -
trunk/Source/WebCore/storage/StorageMap.cpp
r276659 r276689 27 27 #include "StorageMap.h" 28 28 29 #include <wtf/CheckedArithmetic.h> 29 30 #include <wtf/SetForScope.h> 30 31 … … 94 95 m_impl = m_impl->copy(); 95 96 96 // Quota tracking. This is done in a couple of steps to keep the overflow tracking simple. 97 unsigned newLength = m_impl->currentLength; 98 bool overflow = newLength + value.length() < newLength; 99 newLength += value.length(); 97 oldValue = m_impl->map.get(key); 100 98 101 oldValue = m_impl->map.get(key); 102 overflow |= newLength - oldValue.length() > newLength; 103 newLength -= oldValue.length(); 104 105 unsigned adjustedKeyLength = oldValue.isNull() ? key.length() : 0; 106 overflow |= newLength + adjustedKeyLength < newLength; 107 newLength += adjustedKeyLength; 108 109 ASSERT(!overflow); // Overflow is bad...even if quotas are off. 110 bool overQuota = newLength > m_quotaSize / sizeof(UChar); 111 if (m_quotaSize != noQuota && (overflow || overQuota)) { 99 // Quota tracking. This is done in a couple of steps to keep the overflow tracking simple. 100 CheckedUint32 newSize = m_impl->currentSize; 101 newSize -= oldValue.sizeInBytes(); 102 newSize += value.sizeInBytes(); 103 if (oldValue.isNull()) 104 newSize += key.sizeInBytes(); 105 if (m_quotaSize != noQuota && (newSize.hasOverflowed() || newSize.unsafeGet() > m_quotaSize)) { 112 106 quotaException = true; 113 107 return; 114 108 } 115 m_impl->current Length = newLength;109 m_impl->currentSize = newSize.unsafeGet(); 116 110 117 111 HashMap<String, String>::AddResult addResult = m_impl->map.add(key, value); … … 124 118 void StorageMap::setItemIgnoringQuota(const String& key, const String& value) 125 119 { 126 SetForScope<unsigned> quotaSizeChange(m_quotaSize, static_cast<unsigned>(noQuota));120 SetForScope<unsigned> quotaSizeChange(m_quotaSize, noQuota); 127 121 128 122 String oldValue; … … 139 133 140 134 oldValue = m_impl->map.take(key); 141 if (!oldValue.isNull()) { 142 invalidateIterator(); 143 ASSERT(m_impl->currentLength - key.length() <= m_impl->currentLength); 144 m_impl->currentLength -= key.length(); 145 } 146 ASSERT(m_impl->currentLength - oldValue.length() <= m_impl->currentLength); 147 m_impl->currentLength -= oldValue.length(); 135 if (oldValue.isNull()) 136 return; 137 138 invalidateIterator(); 139 ASSERT(m_impl->currentSize - key.sizeInBytes() <= m_impl->currentSize); 140 m_impl->currentSize -= key.sizeInBytes(); 141 ASSERT(m_impl->currentSize - oldValue.sizeInBytes() <= m_impl->currentSize); 142 m_impl->currentSize -= oldValue.sizeInBytes(); 148 143 } 149 144 … … 155 150 } 156 151 m_impl->map.clear(); 157 m_impl->current Length= 0;152 m_impl->currentSize = 0; 158 153 } 159 154 … … 169 164 m_impl->map = WTFMove(items); 170 165 for (auto& pair : m_impl->map) { 171 ASSERT(m_impl->current Length + pair.key.length() + pair.value.length() >= m_impl->currentLength);172 m_impl->current Length += (pair.key.length() + pair.value.length());166 ASSERT(m_impl->currentSize + pair.key.sizeInBytes() + pair.value.sizeInBytes() >= m_impl->currentSize); 167 m_impl->currentSize += (pair.key.sizeInBytes() + pair.value.sizeInBytes()); 173 168 } 174 169 return; … … 179 174 auto& value = item.value; 180 175 181 ASSERT(m_impl->current Length + key.length() + value.length() >= m_impl->currentLength);182 m_impl->current Length += (key.length() + value.length());183 176 ASSERT(m_impl->currentSize + key.sizeInBytes() + value.sizeInBytes() >= m_impl->currentSize); 177 m_impl->currentSize += (key.sizeInBytes() + value.sizeInBytes()); 178 184 179 auto result = m_impl->map.add(WTFMove(key), WTFMove(value)); 185 180 ASSERT_UNUSED(result, result.isNewEntry); // True if the key didn't exist previously. … … 191 186 auto copy = Impl::create(); 192 187 copy->map = map; 193 copy->current Length = currentLength;188 copy->currentSize = currentSize; 194 189 return copy; 195 190 } -
trunk/Source/WebCore/storage/StorageMap.h
r276659 r276689 57 57 bool isShared() const { return !m_impl->hasOneRef(); } 58 58 59 static constexpr unsigned noQuota = UINT_MAX;59 static constexpr unsigned noQuota = std::numeric_limits<unsigned>::max(); 60 60 61 61 private: … … 74 74 HashMap<String, String>::iterator iterator { map.end() }; 75 75 unsigned iteratorIndex { std::numeric_limits<unsigned>::max() }; 76 unsigned current Length { 0 }; // Measured in UChars.76 unsigned currentSize { 0 }; 77 77 }; 78 78 -
trunk/Source/WebKit/ChangeLog
r276688 r276689 1 2021-04-27 Chris Dumez <cdumez@apple.com> 2 3 Improve local storage size estimation for quota limitation 4 https://bugs.webkit.org/show_bug.cgi?id=225123 5 6 Reviewed by Alex Christensen. 7 8 Improve local storage size estimation for quota limitation: 9 - Rely on String::sizeInBytes() to compute the String size, instead of using 10 String::length() * sizeof(UChar) 11 - Make estimation consistent between StorageMap & LocalStorageDatabase 12 13 * NetworkProcess/WebStorage/LocalStorageDatabase.cpp: 14 (WebKit::LocalStorageDatabase::removeItem): 15 (WebKit::LocalStorageDatabase::setItem): 16 (WebKit::estimateEntrySize): Deleted. 17 * NetworkProcess/WebStorage/LocalStorageDatabase.h: 18 1 19 2021-04-27 Wenson Hsieh <wenson_hsieh@apple.com> 2 20 -
trunk/Source/WebKit/NetworkProcess/WebStorage/LocalStorageDatabase.cpp
r276653 r276689 48 48 static const char getItemsQueryString[] = "SELECT key, value FROM ItemTable"; 49 49 50 static CheckedUint64 estimateEntrySize(const String& key, const String& value)51 {52 CheckedUint64 entrySize;53 entrySize += key.length() * sizeof(UChar);54 entrySize += value.length() * sizeof(UChar);55 return entrySize;56 }57 58 50 Ref<LocalStorageDatabase> LocalStorageDatabase::create(Ref<WorkQueue>&& queue, Ref<LocalStorageDatabaseTracker>&& tracker, const SecurityOriginData& securityOrigin, unsigned quotaInBytes) 59 51 { … … 218 210 219 211 if (m_databaseSize) { 220 CheckedUint64 entrySize = estimateEntrySize(key, oldValue);221 if ( entrySize.hasOverflowed() || entrySize.unsafeGet()>= *m_databaseSize)212 auto sizeDecrease = key.sizeInBytes() + oldValue.sizeInBytes(); 213 if (sizeDecrease >= *m_databaseSize) 222 214 *m_databaseSize = 0; 223 215 else 224 *m_databaseSize -= entrySize.unsafeGet();216 *m_databaseSize -= sizeDecrease; 225 217 } 226 218 } … … 255 247 return; 256 248 249 oldValue = item(key); 250 257 251 if (m_quotaInBytes != WebCore::StorageMap::noQuota) { 258 252 if (!m_databaseSize) 259 253 m_databaseSize = SQLiteFileSystem::getDatabaseFileSize(m_databasePath); 260 if (*m_databaseSize >= m_quotaInBytes) { 261 quotaException = true; 262 return; 263 } 264 CheckedUint64 newDatabaseSize = *m_databaseSize; 265 newDatabaseSize += estimateEntrySize(key, value); 254 CheckedUint32 newDatabaseSize = *m_databaseSize; 255 newDatabaseSize -= oldValue.sizeInBytes(); 256 newDatabaseSize += value.sizeInBytes(); 257 if (oldValue.isNull()) 258 newDatabaseSize += key.sizeInBytes(); 266 259 if (newDatabaseSize.hasOverflowed() || newDatabaseSize.unsafeGet() > m_quotaInBytes) { 267 260 quotaException = true; … … 271 264 } 272 265 273 oldValue = item(key);274 275 266 auto insertStatement = scopedStatement(m_insertStatement, "INSERT INTO ItemTable VALUES (?, ?)"_s); 276 267 if (!insertStatement) { -
trunk/Source/WebKit/NetworkProcess/WebStorage/LocalStorageDatabase.h
r276653 r276689 76 76 String m_databasePath; 77 77 mutable WebCore::SQLiteDatabase m_database; 78 unsigned m_quotaInBytes { 0 };78 const unsigned m_quotaInBytes { 0 }; 79 79 bool m_failedToOpenDatabase { false }; 80 80 bool m_isClosed { false }; 81 Optional<u int64_t> m_databaseSize;81 Optional<unsigned> m_databaseSize; 82 82 83 83 std::unique_ptr<WebCore::SuddenTerminationDisabler> m_disableSuddenTerminationWhileWritingToLocalStorage;
Note: See TracChangeset
for help on using the changeset viewer.