#pragma once
#include "BlobPropertyBag.h"
#include "FileReaderLoader.h"
#include "ScriptExecutionContext.h"
#include "ScriptWrappable.h"
#include <wtf/IsoMalloc.h>
#include <wtf/URL.h>
#include "URLRegistry.h"
#include <wtf/Variant.h>
namespace JSC {
class ArrayBufferView;
class ArrayBuffer;
}
namespace WebCore {
class Blob;
class BlobLoader;
class DeferredPromise;
class ScriptExecutionContext;
class SharedBuffer;
using BlobPartVariant = Variant<RefPtr<JSC::ArrayBufferView>, RefPtr<JSC::ArrayBuffer>, RefPtr<Blob>, String>;
class Blob : public ScriptWrappable, public URLRegistrable, public RefCounted<Blob>, public ActiveDOMObject {
WTF_MAKE_ISO_ALLOCATED_EXPORT(Blob, WEBCORE_EXPORT);
public:
static Ref<Blob> create(ScriptExecutionContext* context)
{
auto blob = adoptRef(*new Blob(context));
blob->suspendIfNeeded();
return blob;
}
static Ref<Blob> create(ScriptExecutionContext& context, Vector<BlobPartVariant>&& blobPartVariants, const BlobPropertyBag& propertyBag)
{
auto blob = adoptRef(*new Blob(context, WTFMove(blobPartVariants), propertyBag));
blob->suspendIfNeeded();
return blob;
}
static Ref<Blob> create(ScriptExecutionContext* context, const SharedBuffer& buffer, const String& contentType)
{
auto blob = adoptRef(*new Blob(context, buffer, contentType));
blob->suspendIfNeeded();
return blob;
}
static Ref<Blob> create(ScriptExecutionContext* context, Vector<uint8_t>&& data, const String& contentType)
{
auto blob = adoptRef(*new Blob(context, WTFMove(data), contentType));
blob->suspendIfNeeded();
return blob;
}
static Ref<Blob> deserialize(ScriptExecutionContext* context, const URL& srcURL, const String& type, long long size, const String& fileBackedPath)
{
ASSERT(Blob::isNormalizedContentType(type));
auto blob = adoptRef(*new Blob(deserializationContructor, context, srcURL, type, size, fileBackedPath));
blob->suspendIfNeeded();
return blob;
}
virtual ~Blob();
const URL& url() const { return m_internalURL; }
const String& type() const { return m_type; }
WEBCORE_EXPORT unsigned long long size() const;
virtual bool isFile() const { return false; }
static bool isValidContentType(const String&);
static String normalizedContentType(const String&);
#if ASSERT_ENABLED
static bool isNormalizedContentType(const String&);
static bool isNormalizedContentType(const CString&);
#endif
URLRegistry& registry() const override;
Ref<Blob> slice(ScriptExecutionContext& context, long long start, long long end, const String& contentType) const
{
auto blob = adoptRef(*new Blob(&context, m_internalURL, start, end, contentType));
blob->suspendIfNeeded();
return blob;
}
void text(ScriptExecutionContext&, Ref<DeferredPromise>&&);
void arrayBuffer(ScriptExecutionContext&, Ref<DeferredPromise>&&);
protected:
WEBCORE_EXPORT explicit Blob(ScriptExecutionContext*);
Blob(ScriptExecutionContext&, Vector<BlobPartVariant>&&, const BlobPropertyBag&);
Blob(ScriptExecutionContext*, const SharedBuffer&, const String& contentType);
Blob(ScriptExecutionContext*, Vector<uint8_t>&&, const String& contentType);
enum ReferencingExistingBlobConstructor { referencingExistingBlobConstructor };
Blob(ReferencingExistingBlobConstructor, ScriptExecutionContext*, const Blob&);
enum UninitializedContructor { uninitializedContructor };
Blob(UninitializedContructor, ScriptExecutionContext*, URL&&, String&& type);
enum DeserializationContructor { deserializationContructor };
Blob(DeserializationContructor, ScriptExecutionContext*, const URL& srcURL, const String& type, Optional<unsigned long long> size, const String& fileBackedPath);
Blob(ScriptExecutionContext*, const URL& srcURL, long long start, long long end, const String& contentType);
private:
void loadBlob(ScriptExecutionContext&, FileReaderLoader::ReadType, CompletionHandler<void(std::unique_ptr<BlobLoader>)>&&);
const char* activeDOMObjectName() const override;
URL m_internalURL;
String m_type;
mutable Optional<unsigned long long> m_size;
HashSet<std::unique_ptr<BlobLoader>> m_blobLoaders;
};
}