Add API to clean CacheStorage data
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 11 Oct 2017 23:55:11 +0000 (23:55 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 11 Oct 2017 23:55:11 +0000 (23:55 +0000)
https://bugs.webkit.org/show_bug.cgi?id=178034

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

Source/WebCore:

Test: http/tests/cache-storage/cache-clearing.https.html

* platform/FileSystem.h:

Source/WebKit:

Introducing a new website data type for DOMCache.
Adding API to delete DOMCache for a given origin or for all origins.
This is added to WKWebsiteDataStore.

Cleaning a CacheStorage will remove all data in the Cache object but the object will stay live
for the duration of the NetworkProcess.
This allows ensuring that once a cache is cleaned, WebProcess will update to this new state.

Fetching of WebsiteData for DOMCache is not implemented yet since we do not keep a list of all origins for which we have data.

* NetworkProcess/NetworkProcess.cpp:
(WebKit::fetchDOMCacheEntries):
(WebKit::NetworkProcess::fetchWebsiteData):
(WebKit::NetworkProcess::deleteWebsiteData):
(WebKit::NetworkProcess::deleteWebsiteDataForOrigins):
* NetworkProcess/cache/CacheStorageEngine.cpp:
(WebKit::CacheStorage::Engine::cachesRootPath):
(WebKit::CacheStorage::Engine::fetchEntries):
(WebKit::CacheStorage::ClearTasksHandler::ClearTasksHandler):
(WebKit::CacheStorage::ClearTasksHandler::~ClearTasksHandler):
(WebKit::CacheStorage::Engine::clearEngines):
(WebKit::CacheStorage::Engine::clearCachesForOrigins):
(WebKit::CacheStorage::Engine::readCachesFromDisk):
(WebKit::CacheStorage::deleteFolder):
(WebKit::CacheStorage::Engine::clearCaches):
(WebKit::CacheStorage::Engine::unlock): Removing the assertion as Cache objects are removed when clearing data.
* NetworkProcess/cache/CacheStorageEngine.h:
* NetworkProcess/cache/CacheStorageEngineCaches.cpp:
(WebKit::CacheStorage::Caches::Caches):
(WebKit::CacheStorage::Caches::clear):
* NetworkProcess/cache/CacheStorageEngineCaches.h:
(WebKit::CacheStorage::Caches::create):
* Shared/WebsiteData/WebsiteDataType.h:
* UIProcess/API/C/WKWebsiteDataStoreRef.cpp:
(WKWebsiteDataStoreRemoveAllDOMCaches):
(WKWebsiteDataStoreRemoveDOMCacheForOrigin):
* UIProcess/API/C/WKWebsiteDataStoreRef.h:
* UIProcess/API/Cocoa/WKWebsiteDataRecord.h:
* UIProcess/API/Cocoa/WKWebsiteDataRecord.mm:
(dataTypesToString):
* UIProcess/API/Cocoa/WKWebsiteDataRecordInternal.h:
(WebKit::toWebsiteDataType):
(WebKit::toWKWebsiteDataTypes):
* UIProcess/API/Cocoa/WKWebsiteDataStore.mm:
(+[WKWebsiteDataStore allWebsiteDataTypes]):
* UIProcess/WebsiteData/WebsiteDataStore.cpp:
(WebKit::computeNetworkProcessAccessTypeForDataFetch):
(WebKit::computeNetworkProcessAccessTypeForDataRemoval):

Source/WTF:

Moving CallbackAggregator pattern into its own class for easier reuse.

* WTF.xcodeproj/project.pbxproj:
* wtf/CallbackAggregator.h: Added.
(WTF::CallbackAggregator::create):
(WTF::CallbackAggregator::~CallbackAggregator):
(WTF::CallbackAggregator::CallbackAggregator):

Tools:

Adding internals API to trigger deleting all or origin-persistent cache storage persistent data.

* WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
* WebKitTestRunner/InjectedBundle/TestRunner.cpp:
(WTR::TestRunner::clearDOMCache):
* WebKitTestRunner/InjectedBundle/TestRunner.h:
* WebKitTestRunner/TestController.cpp:
(WTR::TestController::clearDOMCache):
* WebKitTestRunner/TestController.h:
* WebKitTestRunner/TestInvocation.cpp:
(WTR::TestInvocation::didReceiveMessageFromInjectedBundle):

LayoutTests:

* http/tests/cache-storage/cache-clearing.https-expected.txt: Added.
* http/tests/cache-storage/cache-clearing.https.html: Added.

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

29 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/cache-storage/cache-clearing.https-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/cache-storage/cache-clearing.https.html [new file with mode: 0644]
Source/WTF/ChangeLog
Source/WTF/WTF.xcodeproj/project.pbxproj
Source/WTF/wtf/CallbackAggregator.h [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/platform/FileSystem.h
Source/WebKit/ChangeLog
Source/WebKit/NetworkProcess/NetworkProcess.cpp
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/Shared/WebsiteData/WebsiteDataType.h
Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp
Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h
Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataRecord.h
Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataRecord.mm
Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataRecordInternal.h
Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm
Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp
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 7f333cf..5920f5e 100644 (file)
@@ -1,3 +1,13 @@
+2017-10-11  Youenn Fablet  <youenn@apple.com>
+
+        Add API to clean CacheStorage data
+        https://bugs.webkit.org/show_bug.cgi?id=178034
+
+        Reviewed by Chris Dumez.
+
+        * http/tests/cache-storage/cache-clearing.https-expected.txt: Added.
+        * http/tests/cache-storage/cache-clearing.https.html: Added.
+
 2017-10-11  Chris Dumez  <cdumez@apple.com>
 
         [Geolocation] Expose Coordinates.floorLevel
diff --git a/LayoutTests/http/tests/cache-storage/cache-clearing.https-expected.txt b/LayoutTests/http/tests/cache-storage/cache-clearing.https-expected.txt
new file mode 100644 (file)
index 0000000..55abe34
--- /dev/null
@@ -0,0 +1,5 @@
+
+PASS Cleaning existing caches 
+PASS Clearing disk cache of a given origin 
+PASS Clearing all disk cache 
+
diff --git a/LayoutTests/http/tests/cache-storage/cache-clearing.https.html b/LayoutTests/http/tests/cache-storage/cache-clearing.https.html
new file mode 100644 (file)
index 0000000..4bc7374
--- /dev/null
@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Cache Storage: testing Cache persistency</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+    <script>
+promise_test(test => {
+    return self.caches.keys().then(keys => {
+        var pending = [];
+        for (key of keys)
+            pending.push(self.caches.delete(keys[0]));
+        return Promise.all(pending);
+    });
+}, "Cleaning existing caches");
+
+var test_url = 'https://example.com/foo';
+var test_body = 'Hello world!';
+
+function waitFor(delay)
+{
+    return new Promise(resolve => {
+        setTimeout(resolve, delay);
+    });
+}
+
+async function validateCachesEmptyness(expected, counter)
+{
+    var keys = await self.caches.keys();
+
+    var isEmpty = keys.length === 0;
+    if (isEmpty === expected)
+        return true;
+
+    if (counter > 10)
+        return false;
+
+    await waitFor(100);
+    if (!counter)
+        counter = 0;
+    return validateCachesEmptyness(expected, ++counter);
+}
+
+promise_test(() => {
+    var cache;
+    var cache_keys;
+    var first_response = new Response("Old body", { statusText: 'Old status' });
+    var alternate_response = new Response("New body", { statusText: 'New status' });
+    return self.caches.open("test-cache-records-persistency").then(c => {
+        cache = c;
+    }).then(() => {
+        return cache.put(test_url, first_response);
+    }).then(() => {
+        if (!window.testRunner)
+            return Promise.reject("test runner needed");
+        testRunner.clearDOMCache('https://localhost:80');
+        return validateCachesEmptyness(false);
+    }).then(result => {
+        assert_true(result, "caches should not be empty");
+        testRunner.clearDOMCache(window.location.origin);
+        return validateCachesEmptyness(true);
+    }).then(result => {
+        assert_true(result, "caches should be empty");
+        return self.caches.open("test-cache-records-persistency");
+    }).then(cache => {
+        return cache.keys();
+    }).then(keys => {
+        assert_equals(keys.length, 0, "records should be empty");
+    });
+}, 'Clearing disk cache of a given origin');
+
+promise_test(() => {
+    var cache;
+    var cache_keys;
+    var first_response = new Response("Old body", { statusText: 'Old status' });
+    var alternate_response = new Response("New body", { statusText: 'New status' });
+    return self.caches.open("test-cache-records-persistency").then(c => {
+        cache = c;
+    }).then(() => {
+        return cache.put(test_url, first_response);
+    }).then(() => {
+        if (!window.testRunner)
+            return Promise.reject("test runner needed");
+        testRunner.clearDOMCache();
+        return validateCachesEmptyness(true);
+    }).then(result => {
+        assert_true(result, "caches should be empty");
+        return self.caches.open("test-cache-records-persistency");
+    }).then(cache => {
+        return cache.keys();
+    }).then(keys => {
+        assert_equals(keys.length, 0, "records should be empty");
+    });
+}, 'Clearing all disk cache');
+    </script>
+</body>
+</html>
index f5b4c18..fd9390f 100644 (file)
@@ -1,3 +1,18 @@
+2017-10-11  Youenn Fablet  <youenn@apple.com>
+
+        Add API to clean CacheStorage data
+        https://bugs.webkit.org/show_bug.cgi?id=178034
+
+        Reviewed by Chris Dumez.
+
+        Moving CallbackAggregator pattern into its own class for easier reuse.
+
+        * WTF.xcodeproj/project.pbxproj:
+        * wtf/CallbackAggregator.h: Added.
+        (WTF::CallbackAggregator::create):
+        (WTF::CallbackAggregator::~CallbackAggregator):
+        (WTF::CallbackAggregator::CallbackAggregator):
+
 2017-10-10  Sam Weinig  <sam@webkit.org>
 
         Replace copyKeysToVector/copyValuesToVector with copyToVector(map.keys())/copyToVector(map.values())
index b484d61..617d62e 100644 (file)
                3137E1D7DBD84AC38FAE4D34 /* IndexSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IndexSet.h; sourceTree = "<group>"; };
                313EDEC9778E49C9BEA91CFC /* StackTrace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StackTrace.cpp; sourceTree = "<group>"; };
                37C7CC291EA40A73007BD956 /* WeakLinking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakLinking.h; sourceTree = "<group>"; };
+               413FE8F51F8D2EAB00F6D7D7 /* CallbackAggregator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallbackAggregator.h; sourceTree = "<group>"; };
                430B47871AAAAC1A001223DA /* StringCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringCommon.h; sourceTree = "<group>"; };
                46BA9EAB1F4CD61E009A2BBC /* CompletionHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CompletionHandler.h; sourceTree = "<group>"; };
                513E170A1CD7D5BF00E3650B /* LoggingAccumulator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoggingAccumulator.h; sourceTree = "<group>"; };
                                EB95E1EF161A72410089A2F5 /* ByteOrder.h */,
                                0FEC3C4F1F323C6800F59B6C /* CagedPtr.h */,
                                0F5F3D681F3FEBA600B115A2 /* CagedUniquePtr.h */,
+                               413FE8F51F8D2EAB00F6D7D7 /* CallbackAggregator.h */,
                                A8A4726A151A825A004123FF /* CheckedArithmetic.h */,
                                A8A4726B151A825A004123FF /* CheckedBoolean.h */,
                                0F66B2801DC97BAB004A1D3F /* ClockType.cpp */,
diff --git a/Source/WTF/wtf/CallbackAggregator.h b/Source/WTF/wtf/CallbackAggregator.h
new file mode 100644 (file)
index 0000000..553bd45
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "CompletionHandler.h"
+#include "MainThread.h"
+#include "ThreadSafeRefCounted.h"
+
+namespace WTF {
+
+class CallbackAggregator : public ThreadSafeRefCounted<CallbackAggregator> {
+public:
+    static Ref<CallbackAggregator> create(CompletionHandler<void()>&& callback) { return adoptRef(*new CallbackAggregator(WTFMove(callback))); }
+
+    ~CallbackAggregator()
+    {
+        if (!m_callback)
+            return;
+        if (isMainThread()) {
+            m_callback();
+            return;
+        }
+        callOnMainThread([callback = WTFMove(m_callback)] () mutable {
+            callback();
+        });
+    }
+
+private:
+    explicit CallbackAggregator(CompletionHandler<void()>&& callback)
+        : m_callback(WTFMove(callback))
+    {
+    }
+
+    CompletionHandler<void()> m_callback;
+};
+
+} // namespace WTF
+
+using WTF::CallbackAggregator;
index 1e1bfb9..2579ba2 100644 (file)
@@ -1,3 +1,14 @@
+2017-10-11  Youenn Fablet  <youenn@apple.com>
+
+        Add API to clean CacheStorage data
+        https://bugs.webkit.org/show_bug.cgi?id=178034
+
+        Reviewed by Chris Dumez.
+
+        Test: http/tests/cache-storage/cache-clearing.https.html
+
+        * platform/FileSystem.h:
+
 2017-10-11  David Kilzer  <ddkilzer@apple.com>
 
         Part 2: Fix -Wcast-qual and -Wunused-lambda-capture warnings in WebCore with new clang compiler
index f5e7ec7..32c93e6 100644 (file)
@@ -104,7 +104,7 @@ WEBCORE_EXPORT bool getFileModificationTime(const String&, time_t& result);
 WEBCORE_EXPORT bool getFileCreationTime(const String&, time_t& result); // Not all platforms store file creation time.
 WEBCORE_EXPORT std::optional<FileMetadata> fileMetadata(const String& path);
 WEBCORE_EXPORT std::optional<FileMetadata> fileMetadataFollowingSymlinks(const String& path);
-bool fileIsDirectory(const String&, ShouldFollowSymbolicLinks);
+WEBCORE_EXPORT bool fileIsDirectory(const String&, ShouldFollowSymbolicLinks);
 WEBCORE_EXPORT String pathByAppendingComponent(const String& path, const String& component);
 String pathByAppendingComponents(StringView path, const Vector<StringView>& components);
 String lastComponentOfPathIgnoringTrailingSlash(const String& path);
index 5c347c3..b35b3cb 100644 (file)
@@ -1,3 +1,59 @@
+2017-10-11  Youenn Fablet  <youenn@apple.com>
+
+        Add API to clean CacheStorage data
+        https://bugs.webkit.org/show_bug.cgi?id=178034
+
+        Reviewed by Chris Dumez.
+
+        Introducing a new website data type for DOMCache.
+        Adding API to delete DOMCache for a given origin or for all origins.
+        This is added to WKWebsiteDataStore.
+
+        Cleaning a CacheStorage will remove all data in the Cache object but the object will stay live
+        for the duration of the NetworkProcess.
+        This allows ensuring that once a cache is cleaned, WebProcess will update to this new state.
+
+        Fetching of WebsiteData for DOMCache is not implemented yet since we do not keep a list of all origins for which we have data.
+
+        * NetworkProcess/NetworkProcess.cpp:
+        (WebKit::fetchDOMCacheEntries):
+        (WebKit::NetworkProcess::fetchWebsiteData):
+        (WebKit::NetworkProcess::deleteWebsiteData):
+        (WebKit::NetworkProcess::deleteWebsiteDataForOrigins):
+        * NetworkProcess/cache/CacheStorageEngine.cpp:
+        (WebKit::CacheStorage::Engine::cachesRootPath):
+        (WebKit::CacheStorage::Engine::fetchEntries):
+        (WebKit::CacheStorage::ClearTasksHandler::ClearTasksHandler):
+        (WebKit::CacheStorage::ClearTasksHandler::~ClearTasksHandler):
+        (WebKit::CacheStorage::Engine::clearEngines):
+        (WebKit::CacheStorage::Engine::clearCachesForOrigins):
+        (WebKit::CacheStorage::Engine::readCachesFromDisk):
+        (WebKit::CacheStorage::deleteFolder):
+        (WebKit::CacheStorage::Engine::clearCaches):
+        (WebKit::CacheStorage::Engine::unlock): Removing the assertion as Cache objects are removed when clearing data.
+        * NetworkProcess/cache/CacheStorageEngine.h:
+        * NetworkProcess/cache/CacheStorageEngineCaches.cpp:
+        (WebKit::CacheStorage::Caches::Caches):
+        (WebKit::CacheStorage::Caches::clear):
+        * NetworkProcess/cache/CacheStorageEngineCaches.h:
+        (WebKit::CacheStorage::Caches::create):
+        * Shared/WebsiteData/WebsiteDataType.h:
+        * UIProcess/API/C/WKWebsiteDataStoreRef.cpp:
+        (WKWebsiteDataStoreRemoveAllDOMCaches):
+        (WKWebsiteDataStoreRemoveDOMCacheForOrigin):
+        * UIProcess/API/C/WKWebsiteDataStoreRef.h:
+        * UIProcess/API/Cocoa/WKWebsiteDataRecord.h:
+        * UIProcess/API/Cocoa/WKWebsiteDataRecord.mm:
+        (dataTypesToString):
+        * UIProcess/API/Cocoa/WKWebsiteDataRecordInternal.h:
+        (WebKit::toWebsiteDataType):
+        (WebKit::toWKWebsiteDataTypes):
+        * UIProcess/API/Cocoa/WKWebsiteDataStore.mm:
+        (+[WKWebsiteDataStore allWebsiteDataTypes]):
+        * UIProcess/WebsiteData/WebsiteDataStore.cpp:
+        (WebKit::computeNetworkProcessAccessTypeForDataFetch):
+        (WebKit::computeNetworkProcessAccessTypeForDataRemoval):
+
 2017-10-11  Chris Dumez  <cdumez@apple.com>
 
         [Geolocation] Expose Coordinates.floorLevel
index 3bdaba7..ea26243 100644 (file)
@@ -66,6 +66,7 @@
 #include <WebCore/Settings.h>
 #include <WebCore/URLParser.h>
 #include <pal/SessionID.h>
+#include <wtf/CallbackAggregator.h>
 #include <wtf/OptionSet.h>
 #include <wtf/RunLoop.h>
 #include <wtf/text/AtomicString.h>
@@ -407,6 +408,12 @@ void NetworkProcess::fetchWebsiteData(PAL::SessionID sessionID, OptionSet<Websit
             callbackAggregator->m_websiteData.entries.appendVector(entries);
         });
     }
