Implement listing origins for which CacheStorage is storing data
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 13 Oct 2017 20:31:34 +0000 (20:31 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 13 Oct 2017 20:31:34 +0000 (20:31 +0000)
https://bugs.webkit.org/show_bug.cgi?id=178236

Patch by Youenn Fablet <youenn@apple.com> on 2017-10-13
Reviewed by Chris Dumez.

Source/WebKit:

Cache storage is split on per-origin folders which name is obfuscated through salting.
To retrieve the origin for each folder, an origin file is now stored within each folder.
This file contains the actual origin.

Adding support to get the list of origin by iterating through each folder and
getting the actual origin by reading the content of the 'origin' file.

Adding C API for WebKitTestRunner.

* NetworkProcess/cache/CacheStorageEngine.cpp:
(WebKit::CacheStorage::Engine::fetchEntries):
(WebKit::CacheStorage::ReadOriginsTaskCounter::create):
(WebKit::CacheStorage::ReadOriginsTaskCounter::~ReadOriginsTaskCounter):
(WebKit::CacheStorage::ReadOriginsTaskCounter::addOrigin):
(WebKit::CacheStorage::ReadOriginsTaskCounter::ReadOriginsTaskCounter):
* NetworkProcess/cache/CacheStorageEngine.h:
* NetworkProcess/cache/CacheStorageEngineCaches.cpp:
(WebKit::CacheStorage::cachesOriginFilename):
(WebKit::CacheStorage::Caches::retrieveOriginFromDirectory):
(WebKit::CacheStorage::Caches::Caches):
(WebKit::CacheStorage::Caches::storeOrigin):
(WebKit::CacheStorage::Caches::readOrigin):
(WebKit::CacheStorage::Caches::initialize):
* NetworkProcess/cache/CacheStorageEngineCaches.h:
(WebKit::CacheStorage::Caches::origin const):
* UIProcess/API/C/WKWebsiteDataStoreRef.cpp:
(WKWebsiteDataStoreGetFetchCacheOrigins):
* UIProcess/API/C/WKWebsiteDataStoreRef.h:

Tools:

Adding hasDOMCache API for checking whether origin is storing data through Cache API.

* WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
* WebKitTestRunner/InjectedBundle/TestRunner.cpp:
(WTR::TestRunner::hasDOMCache):
* WebKitTestRunner/InjectedBundle/TestRunner.h:
* WebKitTestRunner/TestController.cpp:
(WTR::FetchCacheOriginsCallbackContext::FetchCacheOriginsCallbackContext):
(WTR::fetchCacheOriginsCallback):
(WTR::TestController::hasDOMCache):
* WebKitTestRunner/TestController.h:
* WebKitTestRunner/TestInvocation.cpp:
(WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):

LayoutTests:

* http/tests/cache-storage/cache-clearing-origin.https.html:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@223299 268f45cc-cd09-0410-ab3c-d52691b4dbfc

16 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/cache-storage/cache-clearing-origin.https.html
Source/WebKit/ChangeLog
Source/WebKit/NetworkProcess/cache/CacheStorageEngine.cpp
Source/WebKit/NetworkProcess/cache/CacheStorageEngine.h
Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.cpp
Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.h
Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp
Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h
Tools/ChangeLog
Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl
Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp
Tools/WebKitTestRunner/InjectedBundle/TestRunner.h
Tools/WebKitTestRunner/TestController.cpp
Tools/WebKitTestRunner/TestController.h
Tools/WebKitTestRunner/TestInvocation.cpp

index 2b97e7c..b45e5ec 100644 (file)
@@ -1,5 +1,14 @@
 2017-10-13  Youenn Fablet  <youenn@apple.com>
 
+        Implement listing origins for which CacheStorage is storing data
+        https://bugs.webkit.org/show_bug.cgi?id=178236
+
+        Reviewed by Chris Dumez.
+
+        * http/tests/cache-storage/cache-clearing-origin.https.html:
+
+2017-10-13  Youenn Fablet  <youenn@apple.com>
+
         http/tests/cache-storage/cache-origins.https.html is flaky
         https://bugs.webkit.org/show_bug.cgi?id=178266
 
index 1ad7b42..090b65e 100644 (file)
@@ -22,12 +22,18 @@ promise_test(async test => {
 
     if (!window.testRunner)
         return Promise.reject("test runner needed");
+
+    assert_false(testRunner.hasDOMCache('https://localhost:80'), 'hasDOMCache with fake origin');
+    assert_true(testRunner.hasDOMCache(window.location.origin), "hasDOMCache with actual origin");
+
     testRunner.clearDOMCache('https://localhost:80');
 
     var keys = await self.caches.keys();
     assert_not_equals(keys.length, 0, "keys should not be empty");
 
     testRunner.clearDOMCache(window.location.origin);
+    assert_false(testRunner.hasDOMCache(window.location.origin), "Actual origin cache is cleared");
+
     keys = await self.caches.keys();
     assert_equals(keys.length, 0, "keys should be empty");
 
index 03011e7..943b303 100644 (file)
@@ -1,3 +1,39 @@
+2017-10-13  Youenn Fablet  <youenn@apple.com>
+
+        Implement listing origins for which CacheStorage is storing data
+        https://bugs.webkit.org/show_bug.cgi?id=178236
+
+        Reviewed by Chris Dumez.
+
+        Cache storage is split on per-origin folders which name is obfuscated through salting.
+        To retrieve the origin for each folder, an origin file is now stored within each folder.
+        This file contains the actual origin.
+
+        Adding support to get the list of origin by iterating through each folder and
+        getting the actual origin by reading the content of the 'origin' file.
+
+        Adding C API for WebKitTestRunner.
+
+        * NetworkProcess/cache/CacheStorageEngine.cpp:
+        (WebKit::CacheStorage::Engine::fetchEntries):
+        (WebKit::CacheStorage::ReadOriginsTaskCounter::create):
+        (WebKit::CacheStorage::ReadOriginsTaskCounter::~ReadOriginsTaskCounter):
+        (WebKit::CacheStorage::ReadOriginsTaskCounter::addOrigin):
+        (WebKit::CacheStorage::ReadOriginsTaskCounter::ReadOriginsTaskCounter):
+        * NetworkProcess/cache/CacheStorageEngine.h:
+        * NetworkProcess/cache/CacheStorageEngineCaches.cpp:
+        (WebKit::CacheStorage::cachesOriginFilename):
+        (WebKit::CacheStorage::Caches::retrieveOriginFromDirectory):
+        (WebKit::CacheStorage::Caches::Caches):
+        (WebKit::CacheStorage::Caches::storeOrigin):
+        (WebKit::CacheStorage::Caches::readOrigin):
+        (WebKit::CacheStorage::Caches::initialize):
+        * NetworkProcess/cache/CacheStorageEngineCaches.h:
+        (WebKit::CacheStorage::Caches::origin const):
+        * UIProcess/API/C/WKWebsiteDataStoreRef.cpp:
+        (WKWebsiteDataStoreGetFetchCacheOrigins):
+        * UIProcess/API/C/WKWebsiteDataStoreRef.h:
+
 2017-10-13  Alex Christensen  <achristensen@webkit.org>
 
         Fix API tests after r223269.
index 2e9cb29..4d2ab44 100644 (file)
@@ -29,8 +29,9 @@
 #include "NetworkCacheFileSystem.h"
 #include "NetworkCacheIOChannel.h"
 #include "NetworkProcess.h"
+#include "WebsiteDataType.h"
 #include <WebCore/CacheQueryOptions.h>
-#include <WebCore/NotImplemented.h>
+#include <WebCore/SecurityOrigin.h>
 #include <pal/SessionID.h>
 #include <wtf/CallbackAggregator.h>
 #include <wtf/NeverDestroyed.h>
@@ -80,11 +81,9 @@ void Engine::destroyEngine(PAL::SessionID sessionID)
     globalEngineMap().remove(sessionID);
 }
 
-void Engine::fetchEntries(PAL::SessionID sessionID, bool shouldComputeSize, WTF::Function<void(Vector<WebsiteData::Entry>)>&& completionHandler)
+void Engine::fetchEntries(PAL::SessionID sessionID, bool shouldComputeSize, WTF::CompletionHandler<void(Vector<WebsiteData::Entry>)>&& completionHandler)
 {
-    // FIXME: Support fetching entries
-    notImplemented();
-    completionHandler({ });
+    from(sessionID).fetchEntries(shouldComputeSize, WTFMove(completionHandler));
 }
 
 void Engine::clearAllEngines(WTF::Function<void()>&& completionHandler)
@@ -345,6 +344,54 @@ void Engine::removeCaches(const String& origin)
     m_caches.remove(origin);
 }
 
+class ReadOriginsTaskCounter : public RefCounted<ReadOriginsTaskCounter> {
+public:
+    static Ref<ReadOriginsTaskCounter> create(WTF::CompletionHandler<void(Vector<WebsiteData::Entry>)>&& callback)
+    {
+        return adoptRef(*new ReadOriginsTaskCounter(WTFMove(callback)));}
+
+    ~ReadOriginsTaskCounter()
+    {
+        m_callback(WTFMove(m_entries));
+    }
+
+    void addOrigin(WebCore::SecurityOriginData&& origin)
+    {
+        m_entries.append(WebsiteData::Entry { WTFMove(origin), WebsiteDataType::DOMCache, 0 });
+    }
+
+private:
+    explicit ReadOriginsTaskCounter(WTF::CompletionHandler<void(Vector<WebsiteData::Entry>)>&& callback)
+        : m_callback(WTFMove(callback))
+    {
+    }
+
+    WTF::CompletionHandler<void(Vector<WebsiteData::Entry>)> m_callback;
+    Vector<WebsiteData::Entry> m_entries;
+};
+
+void Engine::fetchEntries(bool /* shouldComputeSize */, WTF::CompletionHandler<void(Vector<WebsiteData::Entry>)>&& completionHandler)
+{
+    if (!shouldPersist()) {
+        auto entries = WTF::map(m_caches, [] (auto& pair) {
+            return WebsiteData::Entry { pair.value->origin(), WebsiteDataType::DOMCache, 0 };
+        });
+        completionHandler(WTFMove(entries));
+        return;
+    }
+
+    auto taskCounter = ReadOriginsTaskCounter::create(WTFMove(completionHandler));
+    for (auto& folderPath : WebCore::listDirectory(m_rootPath, "*")) {
+        if (!WebCore::fileIsDirectory(folderPath, WebCore::ShouldFollowSymbolicLinks::No))
+            continue;
+        Caches::retrieveOriginFromDirectory(folderPath, *m_ioQueue, [taskCounter = taskCounter.copyRef()] (std::optional<WebCore::SecurityOriginData>&& origin) mutable {
+            ASSERT(RunLoop::isMain());
+            if (origin)
+                taskCounter->addOrigin(WTFMove(origin.value()));
+        });
+    }
+}
+
 void Engine::clearAllCaches(CallbackAggregator& taskHandler)
 {
     for (auto& caches : m_caches.values())
index f19a185..ec8843a 100644 (file)
@@ -59,7 +59,7 @@ public:
     static void destroyEngine(PAL::SessionID);
     static void clearAllEngines(WTF::Function<void()>&&);
     static void clearEnginesForOrigins(const Vector<String>& origins, WTF::Function<void()>&&);
-    static void fetchEntries(PAL::SessionID, bool shouldComputeSize, WTF::Function<void(Vector<WebsiteData::Entry>)>&&);
+    static void fetchEntries(PAL::SessionID, bool shouldComputeSize, WTF::CompletionHandler<void(Vector<WebsiteData::Entry>)>&&);
 
     static Ref<Engine> create(String&& rootPath) { return adoptRef(*new Engine(WTFMove(rootPath))); }
 
@@ -95,6 +95,8 @@ private:
 
     String cachesRootPath(const String& origin);
 
+    void fetchEntries(bool /* shouldComputeSize */, WTF::CompletionHandler<void(Vector<WebsiteData::Entry>)>&&);
+
     void initialize(WTF::Function<void(std::optional<WebCore::DOMCacheEngine::Error>&&)>&&);
     void clearAllCaches(WTF::CallbackAggregator&);
     void clearCachesForOrigin(const String& origin, WTF::CallbackAggregator&);
index 6d21bec..3825128 100644 (file)
@@ -27,6 +27,8 @@
 #include "CacheStorageEngine.h"
 
 #include "NetworkCacheCoders.h"
+#include "NetworkCacheIOChannel.h"
+#include <WebCore/SecurityOrigin.h>
 #include <wtf/RunLoop.h>
 #include <wtf/UUID.h>
 #include <wtf/text/StringBuilder.h>
@@ -43,14 +45,67 @@ static inline String cachesListFilename(const String& cachesRootPath)
     return WebCore::pathByAppendingComponent(cachesRootPath, ASCIILiteral("cacheslist"));
 }
 
+static inline String cachesOriginFilename(const String& cachesRootPath)
+{
+    return WebCore::pathByAppendingComponent(cachesRootPath, ASCIILiteral("origin"));
+}
+
+void Caches::retrieveOriginFromDirectory(const String& folderPath, WorkQueue& queue, WTF::CompletionHandler<void(std::optional<WebCore::SecurityOriginData>&&)>&& completionHandler)
+{
+    queue.dispatch([completionHandler = WTFMove(completionHandler), folderPath = folderPath.isolatedCopy()]() mutable {
+        if (!WebCore::fileExists(cachesListFilename(folderPath))) {
+            RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler)]() mutable {
+                completionHandler(std::nullopt);
+            });
+            return;
+        }
+
+        auto channel = IOChannel::open(cachesOriginFilename(folderPath), IOChannel::Type::Read);
+        channel->read(0, std::numeric_limits<size_t>::max(), nullptr, [completionHandler = WTFMove(completionHandler)](const Data& data, int error) mutable {
+            ASSERT(RunLoop::isMain());
+            if (error) {
+                completionHandler(std::nullopt);
+                return;
+            }
+            completionHandler(readOrigin(data));
+        });
+    });
+}
+
 Caches::Caches(Engine& engine, String&& origin, String&& rootPath, uint64_t quota)
     : m_engine(&engine)
