[Win] Implement NetworkCache::Data by using FileSystem::MappedFileData
authorchris.reid@sony.com <chris.reid@sony.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 14 Feb 2020 20:06:28 +0000 (20:06 +0000)
committerchris.reid@sony.com <chris.reid@sony.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 14 Feb 2020 20:06:28 +0000 (20:06 +0000)
https://bugs.webkit.org/show_bug.cgi?id=197684

Reviewed by Fujii Hironori.

Source/WebKit:

* NetworkProcess/NetworkProcess.cpp:
Ensure that the CacheStorage directory is actually being created.

* NetworkProcess/cache/NetworkCacheData.cpp:
* NetworkProcess/cache/NetworkCacheData.h:
* NetworkProcess/cache/NetworkCacheDataCocoa.mm:
* NetworkProcess/cache/NetworkCacheDataSoup.cpp:
* NetworkProcess/cache/NetworkCacheFileSystem.cpp:
Use more FileSystem functionality to share code across platforms.

* NetworkProcess/cache/NetworkCacheDataCurl.cpp:
Use Optional<Vector> for m_buffer since we need to differentiate isEmpty and isNull.

Source/WTF:

* wtf/FileSystem.cpp:
* wtf/FileSystem.h:
Added FileAccessPermission flag when opening files.
Remove default argument for the listDirectory filter since the defaut
String() filter doesn't match all files on Mac and Windows.

* wtf/glib/FileSystemGlib.cpp:
* wtf/posix/FileSystemPOSIX.cpp:
Added (S_IRUSR | S_IWUSR) file open modes.

* wtf/win/FileSystemWin.cpp:
Implement getVolumeFreeSpace since some of the tests use it when toggling cache.

* wtf/win/PathWalker.cpp:

LayoutTests:

* platform/wincairo/TestExpectations:

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

17 files changed:
LayoutTests/ChangeLog
LayoutTests/platform/wincairo/TestExpectations
Source/WTF/ChangeLog
Source/WTF/wtf/FileSystem.cpp
Source/WTF/wtf/FileSystem.h
Source/WTF/wtf/glib/FileSystemGlib.cpp
Source/WTF/wtf/posix/FileSystemPOSIX.cpp
Source/WTF/wtf/win/FileSystemWin.cpp
Source/WTF/wtf/win/PathWalker.cpp
Source/WebKit/ChangeLog
Source/WebKit/NetworkProcess/NetworkProcess.cpp
Source/WebKit/NetworkProcess/cache/NetworkCacheData.cpp
Source/WebKit/NetworkProcess/cache/NetworkCacheData.h
Source/WebKit/NetworkProcess/cache/NetworkCacheDataCocoa.mm
Source/WebKit/NetworkProcess/cache/NetworkCacheDataCurl.cpp
Source/WebKit/NetworkProcess/cache/NetworkCacheDataSoup.cpp
Source/WebKit/NetworkProcess/cache/NetworkCacheFileSystem.cpp

index dfc6fbf..bb29e6d 100644 (file)
@@ -1,3 +1,12 @@
+2020-02-14  Christopher Reid  <chris.reid@sony.com>
+
+        [Win] Implement NetworkCache::Data by using FileSystem::MappedFileData
+        https://bugs.webkit.org/show_bug.cgi?id=197684
+
+        Reviewed by Fujii Hironori.
+
+        * platform/wincairo/TestExpectations:
+
 2020-02-14  Antoine Quint  <graouts@webkit.org>
 
         [Web Animations] Style changes due to Web Animations should not trigger CSS Transitions 
index 686b7c9..0bdee55 100644 (file)
@@ -1161,7 +1161,20 @@ crypto/subtle/wrap-key-malformed-parameters.html [ Skip ]
 
 http/tests/appcache [ Skip ]
 http/tests/blink/sendbeacon [ Skip ]
-http/tests/cache [ Skip ]
+
+# needs more investigation
+http/tests/cache/cancel-multiple-post-xhrs.html [ Failure ]
+
+# fails because of conversion to epoch behavior specific to Mac
+http/tests/cache/disk-cache/disk-cache-last-modified.html [ Failure ]
+
+# needs more investigation
+http/tests/cache/iframe-304-crash.html [ Failure ]
+http/tests/cache/network-error-during-revalidation.html [ Failure ]
+http/tests/cache/partitioned-cache-iframe.html [ Failure ]
+http/tests/cache/partitioned-cache.html [ Failure ]
+http/tests/cache/willsendrequest-returns-null-for-memory-cache-load.html [ Failure ]
+
 http/tests/cache-storage [ Skip ]
 http/tests/canvas [ Skip ]
 http/tests/contentdispositionattachmentsandbox [ Skip ]
