зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1497925 - CreateImageBitmap must ignore the Blob.type value, r=aosmond
This commit is contained in:
Родитель
595a1dde91
Коммит
4b02de9de7
|
@ -18,9 +18,12 @@
|
||||||
#include "mozilla/gfx/Swizzle.h"
|
#include "mozilla/gfx/Swizzle.h"
|
||||||
#include "mozilla/Mutex.h"
|
#include "mozilla/Mutex.h"
|
||||||
#include "mozilla/ScopeExit.h"
|
#include "mozilla/ScopeExit.h"
|
||||||
|
#include "nsNetUtil.h"
|
||||||
|
#include "nsStreamUtils.h"
|
||||||
#include "ImageBitmapColorUtils.h"
|
#include "ImageBitmapColorUtils.h"
|
||||||
#include "ImageBitmapUtils.h"
|
#include "ImageBitmapUtils.h"
|
||||||
#include "ImageUtils.h"
|
#include "ImageUtils.h"
|
||||||
|
#include "imgLoader.h"
|
||||||
#include "imgTools.h"
|
#include "imgTools.h"
|
||||||
|
|
||||||
using namespace mozilla::gfx;
|
using namespace mozilla::gfx;
|
||||||
|
@ -1234,12 +1237,14 @@ class CreateImageBitmapFromBlobRunnable;
|
||||||
|
|
||||||
class CreateImageBitmapFromBlob final : public CancelableRunnable
|
class CreateImageBitmapFromBlob final : public CancelableRunnable
|
||||||
, public imgIContainerCallback
|
, public imgIContainerCallback
|
||||||
|
, public nsIInputStreamCallback
|
||||||
{
|
{
|
||||||
friend class CreateImageBitmapFromBlobRunnable;
|
friend class CreateImageBitmapFromBlobRunnable;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
NS_DECL_IMGICONTAINERCALLBACK
|
NS_DECL_IMGICONTAINERCALLBACK
|
||||||
|
NS_DECL_NSIINPUTSTREAMCALLBACK
|
||||||
|
|
||||||
static already_AddRefed<CreateImageBitmapFromBlob>
|
static already_AddRefed<CreateImageBitmapFromBlob>
|
||||||
Create(Promise* aPromise,
|
Create(Promise* aPromise,
|
||||||
|
@ -1252,9 +1257,9 @@ public:
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(IsCurrentThread());
|
MOZ_ASSERT(IsCurrentThread());
|
||||||
|
|
||||||
nsresult rv = StartDecodeAndCropBlob();
|
nsresult rv = StartMimeTypeAndDecodeAndCropBlob();
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
DecodeAndCropBlobCompletedMainThread(nullptr, rv);
|
MimeTypeAndDecodeAndCropBlobCompletedMainThread(nullptr, rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -1267,7 +1272,6 @@ private:
|
||||||
CreateImageBitmapFromBlob(Promise* aPromise,
|
CreateImageBitmapFromBlob(Promise* aPromise,
|
||||||
nsIGlobalObject* aGlobal,
|
nsIGlobalObject* aGlobal,
|
||||||
already_AddRefed<nsIInputStream> aInputStream,
|
already_AddRefed<nsIInputStream> aInputStream,
|
||||||
const nsACString& aMimeType,
|
|
||||||
const Maybe<IntRect>& aCropRect,
|
const Maybe<IntRect>& aCropRect,
|
||||||
nsIEventTarget* aMainThreadEventTarget)
|
nsIEventTarget* aMainThreadEventTarget)
|
||||||
: CancelableRunnable("dom::CreateImageBitmapFromBlob")
|
: CancelableRunnable("dom::CreateImageBitmapFromBlob")
|
||||||
|
@ -1275,7 +1279,6 @@ private:
|
||||||
, mPromise(aPromise)
|
, mPromise(aPromise)
|
||||||
, mGlobalObject(aGlobal)
|
, mGlobalObject(aGlobal)
|
||||||
, mInputStream(std::move(aInputStream))
|
, mInputStream(std::move(aInputStream))
|
||||||
, mMimeType(aMimeType)
|
|
||||||
, mCropRect(aCropRect)
|
, mCropRect(aCropRect)
|
||||||
, mOriginalCropRect(aCropRect)
|
, mOriginalCropRect(aCropRect)
|
||||||
, mMainThreadEventTarget(aMainThreadEventTarget)
|
, mMainThreadEventTarget(aMainThreadEventTarget)
|
||||||
|
@ -1293,20 +1296,29 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called on the owning thread.
|
// Called on the owning thread.
|
||||||
nsresult StartDecodeAndCropBlob();
|
nsresult StartMimeTypeAndDecodeAndCropBlob();
|
||||||
|
|
||||||
// Will be called when the decoding + cropping is completed on the
|
// Will be called when the decoding + cropping is completed on the
|
||||||
// main-thread. This could the not the owning thread!
|
// main-thread. This could the not the owning thread!
|
||||||
void DecodeAndCropBlobCompletedMainThread(layers::Image* aImage,
|
void MimeTypeAndDecodeAndCropBlobCompletedMainThread(layers::Image* aImage,
|
||||||
nsresult aStatus);
|
nsresult aStatus);
|
||||||
|
|
||||||
// Will be called when the decoding + cropping is completed on the owning
|
// Will be called when the decoding + cropping is completed on the owning
|
||||||
// thread.
|
// thread.
|
||||||
void DecodeAndCropBlobCompletedOwningThread(layers::Image* aImage,
|
void MimeTypeAndDecodeAndCropBlobCompletedOwningThread(layers::Image* aImage,
|
||||||
nsresult aStatus);
|
nsresult aStatus);
|
||||||
|
|
||||||
// This is called on the main-thread only.
|
// This is called on the main-thread only.
|
||||||
nsresult DecodeAndCropBlob();
|
nsresult MimeTypeAndDecodeAndCropBlob();
|
||||||
|
|
||||||
|
// This is called on the main-thread only.
|
||||||
|
nsresult DecodeAndCropBlob(const nsACString& aMimeType);
|
||||||
|
|
||||||
|
// This is called on the main-thread only.
|
||||||
|
nsresult GetMimeTypeSync(nsACString& aMimeType);
|
||||||
|
|
||||||
|
// This is called on the main-thread only.
|
||||||
|
nsresult GetMimeTypeAsync();
|
||||||
|
|
||||||
Mutex mMutex;
|
Mutex mMutex;
|
||||||
|
|
||||||
|
@ -1321,7 +1333,6 @@ private:
|
||||||
nsCOMPtr<nsIGlobalObject> mGlobalObject;
|
nsCOMPtr<nsIGlobalObject> mGlobalObject;
|
||||||
|
|
||||||
nsCOMPtr<nsIInputStream> mInputStream;
|
nsCOMPtr<nsIInputStream> mInputStream;
|
||||||
nsCString mMimeType;
|
|
||||||
Maybe<IntRect> mCropRect;
|
Maybe<IntRect> mCropRect;
|
||||||
Maybe<IntRect> mOriginalCropRect;
|
Maybe<IntRect> mOriginalCropRect;
|
||||||
IntSize mSourceSize;
|
IntSize mSourceSize;
|
||||||
|
@ -1331,7 +1342,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS_INHERITED(CreateImageBitmapFromBlob, CancelableRunnable,
|
NS_IMPL_ISUPPORTS_INHERITED(CreateImageBitmapFromBlob, CancelableRunnable,
|
||||||
imgIContainerCallback)
|
imgIContainerCallback, nsIInputStreamCallback)
|
||||||
|
|
||||||
class CreateImageBitmapFromBlobRunnable : public WorkerRunnable
|
class CreateImageBitmapFromBlobRunnable : public WorkerRunnable
|
||||||
{
|
{
|
||||||
|
@ -1349,7 +1360,7 @@ public:
|
||||||
bool
|
bool
|
||||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
|
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
|
||||||
{
|
{
|
||||||
mTask->DecodeAndCropBlobCompletedOwningThread(mImage, mStatus);
|
mTask->MimeTypeAndDecodeAndCropBlobCompletedOwningThread(mImage, mStatus);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2167,14 +2178,19 @@ CreateImageBitmapFromBlob::Create(Promise* aPromise,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the MIME type string of the blob.
|
if (!NS_InputStreamIsBuffered(stream)) {
|
||||||
// The type will be checked in the DecodeImageAsync() method.
|
nsCOMPtr<nsIInputStream> bufferedStream;
|
||||||
nsAutoString mimeTypeUTF16;
|
nsresult rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
|
||||||
aBlob.Impl()->GetType(mimeTypeUTF16);
|
stream.forget(), 4096);
|
||||||
NS_ConvertUTF16toUTF8 mimeType(mimeTypeUTF16);
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream = bufferedStream;
|
||||||
|
}
|
||||||
|
|
||||||
RefPtr<CreateImageBitmapFromBlob> task =
|
RefPtr<CreateImageBitmapFromBlob> task =
|
||||||
new CreateImageBitmapFromBlob(aPromise, aGlobal, stream.forget(), mimeType,
|
new CreateImageBitmapFromBlob(aPromise, aGlobal, stream.forget(),
|
||||||
aCropRect, aMainThreadEventTarget);
|
aCropRect, aMainThreadEventTarget);
|
||||||
|
|
||||||
// Nothing to do for the main-thread.
|
// Nothing to do for the main-thread.
|
||||||
|
@ -2201,7 +2217,7 @@ CreateImageBitmapFromBlob::Create(Promise* aPromise,
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
CreateImageBitmapFromBlob::StartDecodeAndCropBlob()
|
CreateImageBitmapFromBlob::StartMimeTypeAndDecodeAndCropBlob()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(IsCurrentThread());
|
MOZ_ASSERT(IsCurrentThread());
|
||||||
|
|
||||||
|
@ -2209,11 +2225,11 @@ CreateImageBitmapFromBlob::StartDecodeAndCropBlob()
|
||||||
if (!NS_IsMainThread()) {
|
if (!NS_IsMainThread()) {
|
||||||
RefPtr<CreateImageBitmapFromBlob> self = this;
|
RefPtr<CreateImageBitmapFromBlob> self = this;
|
||||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
|
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
|
||||||
"CreateImageBitmapFromBlob::DecodeAndCropBlob",
|
"CreateImageBitmapFromBlob::MimeTypeAndDecodeAndCropBlob",
|
||||||
[self]() {
|
[self]() {
|
||||||
nsresult rv = self->DecodeAndCropBlob();
|
nsresult rv = self->MimeTypeAndDecodeAndCropBlob();
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
self->DecodeAndCropBlobCompletedMainThread(nullptr, rv);
|
self->MimeTypeAndDecodeAndCropBlobCompletedMainThread(nullptr, rv);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2221,14 +2237,30 @@ CreateImageBitmapFromBlob::StartDecodeAndCropBlob()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main-thread.
|
// Main-thread.
|
||||||
return DecodeAndCropBlob();
|
return MimeTypeAndDecodeAndCropBlob();
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
CreateImageBitmapFromBlob::DecodeAndCropBlob()
|
CreateImageBitmapFromBlob::MimeTypeAndDecodeAndCropBlob()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
nsAutoCString mimeType;
|
||||||
|
nsresult rv = GetMimeTypeSync(mimeType);
|
||||||
|
if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
|
||||||
|
return GetMimeTypeAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DecodeAndCropBlob(mimeType);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
CreateImageBitmapFromBlob::DecodeAndCropBlob(const nsACString& aMimeType)
|
||||||
|
{
|
||||||
// Get the Component object.
|
// Get the Component object.
|
||||||
nsCOMPtr<imgITools> imgtool = do_GetService(NS_IMGTOOLS_CID);
|
nsCOMPtr<imgITools> imgtool = do_GetService(NS_IMGTOOLS_CID);
|
||||||
if (NS_WARN_IF(!imgtool)) {
|
if (NS_WARN_IF(!imgtool)) {
|
||||||
|
@ -2236,8 +2268,7 @@ CreateImageBitmapFromBlob::DecodeAndCropBlob()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode image.
|
// Decode image.
|
||||||
nsCOMPtr<imgIContainer> imgContainer;
|
nsresult rv = imgtool->DecodeImageAsync(mInputStream, aMimeType, this,
|
||||||
nsresult rv = imgtool->DecodeImageAsync(mInputStream, mMimeType, this,
|
|
||||||
mMainThreadEventTarget);
|
mMainThreadEventTarget);
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -2246,6 +2277,54 @@ CreateImageBitmapFromBlob::DecodeAndCropBlob()
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static nsresult
|
||||||
|
sniff_cb(nsIInputStream* aInputStream,
|
||||||
|
void* aClosure,
|
||||||
|
const char* aFromRawSegment,
|
||||||
|
uint32_t aToOffset,
|
||||||
|
uint32_t aCount,
|
||||||
|
uint32_t* aWriteCount)
|
||||||
|
{
|
||||||
|
nsACString* mimeType = static_cast<nsACString*>(aClosure);
|
||||||
|
MOZ_ASSERT(mimeType);
|
||||||
|
|
||||||
|
if (aCount > 0) {
|
||||||
|
imgLoader::GetMimeTypeFromContent(aFromRawSegment, aCount, *mimeType);
|
||||||
|
}
|
||||||
|
|
||||||
|
*aWriteCount = 0;
|
||||||
|
|
||||||
|
// We don't want to consume data from the stream.
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
CreateImageBitmapFromBlob::GetMimeTypeSync(nsACString& aMimeType)
|
||||||
|
{
|
||||||
|
uint32_t dummy;
|
||||||
|
return mInputStream->ReadSegments(sniff_cb, &aMimeType, 128, &dummy);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
CreateImageBitmapFromBlob::GetMimeTypeAsync()
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIAsyncInputStream> asyncInputStream =
|
||||||
|
do_QueryInterface(mInputStream);
|
||||||
|
if (NS_WARN_IF(!asyncInputStream)) {
|
||||||
|
// If the stream is not async, why are we here?
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return asyncInputStream->AsyncWait(this, 0, 128, mMainThreadEventTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
CreateImageBitmapFromBlob::OnInputStreamReady(nsIAsyncInputStream* aStream)
|
||||||
|
{
|
||||||
|
// The stream should have data now. Let's start from scratch again.
|
||||||
|
return MimeTypeAndDecodeAndCropBlob();
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
CreateImageBitmapFromBlob::OnImageReady(imgIContainer* aImgContainer,
|
CreateImageBitmapFromBlob::OnImageReady(imgIContainer* aImgContainer,
|
||||||
nsresult aStatus)
|
nsresult aStatus)
|
||||||
|
@ -2253,7 +2332,7 @@ CreateImageBitmapFromBlob::OnImageReady(imgIContainer* aImgContainer,
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
if (NS_FAILED(aStatus)) {
|
if (NS_FAILED(aStatus)) {
|
||||||
DecodeAndCropBlobCompletedMainThread(nullptr, aStatus);
|
MimeTypeAndDecodeAndCropBlobCompletedMainThread(nullptr, aStatus);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2265,12 +2344,13 @@ CreateImageBitmapFromBlob::OnImageReady(imgIContainer* aImgContainer,
|
||||||
RefPtr<SourceSurface> surface = aImgContainer->GetFrame(whichFrame, frameFlags);
|
RefPtr<SourceSurface> surface = aImgContainer->GetFrame(whichFrame, frameFlags);
|
||||||
|
|
||||||
if (NS_WARN_IF(!surface)) {
|
if (NS_WARN_IF(!surface)) {
|
||||||
DecodeAndCropBlobCompletedMainThread(nullptr,
|
MimeTypeAndDecodeAndCropBlobCompletedMainThread(nullptr,
|
||||||
NS_ERROR_DOM_INVALID_STATE_ERR);
|
NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the sourceSize value for the DecodeAndCropBlobCompletedMainThread call.
|
// Store the sourceSize value for the
|
||||||
|
// MimeTypeAndDecodeAndCropBlobCompletedMainThread call.
|
||||||
mSourceSize = surface->GetSize();
|
mSourceSize = surface->GetSize();
|
||||||
|
|
||||||
// Crop the source surface if needed.
|
// Crop the source surface if needed.
|
||||||
|
@ -2295,8 +2375,8 @@ CreateImageBitmapFromBlob::OnImageReady(imgIContainer* aImgContainer,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NS_WARN_IF(!croppedSurface)) {
|
if (NS_WARN_IF(!croppedSurface)) {
|
||||||
DecodeAndCropBlobCompletedMainThread(nullptr,
|
MimeTypeAndDecodeAndCropBlobCompletedMainThread(nullptr,
|
||||||
NS_ERROR_DOM_INVALID_STATE_ERR);
|
NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2304,18 +2384,18 @@ CreateImageBitmapFromBlob::OnImageReady(imgIContainer* aImgContainer,
|
||||||
RefPtr<layers::Image> image = CreateImageFromSurface(croppedSurface);
|
RefPtr<layers::Image> image = CreateImageFromSurface(croppedSurface);
|
||||||
|
|
||||||
if (NS_WARN_IF(!image)) {
|
if (NS_WARN_IF(!image)) {
|
||||||
DecodeAndCropBlobCompletedMainThread(nullptr,
|
MimeTypeAndDecodeAndCropBlobCompletedMainThread(nullptr,
|
||||||
NS_ERROR_DOM_INVALID_STATE_ERR);
|
NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
DecodeAndCropBlobCompletedMainThread(image, NS_OK);
|
MimeTypeAndDecodeAndCropBlobCompletedMainThread(image, NS_OK);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CreateImageBitmapFromBlob::DecodeAndCropBlobCompletedMainThread(layers::Image* aImage,
|
CreateImageBitmapFromBlob::MimeTypeAndDecodeAndCropBlobCompletedMainThread(layers::Image* aImage,
|
||||||
nsresult aStatus)
|
nsresult aStatus)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
@ -2334,12 +2414,12 @@ CreateImageBitmapFromBlob::DecodeAndCropBlobCompletedMainThread(layers::Image* a
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DecodeAndCropBlobCompletedOwningThread(aImage, aStatus);
|
MimeTypeAndDecodeAndCropBlobCompletedOwningThread(aImage, aStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CreateImageBitmapFromBlob::DecodeAndCropBlobCompletedOwningThread(layers::Image* aImage,
|
CreateImageBitmapFromBlob::MimeTypeAndDecodeAndCropBlobCompletedOwningThread(layers::Image* aImage,
|
||||||
nsresult aStatus)
|
nsresult aStatus)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(IsCurrentThread());
|
MOZ_ASSERT(IsCurrentThread());
|
||||||
|
|
||||||
|
|
|
@ -311,3 +311,4 @@ skip-if = 1
|
||||||
subsuite = gpu
|
subsuite = gpu
|
||||||
tags = offscreencanvas
|
tags = offscreencanvas
|
||||||
skip-if = 1
|
skip-if = 1
|
||||||
|
[test_invalid_mime_type_blob.html]
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<title>createImageBitmap from Blob with invalid type</title>
|
||||||
|
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
function syncBlob() {
|
||||||
|
info("Let's create a small memory blob...");
|
||||||
|
|
||||||
|
// A 1x1 PNG image.
|
||||||
|
// Source: https://commons.wikimedia.org/wiki/File:1x1.png (Public Domain)
|
||||||
|
const IMAGE = atob("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAA" +
|
||||||
|
"ACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=");
|
||||||
|
|
||||||
|
let bytes = new Array(IMAGE.length);
|
||||||
|
for (let i = 0; i < IMAGE.length; i++) {
|
||||||
|
bytes[i] = IMAGE.charCodeAt(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
let blob = new Blob([new Uint8Array(bytes)], { type: "text/html"});
|
||||||
|
window.createImageBitmap(blob)
|
||||||
|
.then(imageBitmap => {
|
||||||
|
ok(true, "Image created!");
|
||||||
|
is(imageBitmap.width, 1, "Image is 1x1");
|
||||||
|
is(imageBitmap.height, 1, "Image is 1x1");
|
||||||
|
})
|
||||||
|
.then(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
function asyncBlob() {
|
||||||
|
info("Let's create a big memory blob...");
|
||||||
|
|
||||||
|
// A 1x1 PNG image.
|
||||||
|
// Source: https://commons.wikimedia.org/wiki/File:1x1.png (Public Domain)
|
||||||
|
const IMAGE = atob("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAA" +
|
||||||
|
"ACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=");
|
||||||
|
|
||||||
|
let bytes = new Array(IMAGE.length);
|
||||||
|
for (let i = 0; i < IMAGE.length; i++) {
|
||||||
|
bytes[i] = IMAGE.charCodeAt(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
let array = [];
|
||||||
|
for (let i = 0; i < 20000; ++i) {
|
||||||
|
array.push(new Uint8Array(bytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
let blob = new Blob(array, { type: "text/html"});
|
||||||
|
ok(blob.size > 1000000, "More than 1mb");
|
||||||
|
|
||||||
|
let bc = new BroadcastChannel('a');
|
||||||
|
bc.onmessage = e => {
|
||||||
|
window.createImageBitmap(e.data)
|
||||||
|
.then(imageBitmap => {
|
||||||
|
ok(true, "Image created!");
|
||||||
|
is(imageBitmap.width, 1, "Image is 1x1");
|
||||||
|
is(imageBitmap.height, 1, "Image is 1x1");
|
||||||
|
})
|
||||||
|
.then(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
new BroadcastChannel('a').postMessage(blob);
|
||||||
|
}
|
||||||
|
|
||||||
|
let tests = [
|
||||||
|
syncBlob,
|
||||||
|
asyncBlob,
|
||||||
|
];
|
||||||
|
|
||||||
|
function next() {
|
||||||
|
if (tests.length == 0) {
|
||||||
|
SimpleTest.finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let test = tests.shift();
|
||||||
|
test();
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
next();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,27 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<title>createImageBitmap: blob with wrong mime type</title>
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
<script src="/common/canvas-tests.js"></script>
|
||||||
|
<script>
|
||||||
|
promise_test(t => {
|
||||||
|
// Source: https://commons.wikimedia.org/wiki/File:1x1.png (Public Domain)
|
||||||
|
const IMAGE = atob("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAA" +
|
||||||
|
"ACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=");
|
||||||
|
|
||||||
|
let bytes = new Array(IMAGE.length);
|
||||||
|
for (let i = 0; i < IMAGE.length; i++) {
|
||||||
|
bytes[i] = IMAGE.charCodeAt(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
let blob = new Blob([new Uint8Array(bytes)], { type: "text/html"});
|
||||||
|
|
||||||
|
return window.createImageBitmap(blob)
|
||||||
|
.then(imageBitmap => {
|
||||||
|
assert_true(true, "Image created!");
|
||||||
|
assert_equals(imageBitmap.width, 1, "Image is 1x1");
|
||||||
|
assert_equals(imageBitmap.height, 1, "Image is 1x1");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
Загрузка…
Ссылка в новой задаче