+
+    if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
+        CacheStorage::Engine::fetchEntries(sessionID, fetchOptions.contains(WebsiteDataFetchOption::ComputeSizes), [callbackAggregator = WTFMove(callbackAggregator)](auto entries) mutable {
+            callbackAggregator->m_websiteData.entries.appendVector(entries);
+        });
+    }
 }
 
 void NetworkProcess::deleteWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, std::chrono::system_clock::time_point modifiedSince, uint64_t callbackID)
@@ -427,17 +434,16 @@ void NetworkProcess::deleteWebsiteData(PAL::SessionID sessionID, OptionSet<Websi
         if (NetworkStorageSession::storageSession(sessionID))
             NetworkStorageSession::storageSession(sessionID)->credentialStorage().clearCredentials();
     }
-    
-    auto completionHandler = [this, callbackID] {
+
+    auto clearTasksHandler = WTF::CallbackAggregator::create([this, callbackID] {
         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteData(callbackID), 0);
-    };
+    });
 
-    if (websiteDataTypes.contains(WebsiteDataType::DiskCache) && !sessionID.isEphemeral()) {
-        clearDiskCache(modifiedSince, WTFMove(completionHandler));
-        return;
-    }
+    if (websiteDataTypes.contains(WebsiteDataType::DOMCache))
+        CacheStorage::Engine::clearAllEngines([clearTasksHandler = clearTasksHandler.copyRef()] { });
 
