⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 286601 in webkit


Ignore:
Timestamp:
Dec 7, 2021, 11:33:16 AM (5 years ago)
Author:
sihui_liu@apple.com
Message:

Fetch and remove file system data via WKWebsiteDataStore
https://bugs.webkit.org/show_bug.cgi?id=233567
<rdar://problem/86029185>

Reviewed by Youenn Fablet.

Source/WebCore:

  • Modules/filesystemaccess/FileSystemStorageConnection.h:

Source/WebKit:

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::NetworkStorageManager::persist):
(WebKit::NetworkStorageManager::clearStorageForTesting): Only reset persisted state here as our test bot can run
tests in parallel. If one worker finishes a test and asks to clear storage, while another worker is running a
filesystem test; the test may fail as data is gone. (The workers are using the same network process.)
(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::fileSystemStorageManager):
(WebKit::OriginStorageManager::isActive):
(WebKit::OriginStorageManager::deleteData):
(WebKit::OriginStorageManager::setPersisted):
(WebKit::OriginStorageManager::persist): Deleted.

  • 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.

Source/WTF:

  • 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:

Tools:

  • TestWebKitAPI/Tests/WebKitCocoa/FileSystemAccess.mm:
Location:
trunk
Files:
1 added
29 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WTF/ChangeLog

    r286569 r286601  
     12021-12-07  Sihui Liu  <sihui_liu@apple.com>
     2
     3        Fetch and remove file system data via WKWebsiteDataStore
     4        https://bugs.webkit.org/show_bug.cgi?id=233567
     5        <rdar://problem/86029185>
     6
     7        Reviewed by Youenn Fablet.
     8
     9        * wtf/FileSystem.cpp:
     10        (WTF::FileSystemImpl::readEntireFile): Read whole file content into a Vector.
     11        (WTF::FileSystemImpl::deleteAllFilesModifiedSince): Recursively delete files and folders modified after
     12        specified time in a directory.
     13        * wtf/FileSystem.h:
     14
    1152021-12-06  Ryan Haddad  <ryanhaddad@apple.com>
    216
  • trunk/Source/WTF/wtf/FileSystem.cpp

    r286569 r286601  
    515515}
    516516
     517std::optional<Vector<uint8_t>> readEntireFile(PlatformFileHandle handle)
     518{
     519    if (!FileSystem::isHandleValid(handle))
     520        return std::nullopt;
     521
     522    auto size = FileSystem::fileSize(handle).value_or(0);
     523    if (!size)
     524        return std::nullopt;
     525
     526    unsigned bytesToRead;
     527    if (!WTF::convertSafely(size, bytesToRead))
     528        return std::nullopt;
     529
     530    Vector<uint8_t> buffer(bytesToRead);
     531    unsigned totalBytesRead = FileSystem::readFromFile(handle, buffer.data(), buffer.size());
     532    if (totalBytesRead != bytesToRead)
     533        return std::nullopt;
     534
     535    return buffer;
     536}
     537
     538void deleteAllFilesModifiedSince(const String& directory, WallTime time)
     539{
     540    // This function may delete directory folder.
     541    if (time == -WallTime::infinity()) {
     542        deleteNonEmptyDirectory(directory);
     543        return;
     544    }
     545
     546    auto children = listDirectory(directory);
     547    for (auto& child : children) {
     548        auto childPath = FileSystem::pathByAppendingComponent(directory, child);
     549        auto childType = fileType(childPath);
     550        if (!childType)
     551            continue;
     552
     553        switch (*childType) {
     554        case FileType::Regular: {
     555            if (auto modificationTime = FileSystem::fileModificationTime(childPath); modificationTime && *modificationTime >= time)
     556                deleteFile(childPath);
     557            break;
     558        }
     559        case FileType::Directory:
     560            deleteAllFilesModifiedSince(childPath, time);
     561            deleteEmptyDirectory(childPath);
     562            break;
     563        case FileType::SymbolicLink:
     564            break;
     565        }
     566    }
     567
     568    FileSystem::deleteEmptyDirectory(directory);
     569}
     570
    517571#if HAVE(STD_FILESYSTEM) || HAVE(STD_EXPERIMENTAL_FILESYSTEM)
    518572
  • trunk/Source/WTF/wtf/FileSystem.h

    r286569 r286601  
    109109WTF_EXPORT_PRIVATE bool fileExists(const String&);
    110110WTF_EXPORT_PRIVATE bool deleteFile(const String&);
     111WTF_EXPORT_PRIVATE void deleteAllFilesModifiedSince(const String&, WallTime);
    111112WTF_EXPORT_PRIVATE bool deleteEmptyDirectory(const String&);
    112113WTF_EXPORT_PRIVATE bool moveFile(const String& oldPath, const String& newPath);
     
    147148using Salt = std::array<uint8_t, 8>;
    148149WTF_EXPORT_PRIVATE std::optional<Salt> readOrMakeSalt(const String& path);
     150WTF_EXPORT_PRIVATE std::optional<Vector<uint8_t>> readEntireFile(PlatformFileHandle);
    149151
    150152// Prefix is what the filename should be prefixed with, not the full path.
  • trunk/Source/WebCore/ChangeLog

    r286599 r286601  
     12021-12-07  Sihui Liu  <sihui_liu@apple.com>
     2
     3        Fetch and remove file system data via WKWebsiteDataStore
     4        https://bugs.webkit.org/show_bug.cgi?id=233567
     5        <rdar://problem/86029185>
     6
     7        Reviewed by Youenn Fablet.
     8
     9        * Modules/filesystemaccess/FileSystemStorageConnection.h:
     10
    1112021-12-07  Antti Koivisto  <antti@apple.com>
    212
  • trunk/Source/WebCore/Modules/filesystemaccess/FileSystemStorageConnection.h

    r286569 r286601  
    2828#include "FileSystemHandleIdentifier.h"
    2929#include "FileSystemSyncAccessHandleIdentifier.h"
     30#include "ProcessQualified.h"
    3031#include "ScriptExecutionContextIdentifier.h"
    3132#include <wtf/CompletionHandler.h>
  • trunk/Source/WebKit/CMakeLists.txt

    r286569 r286601  
    311311    WebProcess/WebCoreSupport/RemoteWebLockRegistry
    312312    WebProcess/WebCoreSupport/WebBroadcastChannelRegistry
     313    WebProcess/WebCoreSupport/WebFileSystemStorageConnection
    313314    WebProcess/WebCoreSupport/WebSpeechRecognitionConnection
    314315
  • trunk/Source/WebKit/ChangeLog

    r286596 r286601  
     12021-12-07  Sihui Liu  <sihui_liu@apple.com>
     2
     3        Fetch and remove file system data via WKWebsiteDataStore
     4        https://bugs.webkit.org/show_bug.cgi?id=233567
     5        <rdar://problem/86029185>
     6
     7        Reviewed by Youenn Fablet.
     8
     9        Introduce a new WebsiteDataType value FileSystem for FileSystemAccess data. Network process now can fetch and
     10        delete this type of data when fetching and deleteing website data (if FileSystem type is included in target
     11        types).
     12
     13        To track origins that have FileSystem data, this patch introduces a new file named origin in the origin's
     14        directory. This file will be created when OriginStorageManager is created.
     15
     16        To delete existing FileSystem data, network process finds origins that are requested to be deleted and have data
     17        on disk, closes active access handles, and deletes the files. The origin file mentioned above will be deleted if
     18        there is no other file left in the same directory, and empty directories will be deleted.
     19
     20        New API tests: FileSystemAccess.FetchAndRemoveData
     21                       FileSystemAccess.RemoveDataByModificationTime
     22                       FileSystemAccess.FetchDataForThirdParty
     23
     24        * CMakeLists.txt:
     25        * DerivedSources-input.xcfilelist:
     26        * DerivedSources-output.xcfilelist:
     27        * DerivedSources.make:
     28        * NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp:
     29        (WebKit::WebResourceLoadStatisticsStore::monitoredDataTypes):
     30        * NetworkProcess/NetworkProcess.cpp:
     31        (WebKit::NetworkProcess::fetchWebsiteData):
     32        (WebKit::NetworkProcess::deleteWebsiteData):
     33        (WebKit::NetworkProcess::deleteWebsiteDataForOrigins):
     34        (WebKit::NetworkProcess::deleteAndRestrictWebsiteDataForRegistrableDomains):
     35        (WebKit::NetworkProcess::registrableDomainsWithWebsiteData):
     36        * NetworkProcess/storage/FileSystemStorageHandle.h:
     37        (WebKit::FileSystemStorageHandle::activeSyncAccessHandle const):
     38        * NetworkProcess/storage/FileSystemStorageManager.cpp:
     39        (WebKit::FileSystemStorageManager::~FileSystemStorageManager):
     40        (WebKit::FileSystemStorageManager::close):
     41        * NetworkProcess/storage/FileSystemStorageManager.h:
     42        * NetworkProcess/storage/NetworkStorageManager.cpp:
     43        (WebKit::readOriginFromFile):
     44        (WebKit::writeOriginToFileIfNecessary):
     45        (WebKit::deleteOriginFileIfNecessary):
     46        (WebKit::originDirectoryPath):
     47        (WebKit::originFilePath):
     48        (WebKit::NetworkStorageManager::localOriginStorageManager):
     49        (WebKit::NetworkStorageManager::removeOriginStorageManagerIfPossible):
     50        (WebKit::NetworkStorageManager::persist):
     51        (WebKit::NetworkStorageManager::clearStorageForTesting): Only reset persisted state here as our test bot can run
     52        tests in parallel. If one worker finishes a test and asks to clear storage, while another worker is running a
     53        filesystem test; the test may fail as data is gone. (The workers are using the same network process.)
     54        (WebKit::toWebsiteDataType):
     55        (WebKit::NetworkStorageManager::forEachOriginDirectory):
     56        (WebKit::NetworkStorageManager::fetchDataFromDisk):
     57        (WebKit::NetworkStorageManager::fetchData):
     58        (WebKit::NetworkStorageManager::deleteDataOnDisk):
     59        (WebKit::NetworkStorageManager::deleteData):
     60        (WebKit::NetworkStorageManager::deleteDataModifiedSince):
     61        (WebKit::NetworkStorageManager::deleteDataForRegistrableDomains):
     62        (WebKit::originPath): Deleted.
     63        * NetworkProcess/storage/NetworkStorageManager.h:
     64        * NetworkProcess/storage/OriginStorageManager.cpp:
     65        (WebKit::OriginStorageManager::StorageBucket::toStorageIdentifier):
     66        (WebKit::OriginStorageManager::StorageBucket::typeStoragePath const):
     67        (WebKit::OriginStorageManager::StorageBucket::fileSystemStorageManager):
     68        (WebKit::OriginStorageManager::StorageBucket::isActive):
     69        (WebKit::OriginStorageManager::StorageBucket::deleteData):
     70        (WebKit::OriginStorageManager::StorageBucket::deleteFileSystemStorageData):
     71        (WebKit::OriginStorageManager::OriginStorageManager):
     72        (WebKit::OriginStorageManager::fileSystemStorageManager):
     73        (WebKit::OriginStorageManager::isActive):
     74        (WebKit::OriginStorageManager::deleteData):
     75        (WebKit::OriginStorageManager::setPersisted):
     76        (WebKit::OriginStorageManager::persist): Deleted.
     77        * NetworkProcess/storage/OriginStorageManager.h:
     78        * Shared/WebsiteData/WebsiteData.cpp:
     79        (WebKit::WebsiteData::ownerProcess):
     80        * Shared/WebsiteData/WebsiteDataType.h:
     81        * UIProcess/API/Cocoa/WKWebsiteDataRecord.mm:
     82        (dataTypesToString):
     83        * UIProcess/API/Cocoa/WKWebsiteDataRecordInternal.h:
     84        (WebKit::toWebsiteDataType):
     85        (WebKit::toWKWebsiteDataTypes):
     86        * UIProcess/API/Cocoa/WKWebsiteDataRecordPrivate.h:
     87        * UIProcess/API/Cocoa/WKWebsiteDataStore.mm:
     88        (+[WKWebsiteDataStore _allWebsiteDataTypesIncludingPrivate]):
     89        * WebKit.xcodeproj/project.pbxproj:
     90        * WebProcess/Network/NetworkProcessConnection.cpp:
     91        (WebKit::NetworkProcessConnection::didReceiveMessage):
     92        * WebProcess/WebCoreSupport/WebFileSystemStorageConnection.messages.in: Added.
     93
    1942021-12-07  Kimmo Kinnunen  <kkinnunen@apple.com>
    295
  • trunk/Source/WebKit/DerivedSources-input.xcfilelist

    r286569 r286601  
    222222$(PROJECT_DIR)/WebProcess/WebCoreSupport/WebBroadcastChannelRegistry.messages.in
    223223$(PROJECT_DIR)/WebProcess/WebCoreSupport/WebDeviceOrientationUpdateProvider.messages.in
     224$(PROJECT_DIR)/WebProcess/WebCoreSupport/WebFileSystemStorageConnection.messages.in
    224225$(PROJECT_DIR)/WebProcess/WebCoreSupport/WebSpeechRecognitionConnection.messages.in
    225226$(PROJECT_DIR)/WebProcess/WebPage/Cocoa/TextCheckingControllerProxy.messages.in
  • trunk/Source/WebKit/DerivedSources-output.xcfilelist

    r286569 r286601  
    11# This file is generated by the generate-xcfilelists script.
    2 <<<<<<< HEAD
    32$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit/AudioCaptureSampleManagerMessageReceiver.cpp
    43$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit/AudioCaptureSampleManagerMessagesReplies.h
     
    495494$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit/WebDeviceOrientationUpdateProviderProxyMessages.h
    496495$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit/WebDeviceOrientationUpdateProviderProxyMessagesReplies.h
     496$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit/WebFileSystemStorageConnectionMessageReceiver.cpp
     497$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit/WebFileSystemStorageConnectionMessages.h
     498$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit/WebFileSystemStorageConnectionMessagesReplies.h
    497499$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit/WebFullScreenManagerMessageReceiver.cpp
    498500$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit/WebFullScreenManagerMessages.h
     
    621623$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit/com.apple.WebKit.plugin-common.sb
    622624$(BUILT_PRODUCTS_DIR)/DerivedSources/WebKit/com.apple.WebProcess.sb
     625<<<<<<< HEAD
  • trunk/Source/WebKit/DerivedSources.make

    r286569 r286601  
    223223        WebProcess/WebCoreSupport/WebBroadcastChannelRegistry \
    224224        WebProcess/WebCoreSupport/WebDeviceOrientationUpdateProvider \
     225        WebProcess/WebCoreSupport/WebFileSystemStorageConnection \
    225226        WebProcess/WebCoreSupport/WebSpeechRecognitionConnection \
    226227        WebProcess/Speech/SpeechRecognitionRealtimeMediaSourceManager \
  • trunk/Source/WebKit/NetworkProcess/Classifier/WebResourceLoadStatisticsStore.cpp

    r286569 r286601  
    7575        WebsiteDataType::ServiceWorkerRegistrations,
    7676#endif
     77        WebsiteDataType::FileSystem,
    7778    }));
    7879
  • trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp

    r286569 r286601  
    15561556    }
    15571557#endif
     1558
     1559    if (auto iterator = m_storageManagers.find(sessionID); iterator != m_storageManagers.end()) {
     1560        iterator->value->fetchData(websiteDataTypes, [callbackAggregator](auto entries) mutable {
     1561            callbackAggregator->m_websiteData.entries.appendVector(WTFMove(entries));
     1562        });
     1563    }
    15581564}
    15591565
     
    16301636    }
    16311637#endif
     1638
     1639    if (auto iterator = m_storageManagers.find(sessionID); iterator != m_storageManagers.end())
     1640        iterator->value->deleteDataModifiedSince(websiteDataTypes, modifiedSince, [clearTasksHandler] { });
    16321641}
    16331642
     
    17361745    }
    17371746#endif
     1747
     1748    if (auto iterator = m_storageManagers.find(sessionID); iterator != m_storageManagers.end())
     1749        iterator->value->deleteData(websiteDataTypes, originDatas, [clearTasksHandler] { });
    17381750
    17391751    if (auto* networkSession = this->networkSession(sessionID)) {
     
    19601972    }
    19611973
     1974    if (auto iterator = m_storageManagers.find(sessionID); iterator != m_storageManagers.end()) {
     1975        iterator->value->deleteDataForRegistrableDomains(websiteDataTypes, domainsToDeleteAllNonCookieWebsiteDataFor, [callbackAggregator](auto deletedDomains) mutable {
     1976            for (auto domain : deletedDomains)
     1977                callbackAggregator->m_domains.add(WTFMove(domain));
     1978        });
     1979    }
     1980
    19621981    auto dataTypesForUIProcess = WebsiteData::filter(websiteDataTypes, WebsiteDataProcessType::UI);
    19631982    if (!dataTypesForUIProcess.isEmpty() && !domainsToDeleteAllNonCookieWebsiteDataFor.isEmpty()) {
     
    20742093                callbackAggregator->m_websiteData.entries.appendVector(entries);
    20752094            });
     2095        });
     2096    }
     2097
     2098    if (auto iterator = m_storageManagers.find(sessionID); iterator != m_storageManagers.end()) {
     2099        iterator->value->fetchData(websiteDataTypes, [callbackAggregator](auto entries) mutable {
     2100            callbackAggregator->m_websiteData.entries.appendVector(WTFMove(entries));
    20762101        });
    20772102    }
  • trunk/Source/WebKit/NetworkProcess/storage/FileSystemStorageHandle.h

    r286569 r286601  
    6363    Expected<AccessHandleInfo, FileSystemStorageError> createSyncAccessHandle();
    6464    std::optional<FileSystemStorageError> close(WebCore::FileSystemSyncAccessHandleIdentifier);
     65    std::optional<WebCore::FileSystemSyncAccessHandleIdentifier> activeSyncAccessHandle() const { return m_activeSyncAccessHandle; }
    6566
    6667private:
  • trunk/Source/WebKit/NetworkProcess/storage/FileSystemStorageManager.cpp

    r286569 r286601  
    2929#include "FileSystemStorageError.h"
    3030#include "FileSystemStorageHandleRegistry.h"
     31#include "WebFileSystemStorageConnectionMessages.h"
    3132
    3233namespace WebKit {
     
    4344    ASSERT(!RunLoop::isMain());
    4445
    45     for (auto identifier : m_handles.keys())
    46         m_registry.unregisterHandle(identifier);
     46    close();
    4747}
    4848
     
    150150}
    151151
     152void FileSystemStorageManager::close()
     153{
     154    ASSERT(!RunLoop::isMain());
     155
     156    for (auto& [connectionID, identifiers] : m_handlesByConnection) {
     157        for (auto identifier : identifiers) {
     158            auto takenHandle = m_handles.take(identifier);
     159            m_registry.unregisterHandle(identifier);
     160
     161            // Send message to web process to invalidate active sync access handle.
     162            if (auto accessHandleIdentifier = takenHandle->activeSyncAccessHandle())
     163                IPC::Connection::send(connectionID, Messages::WebFileSystemStorageConnection::InvalidateAccessHandle(*accessHandleIdentifier), 0);
     164        }
     165    }
     166
     167    ASSERT(m_handles.isEmpty());
     168    m_handlesByConnection.clear();
     169    m_lockMap.clear();
     170}
     171
    152172} // namespace WebKit
  • trunk/Source/WebKit/NetworkProcess/storage/FileSystemStorageManager.h

    r286569 r286601  
    5050
    5151private:
     52    void close();
     53
    5254    String m_path;
    5355    FileSystemStorageHandleRegistry& m_registry;
  • trunk/Source/WebKit/NetworkProcess/storage/NetworkStorageManager.cpp

    r286569 r286601  
    3232#include "NetworkStorageManagerMessages.h"
    3333#include "OriginStorageManager.h"
     34#include "WebsiteDataType.h"
    3435#include <pal/crypto/CryptoDigest.h>
     36#include <wtf/Scope.h>
     37#include <wtf/persistence/PersistentDecoder.h>
     38#include <wtf/persistence/PersistentEncoder.h>
    3539#include <wtf/text/Base64.h>
    3640
    3741namespace WebKit {
     42
     43static std::optional<WebCore::ClientOrigin> readOriginFromFile(const String& filePath)
     44{
     45    ASSERT(!RunLoop::isMain());
     46
     47    if (!FileSystem::fileExists(filePath))
     48        return std::nullopt;
     49
     50    auto originFileHandle = FileSystem::openFile(filePath, FileSystem::FileOpenMode::Read);
     51    auto closeFile = makeScopeExit([&] {
     52        FileSystem::closeFile(originFileHandle);
     53    });
     54
     55    if (!FileSystem::isHandleValid(originFileHandle))
     56        return std::nullopt;
     57
     58    auto originContent = FileSystem::readEntireFile(originFileHandle);
     59    if (!originContent)
     60        return std::nullopt;
     61
     62    WTF::Persistence::Decoder decoder({ originContent->data(), originContent->size() });
     63    std::optional<WebCore::ClientOrigin> origin;
     64    decoder >> origin;
     65    return origin;
     66}
     67
     68static void writeOriginToFileIfNecessary(const String& filePath, const WebCore::ClientOrigin& origin)
     69{
     70    if (FileSystem::fileExists(filePath))
     71        return;
     72
     73    FileSystem::makeAllDirectories(FileSystem::parentPath(filePath));
     74    auto originFileHandle = FileSystem::openFile(filePath, FileSystem::FileOpenMode::ReadWrite);
     75    auto closeFile = makeScopeExit([&] {
     76        FileSystem::closeFile(originFileHandle);
     77    });
     78
     79    if (!FileSystem::isHandleValid(originFileHandle)) {
     80        LOG_ERROR("writeOriginToFileIfNecessary: Failed to open origin file");
     81        return;
     82    }
     83
     84    WTF::Persistence::Encoder encoder;
     85    encoder << origin;
     86    FileSystem::writeToFile(originFileHandle, encoder.buffer(), encoder.bufferSize());
     87}
     88
     89static void deleteOriginFileIfNecessary(const String& filePath)
     90{
     91    auto parentPath = FileSystem::parentPath(filePath);
     92    auto children = FileSystem::listDirectory(parentPath);
     93    if (children.size() == 1)
     94        FileSystem::deleteFile(filePath);
     95}
    3896
    3997Ref<NetworkStorageManager> NetworkStorageManager::create(PAL::SessionID sessionID, const String& path)
     
    118176}
    119177
    120 static String originPath(const String& rootPath, const WebCore::ClientOrigin& origin, FileSystem::Salt salt)
     178static String originDirectoryPath(const String& rootPath, const WebCore::ClientOrigin& origin, FileSystem::Salt salt)
    121179{
    122180    if (rootPath.isEmpty())
     
    128186}
    129187
     188static String originFilePath(const String& directory)
     189{
     190    return FileSystem::pathByAppendingComponent(directory, "origin"_s);
     191}
     192
    130193OriginStorageManager& NetworkStorageManager::localOriginStorageManager(const WebCore::ClientOrigin& origin)
    131194{
     
    133196
    134197    return *m_localOriginStorageManagers.ensure(origin, [&] {
    135         return makeUnique<OriginStorageManager>(originPath(m_path, origin, m_salt));
     198        auto originDirectory = originDirectoryPath(m_path, origin, m_salt);
     199        writeOriginToFileIfNecessary(originFilePath(originDirectory), origin);
     200        return makeUnique<OriginStorageManager>(WTFMove(originDirectory));
    136201    }).iterator->value;
    137202}
    138203
     204void NetworkStorageManager::removeOriginStorageManagerIfPossible(const WebCore::ClientOrigin& origin)
     205{
     206    if (auto iterator = m_localOriginStorageManagers.find(origin); iterator != m_localOriginStorageManagers.end()) {
     207        if (!iterator->value->isActive())
     208            m_localOriginStorageManagers.remove(iterator);
     209    }
     210}
     211
    139212void NetworkStorageManager::persisted(const WebCore::ClientOrigin& origin, CompletionHandler<void(bool)>&& completionHandler)
    140213{
     
    148221    ASSERT(!RunLoop::isMain());
    149222
    150     localOriginStorageManager(origin).persist();
     223    localOriginStorageManager(origin).setPersisted(true);
    151224    completionHandler(true);
    152225}
     
    157230
    158231    m_queue->dispatch([this, protectedThis = Ref { *this }, completionHandler = WTFMove(completionHandler)]() mutable {
    159         m_localOriginStorageManagers.clear();
    160         m_sessionOriginStorageManagers.clear();
     232        // Reset persisted value.
     233        for (auto& manager : m_localOriginStorageManagers.values())
     234            manager->setPersisted(false);
     235
     236        for (auto& manager : m_sessionOriginStorageManagers.values())
     237            manager->setPersisted(false);
    161238
    162239        RunLoop::main().dispatch([protectedThis = WTFMove(protectedThis), completionHandler = WTFMove(completionHandler)]() mutable {
     
    307384}
    308385
     386static std::optional<WebsiteDataType> toWebsiteDataType(const String& storageType)
     387{
     388    if (storageType == "FileSystem")
     389        return WebsiteDataType::FileSystem;
     390
     391    return std::nullopt;
     392}
     393
     394void NetworkStorageManager::forEachOriginDirectory(const Function<void(const String&)>& apply)
     395{
     396    for (auto& topOrigin : FileSystem::listDirectory(m_path)) {
     397        auto topOriginDirectory = FileSystem::pathByAppendingComponent(m_path, topOrigin);
     398        auto openingOrigins = FileSystem::listDirectory(topOriginDirectory);
     399        if (openingOrigins.isEmpty()) {
     400            FileSystem::deleteEmptyDirectory(topOriginDirectory);
     401            continue;
     402        }
     403
     404        for (auto& openingOrigin : openingOrigins) {
     405            auto openingOriginDirectory = FileSystem::pathByAppendingComponent(topOriginDirectory, openingOrigin);
     406            apply(openingOriginDirectory);
     407        }
     408    }
     409}
     410
     411Vector<WebsiteData::Entry> NetworkStorageManager::fetchDataFromDisk(OptionSet<WebsiteDataType> targetTypes)
     412{
     413    ASSERT(!RunLoop::isMain());
     414
     415    HashMap<WebCore::SecurityOriginData, OptionSet<WebsiteDataType>> originTypes;
     416    forEachOriginDirectory([&](auto directory) mutable {
     417        auto origin = readOriginFromFile(originFilePath(directory));
     418        if (!origin)
     419            return;
     420
     421        for (auto& storageType : FileSystem::listDirectory(directory)) {
     422            if (auto type = toWebsiteDataType(storageType); type && targetTypes.contains(*type)) {
     423                // Return both top origin and opening origin for this data.
     424                originTypes.add(origin->clientOrigin, OptionSet<WebsiteDataType> { }).iterator->value.add(*type);
     425                originTypes.add(origin->topOrigin, OptionSet<WebsiteDataType> { }).iterator->value.add(*type);
     426            }
     427        }
     428    });
     429
     430    Vector<WebsiteData::Entry> entries;
     431    for (auto [origin, types] : originTypes) {
     432        for (auto type : types)
     433            entries.append({ WebsiteData::Entry { origin, type, 0 } });
     434    }
     435
     436    return entries;
     437}
     438
     439void NetworkStorageManager::fetchData(OptionSet<WebsiteDataType> types, CompletionHandler<void(Vector<WebsiteData::Entry>&&)>&& completionHandler)
     440{
     441    ASSERT(RunLoop::isMain());
     442    ASSERT(!m_closed);
     443
     444    m_queue->dispatch([this, protectedThis = Ref { *this }, types, completionHandler = WTFMove(completionHandler)]() mutable {
     445        auto entries = fetchDataFromDisk(types);
     446        RunLoop::main().dispatch([protectedThis = WTFMove(protectedThis), completionHandler = WTFMove(completionHandler), entries = crossThreadCopy(WTFMove(entries))]() mutable {
     447            completionHandler(WTFMove(entries));
     448        });
     449    });
     450}
     451
     452Vector<WebCore::ClientOrigin> NetworkStorageManager::deleteDataOnDisk(OptionSet<WebsiteDataType> types, WallTime modifiedSinceTime, const Function<bool(const WebCore::ClientOrigin&)>& filter)
     453{
     454    ASSERT(!RunLoop::isMain());
     455
     456    Vector<WebCore::ClientOrigin> deletedOrigins;
     457    forEachOriginDirectory([&](auto directory) mutable {
     458        auto filePath = originFilePath(directory);
     459        auto origin = readOriginFromFile(filePath);
     460        if (!origin) {
     461            // If origin cannot be retrieved, but we are asked to remove data for all origins, remove it.
     462            RELEASE_LOG_ERROR(Storage, "NetworkStorageManager::deleteDataOnDisk failed to read origin from '%s'", filePath.utf8().data());
     463            if (filter(WebCore::ClientOrigin { })) {
     464                auto tempOriginStorageManager = makeUnique<OriginStorageManager>(String { directory });
     465                tempOriginStorageManager->deleteData(types, modifiedSinceTime);
     466                deleteOriginFileIfNecessary(filePath);
     467                FileSystem::deleteEmptyDirectory(directory);
     468            }
     469            return;
     470        }
     471
     472        if (!filter(*origin))
     473            return;
     474
     475        deletedOrigins.append(*origin);
     476        localOriginStorageManager(*origin).deleteData(types, modifiedSinceTime);
     477        removeOriginStorageManagerIfPossible(*origin);
     478        deleteOriginFileIfNecessary(filePath);
     479        FileSystem::deleteEmptyDirectory(directory);
     480    });
     481
     482    return deletedOrigins;
     483}
     484
     485void NetworkStorageManager::deleteData(OptionSet<WebsiteDataType> types, const Vector<WebCore::SecurityOriginData>& origins, CompletionHandler<void()>&& completionHandler)
     486{
     487    ASSERT(RunLoop::isMain());
     488    ASSERT(!m_closed);
     489
     490    m_queue->dispatch([this, protectedThis = Ref { *this }, types, origins = crossThreadCopy(origins), completionHandler = WTFMove(completionHandler)]() mutable {
     491        HashSet<WebCore::SecurityOriginData> originSet;
     492        originSet.reserveInitialCapacity(origins.size());
     493        for (auto origin : origins)
     494            originSet.add(WTFMove(origin));
     495
     496        deleteDataOnDisk(types, -WallTime::infinity(), [&originSet](auto origin) {
     497            return originSet.contains(origin.topOrigin) || originSet.contains(origin.clientOrigin);
     498        });
     499
     500        RunLoop::main().dispatch([protectedThis = WTFMove(protectedThis), completionHandler = WTFMove(completionHandler)]() mutable {
     501            completionHandler();
     502        });
     503    });
     504}
     505
     506void NetworkStorageManager::deleteDataModifiedSince(OptionSet<WebsiteDataType> types, WallTime modifiedSinceTime, CompletionHandler<void()>&& completionHandler)
     507{
     508    ASSERT(RunLoop::isMain());
     509    ASSERT(!m_closed);
     510
     511    m_queue->dispatch([this, protectedThis = Ref { *this }, types, modifiedSinceTime, completionHandler = WTFMove(completionHandler)]() mutable {
     512        deleteDataOnDisk(types, modifiedSinceTime, [](auto&) {
     513            return true;
     514        });
     515
     516        RunLoop::main().dispatch([protectedThis = WTFMove(protectedThis), completionHandler = WTFMove(completionHandler)]() mutable {
     517            completionHandler();
     518        });
     519    });
     520}
     521
     522void NetworkStorageManager::deleteDataForRegistrableDomains(OptionSet<WebsiteDataType> types, const Vector<WebCore::RegistrableDomain>& domains, CompletionHandler<void(HashSet<WebCore::RegistrableDomain>&&)>&& completionHandler)
     523{
     524    ASSERT(RunLoop::isMain());
     525    ASSERT(!m_closed);
     526
     527    m_queue->dispatch([this, protectedThis = Ref { *this }, types, domains = crossThreadCopy(domains), completionHandler = WTFMove(completionHandler)]() mutable {
     528        auto deletedOrigins = deleteDataOnDisk(types, -WallTime::infinity(), [&domains](auto& origin) {
     529            auto domain = WebCore::RegistrableDomain::uncheckedCreateFromHost(origin.clientOrigin.host);
     530            return domains.contains(domain);
     531        });
     532
     533        HashSet<WebCore::RegistrableDomain> deletedDomains;
     534        for (auto origin : deletedOrigins) {
     535            auto domain = WebCore::RegistrableDomain::uncheckedCreateFromHost(origin.clientOrigin.host);
     536            deletedDomains.add(domain);
     537        }
     538
     539        RunLoop::main().dispatch([protectedThis = WTFMove(protectedThis), completionHandler = WTFMove(completionHandler), domains = crossThreadCopy(WTFMove(deletedDomains))]() mutable {
     540            completionHandler(WTFMove(domains));
     541        });
     542    });
     543}
     544
    309545} // namespace WebKit
    310546
  • trunk/Source/WebKit/NetworkProcess/storage/NetworkStorageManager.h

    r286569 r286601  
    2929#include "FileSystemStorageError.h"
    3030#include "OriginStorageManager.h"
     31#include "WebsiteData.h"
    3132#include <WebCore/ClientOrigin.h>
    3233#include <WebCore/FileSystemHandleIdentifier.h>
    3334#include <WebCore/FileSystemSyncAccessHandleIdentifier.h>
    3435#include <pal/SessionID.h>
     36#include <wtf/Forward.h>
    3537
    3638namespace IPC {
     
    5658    void close();
    5759    void clearStorageForTesting(CompletionHandler<void()>&&);
     60    void fetchData(OptionSet<WebsiteDataType>, CompletionHandler<void(Vector<WebsiteData::Entry>&&)>&&);
     61    void deleteData(OptionSet<WebsiteDataType>, const Vector<WebCore::SecurityOriginData>&, CompletionHandler<void()>&&);
     62    void deleteDataModifiedSince(OptionSet<WebsiteDataType>, WallTime, CompletionHandler<void()>&&);
     63    void deleteDataForRegistrableDomains(OptionSet<WebsiteDataType>, const Vector<WebCore::RegistrableDomain>&, CompletionHandler<void(HashSet<WebCore::RegistrableDomain>&&)>&&);
    5864
    5965private:
     
    6167    ~NetworkStorageManager();
    6268    OriginStorageManager& localOriginStorageManager(const WebCore::ClientOrigin&);
     69    void removeOriginStorageManagerIfPossible(const WebCore::ClientOrigin&);
    6370    FileSystemStorageHandleRegistry& fileSystemStorageHandleRegistry();
     71
     72    void forEachOriginDirectory(const Function<void(const String&)>&);
     73    Vector<WebsiteData::Entry> fetchDataFromDisk(OptionSet<WebsiteDataType>);
     74    Vector<WebCore::ClientOrigin> deleteDataOnDisk(OptionSet<WebsiteDataType>, WallTime, const Function<bool(const WebCore::ClientOrigin&)>&);
    6475
    6576    // IPC::MessageReceiver (implemented by generated code)
  • trunk/Source/WebKit/NetworkProcess/storage/OriginStorageManager.cpp

    r286569 r286601  
    5252    }
    5353
    54     String typeStoragePath(const String& storageIdentifier) const
     54    enum class StorageType : uint8_t {
     55        FileSystem,
     56    };
     57
     58    static String toStorageIdentifier(StorageType type)
    5559    {
    56         return m_rootPath.isEmpty() ? emptyString() : FileSystem::pathByAppendingComponent(m_rootPath, storageIdentifier);
     60        switch (type) {
     61        case StorageType::FileSystem:
     62            return "FileSystem"_s;
     63        default:
     64            break;
     65        }
     66        ASSERT_NOT_REACHED();
     67        return ""_s;
     68    }
     69
     70    String typeStoragePath(StorageType type) const
     71    {
     72        auto storageIdentifier = toStorageIdentifier(type);
     73        if (m_rootPath.isEmpty() || storageIdentifier.isEmpty())
     74            return emptyString();
     75
     76        return FileSystem::pathByAppendingComponent(m_rootPath, storageIdentifier);
    5777    }
    5878
     
    6080    {
    6181        if (!m_fileSystemStorageManager)
    62             m_fileSystemStorageManager = makeUnique<FileSystemStorageManager>(typeStoragePath("FileSystem"), registry);
     82            m_fileSystemStorageManager = makeUnique<FileSystemStorageManager>(typeStoragePath(StorageType::FileSystem), registry);
    6383
    6484        return *m_fileSystemStorageManager;
    6585    }
    6686
     87    bool isActive()
     88    {
     89        return !!m_fileSystemStorageManager;
     90    }
     91
     92    void deleteData(OptionSet<WebsiteDataType> types, WallTime modifiedSinceTime)
     93    {
     94        if (types.contains(WebsiteDataType::FileSystem))
     95            deleteFileSystemStorageData(modifiedSinceTime);
     96    }
     97
    6798private:
     99    void deleteFileSystemStorageData(WallTime modifiedSinceTime)
     100    {
     101        m_fileSystemStorageManager = nullptr;
     102
     103        auto fileSystemStoragePath = typeStoragePath(StorageType::FileSystem);
     104        FileSystem::deleteAllFilesModifiedSince(fileSystemStoragePath, modifiedSinceTime);
     105    }
     106
    68107    String m_rootPath;
    69108    String m_identifier;
     
    75114    : m_path(WTFMove(path))
    76115{
     116    ASSERT(!RunLoop::isMain());
    77117}
    78118
     
    93133}
    94134
    95 void OriginStorageManager::persist()
    96 {
    97     m_persisted = true;
    98     defaultBucket().setMode(StorageBucketMode::Persistent);
    99 }
    100 
    101135FileSystemStorageManager& OriginStorageManager::fileSystemStorageManager(FileSystemStorageHandleRegistry& registry)
    102136{
     
    104138}
    105139
     140bool OriginStorageManager::isActive()
     141{
     142    return defaultBucket().isActive();
     143}
     144
     145void OriginStorageManager::deleteData(OptionSet<WebsiteDataType> types, WallTime modifiedSince)
     146{
     147    ASSERT(!RunLoop::isMain());
     148    defaultBucket().deleteData(types, modifiedSince);
     149}
     150
     151void OriginStorageManager::setPersisted(bool value)
     152{
     153    ASSERT(!RunLoop::isMain());
     154
     155    m_persisted = value;
     156    defaultBucket().setMode(value ? StorageBucketMode::Persistent : StorageBucketMode::BestEffort);
     157}
     158
    106159} // namespace WebKit
    107160
  • trunk/Source/WebKit/NetworkProcess/storage/OriginStorageManager.h

    r286569 r286601  
    2929#include <wtf/text/WTFString.h>
    3030
     31namespace WebCore {
     32struct ClientOrigin;
     33}
     34
    3135namespace WebKit {
    3236
    3337class FileSystemStorageHandleRegistry;
    3438class FileSystemStorageManager;
     39enum class WebsiteDataType : uint32_t;
    3540
    3641class OriginStorageManager {
     
    4247    void connectionClosed(IPC::Connection::UniqueID);
    4348    bool persisted() const { return m_persisted; }
    44     void persist();
     49    void setPersisted(bool value);
    4550    FileSystemStorageManager& fileSystemStorageManager(FileSystemStorageHandleRegistry&);
     51    bool isActive();
     52    void deleteData(OptionSet<WebsiteDataType>, WallTime);
    4653
    4754private:
     
    4956    class StorageBucket;
    5057    StorageBucket& defaultBucket();
     58
     59    void createOriginFileIfNecessary(const WebCore::ClientOrigin&);
     60    void deleteOriginFileIfNecessary();
    5161
    5262    std::unique_ptr<StorageBucket> m_defaultBucket;
  • trunk/Source/WebKit/Shared/WebsiteData/WebsiteData.cpp

    r286569 r286601  
    130130        return WebsiteDataProcessType::Network;
    131131#endif
     132    case WebsiteDataType::FileSystem:
     133        return WebsiteDataProcessType::Network;
    132134    }
    133135
  • trunk/Source/WebKit/Shared/WebsiteData/WebsiteDataType.h

    r286569 r286601  
    5353    AlternativeServices = 1 << 18,
    5454#endif
     55    FileSystem = 1 << 19,
    5556};
    5657
     
    8081        WebKit::WebsiteDataType::DOMCache,
    8182        WebKit::WebsiteDataType::DeviceIdHashSalt,
    82         WebKit::WebsiteDataType::PrivateClickMeasurements
     83        WebKit::WebsiteDataType::PrivateClickMeasurements,
    8384#if HAVE(CFNETWORK_ALTERNATIVE_SERVICE)
    84         , WebKit::WebsiteDataType::AlternativeServices
     85        WebKit::WebsiteDataType::AlternativeServices,
    8586#endif
     87        WebKit::WebsiteDataType::FileSystem
    8688    >;
    8789};
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataRecord.mm

    r286569 r286601  
    5252NSString * const _WKWebsiteDataTypePrivateClickMeasurements = @"_WKWebsiteDataTypePrivateClickMeasurements";
    5353NSString * const _WKWebsiteDataTypeAlternativeServices = @"_WKWebsiteDataTypeAlternativeServices";
     54NSString * const _WKWebsiteDataTypeFileSystem = @"_WKWebsiteDataTypeFileSystem";
    5455
    5556#if PLATFORM(MAC)
     
    111112    if ([dataTypes containsObject:_WKWebsiteDataTypeAlternativeServices])
    112113        [array addObject:@"Alternative Services"];
     114    if ([dataTypes containsObject:_WKWebsiteDataTypeFileSystem])
     115        [array addObject:@"File System"];
    113116
    114117    return [array componentsJoinedByString:@", "];
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataRecordInternal.h

    r286569 r286601  
    7878        return WebsiteDataType::AlternativeServices;
    7979#endif
     80    if ([websiteDataType isEqualToString:_WKWebsiteDataTypeFileSystem])
     81        return WebsiteDataType::FileSystem;
    8082    return std::nullopt;
    8183}
     
    135137        [wkWebsiteDataTypes addObject:_WKWebsiteDataTypeAlternativeServices];
    136138#endif
     139    if (websiteDataTypes.contains(WebsiteDataType::FileSystem))
     140        [wkWebsiteDataTypes addObject:_WKWebsiteDataTypeFileSystem];
    137141
    138142    return wkWebsiteDataTypes;
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataRecordPrivate.h

    r286569 r286601  
    3838WK_EXTERN NSString * const _WKWebsiteDataTypePrivateClickMeasurements WK_API_AVAILABLE(macos(12.0), ios(15.0));
    3939WK_EXTERN NSString * const _WKWebsiteDataTypeAlternativeServices WK_API_AVAILABLE(macos(11.0), ios(14.0));
     40WK_EXTERN NSString * const _WKWebsiteDataTypeFileSystem WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
    4041
    4142#if !TARGET_OS_IPHONE
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm

    r286569 r286601  
    249249            _WKWebsiteDataTypeAdClickAttributions,
    250250            _WKWebsiteDataTypePrivateClickMeasurements,
    251             _WKWebsiteDataTypeAlternativeServices
     251            _WKWebsiteDataTypeAlternativeServices,
     252            _WKWebsiteDataTypeFileSystem
    252253#if !TARGET_OS_IPHONE
    253254            , _WKWebsiteDataTypePlugInData
  • trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj

    r286596 r286601  
    15051505                93D6B7B925534A170058DD3A /* WKSpeechRecognitionPermissionCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 93D6B7B725534A110058DD3A /* WKSpeechRecognitionPermissionCallback.h */; settings = {ATTRIBUTES = (Private, ); }; };
    15061506                93E6A4EE1BC5DD3900F8A0E7 /* _WKHitTestResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 93E6A4ED1BC5DD3900F8A0E7 /* _WKHitTestResult.h */; settings = {ATTRIBUTES = (Private, ); }; };
     1507                93E799852756FA550074008A /* WebFileSystemStorageConnectionMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93E799822756FA540074008A /* WebFileSystemStorageConnectionMessageReceiver.cpp */; };
     1508                93E799872756FAB40074008A /* WebFileSystemStorageConnectionMessagesReplies.h in Headers */ = {isa = PBXBuildFile; fileRef = 93E799832756FA540074008A /* WebFileSystemStorageConnectionMessagesReplies.h */; };
     1509                93E799882756FAC20074008A /* WebFileSystemStorageConnectionMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 93E799812756FA530074008A /* WebFileSystemStorageConnectionMessages.h */; };
    15071510                93F549B41E3174B7000E7239 /* WKSnapshotConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 93F549B31E3174B7000E7239 /* WKSnapshotConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; };
    15081511                950F2880252414EA00B74F1C /* WKMouseDeviceObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = 950F287E252414E900B74F1C /* WKMouseDeviceObserver.h */; };
     
    53245327                93D6B7B825534A120058DD3A /* WKSpeechRecognitionPermissionCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WKSpeechRecognitionPermissionCallback.cpp; sourceTree = "<group>"; };
    53255328                93E6A4ED1BC5DD3900F8A0E7 /* _WKHitTestResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKHitTestResult.h; sourceTree = "<group>"; };
     5329                93E7997E2756F6700074008A /* WebFileSystemStorageConnection.messages.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebFileSystemStorageConnection.messages.in; sourceTree = "<group>"; };
     5330                93E799812756FA530074008A /* WebFileSystemStorageConnectionMessages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebFileSystemStorageConnectionMessages.h; sourceTree = "<group>"; };
     5331                93E799822756FA540074008A /* WebFileSystemStorageConnectionMessageReceiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebFileSystemStorageConnectionMessageReceiver.cpp; sourceTree = "<group>"; };
     5332                93E799832756FA540074008A /* WebFileSystemStorageConnectionMessagesReplies.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebFileSystemStorageConnectionMessagesReplies.h; sourceTree = "<group>"; };
    53265333                93F549B31E3174B7000E7239 /* WKSnapshotConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKSnapshotConfiguration.h; sourceTree = "<group>"; };
    53275334                93F549B51E3174DA000E7239 /* WKSnapshotConfiguration.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKSnapshotConfiguration.mm; sourceTree = "<group>"; };
     
    1062910636                                9354242B2703BDCB005CA72C /* WebFileSystemStorageConnection.cpp */,
    1063010637                                9354242A2703BDCB005CA72C /* WebFileSystemStorageConnection.h */,
     10638                                93E7997E2756F6700074008A /* WebFileSystemStorageConnection.messages.in */,
    1063110639                                BC111A58112F4FBB00337BAB /* WebFrameLoaderClient.cpp */,
    1063210640                                BC032D6A10F4378D0058C15A /* WebFrameLoaderClient.h */,
     
    1210612114                                E3866B042399979C00F88FE9 /* WebDeviceOrientationUpdateProviderProxyMessageReceiver.cpp */,
    1210712115                                E3866B052399979C00F88FE9 /* WebDeviceOrientationUpdateProviderProxyMessages.h */,
     12116                                93E799822756FA540074008A /* WebFileSystemStorageConnectionMessageReceiver.cpp */,
     12117                                93E799812756FA530074008A /* WebFileSystemStorageConnectionMessages.h */,
     12118                                93E799832756FA540074008A /* WebFileSystemStorageConnectionMessagesReplies.h */,
    1210812119                                CD73BA48131ACD8E00EEDED2 /* WebFullScreenManagerMessageReceiver.cpp */,
    1210912120                                CD73BA49131ACD8E00EEDED2 /* WebFullScreenManagerMessages.h */,
     
    1335213363                                BC111B5D112F629800337BAB /* WebEventFactory.h in Headers */,
    1335313364                                9354242C2703BDCB005CA72C /* WebFileSystemStorageConnection.h in Headers */,
     13365                                93E799882756FAC20074008A /* WebFileSystemStorageConnectionMessages.h in Headers */,
     13366                                93E799872756FAB40074008A /* WebFileSystemStorageConnectionMessagesReplies.h in Headers */,
    1335413367                                1A90C1EE1264FD50003E44D4 /* WebFindOptions.h in Headers */,
    1335513368                                BCE469541214E6CB000B98EB /* WebFormClient.h in Headers */,
     
    1548015493                                E3866B092399A2D500F88FE9 /* WebDeviceOrientationUpdateProviderProxyMessageReceiver.cpp in Sources */,
    1548115494                                2D92A789212B6AB100F493FD /* WebEvent.cpp in Sources */,
     15495                                93E799852756FA550074008A /* WebFileSystemStorageConnectionMessageReceiver.cpp in Sources */,
    1548215496                                CD73BA4E131ACDB700EEDED2 /* WebFullScreenManagerMessageReceiver.cpp in Sources */,
    1548315497                                CD73BA47131ACC9A00EEDED2 /* WebFullScreenManagerProxyMessageReceiver.cpp in Sources */,
  • trunk/Source/WebKit/WebProcess/Network/NetworkProcessConnection.cpp

    r286569 r286601  
    3838#include "WebCookieJar.h"
    3939#include "WebCoreArgumentCoders.h"
     40#include "WebFileSystemStorageConnection.h"
     41#include "WebFileSystemStorageConnectionMessages.h"
    4042#include "WebFrame.h"
    4143#include "WebIDBConnectionToServer.h"
     
    120122        return;
    121123    }
     124    if (decoder.messageReceiverName() == Messages::WebFileSystemStorageConnection::messageReceiverName()) {
     125        WebProcess::singleton().fileSystemStorageConnection().didReceiveMessage(connection, decoder);
     126        return;
     127    }
    122128
    123129#if USE(LIBWEBRTC)
  • trunk/Tools/ChangeLog

    r286600 r286601  
     12021-12-07  Sihui Liu  <sihui_liu@apple.com>
     2
     3        Fetch and remove file system data via WKWebsiteDataStore
     4        https://bugs.webkit.org/show_bug.cgi?id=233567
     5        <rdar://problem/86029185>
     6
     7        Reviewed by Youenn Fablet.
     8
     9        * TestWebKitAPI/Tests/WebKitCocoa/FileSystemAccess.mm:
     10
    1112021-12-07  Jonathan Bedard  <jbedard@apple.com>
    212
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/FileSystemAccess.mm

    r286569 r286601  
    3030#import "DeprecatedGlobalValues.h"
    3131#import "PlatformUtilities.h"
     32#import "TestUIDelegate.h"
    3233#import "TestURLSchemeHandler.h"
    3334#import "TestWKWebView.h"
     
    3536#import <WebKit/WKWebViewConfigurationPrivate.h>
    3637#import <WebKit/WKWebViewPrivate.h>
     38#import <WebKit/WKWebsiteDataRecordPrivate.h>
    3739
    3840@interface FileSystemAccessMessageHandler : NSObject <WKScriptMessageHandler>
     
    4951@end
    5052
    51 static NSString *mainFrameString = @"<script> \
     53static NSString *workerFrameString = @"<script> \
    5254    function start() { \
    5355        var worker = new Worker('worker.js'); \
     
    116118
    117119    auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]);
    118     [webView loadHTMLString:mainFrameString baseURL:[NSURL URLWithString:@"webkit://webkit.org"]];
     120    [webView loadHTMLString:workerFrameString baseURL:[NSURL URLWithString:@"webkit://webkit.org"]];
    119121    TestWebKitAPI::Util::run(&receivedScriptMessage);
    120122    receivedScriptMessage = false;
     
    127129
    128130    auto secondWebView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]);
    129     [secondWebView loadHTMLString:mainFrameString baseURL:[NSURL URLWithString:@"webkit://webkit.org"]];
     131    [secondWebView loadHTMLString:workerFrameString baseURL:[NSURL URLWithString:@"webkit://webkit.org"]];
    130132    TestWebKitAPI::Util::run(&receivedScriptMessage);
    131133    receivedScriptMessage = false;
     
    169171
    170172    auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]);
    171     [webView loadHTMLString:mainFrameString baseURL:[NSURL URLWithString:@"webkit://webkit.org"]];
     173    [webView loadHTMLString:workerFrameString baseURL:[NSURL URLWithString:@"webkit://webkit.org"]];
    172174    TestWebKitAPI::Util::run(&receivedScriptMessage);
    173175    receivedScriptMessage = false;
     
    259261}
    260262
     263static NSString *testString = @"<script> \
     264    async function open(shouldCreateFile) \
     265    { \
     266        try { \
     267            var rootHandle = await navigator.storage.getDirectory(); \
     268            var fileHandle = await rootHandle.getFileHandle('file-system-access.txt', { 'create' : shouldCreateFile }); \
     269            window.webkit.messageHandlers.testHandler.postMessage('file is opened'); \
     270        } catch(err) { \
     271            window.webkit.messageHandlers.testHandler.postMessage('error: ' + err.name + ' - ' + err.message); \
     272        } \
     273    } \
     274    open(true); \
     275    </script>";
     276
     277TEST(FileSystemAccess, FetchAndRemoveData)
     278{
     279    auto handler = adoptNS([[FileSystemAccessMessageHandler alloc] init]);
     280    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     281    [[configuration userContentController] addScriptMessageHandler:handler.get() name:@"testHandler"];
     282    auto websiteDataStore = [configuration websiteDataStore];
     283    auto types = [NSSet setWithObject:_WKWebsiteDataTypeFileSystem];
     284
     285    // Remove existing data.
     286    done = false;
     287    [websiteDataStore removeDataOfTypes:types modifiedSince:[NSDate distantPast] completionHandler:^ {
     288        done = true;
     289    }];
     290    TestWebKitAPI::Util::run(&done);
     291
     292    auto preferences = [configuration preferences];
     293    preferences._fileSystemAccessEnabled = YES;
     294    preferences._storageAPIEnabled = YES;
     295    auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]);
     296    [webView loadHTMLString:testString baseURL:[NSURL URLWithString:@"https://webkit.org"]];
     297    TestWebKitAPI::Util::run(&receivedScriptMessage);
     298    receivedScriptMessage = false;
     299    EXPECT_WK_STREQ(@"file is opened", [lastScriptMessage body]);
     300
     301    // Fetch data and remove it by origin.
     302    done = false;
     303    [websiteDataStore fetchDataRecordsOfTypes:types completionHandler:^(NSArray<WKWebsiteDataRecord *> *records) {
     304        EXPECT_EQ(records.count, 1u);
     305        auto record = [records objectAtIndex:0];
     306        EXPECT_STREQ("webkit.org", [record.displayName UTF8String]);
     307
     308        // Remove data.
     309        [websiteDataStore removeDataOfTypes:types forDataRecords:records completionHandler:^{
     310            done = true;
     311        }];
     312    }];
     313    TestWebKitAPI::Util::run(&done);
     314
     315    // Fetch data after removal.
     316    done = false;
     317    [websiteDataStore fetchDataRecordsOfTypes:types completionHandler:^(NSArray<WKWebsiteDataRecord *> *records) {
     318        EXPECT_EQ(records.count, 0u);
     319        done = true;
     320    }];
     321
     322    // File cannot be opened after data removal.
     323    [webView evaluateJavaScript:@"open(false)" completionHandler:nil];
     324    TestWebKitAPI::Util::run(&receivedScriptMessage);
     325    receivedScriptMessage = false;
     326    EXPECT_WK_STREQ(@"error: NotFoundError - The object can not be found here.", [lastScriptMessage body]);
     327}
     328
     329TEST(FileSystemAccess, RemoveDataByModificationTime)
     330{
     331    auto handler = adoptNS([[FileSystemAccessMessageHandler alloc] init]);
     332    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     333    [[configuration userContentController] addScriptMessageHandler:handler.get() name:@"testHandler"];
     334    auto preferences = [configuration preferences];
     335    preferences._fileSystemAccessEnabled = YES;
     336    preferences._storageAPIEnabled = YES;
     337    auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]);
     338    [webView loadHTMLString:testString baseURL:[NSURL URLWithString:@"https://webkit.org"]];
     339    TestWebKitAPI::Util::run(&receivedScriptMessage);
     340    receivedScriptMessage = false;
     341    EXPECT_WK_STREQ(@"file is opened", [lastScriptMessage body]);
     342
     343    auto websiteDataStore = [configuration websiteDataStore];
     344    auto types = [NSSet setWithObject:_WKWebsiteDataTypeFileSystem];
     345    done = false;
     346    __block NSUInteger recordsCount;
     347    [websiteDataStore fetchDataRecordsOfTypes:types completionHandler:^(NSArray<WKWebsiteDataRecord *> *records) {
     348        recordsCount = records.count;
     349        EXPECT_GT(recordsCount, 0u);
     350        done = true;
     351    }];
     352    TestWebKitAPI::Util::run(&done);
     353
     354    done = false;
     355    [websiteDataStore removeDataOfTypes:types modifiedSince:[NSDate now] completionHandler:^ {
     356        [websiteDataStore fetchDataRecordsOfTypes:types completionHandler:^(NSArray<WKWebsiteDataRecord *> *records) {
     357            recordsCount = records.count;
     358            EXPECT_EQ(records.count, recordsCount);
     359            done = true;
     360        }];
     361    }];
     362    TestWebKitAPI::Util::run(&done);
     363
     364    done = false;
     365    [websiteDataStore removeDataOfTypes:types modifiedSince:[NSDate distantPast] completionHandler:^ {
     366        [websiteDataStore fetchDataRecordsOfTypes:types completionHandler:^(NSArray<WKWebsiteDataRecord *> *records) {
     367            EXPECT_EQ(records.count, 0u);
     368            done = true;
     369        }];
     370    }];
     371    TestWebKitAPI::Util::run(&done);
     372}
     373
     374static NSString *mainFrameString = @"<script> \
     375    function postResult(event) \
     376    { \
     377        window.webkit.messageHandlers.testHandler.postMessage(event.data); \
     378    } \
     379    addEventListener('message', postResult, false); \
     380    </script> \
     381    <iframe src='https://127.0.0.1:9091/'>";
     382
     383static const char* frameBytes = R"TESTRESOURCE(
     384<script>
     385function postMessage(message)
     386{
     387    parent.postMessage(message, '*');
     388}
     389async function open()
     390{
     391    try {
     392        var rootHandle = await navigator.storage.getDirectory();
     393        var fileHandle = await rootHandle.getFileHandle('file-system-access.txt', { 'create' : true });
     394        postMessage('file is opened');
     395    } catch(err) {
     396        postMessage('error: ' + err.name + ' - ' + err.message);
     397    }
     398}
     399open();
     400</script>
     401)TESTRESOURCE";
     402
     403TEST(FileSystemAccess, FetchDataForThirdParty)
     404{
     405    TestWebKitAPI::HTTPServer server({
     406        { "/", { frameBytes } },
     407    }, TestWebKitAPI::HTTPServer::Protocol::Https, nullptr, nullptr, 9091);
     408
     409    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     410    auto handler = adoptNS([[FileSystemAccessMessageHandler alloc] init]);
     411    [[configuration userContentController] addScriptMessageHandler:handler.get() name:@"testHandler"];
     412    auto preferences = [configuration preferences];
     413    preferences._fileSystemAccessEnabled = YES;
     414    preferences._storageAPIEnabled = YES;
     415
     416    auto websiteDataStore = [configuration websiteDataStore];
     417    auto types = [NSSet setWithObject:_WKWebsiteDataTypeFileSystem];
     418    done = false;
     419    [websiteDataStore removeDataOfTypes:types modifiedSince:[NSDate distantPast] completionHandler:^ {
     420        done = true;
     421    }];
     422    TestWebKitAPI::Util::run(&done);
     423
     424    auto webView = adoptNS([[WKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]);
     425    auto navigationDelegate = adoptNS([TestNavigationDelegate new]);
     426    [navigationDelegate setDidReceiveAuthenticationChallenge:^(WKWebView *, NSURLAuthenticationChallenge *challenge, void (^callback)(NSURLSessionAuthChallengeDisposition, NSURLCredential *)) {
     427        EXPECT_WK_STREQ(challenge.protectionSpace.authenticationMethod, NSURLAuthenticationMethodServerTrust);
     428        callback(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
     429    }];
     430    [navigationDelegate setDecidePolicyForNavigationAction:[&](WKNavigationAction *action, void (^decisionHandler)(WKNavigationActionPolicy)) {
     431        decisionHandler(WKNavigationActionPolicyAllow);
     432    }];
     433    [webView setNavigationDelegate:navigationDelegate.get()];
     434
     435    [webView loadHTMLString:mainFrameString baseURL:[NSURL URLWithString:@"https://webkit.org"]];
     436    TestWebKitAPI::Util::run(&receivedScriptMessage);
     437    receivedScriptMessage = false;
     438    EXPECT_WK_STREQ(@"file is opened", [lastScriptMessage body]);
     439
     440    done = false;
     441    [websiteDataStore fetchDataRecordsOfTypes:types completionHandler:^(NSArray<WKWebsiteDataRecord *> *records) {
     442        // Should return both opening origin and top origin.
     443        EXPECT_EQ(records.count, 2u);
     444        auto sortFunction = ^(WKWebsiteDataRecord *record1, WKWebsiteDataRecord *record2){
     445            return [record1.displayName compare:record2.displayName];
     446        };
     447        auto sortedRecords = [records sortedArrayUsingComparator:sortFunction];
     448        EXPECT_WK_STREQ(@"127.0.0.1", [sortedRecords objectAtIndex:0].displayName);
     449        EXPECT_WK_STREQ(@"webkit.org", [sortedRecords objectAtIndex:1].displayName);
     450        done = true;
     451    }];
     452    TestWebKitAPI::Util::run(&done);
     453}
     454
    261455#endif // USE(APPLE_INTERNAL_SDK)
Note: See TracChangeset for help on using the changeset viewer.