Rename AtomicString to AtomString
[WebKit-https.git] / Source / WebCore / loader / appcache / ApplicationCacheStorage.cpp
index 284ab6d..da62d66 100644 (file)
 #include "ApplicationCacheGroup.h"
 #include "ApplicationCacheHost.h"
 #include "ApplicationCacheResource.h"
-#include "FileSystem.h"
 #include "SQLiteDatabaseTracker.h"
 #include "SQLiteStatement.h"
 #include "SQLiteTransaction.h"
 #include "SecurityOrigin.h"
 #include "SecurityOriginData.h"
-#include "URL.h"
-#include "UUID.h"
-#include <wtf/NeverDestroyed.h>
+#include <wtf/FileSystem.h>
 #include <wtf/StdLibExtras.h>
-#include <wtf/StringExtras.h>
+#include <wtf/URL.h>
+#include <wtf/UUID.h>
 #include <wtf/text/CString.h>
 #include <wtf/text/StringBuilder.h>
 
@@ -86,15 +84,10 @@ private:
 
 static unsigned urlHostHash(const URL& url)
 {
-    unsigned hostStart = url.hostStart();
-    unsigned hostEnd = url.hostEnd();
-
-    const String& urlString = url.string();
-
-    if (urlString.is8Bit())
-        return AlreadyHashed::avoidDeletedValue(StringHasher::computeHashAndMaskTop8Bits(urlString.characters8() + hostStart, hostEnd - hostStart));
-    
-    return AlreadyHashed::avoidDeletedValue(StringHasher::computeHashAndMaskTop8Bits(urlString.characters16() + hostStart, hostEnd - hostStart));
+    StringView host = url.host();
+    if (host.is8Bit())
+        return AlreadyHashed::avoidDeletedValue(StringHasher::computeHashAndMaskTop8Bits(host.characters8(), host.length()));
+    return AlreadyHashed::avoidDeletedValue(StringHasher::computeHashAndMaskTop8Bits(host.characters16(), host.length()));
 }
 
 ApplicationCacheGroup* ApplicationCacheStorage::loadCacheGroup(const URL& manifestURL)
