Diff
Modified: trunk/Source/WTF/ChangeLog (286506 => 286507)
--- trunk/Source/WTF/ChangeLog 2021-12-03 19:52:04 UTC (rev 286506)
+++ trunk/Source/WTF/ChangeLog 2021-12-03 20:17:15 UTC (rev 286507)
@@ -1,3 +1,16 @@
+2021-12-03 Sihui Liu <[email protected]>
+
+ Fetch and remove file system data via WKWebsiteDataStore
+ https://bugs.webkit.org/show_bug.cgi?id=233567
+
+ Reviewed by Youenn Fablet.
+
+ * wtf/FileSystem.cpp:
+ (WTF::FileSystemImpl::readEntireFile): Read whole file content into a Vector.
+ (WTF::FileSystemImpl::deleteAllFilesModifiedSince): Recursively delete files and folders modified after
+ specified time in a directory.
+ * wtf/FileSystem.h:
+
2021-12-03 Tim Horton <[email protected]>
Enable Momentum Event Generator by default
Modified: trunk/Source/WTF/wtf/FileSystem.cpp (286506 => 286507)
--- trunk/Source/WTF/wtf/FileSystem.cpp 2021-12-03 19:52:04 UTC (rev 286506)
+++ trunk/Source/WTF/wtf/FileSystem.cpp 2021-12-03 20:17:15 UTC (rev 286507)
@@ -514,6 +514,60 @@
return salt;
}
+std::optional<Vector<uint8_t>> readEntireFile(PlatformFileHandle handle)
+{
+ if (!FileSystem::isHandleValid(handle))
+ return std::nullopt;
+
+ auto size = FileSystem::fileSize(handle).value_or(0);
+ if (!size)
+ return std::nullopt;
+
+ unsigned bytesToRead;
+ if (!WTF::convertSafely(size, bytesToRead))
+ return std::nullopt;
+
+ Vector<uint8_t> buffer(bytesToRead);
+ unsigned totalBytesRead = FileSystem::readFromFile(handle, buffer.data(), buffer.size());
+ if (totalBytesRead != bytesToRead)
+ return std::nullopt;
+
+ return buffer;
+}
+
+void deleteAllFilesModifiedSince(const String& directory, WallTime time)
+{
+ // This function may delete directory folder.
+ if (time == -WallTime::infinity()) {
+ deleteNonEmptyDirectory(directory);
+ return;
+ }
+
+ auto children = listDirectory(directory);
+ for (auto& child : children) {
+ auto childPath = FileSystem::pathByAppendingComponent(directory, child);
+ auto childType = fileType(childPath);
+ if (!childType)
+ continue;
+
+ switch (*childType) {
+ case FileType::Regular: {
+ if (auto modificationTime = FileSystem::fileModificationTime(childPath); modificationTime && *modificationTime >= time)
+ deleteFile(childPath);
+ break;
+ }
+ case FileType::Directory:
+ deleteAllFilesModifiedSince(childPath, time);
+ deleteEmptyDirectory(childPath);
+ break;
+ case FileType::SymbolicLink:
+ break;
+ }
+ }
+
+ FileSystem::deleteEmptyDirectory(directory);
+}
+
#if HAVE(STD_FILESYSTEM) || HAVE(STD_EXPERIMENTAL_FILESYSTEM)
bool deleteEmptyDirectory(const String& path)
Modified: trunk/Source/WTF/wtf/FileSystem.h (286506 => 286507)
--- trunk/Source/WTF/wtf/FileSystem.h 2021-12-03 19:52:04 UTC (rev 286506)
+++ trunk/Source/WTF/wtf/FileSystem.h 2021-12-03 20:17:15 UTC (rev 286507)
@@ -108,6 +108,7 @@
WTF_EXPORT_PRIVATE bool fileExists(const String&);
WTF_EXPORT_PRIVATE bool deleteFile(const String&);
+WTF_EXPORT_PRIVATE void deleteAllFilesModifiedSince(const String&, WallTime);
WTF_EXPORT_PRIVATE bool deleteEmptyDirectory(const String&);
WTF_EXPORT_PRIVATE bool moveFile(const String& oldPath, const String& newPath);
WTF_EXPORT_PRIVATE std::optional<uint64_t> fileSize(const String&); // Follows symlinks.
@@ -146,6 +147,7 @@
using Salt = std::array<uint8_t, 8>;
WTF_EXPORT_PRIVATE std::optional<Salt> readOrMakeSalt(const String& path);
+WTF_EXPORT_PRIVATE std::optional<Vector<uint8_t>> readEntireFile(PlatformFileHandle);
// Prefix is what the filename should be prefixed with, not the full path.
WTF_EXPORT_PRIVATE String openTemporaryFile(const String& prefix, PlatformFileHandle&, const String& suffix = { });
Modified: trunk/Source/WebCore/ChangeLog (286506 => 286507)
--- trunk/Source/WebCore/ChangeLog 2021-12-03 19:52:04 UTC (rev 286506)
+++ trunk/Source/WebCore/ChangeLog 2021-12-03 20:17:15 UTC (rev 286507)
@@ -1,3 +1,12 @@
+2021-12-03 Sihui Liu <[email protected]>
+
+ Fetch and remove file system data via WKWebsiteDataStore
+ https://bugs.webkit.org/show_bug.cgi?id=233567
+
+ Reviewed by Youenn Fablet.
+
+ * Modules/filesystemaccess/FileSystemStorageConnection.h:
+
2021-12-03 Alan Bujtas <[email protected]>
[LFC][IFC] Set the first/last box flag on the (bidi fragmented) inline box type of display boxes
Modified: trunk/Source/WebCore/Modules/filesystemaccess/FileSystemStorageConnection.h (286506 => 286507)
--- trunk/Source/WebCore/Modules/filesystemaccess/FileSystemStorageConnection.h 2021-12-03 19:52:04 UTC (rev 286506)
+++ trunk/Source/WebCore/Modules/filesystemaccess/FileSystemStorageConnection.h 2021-12-03 20:17:15 UTC (rev 286507)
@@ -27,6 +27,7 @@
#include "FileSystemHandleIdentifier.h"
#include "FileSystemSyncAccessHandleIdentifier.h"
+#include "ProcessQualified.h"
#include "ScriptExecutionContextIdentifier.h"
#include <wtf/CompletionHandler.h>
#include <wtf/FileSystem.h>
Modified: trunk/Source/WebKit/CMakeLists.txt (286506 => 286507)
--- trunk/Source/WebKit/CMakeLists.txt 2021-12-03 19:52:04 UTC (rev 286506)
+++ trunk/Source/WebKit/CMakeLists.txt 2021-12-03 20:17:15 UTC (rev 286507)
@@ -310,6 +310,7 @@
WebProcess/WebCoreSupport/RemoteWebLockRegistry
WebProcess/WebCoreSupport/WebBroadcastChannelRegistry
+ WebProcess/WebCoreSupport/WebFileSystemStorageConnection
WebProcess/WebCoreSupport/WebSpeechRecognitionConnection
WebProcess/WebPage/DrawingArea
Modified: trunk/Source/WebKit/ChangeLog (286506 => 286507)
--- trunk/Source/WebKit/ChangeLog 2021-12-03 19:52:04 UTC (rev 286506)
+++ trunk/Source/WebKit/ChangeLog 2021-12-03 20:17:15 UTC (rev 286507)
@@ -1,3 +1,88 @@
+2021-12-03 Sihui Liu <[email protected]>
+
+ Fetch and remove file system data via WKWebsiteDataStore
+ https://bugs.webkit.org/show_bug.cgi?id=233567
+
+ Reviewed by Youenn Fablet.
+
+ Introduce a new WebsiteDataType value FileSystem for FileSystemAccess data. Network process now can fetch and
+ delete this type of data when fetching and deleteing website data (if FileSystem type is included in target
+ types).
+
+ To track origins that have FileSystem data, this patch introduces a new file named origin in the origin's
+ directory. This file will be created when OriginStorageManager is created.
+
+ To delete existing FileSystem data, network process finds origins that are requested to be deleted and have data
+ on disk, closes active access handles, and deletes the files. The origin file mentioned above will be deleted if
+ there is no other file left in the same directory, and empty directories will be deleted.
+
+ New API tests: FileSystemAccess.FetchAndRemoveData
+ FileSystemAccess.RemoveDataByModificationTime
+ FileSystemAccess.FetchDataForThirdParty
+
+ * CMakeLists.txt:
+ * DerivedSources-input.xcfilelist:
+ * DerivedSources-output.xcfilelist:
+ * DerivedSources.make:
+ * NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp:
+ (WebKit::WebResourceLoadStatisticsStore::monitoredDataTypes):
+ * NetworkProcess/NetworkProcess.cpp:
+ (WebKit::NetworkProcess::fetchWebsiteData):
+ (WebKit::NetworkProcess::deleteWebsiteData):
+ (WebKit::NetworkProcess::deleteWebsiteDataForOrigins):
+ (WebKit::NetworkProcess::deleteAndRestrictWebsiteDataForRegistrableDomains):
+ (WebKit::NetworkProcess::registrableDomainsWithWebsiteData):
+ * NetworkProcess/storage/FileSystemStorageHandle.h:
+ (WebKit::FileSystemStorageHandle::activeSyncAccessHandle const):
+ * NetworkProcess/storage/FileSystemStorageManager.cpp:
+ (WebKit::FileSystemStorageManager::~FileSystemStorageManager):
+ (WebKit::FileSystemStorageManager::close):
+ * NetworkProcess/storage/FileSystemStorageManager.h:
+ * NetworkProcess/storage/NetworkStorageManager.cpp:
+ (WebKit::readOriginFromFile):
+ (WebKit::writeOriginToFileIfNecessary):
+ (WebKit::deleteOriginFileIfNecessary):
+ (WebKit::originDirectoryPath):
+ (WebKit::originFilePath):
+ (WebKit::NetworkStorageManager::localOriginStorageManager):
+ (WebKit::NetworkStorageManager::removeOriginStorageManagerIfPossible):
+ (WebKit::toWebsiteDataType):
+ (WebKit::NetworkStorageManager::forEachOriginDirectory):
+ (WebKit::NetworkStorageManager::fetchDataFromDisk):
+ (WebKit::NetworkStorageManager::fetchData):
+ (WebKit::NetworkStorageManager::deleteDataOnDisk):
+ (WebKit::NetworkStorageManager::deleteData):
+ (WebKit::NetworkStorageManager::deleteDataModifiedSince):
+ (WebKit::NetworkStorageManager::deleteDataForRegistrableDomains):
+ (WebKit::originPath): Deleted.
+ * NetworkProcess/storage/NetworkStorageManager.h:
+ * NetworkProcess/storage/OriginStorageManager.cpp:
+ (WebKit::OriginStorageManager::StorageBucket::toStorageIdentifier):
+ (WebKit::OriginStorageManager::StorageBucket::typeStoragePath const):
+ (WebKit::OriginStorageManager::StorageBucket::fileSystemStorageManager):
+ (WebKit::OriginStorageManager::StorageBucket::isActive):
+ (WebKit::OriginStorageManager::StorageBucket::deleteData):
+ (WebKit::OriginStorageManager::StorageBucket::deleteFileSystemStorageData):
+ (WebKit::OriginStorageManager::OriginStorageManager):
+ (WebKit::OriginStorageManager::isActive):
+ (WebKit::OriginStorageManager::deleteData):
+ * NetworkProcess/storage/OriginStorageManager.h:
+ * Shared/WebsiteData/WebsiteData.cpp:
+ (WebKit::WebsiteData::ownerProcess):
+ * Shared/WebsiteData/WebsiteDataType.h:
+ * UIProcess/API/Cocoa/WKWebsiteDataRecord.mm:
+ (dataTypesToString):
+ * UIProcess/API/Cocoa/WKWebsiteDataRecordInternal.h:
+ (WebKit::toWebsiteDataType):
+ (WebKit::toWKWebsiteDataTypes):
+ * UIProcess/API/Cocoa/WKWebsiteDataRecordPrivate.h:
+ * UIProcess/API/Cocoa/WKWebsiteDataStore.mm:
+ (+[WKWebsiteDataStore _allWebsiteDataTypesIncludingPrivate]):
+ * WebKit.xcodeproj/project.pbxproj:
+ * WebProcess/Network/NetworkProcessConnection.cpp:
+ (WebKit::NetworkProcessConnection::didReceiveMessage):
+ * WebProcess/WebCoreSupport/WebFileSystemStorageConnection.messages.in: Added.
+
2021-12-03 Chris Dumez <[email protected]>
Follow-up to r286479 to add API test and address issues found by the test
Modified: trunk/Source/WebKit/DerivedSources-input.xcfilelist (286506 => 286507)
--- trunk/Source/WebKit/DerivedSources-input.xcfilelist 2021-12-03 19:52:04 UTC (rev 286506)
+++ trunk/Source/WebKit/DerivedSources-input.xcfilelist 2021-12-03 20:17:15 UTC (rev 286507)
@@ -221,6 +221,7 @@
$(PROJECT_DIR)/WebProcess/WebCoreSupport/RemoteWebLockRegistry.messages.in
$(PROJECT_DIR)/WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.messages.in
$(PROJECT_DIR)/WebProcess/WebCoreSupport/WebDeviceOrientationUpdateProvider.messages.in
+$(PROJECT_DIR)/WebProcess/WebCoreSupport/WebFileSystemStorageConnection.messages.in
$(PROJECT_DIR)/WebProcess/WebCoreSupport/WebSpeechRecognitionConnection.messages.in
$(PROJECT_DIR)/WebProcess/WebPage/Cocoa/TextCheckingControllerProxy.messages.in
$(PROJECT_DIR)/WebProcess/WebPage/DrawingArea.messages.in
Modified: trunk/Source/WebKit/DerivedSources-output.xcfilelist (286506 => 286507)
--- trunk/Source/WebKit/DerivedSources-output.xcfilelist 2021-12-03 19:52:04 UTC (rev 286506)
+++ trunk/Source/WebKit/DerivedSources-output.xcfilelist 2021-12-03 20:17:15 UTC (rev 286507)
@@ -493,6 +493,9 @@
$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/WebDeviceOrientationUpdateProviderProxyMessageReceiver.cpp
$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/WebDeviceOrientationUpdateProviderProxyMessages.h
$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/WebDeviceOrientationUpdateProviderProxyMessagesReplies.h
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/WebFileSystemStorageConnectionMessageReceiver.cpp
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/WebFileSystemStorageConnectionMessages.h
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/WebFileSystemStorageConnectionMessagesReplies.h
$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/WebFullScreenManagerMessageReceiver.cpp
$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/WebFullScreenManagerMessages.h
$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit2/WebFullScreenManagerMessagesReplies.h
Modified: trunk/Source/WebKit/DerivedSources.make (286506 => 286507)
--- trunk/Source/WebKit/DerivedSources.make 2021-12-03 19:52:04 UTC (rev 286506)
+++ trunk/Source/WebKit/DerivedSources.make 2021-12-03 20:17:15 UTC (rev 286507)
@@ -222,6 +222,7 @@
WebProcess/WebCoreSupport/RemoteWebLockRegistry \
WebProcess/WebCoreSupport/WebBroadcastChannelRegistry \
WebProcess/WebCoreSupport/WebDeviceOrientationUpdateProvider \
+ WebProcess/WebCoreSupport/WebFileSystemStorageConnection \
WebProcess/WebCoreSupport/WebSpeechRecognitionConnection \
WebProcess/Speech/SpeechRecognitionRealtimeMediaSourceManager \
WebProcess/Storage/WebSWContextManagerConnection \
Modified: trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp (286506 => 286507)
--- trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp 2021-12-03 19:52:04 UTC (rev 286506)
+++ trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp 2021-12-03 20:17:15 UTC (rev 286507)
@@ -74,6 +74,7 @@
#if ENABLE(SERVICE_WORKER)
WebsiteDataType::ServiceWorkerRegistrations,
#endif
+ WebsiteDataType::FileSystem,
}));
ASSERT(RunLoop::isMain());
Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp (286506 => 286507)
--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp 2021-12-03 19:52:04 UTC (rev 286506)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp 2021-12-03 20:17:15 UTC (rev 286507)
@@ -1555,6 +1555,12 @@
}
}
#endif
+
+ if (auto iterator = m_storageManagers.find(sessionID); iterator != m_storageManagers.end()) {
+ iterator->value->fetchData(websiteDataTypes, [callbackAggregator](auto entries) mutable {
+ callbackAggregator->m_websiteData.entries.appendVector(WTFMove(entries));
+ });
+ }
}
void NetworkProcess::deleteWebsiteData(PAL::SessionID sessionID, OptionSet<WebsiteDataType> websiteDataTypes, WallTime modifiedSince, CompletionHandler<void()>&& completionHandler)
@@ -1629,6 +1635,9 @@
networkSession->clearAlternativeServices(modifiedSince);
}
#endif
+
+ if (auto iterator = m_storageManagers.find(sessionID); iterator != m_storageManagers.end())
+ iterator->value->deleteDataModifiedSince(websiteDataTypes, modifiedSince, [clearTasksHandler] { });
}
static void clearDiskCacheEntries(NetworkCache::Cache* cache, const Vector<SecurityOriginData>& origins, CompletionHandler<void()>&& completionHandler)
@@ -1736,6 +1745,9 @@
}
#endif
+ if (auto iterator = m_storageManagers.find(sessionID); iterator != m_storageManagers.end())
+ iterator->value->deleteData(websiteDataTypes, originDatas, [clearTasksHandler] { });
+
if (auto* networkSession = this->networkSession(sessionID)) {
HashSet<WebCore::RegistrableDomain> domainsToDeleteNetworkDataFor;
for (auto& originData : originDatas)
@@ -1959,6 +1971,13 @@
});
}
+ if (auto iterator = m_storageManagers.find(sessionID); iterator != m_storageManagers.end()) {
+ iterator->value->deleteDataForRegistrableDomains(websiteDataTypes, domainsToDeleteAllNonCookieWebsiteDataFor, [callbackAggregator](auto deletedDomains) mutable {
+ for (auto domain : deletedDomains)
+ callbackAggregator->m_domains.add(WTFMove(domain));
+ });
+ }
+
auto dataTypesForUIProcess = WebsiteData::filter(websiteDataTypes, WebsiteDataProcessType::UI);
if (!dataTypesForUIProcess.isEmpty() && !domainsToDeleteAllNonCookieWebsiteDataFor.isEmpty()) {
CompletionHandler<void(const HashSet<RegistrableDomain>&)> completionHandler = [callbackAggregator] (const HashSet<RegistrableDomain>& domains) {
@@ -2075,6 +2094,12 @@
});
});
}
+
+ if (auto iterator = m_storageManagers.find(sessionID); iterator != m_storageManagers.end()) {
+ iterator->value->fetchData(websiteDataTypes, [callbackAggregator](auto entries) mutable {
+ callbackAggregator->m_websiteData.entries.appendVector(WTFMove(entries));
+ });
+ }
}
#endif // ENABLE(INTELLIGENT_TRACKING_PREVENTION)
Modified: trunk/Source/WebKit/NetworkProcess/storage/FileSystemStorageHandle.h (286506 => 286507)
--- trunk/Source/WebKit/NetworkProcess/storage/FileSystemStorageHandle.h 2021-12-03 19:52:04 UTC (rev 286506)
+++ trunk/Source/WebKit/NetworkProcess/storage/FileSystemStorageHandle.h 2021-12-03 20:17:15 UTC (rev 286507)
@@ -62,6 +62,7 @@
using AccessHandleInfo = std::pair<WebCore::FileSystemSyncAccessHandleIdentifier, IPC::SharedFileHandle>;
Expected<AccessHandleInfo, FileSystemStorageError> createSyncAccessHandle();
std::optional<FileSystemStorageError> close(WebCore::FileSystemSyncAccessHandleIdentifier);
+ std::optional<WebCore::FileSystemSyncAccessHandleIdentifier> activeSyncAccessHandle() const { return m_activeSyncAccessHandle; }
private:
Expected<WebCore::FileSystemHandleIdentifier, FileSystemStorageError> requestCreateHandle(IPC::Connection::UniqueID, Type, String&& name, bool createIfNecessary);
Modified: trunk/Source/WebKit/NetworkProcess/storage/FileSystemStorageManager.cpp (286506 => 286507)
--- trunk/Source/WebKit/NetworkProcess/storage/FileSystemStorageManager.cpp 2021-12-03 19:52:04 UTC (rev 286506)
+++ trunk/Source/WebKit/NetworkProcess/storage/FileSystemStorageManager.cpp 2021-12-03 20:17:15 UTC (rev 286507)
@@ -28,6 +28,7 @@
#include "FileSystemStorageError.h"
#include "FileSystemStorageHandleRegistry.h"
+#include "WebFileSystemStorageConnectionMessages.h"
namespace WebKit {
@@ -42,8 +43,7 @@
{
ASSERT(!RunLoop::isMain());
- for (auto identifier : m_handles.keys())
- m_registry.unregisterHandle(identifier);
+ close();
}
Expected<WebCore::FileSystemHandleIdentifier, FileSystemStorageError> FileSystemStorageManager::createHandle(IPC::Connection::UniqueID connection, FileSystemStorageHandle::Type type, String&& path, String&& name, bool createIfNecessary)
@@ -149,4 +149,24 @@
return false;
}
+void FileSystemStorageManager::close()
+{
+ ASSERT(!RunLoop::isMain());
+
+ for (auto& [connectionID, identifiers] : m_handlesByConnection) {
+ for (auto identifier : identifiers) {
+ auto takenHandle = m_handles.take(identifier);
+ m_registry.unregisterHandle(identifier);
+
+ // Send message to web process to invalidate active sync access handle.
+ if (auto accessHandleIdentifier = takenHandle->activeSyncAccessHandle())
+ IPC::Connection::send(connectionID, Messages::WebFileSystemStorageConnection::InvalidateAccessHandle(*accessHandleIdentifier), 0);
+ }
+ }
+
+ ASSERT(m_handles.isEmpty());
+ m_handlesByConnection.clear();
+ m_lockMap.clear();
+}
+
} // namespace WebKit
Modified: trunk/Source/WebKit/NetworkProcess/storage/FileSystemStorageManager.h (286506 => 286507)
--- trunk/Source/WebKit/NetworkProcess/storage/FileSystemStorageManager.h 2021-12-03 19:52:04 UTC (rev 286506)
+++ trunk/Source/WebKit/NetworkProcess/storage/FileSystemStorageManager.h 2021-12-03 20:17:15 UTC (rev 286507)
@@ -49,6 +49,8 @@
bool releaseLockForFile(const String& path, WebCore::FileSystemHandleIdentifier);
private:
+ void close();
+
String m_path;
FileSystemStorageHandleRegistry& m_registry;
HashMap<IPC::Connection::UniqueID, HashSet<WebCore::FileSystemHandleIdentifier>> m_handlesByConnection;
Modified: trunk/Source/WebKit/NetworkProcess/storage/NetworkStorageManager.cpp (286506 => 286507)
--- trunk/Source/WebKit/NetworkProcess/storage/NetworkStorageManager.cpp 2021-12-03 19:52:04 UTC (rev 286506)
+++ trunk/Source/WebKit/NetworkProcess/storage/NetworkStorageManager.cpp 2021-12-03 20:17:15 UTC (rev 286507)
@@ -30,11 +30,69 @@
#include "FileSystemStorageManager.h"
#include "NetworkStorageManagerMessages.h"
#include "OriginStorageManager.h"
+#include "WebsiteDataType.h"
#include <pal/crypto/CryptoDigest.h>
+#include <wtf/Scope.h>
+#include <wtf/persistence/PersistentDecoder.h>
+#include <wtf/persistence/PersistentEncoder.h>
#include <wtf/text/Base64.h>
namespace WebKit {
+static std::optional<WebCore::ClientOrigin> readOriginFromFile(const String& filePath)
+{
+ ASSERT(!RunLoop::isMain());
+
+ if (!FileSystem::fileExists(filePath))
+ return std::nullopt;
+
+ auto originFileHandle = FileSystem::openFile(filePath, FileSystem::FileOpenMode::Read);
+ auto closeFile = makeScopeExit([&] {
+ FileSystem::closeFile(originFileHandle);
+ });
+
+ if (!FileSystem::isHandleValid(originFileHandle))
+ return std::nullopt;
+
+ auto originContent = FileSystem::readEntireFile(originFileHandle);
+ if (!originContent)
+ return std::nullopt;
+
+ WTF::Persistence::Decoder decoder({ originContent->data(), originContent->size() });
+ std::optional<WebCore::ClientOrigin> origin;
+ decoder >> origin;
+ return origin;
+}
+
+static void writeOriginToFileIfNecessary(const String& filePath, const WebCore::ClientOrigin& origin)
+{
+ if (FileSystem::fileExists(filePath))
+ return;
+
+ FileSystem::makeAllDirectories(FileSystem::parentPath(filePath));
+ auto originFileHandle = FileSystem::openFile(filePath, FileSystem::FileOpenMode::ReadWrite);
+ auto closeFile = makeScopeExit([&] {
+ FileSystem::closeFile(originFileHandle);
+ });
+
+ if (!FileSystem::isHandleValid(originFileHandle)) {
+ LOG_ERROR("writeOriginToFileIfNecessary: Failed to open origin file");
+ return;
+ }
+
+ WTF::Persistence::Encoder encoder;
+ encoder << origin;
+ FileSystem::writeToFile(originFileHandle, encoder.buffer(), encoder.bufferSize());
+}
+
+static void deleteOriginFileIfNecessary(const String& filePath)
+{
+ auto parentPath = FileSystem::parentPath(filePath);
+ auto children = FileSystem::listDirectory(parentPath);
+ if (children.size() == 1)
+ FileSystem::deleteFile(filePath);
+}
+
Ref<NetworkStorageManager> NetworkStorageManager::create(PAL::SessionID sessionID, const String& path)
{
return adoptRef(*new NetworkStorageManager(sessionID, path));
@@ -116,7 +174,7 @@
return base64URLEncodeToString(hash.data(), hash.size());
}
-static String originPath(const String& rootPath, const WebCore::ClientOrigin& origin, FileSystem::Salt salt)
+static String originDirectoryPath(const String& rootPath, const WebCore::ClientOrigin& origin, FileSystem::Salt salt)
{
if (rootPath.isEmpty())
return rootPath;
@@ -126,15 +184,30 @@
return FileSystem::pathByAppendingComponents(rootPath, { encodedTopOrigin, encodedOpeningOrigin });
}
+static String originFilePath(const String& directory)
+{
+ return FileSystem::pathByAppendingComponent(directory, "origin"_s);
+}
+
OriginStorageManager& NetworkStorageManager::localOriginStorageManager(const WebCore::ClientOrigin& origin)
{
ASSERT(!RunLoop::isMain());
return *m_localOriginStorageManagers.ensure(origin, [&] {
- return makeUnique<OriginStorageManager>(originPath(m_path, origin, m_salt));
+ auto originDirectory = originDirectoryPath(m_path, origin, m_salt);
+ writeOriginToFileIfNecessary(originFilePath(originDirectory), origin);
+ return makeUnique<OriginStorageManager>(WTFMove(originDirectory));
}).iterator->value;
}
+void NetworkStorageManager::removeOriginStorageManagerIfPossible(const WebCore::ClientOrigin& origin)
+{
+ if (auto iterator = m_localOriginStorageManagers.find(origin); iterator != m_localOriginStorageManagers.end()) {
+ if (!iterator->value->isActive())
+ m_localOriginStorageManagers.remove(iterator);
+ }
+}
+
void NetworkStorageManager::persisted(const WebCore::ClientOrigin& origin, CompletionHandler<void(bool)>&& completionHandler)
{
ASSERT(!RunLoop::isMain());
@@ -305,5 +378,162 @@
completionHandler(handle->getHandle(connection.uniqueID(), WTFMove(name)));
}
+static std::optional<WebsiteDataType> toWebsiteDataType(const String& storageType)
+{
+ if (storageType == "FileSystem")
+ return WebsiteDataType::FileSystem;
+
+ return std::nullopt;
+}
+
+void NetworkStorageManager::forEachOriginDirectory(const Function<void(const String&)>& apply)
+{
+ for (auto& topOrigin : FileSystem::listDirectory(m_path)) {
+ auto topOriginDirectory = FileSystem::pathByAppendingComponent(m_path, topOrigin);
+ auto openingOrigins = FileSystem::listDirectory(topOriginDirectory);
+ if (openingOrigins.isEmpty()) {
+ FileSystem::deleteEmptyDirectory(topOriginDirectory);
+ continue;
+ }
+
+ for (auto& openingOrigin : openingOrigins) {
+ auto openingOriginDirectory = FileSystem::pathByAppendingComponent(topOriginDirectory, openingOrigin);
+ apply(openingOriginDirectory);
+ }
+ }
+}
+
+Vector<WebsiteData::Entry> NetworkStorageManager::fetchDataFromDisk(OptionSet<WebsiteDataType> targetTypes)
+{
+ ASSERT(!RunLoop::isMain());
+
+ HashMap<WebCore::SecurityOriginData, OptionSet<WebsiteDataType>> originTypes;
+ forEachOriginDirectory([&](auto directory) mutable {
+ auto origin = readOriginFromFile(originFilePath(directory));
+ if (!origin)
+ return;
+
+ for (auto& storageType : FileSystem::listDirectory(directory)) {
+ if (auto type = toWebsiteDataType(storageType); type && targetTypes.contains(*type)) {
+ // Return both top origin and opening origin for this data.
+ originTypes.add(origin->clientOrigin, OptionSet<WebsiteDataType> { }).iterator->value.add(*type);
+ originTypes.add(origin->topOrigin, OptionSet<WebsiteDataType> { }).iterator->value.add(*type);
+ }
+ }
+ });
+
+ Vector<WebsiteData::Entry> entries;
+ for (auto [origin, types] : originTypes) {
+ for (auto type : types)
+ entries.append({ WebsiteData::Entry { origin, type, 0 } });
+ }
+
+ return entries;
+}
+
+void NetworkStorageManager::fetchData(OptionSet<WebsiteDataType> types, CompletionHandler<void(Vector<WebsiteData::Entry>&&)>&& completionHandler)
+{
+ ASSERT(RunLoop::isMain());
+ ASSERT(!m_closed);
+
+ m_queue->dispatch([this, protectedThis = Ref { *this }, types, completionHandler = WTFMove(completionHandler)]() mutable {
+ auto entries = fetchDataFromDisk(types);
+ RunLoop::main().dispatch([protectedThis = WTFMove(protectedThis), completionHandler = WTFMove(completionHandler), entries = crossThreadCopy(WTFMove(entries))]() mutable {
+ completionHandler(WTFMove(entries));
+ });
+ });
+}
+
+Vector<WebCore::ClientOrigin> NetworkStorageManager::deleteDataOnDisk(OptionSet<WebsiteDataType> types, WallTime modifiedSinceTime, const Function<bool(const WebCore::ClientOrigin&)>& filter)
+{
+ ASSERT(!RunLoop::isMain());
+
+ Vector<WebCore::ClientOrigin> deletedOrigins;
+ forEachOriginDirectory([&](auto directory) mutable {
+ auto filePath = originFilePath(directory);
+ auto origin = readOriginFromFile(filePath);
+ if (!origin) {
+ // If origin cannot be retrieved, but we are asked to remove data for all origins, remove it.
+ RELEASE_LOG_ERROR(Storage, "NetworkStorageManager::deleteDataOnDisk failed to read origin from '%s'", filePath.utf8().data());
+ if (filter(WebCore::ClientOrigin { })) {
+ FileSystem::deleteAllFilesModifiedSince(directory, modifiedSinceTime);
+ FileSystem::deleteEmptyDirectory(directory);
+ }
+ return;
+ }
+
+ if (!filter(*origin))
+ return;
+
+ deletedOrigins.append(*origin);
+ localOriginStorageManager(*origin).deleteData(types, modifiedSinceTime);
+ removeOriginStorageManagerIfPossible(*origin);
+ deleteOriginFileIfNecessary(filePath);
+ FileSystem::deleteEmptyDirectory(directory);
+ });
+
+ return deletedOrigins;
+}
+
+void NetworkStorageManager::deleteData(OptionSet<WebsiteDataType> types, const Vector<WebCore::SecurityOriginData>& origins, CompletionHandler<void()>&& completionHandler)
+{
+ ASSERT(RunLoop::isMain());
+ ASSERT(!m_closed);
+
+ m_queue->dispatch([this, protectedThis = Ref { *this }, types, origins = crossThreadCopy(origins), completionHandler = WTFMove(completionHandler)]() mutable {
+ HashSet<WebCore::SecurityOriginData> originSet;
+ originSet.reserveInitialCapacity(origins.size());
+ for (auto origin : origins)
+ originSet.add(WTFMove(origin));
+
+ deleteDataOnDisk(types, -WallTime::infinity(), [&originSet](auto origin) {
+ return originSet.contains(origin.topOrigin) || originSet.contains(origin.clientOrigin);
+ });
+
+ RunLoop::main().dispatch([protectedThis = WTFMove(protectedThis), completionHandler = WTFMove(completionHandler)]() mutable {
+ completionHandler();
+ });
+ });
+}
+
+void NetworkStorageManager::deleteDataModifiedSince(OptionSet<WebsiteDataType> types, WallTime modifiedSinceTime, CompletionHandler<void()>&& completionHandler)
+{
+ ASSERT(RunLoop::isMain());
+ ASSERT(!m_closed);
+
+ m_queue->dispatch([this, protectedThis = Ref { *this }, types, modifiedSinceTime, completionHandler = WTFMove(completionHandler)]() mutable {
+ deleteDataOnDisk(types, modifiedSinceTime, [](auto&) {
+ return true;
+ });
+
+ RunLoop::main().dispatch([protectedThis = WTFMove(protectedThis), completionHandler = WTFMove(completionHandler)]() mutable {
+ completionHandler();
+ });
+ });
+}
+
+void NetworkStorageManager::deleteDataForRegistrableDomains(OptionSet<WebsiteDataType> types, const Vector<WebCore::RegistrableDomain>& domains, CompletionHandler<void(HashSet<WebCore::RegistrableDomain>&&)>&& completionHandler)
+{
+ ASSERT(RunLoop::isMain());
+ ASSERT(!m_closed);
+
+ m_queue->dispatch([this, protectedThis = Ref { *this }, types, domains = crossThreadCopy(domains), completionHandler = WTFMove(completionHandler)]() mutable {
+ auto deletedOrigins = deleteDataOnDisk(types, -WallTime::infinity(), [&domains](auto& origin) {
+ auto domain = WebCore::RegistrableDomain::uncheckedCreateFromHost(origin.clientOrigin.host);
+ return domains.contains(domain);
+ });
+
+ HashSet<WebCore::RegistrableDomain> deletedDomains;
+ for (auto origin : deletedOrigins) {
+ auto domain = WebCore::RegistrableDomain::uncheckedCreateFromHost(origin.clientOrigin.host);
+ deletedDomains.add(domain);
+ }
+
+ RunLoop::main().dispatch([protectedThis = WTFMove(protectedThis), completionHandler = WTFMove(completionHandler), domains = crossThreadCopy(WTFMove(deletedDomains))]() mutable {
+ completionHandler(WTFMove(domains));
+ });
+ });
+}
+
} // namespace WebKit
Modified: trunk/Source/WebKit/NetworkProcess/storage/NetworkStorageManager.h (286506 => 286507)
--- trunk/Source/WebKit/NetworkProcess/storage/NetworkStorageManager.h 2021-12-03 19:52:04 UTC (rev 286506)
+++ trunk/Source/WebKit/NetworkProcess/storage/NetworkStorageManager.h 2021-12-03 20:17:15 UTC (rev 286507)
@@ -28,10 +28,12 @@
#include "Connection.h"
#include "FileSystemStorageError.h"
#include "OriginStorageManager.h"
+#include "WebsiteData.h"
#include <WebCore/ClientOrigin.h>
#include <WebCore/FileSystemHandleIdentifier.h>
#include <WebCore/FileSystemSyncAccessHandleIdentifier.h>
#include <pal/SessionID.h>
+#include <wtf/Forward.h>
namespace IPC {
class SharedFileHandle;
@@ -55,13 +57,22 @@
PAL::SessionID sessionID() const { return m_sessionID; }
void close();
void clearStorageForTesting(CompletionHandler<void()>&&);
+ void fetchData(OptionSet<WebsiteDataType>, CompletionHandler<void(Vector<WebsiteData::Entry>&&)>&&);
+ void deleteData(OptionSet<WebsiteDataType>, const Vector<WebCore::SecurityOriginData>&, CompletionHandler<void()>&&);
+ void deleteDataModifiedSince(OptionSet<WebsiteDataType>, WallTime, CompletionHandler<void()>&&);
+ void deleteDataForRegistrableDomains(OptionSet<WebsiteDataType>, const Vector<WebCore::RegistrableDomain>&, CompletionHandler<void(HashSet<WebCore::RegistrableDomain>&&)>&&);
private:
NetworkStorageManager(PAL::SessionID, const String& path);
~NetworkStorageManager();
OriginStorageManager& localOriginStorageManager(const WebCore::ClientOrigin&);
+ void removeOriginStorageManagerIfPossible(const WebCore::ClientOrigin&);
FileSystemStorageHandleRegistry& fileSystemStorageHandleRegistry();
+ void forEachOriginDirectory(const Function<void(const String&)>&);
+ Vector<WebsiteData::Entry> fetchDataFromDisk(OptionSet<WebsiteDataType>);
+ Vector<WebCore::ClientOrigin> deleteDataOnDisk(OptionSet<WebsiteDataType>, WallTime, const Function<bool(const WebCore::ClientOrigin&)>&);
+
// IPC::MessageReceiver (implemented by generated code)
void didReceiveMessage(IPC::Connection&, IPC::Decoder&);
Modified: trunk/Source/WebKit/NetworkProcess/storage/OriginStorageManager.cpp (286506 => 286507)
--- trunk/Source/WebKit/NetworkProcess/storage/OriginStorageManager.cpp 2021-12-03 19:52:04 UTC (rev 286506)
+++ trunk/Source/WebKit/NetworkProcess/storage/OriginStorageManager.cpp 2021-12-03 20:17:15 UTC (rev 286507)
@@ -51,20 +51,61 @@
m_fileSystemStorageManager->connectionClosed(connection);
}
- String typeStoragePath(const String& storageIdentifier) const
+ enum class StorageType : uint8_t {
+ FileSystem,
+ };
+
+ static String toStorageIdentifier(StorageType type)
{
- return m_rootPath.isEmpty() ? emptyString() : FileSystem::pathByAppendingComponent(m_rootPath, storageIdentifier);
+ switch (type) {
+ case StorageType::FileSystem:
+ return "FileSystem"_s;
+ default:
+ break;
+ }
+ ASSERT_NOT_REACHED();
+ return ""_s;
}
+ String typeStoragePath(StorageType type) const
+ {
+ auto storageIdentifier = toStorageIdentifier(type);
+ if (m_rootPath.isEmpty() || storageIdentifier.isEmpty())
+ return emptyString();
+
+ return FileSystem::pathByAppendingComponent(m_rootPath, storageIdentifier);
+ }
+
FileSystemStorageManager& fileSystemStorageManager(FileSystemStorageHandleRegistry& registry)
{
if (!m_fileSystemStorageManager)
- m_fileSystemStorageManager = makeUnique<FileSystemStorageManager>(typeStoragePath("FileSystem"), registry);
+ m_fileSystemStorageManager = makeUnique<FileSystemStorageManager>(typeStoragePath(StorageType::FileSystem), registry);
return *m_fileSystemStorageManager;
}
+ bool isActive()
+ {
+ return !!m_fileSystemStorageManager;
+ }
+
+ void deleteData(OptionSet<WebsiteDataType> types, WallTime modifiedSinceTime)
+ {
+ if (types.contains(WebsiteDataType::FileSystem))
+ deleteFileSystemStorageData(modifiedSinceTime);
+
+ FileSystem::deleteNonEmptyDirectory(m_rootPath);
+ }
+
private:
+ void deleteFileSystemStorageData(WallTime modifiedSinceTime)
+ {
+ m_fileSystemStorageManager = nullptr;
+
+ auto fileSystemStoragePath = typeStoragePath(StorageType::FileSystem);
+ FileSystem::deleteAllFilesModifiedSince(fileSystemStoragePath, modifiedSinceTime);
+ }
+
String m_rootPath;
String m_identifier;
StorageBucketMode m_mode { StorageBucketMode::BestEffort };
@@ -74,6 +115,7 @@
OriginStorageManager::OriginStorageManager(String&& path)
: m_path(WTFMove(path))
{
+ ASSERT(!RunLoop::isMain());
}
OriginStorageManager::~OriginStorageManager() = default;
@@ -103,5 +145,16 @@
return defaultBucket().fileSystemStorageManager(registry);
}
+bool OriginStorageManager::isActive()
+{
+ return defaultBucket().isActive();
+}
+
+void OriginStorageManager::deleteData(OptionSet<WebsiteDataType> types, WallTime modifiedSince)
+{
+ ASSERT(!RunLoop::isMain());
+ defaultBucket().deleteData(types, modifiedSince);
+}
+
} // namespace WebKit
Modified: trunk/Source/WebKit/NetworkProcess/storage/OriginStorageManager.h (286506 => 286507)
--- trunk/Source/WebKit/NetworkProcess/storage/OriginStorageManager.h 2021-12-03 19:52:04 UTC (rev 286506)
+++ trunk/Source/WebKit/NetworkProcess/storage/OriginStorageManager.h 2021-12-03 20:17:15 UTC (rev 286507)
@@ -28,10 +28,15 @@
#include "Connection.h"
#include <wtf/text/WTFString.h>
+namespace WebCore {
+struct ClientOrigin;
+}
+
namespace WebKit {
class FileSystemStorageHandleRegistry;
class FileSystemStorageManager;
+enum class WebsiteDataType : uint32_t;
class OriginStorageManager {
WTF_MAKE_FAST_ALLOCATED;
@@ -43,6 +48,8 @@
bool persisted() const { return m_persisted; }
void persist();
FileSystemStorageManager& fileSystemStorageManager(FileSystemStorageHandleRegistry&);
+ bool isActive();
+ void deleteData(OptionSet<WebsiteDataType>, WallTime);
private:
enum class StorageBucketMode : bool;
@@ -49,6 +56,9 @@
class StorageBucket;
StorageBucket& defaultBucket();
+ void createOriginFileIfNecessary(const WebCore::ClientOrigin&);
+ void deleteOriginFileIfNecessary();
+
std::unique_ptr<StorageBucket> m_defaultBucket;
String m_path;
bool m_persisted { false };
Modified: trunk/Source/WebKit/Shared/WebsiteData/WebsiteData.cpp (286506 => 286507)
--- trunk/Source/WebKit/Shared/WebsiteData/WebsiteData.cpp 2021-12-03 19:52:04 UTC (rev 286506)
+++ trunk/Source/WebKit/Shared/WebsiteData/WebsiteData.cpp 2021-12-03 20:17:15 UTC (rev 286507)
@@ -129,6 +129,8 @@
case WebsiteDataType::AlternativeServices:
return WebsiteDataProcessType::Network;
#endif
+ case WebsiteDataType::FileSystem:
+ return WebsiteDataProcessType::Network;
}
RELEASE_ASSERT_NOT_REACHED();
Modified: trunk/Source/WebKit/Shared/WebsiteData/WebsiteDataType.h (286506 => 286507)
--- trunk/Source/WebKit/Shared/WebsiteData/WebsiteDataType.h 2021-12-03 19:52:04 UTC (rev 286506)
+++ trunk/Source/WebKit/Shared/WebsiteData/WebsiteDataType.h 2021-12-03 20:17:15 UTC (rev 286507)
@@ -52,6 +52,7 @@
#if HAVE(CFNETWORK_ALTERNATIVE_SERVICE)
AlternativeServices = 1 << 18,
#endif
+ FileSystem = 1 << 19,
};
} // namespace WebKit
@@ -79,10 +80,11 @@
#endif
WebKit::WebsiteDataType::DOMCache,
WebKit::WebsiteDataType::DeviceIdHashSalt,
- WebKit::WebsiteDataType::PrivateClickMeasurements
+ WebKit::WebsiteDataType::PrivateClickMeasurements,
#if HAVE(CFNETWORK_ALTERNATIVE_SERVICE)
- , WebKit::WebsiteDataType::AlternativeServices
+ WebKit::WebsiteDataType::AlternativeServices,
#endif
+ WebKit::WebsiteDataType::FileSystem
>;
};
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataRecord.mm (286506 => 286507)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataRecord.mm 2021-12-03 19:52:04 UTC (rev 286506)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataRecord.mm 2021-12-03 20:17:15 UTC (rev 286507)
@@ -51,6 +51,7 @@
NSString * const _WKWebsiteDataTypeAdClickAttributions = @"_WKWebsiteDataTypeAdClickAttributions";
NSString * const _WKWebsiteDataTypePrivateClickMeasurements = @"_WKWebsiteDataTypePrivateClickMeasurements";
NSString * const _WKWebsiteDataTypeAlternativeServices = @"_WKWebsiteDataTypeAlternativeServices";
+NSString * const _WKWebsiteDataTypeFileSystem = @"_WKWebsiteDataTypeFileSystem";
#if PLATFORM(MAC)
NSString * const _WKWebsiteDataTypePlugInData = @"_WKWebsiteDataTypePlugInData";
@@ -110,6 +111,8 @@
[array addObject:@"Private Click Measurements"];
if ([dataTypes containsObject:_WKWebsiteDataTypeAlternativeServices])
[array addObject:@"Alternative Services"];
+ if ([dataTypes containsObject:_WKWebsiteDataTypeFileSystem])
+ [array addObject:@"File System"];
return [array componentsJoinedByString:@", "];
}
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataRecordInternal.h (286506 => 286507)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataRecordInternal.h 2021-12-03 19:52:04 UTC (rev 286506)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataRecordInternal.h 2021-12-03 20:17:15 UTC (rev 286507)
@@ -77,6 +77,8 @@
if ([websiteDataType isEqualToString:_WKWebsiteDataTypeAlternativeServices])
return WebsiteDataType::AlternativeServices;
#endif
+ if ([websiteDataType isEqualToString:_WKWebsiteDataTypeFileSystem])
+ return WebsiteDataType::FileSystem;
return std::nullopt;
}
@@ -134,6 +136,8 @@
if (websiteDataTypes.contains(WebsiteDataType::AlternativeServices))
[wkWebsiteDataTypes addObject:_WKWebsiteDataTypeAlternativeServices];
#endif
+ if (websiteDataTypes.contains(WebsiteDataType::FileSystem))
+ [wkWebsiteDataTypes addObject:_WKWebsiteDataTypeFileSystem];
return wkWebsiteDataTypes;
}
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataRecordPrivate.h (286506 => 286507)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataRecordPrivate.h 2021-12-03 19:52:04 UTC (rev 286506)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataRecordPrivate.h 2021-12-03 20:17:15 UTC (rev 286507)
@@ -37,6 +37,7 @@
WK_EXTERN NSString * const _WKWebsiteDataTypeAdClickAttributions WK_API_AVAILABLE(macos(10.15), ios(13.0));
WK_EXTERN NSString * const _WKWebsiteDataTypePrivateClickMeasurements WK_API_AVAILABLE(macos(12.0), ios(15.0));
WK_EXTERN NSString * const _WKWebsiteDataTypeAlternativeServices WK_API_AVAILABLE(macos(11.0), ios(14.0));
+WK_EXTERN NSString * const _WKWebsiteDataTypeFileSystem WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
#if !TARGET_OS_IPHONE
WK_EXTERN NSString * const _WKWebsiteDataTypePlugInData WK_API_AVAILABLE(macos(10.11));
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm (286506 => 286507)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm 2021-12-03 19:52:04 UTC (rev 286506)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm 2021-12-03 20:17:15 UTC (rev 286507)
@@ -248,7 +248,8 @@
_WKWebsiteDataTypeCredentials,
_WKWebsiteDataTypeAdClickAttributions,
_WKWebsiteDataTypePrivateClickMeasurements,
- _WKWebsiteDataTypeAlternativeServices
+ _WKWebsiteDataTypeAlternativeServices,
+ _WKWebsiteDataTypeFileSystem
#if !TARGET_OS_IPHONE
, _WKWebsiteDataTypePlugInData
#endif
Modified: trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj (286506 => 286507)
--- trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj 2021-12-03 19:52:04 UTC (rev 286506)
+++ trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj 2021-12-03 20:17:15 UTC (rev 286507)
@@ -1499,6 +1499,9 @@
93D6B7B5255268D70058DD3A /* SpeechRecognitionPermissionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D6B7B2255268A20058DD3A /* SpeechRecognitionPermissionManager.h */; };
93D6B7B925534A170058DD3A /* WKSpeechRecognitionPermissionCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D6B7B725534A110058DD3A /* WKSpeechRecognitionPermissionCallback.h */; settings = {ATTRIBUTES = (Private, ); }; };
93E6A4EE1BC5DD3900F8A0E7 /* _WKHitTestResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 93E6A4ED1BC5DD3900F8A0E7 /* _WKHitTestResult.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 93E799852756FA550074008A /* WebFileSystemStorageConnectionMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93E799822756FA540074008A /* WebFileSystemStorageConnectionMessageReceiver.cpp */; };
+ 93E799872756FAB40074008A /* WebFileSystemStorageConnectionMessagesReplies.h in Headers */ = {isa = PBXBuildFile; fileRef = 93E799832756FA540074008A /* WebFileSystemStorageConnectionMessagesReplies.h */; };
+ 93E799882756FAC20074008A /* WebFileSystemStorageConnectionMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 93E799812756FA530074008A /* WebFileSystemStorageConnectionMessages.h */; };
93F549B41E3174B7000E7239 /* WKSnapshotConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 93F549B31E3174B7000E7239 /* WKSnapshotConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; };
950F2880252414EA00B74F1C /* WKMouseDeviceObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = 950F287E252414E900B74F1C /* WKMouseDeviceObserver.h */; };
9565083926D87A2B00E15CB7 /* AppleMediaServicesSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 9565083726D87A2B00E15CB7 /* AppleMediaServicesSPI.h */; };
@@ -5301,6 +5304,10 @@
93D6B7B725534A110058DD3A /* WKSpeechRecognitionPermissionCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKSpeechRecognitionPermissionCallback.h; sourceTree = "<group>"; };
93D6B7B825534A120058DD3A /* WKSpeechRecognitionPermissionCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WKSpeechRecognitionPermissionCallback.cpp; sourceTree = "<group>"; };
93E6A4ED1BC5DD3900F8A0E7 /* _WKHitTestResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKHitTestResult.h; sourceTree = "<group>"; };
+ 93E7997E2756F6700074008A /* WebFileSystemStorageConnection.messages.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebFileSystemStorageConnection.messages.in; sourceTree = "<group>"; };
+ 93E799812756FA530074008A /* WebFileSystemStorageConnectionMessages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebFileSystemStorageConnectionMessages.h; sourceTree = "<group>"; };
+ 93E799822756FA540074008A /* WebFileSystemStorageConnectionMessageReceiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebFileSystemStorageConnectionMessageReceiver.cpp; sourceTree = "<group>"; };
+ 93E799832756FA540074008A /* WebFileSystemStorageConnectionMessagesReplies.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebFileSystemStorageConnectionMessagesReplies.h; sourceTree = "<group>"; };
93F549B31E3174B7000E7239 /* WKSnapshotConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKSnapshotConfiguration.h; sourceTree = "<group>"; };
93F549B51E3174DA000E7239 /* WKSnapshotConfiguration.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKSnapshotConfiguration.mm; sourceTree = "<group>"; };
950F287E252414E900B74F1C /* WKMouseDeviceObserver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WKMouseDeviceObserver.h; path = ios/WKMouseDeviceObserver.h; sourceTree = "<group>"; };
@@ -10582,6 +10589,7 @@
BC032D6810F4378D0058C15A /* WebEditorClient.h */,
9354242B2703BDCB005CA72C /* WebFileSystemStorageConnection.cpp */,
9354242A2703BDCB005CA72C /* WebFileSystemStorageConnection.h */,
+ 93E7997E2756F6700074008A /* WebFileSystemStorageConnection.messages.in */,
BC111A58112F4FBB00337BAB /* WebFrameLoaderClient.cpp */,
BC032D6A10F4378D0058C15A /* WebFrameLoaderClient.h */,
BC1BE1DF12D54A410004A228 /* WebGeolocationClient.cpp */,
@@ -12059,6 +12067,9 @@
E3866B072399979D00F88FE9 /* WebDeviceOrientationUpdateProviderMessages.h */,
E3866B042399979C00F88FE9 /* WebDeviceOrientationUpdateProviderProxyMessageReceiver.cpp */,
E3866B052399979C00F88FE9 /* WebDeviceOrientationUpdateProviderProxyMessages.h */,
+ 93E799822756FA540074008A /* WebFileSystemStorageConnectionMessageReceiver.cpp */,
+ 93E799812756FA530074008A /* WebFileSystemStorageConnectionMessages.h */,
+ 93E799832756FA540074008A /* WebFileSystemStorageConnectionMessagesReplies.h */,
CD73BA48131ACD8E00EEDED2 /* WebFullScreenManagerMessageReceiver.cpp */,
CD73BA49131ACD8E00EEDED2 /* WebFullScreenManagerMessages.h */,
CD73BA45131ACC8800EEDED2 /* WebFullScreenManagerProxyMessageReceiver.cpp */,
@@ -13306,6 +13317,8 @@
BC032DBB10F4380F0058C15A /* WebEventConversion.h in Headers */,
BC111B5D112F629800337BAB /* WebEventFactory.h in Headers */,
9354242C2703BDCB005CA72C /* WebFileSystemStorageConnection.h in Headers */,
+ 93E799882756FAC20074008A /* WebFileSystemStorageConnectionMessages.h in Headers */,
+ 93E799872756FAB40074008A /* WebFileSystemStorageConnectionMessagesReplies.h in Headers */,
1A90C1EE1264FD50003E44D4 /* WebFindOptions.h in Headers */,
BCE469541214E6CB000B98EB /* WebFormClient.h in Headers */,
BCE469561214E6CB000B98EB /* WebFormSubmissionListenerProxy.h in Headers */,
@@ -15402,6 +15415,7 @@
E3866AE52397400400F88FE9 /* WebDeviceOrientationUpdateProviderProxy.mm in Sources */,
E3866B092399A2D500F88FE9 /* WebDeviceOrientationUpdateProviderProxyMessageReceiver.cpp in Sources */,
2D92A789212B6AB100F493FD /* WebEvent.cpp in Sources */,
+ 93E799852756FA550074008A /* WebFileSystemStorageConnectionMessageReceiver.cpp in Sources */,
CD73BA4E131ACDB700EEDED2 /* WebFullScreenManagerMessageReceiver.cpp in Sources */,
CD73BA47131ACC9A00EEDED2 /* WebFullScreenManagerProxyMessageReceiver.cpp in Sources */,
BC0E606112D6BA910012A72A /* WebGeolocationManagerMessageReceiver.cpp in Sources */,
Modified: trunk/Source/WebKit/WebProcess/Network/NetworkProcessConnection.cpp (286506 => 286507)
--- trunk/Source/WebKit/WebProcess/Network/NetworkProcessConnection.cpp 2021-12-03 19:52:04 UTC (rev 286506)
+++ trunk/Source/WebKit/WebProcess/Network/NetworkProcessConnection.cpp 2021-12-03 20:17:15 UTC (rev 286507)
@@ -37,6 +37,8 @@
#include "WebCacheStorageProvider.h"
#include "WebCookieJar.h"
#include "WebCoreArgumentCoders.h"
+#include "WebFileSystemStorageConnection.h"
+#include "WebFileSystemStorageConnectionMessages.h"
#include "WebFrame.h"
#include "WebIDBConnectionToServer.h"
#include "WebIDBConnectionToServerMessages.h"
@@ -119,6 +121,10 @@
storageAreaMap->didReceiveMessage(connection, decoder);
return;
}
+ if (decoder.messageReceiverName() == Messages::WebFileSystemStorageConnection::messageReceiverName()) {
+ WebProcess::singleton().fileSystemStorageConnection().didReceiveMessage(connection, decoder);
+ return;
+ }
#if USE(LIBWEBRTC)
if (decoder.messageReceiverName() == Messages::WebRTCMonitor::messageReceiverName()) {
Added: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebFileSystemStorageConnection.messages.in (0 => 286507)
--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebFileSystemStorageConnection.messages.in (rev 0)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebFileSystemStorageConnection.messages.in 2021-12-03 20:17:15 UTC (rev 286507)
@@ -0,0 +1,25 @@
+# Copyright (C) 2021 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.
+
+messages -> WebFileSystemStorageConnection NotRefCounted {
+ InvalidateAccessHandle(WebCore::FileSystemSyncAccessHandleIdentifier identifier)
+}
Modified: trunk/Tools/ChangeLog (286506 => 286507)
--- trunk/Tools/ChangeLog 2021-12-03 19:52:04 UTC (rev 286506)
+++ trunk/Tools/ChangeLog 2021-12-03 20:17:15 UTC (rev 286507)
@@ -1,3 +1,12 @@
+2021-12-03 Sihui Liu <[email protected]>
+
+ Fetch and remove file system data via WKWebsiteDataStore
+ https://bugs.webkit.org/show_bug.cgi?id=233567
+
+ Reviewed by Youenn Fablet.
+
+ * TestWebKitAPI/Tests/WebKitCocoa/FileSystemAccess.mm:
+
2021-12-03 Chris Dumez <[email protected]>
Follow-up to r286479 to add API test and address issues found by the test
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/FileSystemAccess.mm (286506 => 286507)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/FileSystemAccess.mm 2021-12-03 19:52:04 UTC (rev 286506)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/FileSystemAccess.mm 2021-12-03 20:17:15 UTC (rev 286507)
@@ -29,11 +29,13 @@
#import "DeprecatedGlobalValues.h"
#import "PlatformUtilities.h"
+#import "TestUIDelegate.h"
#import "TestURLSchemeHandler.h"
#import "TestWKWebView.h"
#import <WebKit/WKPreferencesPrivate.h>
#import <WebKit/WKWebViewConfigurationPrivate.h>
#import <WebKit/WKWebViewPrivate.h>
+#import <WebKit/WKWebsiteDataRecordPrivate.h>
@interface FileSystemAccessMessageHandler : NSObject <WKScriptMessageHandler>
@end
@@ -48,7 +50,7 @@
@end
-static NSString *mainFrameString = @"<script> \
+static NSString *workerFrameString = @"<script> \
function start() { \
var worker = new Worker('worker.js'); \
worker._onmessage_ = function(event) { \
@@ -115,7 +117,7 @@
[configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"webkit"];
auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]);
- [webView loadHTMLString:mainFrameString baseURL:[NSURL URLWithString:@"webkit://webkit.org"]];
+ [webView loadHTMLString:workerFrameString baseURL:[NSURL URLWithString:@"webkit://webkit.org"]];
TestWebKitAPI::Util::run(&receivedScriptMessage);
receivedScriptMessage = false;
EXPECT_WK_STREQ(@"page is loaded", [lastScriptMessage body]);
@@ -126,7 +128,7 @@
EXPECT_WK_STREQ(@"success: write 10 bytes", [lastScriptMessage body]);
auto secondWebView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]);
- [secondWebView loadHTMLString:mainFrameString baseURL:[NSURL URLWithString:@"webkit://webkit.org"]];
+ [secondWebView loadHTMLString:workerFrameString baseURL:[NSURL URLWithString:@"webkit://webkit.org"]];
TestWebKitAPI::Util::run(&receivedScriptMessage);
receivedScriptMessage = false;
EXPECT_WK_STREQ(@"page is loaded", [lastScriptMessage body]);
@@ -168,7 +170,7 @@
[configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"webkit"];
auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]);
- [webView loadHTMLString:mainFrameString baseURL:[NSURL URLWithString:@"webkit://webkit.org"]];
+ [webView loadHTMLString:workerFrameString baseURL:[NSURL URLWithString:@"webkit://webkit.org"]];
TestWebKitAPI::Util::run(&receivedScriptMessage);
receivedScriptMessage = false;
EXPECT_WK_STREQ(@"page is loaded", [lastScriptMessage body]);
@@ -258,4 +260,196 @@
EXPECT_WK_STREQ(@"file is opened", [lastScriptMessage body]);
}
+static NSString *testString = @"<script> \
+ async function open(shouldCreateFile) \
+ { \
+ try { \
+ var rootHandle = await navigator.storage.getDirectory(); \
+ var fileHandle = await rootHandle.getFileHandle('file-system-access.txt', { 'create' : shouldCreateFile }); \
+ window.webkit.messageHandlers.testHandler.postMessage('file is opened'); \
+ } catch(err) { \
+ window.webkit.messageHandlers.testHandler.postMessage('error: ' + err.name + ' - ' + err.message); \
+ } \
+ } \
+ open(true); \
+ </script>";
+
+TEST(FileSystemAccess, FetchAndRemoveData)
+{
+ auto handler = adoptNS([[FileSystemAccessMessageHandler alloc] init]);
+ auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+ [[configuration userContentController] addScriptMessageHandler:handler.get() name:@"testHandler"];
+ auto websiteDataStore = [configuration websiteDataStore];
+ auto types = [NSSet setWithObject:_WKWebsiteDataTypeFileSystem];
+
+ // Remove existing data.
+ done = false;
+ [websiteDataStore removeDataOfTypes:types modifiedSince:[NSDate distantPast] completionHandler:^ {
+ done = true;
+ }];
+ TestWebKitAPI::Util::run(&done);
+
+ auto preferences = [configuration preferences];
+ preferences._fileSystemAccessEnabled = YES;
+ preferences._storageAPIEnabled = YES;
+ auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]);
+ [webView loadHTMLString:testString baseURL:[NSURL URLWithString:@"https://webkit.org"]];
+ TestWebKitAPI::Util::run(&receivedScriptMessage);
+ receivedScriptMessage = false;
+ EXPECT_WK_STREQ(@"file is opened", [lastScriptMessage body]);
+
+ // Fetch data and remove it by origin.
+ done = false;
+ [websiteDataStore fetchDataRecordsOfTypes:types completionHandler:^(NSArray<WKWebsiteDataRecord *> *records) {
+ EXPECT_EQ(records.count, 1u);
+ auto record = [records objectAtIndex:0];
+ EXPECT_STREQ("webkit.org", [record.displayName UTF8String]);
+
+ // Remove data.
+ [websiteDataStore removeDataOfTypes:types forDataRecords:records completionHandler:^{
+ done = true;
+ }];
+ }];
+ TestWebKitAPI::Util::run(&done);
+
+ // Fetch data after removal.
+ done = false;
+ [websiteDataStore fetchDataRecordsOfTypes:types completionHandler:^(NSArray<WKWebsiteDataRecord *> *records) {
+ EXPECT_EQ(records.count, 0u);
+ done = true;
+ }];
+
+ // File cannot be opened after data removal.
+ [webView evaluateJavaScript:@"open(false)" completionHandler:nil];
+ TestWebKitAPI::Util::run(&receivedScriptMessage);
+ receivedScriptMessage = false;
+ EXPECT_WK_STREQ(@"error: NotFoundError - The object can not be found here.", [lastScriptMessage body]);
+}
+
+TEST(FileSystemAccess, RemoveDataByModificationTime)
+{
+ auto handler = adoptNS([[FileSystemAccessMessageHandler alloc] init]);
+ auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+ [[configuration userContentController] addScriptMessageHandler:handler.get() name:@"testHandler"];
+ auto preferences = [configuration preferences];
+ preferences._fileSystemAccessEnabled = YES;
+ preferences._storageAPIEnabled = YES;
+ auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]);
+ [webView loadHTMLString:testString baseURL:[NSURL URLWithString:@"https://webkit.org"]];
+ TestWebKitAPI::Util::run(&receivedScriptMessage);
+ receivedScriptMessage = false;
+ EXPECT_WK_STREQ(@"file is opened", [lastScriptMessage body]);
+
+ auto websiteDataStore = [configuration websiteDataStore];
+ auto types = [NSSet setWithObject:_WKWebsiteDataTypeFileSystem];
+ done = false;
+ __block NSUInteger recordsCount;
+ [websiteDataStore fetchDataRecordsOfTypes:types completionHandler:^(NSArray<WKWebsiteDataRecord *> *records) {
+ recordsCount = records.count;
+ EXPECT_GT(recordsCount, 0u);
+ done = true;
+ }];
+ TestWebKitAPI::Util::run(&done);
+
+ done = false;
+ [websiteDataStore removeDataOfTypes:types modifiedSince:[NSDate now] completionHandler:^ {
+ [websiteDataStore fetchDataRecordsOfTypes:types completionHandler:^(NSArray<WKWebsiteDataRecord *> *records) {
+ recordsCount = records.count;
+ EXPECT_EQ(records.count, recordsCount);
+ done = true;
+ }];
+ }];
+ TestWebKitAPI::Util::run(&done);
+
+ done = false;
+ [websiteDataStore removeDataOfTypes:types modifiedSince:[NSDate distantPast] completionHandler:^ {
+ [websiteDataStore fetchDataRecordsOfTypes:types completionHandler:^(NSArray<WKWebsiteDataRecord *> *records) {
+ EXPECT_EQ(records.count, 0u);
+ done = true;
+ }];
+ }];
+ TestWebKitAPI::Util::run(&done);
+}
+
+static NSString *mainFrameString = @"<script> \
+ function postResult(event) \
+ { \
+ window.webkit.messageHandlers.testHandler.postMessage(event.data); \
+ } \
+ addEventListener('message', postResult, false); \
+ </script> \
+ <iframe src=''>";
+
+static const char* frameBytes = R"TESTRESOURCE(
+<script>
+function postMessage(message)
+{
+ parent.postMessage(message, '*');
+}
+async function open()
+{
+ try {
+ var rootHandle = await navigator.storage.getDirectory();
+ var fileHandle = await rootHandle.getFileHandle('file-system-access.txt', { 'create' : true });
+ postMessage('file is opened');
+ } catch(err) {
+ postMessage('error: ' + err.name + ' - ' + err.message);
+ }
+}
+open();
+</script>
+)TESTRESOURCE";
+
+TEST(FileSystemAccess, FetchDataForThirdParty)
+{
+ TestWebKitAPI::HTTPServer server({
+ { "/", { frameBytes } },
+ }, TestWebKitAPI::HTTPServer::Protocol::Https, nullptr, nullptr, 9091);
+
+ auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+ auto handler = adoptNS([[FileSystemAccessMessageHandler alloc] init]);
+ [[configuration userContentController] addScriptMessageHandler:handler.get() name:@"testHandler"];
+ auto preferences = [configuration preferences];
+ preferences._fileSystemAccessEnabled = YES;
+ preferences._storageAPIEnabled = YES;
+
+ auto websiteDataStore = [configuration websiteDataStore];
+ auto types = [NSSet setWithObject:_WKWebsiteDataTypeFileSystem];
+ done = false;
+ [websiteDataStore removeDataOfTypes:types modifiedSince:[NSDate distantPast] completionHandler:^ {
+ done = true;
+ }];
+ TestWebKitAPI::Util::run(&done);
+
+ auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]);
+ auto navigationDelegate = adoptNS([TestNavigationDelegate new]);
+ [navigationDelegate setDidReceiveAuthenticationChallenge:^(WKWebView *, NSURLAuthenticationChallenge *challenge, void (^callback)(NSURLSessionAuthChallengeDisposition, NSURLCredential *)) {
+ EXPECT_WK_STREQ(challenge.protectionSpace.authenticationMethod, NSURLAuthenticationMethodServerTrust);
+ callback(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
+ }];
+ [navigationDelegate setDecidePolicyForNavigationAction:[&](WKNavigationAction *action, void (^decisionHandler)(WKNavigationActionPolicy)) {
+ decisionHandler(WKNavigationActionPolicyAllow);
+ }];
+ [webView setNavigationDelegate:navigationDelegate.get()];
+
+ [webView loadHTMLString:mainFrameString baseURL:[NSURL URLWithString:@"https://webkit.org"]];
+ TestWebKitAPI::Util::run(&receivedScriptMessage);
+ receivedScriptMessage = false;
+ EXPECT_WK_STREQ(@"file is opened", [lastScriptMessage body]);
+
+ done = false;
+ [websiteDataStore fetchDataRecordsOfTypes:types completionHandler:^(NSArray<WKWebsiteDataRecord *> *records) {
+ // Should return both opening origin and top origin.
+ EXPECT_EQ(records.count, 2u);
+ auto sortFunction = ^(WKWebsiteDataRecord *record1, WKWebsiteDataRecord *record2){
+ return [record1.displayName compare:record2.displayName];
+ };
+ auto sortedRecords = [records sortedArrayUsingComparator:sortFunction];
+ EXPECT_WK_STREQ(@"127.0.0.1", [sortedRecords objectAtIndex:0].displayName);
+ EXPECT_WK_STREQ(@"webkit.org", [sortedRecords objectAtIndex:1].displayName);
+ done = true;
+ }];
+ TestWebKitAPI::Util::run(&done);
+}
+
#endif // USE(APPLE_INTERNAL_SDK)