3 * Copyright (C) 2017 Apple Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24 * THE POSSIBILITY OF SUCH DAMAGE.
28 #include "WorkerCacheStorageConnection.h"
30 #include "CacheQueryOptions.h"
31 #include "CacheStorageProvider.h"
34 #include "WorkerGlobalScope.h"
35 #include "WorkerLoaderProxy.h"
36 #include "WorkerRunLoop.h"
37 #include "WorkerThread.h"
41 struct CrossThreadRecordData {
43 uint64_t updateResponseCounter;
45 FetchHeaders::Guard requestHeadersGuard;
46 ResourceRequest request;
51 FetchHeaders::Guard responseHeadersGuard;
52 ResourceResponse::CrossThreadData response;
53 CacheStorageConnection::ResponseBody responseBody;
56 static CrossThreadRecordData toCrossThreadRecordData(const CacheStorageConnection::Record& record)
58 return CrossThreadRecordData {
60 record.updateResponseCounter,
61 record.requestHeadersGuard,
62 record.request.isolatedCopy(),
63 record.options.isolatedCopy(),
64 record.referrer.isolatedCopy(),
65 record.responseHeadersGuard,
66 record.response.crossThreadData(),
67 CacheStorageConnection::isolatedResponseBody(record.responseBody)
71 static CacheStorageConnection::Record fromCrossThreadRecordData(CrossThreadRecordData&& data)
73 return CacheStorageConnection::Record {
75 data.updateResponseCounter,
76 data.requestHeadersGuard,
77 WTFMove(data.request),
78 WTFMove(data.options),
79 WTFMove(data.referrer),
80 data.responseHeadersGuard,
81 ResourceResponse::fromCrossThreadData(WTFMove(data.response)),
82 WTFMove(data.responseBody)
86 Ref<WorkerCacheStorageConnection> WorkerCacheStorageConnection::create(WorkerGlobalScope& scope)
88 auto connection = adoptRef(*new WorkerCacheStorageConnection(scope));
89 connection->m_proxy.postTaskToLoader([protectedConnection = makeRef(connection.get())](ScriptExecutionContext& context) mutable {
90 ASSERT(isMainThread());
91 Document& document = downcast<Document>(context);
93 ASSERT(document.page());
94 protectedConnection->m_mainThreadConnection = document.page()->cacheStorageProvider().createCacheStorageConnection(document.page()->sessionID());
99 WorkerCacheStorageConnection::WorkerCacheStorageConnection(WorkerGlobalScope& scope)
101 , m_proxy(m_scope.thread().workerLoaderProxy())
102 , m_taskMode(WorkerRunLoop::defaultMode().isolatedCopy())
106 WorkerCacheStorageConnection::~WorkerCacheStorageConnection()
108 if (m_mainThreadConnection)
109 m_proxy.postTaskToLoader([mainThreadConnection = WTFMove(m_mainThreadConnection)](ScriptExecutionContext&) mutable { });
112 void WorkerCacheStorageConnection::doOpen(uint64_t requestIdentifier, const String& origin, const String& cacheName)
114 m_proxy.postTaskToLoader([this, protectedThis = makeRef(*this), requestIdentifier, origin = origin.isolatedCopy(), cacheName = cacheName.isolatedCopy()](ScriptExecutionContext&) mutable {
115 ASSERT(isMainThread());
116 ASSERT(m_mainThreadConnection);
118 m_mainThreadConnection->open(origin, cacheName, [this, protectedThis = WTFMove(protectedThis), requestIdentifier](uint64_t cacheIdentifier, Error error) mutable {
119 m_proxy.postTaskForModeToWorkerGlobalScope([this, error, cacheIdentifier, protectedThis = WTFMove(protectedThis), requestIdentifier](ScriptExecutionContext& context) mutable {
120 ASSERT_UNUSED(context, context.isWorkerGlobalScope());
121 openCompleted(requestIdentifier, cacheIdentifier, error);
127 void WorkerCacheStorageConnection::doRemove(uint64_t requestIdentifier, uint64_t cacheIdentifier)
129 m_proxy.postTaskToLoader([this, protectedThis = makeRef(*this), requestIdentifier, cacheIdentifier](ScriptExecutionContext&) mutable {
130 ASSERT(isMainThread());
131 ASSERT(m_mainThreadConnection);
133 m_mainThreadConnection->remove(cacheIdentifier, [this, protectedThis = WTFMove(protectedThis), requestIdentifier, cacheIdentifier](uint64_t removedCacheIdentifier, Error error) mutable {
134 ASSERT_UNUSED(removedCacheIdentifier, removedCacheIdentifier == cacheIdentifier);
135 m_proxy.postTaskForModeToWorkerGlobalScope([this, protectedThis = WTFMove(protectedThis), requestIdentifier, cacheIdentifier, error](ScriptExecutionContext& context) mutable {
136 ASSERT_UNUSED(context, context.isWorkerGlobalScope());
137 removeCompleted(requestIdentifier, cacheIdentifier, error);
143 void WorkerCacheStorageConnection::doRetrieveCaches(uint64_t requestIdentifier, const String& origin)
145 m_proxy.postTaskToLoader([this, protectedThis = makeRef(*this), requestIdentifier, origin = origin.isolatedCopy()](ScriptExecutionContext&) mutable {
146 ASSERT(isMainThread());
147 ASSERT(m_mainThreadConnection);
149 m_mainThreadConnection->retrieveCaches(origin, [this, protectedThis = WTFMove(protectedThis), requestIdentifier](const Vector<CacheInfo>& caches) mutable {
150 Vector<CacheInfo> isolatedCaches;
151 isolatedCaches.reserveInitialCapacity(caches.size());
152 for (const auto& cache : caches)
153 isolatedCaches.uncheckedAppend(CacheInfo { cache.identifier, cache.name.isolatedCopy() });
155 m_proxy.postTaskForModeToWorkerGlobalScope([this, protectedThis = WTFMove(protectedThis), caches = WTFMove(isolatedCaches), requestIdentifier](ScriptExecutionContext& context) mutable {
156 ASSERT_UNUSED(context, context.isWorkerGlobalScope());
157 updateCaches(requestIdentifier, WTFMove(caches));
163 static inline Vector<CrossThreadRecordData> recordsDataFromRecords(const Vector<CacheStorageConnection::Record>& records)
165 Vector<CrossThreadRecordData> recordsData;
166 recordsData.reserveInitialCapacity(records.size());
167 for (const auto& record : records)
168 recordsData.uncheckedAppend(toCrossThreadRecordData(record));
172 static inline Vector<CacheStorageConnection::Record> recordsFromRecordsData(Vector<CrossThreadRecordData>&& recordsData)
174 Vector<CacheStorageConnection::Record> records;
175 records.reserveInitialCapacity(recordsData.size());
176 for (auto& recordData : recordsData)
177 records.uncheckedAppend(fromCrossThreadRecordData(WTFMove(recordData)));
181 void WorkerCacheStorageConnection::doRetrieveRecords(uint64_t requestIdentifier, uint64_t cacheIdentifier)
183 m_proxy.postTaskToLoader([this, protectedThis = makeRef(*this), requestIdentifier, cacheIdentifier](ScriptExecutionContext&) mutable {
184 ASSERT(isMainThread());
185 ASSERT(m_mainThreadConnection);
187 m_mainThreadConnection->retrieveRecords(cacheIdentifier, [this, protectedThis = WTFMove(protectedThis), requestIdentifier](Vector<Record>&& records) mutable {
188 m_proxy.postTaskForModeToWorkerGlobalScope([this, protectedThis = WTFMove(protectedThis), recordsData = recordsDataFromRecords(records), requestIdentifier](ScriptExecutionContext& context) mutable {
189 ASSERT_UNUSED(context, context.isWorkerGlobalScope());
190 updateRecords(requestIdentifier, recordsFromRecordsData(WTFMove(recordsData)));
196 void WorkerCacheStorageConnection::doBatchDeleteOperation(uint64_t requestIdentifier, uint64_t cacheIdentifier, const ResourceRequest& request, CacheQueryOptions&& options)
198 m_proxy.postTaskToLoader([this, protectedThis = makeRef(*this), requestIdentifier, cacheIdentifier, request = request.isolatedCopy(), options = options.isolatedCopy()](ScriptExecutionContext&) mutable {
199 ASSERT(isMainThread());
200 ASSERT(m_mainThreadConnection);
202 m_mainThreadConnection->batchDeleteOperation(cacheIdentifier, request, WTFMove(options), [this, protectedThis = WTFMove(protectedThis), requestIdentifier](Vector<uint64_t>&& records, Error error) mutable {
204 m_proxy.postTaskForModeToWorkerGlobalScope([this, protectedThis = WTFMove(protectedThis), records = WTFMove(records), error, requestIdentifier](ScriptExecutionContext& context) mutable {
205 ASSERT_UNUSED(context, context.isWorkerGlobalScope());
206 deleteRecordsCompleted(requestIdentifier, WTFMove(records), error);
212 void WorkerCacheStorageConnection::doBatchPutOperation(uint64_t requestIdentifier, uint64_t cacheIdentifier, Vector<Record>&& records)
214 m_proxy.postTaskToLoader([this, protectedThis = makeRef(*this), requestIdentifier, cacheIdentifier, recordsData = recordsDataFromRecords(records)](ScriptExecutionContext&) mutable {
215 ASSERT(isMainThread());
216 ASSERT(m_mainThreadConnection);
218 m_mainThreadConnection->batchPutOperation(cacheIdentifier, recordsFromRecordsData(WTFMove(recordsData)), [this, protectedThis = WTFMove(protectedThis), requestIdentifier](Vector<uint64_t>&& records, Error error) mutable {
220 m_proxy.postTaskForModeToWorkerGlobalScope([this, protectedThis = WTFMove(protectedThis), records = WTFMove(records), error, requestIdentifier](ScriptExecutionContext& context) mutable {
221 ASSERT_UNUSED(context, context.isWorkerGlobalScope());
222 putRecordsCompleted(requestIdentifier, WTFMove(records), error);
228 } // namespace WebCore