-    , m_origin(WTFMove(origin))
+    , m_origin(WebCore::SecurityOriginData::fromSecurityOrigin(WebCore::SecurityOrigin::createFromString(origin)))
     , m_rootPath(WTFMove(rootPath))
     , m_quota(quota)
 {
 }
 
+void Caches::storeOrigin(CompletionCallback&& completionHandler)
+{
+    WTF::Persistence::Encoder encoder;
+    encoder << m_origin.protocol;
+    encoder << m_origin.host;
+    encoder << m_origin.port;
+    m_engine->writeFile(cachesOriginFilename(m_rootPath), Data { encoder.buffer(), encoder.bufferSize() }, [protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)] (std::optional<Error>&& error) mutable {
+        completionHandler(WTFMove(error));
+    });
+}
+
+std::optional<WebCore::SecurityOriginData> Caches::readOrigin(const Data& data)
+{
+    // FIXME: We should be able to use modern decoders for persistent data.
+    WebCore::SecurityOriginData origin;
+    WTF::Persistence::Decoder decoder(data.data(), data.size());
+
+    if (!decoder.decode(origin.protocol))
+        return std::nullopt;
+    if (!decoder.decode(origin.host))
+        return std::nullopt;
+    if (!decoder.decode(origin.port))
+        return std::nullopt;
+    return WTFMove(origin);
+}
+
 void Caches::initialize(WebCore::DOMCacheEngine::CompletionCallback&& callback)
 {
     if (m_isInitialized) {
@@ -77,19 +132,28 @@ void Caches::initialize(WebCore::DOMCacheEngine::CompletionCallback&& callback)
     }
     m_storage = storage.releaseNonNull();
     m_storage->writeWithoutWaiting();
-    readCachesFromDisk([this, callback = WTFMove(callback)](Expected<Vector<Cache>, Error>&& result) mutable {
-        makeDirty();
-
-        if (!result.hasValue()) {
-            callback(result.error());
 
-            auto pendingCallbacks = WTFMove(m_pendingInitializationCallbacks);
-            for (auto& callback : pendingCallbacks)
-                callback(result.error());
+    storeOrigin([this, callback = WTFMove(callback)] (std::optional<Error>&& error) mutable {
+        if (error) {
+            callback(Error::WriteDisk);
             return;
         }
-        m_caches = WTFMove(result.value());
-        initializeSize(WTFMove(callback));
+
+        readCachesFromDisk([this, callback = WTFMove(callback)](Expected<Vector<Cache>, Error>&& result) mutable {
+            makeDirty();
+
+            if (!result.hasValue()) {
+                callback(result.error());
+
+                auto pendingCallbacks = WTFMove(m_pendingInitializationCallbacks);
+                for (auto& callback : pendingCallbacks)
+                    callback(result.error());
+                return;
+            }
+            m_caches = WTFMove(result.value());
+
+            initializeSize(WTFMove(callback));
+        });
     });
 }
 
index 671c319..1f057be 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "CacheStorageEngineCache.h"
 #include "NetworkCacheStorage.h"
+#include <WebCore/SecurityOriginData.h>
 #include <wtf/CompletionHandler.h>
 
 namespace WebKit {
@@ -39,6 +40,8 @@ class Caches : public RefCounted<Caches> {
 public:
     static Ref<Caches> create(Engine& engine, String&& origin, String&& rootPath, uint64_t quota) { return adoptRef(*new Caches { engine, WTFMove(origin), WTFMove(rootPath), quota }); }
 
+    static void retrieveOriginFromDirectory(const String& folderPath, WorkQueue&, WTF::CompletionHandler<void(std::optional<WebCore::SecurityOriginData>&&)>&&);
+
     void initialize(WebCore::DOMCacheEngine::CompletionCallback&&);
     void open(const String& name, WebCore::DOMCacheEngine::CacheIdentifierCallback&&);
     void remove(uint64_t identifier, WebCore::DOMCacheEngine::CacheIdentifierCallback&&);
@@ -63,6 +66,7 @@ public:
     void removeRecord(const RecordInformation&);
 
     const NetworkCache::Salt& salt() const;
+    const WebCore::SecurityOriginData& origin() const { return m_origin; }
 
     bool shouldPersist() const { return !m_rootPath.isNull(); }
 
@@ -76,6 +80,9 @@ private:
     void readCachesFromDisk(WTF::Function<void(Expected<Vector<Cache>, WebCore::DOMCacheEngine::Error>&&)>&&);
     void writeCachesToDisk(WebCore::DOMCacheEngine::CompletionCallback&&);
 
+    void storeOrigin(WebCore::DOMCacheEngine::CompletionCallback&&);
+    static std::optional<WebCore::SecurityOriginData> readOrigin(const NetworkCache::Data&);
+
     Cache* find(const String& name);
 
     void makeDirty() { ++m_updateCounter; }
@@ -84,7 +91,7 @@ private:
     bool m_isInitialized { false };
     Engine* m_engine { nullptr };
     uint64_t m_updateCounter { 0 };
-    String m_origin;
+    WebCore::SecurityOriginData m_origin;
     String m_rootPath;
     uint64_t m_quota { 0 };
     uint64_t m_size { 0 };
index 48fa548..cebf689 100644 (file)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "WKWebsiteDataStoreRef.h"
 
+#include "APIArray.h"
 #include "APIWebsiteDataStore.h"
 #include "WKAPICast.h"
 #include "WebResourceLoadStatisticsStore.h"
@@ -355,3 +356,15 @@ void WKWebsiteDataStoreRemoveAllServiceWorkerRegistrations(WKWebsiteDataStoreRef
     UNUSED_PARAM(dataStoreRef);
 #endif
 }
+
+void WKWebsiteDataStoreGetFetchCacheOrigins(WKWebsiteDataStoreRef dataStoreRef, void* context, WKWebsiteDataStoreGetFetchCacheOriginsFunction callback)
+{
+    WebKit::toImpl(dataStoreRef)->websiteDataStore().fetchData(WebKit::WebsiteDataType::DOMCache, { }, [context, callback] (auto dataRecords) {
+        Vector<RefPtr<API::Object>> securityOrigins;
+        for (const auto& dataRecord : dataRecords) {
+            for (const auto& origin : dataRecord.origins)
+                securityOrigins.append(API::SecurityOrigin::create(origin.securityOrigin()));
+        }
+        callback(WebKit::toAPI(API::Array::create(WTFMove(securityOrigins)).ptr()), context);
+    });
+}
index 538234b..8780638 100644 (file)
@@ -78,6 +78,9 @@ WK_EXPORT void WKWebsiteDataStoreRemoveAllFetchCaches(WKWebsiteDataStoreRef data
 WK_EXPORT void WKWebsiteDataStoreRemoveAllIndexedDatabases(WKWebsiteDataStoreRef dataStoreRef);
 WK_EXPORT void WKWebsiteDataStoreRemoveAllServiceWorkerRegistrations(WKWebsiteDataStoreRef dataStoreRef);
 
+typedef void (*WKWebsiteDataStoreGetFetchCacheOriginsFunction)(WKArrayRef, void*);
+WK_EXPORT void WKWebsiteDataStoreGetFetchCacheOrigins(WKWebsiteDataStoreRef dataStoreRef, void* context, WKWebsiteDataStoreGetFetchCacheOriginsFunction function);
+
 #ifdef __cplusplus
 }
 #endif
index d6bc5de..0e810ab 100644 (file)
@@ -1,3 +1,24 @@
+2017-10-13  Youenn Fablet  <youenn@apple.com>
+
+        Implement listing origins for which CacheStorage is storing data
+        https://bugs.webkit.org/show_bug.cgi?id=178236
+
+        Reviewed by Chris Dumez.
+
+        Adding hasDOMCache API for checking whether origin is storing data through Cache API.
+
+        * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
+        * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+        (WTR::TestRunner::hasDOMCache):
+        * WebKitTestRunner/InjectedBundle/TestRunner.h:
+        * WebKitTestRunner/TestController.cpp:
+        (WTR::FetchCacheOriginsCallbackContext::FetchCacheOriginsCallbackContext):
+        (WTR::fetchCacheOriginsCallback):
+        (WTR::TestController::hasDOMCache):
+        * WebKitTestRunner/TestController.h:
+        * WebKitTestRunner/TestInvocation.cpp:
+        (WTR::TestInvocation::didReceiveSynchronousMessageFromInjectedBundle):
+
 2017-10-13  Alex Christensen  <achristensen@webkit.org>
 
         Remove Editor::simplifyMarkup
index 6fe56f6..1cdc616 100644 (file)
@@ -58,6 +58,7 @@ interface TestRunner {
     void dumpPolicyDelegateCallbacks();
 
     void clearDOMCache(DOMString origin);
+    boolean hasDOMCache(DOMString origin);
 
     // Special options.
     void keepWebHistory();
index d538b71..e6585f4 100644 (file)
@@ -1836,4 +1836,13 @@ void TestRunner::clearDOMCache(JSStringRef origin)
     WKBundlePostSynchronousMessage(InjectedBundle::singleton().bundle(), messageName.get(), messageBody.get(), nullptr);
 }
 
+bool TestRunner::hasDOMCache(JSStringRef origin)
+{
+    WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("HasDOMCache"));
+    WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(origin));
+    WKTypeRef returnData = 0;
+    WKBundlePagePostSynchronousMessageForTesting(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get(), &returnData);
+    return WKBooleanGetValue(static_cast<WKBooleanRef>(returnData));
+}
+
 } // namespace WTR
index e8ed616..5c70c93 100644 (file)
@@ -165,6 +165,7 @@ public:
     JSValueRef originsWithApplicationCache();
 
     void clearDOMCache(JSStringRef origin);
+    bool hasDOMCache(JSStringRef origin);
 
     // Failed load condition testing
     void forceImmediateCompletion();
index ef0e5ce..dc785bc 100644 (file)
@@ -2335,6 +2335,44 @@ void TestController::clearDOMCache(WKStringRef origin)
 #endif
 }
 
+struct FetchCacheOriginsCallbackContext {
+    FetchCacheOriginsCallbackContext(TestController& controller, WKStringRef origin)
+        : testController(controller)
+        , origin(origin)
+    {
+    }
+
+    TestController& testController;
+    WKStringRef origin;
+
+    bool done { false };
+    bool result { false };
+};
+
+static void fetchCacheOriginsCallback(WKArrayRef origins, void* userData)
+{
+    auto* context = static_cast<FetchCacheOriginsCallbackContext*>(userData);
+    context->done = true;
+
+    auto size = WKArrayGetSize(origins);
+    for (size_t index = 0; index < size && !context->result; ++index) {
+        WKSecurityOriginRef securityOrigin = reinterpret_cast<WKSecurityOriginRef>(WKArrayGetItemAtIndex(origins, index));
+        if (WKStringIsEqual(context->origin, adoptWK(WKSecurityOriginCopyToString(securityOrigin)).get()))
+            context->result = true;
+    }
+    context->testController.notifyDone();
+}
+
+bool TestController::hasDOMCache(WKStringRef origin)
+{
+    auto* dataStore = WKContextGetWebsiteDataStore(platformContext());
+    FetchCacheOriginsCallbackContext context(*this, origin);
+    WKWebsiteDataStoreGetFetchCacheOrigins(dataStore, &context, fetchCacheOriginsCallback);
+    if (!context.done)
+        runUntil(context.done, m_currentInvocation->shortTimeout());
+    return context.result;
+}
+
 #if !PLATFORM(COCOA) || !WK_API_ENABLED
 
 void TestController::setStatisticsLastSeen(WKStringRef host, double seconds)
index 4749bdd..9b58669 100644 (file)
@@ -183,6 +183,8 @@ public:
     void statisticsClearThroughWebsiteDataRemoval();
     void statisticsResetToConsistentState();
 
+    bool hasDOMCache(WKStringRef);
+
     WKArrayRef openPanelFileURLs() const { return m_openPanelFileURLs.get(); }
     void setOpenPanelFileURLs(WKArrayRef fileURLs) { m_openPanelFileURLs = fileURLs; }
 
index c793a04..f6b778c 100644 (file)
@@ -1210,6 +1210,15 @@ WKRetainPtr<WKTypeRef> TestInvocation::didReceiveSynchronousMessageFromInjectedB
         return nullptr;
     }
 
+    if (WKStringIsEqualToUTF8CString(messageName, "HasDOMCache")) {
+        ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
+        WKStringRef origin = static_cast<WKStringRef>(messageBody);
+
+        bool hasDOMCache = TestController::singleton().hasDOMCache(origin);
+        WKRetainPtr<WKTypeRef> result(AdoptWK, WKBooleanCreate(hasDOMCache));
+        return result;
+    }
+
     ASSERT_NOT_REACHED();
     return nullptr;
 }