index e848368..2f573b1 100644 (file)
@@ -1,3 +1,25 @@
+2020-02-14  Christopher Reid  <chris.reid@sony.com>
+
+        [Win] Implement NetworkCache::Data by using FileSystem::MappedFileData
+        https://bugs.webkit.org/show_bug.cgi?id=197684
+
+        Reviewed by Fujii Hironori.
+
+        * wtf/FileSystem.cpp:
+        * wtf/FileSystem.h:
+        Added FileAccessPermission flag when opening files.
+        Remove default argument for the listDirectory filter since the defaut
+        String() filter doesn't match all files on Mac and Windows.
+
+        * wtf/glib/FileSystemGlib.cpp:
+        * wtf/posix/FileSystemPOSIX.cpp:
+        Added (S_IRUSR | S_IWUSR) file open modes.
+
+        * wtf/win/FileSystemWin.cpp:
+        Implement getVolumeFreeSpace since some of the tests use it when toggling cache.
+        
+        * wtf/win/PathWalker.cpp:
+
 2020-02-14  Alex Christensen  <achristensen@webkit.org>
 
         Allow UIDNAInfo.errors from uidna_nameToUnicode that would not cause URL parsing failures
index 72f953e..f36cdd2 100644 (file)
@@ -287,17 +287,17 @@ MappedFileData::~MappedFileData()
     unmapViewOfFile(m_fileData, m_fileSize);
 }
 
-#if HAVE(MMAP)
-
-MappedFileData::MappedFileData(const String& filePath, MappedFileMode mode, bool& success)
+MappedFileData::MappedFileData(const String& filePath, MappedFileMode mapMode, bool& success)
 {
-    auto fd = openFile(filePath, FileOpenMode::Read);
+    auto fd = openFile(filePath, FileSystem::FileOpenMode::Read);
 
-    success = mapFileHandle(fd, mode);
+    success = mapFileHandle(fd, FileSystem::FileOpenMode::Read, mapMode);
     closeFile(fd);
 }
 
