blob: 5ace91abee4d85107cc680a3ed4fce5d10e3120e [file] [log] [blame]
/*
* Copyright (C) 2021 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "WorkerStorageConnection.h"
#include "ClientOrigin.h"
#include "WorkerFileSystemStorageConnection.h"
#include "WorkerGlobalScope.h"
#include "WorkerLoaderProxy.h"
#include "WorkerThread.h"
#include <wtf/Scope.h>
namespace WebCore {
Ref<WorkerStorageConnection> WorkerStorageConnection::create(WorkerGlobalScope& scope)
{
return adoptRef(*new WorkerStorageConnection(scope));
}
WorkerStorageConnection::WorkerStorageConnection(WorkerGlobalScope& scope)
: m_scope(scope)
{
}
void WorkerStorageConnection::scopeClosed()
{
auto getPersistedCallbacks = std::exchange(m_getPersistedCallbacks, { });
for (auto& callback : getPersistedCallbacks.values())
callback(false);
auto getDirectoryCallbacks = std::exchange(m_getDirectoryCallbacks, { });
for (auto& callback : getDirectoryCallbacks.values())
callback(Exception { InvalidStateError });
m_scope = nullptr;
}
void WorkerStorageConnection::getPersisted(ClientOrigin&& origin, StorageConnection::PersistCallback&& completionHandler)
{
ASSERT(m_scope);
auto callbackIdentifier = ++m_lastCallbackIdentifier;
m_getPersistedCallbacks.add(callbackIdentifier, WTFMove(completionHandler));
callOnMainThread([callbackIdentifier, workerThread = Ref { m_scope->thread() }, origin = WTFMove(origin).isolatedCopy()]() mutable {
auto mainThreadConnection = workerThread->workerLoaderProxy().storageConnection();
auto mainThreadCallback = [callbackIdentifier, workerThread = WTFMove(workerThread)](bool result) mutable {
workerThread->runLoop().postTaskForMode([callbackIdentifier, result] (auto& scope) mutable {
downcast<WorkerGlobalScope>(scope).storageConnection().didGetPersisted(callbackIdentifier, result);
}, WorkerRunLoop::defaultMode());
};
if (!mainThreadConnection)
return mainThreadCallback(false);
mainThreadConnection->getPersisted(WTFMove(origin), WTFMove(mainThreadCallback));
});
}
void WorkerStorageConnection::didGetPersisted(uint64_t callbackIdentifier, bool persisted)
{
if (auto callback = m_getPersistedCallbacks.take(callbackIdentifier))
callback(persisted);
}
void WorkerStorageConnection::fileSystemGetDirectory(ClientOrigin&& origin, StorageConnection::GetDirectoryCallback&& completionHandler)
{
ASSERT(m_scope);
auto callbackIdentifier = ++m_lastCallbackIdentifier;
m_getDirectoryCallbacks.add(callbackIdentifier, WTFMove(completionHandler));
callOnMainThread([callbackIdentifier, workerThread = Ref { m_scope->thread() }, origin = WTFMove(origin).isolatedCopy()]() mutable {
auto mainThreadConnection = workerThread->workerLoaderProxy().storageConnection();
auto mainThreadCallback = [callbackIdentifier, workerThread = WTFMove(workerThread)](auto&& result) mutable {
workerThread->runLoop().postTaskForMode([callbackIdentifier, result = crossThreadCopy(WTFMove(result))] (auto& scope) mutable {
downcast<WorkerGlobalScope>(scope).storageConnection().didGetDirectory(callbackIdentifier, WTFMove(result));
}, WorkerRunLoop::defaultMode());
};
if (!mainThreadConnection)
return mainThreadCallback(Exception { InvalidStateError });
mainThreadConnection->fileSystemGetDirectory(WTFMove(origin), WTFMove(mainThreadCallback));
});
}
void WorkerStorageConnection::didGetDirectory(uint64_t callbackIdentifier, ExceptionOr<StorageConnection::DirectoryInfo>&& result)
{
RefPtr<FileSystemStorageConnection> mainThreadFileSystemStorageConnection = result.hasException() ? nullptr : result.returnValue().second;
auto releaseConnectionScope = makeScopeExit([connection = mainThreadFileSystemStorageConnection]() mutable {
if (connection)
callOnMainThread([connection = WTFMove(connection)]() { });
});
auto callback = m_getDirectoryCallbacks.take(callbackIdentifier);
if (!callback)
return;
if (result.hasException())
return callback(WTFMove(result));
if (!m_scope)
return callback(Exception { InvalidStateError });
releaseConnectionScope.release();
auto& workerFileSystemStorageConnection = m_scope->getFileSystemStorageConnection(Ref { *mainThreadFileSystemStorageConnection });
callback(StorageConnection::DirectoryInfo { result.returnValue().first, Ref { workerFileSystemStorageConnection } });
}
} // namespace WebCore