Changeset 223073 in webkit
- Timestamp:
- Oct 9, 2017 3:17:05 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 31 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r223071 r223073 1 2017-10-09 Youenn Fablet <youenn@apple.com> 2 3 Add quota to cache API 4 https://bugs.webkit.org/show_bug.cgi?id=177552 5 6 Reviewed by Alex Christensen. 7 8 * http/wpt/cache-storage/cache-quota.https.any-expected.txt: Added. 9 * http/wpt/cache-storage/cache-quota.https.any.html: Added. 10 * http/wpt/cache-storage/cache-quota.https.any.js: Added. 11 1 12 2017-10-09 Matt Lewis <jlewis3@apple.com> 2 13 -
trunk/Source/WebCore/ChangeLog
r223072 r223073 1 2017-10-09 Youenn Fablet <youenn@apple.com> 2 3 Add quota to cache API 4 https://bugs.webkit.org/show_bug.cgi?id=177552 5 6 Reviewed by Alex Christensen. 7 8 Tests: http/wpt/cache-storage/cache-quota.any.html 9 10 Storing padded opaque response body sizes within FetchResponse and CacheStorageConnection. 11 See https://github.com/whatwg/storage/issues/31 for the rationale about this padding. 12 Storing in CacheStorageConnection is needed for handling cloned network fetched created responses. 13 Storing in FetchResponse is needed for handling cloned cache-storage created opaque responses. 14 15 Adding internals to query and set the fuzzed size of a response. 16 17 * Modules/cache/CacheStorageConnection.cpp: 18 (WebCore::computeRealBodySize): 19 (WebCore::CacheStorageConnection::computeRecordBodySize): 20 (WebCore::CacheStorageConnection::setResponseBodySizeWithPadding): 21 (WebCore::CacheStorageConnection::responseBodySizeWithPadding const): 22 * Modules/cache/CacheStorageConnection.h: 23 * Modules/cache/DOMCache.cpp: 24 (WebCore::DOMCache::toConnectionRecord): 25 (WebCore::DOMCache::updateRecords): 26 * Modules/cache/DOMCache.h: 27 * Modules/cache/DOMCacheEngine.cpp: 28 (WebCore::DOMCacheEngine::errorToException): 29 (WebCore::DOMCacheEngine::Record::copy const): 30 * Modules/cache/DOMCacheEngine.h: 31 * Modules/cache/WorkerCacheStorageConnection.cpp: 32 (WebCore::toCrossThreadRecordData): 33 (WebCore::fromCrossThreadRecordData): 34 * Modules/fetch/FetchResponse.cpp: 35 (WebCore::FetchResponse::clone): 36 (WebCore::FetchResponse::BodyLoader::didReceiveResponse): 37 * Modules/fetch/FetchResponse.h: 38 * Modules/fetch/FetchResponse.idl: 39 * testing/Internals.cpp: 40 (WebCore::Internals::setResponseSizeWithPadding): 41 (WebCore::Internals::responseSizeWithPadding const): 42 * testing/Internals.h: 43 * testing/Internals.idl: 44 1 45 2017-10-09 Zalan Bujtas <zalan@apple.com> 2 46 -
trunk/Source/WebCore/Modules/cache/CacheStorageConnection.cpp
r221624 r223073 27 27 #include "config.h" 28 28 #include "CacheStorageConnection.h" 29 30 #include "FetchResponse.h" 31 #include <wtf/RandomNumber.h> 29 32 30 33 using namespace WebCore::DOMCacheEngine; … … 72 75 } 73 76 77 static inline uint64_t computeRealBodySize(const DOMCacheEngine::ResponseBody& body) 78 { 79 uint64_t result = 0; 80 WTF::switchOn(body, [&] (const Ref<WebCore::FormData>& formData) { 81 result = formData->lengthInBytes(); 82 }, [&] (const Ref<WebCore::SharedBuffer>& buffer) { 83 result = buffer->size(); 84 }, [] (const std::nullptr_t&) { 85 }); 86 return result; 87 } 88 89 uint64_t CacheStorageConnection::computeRecordBodySize(const FetchResponse& response, const DOMCacheEngine::ResponseBody& body, ResourceResponse::Tainting tainting) 90 { 91 if (!response.opaqueLoadIdentifier()) { 92 ASSERT_UNUSED(tainting, tainting != ResourceResponse::Tainting::Opaque); 93 return computeRealBodySize(body); 94 } 95 96 return m_opaqueResponseToSizeWithPaddingMap.ensure(response.opaqueLoadIdentifier(), [&] () { 97 uint64_t realSize = computeRealBodySize(body); 98 99 // Padding the size as per https://github.com/whatwg/storage/issues/31. 100 uint64_t sizeWithPadding = realSize + static_cast<uint64_t>(randomNumber() * 128000); 101 sizeWithPadding = ((sizeWithPadding / 32000) + 1) * 32000; 102 103 m_opaqueResponseToSizeWithPaddingMap.set(response.opaqueLoadIdentifier(), sizeWithPadding); 104 return sizeWithPadding; 105 }).iterator->value; 106 } 107 74 108 void CacheStorageConnection::batchPutOperation(uint64_t cacheIdentifier, Vector<Record>&& records, RecordIdentifiersCallback&& callback) 75 109 { -
trunk/Source/WebCore/Modules/cache/CacheStorageConnection.h
r221710 r223073 33 33 namespace WebCore { 34 34 35 class FetchResponse; 36 35 37 class CacheStorageConnection : public ThreadSafeRefCounted<CacheStorageConnection> { 36 38 public: … … 45 47 void batchDeleteOperation(uint64_t cacheIdentifier, const ResourceRequest&, CacheQueryOptions&&, DOMCacheEngine::RecordIdentifiersCallback&&); 46 48 void batchPutOperation(uint64_t cacheIdentifier, Vector<DOMCacheEngine::Record>&&, DOMCacheEngine::RecordIdentifiersCallback&&); 49 uint64_t computeRecordBodySize(const FetchResponse&, const DOMCacheEngine::ResponseBody&, ResourceResponse::Tainting); 47 50 48 51 virtual void reference(uint64_t /* cacheIdentifier */) { } … … 79 82 HashMap<uint64_t, DOMCacheEngine::RecordsCallback> m_retrieveRecordsPendingRequests; 80 83 HashMap<uint64_t, DOMCacheEngine::RecordIdentifiersCallback> m_batchDeleteAndPutPendingRequests; 84 HashMap<uint64_t, uint64_t> m_opaqueResponseToSizeWithPaddingMap; 81 85 82 86 uint64_t m_lastRequestIdentifier { 0 }; -
trunk/Source/WebCore/Modules/cache/DOMCache.cpp
r222774 r223073 39 39 namespace WebCore { 40 40 41 static Record toConnectionRecord(const FetchRequest&, FetchResponse&, ResponseBody&&);42 43 41 DOMCache::DOMCache(ScriptExecutionContext& context, String&& name, uint64_t identifier, Ref<CacheStorageConnection>&& connection) 44 42 : ActiveDOMObject(&context) … … 481 479 } 482 480 483 Record toConnectionRecord(const FetchRequest& request, FetchResponse& response, DOMCacheEngine::ResponseBody&& responseBody)481 Record DOMCache::toConnectionRecord(const FetchRequest& request, FetchResponse& response, DOMCacheEngine::ResponseBody&& responseBody) 484 482 { 485 483 // FIXME: Add a setHTTPHeaderFields on ResourceResponseBase. … … 494 492 ASSERT(!cachedResponse.isNull()); 495 493 494 auto sizeWithPadding = response.bodySizeWithPadding(); 495 if (!sizeWithPadding) { 496 sizeWithPadding = m_connection->computeRecordBodySize(response, responseBody, cachedResponse.tainting()); 497 response.setBodySizeWithPadding(sizeWithPadding); 498 } 499 496 500 return { 0, 0, 497 501 request.headers().guard(), WTFMove(cachedRequest), request.fetchOptions(), request.internalRequestReferrer(), 498 response.headers().guard(), WTFMove(cachedResponse), WTFMove(responseBody) 502 response.headers().guard(), WTFMove(cachedResponse), WTFMove(responseBody), sizeWithPadding 499 503 }; 500 504 } … … 534 538 auto responseHeaders = FetchHeaders::create(record.responseHeadersGuard, HTTPHeaderMap { record.response.httpHeaderFields() }); 535 539 auto response = FetchResponse::create(*scriptExecutionContext(), std::nullopt, WTFMove(responseHeaders), WTFMove(record.response)); 536 response->setBodyData(WTFMove(record.responseBody) );540 response->setBodyData(WTFMove(record.responseBody), record.responseBodySize); 537 541 538 542 current.response = WTFMove(response); … … 546 550 auto responseHeaders = FetchHeaders::create(record.responseHeadersGuard, HTTPHeaderMap { record.response.httpHeaderFields() }); 547 551 auto response = FetchResponse::create(*scriptExecutionContext(), std::nullopt, WTFMove(responseHeaders), WTFMove(record.response)); 548 response->setBodyData(WTFMove(record.responseBody) );552 response->setBodyData(WTFMove(record.responseBody), record.responseBodySize); 549 553 550 554 newRecords.append(CacheStorageRecord { record.identifier, record.updateResponseCounter, WTFMove(request), WTFMove(response) }); -
trunk/Source/WebCore/Modules/cache/DOMCache.h
r222774 r223073 81 81 void updateRecords(Vector<DOMCacheEngine::Record>&&); 82 82 Vector<Ref<FetchResponse>> cloneResponses(const Vector<CacheStorageRecord>&); 83 DOMCacheEngine::Record toConnectionRecord(const FetchRequest&, FetchResponse&, DOMCacheEngine::ResponseBody&&); 83 84 84 85 String m_name; -
trunk/Source/WebCore/Modules/cache/DOMCacheEngine.cpp
r222774 r223073 45 45 case Error::WriteDisk: 46 46 return Exception { TypeError, ASCIILiteral("Failed writing data to the file system") }; 47 case Error::QuotaExceeded: 48 return Exception { QuotaExceededError, ASCIILiteral("Quota exceeded") }; 47 49 default: 48 50 return Exception { TypeError, ASCIILiteral("Internal error") }; … … 136 138 Record Record::copy() const 137 139 { 138 return Record { identifier, updateResponseCounter, requestHeadersGuard, request, options, referrer, responseHeadersGuard, response, copyResponseBody(responseBody) };140 return Record { identifier, updateResponseCounter, requestHeadersGuard, request, options, referrer, responseHeadersGuard, response, copyResponseBody(responseBody), responseBodySize }; 139 141 } 140 142 -
trunk/Source/WebCore/Modules/cache/DOMCacheEngine.h
r222233 r223073 43 43 ReadDisk, 44 44 WriteDisk, 45 QuotaExceeded, 45 46 Internal 46 47 }; … … 69 70 ResourceResponse response; 70 71 ResponseBody responseBody; 72 uint64_t responseBodySize; 71 73 }; 72 74 … … 122 124 if (!infos) 123 125 return std::nullopt; 124 126 125 127 std::optional<uint64_t> updateCounter; 126 128 decoder >> updateCounter; 127 129 if (!updateCounter) 128 130 return std::nullopt; 129 131 130 132 return {{ WTFMove(*infos), WTFMove(*updateCounter) }}; 131 133 } … … 143 145 if (!identifier) 144 146 return std::nullopt; 145 147 146 148 std::optional<bool> hadStorageError; 147 149 decoder >> hadStorageError; … … 162 164 WebCore::DOMCacheEngine::Error::ReadDisk, 163 165 WebCore::DOMCacheEngine::Error::WriteDisk, 166 WebCore::DOMCacheEngine::Error::QuotaExceeded, 164 167 WebCore::DOMCacheEngine::Error::Internal 165 168 >; -
trunk/Source/WebCore/Modules/cache/WorkerCacheStorageConnection.cpp
r222774 r223073 54 54 ResourceResponse::CrossThreadData response; 55 55 ResponseBody responseBody; 56 uint64_t responseBodySize; 56 57 }; 57 58 … … 67 68 record.responseHeadersGuard, 68 69 record.response.crossThreadData(), 69 isolatedResponseBody(record.responseBody) 70 isolatedResponseBody(record.responseBody), 71 record.responseBodySize 70 72 }; 71 73 } … … 82 84 data.responseHeadersGuard, 83 85 ResourceResponse::fromCrossThreadData(WTFMove(data.response)), 84 WTFMove(data.responseBody) 86 WTFMove(data.responseBody), 87 data.responseBodySize 85 88 }; 86 89 } -
trunk/Source/WebCore/Modules/fetch/FetchResponse.cpp
r222561 r223073 160 160 if (isBodyOpaque()) 161 161 clone->setBodyAsOpaque(); 162 clone->m_opaqueLoadIdentifier = m_opaqueLoadIdentifier; 163 clone->m_bodySizeWithPadding = m_bodySizeWithPadding; 162 164 return WTFMove(clone); 163 165 } … … 240 242 } 241 243 244 static uint64_t nextOpaqueLoadIdentifier { 0 }; 242 245 void FetchResponse::BodyLoader::didReceiveResponse(const ResourceResponse& resourceResponse) 243 246 { 244 247 m_response.m_response = ResourceResponseBase::filter(resourceResponse); 245 if (resourceResponse.tainting() == ResourceResponse::Tainting::Opaque) 248 if (resourceResponse.tainting() == ResourceResponse::Tainting::Opaque) { 249 m_response.m_opaqueLoadIdentifier = ++nextOpaqueLoadIdentifier; 246 250 m_response.setBodyAsOpaque(); 251 } 247 252 248 253 m_response.m_headers->filterAndFill(m_response.m_response.httpHeaderFields(), FetchHeaders::Guard::Response); … … 327 332 } 328 333 329 void FetchResponse::setBodyData(ResponseData&& data) 330 { 334 void FetchResponse::setBodyData(ResponseData&& data, uint64_t bodySizeWithPadding) 335 { 336 m_bodySizeWithPadding = bodySizeWithPadding; 331 337 WTF::switchOn(data, 332 338 [this](Ref<FormData>& formData) { -
trunk/Source/WebCore/Modules/fetch/FetchResponse.h
r221806 r223073 88 88 using ResponseData = Variant<std::nullptr_t, Ref<FormData>, Ref<SharedBuffer>>; 89 89 ResponseData consumeBody(); 90 void setBodyData(ResponseData&& );90 void setBodyData(ResponseData&&, uint64_t bodySizeWithPadding); 91 91 92 92 bool isLoading() const { return !!m_bodyLoader; } … … 97 97 98 98 const ResourceResponse& resourceResponse() const { return m_response; } 99 100 uint64_t bodySizeWithPadding() const { return m_bodySizeWithPadding; } 101 void setBodySizeWithPadding(uint64_t size) { m_bodySizeWithPadding = size; } 102 uint64_t opaqueLoadIdentifier() const { return m_opaqueLoadIdentifier; } 99 103 100 104 private: … … 139 143 std::optional<BodyLoader> m_bodyLoader; 140 144 mutable String m_responseURL; 145 // Opaque responses will padd their body size when used with Cache API. 146 uint64_t m_bodySizeWithPadding { 0 }; 147 uint64_t m_opaqueLoadIdentifier { 0 }; 141 148 }; 142 149 -
trunk/Source/WebCore/Modules/fetch/FetchResponse.idl
r221806 r223073 44 44 ConstructorMayThrowException, 45 45 EnabledAtRuntime=FetchAPI, 46 ExportToWrappedFunction, 46 47 Exposed=(Window,Worker), 47 48 InterfaceName=Response, -
trunk/Source/WebCore/testing/Internals.cpp
r222946 r223073 59 59 #include "EventHandler.h" 60 60 #include "ExtensionStyleSheets.h" 61 #include "FetchResponse.h" 61 62 #include "File.h" 62 63 #include "FontCache.h" … … 4175 4176 } 4176 4177 4178 void Internals::setResponseSizeWithPadding(FetchResponse& response, uint64_t size) 4179 { 4180 response.setBodySizeWithPadding(size); 4181 } 4182 4183 uint64_t Internals::responseSizeWithPadding(FetchResponse& response) const 4184 { 4185 return response.bodySizeWithPadding(); 4186 } 4187 4177 4188 } // namespace WebCore -
trunk/Source/WebCore/testing/Internals.h
r222858 r223073 51 51 class Document; 52 52 class Element; 53 class FetchResponse; 53 54 class File; 54 55 class Frame; … … 601 602 void clearCacheStorageMemoryRepresentation(DOMPromiseDeferred<void>&&); 602 603 void cacheStorageEngineRepresentation(DOMPromiseDeferred<IDLDOMString>&&); 604 void setResponseSizeWithPadding(FetchResponse&, uint64_t size); 605 uint64_t responseSizeWithPadding(FetchResponse&) const; 603 606 604 607 void setConsoleMessageListener(RefPtr<StringCallback>&&); -
trunk/Source/WebCore/testing/Internals.idl
r222613 r223073 548 548 Promise<void> clearCacheStorageMemoryRepresentation(); 549 549 Promise<DOMString> cacheStorageEngineRepresentation(); 550 void setResponseSizeWithPadding(FetchResponse response, unsigned long long size); 551 unsigned long long responseSizeWithPadding(FetchResponse response); 550 552 551 553 void setConsoleMessageListener(StringCallback callback); -
trunk/Source/WebKit/ChangeLog
r223061 r223073 1 2017-10-09 Youenn Fablet <youenn@apple.com> 2 3 Add quota to cache API 4 https://bugs.webkit.org/show_bug.cgi?id=177552 5 6 Reviewed by Alex Christensen. 7 8 Adding support for quota checking in CacheStorage::Caches. 9 It is passed to NetworkProcess at creation time. 10 Default quota size is configured to 400Ko by origin per default. 11 This value is suitable for testing. 12 Future patch should raise this default value and allows configuring it. 13 14 Quota is computed based on the response body size. 15 This size is padded at WebCore for opaque responses. 16 Size is stored persistently as opaque response padded size should remain stable. 17 See https://github.com/whatwg/storage/issues/31 for the rationale about this padding. 18 19 In case of putting several records at the same time, the size of all records 20 is computed so that all records will be written or rejected together. 21 22 Sending QuotaExceeded error when quota is exceeded. 23 Future effort should allow asking UIProcess for quota extension. 24 25 * NetworkProcess/NetworkProcess.cpp: 26 (WebKit::NetworkProcess::cacheStoragePerOriginQuota const): 27 * NetworkProcess/NetworkProcess.h: 28 * NetworkProcess/NetworkProcessCreationParameters.cpp: 29 (WebKit::NetworkProcessCreationParameters::encode const): 30 (WebKit::NetworkProcessCreationParameters::decode): 31 * NetworkProcess/NetworkProcessCreationParameters.h: 32 * NetworkProcess/cache/CacheStorageEngine.cpp: 33 (WebKit::CacheStorage::Engine::readCachesFromDisk): 34 * NetworkProcess/cache/CacheStorageEngineCache.cpp: 35 (WebKit::CacheStorage::Cache::toRecordInformation): 36 (WebKit::CacheStorage::isolatedCopy): 37 (WebKit::CacheStorage::Cache::open): 38 (WebKit::CacheStorage::Cache::storeRecords): 39 (WebKit::CacheStorage::Cache::put): 40 (WebKit::CacheStorage::Cache::writeRecordToDisk): 41 (WebKit::CacheStorage::Cache::updateRecordToDisk): 42 (WebKit::CacheStorage::Cache::removeRecordFromDisk): 43 (WebKit::CacheStorage::Cache::encode): 44 (WebKit::CacheStorage::Cache::decodeRecordHeader): 45 (WebKit::CacheStorage::Cache::decode): 46 * NetworkProcess/cache/CacheStorageEngineCache.h: 47 * NetworkProcess/cache/CacheStorageEngineCaches.cpp: 48 (WebKit::CacheStorage::Caches::Caches): 49 (WebKit::CacheStorage::Caches::initialize): 50 (WebKit::CacheStorage::Caches::initializeSize): 51 (WebKit::CacheStorage::Caches::requestSpace): 52 (WebKit::CacheStorage::Caches::writeRecord): 53 (WebKit::CacheStorage::Caches::removeRecord): 54 (WebKit::CacheStorage::Caches::removeCacheEntry): 55 * NetworkProcess/cache/CacheStorageEngineCaches.h: 56 (WebKit::CacheStorage::Caches::create): 57 (WebKit::CacheStorage::Caches::hasEnoughSpace const): 58 * NetworkProcess/cache/NetworkCacheStorage.cpp: 59 (WebKit::NetworkCache::Storage::traverse): 60 * NetworkProcess/cocoa/NetworkProcessCocoa.mm: 61 (WebKit::NetworkProcess::platformInitializeNetworkProcessCocoa): 62 * Shared/WebCoreArgumentCoders.cpp: 63 (IPC::ArgumentCoder<DOMCacheEngine::Record>::encode): 64 (IPC::ArgumentCoder<DOMCacheEngine::Record>::decode): 65 * UIProcess/API/APIProcessPoolConfiguration.cpp: 66 (API::ProcessPoolConfiguration::copy): 67 * UIProcess/API/APIProcessPoolConfiguration.h: 68 * UIProcess/WebProcessPool.cpp: 69 (WebKit::WebProcessPool::ensureNetworkProcess): 70 1 71 2017-10-09 Sam Weinig <sam@webkit.org> 2 72 -
trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp
r222673 r223073 767 767 } 768 768 769 uint64_t NetworkProcess::cacheStoragePerOriginQuota() const 770 { 771 return m_cacheStoragePerOriginQuota; 772 } 773 769 774 #if !PLATFORM(COCOA) 770 775 void NetworkProcess::initializeProcess(const ChildProcessInitializationParameters&) -
trunk/Source/WebKit/NetworkProcess/NetworkProcess.h
r222673 r223073 146 146 Seconds loadThrottleLatency() const { return m_loadThrottleLatency; } 147 147 String cacheStorageDirectory(PAL::SessionID) const; 148 uint64_t cacheStoragePerOriginQuota() const; 148 149 149 150 void preconnectTo(const WebCore::URL&, WebCore::StoredCredentialsPolicy); … … 238 239 239 240 String m_cacheStorageDirectory; 241 uint64_t m_cacheStoragePerOriginQuota { 0 }; 240 242 String m_diskCacheDirectory; 241 243 bool m_hasSetCacheModel; -
trunk/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.cpp
r221175 r223073 47 47 encoder << canHandleHTTPSServerTrustEvaluation; 48 48 encoder << cacheStorageDirectory; 49 encoder << cacheStoragePerOriginQuota; 49 50 encoder << cacheStorageDirectoryExtensionHandle; 50 51 encoder << diskCacheDirectory; … … 117 118 if (!decoder.decode(result.cacheStorageDirectory)) 118 119 return false; 120 if (!decoder.decode(result.cacheStoragePerOriginQuota)) 121 return false; 119 122 if (!decoder.decode(result.cacheStorageDirectoryExtensionHandle)) 120 123 return false; -
trunk/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.h
r222309 r223073 57 57 58 58 String cacheStorageDirectory; 59 uint64_t cacheStoragePerOriginQuota; 59 60 SandboxExtension::Handle cacheStorageDirectoryExtensionHandle; 60 61 String diskCacheDirectory; -
trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngine.cpp
r222880 r223073 191 191 initialize([this, origin, callback = WTFMove(callback)](std::optional<Error>&& error) mutable { 192 192 auto& caches = m_caches.ensure(origin, [&origin, this] { 193 return Caches::create(*this, String { origin } );193 return Caches::create(*this, String { origin }, NetworkProcess::singleton().cacheStoragePerOriginQuota()); 194 194 }).iterator->value; 195 195 -
trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCache.cpp
r222093 r223073 53 53 namespace CacheStorage { 54 54 55 static std::optional<std::pair<Record, double>> decodeRecordHeader(const Storage::Record&);56 57 55 static inline String computeKeyURL(const URL& url) 58 56 { … … 101 99 { 102 100 Key key { ASCIILiteral("record"), m_uniqueName, { }, createCanonicalUUIDString(), m_caches.salt() }; 103 RecordInformation recordInformation { WTFMove(key), monotonicallyIncreasingTimeMS(), record.identifier, 0 , record.re quest.url(), false, { } };101 RecordInformation recordInformation { WTFMove(key), monotonicallyIncreasingTimeMS(), record.identifier, 0 , record.responseBodySize, record.request.url(), false, { } }; 104 102 105 103 updateVaryInformation(recordInformation, record.request, record.response); … … 124 122 void Cache::clearMemoryRepresentation() 125 123 { 124 for (auto& records : m_records.values()) { 125 for (auto& record : records) 126 removeRecordFromDisk(record); 127 } 128 126 129 m_records = { }; 127 130 m_nextRecordIdentifier = 0; … … 131 134 static RecordInformation isolatedCopy(const RecordInformation& information) 132 135 { 133 auto result = RecordInformation { information.key, information.insertionTime, information.identifier, information.updateResponseCounter, information. url.isolatedCopy(), information.hasVaryStar, { } };136 auto result = RecordInformation { information.key, information.insertionTime, information.identifier, information.updateResponseCounter, information.size, information.url.isolatedCopy(), information.hasVaryStar, { } }; 134 137 HashMap<String, String> varyHeaders; 135 138 for (const auto& keyValue : information.varyHeaders) … … 176 179 RunLoop::main().dispatch([caches = WTFMove(caches), callback = WTFMove(callback), traversalResult = isolatedCopy(WTFMove(traversalResult)) ]() mutable { 177 180 for (auto& key : traversalResult.failedRecords) 178 caches->remove Record(key);181 caches->removeCacheEntry(key); 179 182 180 183 auto* cache = caches->find(traversalResult.cacheIdentifier); … … 195 198 } 196 199 197 auto& record = decoded-> first;198 auto insertionTime = decoded-> second;199 200 RecordInformation recordInformation { storageRecord->key, insertionTime, 0, 0, record.re quest.url(), false, { } };200 auto& record = decoded->record; 201 auto insertionTime = decoded->insertionTime; 202 203 RecordInformation recordInformation { storageRecord->key, insertionTime, 0, 0, record.responseBodySize, record.request.url(), false, { } }; 201 204 updateVaryInformation(recordInformation, record.request, record.response); 202 205 … … 378 381 }; 379 382 380 void Cache::put(Vector<Record>&& records, RecordIdentifiersCallback&& callback) 381 { 382 ASSERT(m_state == State::Open); 383 383 void Cache::storeRecords(Vector<Record>&& records, RecordIdentifiersCallback&& callback) 384 { 384 385 auto taskCounter = AsynchronousPutTaskCounter::create(WTFMove(callback)); 385 386 … … 387 388 for (auto& record : records) { 388 389 auto* sameURLRecords = recordsFromURL(record.request.url()); 389 390 390 auto matchingRecords = queryCache(sameURLRecords, record.request, options); 391 if (matchingRecords.isEmpty()) { 391 392 auto position = !matchingRecords.isEmpty() ? sameURLRecords->findMatching([&](const auto& item) { return item.identifier == matchingRecords[0]; }) : notFound; 393 394 if (position == notFound) { 392 395 record.identifier = ++m_nextRecordIdentifier; 393 396 taskCounter->addRecordIdentifier(record.identifier); 394 397 395 398 auto& recordToWrite = addRecord(sameURLRecords, record); 396 writeRecordToDisk(recordToWrite, WTFMove(record), taskCounter.copyRef() );399 writeRecordToDisk(recordToWrite, WTFMove(record), taskCounter.copyRef(), 0); 397 400 } else { 398 auto identifier = matchingRecords[0]; 399 auto position = sameURLRecords->findMatching([&](const auto& item) { return item.identifier == identifier; }); 400 ASSERT(position != notFound); 401 if (position != notFound) { 402 auto& existingRecord = sameURLRecords->at(position); 403 taskCounter->addRecordIdentifier(identifier); 404 updateRecordToDisk(existingRecord, WTFMove(record), taskCounter.copyRef()); 405 } 401 auto& existingRecord = sameURLRecords->at(position); 402 taskCounter->addRecordIdentifier(existingRecord.identifier); 403 updateRecordToDisk(existingRecord, WTFMove(record), taskCounter.copyRef()); 406 404 } 407 405 } 406 } 407 408 void Cache::put(Vector<Record>&& records, RecordIdentifiersCallback&& callback) 409 { 410 ASSERT(m_state == State::Open); 411 412 WebCore::CacheQueryOptions options; 413 uint64_t spaceRequired = 0; 414 415 for (auto& record : records) { 416 auto* sameURLRecords = recordsFromURL(record.request.url()); 417 auto matchingRecords = queryCache(sameURLRecords, record.request, options); 418 419 auto position = (sameURLRecords && !matchingRecords.isEmpty()) ? sameURLRecords->findMatching([&](const auto& item) { return item.identifier == matchingRecords[0]; }) : notFound; 420 421 spaceRequired += record.responseBodySize; 422 if (position != notFound) 423 spaceRequired -= sameURLRecords->at(position).size; 424 } 425 426 if (m_caches.hasEnoughSpace(spaceRequired)) { 427 storeRecords(WTFMove(records), WTFMove(callback)); 428 return; 429 } 430 431 m_caches.requestSpace(spaceRequired, [caches = makeRef(m_caches), identifier = m_identifier, records = WTFMove(records), callback = WTFMove(callback)](std::optional<DOMCacheEngine::Error>&& error) mutable { 432 if (error) { 433 callback(makeUnexpected(error.value())); 434 return; 435 } 436 auto* cache = caches->find(identifier); 437 if (!cache) 438 return; 439 440 cache->storeRecords(WTFMove(records), WTFMove(callback)); 441 }); 408 442 } 409 443 … … 447 481 } 448 482 449 void Cache::writeRecordToDisk(const RecordInformation& recordInformation, Record&& record, Ref<AsynchronousPutTaskCounter>&& taskCounter )450 { 451 m_caches.writeRecord(*this, recordInformation, WTFMove(record), [taskCounter = WTFMove(taskCounter)](std::optional<Error>&& error) {483 void Cache::writeRecordToDisk(const RecordInformation& recordInformation, Record&& record, Ref<AsynchronousPutTaskCounter>&& taskCounter, uint64_t previousRecordSize) 484 { 485 m_caches.writeRecord(*this, recordInformation, WTFMove(record), previousRecordSize, [taskCounter = WTFMove(taskCounter)](std::optional<Error>&& error) { 452 486 if (error) 453 487 taskCounter->setError(error.value()); … … 474 508 return; 475 509 auto& recordInfo = sameURLRecords->at(position); 510 auto previousSize = recordInfo.size; 511 recordInfo.size = record.responseBodySize; 476 512 477 513 auto& recordFromDisk = result.value(); … … 483 519 updateVaryInformation(recordInfo, record.request, record.response); 484 520 485 cache->writeRecordToDisk(recordInfo, WTFMove(record), WTFMove(taskCounter) );521 cache->writeRecordToDisk(recordInfo, WTFMove(record), WTFMove(taskCounter), previousSize); 486 522 }); 487 523 } … … 494 530 void Cache::removeRecordFromDisk(const RecordInformation& record) 495 531 { 496 m_caches.removeRecord(record .key);532 m_caches.removeRecord(record); 497 533 } 498 534 … … 501 537 WTF::Persistence::Encoder encoder; 502 538 encoder << recordInformation.insertionTime; 539 encoder << recordInformation.size; 503 540 encoder << record.requestHeadersGuard; 504 541 record.request.encodeWithoutPlatformData(encoder); … … 508 545 encoder << record.responseHeadersGuard; 509 546 encoder << record.response; 547 encoder << record.responseBodySize; 510 548 511 549 encoder.encodeChecksum(); … … 523 561 } 524 562 525 st atic inline std::optional<std::pair<Record, double>>decodeRecordHeader(const Storage::Record& storage)563 std::optional<Cache::DecodedRecord> Cache::decodeRecordHeader(const Storage::Record& storage) 526 564 { 527 565 WTF::Persistence::Decoder decoder(storage.header.data(), storage.header.size()); … … 533 571 return std::nullopt; 534 572 573 uint64_t size; 574 if (!decoder.decode(size)) 575 return std::nullopt; 576 535 577 if (!decoder.decode(record.requestHeadersGuard)) 536 578 return std::nullopt; … … 551 593 return std::nullopt; 552 594 595 if (!decoder.decode(record.responseBodySize)) 596 return std::nullopt; 597 553 598 if (!decoder.verifyChecksum()) 554 599 return std::nullopt; 555 600 556 return std::make_pair(WTFMove(record), insertionTime);601 return DecodedRecord { insertionTime, size, WTFMove(record) }; 557 602 } 558 603 … … 564 609 return std::nullopt; 565 610 566 auto record = WTFMove(result-> first);611 auto record = WTFMove(result->record); 567 612 record.responseBody = WebCore::SharedBuffer::create(storage.body.data(), storage.body.size()); 568 613 -
trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCache.h
r222073 r223073 44 44 uint64_t updateResponseCounter { 0 }; 45 45 46 uint64_t size { 0 }; 47 46 48 WebCore::URL url; 47 49 bool hasVaryStar { false }; … … 79 81 static NetworkCache::Storage::Record encode(const RecordInformation&, const WebCore::DOMCacheEngine::Record&); 80 82 83 struct DecodedRecord { 84 DecodedRecord(double insertionTime, uint64_t size, WebCore::DOMCacheEngine::Record&& record) 85 : insertionTime(insertionTime) 86 , size(size) 87 , record(WTFMove(record)) 88 { } 89 90 double insertionTime { 0 }; 91 uint64_t size { 0 }; 92 WebCore::DOMCacheEngine::Record record; 93 }; 94 static std::optional<DecodedRecord> decodeRecordHeader(const NetworkCache::Storage::Record&); 95 81 96 private: 82 97 Vector<RecordInformation>* recordsFromURL(const WebCore::URL&); 83 98 const Vector<RecordInformation>* recordsFromURL(const WebCore::URL&) const; 84 99 RecordInformation& addRecord(Vector<RecordInformation>*, const WebCore::DOMCacheEngine::Record&); 100 101 void storeRecords(Vector<WebCore::DOMCacheEngine::Record>&&, WebCore::DOMCacheEngine::RecordIdentifiersCallback&&); 85 102 86 103 RecordInformation toRecordInformation(const WebCore::DOMCacheEngine::Record&); … … 90 107 91 108 void readRecordsList(WebCore::DOMCacheEngine::CompletionCallback&&); 92 void writeRecordToDisk(const RecordInformation&, WebCore::DOMCacheEngine::Record&&, Ref<AsynchronousPutTaskCounter>&& );109 void writeRecordToDisk(const RecordInformation&, WebCore::DOMCacheEngine::Record&&, Ref<AsynchronousPutTaskCounter>&&, uint64_t previousRecordSize); 93 110 void updateRecordToDisk(RecordInformation&, WebCore::DOMCacheEngine::Record&&, Ref<AsynchronousPutTaskCounter>&&); 94 111 void removeRecordFromDisk(const RecordInformation&); -
trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.cpp
r222073 r223073 52 52 } 53 53 54 Caches::Caches(Engine& engine, String&& origin )54 Caches::Caches(Engine& engine, String&& origin, uint64_t quota) 55 55 : m_engine(&engine) 56 56 , m_origin(WTFMove(origin)) 57 57 , m_rootPath(cachesRootPath(engine, m_origin)) 58 , m_quota(quota) 58 59 { 59 60 } … … 85 86 m_storage = storage.releaseNonNull(); 86 87 m_storage->writeWithoutWaiting(); 87 readCachesFromDisk([this, callback = WTFMove(callback)](Expected<Vector<Cache>, Error>&& result) {88 readCachesFromDisk([this, callback = WTFMove(callback)](Expected<Vector<Cache>, Error>&& result) mutable { 88 89 makeDirty(); 89 90 … … 97 98 } 98 99 m_caches = WTFMove(result.value()); 99 m_isInitialized = true; 100 callback(std::nullopt); 101 102 auto pendingCallbacks = WTFMove(m_pendingInitializationCallbacks); 103 for (auto& callback : pendingCallbacks) 100 initializeSize(WTFMove(callback)); 101 }); 102 } 103 104 void Caches::initializeSize(WebCore::DOMCacheEngine::CompletionCallback&& callback) 105 { 106 uint64_t size = 0; 107 m_storage->traverse({ }, 0, [protectedThis = makeRef(*this), this, protectedStorage = makeRef(*m_storage), callback = WTFMove(callback), size](const auto* storage, const auto& information) mutable { 108 if (!storage) { 109 m_size = size; 110 m_isInitialized = true; 104 111 callback(std::nullopt); 112 113 auto pendingCallbacks = WTFMove(m_pendingInitializationCallbacks); 114 for (auto& callback : pendingCallbacks) 115 callback(std::nullopt); 116 117 return; 118 } 119 auto decoded = Cache::decodeRecordHeader(*storage); 120 if (decoded) 121 size += decoded->size; 105 122 }); 106 123 } … … 300 317 } 301 318 302 void Caches::writeRecord(const Cache& cache, const RecordInformation& recordInformation, Record&& record, CompletionCallback&& callback) 303 { 304 ASSERT(m_isInitialized); 305 306 // FIXME: Check for storage quota. 319 void Caches::requestSpace(uint64_t spaceRequired, WebCore::DOMCacheEngine::CompletionCallback&& callback) 320 { 321 // FIXME: Implement quota increase request. 322 ASSERT(m_quota < m_size + spaceRequired); 323 callback(Error::QuotaExceeded); 324 } 325 326 void Caches::writeRecord(const Cache& cache, const RecordInformation& recordInformation, Record&& record, uint64_t previousRecordSize, CompletionCallback&& callback) 327 { 328 ASSERT(m_isInitialized); 329 330 ASSERT(m_size >= previousRecordSize); 331 m_size += recordInformation.size; 332 m_size -= previousRecordSize; 333 334 ASSERT(m_size <= m_quota); 335 307 336 if (!shouldPersist()) { 308 337 m_volatileStorage.set(recordInformation.key, WTFMove(record)); … … 346 375 } 347 376 348 void Caches::removeRecord(const NetworkCache::Key& key) 377 void Caches::removeRecord(const RecordInformation& record) 378 { 379 ASSERT(m_isInitialized); 380 381 ASSERT(m_size >= record.size); 382 m_size -= record.size; 383 removeCacheEntry(record.key); 384 } 385 386 void Caches::removeCacheEntry(const NetworkCache::Key& key) 349 387 { 350 388 ASSERT(m_isInitialized); -
trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.h
r222073 r223073 37 37 class Caches : public RefCounted<Caches> { 38 38 public: 39 static Ref<Caches> create(Engine& engine, String&& origin ) { return adoptRef(*new Caches { engine, WTFMove(origin)}); }39 static Ref<Caches> create(Engine& engine, String&& origin, uint64_t quota) { return adoptRef(*new Caches { engine, WTFMove(origin), quota }); } 40 40 41 41 void initialize(WebCore::DOMCacheEngine::CompletionCallback&&); … … 55 55 void readRecordsList(Cache&, NetworkCache::Storage::TraverseHandler&&); 56 56 void readRecord(const NetworkCache::Key&, WTF::Function<void(Expected<WebCore::DOMCacheEngine::Record, WebCore::DOMCacheEngine::Error>&&)>&&); 57 void writeRecord(const Cache&, const RecordInformation&, WebCore::DOMCacheEngine::Record&&, WebCore::DOMCacheEngine::CompletionCallback&&); 58 void removeRecord(const NetworkCache::Key&); 57 58 bool hasEnoughSpace(uint64_t spaceRequired) const { return m_quota >= m_size + spaceRequired; } 59 void requestSpace(uint64_t spaceRequired, WebCore::DOMCacheEngine::CompletionCallback&&); 60 void writeRecord(const Cache&, const RecordInformation&, WebCore::DOMCacheEngine::Record&&, uint64_t previousRecordSize, WebCore::DOMCacheEngine::CompletionCallback&&); 61 62 void removeCacheEntry(const NetworkCache::Key&); 63 void removeRecord(const RecordInformation&); 59 64 60 65 const NetworkCache::Salt& salt() const; … … 63 68 64 69 private: 65 Caches(Engine&, String&& origin );70 Caches(Engine&, String&& origin, uint64_t quota); 66 71 72 void initializeSize(WebCore::DOMCacheEngine::CompletionCallback&&); 67 73 void readCachesFromDisk(WTF::Function<void(Expected<Vector<Cache>, WebCore::DOMCacheEngine::Error>&&)>&&); 68 74 void writeCachesToDisk(WebCore::DOMCacheEngine::CompletionCallback&&); … … 78 84 String m_origin; 79 85 String m_rootPath; 86 uint64_t m_quota { 0 }; 87 uint64_t m_size { 0 }; 80 88 Vector<Cache> m_caches; 81 89 Vector<Cache> m_removedCaches; -
trunk/Source/WebKit/NetworkProcess/cache/NetworkCacheStorage.cpp
r222073 r223073 862 862 ioQueue().dispatch([this, &traverseOperation] { 863 863 traverseRecordsFiles(recordsPath(), traverseOperation.type, [this, &traverseOperation](const String& fileName, const String& hashString, const String& type, bool isBlob, const String& recordDirectoryPath) { 864 ASSERT(type == traverseOperation.type );864 ASSERT(type == traverseOperation.type || traverseOperation.type.isEmpty()); 865 865 if (isBlob) 866 866 return; -
trunk/Source/WebKit/NetworkProcess/cocoa/NetworkProcessCocoa.mm
r222896 r223073 108 108 if (!parameters.cacheStorageDirectory.isNull()) { 109 109 m_cacheStorageDirectory = parameters.cacheStorageDirectory; 110 m_cacheStoragePerOriginQuota = parameters.cacheStoragePerOriginQuota; 110 111 SandboxExtension::consumePermanently(parameters.cacheStorageDirectoryExtensionHandle); 111 112 } -
trunk/Source/WebKit/Shared/WebCoreArgumentCoders.cpp
r222886 r223073 262 262 encoder << record.response; 263 263 encoder << record.updateResponseCounter; 264 encoder << record.responseBodySize; 264 265 265 266 WTF::switchOn(record.responseBody, [&](const Ref<SharedBuffer>& buffer) { … … 308 309 uint64_t updateResponseCounter; 309 310 if (!decoder.decode(updateResponseCounter)) 311 return std::nullopt; 312 313 uint64_t responseBodySize; 314 if (!decoder.decode(responseBodySize)) 310 315 return std::nullopt; 311 316 … … 333 338 } 334 339 335 return {{ WTFMove(identifier), WTFMove(updateResponseCounter), WTFMove(requestHeadersGuard), WTFMove(request), WTFMove(options), WTFMove(referrer), WTFMove(responseHeadersGuard), WTFMove(response), WTFMove(responseBody) }};340 return {{ WTFMove(identifier), WTFMove(updateResponseCounter), WTFMove(requestHeadersGuard), WTFMove(request), WTFMove(options), WTFMove(referrer), WTFMove(responseHeadersGuard), WTFMove(response), WTFMove(responseBody), responseBodySize }}; 336 341 } 337 342 -
trunk/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp
r222211 r223073 112 112 copy->m_applicationCacheFlatFileSubdirectoryName = this->m_applicationCacheFlatFileSubdirectoryName; 113 113 copy->m_cacheStorageDirectory = this->m_cacheStorageDirectory; 114 copy->m_diskCacheDirectory = this->m_diskCacheDirectory; 114 copy->m_cacheStorageDirectory = this->m_cacheStorageDirectory; 115 copy->m_cacheStoragePerOriginQuota = this->m_cacheStoragePerOriginQuota; 115 116 copy->m_mediaCacheDirectory = this->m_mediaCacheDirectory; 116 117 copy->m_indexedDBDatabaseDirectory = this->m_indexedDBDatabaseDirectory; -
trunk/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.h
r222309 r223073 70 70 const WTF::String& cacheStorageDirectory() const { return m_cacheStorageDirectory; } 71 71 void setCacheStorageDirectory(WTF::String&& cacheStorageDirectory) { m_cacheStorageDirectory = WTFMove(cacheStorageDirectory); } 72 uint64_t cacheStoragePerOriginQuota() const { return m_cacheStoragePerOriginQuota; } 72 73 73 74 const WTF::String& diskCacheDirectory() const { return m_diskCacheDirectory; } … … 153 154 WTF::String m_applicationCacheFlatFileSubdirectoryName; 154 155 WTF::String m_cacheStorageDirectory; 156 uint64_t m_cacheStoragePerOriginQuota { 400 * 1024 }; 155 157 WTF::String m_diskCacheDirectory; 156 158 WTF::String m_mediaCacheDirectory; -
trunk/Source/WebKit/UIProcess/WebProcessPool.cpp
r222664 r223073 435 435 436 436 parameters.cacheStorageDirectory = m_configuration->cacheStorageDirectory(); 437 parameters.cacheStoragePerOriginQuota = m_configuration->cacheStoragePerOriginQuota(); 437 438 if (!parameters.cacheStorageDirectory.isEmpty()) 438 439 SandboxExtension::createHandleForReadWriteDirectory(parameters.cacheStorageDirectory, parameters.cacheStorageDirectoryExtensionHandle);
Note: See TracChangeset
for help on using the changeset viewer.