2 * Copyright (C) 2017 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
27 #include "CacheStorage.h"
29 #include "CacheQueryOptions.h"
31 #include "ScriptExecutionContext.h"
35 CacheStorage::CacheStorage(ScriptExecutionContext& context, Ref<CacheStorageConnection>&& connection)
36 : ActiveDOMObject(&context)
37 , m_connection(WTFMove(connection))
42 String CacheStorage::origin() const
44 // FIXME: Do we really need to check for origin being null?
45 auto* origin = scriptExecutionContext() ? scriptExecutionContext()->securityOrigin() : nullptr;
46 return origin ? origin->toString() : String();
49 void CacheStorage::match(Cache::RequestInfo&&, CacheQueryOptions&&, Ref<DeferredPromise>&& promise)
51 promise->reject(Exception { NotSupportedError, ASCIILiteral("Not implemented")});
54 void CacheStorage::has(const String& name, DOMPromiseDeferred<IDLBoolean>&& promise)
56 retrieveCaches([this, name, promise = WTFMove(promise)]() mutable {
57 promise.resolve(m_caches.findMatching([&](auto& item) { return item->name() == name; }) != notFound);
61 void CacheStorage::retrieveCaches(WTF::Function<void()>&& callback)
63 String origin = this->origin();
67 setPendingActivity(this);
68 m_connection->retrieveCaches(origin, [this, callback = WTFMove(callback)](Vector<CacheStorageConnection::CacheInfo>&& cachesInfo) {
70 ASSERT(scriptExecutionContext());
71 m_caches.removeAllMatching([&](auto& cache) {
72 return cachesInfo.findMatching([&](const auto& info) { return info.identifier == cache->identifier(); }) == notFound;
74 for (auto& info : cachesInfo) {
75 if (m_caches.findMatching([&](const auto& cache) { return info.identifier == cache->identifier(); }) == notFound)
76 m_caches.append(Cache::create(*scriptExecutionContext(), WTFMove(info.name), info.identifier, m_connection.copyRef()));
79 std::sort(m_caches.begin(), m_caches.end(), [&](auto& a, auto& b) {
80 return a->identifier() < b->identifier();
85 unsetPendingActivity(this);
89 void CacheStorage::open(const String& name, DOMPromiseDeferred<IDLInterface<Cache>>&& promise)
91 retrieveCaches([this, name, promise = WTFMove(promise)]() mutable {
92 auto position = m_caches.findMatching([&](auto& item) { return item->name() == name; });
93 if (position != notFound) {
94 auto& cache = m_caches[position];
95 promise.resolve(Cache::create(*scriptExecutionContext(), String { cache->name() }, cache->identifier(), m_connection.copyRef()));
99 String origin = this->origin();
100 ASSERT(!origin.isNull());
102 setPendingActivity(this);
103 m_connection->open(origin, name, [this, name, promise = WTFMove(promise)](uint64_t cacheIdentifier, CacheStorageConnection::Error error) mutable {
105 if (error != CacheStorageConnection::Error::None)
106 promise.reject(CacheStorageConnection::exceptionFromError(error));
108 auto cache = Cache::create(*scriptExecutionContext(), String { name }, cacheIdentifier, m_connection.copyRef());
109 promise.resolve(cache);
110 m_caches.append(WTFMove(cache));
113 unsetPendingActivity(this);
118 void CacheStorage::remove(const String& name, DOMPromiseDeferred<IDLBoolean>&& promise)
120 retrieveCaches([this, name, promise = WTFMove(promise)]() mutable {
121 auto position = m_caches.findMatching([&](auto& item) { return item->name() == name; });
122 if (position == notFound) {
123 promise.resolve(false);
127 String origin = this->origin();
128 ASSERT(!origin.isNull());
130 setPendingActivity(this);
131 m_connection->remove(m_caches[position]->identifier(), [this, name, promise = WTFMove(promise)](uint64_t cacheIdentifier, CacheStorageConnection::Error error) mutable {
132 UNUSED_PARAM(cacheIdentifier);
134 if (error != CacheStorageConnection::Error::None)
135 promise.reject(CacheStorageConnection::exceptionFromError(error));
137 promise.resolve(true);
139 unsetPendingActivity(this);
141 m_caches.remove(position);
145 void CacheStorage::keys(KeysPromise&& promise)
147 retrieveCaches([this, promise = WTFMove(promise)]() mutable {
149 keys.reserveInitialCapacity(m_caches.size());
150 for (auto& cache : m_caches)
151 keys.uncheckedAppend(cache->name());
152 promise.resolve(keys);
156 void CacheStorage::stop()
161 const char* CacheStorage::activeDOMObjectName() const
163 return "CacheStorage";
166 bool CacheStorage::canSuspendForDocumentSuspension() const
168 return !hasPendingActivity();
171 } // namespace WebCore