ThreadableBlobRegistry.cpp [plain text]
#include "config.h"
#include "ThreadableBlobRegistry.h"
#include "BlobDataFileReference.h"
#include "BlobPart.h"
#include "BlobRegistry.h"
#include "BlobURL.h"
#include "SecurityOrigin.h"
#include <mutex>
#include <wtf/CrossThreadQueue.h>
#include <wtf/CrossThreadTask.h>
#include <wtf/HashMap.h>
#include <wtf/MainThread.h>
#include <wtf/RefPtr.h>
#include <wtf/ThreadSpecific.h>
#include <wtf/text/StringHash.h>
#include <wtf/threads/BinarySemaphore.h>
using WTF::ThreadSpecific;
namespace WebCore {
typedef HashMap<String, RefPtr<SecurityOrigin>> BlobUrlOriginMap;
static ThreadSpecific<BlobUrlOriginMap>& originMap()
{
static std::once_flag onceFlag;
static ThreadSpecific<BlobUrlOriginMap>* map;
std::call_once(onceFlag, []{
map = new ThreadSpecific<BlobUrlOriginMap>;
});
return *map;
}
void ThreadableBlobRegistry::registerFileBlobURL(const URL& url, const String& path, const String& contentType)
{
if (isMainThread()) {
blobRegistry().registerFileBlobURL(url, BlobDataFileReference::create(path), contentType);
return;
}
callOnMainThread([url = url.isolatedCopy(), path = path.isolatedCopy(), contentType = contentType.isolatedCopy()] {
blobRegistry().registerFileBlobURL(url, BlobDataFileReference::create(path), contentType);
});
}
void ThreadableBlobRegistry::registerBlobURL(const URL& url, Vector<BlobPart>&& blobParts, const String& contentType)
{
if (isMainThread()) {
blobRegistry().registerBlobURL(url, WTFMove(blobParts), contentType);
return;
}
for (auto& part : blobParts)
part.detachFromCurrentThread();
callOnMainThread([url = url.isolatedCopy(), blobParts = WTFMove(blobParts), contentType = contentType.isolatedCopy()]() mutable {
blobRegistry().registerBlobURL(url, WTFMove(blobParts), contentType);
});
}
static inline bool isBlobURLContainsNullOrigin(const URL& url)
{
ASSERT(url.protocolIsBlob());
return BlobURL::getOrigin(url) == "null";
}
void ThreadableBlobRegistry::registerBlobURL(SecurityOrigin* origin, const URL& url, const URL& srcURL)
{
if (origin && isBlobURLContainsNullOrigin(url))
originMap()->add(url.string(), origin);
if (isMainThread()) {
blobRegistry().registerBlobURL(url, srcURL);
return;
}
callOnMainThread([url = url.isolatedCopy(), srcURL = srcURL.isolatedCopy()] {
blobRegistry().registerBlobURL(url, srcURL);
});
}
void ThreadableBlobRegistry::registerBlobURLOptionallyFileBacked(const URL& url, const URL& srcURL, const String& fileBackedPath, const String& contentType)
{
if (isMainThread()) {
blobRegistry().registerBlobURLOptionallyFileBacked(url, srcURL, BlobDataFileReference::create(fileBackedPath), contentType);
return;
}
callOnMainThread([url = url.isolatedCopy(), srcURL = srcURL.isolatedCopy(), fileBackedPath = fileBackedPath.isolatedCopy(), contentType = contentType.isolatedCopy()] {
blobRegistry().registerBlobURLOptionallyFileBacked(url, srcURL, BlobDataFileReference::create(fileBackedPath), contentType);
});
}
void ThreadableBlobRegistry::registerBlobURLForSlice(const URL& newURL, const URL& srcURL, long long start, long long end)
{
if (isMainThread()) {
blobRegistry().registerBlobURLForSlice(newURL, srcURL, start, end);
return;
}
callOnMainThread([newURL = newURL.isolatedCopy(), srcURL = srcURL.isolatedCopy(), start, end] {
blobRegistry().registerBlobURLForSlice(newURL, srcURL, start, end);
});
}
unsigned long long ThreadableBlobRegistry::blobSize(const URL& url)
{
if (isMainThread())
return blobRegistry().blobSize(url);
unsigned long long resultSize;
BinarySemaphore semaphore;
callOnMainThread([url = url.isolatedCopy(), &semaphore, &resultSize] {
resultSize = blobRegistry().blobSize(url);
semaphore.signal();
});
semaphore.wait();
return resultSize;
}
void ThreadableBlobRegistry::unregisterBlobURL(const URL& url)
{
if (isBlobURLContainsNullOrigin(url))
originMap()->remove(url.string());
if (isMainThread()) {
blobRegistry().unregisterBlobURL(url);
return;
}
callOnMainThread([url = url.isolatedCopy()] {
blobRegistry().unregisterBlobURL(url);
});
}
RefPtr<SecurityOrigin> ThreadableBlobRegistry::getCachedOrigin(const URL& url)
{
if (auto cachedOrigin = originMap()->get(url.string()))
return cachedOrigin;
if (!url.protocolIsBlob() || !isBlobURLContainsNullOrigin(url))
return nullptr;
return SecurityOrigin::createUnique();
}
}