-    completionHandler();
+    if (websiteDataTypes.contains(WebsiteDataType::DiskCache) && !sessionID.isEphemeral())
+        clearDiskCache(modifiedSince, [clearTasksHandler = WTFMove(clearTasksHandler)] { });
 }
 
 static void clearDiskCacheEntries(const Vector<SecurityOriginData>& origins, Function<void ()>&& completionHandler)
@@ -465,23 +471,26 @@ static void clearDiskCacheEntries(const Vector<SecurityOriginData>& origins, Fun
     RunLoop::main().dispatch(WTFMove(completionHandler));
 }
 
-void NetworkProcess::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, const Vector<SecurityOriginData>& origins, const Vector<String>& cookieHostNames, uint64_t callbackID)
+void NetworkProcess::deleteWebsiteDataForOrigins(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, const Vector<SecurityOriginData>& originDatas, const Vector<String>& cookieHostNames, uint64_t callbackID)
 {
     if (websiteDataTypes.contains(WebsiteDataType::Cookies)) {
         if (auto* networkStorageSession = NetworkStorageSession::storageSession(sessionID))
             deleteCookiesForHostnames(*networkStorageSession, cookieHostNames);
     }
 
-    auto completionHandler = [this, callbackID] {
+    auto clearTasksHandler = WTF::CallbackAggregator::create([this, callbackID] {
         parentProcessConnection()->send(Messages::NetworkProcessProxy::DidDeleteWebsiteDataForOrigins(callbackID), 0);
-    };
+    });
 
-    if (websiteDataTypes.contains(WebsiteDataType::DiskCache) && !sessionID.isEphemeral()) {
-        clearDiskCacheEntries(origins, WTFMove(completionHandler));
-        return;
+    if (websiteDataTypes.contains(WebsiteDataType::DOMCache)) {
+        auto origins = WTF::map(originDatas, [] (auto& originData) {
+            return originData.securityOrigin()->toString();
+        });
+        CacheStorage::Engine::clearEnginesForOrigins(origins, [clearTasksHandler = clearTasksHandler.copyRef()] { });
     }
 
-    completionHandler();
+    if (websiteDataTypes.contains(WebsiteDataType::DiskCache) && !sessionID.isEphemeral())
+        clearDiskCacheEntries(originDatas, [clearTasksHandler = WTFMove(clearTasksHandler)] { });
 }
 
 void NetworkProcess::downloadRequest(PAL::SessionID sessionID, DownloadID downloadID, const ResourceRequest& request, const String& suggestedFilename)
index 727ce49..d2a7efc 100644 (file)
 #include "config.h"
 #include "CacheStorageEngine.h"
 
+#include "NetworkCacheFileSystem.h"
 #include "NetworkCacheIOChannel.h"
 #include "NetworkProcess.h"
 #include <WebCore/CacheQueryOptions.h>
+#include <WebCore/NotImplemented.h>
 #include <pal/SessionID.h>
-#include <wtf/MainThread.h>
+#include <wtf/CallbackAggregator.h>
 #include <wtf/NeverDestroyed.h>
 #include <wtf/text/StringBuilder.h>
 #include <wtf/text/StringHash.h>
@@ -49,6 +51,15 @@ static HashMap<PAL::SessionID, RefPtr<Engine>>& globalEngineMap()
     return map;
 }
 