@@ -225,7 +218,7 @@ ApplicationCacheGroup* ApplicationCacheStorage::cacheGroupForURL(const URL& url)
     
     int result;
     while ((result = statement.step()) == SQLITE_ROW) {
-        URL manifestURL = URL(ParsedURLString, statement.getColumnText(1));
+        URL manifestURL = URL({ }, statement.getColumnText(1));
 
         if (m_cachesInMemory.contains(manifestURL))
             continue;
@@ -292,7 +285,7 @@ ApplicationCacheGroup* ApplicationCacheStorage::fallbackCacheGroupForURL(const U
     
     int result;
     while ((result = statement.step()) == SQLITE_ROW) {
-        URL manifestURL = URL(ParsedURLString, statement.getColumnText(1));
+        URL manifestURL = URL({ }, statement.getColumnText(1));
 
         if (m_cachesInMemory.contains(manifestURL))
             continue;
@@ -358,11 +351,6 @@ void ApplicationCacheStorage::cacheGroupMadeObsolete(ApplicationCacheGroup& grou
     m_cacheHostSet.remove(urlHostHash(group.manifestURL()));
 }
 
-const String& ApplicationCacheStorage::cacheDirectory() const
-{
-    return m_cacheDirectory;
-}
-
 void ApplicationCacheStorage::setMaximumSize(int64_t size)
 {
     m_maximumSize = size;
@@ -382,7 +370,7 @@ int64_t ApplicationCacheStorage::spaceNeeded(int64_t cacheToSave)
 {
     int64_t spaceNeeded = 0;
     long long fileSize = 0;
-    if (!getFileSize(m_cacheFile, fileSize))
+    if (!FileSystem::getFileSize(m_cacheFile, fileSize))
         return 0;
 
     int64_t currentSize = fileSize + flatFileAreaSize();
@@ -432,7 +420,7 @@ bool ApplicationCacheStorage::calculateQuotaForOrigin(const SecurityOrigin& orig
     if (statement.prepare() != SQLITE_OK)
         return false;
 
-    statement.bindText(1, SecurityOriginData::fromSecurityOrigin(origin).databaseIdentifier());
+    statement.bindText(1, origin.data().databaseIdentifier());
     int result = statement.step();
 
     // Return the quota, or if it was null the default.
@@ -460,7 +448,7 @@ bool ApplicationCacheStorage::calculateUsageForOrigin(const SecurityOrigin* orig
     if (statement.prepare() != SQLITE_OK)
         return false;
 
-    statement.bindText(1, SecurityOriginData::fromSecurityOrigin(*origin).databaseIdentifier());
+    statement.bindText(1, origin->data().databaseIdentifier());
     int result = statement.step();
 
     if (result == SQLITE_ROW) {
@@ -503,7 +491,7 @@ bool ApplicationCacheStorage::calculateRemainingSizeForOriginExcludingCache(cons
     if (statement.prepare() != SQLITE_OK)
         return false;
 
-    statement.bindText(1, SecurityOriginData::fromSecurityOrigin(origin).databaseIdentifier());
+    statement.bindText(1, origin.data().databaseIdentifier());
     if (excludingCacheIdentifier != 0)
         statement.bindInt64(2, excludingCacheIdentifier);
     int result = statement.step();
@@ -539,7 +527,7 @@ bool ApplicationCacheStorage::storeUpdatedQuotaForOrigin(const SecurityOrigin* o
         return false;
 
     updateStatement.bindInt64(1, quota);
-    updateStatement.bindText(2, SecurityOriginData::fromSecurityOrigin(*origin).databaseIdentifier());
+    updateStatement.bindText(2, origin->data().databaseIdentifier());
 
     return executeStatement(updateStatement);
 }
@@ -601,11 +589,11 @@ void ApplicationCacheStorage::openDatabase(bool createIfDoesNotExist)
     if (m_cacheDirectory.isNull())
         return;
 
-    m_cacheFile = pathByAppendingComponent(m_cacheDirectory, "ApplicationCache.db");
-    if (!createIfDoesNotExist && !fileExists(m_cacheFile))
+    m_cacheFile = FileSystem::pathByAppendingComponent(m_cacheDirectory, "ApplicationCache.db");
+    if (!createIfDoesNotExist && !FileSystem::fileExists(m_cacheFile))
         return;
 
-    makeAllDirectories(m_cacheDirectory);
+    FileSystem::makeAllDirectories(m_cacheDirectory);
     m_database.open(m_cacheFile);
     
     if (!m_database.isOpen())
@@ -688,7 +676,7 @@ bool ApplicationCacheStorage::store(ApplicationCacheGroup* group, GroupStorageID
 
     statement.bindInt64(1, urlHostHash(group->manifestURL()));
     statement.bindText(2, group->manifestURL());
-    statement.bindText(3, SecurityOriginData::fromSecurityOrigin(group->origin()).databaseIdentifier());
+    statement.bindText(3, group->origin().data().databaseIdentifier());
 
     if (!executeStatement(statement))
         return false;
@@ -800,17 +788,17 @@ bool ApplicationCacheStorage::store(ApplicationCacheResource* resource, unsigned
 
     String fullPath;
     if (!resource->path().isEmpty())
-        dataStatement.bindText(2, pathGetFileName(resource->path()));
+        dataStatement.bindText(2, FileSystem::pathGetFileName(resource->path()));
     else if (shouldStoreResourceAsFlatFile(resource)) {
         // First, check to see if creating the flat file would violate the maximum total quota. We don't need
         // to check the per-origin quota here, as it was already checked in storeNewestCache().
-        if (m_database.totalSize() + flatFileAreaSize() + resource->data().size() > m_maximumSize) {
+        if (m_database.totalSize() + flatFileAreaSize() + static_cast<int64_t>(resource->data().size()) > m_maximumSize) {
             m_isMaximumSizeReached = true;
             return false;
         }
         
-        String flatFileDirectory = pathByAppendingComponent(m_cacheDirectory, m_flatFileSubdirectoryName);
-        makeAllDirectories(flatFileDirectory);
+        String flatFileDirectory = FileSystem::pathByAppendingComponent(m_cacheDirectory, m_flatFileSubdirectoryName);
+        FileSystem::makeAllDirectories(flatFileDirectory);
 
         String extension;
         
@@ -823,7 +811,7 @@ bool ApplicationCacheStorage::store(ApplicationCacheResource* resource, unsigned
         if (!writeDataToUniqueFileInDirectory(resource->data(), flatFileDirectory, path, extension))
             return false;
         
-        fullPath = pathByAppendingComponent(flatFileDirectory, path);
+        fullPath = FileSystem::pathByAppendingComponent(flatFileDirectory, path);
         resource->setPath(fullPath);
         dataStatement.bindText(2, path);
     } else {
@@ -834,7 +822,7 @@ bool ApplicationCacheStorage::store(ApplicationCacheResource* resource, unsigned
     if (!dataStatement.executeCommand()) {
         // Clean up the file which we may have written to:
         if (!fullPath.isEmpty())
-            deleteFile(fullPath);
+            FileSystem::deleteFile(fullPath);
 
         return false;
     }
@@ -959,7 +947,7 @@ bool ApplicationCacheStorage::ensureOriginRecord(const SecurityOrigin* origin)
     if (insertOriginStatement.prepare() != SQLITE_OK)
         return false;
 
-    insertOriginStatement.bindText(1, SecurityOriginData::fromSecurityOrigin(*origin).databaseIdentifier());
+    insertOriginStatement.bindText(1, origin->data().databaseIdentifier());
     insertOriginStatement.bindInt64(2, m_defaultOriginQuota);
     if (!executeStatement(insertOriginStatement))
         return false;
@@ -1073,7 +1061,7 @@ static inline void parseHeader(const CharacterType* header, unsigned headerLengt
 
     // Save memory by putting the header names into atomic strings so each is stored only once,
     // even though the setHTTPHeaderField function does not require an atomic string.
-    AtomicString headerName { header, colonPosition };
+    AtomString headerName { header, colonPosition };
     String headerValue { header + colonPosition + 1, headerLength - colonPosition - 1 };
 
     response.setHTTPHeaderField(headerName, headerValue);
@@ -1117,11 +1105,11 @@ RefPtr<ApplicationCache> ApplicationCacheStorage::loadCache(unsigned storageID)
 
     auto cache = ApplicationCache::create();
 
-    String flatFileDirectory = pathByAppendingComponent(m_cacheDirectory, m_flatFileSubdirectoryName);
+    String flatFileDirectory = FileSystem::pathByAppendingComponent(m_cacheDirectory, m_flatFileSubdirectoryName);
 
     int result;
     while ((result = cacheStatement.step()) == SQLITE_ROW) {
-        URL url(ParsedURLString, cacheStatement.getColumnText(0));
+        URL url({ }, cacheStatement.getColumnText(0));
         
         int httpStatusCode = cacheStatement.getColumnInt(1);
 
@@ -1137,8 +1125,8 @@ RefPtr<ApplicationCache> ApplicationCacheStorage::loadCache(unsigned storageID)
         if (path.isEmpty())
             size = data->size();
         else {
-            path = pathByAppendingComponent(flatFileDirectory, path);
-            getFileSize(path, size);
+            path = FileSystem::pathByAppendingComponent(flatFileDirectory, path);
+            FileSystem::getFileSize(path, size);
         }
         
         String mimeType = cacheStatement.getColumnText(3);
@@ -1174,7 +1162,7 @@ RefPtr<ApplicationCache> ApplicationCacheStorage::loadCache(unsigned storageID)
     
     Vector<URL> whitelist;
     while ((result = whitelistStatement.step()) == SQLITE_ROW) 
-        whitelist.append(URL(ParsedURLString, whitelistStatement.getColumnText(0)));
+        whitelist.append(URL({ }, whitelistStatement.getColumnText(0)));
 
     if (result != SQLITE_DONE)
         LOG_ERROR("Could not load cache online whitelist, error \"%s\"", m_database.lastErrorMsg());
@@ -1204,7 +1192,7 @@ RefPtr<ApplicationCache> ApplicationCacheStorage::loadCache(unsigned storageID)
     
     FallbackURLVector fallbackURLs;
     while ((result = fallbackStatement.step()) == SQLITE_ROW) 
-        fallbackURLs.append(std::make_pair(URL(ParsedURLString, fallbackStatement.getColumnText(0)), URL(ParsedURLString, fallbackStatement.getColumnText(1))));
+        fallbackURLs.append(std::make_pair(URL({ }, fallbackStatement.getColumnText(0)), URL({ }, fallbackStatement.getColumnText(1))));
 
     if (result != SQLITE_DONE)
         LOG_ERROR("Could not load fallback URLs, error \"%s\"", m_database.lastErrorMsg());
@@ -1213,7 +1201,7 @@ RefPtr<ApplicationCache> ApplicationCacheStorage::loadCache(unsigned storageID)
     
     cache->setStorageID(storageID);
 
-    return WTFMove(cache);
+    return cache;
 }    
     
 void ApplicationCacheStorage::remove(ApplicationCache* cache)
@@ -1286,8 +1274,8 @@ void ApplicationCacheStorage::deleteTables()
     
 bool ApplicationCacheStorage::shouldStoreResourceAsFlatFile(ApplicationCacheResource* resource)
 {
-    return resource->response().mimeType().startsWith("audio/", false) 
-        || resource->response().mimeType().startsWith("video/", false);
+    auto& type = resource->response().mimeType();
+    return startsWithLettersIgnoringASCIICase(type, "audio/") || startsWithLettersIgnoringASCIICase(type, "video/");
 }
     
 bool ApplicationCacheStorage::writeDataToUniqueFileInDirectory(SharedBuffer& data, const String& directory, String& path, const String& fileExtension)
@@ -1295,77 +1283,49 @@ bool ApplicationCacheStorage::writeDataToUniqueFileInDirectory(SharedBuffer& dat
     String fullPath;
     
     do {
-        path = encodeForFileName(createCanonicalUUIDString()) + fileExtension;
+        path = FileSystem::encodeForFileName(createCanonicalUUIDString()) + fileExtension;
         // Guard against the above function being called on a platform which does not implement
         // createCanonicalUUIDString().
         ASSERT(!path.isEmpty());
         if (path.isEmpty())
             return false;
         
-        fullPath = pathByAppendingComponent(directory, path);
-    } while (directoryName(fullPath) != directory || fileExists(fullPath));
+        fullPath = FileSystem::pathByAppendingComponent(directory, path);
+    } while (FileSystem::directoryName(fullPath) != directory || FileSystem::fileExists(fullPath));
     
-    PlatformFileHandle handle = openFile(fullPath, OpenForWrite);
+    FileSystem::PlatformFileHandle handle = FileSystem::openFile(fullPath, FileSystem::FileOpenMode::Write);
     if (!handle)
         return false;
     
-    int64_t writtenBytes = writeToFile(handle, data.data(), data.size());
-    closeFile(handle);
+    int64_t writtenBytes = FileSystem::writeToFile(handle, data.data(), data.size());
+    FileSystem::closeFile(handle);
     
     if (writtenBytes != static_cast<int64_t>(data.size())) {
-        deleteFile(fullPath);
+        FileSystem::deleteFile(fullPath);
         return false;
     }
     
     return true;
 }
 
-bool ApplicationCacheStorage::getManifestURLs(Vector<URL>* urls)
+Optional<Vector<URL>> ApplicationCacheStorage::manifestURLs()
 {
     SQLiteTransactionInProgressAutoCounter transactionCounter;
 
-    ASSERT(urls);
     openDatabase(false);
     if (!m_database.isOpen())
-        return false;
+        return WTF::nullopt;
 
     SQLiteStatement selectURLs(m_database, "SELECT manifestURL FROM CacheGroups");
 
     if (selectURLs.prepare() != SQLITE_OK)
-        return false;
+        return WTF::nullopt;
 
+    Vector<URL> urls;
     while (selectURLs.step() == SQLITE_ROW)
-        urls->append(URL(ParsedURLString, selectURLs.getColumnText(0)));
-
-    return true;
-}
-
-bool ApplicationCacheStorage::cacheGroupSize(const String& manifestURL, int64_t* size)
-{
-    SQLiteTransactionInProgressAutoCounter transactionCounter;
-
-    ASSERT(size);
-    openDatabase(false);
-    if (!m_database.isOpen())
-        return false;
-
-    SQLiteStatement statement(m_database, "SELECT sum(Caches.size) FROM Caches INNER JOIN CacheGroups ON Caches.cacheGroup=CacheGroups.id WHERE CacheGroups.manifestURL=?");
-    if (statement.prepare() != SQLITE_OK)
-        return false;
-
-    statement.bindText(1, manifestURL);
-
-    int result = statement.step();
-    if (result == SQLITE_DONE)
-        return false;
-
-    if (result != SQLITE_ROW) {
-        LOG_ERROR("Could not get the size of the cache group, error \"%s\"", m_database.lastErrorMsg());
-        return false;
-    }
+        urls.append(URL({ }, selectURLs.getColumnText(0)));
 
-    *size = statement.getColumnInt64(0);
-    return true;
+    return urls;
 }
 
 bool ApplicationCacheStorage::deleteCacheGroupRecord(const String& manifestURL)
@@ -1405,8 +1365,7 @@ bool ApplicationCacheStorage::deleteCacheGroup(const String& manifestURL)
     SQLiteTransaction deleteTransaction(m_database);
 
     // Check to see if the group is in memory.
-    auto* group = m_cachesInMemory.get(manifestURL);
-    if (group)
+    if (auto* group = m_cachesInMemory.get(manifestURL))
         cacheGroupMadeObsolete(*group);
     else {
         // The cache group is not in memory, so remove it from the disk.
@@ -1467,15 +1426,15 @@ void ApplicationCacheStorage::checkForDeletedResources()
         if (path.isEmpty())
             continue;
         
-        String flatFileDirectory = pathByAppendingComponent(m_cacheDirectory, m_flatFileSubdirectoryName);
-        String fullPath = pathByAppendingComponent(flatFileDirectory, path);
+        String flatFileDirectory = FileSystem::pathByAppendingComponent(m_cacheDirectory, m_flatFileSubdirectoryName);
+        String fullPath = FileSystem::pathByAppendingComponent(flatFileDirectory, path);
         
         // Don't exit the flatFileDirectory! This should only happen if the "path" entry contains a directory 
         // component, but protect against it regardless.
-        if (directoryName(fullPath) != flatFileDirectory)
+        if (FileSystem::directoryName(fullPath) != flatFileDirectory)
             continue;
         
-        deleteFile(fullPath);
+        FileSystem::deleteFile(fullPath);
     } while (selectPaths.step() == SQLITE_ROW);
     
     executeSQLCommand("DELETE FROM DeletedCacheResources");
@@ -1495,12 +1454,12 @@ long long ApplicationCacheStorage::flatFileAreaSize()
     }
 
     long long totalSize = 0;
-    String flatFileDirectory = pathByAppendingComponent(m_cacheDirectory, m_flatFileSubdirectoryName);
+    String flatFileDirectory = FileSystem::pathByAppendingComponent(m_cacheDirectory, m_flatFileSubdirectoryName);
     while (selectPaths.step() == SQLITE_ROW) {
         String path = selectPaths.getColumnText(0);
-        String fullPath = pathByAppendingComponent(flatFileDirectory, path);
+        String fullPath = FileSystem::pathByAppendingComponent(flatFileDirectory, path);
         long long pathSize = 0;
-        if (!getFileSize(fullPath, pathSize))
+        if (!FileSystem::getFileSize(fullPath, pathSize))
             continue;
         totalSize += pathSize;
     }
@@ -1508,15 +1467,19 @@ long long ApplicationCacheStorage::flatFileAreaSize()
     return totalSize;
 }
 
-void ApplicationCacheStorage::getOriginsWithCache(HashSet<RefPtr<SecurityOrigin>>& origins)
+Vector<Ref<SecurityOrigin>> ApplicationCacheStorage::originsWithCache()
 {
-    Vector<URL> urls;
-    getManifestURLs(&urls);
+    auto urls = manifestURLs();
+    if (!urls)
+        return { };
 
     // Multiple manifest URLs might share the same SecurityOrigin, so we might be creating extra, wasted origins here.
     // The current schema doesn't allow for a more efficient way of building this list.
-    for (auto& url : urls)
-        origins.add(SecurityOrigin::create(url));
+    Vector<Ref<SecurityOrigin>> origins;
+    origins.reserveInitialCapacity(urls->size());
+    for (auto& url : *urls)
+        origins.uncheckedAppend(SecurityOrigin::create(url));
+    return origins;
 }
 
 void ApplicationCacheStorage::deleteAllEntries()
@@ -1527,26 +1490,24 @@ void ApplicationCacheStorage::deleteAllEntries()
 
 void ApplicationCacheStorage::deleteAllCaches()
 {
-    HashSet<RefPtr<SecurityOrigin>> origins;
-
-    getOriginsWithCache(origins);
+    auto origins = originsWithCache();
     for (auto& origin : origins)
-        deleteCacheForOrigin(*origin);
+        deleteCacheForOrigin(origin);
 
     vacuumDatabaseFile();
 }
 
 void ApplicationCacheStorage::deleteCacheForOrigin(const SecurityOrigin& securityOrigin)
 {
-    Vector<URL> urls;
-    if (!getManifestURLs(&urls)) {
+    auto urls = manifestURLs();
+    if (!urls) {
         LOG_ERROR("Failed to retrieve ApplicationCache manifest URLs");
         return;
     }
 
     URL originURL(URL(), securityOrigin.toString());
 
-    for (const auto& url : urls) {
+    for (const auto& url : *urls) {
         if (!protocolHostAndPortAreEqual(url, originURL))
             continue;
 
@@ -1567,15 +1528,7 @@ int64_t ApplicationCacheStorage::diskUsageForOrigin(const SecurityOrigin& securi
 ApplicationCacheStorage::ApplicationCacheStorage(const String& cacheDirectory, const String& flatFileSubdirectoryName)
     : m_cacheDirectory(cacheDirectory)
     , m_flatFileSubdirectoryName(flatFileSubdirectoryName)
-    , m_maximumSize(ApplicationCacheStorage::noQuota())
-    , m_isMaximumSizeReached(false)
-    , m_defaultOriginQuota(ApplicationCacheStorage::noQuota())
 {
 }
 
-Ref<ApplicationCacheStorage> ApplicationCacheStorage::create(const String& cacheDirectory, const String& flatFileSubdirectoryName)
-{
-    return adoptRef(*new ApplicationCacheStorage(cacheDirectory, flatFileSubdirectoryName));
-}
-
-}
+} // namespace WebCore