Bug 648610: Implement <canvas>.toBlob. r=smaug

--HG--
rename : content/canvas/test/test_mozGetAsFile.html => content/canvas/test/test_toBlob.html
This commit is contained in:
Kyle Huey 2012-10-15 14:15:25 -07:00
parent a898f8ae41
commit e860e3a746
4 changed files with 125 additions and 0 deletions

View File

@ -50,6 +50,7 @@ MOCHITEST_FILES = \
test_2d.composite.uncovered.image.source-out.html \
test_2d.drawImage.zerocanvas.html \
test_2d.strokeRect.zero.5.html \
test_toBlob.html \
test_toDataURL_alpha.html \
test_toDataURL_lowercase_ascii.html \
test_toDataURL_parameters.html \

View File

@ -0,0 +1,42 @@
<!DOCTYPE HTML>
<title>Canvas test: mozGetAsFile</title>
<script src="/MochiKit/MochiKit.js"></script>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
<body>
<canvas id="c" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
<script>
var gCompares = 2;
function BlobListener(type, canvas, file)
{
is(file.type, type,
"When a valid type is specified that should be returned");
var reader = new FileReader();
reader.onload =
function(e) {
is(e.target.result, canvas.toDataURL(type),
"<canvas>.mozGetAsFile().getAsDataURL() should equal <canvas>.toDataURL()");
if (--gCompares == 0) {
SimpleTest.finish();
}
};
reader.readAsDataURL(file);
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(function () {
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
ctx.drawImage(document.getElementById('yellow75.png'), 0, 0);
canvas.toBlob(BlobListener.bind(undefined, "image/png", canvas));
canvas.toBlob(BlobListener.bind(undefined, "image/jpeg", canvas), "image/jpeg");
});
</script>
<img src="image_yellow75.png" id="yellow75.png" class="resource">

View File

@ -40,6 +40,32 @@ using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::layers;
namespace {
class ToBlobRunnable : public nsRunnable
{
public:
ToBlobRunnable(nsIFileCallback* aCallback,
nsIDOMBlob* aBlob)
: mCallback(aCallback),
mBlob(aBlob)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
}
NS_IMETHOD Run()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
mCallback->Receive(mBlob);
return NS_OK;
}
private:
nsCOMPtr<nsIFileCallback> mCallback;
nsCOMPtr<nsIDOMBlob> mBlob;
};
} // anonymous namespace
class nsHTMLCanvasPrintState : public nsIDOMMozCanvasPrintState
{
public:
@ -550,6 +576,52 @@ nsHTMLCanvasElement::ToDataURLImpl(const nsAString& aMimeType,
return Base64EncodeInputStream(stream, aDataURL, (uint32_t)count, aDataURL.Length());
}
// XXXkhuey the encoding should be off the main thread, but we're lazy.
NS_IMETHODIMP
nsHTMLCanvasElement::ToBlob(nsIFileCallback* aCallback,
const nsAString& aType,
nsIVariant* aParams,
uint8_t optional_argc)
{
// do a trust check if this is a write-only canvas
if (mWriteOnly && !nsContentUtils::IsCallerTrustedForRead()) {
return NS_ERROR_DOM_SECURITY_ERR;
}
nsAutoString type;
nsresult rv = nsContentUtils::ASCIIToLower(aType, type);
if (NS_FAILED(rv)) {
return rv;
}
bool fallbackToPNG = false;
nsCOMPtr<nsIInputStream> stream;
nsresult rv = ExtractData(type, EmptyString(), getter_AddRefs(stream),
fallbackToPNG);
NS_ENSURE_SUCCESS(rv, rv);
if (fallbackToPNG) {
type.AssignLiteral("image/png");
}
uint64_t imgSize;
rv = stream->Available(&imgSize);
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(imgSize <= UINT32_MAX, NS_ERROR_FILE_TOO_BIG);
void* imgData = nullptr;
rv = NS_ReadInputStreamToBuffer(stream, &imgData, imgSize);
NS_ENSURE_SUCCESS(rv, rv);
// The DOMFile takes ownership of the buffer
nsRefPtr<nsDOMMemoryFile> blob =
new nsDOMMemoryFile(imgData, imgSize, type);
nsRefPtr<ToBlobRunnable> runnable = new ToBlobRunnable(aCallback, blob);
return NS_DispatchToCurrentThread(runnable);
}
NS_IMETHODIMP
nsHTMLCanvasElement::MozGetAsFile(const nsAString& aName,
const nsAString& aType,

View File

@ -20,6 +20,7 @@
* @status UNDER_DEVELOPMENT
*/
interface nsIDOMBlob;
interface nsIDOMFile;
interface nsIVariant;
interface nsIInputStreamCallback;
@ -40,6 +41,11 @@ interface nsIPrintCallback : nsISupports
void render(in nsIDOMMozCanvasPrintState ctx);
};
[scriptable, function, uuid(6e9ffb59-2067-4aef-a51c-65e65a3e0d81)]
interface nsIFileCallback : nsISupports {
void receive(in nsIDOMBlob file);
};
[scriptable, uuid(a7062fca-41c6-4520-b777-3bb30fd77273)]
interface nsIDOMHTMLCanvasElement : nsIDOMHTMLElement
{
@ -64,6 +70,10 @@ interface nsIDOMHTMLCanvasElement : nsIDOMHTMLElement
[optional_argc] nsIDOMFile mozGetAsFile(in DOMString name,
[optional] in DOMString type);
[optional_argc] void toBlob(in nsIFileCallback callback,
[optional] in DOMString type,
[optional] in nsIVariant params);
// A Mozilla-only extension to get a canvas context backed by double-buffered
// shared memory. Only privileged callers can call this.
nsISupports MozGetIPCContext(in DOMString contextId);