+String Engine::cachesRootPath(const String& origin)
+{
+    if (!shouldPersist())
+        return { };
+
+    Key key(origin, { }, { }, { }, salt());
+    return WebCore::pathByAppendingComponent(rootPath(), key.partitionHashAsString());
+}
+
 Engine::~Engine()
 {
     for (auto& caches : m_caches.values())
@@ -69,6 +80,29 @@ void Engine::destroyEngine(PAL::SessionID sessionID)
     globalEngineMap().remove(sessionID);
 }
 
+void Engine::fetchEntries(PAL::SessionID sessionID, bool shouldComputeSize, WTF::Function<void(Vector<WebsiteData::Entry>)>&& completionHandler)
+{
+    // FIXME: Support fetching entries
+    notImplemented();
+    completionHandler({ });
+}
+
+void Engine::clearAllEngines(WTF::Function<void()>&& completionHandler)
+{
+    auto clearTaskHandler = CallbackAggregator::create(WTFMove(completionHandler));
+    for (auto& engine : globalEngineMap().values())
+        engine->clearAllCaches(clearTaskHandler.get());
+}
+
+void Engine::clearEnginesForOrigins(const Vector<String>& origins, WTF::Function<void()>&& completionHandler)
+{
+    auto clearTaskHandler = CallbackAggregator::create(WTFMove(completionHandler));
+    for (auto& engine : globalEngineMap().values()) {
+        for (auto& origin : origins)
+            engine->clearCachesForOrigin(origin, clearTaskHandler.get());
+    }
+}
+
 Engine& Engine::defaultEngine()
 {
     auto sessionID = PAL::SessionID::defaultSessionID();
@@ -190,7 +224,7 @@ void Engine::readCachesFromDisk(const String& origin, CachesCallback&& callback)
 {
     initialize([this, origin, callback = WTFMove(callback)](std::optional<Error>&& error) mutable {
         auto& caches = m_caches.ensure(origin, [&origin, this] {
-            return Caches::create(*this, String { origin }, NetworkProcess::singleton().cacheStoragePerOriginQuota());
+            return Caches::create(*this, String { origin }, cachesRootPath(origin), NetworkProcess::singleton().cacheStoragePerOriginQuota());
         }).iterator->value;
 
         if (caches->isInitialized()) {
@@ -311,6 +345,34 @@ void Engine::removeCaches(const String& origin)
     m_caches.remove(origin);
 }
 
+void Engine::clearAllCaches(CallbackAggregator& taskHandler)
+{
+    for (auto& caches : m_caches.values())
+        caches->clear([taskHandler = makeRef(taskHandler)] { });
+
+    if (!shouldPersist())
+        return;
+
+    m_ioQueue->dispatch([filename = m_rootPath.isolatedCopy(), taskHandler = makeRef(taskHandler)] {
+        deleteDirectoryRecursively(filename);
+    });
+}
+
+void Engine::clearCachesForOrigin(const String& origin, CallbackAggregator& taskHandler)
+{
+    if (auto caches = m_caches.get(origin)) {
+        caches->clear([taskHandler = makeRef(taskHandler)] { });
+        return;
+    }
+
+    if (!shouldPersist())
+        return;
+
+    m_ioQueue->dispatch([filename = cachesRootPath(origin), taskHandler = makeRef(taskHandler)] {
+        deleteDirectoryRecursively(filename);
+    });
+}
+
 void Engine::clearMemoryRepresentation(const String& origin, WebCore::DOMCacheEngine::CompletionCallback&& callback)
 {
     readCachesFromDisk(origin, [callback = WTFMove(callback)](CachesOrError&& result) {
@@ -335,7 +397,6 @@ void Engine::lock(uint64_t cacheIdentifier)
 void Engine::unlock(uint64_t cacheIdentifier)
 {
     auto lockCount = m_cacheLocks.find(cacheIdentifier);
-    ASSERT(lockCount != m_cacheLocks.end());
     if (lockCount == m_cacheLocks.end())
         return;
 
index 996dc01..f19a185 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "CacheStorageEngineCaches.h"
 #include "NetworkCacheData.h"
+#include "WebsiteData.h"
 #include <wtf/HashMap.h>
 #include <wtf/ThreadSafeRefCounted.h>
 #include <wtf/WorkQueue.h>
@@ -39,6 +40,10 @@ namespace WebCore {
 class SessionID;
 }
 
+namespace WTF {
+class CallbackAggregator;
+};
+
 namespace WebKit {
 
 namespace CacheStorage {
@@ -52,6 +57,10 @@ public:
 
     static Engine& from(PAL::SessionID);
     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 Ref<Engine> create(String&& rootPath) { return adoptRef(*new Engine(WTFMove(rootPath))); }
 
     bool shouldPersist() const { return !!m_ioQueue;}
@@ -84,7 +93,11 @@ private:
     static Engine& defaultEngine();
     explicit Engine(String&& rootPath);
 
-    void initialize(Function<void(std::optional<WebCore::DOMCacheEngine::Error>&&)>&&);
+    String cachesRootPath(const String& origin);
+
+    void initialize(WTF::Function<void(std::optional<WebCore::DOMCacheEngine::Error>&&)>&&);
+    void clearAllCaches(WTF::CallbackAggregator&);
+    void clearCachesForOrigin(const String& origin, WTF::CallbackAggregator&);
 
     using CachesOrError = Expected<std::reference_wrapper<Caches>, WebCore::DOMCacheEngine::Error>;
     using CachesCallback = WTF::Function<void(CachesOrError&&)>;
index c7b4fbb..6d21bec 100644 (file)
@@ -27,6 +27,7 @@
 #include "CacheStorageEngine.h"
 
 #include "NetworkCacheCoders.h"
+#include <wtf/RunLoop.h>
 #include <wtf/UUID.h>
 #include <wtf/text/StringBuilder.h>
 
@@ -37,24 +38,15 @@ namespace WebKit {
 
 namespace CacheStorage {
 
-static inline String cachesRootPath(Engine& engine, const String& origin)
-{
-    if (!engine.shouldPersist())
-        return { };
-
-    Key key(origin, { }, { }, { }, engine.salt());
-    return WebCore::pathByAppendingComponent(engine.rootPath(), key.partitionHashAsString());
-}
-
 static inline String cachesListFilename(const String& cachesRootPath)
 {
     return WebCore::pathByAppendingComponent(cachesRootPath, ASCIILiteral("cacheslist"));
 }
 
-Caches::Caches(Engine& engine, String&& origin, uint64_t quota)
+Caches::Caches(Engine& engine, String&& origin, String&& rootPath, uint64_t quota)
     : m_engine(&engine)
     , m_origin(WTFMove(origin))
-    , m_rootPath(cachesRootPath(engine, m_origin))
+    , m_rootPath(WTFMove(rootPath))
     , m_quota(quota)
 {
 }
@@ -128,6 +120,22 @@ void Caches::detach()
     m_rootPath = { };
 }
 
+void Caches::clear(CompletionHandler<void()>&& completionHandler)
+{
+    if (m_engine)
+        m_engine->removeFile(cachesListFilename(m_rootPath));
+    if (m_storage) {
+        m_storage->clear(String { }, std::chrono::system_clock::time_point::min(), [protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)]() mutable {
+            ASSERT(RunLoop::isMain());
+            protectedThis->clearMemoryRepresentation();
+            completionHandler();
+        });
+        return;
+    }
+    clearMemoryRepresentation();
+    completionHandler();
+}
+
 Cache* Caches::find(const String& name)
 {
     auto position = m_caches.findMatching([&](const auto& item) { return item.name() == name; });
index 51296ac..671c319 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "CacheStorageEngineCache.h"
 #include "NetworkCacheStorage.h"
+#include <wtf/CompletionHandler.h>
 
 namespace WebKit {
 
@@ -36,12 +37,11 @@ class Engine;
 
 class Caches : public RefCounted<Caches> {
 public:
-    static Ref<Caches> create(Engine& engine, String&& origin, uint64_t quota) { return adoptRef(*new Caches { engine, WTFMove(origin), quota }); }
+    static Ref<Caches> create(Engine& engine, String&& origin, String&& rootPath, uint64_t quota) { return adoptRef(*new Caches { engine, WTFMove(origin), WTFMove(rootPath), quota }); }
 
     void initialize(WebCore::DOMCacheEngine::CompletionCallback&&);
     void open(const String& name, WebCore::DOMCacheEngine::CacheIdentifierCallback&&);
     void remove(uint64_t identifier, WebCore::DOMCacheEngine::CacheIdentifierCallback&&);
-    void clearMemoryRepresentation();
     void dispose(Cache&);
 
     void detach();
@@ -66,8 +66,11 @@ public:
 
     bool shouldPersist() const { return !m_rootPath.isNull(); }
 
+    void clear(WTF::CompletionHandler<void()>&&);
+    void clearMemoryRepresentation();
+
 private:
-    Caches(Engine&, String&& origin, uint64_t quota);
+    Caches(Engine&, String&& origin, String&& rootPath, uint64_t quota);
 
     void initializeSize(WebCore::DOMCacheEngine::CompletionCallback&&);
     void readCachesFromDisk(WTF::Function<void(Expected<Vector<Cache>, WebCore::DOMCacheEngine::Error>&&)>&&);
index 0958b0a..196da06 100644 (file)
@@ -48,6 +48,7 @@ enum class WebsiteDataType {
 #if ENABLE(SERVICE_WORKER)
     ServiceWorkerRegistrations = 1 << 14,
 #endif
+    DOMCache = 1 << 14,
 };
 
 };
index 0667cbb..ba06e0a 100644 (file)
@@ -31,6 +31,7 @@
 #include "WebResourceLoadStatisticsStore.h"
 #include "WebResourceLoadStatisticsTelemetry.h"
 #include "WebsiteData.h"
+#include "WebsiteDataRecord.h"
 #include "WebsiteDataType.h"
 #include <WebCore/URL.h>
 
@@ -319,6 +320,22 @@ void WKWebsiteDataStoreStatisticsResetToConsistentState(WKWebsiteDataStoreRef da
     store->scheduleClearInMemory();
 }
 
+void WKWebsiteDataStoreRemoveAllFetchCaches(WKWebsiteDataStoreRef dataStoreRef)
+{
+    OptionSet<WebKit::WebsiteDataType> dataTypes = WebKit::WebsiteDataType::DOMCache;
+    WebKit::toImpl(dataStoreRef)->websiteDataStore().removeData(dataTypes, std::chrono::system_clock::time_point::min(), [] { });
+}
+
+void WKWebsiteDataStoreRemoveFetchCacheForOrigin(WKWebsiteDataStoreRef dataStoreRef, WKSecurityOriginRef origin)
+{
+    WebKit::WebsiteDataRecord dataRecord;
+    dataRecord.add(WebKit::WebsiteDataType::DOMCache, WebCore::SecurityOriginData::fromSecurityOrigin(WebKit::toImpl(origin)->securityOrigin()));
+    Vector<WebKit::WebsiteDataRecord> dataRecords = { WTFMove(dataRecord) };
+
+    OptionSet<WebKit::WebsiteDataType> dataTypes = WebKit::WebsiteDataType::DOMCache;
+    WebKit::toImpl(dataStoreRef)->websiteDataStore().removeData(dataTypes, dataRecords, [] { });
+}
+
 void WKWebsiteDataStoreRemoveAllIndexedDatabases(WKWebsiteDataStoreRef dataStoreRef)
 {
     OptionSet<WebKit::WebsiteDataType> dataTypes = WebKit::WebsiteDataType::IndexedDBDatabases;
index 5e26901..faac845 100644 (file)
@@ -70,6 +70,8 @@ WK_EXPORT void WKWebsiteDataStoreStatisticsClearInMemoryAndPersistentStoreModifi
 typedef void (*WKWebsiteDataStoreStatisticsClearThroughWebsiteDataRemovalFunction)(void* functionContext);
 WK_EXPORT void WKWebsiteDataStoreStatisticsClearThroughWebsiteDataRemoval(WKWebsiteDataStoreRef dataStoreRef, void* context, WKWebsiteDataStoreStatisticsClearThroughWebsiteDataRemovalFunction callback);
 WK_EXPORT void WKWebsiteDataStoreStatisticsResetToConsistentState(WKWebsiteDataStoreRef dataStoreRef);
+WK_EXPORT void WKWebsiteDataStoreRemoveFetchCacheForOrigin(WKWebsiteDataStoreRef dataStoreRef, WKSecurityOriginRef origin);
+WK_EXPORT void WKWebsiteDataStoreRemoveAllFetchCaches(WKWebsiteDataStoreRef dataStoreRef);
 WK_EXPORT void WKWebsiteDataStoreRemoveAllIndexedDatabases(WKWebsiteDataStoreRef dataStoreRef);
 WK_EXPORT void WKWebsiteDataStoreRemoveAllServiceWorkerRegistrations(WKWebsiteDataStoreRef dataStoreRef);
 
index aa5f475..7edbb76 100644 (file)
@@ -31,6 +31,9 @@
 
 NS_ASSUME_NONNULL_BEGIN
 
+/*! @constant WKWebsiteDataTypeFetchCache On-disk Fetch caches. */
+WK_EXTERN NSString * const WKWebsiteDataTypeFetchCache WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_MAC_TBA));
+
 /*! @constant WKWebsiteDataTypeDiskCache On-disk caches. */
 WK_EXTERN NSString * const WKWebsiteDataTypeDiskCache WK_API_AVAILABLE(macosx(10.11), ios(9.0));
 
index bcdc4ca..f7a6bfb 100644 (file)
@@ -30,6 +30,7 @@
 
 #import "_WKWebsiteDataSizeInternal.h"
 
+NSString * const WKWebsiteDataTypeFetchCache = @"WKWebsiteDataTypeFetchCache";
 NSString * const WKWebsiteDataTypeDiskCache = @"WKWebsiteDataTypeDiskCache";
 NSString * const WKWebsiteDataTypeMemoryCache = @"WKWebsiteDataTypeMemoryCache";
 NSString * const WKWebsiteDataTypeOfflineWebApplicationCache = @"WKWebsiteDataTypeOfflineWebApplicationCache";
@@ -67,6 +68,8 @@ static NSString *dataTypesToString(NSSet *dataTypes)
 
     if ([dataTypes containsObject:WKWebsiteDataTypeDiskCache])
         [array addObject:@"Disk Cache"];
+    if ([dataTypes containsObject:WKWebsiteDataTypeFetchCache])
+        [array addObject:@"Fetch Cache"];
     if ([dataTypes containsObject:WKWebsiteDataTypeMemoryCache])
         [array addObject:@"Memory Cache"];
     if ([dataTypes containsObject:WKWebsiteDataTypeOfflineWebApplicationCache])
index 5cebf81..7a8042a 100644 (file)
@@ -44,6 +44,8 @@ static inline std::optional<WebsiteDataType> toWebsiteDataType(NSString *website
 {
     if ([websiteDataType isEqualToString:WKWebsiteDataTypeCookies])
         return WebsiteDataType::Cookies;
+    if ([websiteDataType isEqualToString:WKWebsiteDataTypeFetchCache])
+        return WebsiteDataType::DOMCache;
     if ([websiteDataType isEqualToString:WKWebsiteDataTypeDiskCache])
         return WebsiteDataType::DiskCache;
     if ([websiteDataType isEqualToString:WKWebsiteDataTypeMemoryCache])
@@ -99,6 +101,8 @@ static inline RetainPtr<NSSet> toWKWebsiteDataTypes(OptionSet<WebKit::WebsiteDat
         [wkWebsiteDataTypes addObject:WKWebsiteDataTypeCookies];
     if (websiteDataTypes.contains(WebsiteDataType::DiskCache))
         [wkWebsiteDataTypes addObject:WKWebsiteDataTypeDiskCache];
+    if (websiteDataTypes.contains(WebsiteDataType::DOMCache))
+        [wkWebsiteDataTypes addObject:WKWebsiteDataTypeFetchCache];
     if (websiteDataTypes.contains(WebsiteDataType::MemoryCache))
         [wkWebsiteDataTypes addObject:WKWebsiteDataTypeMemoryCache];
     if (websiteDataTypes.contains(WebsiteDataType::OfflineWebApplicationCache))
index 16d2f97..5404894 100644 (file)
@@ -95,7 +95,7 @@ using namespace WebCore;
     static dispatch_once_t onceToken;
     static NSSet *allWebsiteDataTypes;
     dispatch_once(&onceToken, ^{
-        allWebsiteDataTypes = [[NSSet alloc] initWithArray:@[ WKWebsiteDataTypeDiskCache, WKWebsiteDataTypeMemoryCache, WKWebsiteDataTypeOfflineWebApplicationCache, WKWebsiteDataTypeCookies, WKWebsiteDataTypeSessionStorage, WKWebsiteDataTypeLocalStorage, WKWebsiteDataTypeIndexedDBDatabases, WKWebsiteDataTypeServiceWorkerRegistrations, WKWebsiteDataTypeWebSQLDatabases ]];
+        allWebsiteDataTypes = [[NSSet alloc] initWithArray:@[ WKWebsiteDataTypeDiskCache, WKWebsiteDataTypeFetchCache, WKWebsiteDataTypeMemoryCache, WKWebsiteDataTypeOfflineWebApplicationCache, WKWebsiteDataTypeCookies, WKWebsiteDataTypeSessionStorage, WKWebsiteDataTypeLocalStorage, WKWebsiteDataTypeIndexedDBDatabases, WKWebsiteDataTypeServiceWorkerRegistrations, WKWebsiteDataTypeWebSQLDatabases ]];
     });
 
     return allWebsiteDataTypes;
index 5fd41a6..6fbe359 100644 (file)
@@ -161,6 +161,9 @@ static ProcessAccessType computeNetworkProcessAccessTypeForDataFetch(OptionSet<W
     if (dataTypes.contains(WebsiteDataType::DiskCache) && !isNonPersistentStore)
         processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
 
+    if (dataTypes.contains(WebsiteDataType::DOMCache))
+        processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
+
     return processAccessType;
 }
 
@@ -569,6 +572,9 @@ static ProcessAccessType computeNetworkProcessAccessTypeForDataRemoval(OptionSet
     if (dataTypes.contains(WebsiteDataType::Credentials))
         processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
 
+    if (dataTypes.contains(WebsiteDataType::DOMCache))
+        processAccessType = std::max(processAccessType, ProcessAccessType::Launch);
+
     return processAccessType;
 }
 
index b347c46..3a3ef78 100644 (file)
@@ -1,3 +1,22 @@
+2017-10-11  Youenn Fablet  <youenn@apple.com>
+
+        Add API to clean CacheStorage data
+        https://bugs.webkit.org/show_bug.cgi?id=178034
+
+        Reviewed by Chris Dumez.
+
+        Adding internals API to trigger deleting all or origin-persistent cache storage persistent data. 
+
+        * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
+        * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+        (WTR::TestRunner::clearDOMCache):
+        * WebKitTestRunner/InjectedBundle/TestRunner.h:
+        * WebKitTestRunner/TestController.cpp:
+        (WTR::TestController::clearDOMCache):
+        * WebKitTestRunner/TestController.h:
+        * WebKitTestRunner/TestInvocation.cpp:
+        (WTR::TestInvocation::didReceiveMessageFromInjectedBundle):
+
 2017-10-11  Chris Dumez  <cdumez@apple.com>
 
         [Geolocation] Expose Coordinates.floorLevel
index 76efc78..670940b 100644 (file)
@@ -57,6 +57,8 @@ interface TestRunner {
     void dumpDOMAsWebArchive();
     void dumpPolicyDelegateCallbacks();
 
+    void clearDOMCache(DOMString origin);
+
     // Special options.
     void keepWebHistory();
     void setAcceptsEditing(boolean value);
index aab9407..ae5b661 100644 (file)
@@ -1777,4 +1777,11 @@ void TestRunner::callDidRemoveAllSessionCredentialsCallback()
     callTestRunnerCallback(DidRemoveAllSessionCredentialsCallbackID);
 }
 
+void TestRunner::clearDOMCache(JSStringRef origin)
+{
+    WKRetainPtr<WKStringRef> messageName(AdoptWK, WKStringCreateWithUTF8CString("ClearDOMCache"));
+    WKRetainPtr<WKStringRef> messageBody(AdoptWK, WKStringCreateWithJSString(origin));
+    WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), messageName.get(), messageBody.get());
+}
+
 } // namespace WTR
index 6107276..172c309 100644 (file)
@@ -164,6 +164,8 @@ public:
     bool shouldDisallowIncreaseForApplicationCacheQuota() { return m_disallowIncreaseForApplicationCacheQuota; }
     JSValueRef originsWithApplicationCache();
 
+    void clearDOMCache(JSStringRef origin);
+
     // Failed load condition testing
     void forceImmediateCompletion();
 
index a95cd0e..cd8e193 100644 (file)
@@ -2295,6 +2295,21 @@ void TestController::removeAllSessionCredentials()
 
 #endif
 
+void TestController::clearDOMCache(WKStringRef origin)
+{
+#if WK_API_ENABLED
+    auto websiteDataStore = WKContextGetWebsiteDataStore(platformContext());
+
+    if (WKStringIsEmpty(origin)) {
+        WKWebsiteDataStoreRemoveAllFetchCaches(websiteDataStore);
+        return;
+    }
+
+    auto cacheOrigin = adoptWK(WKSecurityOriginCreateFromString(origin));
+    WKWebsiteDataStoreRemoveFetchCacheForOrigin(websiteDataStore, cacheOrigin.get());
+#endif
+}
+
 #if !PLATFORM(COCOA) || !WK_API_ENABLED
 
 void TestController::setStatisticsLastSeen(WKStringRef host, double seconds)
index 85bf2f3..75fb10b 100644 (file)
@@ -187,6 +187,7 @@ public:
     void terminateNetworkProcess();
 
     void removeAllSessionCredentials();
+    void clearDOMCache(WKStringRef origin);
 
 private:
     WKRetainPtr<WKPageConfigurationRef> generatePageConfiguration(WKContextConfigurationRef);
index 8e97913..3ce46d5 100644 (file)
@@ -763,6 +763,14 @@ void TestInvocation::didReceiveMessageFromInjectedBundle(WKStringRef messageName
         return;
     }
 
+    if (WKStringIsEqualToUTF8CString(messageName, "ClearDOMCache")) {
+        ASSERT(WKGetTypeID(messageBody) == WKStringGetTypeID());
+        WKStringRef origin = static_cast<WKStringRef>(messageBody);
+
+        TestController::singleton().clearDOMCache(origin);
+        return;
+    }
+
     ASSERT_NOT_REACHED();
 }