Changeset 252839 in webkit


Ignore:
Timestamp:
Nov 23, 2019 7:03:26 PM (4 years ago)
Author:
commit-queue@webkit.org
Message:

Unreviewed, rolling out r252805.
https://bugs.webkit.org/show_bug.cgi?id=204553

Caused test failures and ASan crashes (Requested by ap on
#webkit).

Reverted changeset:

"Cross-thread version StorageQuotaManager"
https://bugs.webkit.org/show_bug.cgi?id=203971
https://trac.webkit.org/changeset/252805

Location:
trunk
Files:
2 added
36 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r252837 r252839  
     12019-11-23  Commit Queue  <commit-queue@webkit.org>
     2
     3        Unreviewed, rolling out r252805.
     4        https://bugs.webkit.org/show_bug.cgi?id=204553
     5
     6        Caused test failures and ASan crashes (Requested by ap on
     7        #webkit).
     8
     9        Reverted changeset:
     10
     11        "Cross-thread version StorageQuotaManager"
     12        https://bugs.webkit.org/show_bug.cgi?id=203971
     13        https://trac.webkit.org/changeset/252805
     14
    1152019-11-23  Zalan Bujtas  <zalan@apple.com>
    216
  • trunk/Source/WebCore/Headers.cmake

    r252805 r252839  
    13821382    storage/StorageNamespaceProvider.h
    13831383    storage/StorageQuotaManager.h
     1384    storage/StorageQuotaUser.h
    13841385    storage/StorageType.h
    13851386
  • trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.cpp

    r252805 r252839  
    4747namespace IDBServer {
    4848
    49 Ref<IDBServer> IDBServer::create(PAL::SessionID sessionID, StorageQuotaManagerSpaceRequester&& quotaManagerGetter)
     49Ref<IDBServer> IDBServer::create(PAL::SessionID sessionID, QuotaManagerGetter&& quotaManagerGetter)
    5050{
    5151    return adoptRef(*new IDBServer(sessionID, WTFMove(quotaManagerGetter)));
    5252}
    5353
    54 Ref<IDBServer> IDBServer::create(PAL::SessionID sessionID, const String& databaseDirectoryPath, StorageQuotaManagerSpaceRequester&& quotaManagerGetter)
     54Ref<IDBServer> IDBServer::create(PAL::SessionID sessionID, const String& databaseDirectoryPath, QuotaManagerGetter&& quotaManagerGetter)
    5555{
    5656    return adoptRef(*new IDBServer(sessionID, databaseDirectoryPath, WTFMove(quotaManagerGetter)));
    5757}
    5858
    59 IDBServer::IDBServer(PAL::SessionID sessionID, StorageQuotaManagerSpaceRequester&& spaceRequester)
     59IDBServer::IDBServer(PAL::SessionID sessionID, QuotaManagerGetter&& quotaManagerGetter)
    6060    : CrossThreadTaskHandler("IndexedDatabase Server", AutodrainedPoolForRunLoop::Use)
    6161    , m_sessionID(sessionID)
    62     , m_spaceRequester(WTFMove(spaceRequester))
    63 {
    64 }
    65 
    66 IDBServer::IDBServer(PAL::SessionID sessionID, const String& databaseDirectoryPath, StorageQuotaManagerSpaceRequester&& spaceRequester)
     62    , m_quotaManagerGetter(WTFMove(quotaManagerGetter))
     63{
     64}
     65
     66IDBServer::IDBServer(PAL::SessionID sessionID, const String& databaseDirectoryPath, QuotaManagerGetter&& quotaManagerGetter)
    6767    : CrossThreadTaskHandler("IndexedDatabase Server", AutodrainedPoolForRunLoop::Use)
    6868    , m_sessionID(sessionID)
    6969    , m_databaseDirectoryPath(databaseDirectoryPath)
    70     , m_spaceRequester(WTFMove(spaceRequester))
     70    , m_quotaManagerGetter(WTFMove(quotaManagerGetter))
    7171{
    7272    LOG(IndexedDB, "IDBServer created at path %s", databaseDirectoryPath.utf8().data());
     
    684684void IDBServer::didPerformCloseAndDeleteDatabases(uint64_t callbackID)
    685685{
     686    for (auto& user : m_quotaUsers.values())
     687        user->resetSpaceUsed();
     688
    686689    auto callback = m_deleteDatabaseCompletionHandlers.take(callbackID);
    687690    ASSERT(callback);
     
    689692}
    690693
    691 StorageQuotaManager::Decision IDBServer::requestSpace(const ClientOrigin& origin, uint64_t taskSize)
     694IDBServer::QuotaUser::QuotaUser(IDBServer& server, StorageQuotaManager* manager, ClientOrigin&& origin)
     695    : m_server(server)
     696    , m_manager(makeWeakPtr(manager))
     697    , m_origin(WTFMove(origin))
     698    , m_isInitialized(m_server.m_sessionID.isEphemeral())
     699{
     700    if (manager)
     701        manager->addUser(*this);
     702}
     703
     704IDBServer::QuotaUser::~QuotaUser()
     705{
     706    if (m_manager)
     707        m_manager->removeUser(*this);
     708}
     709
     710void IDBServer::QuotaUser::resetSpaceUsed()
     711{
     712    m_spaceUsed = 0;
     713
     714    if (!m_manager)
     715        return;
     716
     717    if (m_server.m_sessionID.isEphemeral())
     718        return;
     719
     720    if (!m_isInitialized)
     721        return;
     722
     723    ASSERT(!m_initializationCallback);
     724
     725    m_isInitialized = false;
     726
     727    // Do add/remove to trigger call to whenInitialized.
     728    m_manager->removeUser(*this);
     729    m_manager->addUser(*this);
     730}
     731
     732void IDBServer::QuotaUser::computeSpaceUsed()
     733{
     734    resetSpaceUsed();
     735}
     736
     737void IDBServer::QuotaUser::increaseSpaceUsed(uint64_t size)
     738{
     739    if (!m_isInitialized)
     740        return;
     741    ASSERT(m_spaceUsed + size > m_spaceUsed);
     742    m_spaceUsed += size;
     743}
     744void IDBServer::QuotaUser::decreaseSpaceUsed(uint64_t size)
     745{
     746    if (!m_isInitialized)
     747        return;
     748    ASSERT(m_spaceUsed >= size);
     749    m_spaceUsed -= size;
     750}
     751
     752void IDBServer::QuotaUser::whenInitialized(CompletionHandler<void()>&& callback)
     753{
     754    if (m_isInitialized) {
     755        callback();
     756        return;
     757    }
     758    m_initializationCallback = WTFMove(callback);
     759    m_server.startComputingSpaceUsedForOrigin(m_origin);
     760}
     761
     762void IDBServer::QuotaUser::initializeSpaceUsed(uint64_t spaceUsed)
     763{
     764    ASSERT(m_isInitialized || !m_estimatedSpaceIncrease);
     765    m_spaceUsed = spaceUsed;
     766    m_isInitialized = true;
     767
     768    if (auto callback = WTFMove(m_initializationCallback))
     769        callback();
     770}
     771
     772IDBServer::QuotaUser& IDBServer::ensureQuotaUser(const ClientOrigin& origin)
     773{
     774    return *m_quotaUsers.ensure(origin, [this, &origin] {
     775        return makeUnique<QuotaUser>(*this, m_quotaManagerGetter(m_sessionID, origin), ClientOrigin { origin });
     776    }).iterator->value;
     777}
     778
     779void IDBServer::startComputingSpaceUsedForOrigin(const ClientOrigin& origin)
     780{
     781    ASSERT(!m_sessionID.isEphemeral());
     782    postDatabaseTask(createCrossThreadTask(*this, &IDBServer::computeSpaceUsedForOrigin, origin));
     783}
     784
     785void IDBServer::computeSpaceUsedForOrigin(const ClientOrigin& origin)
    692786{
    693787    ASSERT(!isMainThread());
    694     return m_spaceRequester(origin, taskSize);
    695 }
    696 
    697 uint64_t IDBServer::diskUsage(const String& rootDirectory, const ClientOrigin& origin)
    698 {
    699     ASSERT(!isMainThread());
    700 
    701     auto oldVersionOriginDirectory = IDBDatabaseIdentifier::databaseDirectoryRelativeToRoot(origin.topOrigin, origin.clientOrigin, rootDirectory, "v0"_str);
    702     auto newVersionOriginDirectory = IDBDatabaseIdentifier::databaseDirectoryRelativeToRoot(origin.topOrigin, origin.clientOrigin, rootDirectory, "v1"_str);
    703     return SQLiteIDBBackingStore::databasesSizeForDirectory(oldVersionOriginDirectory) + SQLiteIDBBackingStore::databasesSizeForDirectory(newVersionOriginDirectory);
     788
     789    auto databaseDirectoryPath = this->databaseDirectoryPathIsolatedCopy();
     790    auto oldVersionOriginDirectory = IDBDatabaseIdentifier::databaseDirectoryRelativeToRoot(origin.topOrigin, origin.clientOrigin, databaseDirectoryPath, "v0");
     791    auto newVersionOriginDirectory = IDBDatabaseIdentifier::databaseDirectoryRelativeToRoot(origin.topOrigin, origin.clientOrigin, databaseDirectoryPath, "v1");
     792    auto size = SQLiteIDBBackingStore::databasesSizeForDirectory(oldVersionOriginDirectory) + SQLiteIDBBackingStore::databasesSizeForDirectory(newVersionOriginDirectory);
     793
     794    postDatabaseTaskReply(createCrossThreadTask(*this, &IDBServer::finishComputingSpaceUsedForOrigin, origin, size));
     795}
     796
     797void IDBServer::finishComputingSpaceUsedForOrigin(const ClientOrigin& origin, uint64_t spaceUsed)
     798{
     799    ensureQuotaUser(origin).initializeSpaceUsed(spaceUsed);
     800}
     801
     802void IDBServer::requestSpace(const ClientOrigin& origin, uint64_t taskSize, CompletionHandler<void(StorageQuotaManager::Decision)>&& callback)
     803{
     804    auto* quotaManager = ensureQuotaUser(origin).manager();
     805    if (!quotaManager) {
     806        callback(StorageQuotaManager::Decision::Deny);
     807        return;
     808    }
     809
     810    quotaManager->requestSpace(taskSize, WTFMove(callback));
     811}
     812
     813void IDBServer::resetSpaceUsed(const ClientOrigin& origin)
     814{
     815    if (auto* user = m_quotaUsers.get(origin))
     816        user->resetSpaceUsed();
     817}
     818
     819void IDBServer::increaseSpaceUsed(const ClientOrigin& origin, uint64_t size)
     820{
     821    ensureQuotaUser(origin).increaseSpaceUsed(size);
     822}
     823
     824void IDBServer::decreaseSpaceUsed(const ClientOrigin& origin, uint64_t size)
     825{
     826    ensureQuotaUser(origin).decreaseSpaceUsed(size);
     827}
     828
     829void IDBServer::increasePotentialSpaceUsed(const ClientOrigin& origin, uint64_t taskSize)
     830{
     831    ensureQuotaUser(origin).increasePotentialSpaceUsed(taskSize);
     832}
     833
     834void IDBServer::decreasePotentialSpaceUsed(const ClientOrigin& origin, uint64_t spaceUsed)
     835{
     836    ensureQuotaUser(origin).decreasePotentialSpaceUsed(spaceUsed);
    704837}
    705838
  • trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.h

    r252805 r252839  
    3131#include "IDBDatabaseIdentifier.h"
    3232#include "StorageQuotaManager.h"
     33#include "StorageQuotaUser.h"
    3334#include "UniqueIDBDatabase.h"
    3435#include "UniqueIDBDatabaseConnection.h"
     
    5859class IDBServer : public RefCounted<IDBServer>, public CrossThreadTaskHandler, public CanMakeWeakPtr<IDBServer> {
    5960public:
    60     using StorageQuotaManagerSpaceRequester = Function<StorageQuotaManager::Decision(const ClientOrigin&, uint64_t spaceRequested)>;
    61     static Ref<IDBServer> create(PAL::SessionID, StorageQuotaManagerSpaceRequester&&);
    62     WEBCORE_EXPORT static Ref<IDBServer> create(PAL::SessionID, const String& databaseDirectoryPath, StorageQuotaManagerSpaceRequester&&);
     61    using QuotaManagerGetter = WTF::Function<StorageQuotaManager*(PAL::SessionID, const ClientOrigin&)>;
     62    static Ref<IDBServer> create(PAL::SessionID, QuotaManagerGetter&&);
     63    WEBCORE_EXPORT static Ref<IDBServer> create(PAL::SessionID, const String& databaseDirectoryPath, QuotaManagerGetter&&);
    6364
    6465    WEBCORE_EXPORT void registerConnection(IDBConnectionToClient&);
     
    111112    WEBCORE_EXPORT void closeAndDeleteDatabasesForOrigins(const Vector<SecurityOriginData>&, Function<void ()>&& completionHandler);
    112113
    113     StorageQuotaManager::Decision requestSpace(const ClientOrigin&, uint64_t taskSize);
    114     WEBCORE_EXPORT static uint64_t diskUsage(const String& rootDirectory, const ClientOrigin&);
     114    void requestSpace(const ClientOrigin&, uint64_t taskSize, CompletionHandler<void(StorageQuotaManager::Decision)>&&);
     115    void increasePotentialSpaceUsed(const ClientOrigin&, uint64_t taskSize);
     116    void decreasePotentialSpaceUsed(const ClientOrigin&, uint64_t taskSize);
     117    void increaseSpaceUsed(const ClientOrigin&, uint64_t size);
     118    void decreaseSpaceUsed(const ClientOrigin&, uint64_t size);
     119    void resetSpaceUsed(const ClientOrigin&);
     120
     121    void initializeQuotaUser(const ClientOrigin& origin) { ensureQuotaUser(origin); }
    115122
    116123    WEBCORE_EXPORT void tryStop(ShouldForceStop);
     
    121128
    122129private:
    123     IDBServer(PAL::SessionID, StorageQuotaManagerSpaceRequester&&);
    124     IDBServer(PAL::SessionID, const String& databaseDirectoryPath, StorageQuotaManagerSpaceRequester&&);
     130    IDBServer(PAL::SessionID, QuotaManagerGetter&&);
     131    IDBServer(PAL::SessionID, const String& databaseDirectoryPath, QuotaManagerGetter&&);
    125132
    126133    UniqueIDBDatabase& getOrCreateUniqueIDBDatabase(const IDBDatabaseIdentifier&);
     
    138145    void removeDatabasesModifiedSinceForVersion(WallTime, const String&);
    139146    void removeDatabasesWithOriginsForVersion(const Vector<SecurityOriginData>&, const String&);
     147
     148    class QuotaUser final : public StorageQuotaUser {
     149        WTF_MAKE_FAST_ALLOCATED;
     150    public:
     151        QuotaUser(IDBServer&, StorageQuotaManager*, ClientOrigin&&);
     152        ~QuotaUser();
     153
     154        StorageQuotaManager* manager() { return m_manager.get(); }
     155
     156        void setSpaceUsed(uint64_t spaceUsed) { m_spaceUsed = spaceUsed; }
     157        void resetSpaceUsed();
     158
     159        void increasePotentialSpaceUsed(uint64_t increase) { m_estimatedSpaceIncrease += increase; }
     160        void decreasePotentialSpaceUsed(uint64_t decrease)
     161        {
     162            ASSERT(m_estimatedSpaceIncrease >= decrease);
     163            m_estimatedSpaceIncrease -= decrease;
     164        }
     165        void increaseSpaceUsed(uint64_t size);
     166        void decreaseSpaceUsed(uint64_t size);
     167
     168        void initializeSpaceUsed(uint64_t spaceUsed);
     169
     170    private:
     171        uint64_t spaceUsed() const final
     172        {
     173            ASSERT(m_isInitialized);
     174            return m_spaceUsed + m_estimatedSpaceIncrease;
     175        }
     176        void computeSpaceUsed() final;
     177        void whenInitialized(CompletionHandler<void()>&&) final;
     178
     179        IDBServer& m_server;
     180        WeakPtr<StorageQuotaManager> m_manager;
     181        ClientOrigin m_origin;
     182        bool m_isInitialized { false };
     183        uint64_t m_spaceUsed { 0 };
     184        uint64_t m_estimatedSpaceIncrease { 0 };
     185        CompletionHandler<void()> m_initializationCallback;
     186    };
     187
     188    WEBCORE_EXPORT QuotaUser& ensureQuotaUser(const ClientOrigin&);
     189    void startComputingSpaceUsedForOrigin(const ClientOrigin&);
     190    void computeSpaceUsedForOrigin(const ClientOrigin&);
     191    void finishComputingSpaceUsedForOrigin(const ClientOrigin&, uint64_t spaceUsed);
    140192
    141193    PAL::SessionID m_sessionID;
     
    151203    String m_databaseDirectoryPath;
    152204
    153     StorageQuotaManagerSpaceRequester m_spaceRequester;
     205    HashMap<ClientOrigin, std::unique_ptr<QuotaUser>> m_quotaUsers;
     206    QuotaManagerGetter m_quotaManagerGetter;
    154207};
    155208
  • trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp

    r252805 r252839  
    190190}
    191191
     192void UniqueIDBDatabase::requestSpace(UniqueIDBDatabaseTransaction& transaction, uint64_t taskSize, const char* taskName, CompletionHandler<void(IDBError&&)>&& callback)
     193{
     194    m_server->requestSpace(m_identifier.origin(), taskSize, [weakThis = makeWeakPtr(this), this, weakTransaction = makeWeakPtr(transaction), taskName, callback = WTFMove(callback)](auto decision) mutable {
     195        if (!weakThis) {
     196            callback(IDBError { UnknownError });
     197            return;
     198        }
     199
     200        if (!weakTransaction) {
     201            callback(IDBError { UnknownError });
     202            return;
     203        }
     204        if (m_owningPointerForClose) {
     205            // We are closing the database, there is no point in trying to modify the database at that point.
     206            callback(IDBError { UnknownError });
     207            return;
     208        }
     209
     210        switch (decision) {
     211        case StorageQuotaManager::Decision::Deny:
     212            callback(IDBError { QuotaExceededError, quotaErrorMessageName(taskName) });
     213            return;
     214        case StorageQuotaManager::Decision::Grant:
     215            callback(IDBError { });
     216        };
     217    });
     218}
     219
     220void UniqueIDBDatabase::waitForRequestSpaceCompletion(UniqueIDBDatabaseTransaction& transaction, CompletionHandler<void(IDBError&&)>&& callback)
     221{
     222    requestSpace(transaction, 0, "", WTFMove(callback));
     223}
     224
     225void UniqueIDBDatabase::startSpaceIncreaseTask(uint64_t identifier, uint64_t taskSize)
     226{
     227    m_server->increasePotentialSpaceUsed(m_identifier.origin(), taskSize);
     228    ASSERT(!m_pendingSpaceIncreaseTasks.contains(identifier));
     229    m_pendingSpaceIncreaseTasks.add(identifier, taskSize);
     230}
     231
     232void UniqueIDBDatabase::finishSpaceIncreaseTask(uint64_t identifier, bool isTaskSuccessful)
     233{
     234    auto iterator = m_pendingSpaceIncreaseTasks.find(identifier);
     235    ASSERT(iterator != m_pendingSpaceIncreaseTasks.end());
     236    m_server->decreasePotentialSpaceUsed(m_identifier.origin(), iterator->value);
     237    if (isTaskSuccessful)
     238        m_server->increaseSpaceUsed(m_identifier.origin(), iterator->value);
     239    m_pendingSpaceIncreaseTasks.remove(iterator);
     240}
     241
    192242void UniqueIDBDatabase::performCurrentOpenOperation()
    193243{
     
    200250        if (!m_isOpeningBackingStore) {
    201251            m_isOpeningBackingStore = true;
    202             postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::openBackingStore, m_identifier));
     252            // We do not know whether this is an existing or a new database.
     253            // We set a small cost so that it is not possible to open an infinite number of database.
     254            m_server->requestSpace(m_identifier.origin(), defaultWriteOperationCost, [this, weakThis = makeWeakPtr(this)](auto decision) mutable {
     255                if (!weakThis)
     256                    return;
     257
     258                if (m_owningPointerForClose)
     259                    return;
     260
     261                switch (decision) {
     262                case StorageQuotaManager::Decision::Deny: {
     263                    auto result = IDBResultData::error(m_currentOpenDBRequest->requestData().requestIdentifier(), IDBError { QuotaExceededError, quotaErrorMessageName("openDatabase") });
     264                    m_currentOpenDBRequest->connection().didOpenDatabase(result);
     265                    m_currentOpenDBRequest = nullptr;
     266                    m_isOpeningBackingStore = false;
     267                    break;
     268                }
     269                case StorageQuotaManager::Decision::Grant:
     270                    auto callbackID = this->generateUniqueCallbackIdentifier();
     271                    startSpaceIncreaseTask(callbackID, defaultWriteOperationCost);
     272                    this->postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::openBackingStore, m_identifier, callbackID));
     273                };
     274            });
    203275        }
    204276        return;
     
    764836}
    765837
    766 void UniqueIDBDatabase::openBackingStore(const IDBDatabaseIdentifier& identifier)
     838void UniqueIDBDatabase::openBackingStore(const IDBDatabaseIdentifier& identifier, uint64_t taskIdentifier)
    767839{
    768840    ASSERT(!isMainThread());
    769841    LOG(IndexedDB, "(db) UniqueIDBDatabase::openBackingStore (%p)", this);
    770842
     843    ASSERT(!m_backingStore);
     844
    771845    IDBDatabaseInfo databaseInfo;
    772     m_origin = identifier.origin();
    773     // Quota check.
    774     auto decision = m_server->requestSpace(m_origin, defaultWriteOperationCost);
    775     if (decision == StorageQuotaManager::Decision::Deny) {
    776         postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didOpenBackingStore, databaseInfo, IDBError(QuotaExceededError, quotaErrorMessageName("OpenBackingStore"))));
    777         return;
    778     }
    779 
    780     ASSERT(!m_backingStore);
    781846    IDBError error;
    782847    {
     
    788853    }
    789854
    790     postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didOpenBackingStore, databaseInfo, error));
    791 }
    792 
    793 void UniqueIDBDatabase::didOpenBackingStore(const IDBDatabaseInfo& info, const IDBError& error)
     855    postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didOpenBackingStore, databaseInfo, error,  taskIdentifier));
     856}
     857
     858void UniqueIDBDatabase::didOpenBackingStore(const IDBDatabaseInfo& info, const IDBError& error, uint64_t taskIdentifier)
    794859{
    795860    ASSERT(isMainThread());
     
    802867    m_isOpeningBackingStore = false;
    803868
     869    finishSpaceIncreaseTask(taskIdentifier, error.isNull());
     870
    804871    if (m_hardClosedForUserDelete)
    805872        return;
     
    813880    LOG(IndexedDB, "(main) UniqueIDBDatabase::createObjectStore");
    814881
     882    auto taskSize = defaultWriteOperationCost + estimateSize(info);
     883    requestSpace(transaction, taskSize, "createObjectStore", [this, taskSize, &transaction, info, callback = WTFMove(callback)](auto error) mutable {
     884        if (!error.isNull() && *error.code() != QuotaExceededError) {
     885            callback(WTFMove(error));
     886            return;
     887        }
     888        this->createObjectStoreAfterQuotaCheck(taskSize, transaction, info, WTFMove(callback), error);
     889    });
     890}
     891
     892void UniqueIDBDatabase::createObjectStoreAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction& transaction, const IDBObjectStoreInfo& info, ErrorCallback callback, const IDBError& quotaError)
     893{
    815894    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    816895    if (!callbackID)
    817896        return;
    818897
    819     postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performCreateObjectStore, callbackID, transaction.info().identifier(), info));
    820 }
    821 
    822 void UniqueIDBDatabase::performCreateObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBObjectStoreInfo& info)
     898    startSpaceIncreaseTask(callbackID, taskSize);
     899    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performCreateObjectStore, callbackID, transaction.info().identifier(), info,  quotaError));
     900}
     901
     902void UniqueIDBDatabase::performCreateObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBObjectStoreInfo& info, const IDBError& quotaError)
    823903{
    824904    ASSERT(!isMainThread());
    825905    LOG(IndexedDB, "(db) UniqueIDBDatabase::performCreateObjectStore");
    826906
    827     // Quota check.
    828     auto taskSize = defaultWriteOperationCost + estimateSize(info);
    829     if (m_server->requestSpace(m_origin, taskSize) == StorageQuotaManager::Decision::Deny) {
    830         postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformCreateObjectStore, callbackIdentifier, IDBError(QuotaExceededError, quotaErrorMessageName("CreateObjectStore")), info));
     907    if (!quotaError.isNull()) {
     908        postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformCreateObjectStore, callbackIdentifier, quotaError, info));
    831909        return;
    832910    }
     
    847925    LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformCreateObjectStore");
    848926
     927    finishSpaceIncreaseTask(callbackIdentifier, error.isNull());
    849928    if (error.isNull())
    850929        m_databaseInfo->addExistingObjectStore(info);
     
    858937    LOG(IndexedDB, "(main) UniqueIDBDatabase::deleteObjectStore");
    859938
     939    waitForRequestSpaceCompletion(transaction, [this, &transaction, objectStoreName, callback = WTFMove(callback)](auto&& error) mutable {
     940        if (!error.isNull()) {
     941            callback(WTFMove(error));
     942            return;
     943        }
     944        this->deleteObjectStoreAfterQuotaCheck(transaction, objectStoreName, WTFMove(callback));
     945    });
     946}
     947
     948void UniqueIDBDatabase::deleteObjectStoreAfterQuotaCheck(UniqueIDBDatabaseTransaction& transaction, const String& objectStoreName, ErrorCallback callback)
     949{
    860950    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    861951    if (!callbackID)
     
    902992    LOG(IndexedDB, "(main) UniqueIDBDatabase::renameObjectStore");
    903993
     994    auto taskSize = defaultWriteOperationCost + newName.sizeInBytes();
     995    requestSpace(transaction, taskSize, "renameObjectStore", [this, taskSize, &transaction, objectStoreIdentifier, newName, callback = WTFMove(callback)](auto error) mutable {
     996        if (!error.isNull() && *error.code() != QuotaExceededError) {
     997            callback(WTFMove(error));
     998            return;
     999        }
     1000        this->renameObjectStoreAfterQuotaCheck(taskSize, transaction, objectStoreIdentifier, newName, WTFMove(callback), error);
     1001    });
     1002}
     1003
     1004void UniqueIDBDatabase::renameObjectStoreAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction& transaction, uint64_t objectStoreIdentifier, const String& newName, ErrorCallback callback, const IDBError& quotaError)
     1005{
    9041006    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    9051007    if (!callbackID)
    9061008        return;
    9071009
    908     IDBError error;
     1010    IDBError error = quotaError;
    9091011    auto* info = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
    9101012    if (!info)
    9111013        error = IDBError { UnknownError, "Attempt to rename non-existant object store"_s };
    9121014
     1015    startSpaceIncreaseTask(callbackID, taskSize);
    9131016    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performRenameObjectStore, callbackID, transaction.info().identifier(), objectStoreIdentifier, newName, error));
    9141017}
     
    9191022    LOG(IndexedDB, "(db) UniqueIDBDatabase::performRenameObjectStore");
    9201023
    921     // Quota check.
    922     auto taskSize = defaultWriteOperationCost + newName.sizeInBytes();
    923     if (m_server->requestSpace(m_origin, taskSize) == StorageQuotaManager::Decision::Deny) {
    924         postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformRenameObjectStore, callbackIdentifier, IDBError(QuotaExceededError, quotaErrorMessageName("RenameObjectStore")), objectStoreIdentifier, newName));
     1024    if (!error.isNull()) {
     1025        postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformRenameObjectStore, callbackIdentifier, error, objectStoreIdentifier, newName));
    9251026        return;
    9261027    }
     
    9401041    LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformRenameObjectStore");
    9411042
     1043    finishSpaceIncreaseTask(callbackIdentifier, error.isNull());
    9421044    if (error.isNull())
    9431045        m_databaseInfo->renameObjectStore(objectStoreIdentifier, newName);
     
    9511053    LOG(IndexedDB, "(main) UniqueIDBDatabase::clearObjectStore");
    9521054
     1055    waitForRequestSpaceCompletion(transaction, [this, &transaction, objectStoreIdentifier, callback = WTFMove(callback)](auto&& error) mutable {
     1056        if (!error.isNull()) {
     1057            callback(WTFMove(error));
     1058            return;
     1059        }
     1060        this->clearObjectStoreAfetQuotaCheck(transaction, objectStoreIdentifier, WTFMove(callback));
     1061    });
     1062}
     1063
     1064void UniqueIDBDatabase::clearObjectStoreAfetQuotaCheck(UniqueIDBDatabaseTransaction& transaction, uint64_t objectStoreIdentifier, ErrorCallback callback)
     1065{
    9531066    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    9541067    if (!callbackID)
     
    9851098    LOG(IndexedDB, "(main) UniqueIDBDatabase::createIndex");
    9861099
     1100    auto taskSize = defaultWriteOperationCost + estimateSize(info);
     1101    requestSpace(transaction, taskSize, "createIndex", [this, taskSize, &transaction, info, callback = WTFMove(callback)](auto error) mutable {
     1102        if (!error.isNull() && *error.code() != QuotaExceededError) {
     1103            callback(WTFMove(error));
     1104            return;
     1105        }
     1106        this->createIndexAfterQuotaCheck(taskSize, transaction, info, WTFMove(callback), error);
     1107    });
     1108}
     1109
     1110void UniqueIDBDatabase::createIndexAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction& transaction, const IDBIndexInfo& info, ErrorCallback callback, const IDBError& quotaError)
     1111{
    9871112    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    9881113    if (!callbackID)
    9891114        return;
    9901115
    991     postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performCreateIndex, callbackID, transaction.info().identifier(), info));
    992 }
    993 
    994 void UniqueIDBDatabase::performCreateIndex(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBIndexInfo& info)
     1116    startSpaceIncreaseTask(callbackID, taskSize);
     1117    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performCreateIndex, callbackID, transaction.info().identifier(), info, quotaError));
     1118}
     1119
     1120void UniqueIDBDatabase::performCreateIndex(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBIndexInfo& info, const IDBError& quotaError)
    9951121{
    9961122    ASSERT(!isMainThread());
    9971123    LOG(IndexedDB, "(db) UniqueIDBDatabase::performCreateIndex");
    9981124
    999     auto taskSize = defaultWriteOperationCost + estimateSize(info);
    1000     if (m_server->requestSpace(m_origin, taskSize) == StorageQuotaManager::Decision::Deny) {
    1001         postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformCreateIndex, callbackIdentifier, IDBError(QuotaExceededError, quotaErrorMessageName("CreateIndex")), info));
     1125    if (!quotaError.isNull()) {
     1126        postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformCreateIndex, callbackIdentifier, quotaError, info));
    10021127        return;
    10031128    }
     
    10241149    LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformCreateIndex");
    10251150
     1151    finishSpaceIncreaseTask(callbackIdentifier, error.isNull());
     1152
    10261153    if (error.isNull()) {
    10271154        ASSERT(m_databaseInfo);
     
    10391166    LOG(IndexedDB, "(main) UniqueIDBDatabase::deleteIndex");
    10401167
     1168    waitForRequestSpaceCompletion(transaction, [this, &transaction, objectStoreIdentifier, indexName, callback = WTFMove(callback)](auto&& error) mutable {
     1169        if (!error.isNull()) {
     1170            callback(WTFMove(error));
     1171            return;
     1172        }
     1173        this->deleteIndexAfterQuotaCheck(transaction, objectStoreIdentifier, indexName, WTFMove(callback));
     1174    });
     1175}
     1176
     1177void UniqueIDBDatabase::deleteIndexAfterQuotaCheck(UniqueIDBDatabaseTransaction& transaction, uint64_t objectStoreIdentifier, const String& indexName, ErrorCallback callback)
     1178{
    10411179    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    10421180    if (!callbackID)
     
    10921230    LOG(IndexedDB, "(main) UniqueIDBDatabase::renameIndex");
    10931231
     1232    auto taskSize = defaultWriteOperationCost + newName.sizeInBytes();
     1233    requestSpace(transaction, taskSize, "renameIndex", [this, taskSize, &transaction, objectStoreIdentifier, indexIdentifier, newName, callback = WTFMove(callback)](auto error) mutable {
     1234        if (!error.isNull() && *error.code() != QuotaExceededError) {
     1235            callback(WTFMove(error));
     1236            return;
     1237        }
     1238        this->renameIndexAfterQuotaCheck(taskSize, transaction, objectStoreIdentifier, indexIdentifier, newName, WTFMove(callback), error);
     1239    });
     1240}
     1241
     1242void UniqueIDBDatabase::renameIndexAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction& transaction, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName, ErrorCallback callback, const IDBError& quotaError)
     1243{
    10941244    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    10951245    if (!callbackID)
    10961246        return;
    10971247
    1098     IDBError error;
     1248    IDBError error = quotaError;
    10991249    auto* objectStoreInfo = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
    11001250    if (!objectStoreInfo)
     
    11051255        error = IDBError { UnknownError, "Attempt to rename non-existant index"_s };
    11061256
     1257    startSpaceIncreaseTask(callbackID, taskSize);
    11071258    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performRenameIndex, callbackID, transaction.info().identifier(), objectStoreIdentifier, indexIdentifier, newName, error));
    11081259}
     
    11131264    LOG(IndexedDB, "(db) UniqueIDBDatabase::performRenameIndex");
    11141265
    1115     // Quota check.
    1116     auto taskSize = defaultWriteOperationCost + newName.sizeInBytes();
    1117     if (m_server->requestSpace(m_origin, taskSize) == StorageQuotaManager::Decision::Deny) {
    1118         postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformRenameIndex, callbackIdentifier, IDBError(QuotaExceededError, quotaErrorMessageName("RenameIndex")), objectStoreIdentifier, indexIdentifier, newName));
     1266    if (!error.isNull()) {
     1267        postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformRenameIndex, callbackIdentifier, error, objectStoreIdentifier, indexIdentifier, newName));
    11191268        return;
    11201269    }
     
    11341283    LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformRenameIndex");
    11351284
     1285    finishSpaceIncreaseTask(callbackIdentifier, error.isNull());
    11361286    if (error.isNull()) {
    11371287        auto* objectStoreInfo = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
     
    11471297}
    11481298
    1149 void UniqueIDBDatabase::putOrAdd(const IDBRequestData& requestData, const IDBKeyData& keyData, const IDBValue& value, IndexedDB::ObjectStoreOverwriteMode overwriteMode, KeyDataCallback callback)
     1299void UniqueIDBDatabase::putOrAdd(UniqueIDBDatabaseTransaction& transaction, const IDBRequestData& requestData, const IDBKeyData& keyData, const IDBValue& value, IndexedDB::ObjectStoreOverwriteMode overwriteMode, KeyDataCallback callback)
    11501300{
    11511301    ASSERT(isMainThread());
    11521302    LOG(IndexedDB, "(main) UniqueIDBDatabase::putOrAdd");
    11531303
     1304    auto taskSize = defaultWriteOperationCost + estimateSize(keyData) + estimateSize(value);
     1305    ASSERT(m_databaseInfo);
     1306    auto* objectStore = m_databaseInfo->infoForExistingObjectStore(requestData.objectStoreIdentifier());
     1307    if (objectStore)
     1308        taskSize += objectStore->indexNames().size() * taskSize;
     1309
     1310    requestSpace(transaction, taskSize, "putOrAdd", [this, taskSize, requestData, keyData, value, callback = WTFMove(callback), overwriteMode](auto error) mutable {
     1311        if (!error.isNull() && *error.code() != QuotaExceededError) {
     1312            callback(WTFMove(error), { });
     1313            return;
     1314        }
     1315        this->putOrAddAfterQuotaCheck(taskSize, requestData, keyData, value, overwriteMode, WTFMove(callback), error);
     1316    });
     1317}
     1318
     1319void UniqueIDBDatabase::putOrAddAfterQuotaCheck(uint64_t taskSize, const IDBRequestData& requestData, const IDBKeyData& keyData, const IDBValue& value, IndexedDB::ObjectStoreOverwriteMode overwriteMode, KeyDataCallback callback, const IDBError& quotaError)
     1320{
    11541321    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    11551322    if (!callbackID)
    11561323        return;
    11571324
    1158     postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performPutOrAdd, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), keyData, value, overwriteMode));
    1159 }
    1160 
    1161 void UniqueIDBDatabase::performPutOrAdd(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData& keyData, const IDBValue& originalRecordValue, IndexedDB::ObjectStoreOverwriteMode overwriteMode)
     1325    startSpaceIncreaseTask(callbackID, taskSize);
     1326    postDatabaseTask(createCrossThreadTask(*this, &UniqueIDBDatabase::performPutOrAdd, callbackID, requestData.transactionIdentifier(), requestData.objectStoreIdentifier(), keyData, value, overwriteMode, quotaError));
     1327}
     1328
     1329void UniqueIDBDatabase::performPutOrAdd(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData& keyData, const IDBValue& originalRecordValue, IndexedDB::ObjectStoreOverwriteMode overwriteMode, const IDBError& quotaError)
    11621330{
    11631331    ASSERT(!isMainThread());
    11641332    LOG(IndexedDB, "(db) UniqueIDBDatabase::performPutOrAdd");
    11651333
     1334    ASSERT(m_backingStore);
     1335    ASSERT(objectStoreIdentifier);
     1336
    11661337    IDBKeyData usedKey;
    11671338    IDBError error;
    11681339
    1169     // Quota check.
    1170     auto taskSize = defaultWriteOperationCost + estimateSize(keyData) + estimateSize(originalRecordValue);
    1171     ASSERT(m_databaseInfo);
    1172     auto* objectStore = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
    1173     if (objectStore)
    1174         taskSize += objectStore->indexNames().size() * taskSize;
    1175     if (m_server->requestSpace(m_origin, taskSize) == StorageQuotaManager::Decision::Deny) {
    1176         postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, IDBError(QuotaExceededError, quotaErrorMessageName("PutOrAdd")), usedKey));
    1177         return;
    1178     }
    1179 
    1180     ASSERT(m_backingStore);
    1181     ASSERT(objectStoreIdentifier);
     1340    if (!quotaError.isNull()) {
     1341        postDatabaseTaskReply(createCrossThreadTask(*this, &UniqueIDBDatabase::didPerformPutOrAdd, callbackIdentifier, quotaError, usedKey));
     1342        return;
     1343    }
     1344
    11821345    {
    11831346        LockHolder locker(m_backingStoreLock);
     
    12561419    LOG(IndexedDB, "(main) UniqueIDBDatabase::didPerformPutOrAdd");
    12571420
     1421    finishSpaceIncreaseTask(callbackIdentifier, error.isNull());
    12581422    performKeyDataCallback(callbackIdentifier, error, resultKey);
    12591423}
    12601424
    1261 void UniqueIDBDatabase::getRecord(const IDBRequestData& requestData, const IDBGetRecordData& getRecordData, GetResultCallback callback)
     1425void UniqueIDBDatabase::getRecord(UniqueIDBDatabaseTransaction& transaction, const IDBRequestData& requestData, const IDBGetRecordData& getRecordData, GetResultCallback callback)
    12621426{
    12631427    ASSERT(isMainThread());
    12641428    LOG(IndexedDB, "(main) UniqueIDBDatabase::getRecord");
    12651429
     1430    waitForRequestSpaceCompletion(transaction, [this, requestData, getRecordData, callback = WTFMove(callback)](auto&& error) mutable {
     1431        if (!error.isNull()) {
     1432            callback(WTFMove(error), { });
     1433            return;
     1434        }
     1435        this->getRecordAfterQuotaCheck(requestData, getRecordData, WTFMove(callback));
     1436    });
     1437}
     1438
     1439void UniqueIDBDatabase::getRecordAfterQuotaCheck(const IDBRequestData& requestData, const IDBGetRecordData& getRecordData, GetResultCallback callback)
     1440{
    12661441    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    12671442    if (!callbackID)
     
    12741449}
    12751450
    1276 void UniqueIDBDatabase::getAllRecords(const IDBRequestData& requestData, const IDBGetAllRecordsData& getAllRecordsData, GetAllResultsCallback callback)
     1451void UniqueIDBDatabase::getAllRecords(UniqueIDBDatabaseTransaction& transaction, const IDBRequestData& requestData, const IDBGetAllRecordsData& getAllRecordsData, GetAllResultsCallback callback)
    12771452{
    12781453    ASSERT(isMainThread());
    12791454    LOG(IndexedDB, "(main) UniqueIDBDatabase::getAllRecords");
    12801455
     1456    waitForRequestSpaceCompletion(transaction, [this, requestData, getAllRecordsData, callback = WTFMove(callback)](auto&& error) mutable {
     1457        if (!error.isNull()) {
     1458            callback(WTFMove(error), { });
     1459            return;
     1460        }
     1461        this->getAllRecordsAfterQuotaCheck(requestData, getAllRecordsData, WTFMove(callback));
     1462    });
     1463}
     1464
     1465void UniqueIDBDatabase::getAllRecordsAfterQuotaCheck(const IDBRequestData& requestData, const IDBGetAllRecordsData& getAllRecordsData, GetAllResultsCallback callback)
     1466{
    12811467    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    12821468    if (!callbackID)
     
    12921478
    12931479    ASSERT(m_backingStore);
     1480
    12941481    IDBGetResult result;
    12951482    IDBError error;
     
    13321519
    13331520    ASSERT(m_backingStore);
     1521
    13341522    IDBGetAllResult result;
    13351523    IDBError error;
     
    13501538}
    13511539
    1352 void UniqueIDBDatabase::getCount(const IDBRequestData& requestData, const IDBKeyRangeData& range, CountCallback callback)
     1540void UniqueIDBDatabase::getCount(UniqueIDBDatabaseTransaction& transaction, const IDBRequestData& requestData, const IDBKeyRangeData& range, CountCallback callback)
    13531541{
    13541542    ASSERT(isMainThread());
    13551543    LOG(IndexedDB, "(main) UniqueIDBDatabase::getCount");
    13561544
     1545    waitForRequestSpaceCompletion(transaction, [this, requestData, range, callback = WTFMove(callback)](auto&& error) mutable {
     1546        if (!error.isNull()) {
     1547            callback(WTFMove(error), { });
     1548            return;
     1549        }
     1550        this->getCountAfterQuotaCheck(requestData, range, WTFMove(callback));
     1551    });
     1552}
     1553
     1554void UniqueIDBDatabase::getCountAfterQuotaCheck(const IDBRequestData& requestData, const IDBKeyRangeData& range, CountCallback callback)
     1555{
    13571556    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    13581557    if (!callbackID)
     
    13871586}
    13881587
    1389 void UniqueIDBDatabase::deleteRecord(const IDBRequestData& requestData, const IDBKeyRangeData& keyRangeData, ErrorCallback callback)
     1588void UniqueIDBDatabase::deleteRecord(UniqueIDBDatabaseTransaction& transaction, const IDBRequestData& requestData, const IDBKeyRangeData& keyRangeData, ErrorCallback callback)
    13901589{
    13911590    ASSERT(isMainThread());
    13921591    LOG(IndexedDB, "(main) UniqueIDBDatabase::deleteRecord");
    13931592
     1593    waitForRequestSpaceCompletion(transaction, [this, requestData, keyRangeData, callback = WTFMove(callback)](auto&& error) mutable {
     1594        if (!error.isNull()) {
     1595            callback(WTFMove(error));
     1596            return;
     1597        }
     1598        this->deleteRecordAfterQuotaCheck(requestData, keyRangeData, WTFMove(callback));
     1599    });
     1600}
     1601
     1602void UniqueIDBDatabase::deleteRecordAfterQuotaCheck(const IDBRequestData& requestData, const IDBKeyRangeData& keyRangeData, ErrorCallback callback)
     1603{
    13941604    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    13951605    if (!callbackID)
     
    14201630}
    14211631
    1422 void UniqueIDBDatabase::openCursor(const IDBRequestData& requestData, const IDBCursorInfo& info, GetResultCallback callback)
     1632void UniqueIDBDatabase::openCursor(UniqueIDBDatabaseTransaction& transaction, const IDBRequestData& requestData, const IDBCursorInfo& info, GetResultCallback callback)
    14231633{
    14241634    ASSERT(isMainThread());
    14251635    LOG(IndexedDB, "(main) UniqueIDBDatabase::openCursor");
    14261636
     1637    waitForRequestSpaceCompletion(transaction, [this, requestData, info, callback = WTFMove(callback)](auto&& error) mutable {
     1638        if (!error.isNull()) {
     1639            callback(WTFMove(error), { });
     1640            return;
     1641        }
     1642        this->openCursorAfterQuotaCheck(requestData, info, WTFMove(callback));
     1643    });
     1644}
     1645
     1646void UniqueIDBDatabase::openCursorAfterQuotaCheck(const IDBRequestData& requestData, const IDBCursorInfo& info, GetResultCallback callback)
     1647{
    14271648    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    14281649    if (!callbackID)
     
    14541675}
    14551676
    1456 void UniqueIDBDatabase::iterateCursor(const IDBRequestData& requestData, const IDBIterateCursorData& data, GetResultCallback callback)
     1677void UniqueIDBDatabase::iterateCursor(UniqueIDBDatabaseTransaction& transaction, const IDBRequestData& requestData, const IDBIterateCursorData& data, GetResultCallback callback)
    14571678{
    14581679    ASSERT(isMainThread());
    14591680    LOG(IndexedDB, "(main) UniqueIDBDatabase::iterateCursor");
    14601681
     1682    waitForRequestSpaceCompletion(transaction, [this, requestData, data, callback = WTFMove(callback)](auto&& error) mutable {
     1683        if (!error.isNull()) {
     1684            callback(WTFMove(error), { });
     1685            return;
     1686        }
     1687        this->iterateCursorAfterQuotaCheck(requestData, data, WTFMove(callback));
     1688    });
     1689}
     1690
     1691void UniqueIDBDatabase::iterateCursorAfterQuotaCheck(const IDBRequestData& requestData, const IDBIterateCursorData& data, GetResultCallback callback)
     1692{
    14611693    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    14621694    if (!callbackID)
     
    15361768    ASSERT(transaction.databaseConnection().database() == this);
    15371769
     1770    waitForRequestSpaceCompletion(transaction, [this, &transaction, callback = WTFMove(callback)](auto&& error) mutable {
     1771        if (!error.isNull()) {
     1772            callback(WTFMove(error));
     1773            return;
     1774        }
     1775        this->commitTransactionAfterQuotaCheck(transaction, WTFMove(callback));
     1776    });
     1777}
     1778
     1779void UniqueIDBDatabase::commitTransactionAfterQuotaCheck(UniqueIDBDatabaseTransaction& transaction, ErrorCallback callback)
     1780{
    15381781    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
    15391782    if (!callbackID)
     
    15931836}
    15941837
    1595 void UniqueIDBDatabase::abortTransaction(UniqueIDBDatabaseTransaction& transaction, ErrorCallback callback)
     1838void UniqueIDBDatabase::abortTransaction(UniqueIDBDatabaseTransaction& transaction, WaitForPendingTasks waitForPendingTasks, ErrorCallback callback)
    15961839{
    15971840    ASSERT(isMainThread());
     
    15991842
    16001843    ASSERT(transaction.databaseConnection().database() == this);
     1844
     1845    if (waitForPendingTasks == WaitForPendingTasks::Yes) {
     1846        waitForRequestSpaceCompletion(transaction, [this, &transaction, callback = WTFMove(callback)](auto&& error) mutable {
     1847            if (!error.isNull()) {
     1848                callback(WTFMove(error));
     1849                return;
     1850            }
     1851            this->abortTransaction(transaction, WaitForPendingTasks::No, WTFMove(callback));
     1852        });
     1853        return;
     1854    }
    16011855
    16021856    uint64_t callbackID = storeCallbackOrFireError(WTFMove(callback));
  • trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h

    r252805 r252839  
    4545namespace WebCore {
    4646
    47 struct ClientOrigin;
    4847class IDBError;
    4948class IDBGetAllResult;
     
    9190    void deleteIndex(UniqueIDBDatabaseTransaction&, uint64_t objectStoreIdentifier, const String& indexName, ErrorCallback);
    9291    void renameIndex(UniqueIDBDatabaseTransaction&, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName, ErrorCallback);
    93     void putOrAdd(const IDBRequestData&, const IDBKeyData&, const IDBValue&, IndexedDB::ObjectStoreOverwriteMode, KeyDataCallback);
    94     void getRecord(const IDBRequestData&, const IDBGetRecordData&, GetResultCallback);
    95     void getAllRecords(const IDBRequestData&, const IDBGetAllRecordsData&, GetAllResultsCallback);
    96     void getCount(const IDBRequestData&, const IDBKeyRangeData&, CountCallback);
    97     void deleteRecord(const IDBRequestData&, const IDBKeyRangeData&, ErrorCallback);
    98     void openCursor(const IDBRequestData&, const IDBCursorInfo&, GetResultCallback);
    99     void iterateCursor(const IDBRequestData&, const IDBIterateCursorData&, GetResultCallback);
     92    void putOrAdd(UniqueIDBDatabaseTransaction&, const IDBRequestData&, const IDBKeyData&, const IDBValue&, IndexedDB::ObjectStoreOverwriteMode, KeyDataCallback);
     93    void getRecord(UniqueIDBDatabaseTransaction&, const IDBRequestData&, const IDBGetRecordData&, GetResultCallback);
     94    void getAllRecords(UniqueIDBDatabaseTransaction&, const IDBRequestData&, const IDBGetAllRecordsData&, GetAllResultsCallback);
     95    void getCount(UniqueIDBDatabaseTransaction&, const IDBRequestData&, const IDBKeyRangeData&, CountCallback);
     96    void deleteRecord(UniqueIDBDatabaseTransaction&, const IDBRequestData&, const IDBKeyRangeData&, ErrorCallback);
     97    void openCursor(UniqueIDBDatabaseTransaction&, const IDBRequestData&, const IDBCursorInfo&, GetResultCallback);
     98    void iterateCursor(UniqueIDBDatabaseTransaction&, const IDBRequestData&, const IDBIterateCursorData&, GetResultCallback);
    10099    void commitTransaction(UniqueIDBDatabaseTransaction&, ErrorCallback);
    101     void abortTransaction(UniqueIDBDatabaseTransaction&, ErrorCallback);
     100
     101    enum class WaitForPendingTasks { No, Yes };
     102    void abortTransaction(UniqueIDBDatabaseTransaction&, WaitForPendingTasks, ErrorCallback);
    102103
    103104    void didFinishHandlingVersionChange(UniqueIDBDatabaseConnection&, const IDBResourceIdentifier& transactionIdentifier);
     
    140141    void scheduleShutdownForClose();
    141142
     143    void createObjectStoreAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction&, const IDBObjectStoreInfo&, ErrorCallback, const IDBError&);
     144    void renameObjectStoreAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction&, uint64_t objectStoreIdentifier, const String& newName, ErrorCallback, const IDBError&);
     145    void createIndexAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction&, const IDBIndexInfo&, ErrorCallback, const IDBError&);
     146    void renameIndexAfterQuotaCheck(uint64_t taskSize, UniqueIDBDatabaseTransaction&, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName, ErrorCallback, const IDBError&);
     147    void putOrAddAfterQuotaCheck(uint64_t taskSize, const IDBRequestData&, const IDBKeyData&, const IDBValue&, IndexedDB::ObjectStoreOverwriteMode, KeyDataCallback, const IDBError&);
     148    void deleteRecordAfterQuotaCheck(const IDBRequestData&, const IDBKeyRangeData&, ErrorCallback);
     149
     150    void deleteObjectStoreAfterQuotaCheck(UniqueIDBDatabaseTransaction&, const String& objectStoreName, ErrorCallback);
     151    void clearObjectStoreAfetQuotaCheck(UniqueIDBDatabaseTransaction&, uint64_t objectStoreIdentifier, ErrorCallback);
     152    void deleteIndexAfterQuotaCheck(UniqueIDBDatabaseTransaction&, uint64_t objectStoreIdentifier, const String&, ErrorCallback);
     153    void getRecordAfterQuotaCheck(const IDBRequestData&, const IDBGetRecordData&, GetResultCallback);
     154    void getAllRecordsAfterQuotaCheck(const IDBRequestData&, const IDBGetAllRecordsData&, GetAllResultsCallback);
     155    void getCountAfterQuotaCheck(const IDBRequestData&, const IDBKeyRangeData&, CountCallback);
     156    void openCursorAfterQuotaCheck(const IDBRequestData&, const IDBCursorInfo&, GetResultCallback);
     157    void iterateCursorAfterQuotaCheck(const IDBRequestData&, const IDBIterateCursorData&, GetResultCallback);
     158    void commitTransactionAfterQuotaCheck(UniqueIDBDatabaseTransaction&, ErrorCallback);
     159
    142160    // Database thread operations
    143161    void deleteBackingStore(const IDBDatabaseIdentifier&);
    144     void openBackingStore(const IDBDatabaseIdentifier&);
     162    void openBackingStore(const IDBDatabaseIdentifier&, uint64_t taskIdentifier);
    145163    void performCommitTransaction(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier);
    146164    void performAbortTransaction(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier);
    147165    void beginTransactionInBackingStore(const IDBTransactionInfo&);
    148     void performCreateObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBObjectStoreInfo&);
     166    void performCreateObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBObjectStoreInfo&, const IDBError&);
    149167    void performDeleteObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier);
    150168    void performRenameObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const String& newName, const IDBError&);
    151169    void performClearObjectStore(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier);
    152     void performCreateIndex(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBIndexInfo&);
     170    void performCreateIndex(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBIndexInfo&, const IDBError&);
    153171    void performDeleteIndex(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier);
    154172    void performRenameIndex(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName, const IDBError&);
    155     void performPutOrAdd(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData&, const IDBValue&, IndexedDB::ObjectStoreOverwriteMode);
     173    void performPutOrAdd(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyData&, const IDBValue&, IndexedDB::ObjectStoreOverwriteMode, const IDBError&);
    156174    void performGetRecord(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, const IDBKeyRangeData&, IDBGetRecordDataType);
    157175    void performGetAllRecords(uint64_t callbackIdentifier, const IDBResourceIdentifier& transactionIdentifier, const IDBGetAllRecordsData&);
     
    170188    // Main thread callbacks
    171189    void didDeleteBackingStore(uint64_t deletedVersion);
    172     void didOpenBackingStore(const IDBDatabaseInfo&, const IDBError&);
     190    void didOpenBackingStore(const IDBDatabaseInfo&, const IDBError&, uint64_t taskIdentifier);
    173191    void didPerformCreateObjectStore(uint64_t callbackIdentifier, const IDBError&, const IDBObjectStoreInfo&);
    174192    void didPerformDeleteObjectStore(uint64_t callbackIdentifier, const IDBError&, uint64_t objectStoreIdentifier);
     
    229247    bool isDoneWithHardClose();
    230248
     249    void requestSpace(UniqueIDBDatabaseTransaction&, uint64_t taskSize, const char* errorMessage, CompletionHandler<void(IDBError&&)>&&);
     250    void waitForRequestSpaceCompletion(UniqueIDBDatabaseTransaction&, CompletionHandler<void(IDBError&&)>&&);
     251    void startSpaceIncreaseTask(uint64_t identifier, uint64_t taskSize);
     252    void finishSpaceIncreaseTask(uint64_t identifier, bool isTaskSuccessful);
     253
    231254    void clearTransactionsOnConnection(UniqueIDBDatabaseConnection&);
    232255
     
    289312    HashSet<IDBResourceIdentifier> m_cursorPrefetches;
    290313
     314    HashMap<uint64_t, uint64_t> m_pendingSpaceIncreaseTasks;
     315
    291316    bool m_isSuspended { false };
    292 
    293     ClientOrigin m_origin;
    294317};
    295318
  • trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseConnection.cpp

    r252805 r252839  
    7777        return;
    7878   
    79     m_database->abortTransaction(transaction, [this, protectedThis, transactionIdentifier](const IDBError&) {
     79    m_database->abortTransaction(transaction, UniqueIDBDatabase::WaitForPendingTasks::No, [this, protectedThis, transactionIdentifier](const IDBError&) {
    8080        ASSERT(m_transactionMap.contains(transactionIdentifier));
    8181        m_transactionMap.remove(transactionIdentifier);
  • trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseTransaction.cpp

    r252805 r252839  
    8080    ASSERT(database);
    8181
    82     database->abortTransaction(*this, [this, weakThis = makeWeakPtr(*this)](auto& error) {
     82    database->abortTransaction(*this, UniqueIDBDatabase::WaitForPendingTasks::Yes, [this, weakThis = makeWeakPtr(*this)](auto& error) {
    8383        LOG(IndexedDB, "UniqueIDBDatabaseTransaction::abort (callback)");
    8484        if (!weakThis)
     
    287287    ASSERT(database);
    288288   
    289     database->putOrAdd(requestData, keyData, value, overwriteMode, [this, weakThis = makeWeakPtr(*this), requestData](auto& error, const IDBKeyData& key) {
     289    database->putOrAdd(*this, requestData, keyData, value, overwriteMode, [this, weakThis = makeWeakPtr(*this), requestData](auto& error, const IDBKeyData& key) {
    290290        LOG(IndexedDB, "UniqueIDBDatabaseTransaction::putOrAdd (callback)");
    291291        if (!weakThis)
     
    308308    ASSERT(database);
    309309   
    310     database->getRecord(requestData, getRecordData, [this, weakThis = makeWeakPtr(*this), requestData](auto& error, const IDBGetResult& result) {
     310    database->getRecord(*this, requestData, getRecordData, [this, weakThis = makeWeakPtr(*this), requestData](auto& error, const IDBGetResult& result) {
    311311        LOG(IndexedDB, "UniqueIDBDatabaseTransaction::getRecord (callback)");
    312312        if (!weakThis)
     
    329329    ASSERT(database);
    330330   
    331     database->getAllRecords(requestData, getAllRecordsData, [this, weakThis = makeWeakPtr(*this), requestData](auto& error, const IDBGetAllResult& result) {
     331    database->getAllRecords(*this, requestData, getAllRecordsData, [this, weakThis = makeWeakPtr(*this), requestData](auto& error, const IDBGetAllResult& result) {
    332332        LOG(IndexedDB, "UniqueIDBDatabaseTransaction::getAllRecords (callback)");
    333333        if (!weakThis)
     
    350350    ASSERT(database);
    351351   
    352     database->getCount(requestData, keyRangeData, [this, weakThis = makeWeakPtr(*this), requestData](auto& error, uint64_t count) {
     352    database->getCount(*this, requestData, keyRangeData, [this, weakThis = makeWeakPtr(*this), requestData](auto& error, uint64_t count) {
    353353        LOG(IndexedDB, "UniqueIDBDatabaseTransaction::getCount (callback)");
    354354        if (!weakThis)
     
    371371    ASSERT(database);
    372372   
    373     database->deleteRecord(requestData, keyRangeData, [this, weakThis = makeWeakPtr(*this), requestData](auto& error) {
     373    database->deleteRecord(*this, requestData, keyRangeData, [this, weakThis = makeWeakPtr(*this), requestData](auto& error) {
    374374        LOG(IndexedDB, "UniqueIDBDatabaseTransaction::deleteRecord (callback)");
    375375        if (!weakThis)
     
    392392    ASSERT(database);
    393393   
    394     database->openCursor(requestData, info, [this, weakThis = makeWeakPtr(*this), requestData](auto& error, const IDBGetResult& result) {
     394    database->openCursor(*this, requestData, info, [this, weakThis = makeWeakPtr(*this), requestData](auto& error, const IDBGetResult& result) {
    395395        LOG(IndexedDB, "UniqueIDBDatabaseTransaction::openCursor (callback)");
    396396        if (!weakThis)
     
    413413    ASSERT(database);
    414414   
    415     database->iterateCursor(requestData, data, [this, weakThis = makeWeakPtr(*this), requestData](auto& error, const IDBGetResult& result) {
     415    database->iterateCursor(*this, requestData, data, [this, weakThis = makeWeakPtr(*this), requestData](auto& error, const IDBGetResult& result) {
    416416        LOG(IndexedDB, "UniqueIDBDatabaseTransaction::iterateCursor (callback)");
    417417        if (!weakThis)
  • trunk/Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.cpp

    r252805 r252839  
    6565{
    6666    return m_quotaManagers.ensure(origin, [] {
    67         return StorageQuotaManager::create(StorageQuotaManager::defaultQuota(), [] {
    68             return 0;
    69         }, [](uint64_t quota, uint64_t currentSpace, uint64_t spaceIncrease, auto callback) {
     67        return makeUnique<StorageQuotaManager>(StorageQuotaManager::defaultQuota(), [](uint64_t quota, uint64_t currentSpace, uint64_t spaceIncrease, auto callback) {
    7068            callback(quota + currentSpace + spaceIncrease);
    7169        });
     
    7371}
    7472
    75 static inline IDBServer::IDBServer::StorageQuotaManagerSpaceRequester storageQuotaManagerSpaceRequester(InProcessIDBServer& server)
    76 {
    77     return [server = &server, weakServer = makeWeakPtr(server)](const ClientOrigin& origin, uint64_t spaceRequested) mutable {
    78         auto* storageQuotaManager = weakServer ? server->quotaManager(origin) : nullptr;
    79         return storageQuotaManager ? storageQuotaManager->requestSpaceOnBackgroundThread(spaceRequested) : StorageQuotaManager::Decision::Deny;
     73static inline IDBServer::IDBServer::QuotaManagerGetter storageQuotaManagerGetter(InProcessIDBServer& server)
     74{
     75    return [weakServer = makeWeakPtr(server)](PAL::SessionID, const auto& origin) {
     76        return weakServer ? weakServer->quotaManager(origin) : nullptr;
    8077    };
    8178}
    8279
    8380InProcessIDBServer::InProcessIDBServer(PAL::SessionID sessionID)
    84     : m_server(IDBServer::IDBServer::create(sessionID, storageQuotaManagerSpaceRequester(*this)))
    85 {
    86     ASSERT(isMainThread());
     81    : m_server(IDBServer::IDBServer::create(sessionID, storageQuotaManagerGetter(*this)))
     82{
    8783    relaxAdoptionRequirement();
    8884    m_connectionToServer = IDBClient::IDBConnectionToServer::create(*this);
     
    9187
    9288InProcessIDBServer::InProcessIDBServer(PAL::SessionID sessionID, const String& databaseDirectoryPath)
    93     : m_server(IDBServer::IDBServer::create(sessionID, databaseDirectoryPath, storageQuotaManagerSpaceRequester(*this)))
    94 {
    95     ASSERT(isMainThread());
     89    : m_server(IDBServer::IDBServer::create(sessionID, databaseDirectoryPath, storageQuotaManagerGetter(*this)))
     90{
    9691    relaxAdoptionRequirement();
    9792    m_connectionToServer = IDBClient::IDBConnectionToServer::create(*this);
  • trunk/Source/WebCore/Modules/indexeddb/shared/InProcessIDBServer.h

    r252805 r252839  
    6565    IDBServer::IDBConnectionToClient& connectionToClient() const;
    6666    IDBServer::IDBServer& server() { return m_server.get(); }
     67
    6768    IDBServer::IDBServer& idbServer() { return m_server.get(); }
    6869
     
    135136    RefPtr<IDBServer::IDBConnectionToClient> m_connectionToClient;
    136137
    137     HashMap<ClientOrigin, RefPtr<StorageQuotaManager>> m_quotaManagers;
     138    HashMap<ClientOrigin, std::unique_ptr<StorageQuotaManager>> m_quotaManagers;
    138139};
    139140
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r252820 r252839  
    11301130                41D41C672256874F00697942 /* ServiceWorkerInternals.mm in Sources */ = {isa = PBXBuildFile; fileRef = 41D41C652256859200697942 /* ServiceWorkerInternals.mm */; };
    11311131                41DE7C7C222DA14300532B65 /* StorageQuotaManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 41DE7C7B222DA13E00532B65 /* StorageQuotaManager.h */; settings = {ATTRIBUTES = (Private, ); }; };
     1132                41DE7C7D222DA14800532B65 /* StorageQuotaUser.h in Headers */ = {isa = PBXBuildFile; fileRef = 41DE7C78222DA13C00532B65 /* StorageQuotaUser.h */; settings = {ATTRIBUTES = (Private, ); }; };
    11321133                41DEFCB61E56C1BD000D9E5F /* JSDOMMapLike.h in Headers */ = {isa = PBXBuildFile; fileRef = 41DEFCB41E56C1B9000D9E5F /* JSDOMMapLike.h */; };
    11331134                41E1B1D10FF5986900576B3B /* AbstractWorker.h in Headers */ = {isa = PBXBuildFile; fileRef = 41E1B1CB0FF5986900576B3B /* AbstractWorker.h */; };
     
    74657466                41D41C652256859200697942 /* ServiceWorkerInternals.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ServiceWorkerInternals.mm; sourceTree = "<group>"; };
    74667467                41D51BB21E4E2E8100131A5B /* LibWebRTCAudioFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LibWebRTCAudioFormat.h; path = libwebrtc/LibWebRTCAudioFormat.h; sourceTree = "<group>"; };
     7468                41DE7C78222DA13C00532B65 /* StorageQuotaUser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StorageQuotaUser.h; sourceTree = "<group>"; };
    74677469                41DE7C7A222DA13D00532B65 /* StorageQuotaManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StorageQuotaManager.cpp; sourceTree = "<group>"; };
    74687470                41DE7C7B222DA13E00532B65 /* StorageQuotaManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StorageQuotaManager.h; sourceTree = "<group>"; };
     
    1710017102                                41DE7C7A222DA13D00532B65 /* StorageQuotaManager.cpp */,
    1710117103                                41DE7C7B222DA13E00532B65 /* StorageQuotaManager.h */,
     17104                                41DE7C78222DA13C00532B65 /* StorageQuotaUser.h */,
    1710217105                                5166D3CC1E8ED41100AD62E3 /* StorageType.h */,
    1710317106                        );
     
    3221732220                                1A37636C1A2E68BB009A7EE2 /* StorageNamespaceProvider.h in Headers */,
    3221832221                                41DE7C7C222DA14300532B65 /* StorageQuotaManager.h in Headers */,
     32222                                41DE7C7D222DA14800532B65 /* StorageQuotaUser.h in Headers */,
    3221932223                                5C9EF2F321F06190003BDC56 /* StorageSessionProvider.h in Headers */,
    3222032224                                5166D3CD1E8ED48F00AD62E3 /* StorageType.h in Headers */,
  • trunk/Source/WebCore/storage/StorageQuotaManager.cpp

    r252805 r252839  
    2828
    2929#include "Logging.h"
    30 #include <wtf/Ref.h>
    31 #include <wtf/RefCounted.h>
    32 #include <wtf/threads/BinarySemaphore.h>
     30#include "StorageQuotaUser.h"
    3331
    3432namespace WebCore {
    3533
    36 Ref<StorageQuotaManager> StorageQuotaManager::create(uint64_t quota, UsageGetter&& usageGetter, QuotaIncreaseRequester&& quotaIncreaseRequester)
    37 {
    38     return adoptRef(*new StorageQuotaManager(quota, WTFMove(usageGetter), WTFMove(quotaIncreaseRequester)));
    39 }
    40 
    41 StorageQuotaManager::StorageQuotaManager(uint64_t quota, UsageGetter&& usageGetter, QuotaIncreaseRequester&& quotaIncreaseRequester)
    42     : m_quota(quota)
    43     , m_usageGetter(WTFMove(usageGetter))
    44     , m_quotaIncreaseRequester(WTFMove(quotaIncreaseRequester))
    45     , m_workQueue(WorkQueue::create("StorageQuotaManager Background Queue", WorkQueue::Type::Serial))
    46     , m_initialQuota(quota)
    47 {
    48 }
    49 
    50 void StorageQuotaManager::requestSpaceOnMainThread(uint64_t spaceRequested, RequestCallback&& callback)
    51 {
    52     ASSERT(isMainThread());
    53 
    54     // Fast path.
    55     if (m_quotaCountDownLock.tryLock()) {
    56         if (tryGrantRequest(spaceRequested)) {
    57             m_quotaCountDownLock.unlock();
    58             callback(Decision::Grant);
    59             return;
     34StorageQuotaManager::~StorageQuotaManager()
     35{
     36    while (!m_pendingRequests.isEmpty())
     37        m_pendingRequests.takeFirst().callback(Decision::Deny);
     38}
     39
     40uint64_t StorageQuotaManager::spaceUsage() const
     41{
     42    uint64_t usage = 0;
     43    for (auto& user : m_users)
     44        usage += user->spaceUsed();
     45    return usage;
     46}
     47
     48void StorageQuotaManager::updateQuotaBasedOnSpaceUsage()
     49{
     50    if (!m_quota)
     51        return;
     52
     53    auto defaultQuotaStep = m_quota / 10;
     54    m_quota = std::max(m_quota, defaultQuotaStep * ((spaceUsage() / defaultQuotaStep) + 1));
     55}
     56
     57void StorageQuotaManager::initializeUsersIfNeeded()
     58{
     59    if (m_pendingInitializationUsers.isEmpty())
     60        return;
     61
     62    Vector<StorageQuotaUser*> usersToInitialize;
     63    for (auto& keyValue : m_pendingInitializationUsers) {
     64        if (keyValue.value == WhenInitializedCalled::No) {
     65            keyValue.value = WhenInitializedCalled::Yes;
     66            usersToInitialize.append(keyValue.key);
    6067        }
    61         m_quotaCountDownLock.unlock();
    62     }
    63 
    64     m_workQueue->dispatch([this, protectedThis = makeRef(*this), spaceRequested, callback = WTFMove(callback)]() mutable {
    65         auto decision = requestSpaceOnBackgroundThread(spaceRequested);
    66         callOnMainThread([callback = WTFMove(callback), decision]() mutable {
    67             callback(decision);
     68    }
     69    for (auto* user : usersToInitialize) {
     70        if (m_pendingInitializationUsers.contains(user))
     71            askUserToInitialize(*user);
     72    }
     73}
     74
     75void StorageQuotaManager::askUserToInitialize(StorageQuotaUser& user)
     76{
     77    user.whenInitialized([this, &user, weakThis = makeWeakPtr(this)]() {
     78        if (!weakThis)
     79            return;
     80
     81        if (m_pendingInitializationUsers.remove(&user))
     82            m_users.add(&user);
     83
     84        if (!m_pendingInitializationUsers.isEmpty())
     85            return;
     86
     87        // Make sure quota is set before handling first request.
     88        if (m_state == State::Uninitialized) {
     89            updateQuotaBasedOnSpaceUsage();
     90            m_state = State::MakingDecisionForRequest;
     91        }
     92
     93        processPendingRequests({ });
     94    });
     95}
     96
     97void StorageQuotaManager::addUser(StorageQuotaUser& user)
     98{
     99    ASSERT(!m_pendingInitializationUsers.contains(&user));
     100    ASSERT(!m_users.contains(&user));
     101    m_pendingInitializationUsers.add(&user, WhenInitializedCalled::No);
     102
     103    if (!m_pendingRequests.isEmpty())
     104        askUserToInitialize(user);
     105}
     106
     107bool StorageQuotaManager::shouldAskForMoreSpace(uint64_t spaceIncrease) const
     108{
     109    if (!spaceIncrease)
     110        return false;
     111
     112    return spaceUsage() + spaceIncrease > m_quota;
     113}
     114
     115void StorageQuotaManager::removeUser(StorageQuotaUser& user)
     116{
     117    ASSERT(m_users.contains(&user) || m_pendingInitializationUsers.contains(&user));
     118    m_users.remove(&user);
     119    if (m_pendingInitializationUsers.remove(&user) && m_pendingInitializationUsers.isEmpty()) {
     120        // When being cleared, quota users may remove themselves and add themselves to trigger reinitialization.
     121        // Let's wait for addUser to be called before processing pending requests.
     122        callOnMainThread([this, weakThis = makeWeakPtr(this)] {
     123            if (!weakThis)
     124                return;
     125
     126            if (m_pendingInitializationUsers.isEmpty())
     127                this->processPendingRequests({ });
    68128        });
     129    }
     130}
     131
     132void StorageQuotaManager::requestSpace(uint64_t spaceIncrease, RequestCallback&& callback)
     133{
     134    if (!m_pendingRequests.isEmpty()) {
     135        m_pendingRequests.append({ spaceIncrease, WTFMove(callback) });
     136        return;
     137    }
     138
     139    if (!spaceIncrease) {
     140        callback(Decision::Grant);
     141        return;
     142    }
     143
     144    initializeUsersIfNeeded();
     145
     146    if (!m_pendingInitializationUsers.isEmpty()) {
     147        m_pendingRequests.append({ spaceIncrease, WTFMove(callback) });
     148        return;
     149    }
     150
     151    if (shouldAskForMoreSpace(spaceIncrease)) {
     152        m_pendingRequests.append({ spaceIncrease, WTFMove(callback) });
     153
     154        // Try processing request again after making sure usage is accurate.
     155        m_state = State::ComputingSpaceUsed;
     156        for (auto& user : copyToVector(m_users))
     157            user->computeSpaceUsed();
     158
     159        if (!m_pendingInitializationUsers.isEmpty())
     160            return;
     161
     162        m_state = State::AskingForMoreSpace;
     163        askForMoreSpace(spaceIncrease);
     164        return;
     165    }
     166
     167    m_state = State::MakingDecisionForRequest;
     168    callback(Decision::Grant);
     169}
     170
     171void StorageQuotaManager::askForMoreSpace(uint64_t spaceIncrease)
     172{
     173    ASSERT(shouldAskForMoreSpace(spaceIncrease));
     174    ASSERT(m_state == State::AskingForMoreSpace);
     175
     176    RELEASE_LOG(Storage, "%p - StorageQuotaManager::askForMoreSpace %" PRIu64, this, spaceIncrease);
     177    m_state = State::WaitingForSpaceIncreaseResponse;
     178    m_spaceIncreaseRequester(m_quota, spaceUsage(), spaceIncrease, [this, weakThis = makeWeakPtr(*this)](Optional<uint64_t> newQuota) {
     179        if (!weakThis)
     180            return;
     181
     182        RELEASE_LOG(Storage, "%p - StorageQuotaManager::askForMoreSpace received response %" PRIu64, this, newQuota ? *newQuota : 0);
     183
     184        m_state = State::AskingForMoreSpace;
     185        processPendingRequests(newQuota);
    69186    });
    70187}
    71188
    72 StorageQuotaManager::Decision StorageQuotaManager::requestSpaceOnBackgroundThread(uint64_t spaceRequested)
    73 {
    74     ASSERT(!isMainThread());
    75 
    76     LockHolder locker(m_quotaCountDownLock);
    77 
    78     if (tryGrantRequest(spaceRequested))
    79         return Decision::Grant;
    80 
    81     m_usage = m_usageGetter();
    82     updateQuotaBasedOnUsage();
    83     m_quotaCountDown = m_usage < m_quota ? m_quota - m_usage : 0;
    84     if (tryGrantRequest(spaceRequested))
    85         return Decision::Grant;
    86 
    87     // Block this thread until getting decsion for quota increase.
    88     BinarySemaphore semaphore;
    89     callOnMainThread([this, protectedThis = makeRef(*this), spaceRequested, &semaphore]() mutable {
    90         RELEASE_LOG(Storage, "%p - StorageQuotaManager asks for quota increase %" PRIu64, this, spaceRequested);
    91         m_quotaIncreaseRequester(m_quota, m_usage, spaceRequested, [this, protectedThis = WTFMove(protectedThis), &semaphore](Optional<uint64_t> newQuota) mutable {
    92             RELEASE_LOG(Storage, "%p - StorageQuotaManager receives quota increase response %" PRIu64, this, newQuota ? *newQuota : 0);
    93             ASSERT(isMainThread());
    94 
    95             if (newQuota)
    96                 m_quota = *newQuota;
    97 
    98             semaphore.signal();
    99         });
    100     });
    101 
    102     semaphore.wait();
    103 
    104     m_usage = m_usageGetter();
    105     m_quotaCountDown = m_usage < m_quota ? m_quota - m_usage : 0;
    106     return tryGrantRequest(spaceRequested) ? Decision::Grant : Decision::Deny;
    107 }
    108 
    109 bool StorageQuotaManager::tryGrantRequest(uint64_t spaceRequested)
    110 {
    111     ASSERT(m_quotaCountDownLock.isLocked());
    112     if (spaceRequested <= m_quotaCountDown) {
    113         m_quotaCountDown -= spaceRequested;
    114         return true;
    115     }
    116     return false;
    117 }
    118    
    119 void StorageQuotaManager::updateQuotaBasedOnUsage()
    120 {
    121     // When StorageQuotaManager is used for the first time, we want to make sure its initial quota is bigger than current disk usage,
    122     // based on the assumption that the quota was increased to at least the disk usage under user's permission before.
    123     ASSERT(m_quotaCountDownLock.isLocked());
    124     if (!m_quotaUpdatedBasedOnUsage) {
    125         m_quotaUpdatedBasedOnUsage = true;
    126         auto defaultQuotaStep = m_quota / 10;
    127         m_quota = std::max(m_quota, defaultQuotaStep * ((m_usage / defaultQuotaStep) + 1));
    128     }
    129 }
    130 
    131 void StorageQuotaManager::resetQuotaUpdatedBasedOnUsageForTesting()
    132 {
    133     LockHolder locker(m_quotaCountDownLock);
    134     m_quota = m_initialQuota;
    135     m_quotaCountDown = 0;
    136     m_quotaUpdatedBasedOnUsage = false;
    137 }
    138 
    139 void StorageQuotaManager::resetQuotaForTesting()
    140 {
    141     LockHolder locker(m_quotaCountDownLock);
    142     m_quota = m_initialQuota;
    143     m_quotaCountDown = 0;
     189void StorageQuotaManager::processPendingRequests(Optional<uint64_t> newQuota)
     190{
     191    if (m_pendingRequests.isEmpty())
     192        return;
     193
     194    if (newQuota)
     195        m_quota = *newQuota;
     196
     197    if (m_state == State::WaitingForSpaceIncreaseResponse)
     198        return;
     199
     200    if (!m_pendingInitializationUsers.isEmpty())
     201        return;
     202
     203    if (m_state == State::AskingForMoreSpace) {
     204        auto request = m_pendingRequests.takeFirst();
     205        bool shouldAllowRequest = !shouldAskForMoreSpace(request.spaceIncrease);
     206
     207        RELEASE_LOG(Storage, "%p - StorageQuotaManager::processPendingRequests first request decision is %d", this, shouldAllowRequest);
     208
     209        m_state = State::MakingDecisionForRequest;
     210        request.callback(shouldAllowRequest ? Decision::Grant : Decision::Deny);
     211    }
     212
     213    while (!m_pendingRequests.isEmpty()) {
     214        auto& request = m_pendingRequests.first();
     215
     216        if (shouldAskForMoreSpace(request.spaceIncrease)) {
     217            if (m_state == State::MakingDecisionForRequest) {
     218                m_state = State::ComputingSpaceUsed;
     219                for (auto& user : copyToVector(m_users))
     220                    user->computeSpaceUsed();
     221
     222                if (!m_pendingInitializationUsers.isEmpty())
     223                    return;
     224            }
     225
     226            m_state = State::AskingForMoreSpace;
     227            uint64_t spaceIncrease = 0;
     228            for (auto& pendingRequest : m_pendingRequests)
     229                spaceIncrease += pendingRequest.spaceIncrease;
     230            askForMoreSpace(spaceIncrease);
     231            return;
     232        }
     233
     234        m_state = State::MakingDecisionForRequest;
     235        m_pendingRequests.takeFirst().callback(Decision::Grant);
     236    }
    144237}
    145238
  • trunk/Source/WebCore/storage/StorageQuotaManager.h

    r252805 r252839  
    2626#pragma once
    2727
     28#include "ClientOrigin.h"
    2829#include <wtf/CompletionHandler.h>
    2930#include <wtf/Deque.h>
     
    3132#include <wtf/HashSet.h>
    3233#include <wtf/WeakPtr.h>
    33 #include <wtf/WorkQueue.h>
    3434
    3535namespace WebCore {
    3636
    37 class StorageQuotaManager : public ThreadSafeRefCounted<StorageQuotaManager>, public CanMakeWeakPtr<StorageQuotaManager> {
     37class StorageQuotaUser;
     38
     39class StorageQuotaManager : public CanMakeWeakPtr<StorageQuotaManager> {
    3840    WTF_MAKE_FAST_ALLOCATED;
    3941public:
    40     using UsageGetter = Function<uint64_t()>;
    41     using QuotaIncreaseRequester = Function<void(uint64_t currentQuota, uint64_t currentUsage, uint64_t requestedIncrease, CompletionHandler<void(Optional<uint64_t>)>&&)>;
    42     WEBCORE_EXPORT static Ref<StorageQuotaManager> create(uint64_t quota, UsageGetter&&, QuotaIncreaseRequester&&);
     42    using SpaceIncreaseRequester = WTF::Function<void(uint64_t quota, uint64_t currentSpace, uint64_t spaceIncrease, CompletionHandler<void(Optional<uint64_t>)>&&)>;
     43    StorageQuotaManager(uint64_t quota, SpaceIncreaseRequester&& spaceIncreaseRequester)
     44        : m_quota(quota)
     45        , m_spaceIncreaseRequester(WTFMove(spaceIncreaseRequester))
     46    {
     47    }
     48    WEBCORE_EXPORT ~StorageQuotaManager();
    4349
    4450    static constexpr uint64_t defaultThirdPartyQuotaFromPerOriginQuota(uint64_t quota) { return quota / 10; }
     51
    4552    static constexpr uint64_t defaultQuota() { return 1000 * MB; }
    4653    static constexpr uint64_t defaultThirdPartyQuota() { return defaultThirdPartyQuotaFromPerOriginQuota(defaultQuota()); }
    4754
     55    WEBCORE_EXPORT void addUser(StorageQuotaUser&);
     56    WEBCORE_EXPORT void removeUser(StorageQuotaUser&);
     57
    4858    enum class Decision { Deny, Grant };
    4959    using RequestCallback = CompletionHandler<void(Decision)>;
    50     WEBCORE_EXPORT void requestSpaceOnMainThread(uint64_t, RequestCallback&&);
    51     WEBCORE_EXPORT Decision requestSpaceOnBackgroundThread(uint64_t);
     60    WEBCORE_EXPORT void requestSpace(uint64_t, RequestCallback&&);
     61    void resetQuota(uint64_t newQuota) { m_quota = newQuota; }
    5262
    53     WEBCORE_EXPORT void resetQuotaUpdatedBasedOnUsageForTesting();
    54     WEBCORE_EXPORT void resetQuotaForTesting();
     63    WEBCORE_EXPORT void updateQuotaBasedOnSpaceUsage();
     64
     65    enum class State {
     66        Uninitialized,
     67        ComputingSpaceUsed,
     68        WaitingForSpaceIncreaseResponse,
     69        AskingForMoreSpace,
     70        MakingDecisionForRequest,
     71    };
     72    State state() const { return m_state; }
    5573
    5674private:
    57     StorageQuotaManager(uint64_t quota, UsageGetter&&, QuotaIncreaseRequester&&);
    58     bool tryGrantRequest(uint64_t);
     75    uint64_t spaceUsage() const;
     76    bool shouldAskForMoreSpace(uint64_t spaceIncrease) const;
     77    void askForMoreSpace(uint64_t spaceIncrease);
    5978
    60     void updateQuotaBasedOnUsage();
     79    void initializeUsersIfNeeded();
     80    void askUserToInitialize(StorageQuotaUser&);
    6181
    62     Lock m_quotaCountDownLock;
    63     uint64_t m_quotaCountDown { 0 };
     82    void processPendingRequests(Optional<uint64_t>);
     83
    6484    uint64_t m_quota { 0 };
    65     uint64_t m_usage { 0 };
    6685
    67     UsageGetter m_usageGetter;
    68     QuotaIncreaseRequester m_quotaIncreaseRequester;
     86    SpaceIncreaseRequester m_spaceIncreaseRequester;
    6987
    70     Ref<WorkQueue> m_workQueue;
     88    enum class WhenInitializedCalled { No, Yes };
     89    HashMap<StorageQuotaUser*, WhenInitializedCalled> m_pendingInitializationUsers;
     90    HashSet<StorageQuotaUser*> m_users;
    7191
    72     bool m_quotaUpdatedBasedOnUsage { false };
     92    struct PendingRequest {
     93        uint64_t spaceIncrease;
     94        RequestCallback callback;
     95    };
     96    Deque<PendingRequest> m_pendingRequests;
    7397
    74     // Test only.
    75     uint64_t m_initialQuota { 0 };
     98    State m_state { State::Uninitialized };
    7699};
    77100
  • trunk/Source/WebKit/ChangeLog

    r252819 r252839  
     12019-11-23  Commit Queue  <commit-queue@webkit.org>
     2
     3        Unreviewed, rolling out r252805.
     4        https://bugs.webkit.org/show_bug.cgi?id=204553
     5
     6        Caused test failures and ASan crashes (Requested by ap on
     7        #webkit).
     8
     9        Reverted changeset:
     10
     11        "Cross-thread version StorageQuotaManager"
     12        https://bugs.webkit.org/show_bug.cgi?id=203971
     13        https://trac.webkit.org/changeset/252805
     14
    1152019-11-22  Alex Christensen  <achristensen@webkit.org>
    216
  • trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp

    r252819 r252839  
    6666#include "WebsiteDataStoreParameters.h"
    6767#include "WebsiteDataType.h"
    68 #include <WebCore/ClientOrigin.h>
    6968#include <WebCore/CookieJar.h>
    7069#include <WebCore/DNS.h>
     
    318317    setSession(sessionID, NetworkSession::create(*this, WTFMove(parameters.defaultDataStoreParameters.networkSessionParameters)));
    319318
    320     SandboxExtension::consumePermanently(parameters.defaultDataStoreParameters.cacheStorageDirectoryExtensionHandle);
    321     addSessionStorageQuotaManager(sessionID, parameters.defaultDataStoreParameters.perOriginStorageQuota, parameters.defaultDataStoreParameters.perThirdPartyOriginStorageQuota, parameters.defaultDataStoreParameters.cacheStorageDirectory, parameters.defaultDataStoreParameters.cacheStorageDirectoryExtensionHandle);
    322 
    323319#if ENABLE(INDEXED_DATABASE)
    324320    addIndexedDatabaseSession(sessionID, parameters.defaultDataStoreParameters.indexedDatabaseDirectory, parameters.defaultDataStoreParameters.indexedDatabaseDirectoryExtensionHandle);
     
    331327    }
    332328#endif
     329    initializeStorageQuota(parameters.defaultDataStoreParameters);
    333330
    334331    m_storageManagerSet->add(sessionID, parameters.defaultDataStoreParameters.localStorageDirectory, parameters.defaultDataStoreParameters.localStorageDirectoryExtensionHandle);
     
    438435void NetworkProcess::addWebsiteDataStore(WebsiteDataStoreParameters&& parameters)
    439436{
    440     auto sessionID = parameters.networkSessionParameters.sessionID;
    441 
    442     addSessionStorageQuotaManager(sessionID, parameters.perOriginStorageQuota, parameters.perThirdPartyOriginStorageQuota, parameters.cacheStorageDirectory, parameters.cacheStorageDirectoryExtensionHandle);
    443 
    444437#if ENABLE(INDEXED_DATABASE)
    445     addIndexedDatabaseSession(sessionID, parameters.indexedDatabaseDirectory, parameters.indexedDatabaseDirectoryExtensionHandle);
     438    addIndexedDatabaseSession(parameters.networkSessionParameters.sessionID, parameters.indexedDatabaseDirectory, parameters.indexedDatabaseDirectoryExtensionHandle);
    446439#endif
    447440
    448441#if ENABLE(SERVICE_WORKER)
    449442    if (parentProcessHasServiceWorkerEntitlement())
    450         addServiceWorkerSession(sessionID, parameters.serviceWorkerProcessTerminationDelayEnabled, WTFMove(parameters.serviceWorkerRegistrationDirectory), parameters.serviceWorkerRegistrationDirectoryExtensionHandle);
    451 #endif
    452 
    453     m_storageManagerSet->add(sessionID, parameters.localStorageDirectory, parameters.localStorageDirectoryExtensionHandle);
     443        addServiceWorkerSession(parameters.networkSessionParameters.sessionID, parameters.serviceWorkerProcessTerminationDelayEnabled, WTFMove(parameters.serviceWorkerRegistrationDirectory), parameters.serviceWorkerRegistrationDirectoryExtensionHandle);
     444#endif
     445
     446    m_storageManagerSet->add(parameters.networkSessionParameters.sessionID, parameters.localStorageDirectory, parameters.localStorageDirectoryExtensionHandle);
     447
     448    initializeStorageQuota(parameters);
    454449
    455450    RemoteNetworkingContext::ensureWebsiteDataStoreSession(*this, WTFMove(parameters));
    456451}
    457452
    458 void NetworkProcess::addSessionStorageQuotaManager(PAL::SessionID sessionID, uint64_t defaultQuota, uint64_t defaultThirdPartyQuota, const String& cacheRootPath, SandboxExtension::Handle& cacheRootPathHandle)
    459 {
    460     LockHolder locker(m_sessionStorageQuotaManagersLock);
    461     auto [iter, isNewEntry] = m_sessionStorageQuotaManagers.ensure(sessionID, [defaultQuota, defaultThirdPartyQuota, &cacheRootPath] {
    462         return makeUnique<SessionStorageQuotaManager>(cacheRootPath, defaultQuota, defaultThirdPartyQuota);
    463     });
    464     if (isNewEntry)
    465         SandboxExtension::consumePermanently(cacheRootPathHandle);
    466 }
    467 
    468 void NetworkProcess::removeSessionStorageQuotaManager(PAL::SessionID sessionID)
    469 {
    470     LockHolder locker(m_sessionStorageQuotaManagersLock);
    471     ASSERT(m_sessionStorageQuotaManagers.contains(sessionID));
    472     m_sessionStorageQuotaManagers.remove(sessionID);
     453void NetworkProcess::initializeStorageQuota(const WebsiteDataStoreParameters& parameters)
     454{
     455    auto& managers =  m_storageQuotaManagers.ensure(parameters.networkSessionParameters.sessionID, [] {
     456        return StorageQuotaManagers { };
     457    }).iterator->value;
     458    managers.setDefaultQuotas(parameters.perOriginStorageQuota, parameters.perThirdPartyOriginStorageQuota);
    473459}
    474460
     
    591577
    592578    m_storageManagerSet->remove(sessionID);
     579
     580    m_storageQuotaManagers.remove(sessionID);
    593581}
    594582
     
    14811469        clearDiskCache(modifiedSince, [clearTasksHandler = WTFMove(clearTasksHandler)] { });
    14821470
     1471    if (websiteDataTypes.contains(WebsiteDataType::IndexedDBDatabases) || websiteDataTypes.contains(WebsiteDataType::DOMCache))
     1472        clearStorageQuota(sessionID);
     1473
    14831474    if (websiteDataTypes.contains(WebsiteDataType::AdClickAttributions)) {
    14841475        if (auto* networkSession = this->networkSession(sessionID))
     
    15731564        WebCore::CredentialStorage::removeSessionCredentialsWithOrigins(originDatas);
    15741565    }
     1566
     1567    // FIXME: Implement storage quota clearing for these origins.
     1568}
     1569
     1570void NetworkProcess::clearStorageQuota(PAL::SessionID sessionID)
     1571{
     1572    auto iterator = m_storageQuotaManagers.find(sessionID);
     1573    if (iterator == m_storageQuotaManagers.end())
     1574        return;
     1575
     1576    auto& managers = iterator->value;
     1577    for (auto& manager : managers.managersPerOrigin())
     1578        manager.value->resetQuota(managers.defaultQuota(manager.key));
    15751579}
    15761580
     
    22142218    }
    22152219
    2216     return IDBServer::IDBServer::create(sessionID, path, [this, weakThis = makeWeakPtr(this), sessionID](const auto& origin, uint64_t spaceRequested) {
    2217         RefPtr<StorageQuotaManager> storageQuotaManager = weakThis ? this->storageQuotaManager(sessionID, origin) : nullptr;
    2218         return storageQuotaManager ? storageQuotaManager->requestSpaceOnBackgroundThread(spaceRequested) : StorageQuotaManager::Decision::Deny;
     2220    return IDBServer::IDBServer::create(sessionID, path, [this, weakThis = makeWeakPtr(this)](PAL::SessionID sessionID, const auto& origin) -> StorageQuotaManager* {
     2221        if (!weakThis)
     2222            return nullptr;
     2223        return &this->storageQuotaManager(sessionID, origin);
    22192224    });
    22202225}
     
    23032308        if (!indexedDatabaseDirectory.isEmpty())
    23042309            postStorageTask(createCrossThreadTask(*this, &NetworkProcess::ensurePathExists, indexedDatabaseDirectory));
    2305         setSessionStorageQuotaManagerIDBRootPath(sessionID, indexedDatabaseDirectory);
    2306     }
    2307 }
    2308 
    2309 void NetworkProcess::setSessionStorageQuotaManagerIDBRootPath(PAL::SessionID sessionID, const String& idbRootPath)
    2310 {
    2311     LockHolder locker(m_sessionStorageQuotaManagersLock);
    2312     auto* sessionStorageQuotaManager = m_sessionStorageQuotaManagers.get(sessionID);
    2313     ASSERT(sessionStorageQuotaManager);
    2314     sessionStorageQuotaManager->setIDBRootPath(idbRootPath);
    2315 }
    2316 
     2310    }
     2311}
    23172312#endif // ENABLE(INDEXED_DATABASE)
    23182313
     
    23312326void NetworkProcess::updateQuotaBasedOnSpaceUsageForTesting(PAL::SessionID sessionID, const ClientOrigin& origin)
    23322327{
    2333     auto storageQuotaManager = this->storageQuotaManager(sessionID, origin);
    2334     storageQuotaManager->resetQuotaUpdatedBasedOnUsageForTesting();
    2335 }
    2336 
    2337 void NetworkProcess::resetQuota(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
    2338 {
    2339     LockHolder locker(m_sessionStorageQuotaManagersLock);
    2340     if (auto* sessionStorageQuotaManager = m_sessionStorageQuotaManagers.get(sessionID)) {
    2341         for (auto storageQuotaManager : sessionStorageQuotaManager->existingStorageQuotaManagers())
    2342             storageQuotaManager->resetQuotaForTesting();
    2343     }
    2344     completionHandler();
     2328    auto& manager = storageQuotaManager(sessionID, origin);
     2329    manager.resetQuota(m_storageQuotaManagers.find(sessionID)->value.defaultQuota(origin));
     2330    manager.updateQuotaBasedOnSpaceUsage();
    23452331}
    23462332
     
    24192405}
    24202406
    2421 RefPtr<StorageQuotaManager> NetworkProcess::storageQuotaManager(PAL::SessionID sessionID, const ClientOrigin& origin)
    2422 {
    2423     LockHolder locker(m_sessionStorageQuotaManagersLock);
    2424     auto* sessionStorageQuotaManager = m_sessionStorageQuotaManagers.get(sessionID);
    2425     if (!sessionStorageQuotaManager)
    2426         return nullptr;
    2427 
    2428     String idbRootPath;
    2429 #if ENABLE(INDEXED_DATABASE)
    2430     idbRootPath = sessionStorageQuotaManager->idbRootPath();
    2431 #endif
    2432     StorageQuotaManager::UsageGetter usageGetter = [cacheRootPath = sessionStorageQuotaManager->cacheRootPath().isolatedCopy(), idbRootPath = idbRootPath.isolatedCopy(), origin = origin.isolatedCopy()]() {
    2433         ASSERT(!isMainThread());   
    2434 
    2435         uint64_t usage = CacheStorage::Engine::diskUsage(cacheRootPath, origin);
    2436 #if ENABLE(INDEXED_DATABASE)
    2437         usage += IDBServer::IDBServer::diskUsage(idbRootPath, origin);
    2438 #endif
    2439 
    2440         return usage;
    2441     };
    2442     StorageQuotaManager::QuotaIncreaseRequester quotaIncreaseRequester = [this, weakThis = makeWeakPtr(*this), sessionID, origin] (uint64_t currentQuota, uint64_t currentSpace, uint64_t requestedIncrease, auto&& callback) {
    2443         ASSERT(isMainThread());
     2407class QuotaUserInitializer final : public WebCore::StorageQuotaUser {
     2408    WTF_MAKE_FAST_ALLOCATED;
     2409public:
     2410    explicit QuotaUserInitializer(StorageQuotaManager& manager)
     2411        : m_manager(makeWeakPtr(manager))
     2412    {
     2413        manager.addUser(*this);
     2414    }
     2415
     2416    ~QuotaUserInitializer()
     2417    {
     2418        if (m_manager)
     2419            m_manager->removeUser(*this);
     2420        if (m_callback)
     2421            m_callback();
     2422    }
     2423
     2424private:
     2425    // StorageQuotaUser API.
     2426    uint64_t spaceUsed() const final
     2427    {
     2428        ASSERT_NOT_REACHED();
     2429        return 0;
     2430    }
     2431
     2432    void whenInitialized(CompletionHandler<void()>&& callback) final
     2433    {
     2434        m_callback = WTFMove(callback);
     2435    }
     2436
     2437    WeakPtr<StorageQuotaManager> m_manager;
     2438    CompletionHandler<void()> m_callback;
     2439};
     2440
     2441void NetworkProcess::initializeQuotaUsers(StorageQuotaManager& manager, PAL::SessionID sessionID, const ClientOrigin& origin)
     2442{
     2443    RunLoop::main().dispatch([this, weakThis = makeWeakPtr(this), sessionID, origin, user = makeUnique<QuotaUserInitializer>(manager)]() mutable {
    24442444        if (!weakThis)
    2445             callback({ });
    2446         requestStorageSpace(sessionID, origin, currentQuota, currentSpace, requestedIncrease, WTFMove(callback));
    2447     };
    2448 
    2449     return sessionStorageQuotaManager->ensureOriginStorageQuotaManager(origin, sessionStorageQuotaManager->defaultQuota(origin), WTFMove(usageGetter), WTFMove(quotaIncreaseRequester)).ptr();
     2445            return;
     2446        this->idbServer(sessionID).initializeQuotaUser(origin);
     2447        CacheStorage::Engine::initializeQuotaUser(*this, sessionID, origin, [user = WTFMove(user)] { });
     2448    });
     2449}
     2450
     2451StorageQuotaManager& NetworkProcess::storageQuotaManager(PAL::SessionID sessionID, const ClientOrigin& origin)
     2452{
     2453    auto& storageQuotaManagers = m_storageQuotaManagers.ensure(sessionID, [] {
     2454        return StorageQuotaManagers { };
     2455    }).iterator->value;
     2456    return *storageQuotaManagers.managersPerOrigin().ensure(origin, [this, &storageQuotaManagers, sessionID, &origin] {
     2457        auto manager = makeUnique<StorageQuotaManager>(storageQuotaManagers.defaultQuota(origin), [this, sessionID, origin](uint64_t quota, uint64_t currentSpace, uint64_t spaceIncrease, auto callback) {
     2458            this->requestStorageSpace(sessionID, origin, quota, currentSpace, spaceIncrease, WTFMove(callback));
     2459        });
     2460        initializeQuotaUsers(*manager, sessionID, origin);
     2461        return manager;
     2462    }).iterator->value;
    24502463}
    24512464
  • trunk/Source/WebKit/NetworkProcess/NetworkProcess.h

    r252819 r252839  
    285285
    286286    void updateQuotaBasedOnSpaceUsageForTesting(PAL::SessionID, const WebCore::ClientOrigin&);
    287     void resetQuota(PAL::SessionID, CompletionHandler<void()>&&);
    288287
    289288#if ENABLE(SANDBOX_EXTENSIONS)
     
    329328    void markAdClickAttributionsAsExpiredForTesting(PAL::SessionID, CompletionHandler<void()>&&);
    330329
    331     RefPtr<WebCore::StorageQuotaManager> storageQuotaManager(PAL::SessionID, const WebCore::ClientOrigin&);
     330    WebCore::StorageQuotaManager& storageQuotaManager(PAL::SessionID, const WebCore::ClientOrigin&);
    332331
    333332    void addKeptAliveLoad(Ref<NetworkResourceLoader>&&);
     
    444443    HashSet<WebCore::SecurityOriginData> indexedDatabaseOrigins(const String& path);
    445444    Ref<WebCore::IDBServer::IDBServer> createIDBServer(PAL::SessionID);
    446     void setSessionStorageQuotaManagerIDBRootPath(PAL::SessionID, const String& idbRootPath);
    447445#endif
    448446
     
    464462    void ensurePathExists(const String& path);
    465463
    466     class SessionStorageQuotaManager {
    467         WTF_MAKE_FAST_ALLOCATED;
    468     public:
    469         SessionStorageQuotaManager(const String& cacheRootPath, uint64_t defaultQuota, uint64_t defaultThirdPartyQuota)
    470             : m_cacheRootPath(cacheRootPath)
    471             , m_defaultQuota(defaultQuota)
    472             , m_defaultThirdPartyQuota(defaultThirdPartyQuota)
    473         {
    474         }
    475         uint64_t defaultQuota(const WebCore::ClientOrigin& origin) const { return origin.topOrigin == origin.clientOrigin ? m_defaultQuota : m_defaultThirdPartyQuota; }
    476 
    477         Ref<WebCore::StorageQuotaManager> ensureOriginStorageQuotaManager(WebCore::ClientOrigin origin, uint64_t quota, WebCore::StorageQuotaManager::UsageGetter&& usageGetter, WebCore::StorageQuotaManager::QuotaIncreaseRequester&& quotaIncreaseRequester)
    478         {
    479             auto [iter, isNewEntry] = m_storageQuotaManagers.ensure(origin, [quota, usageGetter = WTFMove(usageGetter), quotaIncreaseRequester = WTFMove(quotaIncreaseRequester)]() mutable {
    480                 return WebCore::StorageQuotaManager::create(quota, WTFMove(usageGetter), WTFMove(quotaIncreaseRequester));
    481             });
    482             return makeRef(*iter->value);
    483         }
    484 
    485         auto existingStorageQuotaManagers() { return m_storageQuotaManagers.values(); }
    486 
    487         const String& cacheRootPath() const { return m_cacheRootPath; }
    488 #if ENABLE(INDEXED_DATABASE)
    489         void setIDBRootPath(const String& idbRootPath) { m_idbRootPath = idbRootPath; }
    490         const String& idbRootPath() const { return m_idbRootPath; }
    491 #endif
    492 
    493     private:
    494         String m_cacheRootPath;
    495 #if ENABLE(INDEXED_DATABASE)
    496         String m_idbRootPath;
    497 #endif
    498         uint64_t m_defaultQuota { WebCore::StorageQuotaManager::defaultQuota() };
    499         uint64_t m_defaultThirdPartyQuota { WebCore::StorageQuotaManager::defaultThirdPartyQuota() };
    500         HashMap<WebCore::ClientOrigin, RefPtr<WebCore::StorageQuotaManager>> m_storageQuotaManagers;
    501     };
    502     void addSessionStorageQuotaManager(PAL::SessionID, uint64_t defaultQuota, uint64_t defaultThirdPartyQuota, const String& cacheRootPath, SandboxExtension::Handle&);
    503     void removeSessionStorageQuotaManager(PAL::SessionID);
     464    void clearStorageQuota(PAL::SessionID);
     465    void initializeStorageQuota(const WebsiteDataStoreParameters&);
    504466
    505467    // Connections to WebProcesses.
     
    572534#endif
    573535   
    574     Lock m_sessionStorageQuotaManagersLock;
    575     HashMap<PAL::SessionID, std::unique_ptr<SessionStorageQuotaManager>> m_sessionStorageQuotaManagers;
     536    class StorageQuotaManagers {
     537    public:
     538        uint64_t defaultQuota(const WebCore::ClientOrigin& origin) const { return origin.topOrigin == origin.clientOrigin ? m_defaultQuota : m_defaultThirdPartyQuota; }
     539        void setDefaultQuotas(uint64_t defaultQuota, uint64_t defaultThirdPartyQuota)
     540        {
     541            m_defaultQuota = defaultQuota;
     542            m_defaultThirdPartyQuota = defaultThirdPartyQuota;
     543        }
     544
     545        HashMap<WebCore::ClientOrigin, std::unique_ptr<WebCore::StorageQuotaManager>>& managersPerOrigin() { return m_managersPerOrigin; }
     546
     547    private:
     548        uint64_t m_defaultQuota { WebCore::StorageQuotaManager::defaultQuota() };
     549        uint64_t m_defaultThirdPartyQuota { WebCore::StorageQuotaManager::defaultThirdPartyQuota() };
     550        HashMap<WebCore::ClientOrigin, std::unique_ptr<WebCore::StorageQuotaManager>> m_managersPerOrigin;
     551    };
     552    HashMap<PAL::SessionID, StorageQuotaManagers> m_storageQuotaManagers;
    576553
    577554    OptionSet<NetworkCache::CacheOption> m_cacheOptions;
  • trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in

    r252819 r252839  
    164164    SetServiceWorkerFetchTimeoutForTesting(Seconds seconds) -> () Synchronous
    165165    ResetServiceWorkerFetchTimeoutForTesting() -> () Synchronous
    166 
    167     ResetQuota(PAL::SessionID sessionID) -> () Async
    168166}
  • trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngine.cpp

    r252805 r252839  
    197197}
    198198
    199 static uint64_t getDirectorySize(const String& directoryPath)
    200 {
    201     ASSERT(!isMainThread());
    202 
    203     uint64_t directorySize = 0;
    204     Deque<String> paths;
    205     paths.append(directoryPath);
    206     while (!paths.isEmpty()) {
    207         auto path = paths.takeFirst();
    208         if (FileSystem::fileIsDirectory(path, FileSystem::ShouldFollowSymbolicLinks::No)) {
    209             auto newPaths = FileSystem::listDirectory(path, "*"_s);
    210             for (auto& newPath : newPaths) {
    211                 // Files in /Blobs directory are hard link.
    212                 auto fileName = FileSystem::lastComponentOfPathIgnoringTrailingSlash(newPath);
    213                 if (fileName == "Blobs")
    214                     continue;
    215                 paths.append(newPath);
    216             }
    217             continue;
    218         }
    219 
    220         long long fileSize = 0;
    221         FileSystem::getFileSize(path, fileSize);
    222         directorySize += fileSize;
    223     }
    224     return directorySize;
    225 }
    226 
    227 uint64_t Engine::diskUsage(const String& rootPath, const WebCore::ClientOrigin& origin)
    228 {
    229     ASSERT(!isMainThread());
    230 
    231     if (rootPath.isEmpty())
    232         return 0;
    233 
    234     String saltPath = FileSystem::pathByAppendingComponent(rootPath, "salt"_s);
    235     auto salt = readOrMakeSalt(saltPath);
    236     if (!salt)
    237         return 0;
    238 
    239     Key key(origin.topOrigin.toString(), origin.clientOrigin.toString(), { }, { }, *salt);
    240     String directoryPath = FileSystem::pathByAppendingComponent(rootPath, key.hashAsString());
    241 
    242     String sizeFilePath = Caches::cachesSizeFilename(directoryPath);
    243     if (auto recordedSize = readSizeFile(sizeFilePath))
    244         return *recordedSize;
    245 
    246     return getDirectorySize(directoryPath);
    247 }
    248 
    249 void Engine::requestSpace(const ClientOrigin& origin, uint64_t spaceRequested, CompletionHandler<void(WebCore::StorageQuotaManager::Decision)>&& callback)
    250 {
    251     ASSERT(isMainThread());
    252 
    253     if (!m_networkProcess)
    254         callback(WebCore::StorageQuotaManager::Decision::Deny);
    255 
    256     RefPtr<WebCore::StorageQuotaManager> storageQuotaManager = m_networkProcess->storageQuotaManager(m_sessionID, origin);
    257     if (!storageQuotaManager)
    258         callback(WebCore::StorageQuotaManager::Decision::Deny);
    259 
    260     storageQuotaManager->requestSpaceOnMainThread(spaceRequested, WTFMove(callback));
     199void Engine::initializeQuotaUser(NetworkProcess& networkProcess, PAL::SessionID sessionID, const WebCore::ClientOrigin& clientOrigin, CompletionHandler<void()>&& completionHandler)
     200{
     201    from(networkProcess, sessionID, [clientOrigin, completionHandler = WTFMove(completionHandler)](auto& engine) mutable {
     202        engine.readCachesFromDisk(clientOrigin, [completionHandler = WTFMove(completionHandler)](auto&& cachesOrError) mutable {
     203            completionHandler();
     204        });
     205    });
    261206}
    262207
     
    397342        auto& caches = m_caches.ensure(origin, [&origin, this] {
    398343            auto path = cachesRootPath(origin);
    399             return Caches::create(*this, WebCore::ClientOrigin { origin }, WTFMove(path));
     344            return Caches::create(*this, WebCore::ClientOrigin { origin }, WTFMove(path), m_networkProcess->storageQuotaManager(m_sessionID, origin));
    400345        }).iterator->value;
    401346
     
    529474}
    530475
    531 void Engine::writeSizeFile(const String& path, uint64_t size, CompletionHandler<void()>&& completionHandler)
    532 {
    533     CompletionHandlerCallingScope completionHandlerCaller(WTFMove(completionHandler));
     476void Engine::writeSizeFile(const String& path, uint64_t size)
     477{
    534478    if (!shouldPersist())
    535479        return;
    536480
    537     m_ioQueue->dispatch([path = path.isolatedCopy(), size, completionHandlerCaller = WTFMove(completionHandlerCaller)]() mutable {
     481    m_ioQueue->dispatch([path = path.isolatedCopy(), size]() {
    538482        LockHolder locker(globalSizeFileLock);
    539483        auto fileHandle = FileSystem::openFile(path, FileSystem::FileOpenMode::Write);
     
    546490        FileSystem::truncateFile(fileHandle, 0);
    547491        FileSystem::writeToFile(fileHandle, String::number(size).utf8().data(), String::number(size).utf8().length());
    548 
    549         RunLoop::main().dispatch([completionHandlerCaller = WTFMove(completionHandlerCaller)]() mutable { });
    550492    });
    551493}
     
    572514        return WTF::nullopt;
    573515
    574     Vector<unsigned char> buffer(bytesToRead);
    575     size_t totalBytesRead = FileSystem::readFromFile(fileHandle, reinterpret_cast<char*>(buffer.data()), buffer.size());
     516    Vector<char> buffer(bytesToRead);
     517    size_t totalBytesRead = FileSystem::readFromFile(fileHandle, buffer.data(), buffer.size());
    576518    if (totalBytesRead != bytesToRead)
    577519        return WTF::nullopt;
  • trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngine.h

    r252805 r252839  
    3030#include "WebsiteData.h"
    3131#include <WebCore/ClientOrigin.h>
    32 #include <WebCore/StorageQuotaManager.h>
    3332#include <pal/SessionID.h>
    3433#include <wtf/HashMap.h>
     
    8180    static void initializeQuotaUser(NetworkProcess&, PAL::SessionID, const WebCore::ClientOrigin&, CompletionHandler<void()>&&);
    8281
    83     static uint64_t diskUsage(const String& rootPath, const WebCore::ClientOrigin&);
    84     void requestSpace(const WebCore::ClientOrigin&, uint64_t spaceRequested, CompletionHandler<void(WebCore::StorageQuotaManager::Decision)>&&);
    85 
    8682    bool shouldPersist() const { return !!m_ioQueue;}
    8783
     
    8985    void readFile(const String& filename, CompletionHandler<void(const NetworkCache::Data&, int error)>&&);
    9086    void removeFile(const String& filename);
    91     void writeSizeFile(const String&, uint64_t size, CompletionHandler<void()>&&);
     87    void writeSizeFile(const String&, uint64_t size);
    9288    static Optional<uint64_t> readSizeFile(const String&);
    9389
  • trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCache.cpp

    r252805 r252839  
    415415
    416416        spaceRequired += record.responseBodySize;
    417         if (position != notFound) {
    418             uint64_t spaceDecreased = sameURLRecords->at(position).size;
    419             if (spaceRequired >= spaceDecreased)
    420                 spaceRequired -= spaceDecreased;
    421         }
     417        if (position != notFound)
     418            spaceRequired -= sameURLRecords->at(position).size;
    422419    }
    423420
     
    454451    });
    455452
    456     // This operation would change caches size, so make sure callback finishes after size file is updated.
    457     m_caches.updateSizeFile([callback = WTFMove(callback), recordIdentifiers = WTFMove(recordIdentifiers)]() mutable {
    458         callback(WTFMove(recordIdentifiers));
    459     });
     453    callback(WTFMove(recordIdentifiers));
    460454}
    461455
  • trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.cpp

    r252805 r252839  
    5757}
    5858
    59 Ref<Caches> Caches::create(Engine& engine, WebCore::ClientOrigin&& origin, String&& rootPath)
    60 {
    61     return adoptRef(*new Caches { engine, WTFMove(origin), WTFMove(rootPath) });
    62 }
    63 
    64 Caches::Caches(Engine& engine, WebCore::ClientOrigin&& origin, String&& rootPath)
     59Ref<Caches> Caches::create(Engine& engine, WebCore::ClientOrigin&& origin, String&& rootPath, WebCore::StorageQuotaManager& quotaManager)
     60{
     61    auto caches = adoptRef(*new Caches { engine, WTFMove(origin), WTFMove(rootPath), quotaManager });
     62    quotaManager.addUser(caches.get());
     63    return caches;
     64}
     65
     66Caches::Caches(Engine& engine, WebCore::ClientOrigin&& origin, String&& rootPath, WebCore::StorageQuotaManager& quotaManager)
    6567    : m_engine(&engine)
    6668    , m_origin(WTFMove(origin))
    6769    , m_rootPath(WTFMove(rootPath))
     70    , m_quotaManager(makeWeakPtr(quotaManager))
    6871{
    6972}
     
    7275{
    7376    ASSERT(m_pendingWritingCachesToDiskCallbacks.isEmpty());
     77
     78    if (m_quotaManager)
     79        m_quotaManager->removeUser(*this);
     80}
     81
     82void Caches::whenInitialized(CompletionHandler<void()>&& callback)
     83{
     84    initialize([callback = WTFMove(callback)](auto&& error) mutable {
     85        if (error)
     86            RELEASE_LOG_ERROR(CacheStorage, "Caches::initialize failed, reported space used will be zero");
     87        callback();
     88    });
    7489}
    7590
     
    194209}
    195210
    196 void Caches::updateSizeFile(CompletionHandler<void()>&& completionHandler)
    197 {
    198     if (!m_engine) {
    199         completionHandler();
    200         return;
    201     }
    202 
    203     m_engine->writeSizeFile(cachesSizeFilename(m_rootPath), m_size, WTFMove(completionHandler));
     211void Caches::updateSizeFile()
     212{
     213    if (m_engine)
     214        m_engine->writeSizeFile(cachesSizeFilename(m_rootPath), m_size);
    204215}
    205216
     
    222233            }
    223234            m_size = size;
    224             updateSizeFile([this, protectedThis = WTFMove(protectedThis)]() mutable {
    225                 m_isInitialized = true;
    226                 auto pendingCallbacks = WTFMove(m_pendingInitializationCallbacks);
    227                 for (auto& callback : pendingCallbacks)
    228                     callback(WTF::nullopt);
    229             });
     235            updateSizeFile();
     236
     237            m_isInitialized = true;
     238            auto pendingCallbacks = WTFMove(m_pendingInitializationCallbacks);
     239            for (auto& callback : pendingCallbacks)
     240                callback(WTF::nullopt);
     241
    230242            return;
    231243        }
     
    262274            ASSERT(RunLoop::isMain());
    263275            protectedThis->clearMemoryRepresentation();
     276            protectedThis->resetSpaceUsed();
    264277            completionHandler();
    265278        });
     
    267280    }
    268281    clearMemoryRepresentation();
     282    resetSpaceUsed();
    269283    clearPendingWritingCachesToDiskCallbacks();
    270284    completionHandler();
     
    512526void Caches::requestSpace(uint64_t spaceRequired, WebCore::DOMCacheEngine::CompletionCallback&& callback)
    513527{
    514     if (!m_engine) {
     528    if (!m_quotaManager) {
    515529        callback(Error::QuotaExceeded);
    516530        return;
    517531    }
    518532
    519     m_engine->requestSpace(m_origin, spaceRequired, [callback = WTFMove(callback)](auto decision) mutable {
     533    m_quotaManager->requestSpace(spaceRequired, [callback = WTFMove(callback)](auto decision) mutable {
    520534        switch (decision) {
    521535        case WebCore::StorageQuotaManager::Decision::Deny:
     
    535549    m_size += recordInformation.size;
    536550    m_size -= previousRecordSize;
     551    updateSizeFile();
    537552
    538553    if (!shouldPersist()) {
     
    542557    }
    543558
    544     m_storage->store(Cache::encode(recordInformation, record), { }, [this, protectedThis = makeRef(*this), protectedStorage = makeRef(*m_storage), callback = WTFMove(callback)](int error) mutable {
     559    m_storage->store(Cache::encode(recordInformation, record), { }, [protectedStorage = makeRef(*m_storage), callback = WTFMove(callback)](int error) mutable {
    545560        if (error) {
    546561            RELEASE_LOG_ERROR(CacheStorage, "Caches::writeRecord failed with error %d", error);
     
    548563            return;
    549564        }
    550         updateSizeFile([callback = WTFMove(callback)]() mutable {
    551             callback(WTF::nullopt);
    552         });
     565        callback(WTF::nullopt);
    553566    });
    554567}
     
    593606    ASSERT(m_size >= record.size);
    594607    m_size -= record.size;
    595     updateSizeFile([] { });
     608    updateSizeFile();
    596609
    597610    removeCacheEntry(record.key);
     
    607620    }
    608621    m_storage->remove(key);
     622}
     623
     624void Caches::resetSpaceUsed()
     625{
     626    m_size = 0;
     627    updateSizeFile();
     628
     629    if (m_quotaManager) {
     630        m_quotaManager->removeUser(*this);
     631        m_quotaManager->addUser(*this);
     632    }
    609633}
    610634
  • trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCaches.h

    r252805 r252839  
    2929#include "NetworkCacheStorage.h"
    3030#include <WebCore/ClientOrigin.h>
     31#include <WebCore/StorageQuotaUser.h>
    3132#include <wtf/CompletionHandler.h>
    3233#include <wtf/Deque.h>
     
    4243class Engine;
    4344
    44 class Caches final : public RefCounted<Caches> {
     45class Caches final : public RefCounted<Caches>, private WebCore::StorageQuotaUser {
    4546public:
    46     static String cachesSizeFilename(const String& cachesRootsPath);
    47     static Ref<Caches> create(Engine&, WebCore::ClientOrigin&&, String&& rootPath);
     47    static String cachesSizeFilename(const String&);
     48    static Ref<Caches> create(Engine&, WebCore::ClientOrigin&&, String&& rootPath, WebCore::StorageQuotaManager&);
    4849    ~Caches();
    4950
     
    7980    void clear(WTF::CompletionHandler<void()>&&);
    8081    void clearMemoryRepresentation();
     82    void resetSpaceUsed();
    8183
    8284    uint64_t storageSize() const;
    83     void updateSizeFile(CompletionHandler<void()>&&);
    8485
    8586private:
    86     Caches(Engine&, WebCore::ClientOrigin&&, String&& rootPath);
     87    Caches(Engine&, WebCore::ClientOrigin&&, String&& rootPath, WebCore::StorageQuotaManager&);
     88
     89    // StorageQuotaUser API.
     90    uint64_t spaceUsed() const final { return m_size; }
    8791
    8892    void initializeSize();
    8993    void readCachesFromDisk(WTF::Function<void(Expected<Vector<Cache>, WebCore::DOMCacheEngine::Error>&&)>&&);
    9094    void writeCachesToDisk(WebCore::DOMCacheEngine::CompletionCallback&&);
     95
     96    void whenInitialized(CompletionHandler<void()>&&) final;
    9197
    9298    void storeOrigin(WebCore::DOMCacheEngine::CompletionCallback&&);
     
    100106
    101107    bool hasActiveCache() const;
     108
     109    void updateSizeFile();
    102110
    103111    bool m_isInitialized { false };
     
    115123    bool m_isWritingCachesToDisk { false };
    116124    Deque<CompletionHandler<void(Optional<WebCore::DOMCacheEngine::Error>)>> m_pendingWritingCachesToDiskCallbacks;
     125    WeakPtr<WebCore::StorageQuotaManager> m_quotaManager;
    117126};
    118127
  • trunk/Source/WebKit/Shared/WebsiteDataStoreParameters.cpp

    r252805 r252839  
    5555
    5656    encoder << localStorageDirectory << localStorageDirectoryExtensionHandle;
    57 
    58     encoder << cacheStorageDirectory << cacheStorageDirectoryExtensionHandle;
    5957
    6058    encoder << perOriginStorageQuota;
     
    144142    parameters.localStorageDirectoryExtensionHandle = WTFMove(*localStorageDirectoryExtensionHandle);
    145143
    146     Optional<String> cacheStorageDirectory;
    147     decoder >> cacheStorageDirectory;
    148     if (!cacheStorageDirectory)
    149         return WTF::nullopt;
    150     parameters.cacheStorageDirectory = WTFMove(*cacheStorageDirectory);
    151 
    152     Optional<SandboxExtension::Handle> cacheStorageDirectoryExtensionHandle;
    153     decoder >> cacheStorageDirectoryExtensionHandle;
    154     if (!cacheStorageDirectoryExtensionHandle)
    155         return WTF::nullopt;
    156     parameters.cacheStorageDirectoryExtensionHandle = WTFMove(*cacheStorageDirectoryExtensionHandle);
    157 
    158144    Optional<uint64_t> perOriginStorageQuota;
    159145    decoder >> perOriginStorageQuota;
  • trunk/Source/WebKit/Shared/WebsiteDataStoreParameters.h

    r252805 r252839  
    7272    SandboxExtension::Handle localStorageDirectoryExtensionHandle;
    7373
    74     String cacheStorageDirectory;
    75     SandboxExtension::Handle cacheStorageDirectoryExtensionHandle;
    76 
    7774    uint64_t perOriginStorageQuota { WebCore::StorageQuotaManager::defaultQuota() };
    7875    uint64_t perThirdPartyOriginStorageQuota { WebCore::StorageQuotaManager::defaultThirdPartyQuota() };
  • trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp

    r252805 r252839  
    687687    WebKit::toImpl(dataStoreRef)->setCacheModelSynchronouslyForTesting(WebKit::toCacheModel(cacheModel));
    688688}
    689 
    690 void WKWebsiteDataStoreResetQuota(WKWebsiteDataStoreRef dataStoreRef, void* context, WKWebsiteDataStoreResetQuotaCallback callback)
    691 {
    692     WebKit::toImpl(dataStoreRef)->resetQuota([context, callback] {
    693         if (callback)
    694             callback(context);
    695     });
    696 }
  • trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.h

    r252805 r252839  
    156156WK_EXPORT void WKWebsiteDataStoreSetCacheModelSynchronouslyForTesting(WKWebsiteDataStoreRef dataStoreRef, WKCacheModel cacheModel);
    157157
    158 typedef void (*WKWebsiteDataStoreResetQuotaCallback)(void* functionContext);
    159 WK_EXPORT void WKWebsiteDataStoreResetQuota(WKWebsiteDataStoreRef dataStoreRef, void* context, WKWebsiteDataStoreResetQuotaCallback callback);
    160 
    161158#ifdef __cplusplus
    162159}
  • trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp

    r252805 r252839  
    13681368}
    13691369
    1370 void NetworkProcessProxy::resetQuota(PAL::SessionID sessionID, CompletionHandler<void()>&& completionHandler)
    1371 {
    1372     sendWithAsyncReply(Messages::NetworkProcess::ResetQuota(sessionID), WTFMove(completionHandler));
    1373 }
    1374 
    13751370} // namespace WebKit
    13761371
  • trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h

    r252805 r252839  
    5757class SecurityOrigin;
    5858struct SecurityOriginData;
    59 struct ClientOrigin;
    6059}
    6160
     
    198197    void unregisterSchemeForLegacyCustomProtocol(const String&);
    199198
    200     void resetQuota(PAL::SessionID, CompletionHandler<void()>&&);
    201 
    202199private:
    203200    // AuxiliaryProcessProxy
  • trunk/Source/WebKit/UIProcess/WebProcessPool.cpp

    r252819 r252839  
    552552    SandboxExtension::createHandleForReadWriteDirectory(localStorageDirectory, parameters.defaultDataStoreParameters.localStorageDirectoryExtensionHandle);
    553553
    554     auto cacheStorageDirectory = m_websiteDataStore ? m_websiteDataStore->cacheStorageDirectory() : nullString();
    555     if (!cacheStorageDirectory.isEmpty()) {
    556         SandboxExtension::createHandleForReadWriteDirectory(cacheStorageDirectory, parameters.defaultDataStoreParameters.cacheStorageDirectoryExtensionHandle);
    557         parameters.defaultDataStoreParameters.cacheStorageDirectory = WTFMove(cacheStorageDirectory);
    558     }
    559 
    560554    if (m_websiteDataStore)
    561555        parameters.defaultDataStoreParameters.networkSessionParameters.resourceLoadStatisticsDirectory = m_websiteDataStore->resolvedResourceLoadStatisticsDirectory();
  • trunk/Source/WebKit/UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm

    r252805 r252839  
    192192        SandboxExtension::createHandleForReadWriteDirectory(parameters.localStorageDirectory, parameters.localStorageDirectoryExtensionHandle);
    193193
    194     parameters.cacheStorageDirectory = cacheStorageDirectory();
    195     if (!parameters.cacheStorageDirectory.isEmpty())
    196         SandboxExtension::createHandleForReadWriteDirectory(parameters.cacheStorageDirectory, parameters.cacheStorageDirectoryExtensionHandle);
    197 
    198194    parameters.perOriginStorageQuota = perOriginStorageQuota();
    199195    parameters.perThirdPartyOriginStorageQuota = perThirdPartyOriginStorageQuota();
  • trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.cpp

    r252805 r252839  
    20842084    }
    20852085
    2086     auto cacheStorageDirectory = this->cacheStorageDirectory();
    2087     if (!cacheStorageDirectory.isEmpty()) {
    2088         SandboxExtension::createHandleForReadWriteDirectory(cacheStorageDirectory, parameters.cacheStorageDirectoryExtensionHandle);
    2089         parameters.cacheStorageDirectory = cacheStorageDirectory;
    2090     }
    2091 
    20922086#if ENABLE(INDEXED_DATABASE)
    20932087    parameters.indexedDatabaseDirectory = resolvedIndexedDatabaseDirectory();
     
    21762170}
    21772171
    2178 void WebsiteDataStore::resetQuota(CompletionHandler<void()>&& completionHandler)
    2179 {
    2180     auto callbackAggregator = CallbackAggregator::create(WTFMove(completionHandler));
    2181     for (auto& processPool : processPools()) {
    2182         if (auto* process = processPool->networkProcess())
    2183             process->resetQuota(m_sessionID, [callbackAggregator = callbackAggregator.copyRef()] { });
    2184     }
    2185 }
    2186 
    21872172#if !PLATFORM(COCOA)
    21882173WTF::String WebsiteDataStore::defaultMediaCacheDirectory()
  • trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h

    r252805 r252839  
    292292    static WTF::String defaultDeviceIdHashSaltsStorageDirectory();
    293293    static WTF::String defaultJavaScriptConfigurationDirectory();
    294 
    295     void resetQuota(CompletionHandler<void()>&&);
    296 
     294   
    297295private:
    298296    void fetchDataAndApply(OptionSet<WebsiteDataType>, OptionSet<WebsiteDataFetchOption>, RefPtr<WorkQueue>&&, Function<void(Vector<WebsiteDataRecord>)>&& apply);
  • trunk/Tools/ChangeLog

    r252834 r252839  
     12019-11-23  Commit Queue  <commit-queue@webkit.org>
     2
     3        Unreviewed, rolling out r252805.
     4        https://bugs.webkit.org/show_bug.cgi?id=204553
     5
     6        Caused test failures and ASan crashes (Requested by ap on
     7        #webkit).
     8
     9        Reverted changeset:
     10
     11        "Cross-thread version StorageQuotaManager"
     12        https://bugs.webkit.org/show_bug.cgi?id=203971
     13        https://trac.webkit.org/changeset/252805
     14
    1152019-11-23  Per Arne Vollan  <pvollan@apple.com>
    216
  • trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj

    r252813 r252839  
    739739                93AF4ECE1506F064007FD57E /* NewFirstVisuallyNonEmptyLayoutForImages_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93AF4ECD1506F064007FD57E /* NewFirstVisuallyNonEmptyLayoutForImages_Bundle.cpp */; };
    740740                93AF4ED11506F130007FD57E /* lots-of-images.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 93AF4ECF1506F123007FD57E /* lots-of-images.html */; };
     741                93B62054234EA62C00D49B97 /* StorageQuotaManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93B62053234EA32B00D49B97 /* StorageQuotaManager.cpp */; };
    741742                93CFA8671CEB9E38000565A8 /* autofocused-text-input.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 93CFA8661CEB9DE1000565A8 /* autofocused-text-input.html */; };
    742743                93D119FC22C680F7009BE3C7 /* localstorage-open-window-private.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 93D119FB22C57112009BE3C7 /* localstorage-open-window-private.html */; };
     
    11431144                        dstSubfolderSpec = 7;
    11441145                        files = (
     1146                                CD8394DF232AF7C000149495 /* media-loading.html in Copy Resources */,
    11451147                                55A817FF2181021A0004A39A /* 100x100-red.tga in Copy Resources */,
    11461148                                1A9E52C913E65EF4006917F5 /* 18-characters.html in Copy Resources */,
     
    13751377                                AD57AC221DA7466E00FF1BDE /* many-iframes.html in Copy Resources */,
    13761378                                7772ECE122FE06C60009A799 /* many-same-origin-iframes.html in Copy Resources */,
    1377                                 CD8394DF232AF7C000149495 /* media-loading.html in Copy Resources */,
    13781379                                CDA3159A1ED548F1009F60D3 /* MediaPlaybackSleepAssertion.html in Copy Resources */,
    13791380                                CDC9442F1EF205D60059C3C4 /* mediastreamtrack-detached.html in Copy Resources */,
     
    21492150                93AF4ECD1506F064007FD57E /* NewFirstVisuallyNonEmptyLayoutForImages_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NewFirstVisuallyNonEmptyLayoutForImages_Bundle.cpp; sourceTree = "<group>"; };
    21502151                93AF4ECF1506F123007FD57E /* lots-of-images.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "lots-of-images.html"; sourceTree = "<group>"; };
     2152                93B62053234EA32B00D49B97 /* StorageQuotaManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StorageQuotaManager.cpp; sourceTree = "<group>"; };
    21512153                93CFA8661CEB9DE1000565A8 /* autofocused-text-input.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "autofocused-text-input.html"; sourceTree = "<group>"; };
    21522154                93CFA8681CEBCFED000565A8 /* CandidateTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CandidateTests.mm; sourceTree = "<group>"; };
     
    31263128                                A17991891E1CA24100A505ED /* SharedBufferTest.cpp */,
    31273129                                A179918A1E1CA24100A505ED /* SharedBufferTest.h */,
     3130                                93B62053234EA32B00D49B97 /* StorageQuotaManager.cpp */,
    31283131                                ECA680CD1E68CC0900731D20 /* StringUtilities.mm */,
    31293132                                CE4D5DE51F6743BA0072CFC6 /* StringWithDirection.cpp */,
     
    38533856                                AD57AC1D1DA7463800FF1BDE /* many-iframes.html */,
    38543857                                7772ECE022FE05E10009A799 /* many-same-origin-iframes.html */,
    3855                                 CD8394DE232AF15E00149495 /* media-loading.html */,
    38563858                                CDC9442B1EF1FBD20059C3C4 /* mediastreamtrack-detached.html */,
    38573859                                51CD1C711B38D48400142CA5 /* modal-alerts-in-new-about-blank-window.html */,
     
    38853887                                1C2B81841C8924A200A5529F /* webfont.html */,
    38863888                                468F2F932368DAA700F4B864 /* window-open-then-document-open.html */,
     3889                                CD8394DE232AF15E00149495 /* media-loading.html */,
    38873890                        );
    38883891                        name = Resources;
     
    48664869                                CDC0932E21C993440030C4B0 /* StopSuspendResumeAllMedia.mm in Sources */,
    48674870                                414AD6862285D1C000777F2D /* StorageQuota.mm in Sources */,
     4871                                93B62054234EA62C00D49B97 /* StorageQuotaManager.cpp in Sources */,
    48684872                                515BE1711D428E4B00DD7C68 /* StoreBlobThenDelete.mm in Sources */,
    48694873                                7CCE7ED01A411A7E00447C4C /* StringByEvaluatingJavaScriptFromString.mm in Sources */,
  • trunk/Tools/WebKitTestRunner/TestController.cpp

    r252805 r252839  
    982982    clearDOMCaches();
    983983
    984     resetQuota();
    985 
    986984    WKContextSetAllowsAnySSLCertificateForServiceWorkerTesting(platformContext(), true);
    987985
     
    31453143}
    31463144
    3147 void TestController::resetQuota()
    3148 {
    3149     StorageVoidCallbackContext context(*this);
    3150     WKWebsiteDataStoreResetQuota(TestController::websiteDataStore(), &context, StorageVoidCallback);
    3151     runUntil(context.done, noTimeout);
    3152 }
    3153 
    31543145struct FetchCacheOriginsCallbackContext {
    31553146    FetchCacheOriginsCallbackContext(TestController& controller, WKStringRef origin)
  • trunk/Tools/WebKitTestRunner/TestController.h

    r252805 r252839  
    270270    void terminateServiceWorkerProcess();
    271271
    272     void resetQuota();
    273 
    274272    void removeAllSessionCredentials();
    275273
Note: See TracChangeset for help on using the changeset viewer.