-bool MappedFileData::mapFileHandle(PlatformFileHandle handle, MappedFileMode mode)
+#if HAVE(MMAP)
+
+bool MappedFileData::mapFileHandle(PlatformFileHandle handle, FileOpenMode openMode, MappedFileMode mapMode)
 {
     if (!isHandleValid(handle))
         return false;
@@ -324,7 +324,21 @@ bool MappedFileData::mapFileHandle(PlatformFileHandle handle, MappedFileMode mod
         return true;
     }
 
-    void* data = mmap(0, size, PROT_READ, MAP_FILE | (mode == MappedFileMode::Shared ? MAP_SHARED : MAP_PRIVATE), fd, 0);
+    int pageProtection = PROT_READ;
+    switch (openMode) {
+    case FileOpenMode::Read:
+        pageProtection = PROT_READ;
+        break;
+    case FileOpenMode::Write:
+        pageProtection = PROT_WRITE;
+        break;
+#if OS(DARWIN)
+    case FileOpenMode::EventsOnly:
+        ASSERT_NOT_REACHED();
+#endif
+    }
+
+    void* data = mmap(0, size, pageProtection, MAP_FILE | (mapMode == MappedFileMode::Shared ? MAP_SHARED : MAP_PRIVATE), fd, 0);
 
     if (data == MAP_FAILED) {
         return false;
index 805a0e4..0241a48 100644 (file)
@@ -84,6 +84,11 @@ enum class FileOpenMode {
 #endif
 };
 
+enum class FileAccessPermission : bool {
+    User,
+    All
+};
+
 enum class FileSeekOrigin {
     Beginning,
     Current,
@@ -131,7 +136,7 @@ WTF_EXPORT_PRIVATE void setMetadataURL(const String& path, const String& urlStri
 bool canExcludeFromBackup(); // Returns true if any file can ever be excluded from backup.
 bool excludeFromBackup(const String&); // Returns true if successful.
 
-WTF_EXPORT_PRIVATE Vector<String> listDirectory(const String& path, const String& filter = String());
+WTF_EXPORT_PRIVATE Vector<String> listDirectory(const String& path, const String& filter);
 
 WTF_EXPORT_PRIVATE CString fileSystemRepresentation(const String&);
 String stringFromFileSystemRepresentation(const char*);
@@ -140,7 +145,7 @@ inline bool isHandleValid(const PlatformFileHandle& handle) { return handle != i
 
 // Prefix is what the filename should be prefixed with, not the full path.
 WTF_EXPORT_PRIVATE String openTemporaryFile(const String& prefix, PlatformFileHandle&);
-WTF_EXPORT_PRIVATE PlatformFileHandle openFile(const String& path, FileOpenMode);
+WTF_EXPORT_PRIVATE PlatformFileHandle openFile(const String& path, FileOpenMode, FileAccessPermission = FileAccessPermission::All);
 WTF_EXPORT_PRIVATE void closeFile(PlatformFileHandle&);
 // Returns the resulting offset from the beginning of the file if successful, -1 otherwise.
 WTF_EXPORT_PRIVATE long long seekFile(PlatformFileHandle, long long offset, FileSeekOrigin);
@@ -206,6 +211,7 @@ public:
     MappedFileData(MappedFileData&&);
     WTF_EXPORT_PRIVATE MappedFileData(const String& filePath, MappedFileMode, bool& success);
     WTF_EXPORT_PRIVATE MappedFileData(PlatformFileHandle, MappedFileMode, bool& success);
+    WTF_EXPORT_PRIVATE MappedFileData(PlatformFileHandle, FileOpenMode, MappedFileMode, bool& success);
     WTF_EXPORT_PRIVATE ~MappedFileData();
     MappedFileData& operator=(MappedFileData&&);
 
@@ -216,15 +222,20 @@ public:
     void* leakHandle() { return std::exchange(m_fileData, nullptr); }
 
 private:
-    WTF_EXPORT_PRIVATE bool mapFileHandle(PlatformFileHandle, MappedFileMode);
+    WTF_EXPORT_PRIVATE bool mapFileHandle(PlatformFileHandle, FileOpenMode, MappedFileMode);
 
     void* m_fileData { nullptr };
     unsigned m_fileSize { 0 };
 };
 
-inline MappedFileData::MappedFileData(PlatformFileHandle handle, MappedFileMode mode, bool& success)
+inline MappedFileData::MappedFileData(PlatformFileHandle handle, MappedFileMode mapMode, bool& success)
+{
+    success = mapFileHandle(handle, FileOpenMode::Read, mapMode);
+}
+
+inline MappedFileData::MappedFileData(PlatformFileHandle handle, FileOpenMode openMode, MappedFileMode mapMode, bool& success)
 {
-    success = mapFileHandle(handle, mode);
+    success = mapFileHandle(handle, openMode, mapMode);
 }
 
 inline MappedFileData::MappedFileData(MappedFileData&& other)
index 86c04f9..d79a854 100644 (file)
@@ -338,7 +338,7 @@ String openTemporaryFile(const String& prefix, PlatformFileHandle& handle)
     return String::fromUTF8(tempPath.get());
 }
 
-PlatformFileHandle openFile(const String& path, FileOpenMode mode)
+PlatformFileHandle openFile(const String& path, FileOpenMode mode, FileAccessPermission permission)
 {
     auto filename = fileSystemRepresentation(path);
     if (!validRepresentation(filename))
@@ -351,8 +351,10 @@ PlatformFileHandle openFile(const String& path, FileOpenMode mode)
     else if (mode == FileOpenMode::Write) {
         if (g_file_test(filename.data(), static_cast<GFileTest>(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)))
             ioStream = adoptGRef(g_file_open_readwrite(file.get(), nullptr, nullptr));
-        else
-            ioStream = adoptGRef(g_file_create_readwrite(file.get(), G_FILE_CREATE_NONE, nullptr, nullptr));
+        else {
+            GFileCreateFlags permissionFlag = (permission == FileAccessPermission::All) ? G_FILE_CREATE_NONE : G_FILE_CREATE_PRIVATE;
+            ioStream = adoptGRef(g_file_create_readwrite(file.get(), permissionFlag, nullptr, nullptr));
+        }
     }
 
     return ioStream.leakRef();
index 2783988..5660053 100644 (file)
@@ -79,7 +79,7 @@ bool deleteFile(const String& path)
     return unlinked;
 }
 
-PlatformFileHandle openFile(const String& path, FileOpenMode mode)
+PlatformFileHandle openFile(const String& path, FileOpenMode mode, FileAccessPermission permission)
 {
     CString fsRep = fileSystemRepresentation(path);
 
@@ -87,16 +87,27 @@ PlatformFileHandle openFile(const String& path, FileOpenMode mode)
         return invalidPlatformFileHandle;
 
     int platformFlag = 0;
-    if (mode == FileOpenMode::Read)
+    switch (mode) {
+    case FileOpenMode::Read:
         platformFlag |= O_RDONLY;
-    else if (mode == FileOpenMode::Write)
+        break;
+    case FileOpenMode::Write:
         platformFlag |= (O_WRONLY | O_CREAT | O_TRUNC);
+        break;
 #if OS(DARWIN)
-    else if (mode == FileOpenMode::EventsOnly)
+    case FileOpenMode::EventsOnly:
         platformFlag |= O_EVTONLY;
+        break;
 #endif
+    }
+
+    int permissionFlag = 0;
+    if (permission == FileAccessPermission::User)
+        permissionFlag |= (S_IRUSR | S_IWUSR);
+    else if (permission == FileAccessPermission::All)
+        permissionFlag |= (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
 
-    return open(fsRep.data(), platformFlag, 0666);
+    return open(fsRep.data(), platformFlag, permissionFlag);
 }
 
 void closeFile(PlatformFileHandle& handle)
index 9334ac0..a995220 100644 (file)
@@ -421,7 +421,7 @@ String openTemporaryFile(const String&, PlatformFileHandle& handle)
     return proposedPath;
 }
 
-PlatformFileHandle openFile(const String& path, FileOpenMode mode)
+PlatformFileHandle openFile(const String& path, FileOpenMode mode, FileAccessPermission)
 {
     DWORD desiredAccess = 0;
     DWORD creationDisposition = 0;
@@ -436,8 +436,6 @@ PlatformFileHandle openFile(const String& path, FileOpenMode mode)
         desiredAccess = GENERIC_WRITE;
         creationDisposition = CREATE_ALWAYS;
         break;
-    default:
-        ASSERT_NOT_REACHED();
     }
 
     String destination = path;
@@ -549,9 +547,14 @@ Vector<String> listDirectory(const String& directory, const String& filter)
     return entries;
 }
 
-bool getVolumeFreeSpace(const String&, uint64_t&)
+bool getVolumeFreeSpace(const String& path, uint64_t& freeSpace)
 {
-    return false;
+    ULARGE_INTEGER freeBytesAvailableToCaller;
+    if (!GetDiskFreeSpaceExW(path.wideCharacters().data(), &freeBytesAvailableToCaller, nullptr, nullptr))
+        return false;
+
+    freeSpace = freeBytesAvailableToCaller.QuadPart;
+    return true;
 }
 
 Optional<int32_t> getFileDeviceId(const CString& fsFile)
@@ -603,15 +606,7 @@ bool unmapViewOfFile(void* buffer, size_t)
     return UnmapViewOfFile(buffer);
 }
 
-MappedFileData::MappedFileData(const String& filePath, MappedFileMode mode, bool& success)
-{
-    auto file = CreateFile(filePath.wideCharacters().data(), GENERIC_READ, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
-
-    success = mapFileHandle(file, mode);
-    closeFile(file);
-}
-
-bool MappedFileData::mapFileHandle(PlatformFileHandle handle, MappedFileMode)
+bool MappedFileData::mapFileHandle(PlatformFileHandle handle, FileOpenMode openMode, MappedFileMode)
 {
     if (!isHandleValid(handle))
         return false;
@@ -625,11 +620,24 @@ bool MappedFileData::mapFileHandle(PlatformFileHandle handle, MappedFileMode)
         return true;
     }
 
-    auto mapping = CreateFileMapping(handle, nullptr, PAGE_READONLY, 0, 0, nullptr);
+    DWORD pageProtection = PAGE_READONLY;
+    DWORD desiredAccess = FILE_MAP_READ;
+    switch (openMode) {
+    case FileOpenMode::Read:
+        pageProtection = PAGE_READONLY;
+        desiredAccess = FILE_MAP_READ;
+        break;
+    case FileOpenMode::Write:
+        pageProtection = PAGE_READWRITE;
+        desiredAccess = FILE_MAP_WRITE;
+        break;
+    }
+
+    auto mapping = CreateFileMapping(handle, nullptr, pageProtection, 0, 0, nullptr);
     if (!mapping)
         return false;
 
-    m_fileData = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, size);
+    m_fileData = MapViewOfFile(mapping, desiredAccess, 0, 0, size);
     CloseHandle(mapping);
     if (!m_fileData)
         return false;
index 8d7d7ac..688fedd 100644 (file)
@@ -32,7 +32,7 @@ namespace WTF {
 
 PathWalker::PathWalker(const String& directory, const String& pattern)
 {
-    String path = directory + "\\" + pattern;
+    String path = makeString(directory, '\\', pattern);
     m_handle = ::FindFirstFileW(path.wideCharacters().data(), &m_data);
 }
 
index 808e7f2..57df8d5 100644 (file)
@@ -1,3 +1,23 @@
+2020-02-14  Christopher Reid  <chris.reid@sony.com>
+
+        [Win] Implement NetworkCache::Data by using FileSystem::MappedFileData
+        https://bugs.webkit.org/show_bug.cgi?id=197684
+
+        Reviewed by Fujii Hironori.
+
+        * NetworkProcess/NetworkProcess.cpp:
+        Ensure that the CacheStorage directory is actually being created.
+
+        * NetworkProcess/cache/NetworkCacheData.cpp:
+        * NetworkProcess/cache/NetworkCacheData.h:
+        * NetworkProcess/cache/NetworkCacheDataCocoa.mm:
+        * NetworkProcess/cache/NetworkCacheDataSoup.cpp:
+        * NetworkProcess/cache/NetworkCacheFileSystem.cpp:
+        Use more FileSystem functionality to share code across platforms.
+
+        * NetworkProcess/cache/NetworkCacheDataCurl.cpp:
+        Use Optional<Vector> for m_buffer since we need to differentiate isEmpty and isNull.
+
 2020-02-14  Yusuke Suzuki  <ysuzuki@apple.com>
 
         NetworkLoadMetrics should be shared by multiple ResourceResponse instances
index 24fc5e4..422ce9e 100644 (file)
@@ -453,8 +453,11 @@ void NetworkProcess::addSessionStorageQuotaManager(PAL::SessionID sessionID, uin
     auto isNewEntry = m_sessionStorageQuotaManagers.ensure(sessionID, [defaultQuota, defaultThirdPartyQuota, &cacheRootPath] {
         return makeUnique<SessionStorageQuotaManager>(cacheRootPath, defaultQuota, defaultThirdPartyQuota);
     }).isNewEntry;
-    if (isNewEntry)
+    if (isNewEntry) {
         SandboxExtension::consumePermanently(cacheRootPathHandle);
+        if (!cacheRootPath.isEmpty())
+            postStorageTask(createCrossThreadTask(*this, &NetworkProcess::ensurePathExists, cacheRootPath));
+    }
 }
 
 void NetworkProcess::removeSessionStorageQuotaManager(PAL::SessionID sessionID)
index 75aa905..3e85c87 100644 (file)
@@ -28,7 +28,6 @@
 
 #include <fcntl.h>
 #include <wtf/CryptographicallyRandomNumber.h>
-#include <wtf/FileSystem.h>
 
 #if !OS(WINDOWS)
 #include <sys/mman.h>
 namespace WebKit {
 namespace NetworkCache {
 
-#if !OS(WINDOWS)
 Data Data::mapToFile(const String& path) const
 {
-    int fd = open(FileSystem::fileSystemRepresentation(path).data(), O_CREAT | O_EXCL | O_RDWR , S_IRUSR | S_IWUSR);
-    if (fd < 0)
-        return { };
-
-    if (ftruncate(fd, m_size) < 0) {
-        close(fd);
+    auto handle = FileSystem::openFile(path, FileSystem::FileOpenMode::Write, FileSystem::FileAccessPermission::User);
+    if (!FileSystem::truncateFile(handle, m_size)) {
+        FileSystem::closeFile(handle);
         return { };
     }
     
     FileSystem::makeSafeToUseMemoryMapForPath(path);
-
-    void* map = mmap(nullptr, m_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
-    if (map == MAP_FAILED) {
-        close(fd);
+    bool success;
+    FileSystem::MappedFileData mappedFile(handle, FileSystem::FileOpenMode::Write, FileSystem::MappedFileMode::Shared, success);
+    if (!success) {
+        FileSystem::closeFile(handle);
         return { };
     }
 
+    void* map = const_cast<void*>(mappedFile.data());
     uint8_t* mapData = static_cast<uint8_t*>(map);
     apply([&mapData](const uint8_t* bytes, size_t bytesSize) {
         memcpy(mapData, bytes, bytesSize);
@@ -66,52 +62,23 @@ Data Data::mapToFile(const String& path) const
         return true;
     });
 
+#if OS(WINDOWS)
+    DWORD oldProtection;
+    VirtualProtect(map, m_size, FILE_MAP_READ, &oldProtection);
+    FlushViewOfFile(map, m_size);
+#else
     // Drop the write permission.
     mprotect(map, m_size, PROT_READ);
 
     // Flush (asynchronously) to file, turning this into clean memory.
     msync(map, m_size, MS_ASYNC);
-
-    return Data::adoptMap(map, m_size, fd);
-}
-#else
-Data Data::mapToFile(const String& path) const
-{
-    auto file = FileSystem::openFile(path, FileSystem::FileOpenMode::Write);
-    if (!FileSystem::isHandleValid(file))
-        return { };
-    if (FileSystem::writeToFile(file, reinterpret_cast<const char*>(data()), size()) < 0)
-        return { };
-    return Data(Vector<uint8_t>(m_buffer));
-}
 #endif
 
-#if !OS(WINDOWS)
-Data mapFile(const char* path)
-{
-    int fd = open(path, O_RDONLY, 0);
-    if (fd < 0)
-        return { };
-    struct stat stat;
-    if (fstat(fd, &stat) < 0) {
-        close(fd);
-        return { };
-    }
-    size_t size = stat.st_size;
-    if (!size) {
-        close(fd);
-        return Data::empty();
-    }
-
-    return adoptAndMapFile(fd, 0, size);
+    return Data::adoptMap(WTFMove(mappedFile), handle);
 }
-#endif
 
-Data mapFile(const String& path)
+Data mapFile(const char* path)
 {
-#if !OS(WINDOWS)
-    return mapFile(FileSystem::fileSystemRepresentation(path).data());
-#else
     auto file = FileSystem::openFile(path, FileSystem::FileOpenMode::Read);
     if (!FileSystem::isHandleValid(file))
         return { };
@@ -119,31 +86,28 @@ Data mapFile(const String& path)
     if (!FileSystem::getFileSize(file, size))
         return { };
     return adoptAndMapFile(file, 0, size);
-#endif
 }
 
-#if !OS(WINDOWS)
-Data adoptAndMapFile(int fd, size_t offset, size_t size)
+Data mapFile(const String& path)
+{
+    return mapFile(FileSystem::fileSystemRepresentation(path).data());
+}
+
+Data adoptAndMapFile(FileSystem::PlatformFileHandle handle, size_t offset, size_t size)
 {
     if (!size) {
-        close(fd);
+        FileSystem::closeFile(handle);
         return Data::empty();
     }
-
-    void* map = mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, offset);
-    if (map == MAP_FAILED) {
-        close(fd);
+    bool success;
+    FileSystem::MappedFileData mappedFile(handle, FileSystem::FileOpenMode::Read, FileSystem::MappedFileMode::Private, success);
+    if (!success) {
+        FileSystem::closeFile(handle);
         return { };
     }
 
-    return Data::adoptMap(map, size, fd);
+    return Data::adoptMap(WTFMove(mappedFile), handle);
 }
-#else
-Data adoptAndMapFile(FileSystem::PlatformFileHandle file, size_t offset, size_t size)
-{
-    return Data(file, offset, size);
-}
-#endif
 
 SHA1::Digest computeSHA1(const Data& data, const Salt& salt)
 {
@@ -179,40 +143,25 @@ static Salt makeSalt()
 
 Optional<Salt> readOrMakeSalt(const String& path)
 {
-#if !OS(WINDOWS)
-    auto cpath = FileSystem::fileSystemRepresentation(path);
-    auto fd = open(cpath.data(), O_RDONLY, 0);
-    Salt salt;
-    auto bytesRead = read(fd, salt.data(), salt.size());
-    close(fd);
-    if (bytesRead != static_cast<ssize_t>(salt.size())) {
-        salt = makeSalt();
-
-        unlink(cpath.data());
-        fd = open(cpath.data(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
-        bool success = write(fd, salt.data(), salt.size()) == static_cast<ssize_t>(salt.size());
-        close(fd);
-        if (!success)
+    if (fileExists(path)) {
+        auto file = FileSystem::openFile(path, FileSystem::FileOpenMode::Read);
+        Salt salt;
+        auto bytesRead = FileSystem::readFromFile(file, reinterpret_cast<char*>(salt.data()), salt.size());
+        FileSystem::closeFile(file);
+        if (bytesRead != salt.size())
             return { };
+
+        return salt;
     }
-    return salt;
-#else
-    auto file = FileSystem::openFile(path, FileSystem::FileOpenMode::Read);
-    Salt salt;
-    auto bytesRead = FileSystem::readFromFile(file, reinterpret_cast<char*>(salt.data()), salt.size());
+
+    Salt salt = makeSalt();
+    auto file = FileSystem::openFile(path, FileSystem::FileOpenMode::Write, FileSystem::FileAccessPermission::User);
+    bool success = FileSystem::writeToFile(file, reinterpret_cast<char*>(salt.data()), salt.size()) == salt.size();
     FileSystem::closeFile(file);
-    if (bytesRead != salt.size()) {
-        salt = makeSalt();
+    if (!success)
+        return { };
 
-        FileSystem::deleteFile(path);
-        file = FileSystem::openFile(path, FileSystem::FileOpenMode::Write);
-        bool success = FileSystem::writeToFile(file, reinterpret_cast<char*>(salt.data()), salt.size()) == salt.size();
-        FileSystem::closeFile(file);
-        if (!success)
-            return { };
-    }
     return salt;
-#endif
 }
 
 } // namespace NetworkCache
index d78d98b..37b5966 100644 (file)
 #include <WebCore/GRefPtrSoup.h>
 #endif
 
+#if USE(CURL)
+#include <wtf/Box.h>
+#include <wtf/Variant.h>
+#endif
+
 namespace WebKit {
 
 class SharedMemory;
@@ -53,19 +58,16 @@ public:
     ~Data() { }
 
     static Data empty();
-#if !OS(WINDOWS)
-    static Data adoptMap(void* map, size_t, int fd);
-#endif
+    static Data adoptMap(FileSystem::MappedFileData&&, FileSystem::PlatformFileHandle);
 
 #if PLATFORM(COCOA)
     enum class Backing { Buffer, Map };
     Data(OSObjectPtr<dispatch_data_t>&&, Backing = Backing::Buffer);
 #endif
 #if USE(SOUP)
-    Data(GRefPtr<SoupBuffer>&&, int fd = -1);
-#elif OS(WINDOWS)
-    explicit Data(Vector<uint8_t>&&);
-    Data(FileSystem::PlatformFileHandle, size_t offset, size_t);
+    Data(GRefPtr<SoupBuffer>&&, FileSystem::PlatformFileHandle fd = FileSystem::invalidPlatformFileHandle);
+#elif USE(CURL)
+    Data(Variant<Vector<uint8_t>, FileSystem::MappedFileData>&&);
 #endif
     bool isNull() const;
     bool isEmpty() const { return !m_size; }
@@ -94,10 +96,10 @@ private:
 #endif
 #if USE(SOUP)
     mutable GRefPtr<SoupBuffer> m_buffer;
-    int m_fileDescriptor { -1 };
+    FileSystem::PlatformFileHandle m_fileDescriptor { FileSystem::invalidPlatformFileHandle };
 #endif
-#if OS(WINDOWS)
-    Vector<uint8_t> m_buffer;
+#if USE(CURL)
+    Box<Variant<Vector<uint8_t>, FileSystem::MappedFileData>> m_buffer;
 #endif
     mutable const uint8_t* m_data { nullptr };
     size_t m_size { 0 };
@@ -106,17 +108,8 @@ private:
 
 Data concatenate(const Data&, const Data&);
 bool bytesEqual(const Data&, const Data&);
-#if !OS(WINDOWS)
-Data adoptAndMapFile(int, size_t offset, size_t);
-#else
 Data adoptAndMapFile(FileSystem::PlatformFileHandle, size_t offset, size_t);
-#endif
-#if USE(GLIB) && !PLATFORM(WIN)
-Data adoptAndMapFile(GFileIOStream*, size_t offset, size_t);
-#endif
-#if !OS(WINDOWS)
 Data mapFile(const char* path);
-#endif
 Data mapFile(const String& path);
 
 using Salt = std::array<uint8_t, 8>;
index 6a39f88..cb4ac38 100644 (file)
@@ -92,11 +92,13 @@ Data concatenate(const Data& a, const Data& b)
     return { adoptOSObject(dispatch_data_create_concat(a.dispatchData(), b.dispatchData())) };
 }
 
-Data Data::adoptMap(void* map, size_t size, int fd)
+Data Data::adoptMap(FileSystem::MappedFileData&& mappedFile, FileSystem::PlatformFileHandle fd)
 {
+    size_t size = mappedFile.size();
+    void* map = mappedFile.leakHandle();
     ASSERT(map);
     ASSERT(map != MAP_FAILED);
-    close(fd);
+    FileSystem::closeFile(fd);
     auto bodyMap = adoptOSObject(dispatch_data_create(map, size, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), [map, size] {
         munmap(map, size);
     }));
index cf43156..192482b 100644 (file)
@@ -30,40 +30,42 @@ namespace WebKit {
 namespace NetworkCache {
 
 Data::Data(const uint8_t* data, size_t size)
+    : m_buffer(Box<Variant<Vector<uint8_t>, FileSystem::MappedFileData>>::create(Vector<uint8_t>(size)))
+    , m_size(size)
 {
-    m_buffer.resize(size);
-    m_size = size;
-    memcpy(m_buffer.data(), data, size);
+    memcpy(WTF::get<Vector<uint8_t>>(*m_buffer).data(), data, size);
 }
 
-Data::Data(FileSystem::PlatformFileHandle file, size_t offset, size_t size)
+Data::Data(Variant<Vector<uint8_t>, FileSystem::MappedFileData>&& data)
+    : m_buffer(Box<Variant<Vector<uint8_t>, FileSystem::MappedFileData>>::create(WTFMove(data)))
+    , m_isMap(WTF::holds_alternative<FileSystem::MappedFileData>(*m_buffer))
 {
-    m_buffer.resize(size);
-    m_size = size;
-    FileSystem::seekFile(file, offset, FileSystem::FileSeekOrigin::Beginning);
-    FileSystem::readFromFile(file, reinterpret_cast<char*>(m_buffer.data()), size);
-    FileSystem::closeFile(file);
-}
-
-Data::Data(Vector<uint8_t>&& buffer)
-    : m_buffer(WTFMove(buffer))
-{
-    m_size = m_buffer.size();
+    m_size = WTF::switchOn(*m_buffer,
+        [](const Vector<uint8_t>& buffer) -> size_t { return buffer.size(); },
+        [](const FileSystem::MappedFileData& mappedFile) -> size_t { return mappedFile.size(); }
+    );
 }
 
 Data Data::empty()
 {
-    return { };
+    Vector<uint8_t> buffer;
+    return { WTFMove(buffer) };
 }
 
 const uint8_t* Data::data() const
 {
-    return m_buffer.data();
+    if (!m_buffer)
+        return nullptr;
+
+    return WTF::switchOn(*m_buffer,
+        [](const Vector<uint8_t>& buffer) -> const uint8_t* { return buffer.data(); },
+        [](const FileSystem::MappedFileData& mappedFile) -> const uint8_t* { return static_cast<const uint8_t*>(mappedFile.data()); }
+    );
 }
 
 bool Data::isNull() const
 {
-    return m_buffer.isEmpty();
+    return !m_buffer;
 }
 
 bool Data::apply(const Function<bool(const uint8_t*, size_t)>& applier) const
@@ -71,21 +73,37 @@ bool Data::apply(const Function<bool(const uint8_t*, size_t)>& applier) const
     if (isEmpty())
         return false;
 
-    return applier(reinterpret_cast<const uint8_t*>(m_buffer.data()), m_buffer.size());
+    return applier(reinterpret_cast<const uint8_t*>(data()), size());
 }
 
 Data Data::subrange(size_t offset, size_t size) const
 {
-    return { m_buffer.data() + offset, size };
+    if (!m_buffer)
+        return { };
+
+    return { data() + offset, size };
 }
 
 Data concatenate(const Data& a, const Data& b)
 {
+    if (a.isNull())
+        return b;
+    if (b.isNull())
+        return a;
+
     Vector<uint8_t> buffer(a.size() + b.size());
     memcpy(buffer.data(), a.data(), a.size());
     memcpy(buffer.data() + a.size(), b.data(), b.size());
     return Data(WTFMove(buffer));
 }
 
+Data Data::adoptMap(FileSystem::MappedFileData&& mappedFile, FileSystem::PlatformFileHandle fd)
+{
+    ASSERT(mappedFile.data());
+    FileSystem::closeFile(fd);
+
+    return { WTFMove(mappedFile) };
+}
+
 } // namespace NetworkCache
 } // namespace WebKit
index 515c09e..d3b79e0 100644 (file)
@@ -48,11 +48,11 @@ Data::Data(const uint8_t* data, size_t size)
     m_buffer = adoptGRef(soup_buffer_new_with_owner(copiedData, size, copiedData, fastFree));
 }
 
-Data::Data(GRefPtr<SoupBuffer>&& buffer, int fd)
+Data::Data(GRefPtr<SoupBuffer>&& buffer, FileSystem::PlatformFileHandle fd)
     : m_buffer(buffer)
     , m_fileDescriptor(fd)
     , m_size(buffer ? buffer->length : 0)
-    , m_isMap(m_size && fd != -1)
+    , m_isMap(m_size && FileSystem::isHandleValid(fd))
 {
 }
 
@@ -108,12 +108,12 @@ struct MapWrapper {
     ~MapWrapper()
     {
         munmap(map, size);
-        close(fileDescriptor);
+        FileSystem::closeFile(fileDescriptor);
     }
 
     void* map;
     size_t size;
-    int fileDescriptor;
+    FileSystem::PlatformFileHandle fileDescriptor;
 };
 
 static void deleteMapWrapper(MapWrapper* wrapper)
@@ -121,8 +121,10 @@ static void deleteMapWrapper(MapWrapper* wrapper)
     delete wrapper;
 }
 
-Data Data::adoptMap(void* map, size_t size, int fd)
+Data Data::adoptMap(FileSystem::MappedFileData&& mappedFile, FileSystem::PlatformFileHandle fd)
 {
+    size_t size = mappedFile.size();
+    void* map = mappedFile.leakHandle();
     ASSERT(map);
     ASSERT(map != MAP_FAILED);
     MapWrapper* wrapper = new MapWrapper { map, size, fd };
@@ -130,21 +132,14 @@ Data Data::adoptMap(void* map, size_t size, int fd)
     return { WTFMove(buffer), fd };
 }
 
-#if USE(GLIB) && !PLATFORM(WIN)
-Data adoptAndMapFile(GFileIOStream* stream, size_t offset, size_t size)
-{
-    GInputStream* inputStream = g_io_stream_get_input_stream(G_IO_STREAM(stream));
-    int fd = g_file_descriptor_based_get_fd(G_FILE_DESCRIPTOR_BASED(inputStream));
-    return adoptAndMapFile(fd, offset, size);
-}
-#endif
-
 RefPtr<SharedMemory> Data::tryCreateSharedMemory() const
 {
     if (isNull() || !isMap())
         return nullptr;
 
-    return SharedMemory::wrapMap(const_cast<char*>(m_buffer->data), m_buffer->length, m_fileDescriptor);
+    GInputStream* inputStream = g_io_stream_get_input_stream(G_IO_STREAM(m_fileDescriptor));
+    int fd = g_file_descriptor_based_get_fd(G_FILE_DESCRIPTOR_BASED(inputStream));
+    return SharedMemory::wrapMap(const_cast<char*>(m_buffer->data), m_buffer->length, fd);
 }
 
 } // namespace NetworkCache
index be84371..7a0ec5e 100644 (file)
 namespace WebKit {
 namespace NetworkCache {
 
-#if !OS(WINDOWS)
-static DirectoryEntryType directoryEntryType(uint8_t dtype)
-{
-    switch (dtype) {
-    case DT_DIR:
-        return DirectoryEntryType::Directory;
-    case DT_REG:
-        return DirectoryEntryType::File;
-    default:
-        ASSERT_NOT_REACHED();
-        return DirectoryEntryType::File;
-    }
-    return DirectoryEntryType::File;
-}
-#endif
-
 void traverseDirectory(const String& path, const Function<void (const String&, DirectoryEntryType)>& function)
 {
-#if !OS(WINDOWS)
-    DIR* dir = opendir(FileSystem::fileSystemRepresentation(path).data());
-    if (!dir)
-        return;
-    dirent* dp;
-    while ((dp = readdir(dir))) {
-        if (dp->d_type != DT_DIR && dp->d_type != DT_REG)
-            continue;
-        const char* name = dp->d_name;
-        if (!strcmp(name, ".") || !strcmp(name, ".."))
-            continue;
-        auto nameString = String::fromUTF8(name);
-        if (nameString.isNull())
-            continue;
-        function(nameString, directoryEntryType(dp->d_type));
-    }
-    closedir(dir);
-#else
-    auto entries = FileSystem::listDirectory(path);
+    auto entries = FileSystem::listDirectory(path, "*"_s);
     for (auto& entry : entries) {
         auto type = FileSystem::fileIsDirectory(entry, FileSystem::ShouldFollowSymbolicLinks::No) ? DirectoryEntryType::Directory : DirectoryEntryType::File;
-        function(entry, type);
+        function(FileSystem::pathGetFileName(entry), type);
     }
-#endif
 }
 
 void deleteDirectoryRecursively(const String& path)