# HG changeset patch # User Ehsan Akhgari Bug 1180105 - Do not leak the SourceSurface returned from imgIContainer::GetFrame in BlockUntilDecodedAndFinishObserving; r=seth diff --git a/image/MultipartImage.cpp b/image/MultipartImage.cpp index 299ee07..a34d47d 100644 --- a/image/MultipartImage.cpp +++ b/image/MultipartImage.cpp @@ -33,18 +33,19 @@ public: nsRefPtr tracker = mImage->GetProgressTracker(); tracker->AddObserver(this); } void BlockUntilDecodedAndFinishObserving() { // Use GetFrame() to block until our image finishes decoding. - mImage->GetFrame(imgIContainer::FRAME_CURRENT, - imgIContainer::FLAG_SYNC_DECODE); + nsRefPtr surface = + mImage->GetFrame(imgIContainer::FRAME_CURRENT, + imgIContainer::FLAG_SYNC_DECODE); FinishObserving(); } virtual void Notify(int32_t aType, const nsIntRect* aRect = nullptr) override { if (!mImage) { diff --git a/image/test/mochitest/bug1180105-waiter.sjs b/image/test/mochitest/bug1180105-waiter.sjs new file mode 100644 index 0000000..4e86ae2 --- /dev/null +++ b/image/test/mochitest/bug1180105-waiter.sjs @@ -0,0 +1,24 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +var timer = Components.classes["@mozilla.org/timer;1"]; +var waitTimer = timer.createInstance(Components.interfaces.nsITimer); + +function handleRequest(request, response) { + response.setHeader("Content-Type", "text/html", false); + response.setHeader("Cache-Control", "no-cache", false); + response.setStatusLine(request.httpVersion, 200, "OK"); + response.processAsync(); + waitForFinish(response); +} + +function waitForFinish(response) { + if (getSharedState("all-parts-done") === "1") { + response.write("done"); + response.finish(); + } else { + waitTimer.initWithCallback(function() {waitForFinish(response);}, 10, + Components.interfaces.nsITimer.TYPE_ONE_SHOT); + } +} diff --git a/image/test/mochitest/bug1180105.sjs b/image/test/mochitest/bug1180105.sjs new file mode 100644 index 0000000..e138e54 --- /dev/null +++ b/image/test/mochitest/bug1180105.sjs @@ -0,0 +1,63 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +var counter = 100; +var timer = Components.classes["@mozilla.org/timer;1"]; +var partTimer = timer.createInstance(Components.interfaces.nsITimer); + +function getFileAsInputStream(aFilename) { + var file = Components.classes["@mozilla.org/file/directory_service;1"] + .getService(Components.interfaces.nsIProperties) + .get("CurWorkD", Components.interfaces.nsIFile); + + file.append("tests"); + file.append("image"); + file.append("test"); + file.append("mochitest"); + file.append(aFilename); + + var fileStream = Components.classes['@mozilla.org/network/file-input-stream;1'] + .createInstance(Components.interfaces.nsIFileInputStream); + fileStream.init(file, 1, 0, false); + return fileStream; +} + +function handleRequest(request, response) +{ + response.setHeader("Content-Type", + "multipart/x-mixed-replace;boundary=BOUNDARYOMG", false); + response.setHeader("Cache-Control", "no-cache", false); + response.setStatusLine(request.httpVersion, 200, "OK"); + // We're sending parts off in a delayed fashion, to let the tests occur. + response.processAsync(); + response.write("--BOUNDARYOMG\r\n"); + sendParts(response); +} + +function sendParts(response) { + if (counter-- == 0) { + sendClose(response); + setSharedState("all-parts-done", "1"); + return; + } + sendNextPart(response); + partTimer.initWithCallback(function() {sendParts(response);}, 1, + Components.interfaces.nsITimer.TYPE_ONE_SHOT); +} + +function sendClose(response) { + response.write("--BOUNDARYOMG--\r\n"); + response.finish(); +} + +function sendNextPart(response) { + var nextPartHead = "Content-Type: image/jpeg\r\n\r\n"; + var inputStream = getFileAsInputStream("damon.jpg"); + response.bodyOutputStream.write(nextPartHead, nextPartHead.length); + response.bodyOutputStream.writeFrom(inputStream, inputStream.available()); + inputStream.close(); + // Toss in the boundary, so the browser can know this part is complete + response.write("--BOUNDARYOMG\r\n"); +} + diff --git a/image/test/mochitest/mochitest.ini b/image/test/mochitest/mochitest.ini index 611d543..8944a81 100644 --- a/image/test/mochitest/mochitest.ini +++ b/image/test/mochitest/mochitest.ini @@ -25,16 +25,18 @@ support-files = bug671906.sjs bug733553-informant.sjs bug733553.sjs bug767779.sjs bug89419-iframe.html bug89419.sjs bug900200.png bug900200-ref.png + bug1180105.sjs + bug1180105-waiter.sjs clear.gif clear.png clear2.gif clear2-results.gif damon.jpg error-early.png green.png green-background.html @@ -81,16 +83,17 @@ skip-if = (toolkit == 'android' && processor == 'x86') #x86 only skip-if = (toolkit == 'android' && processor == 'x86') #x86 only [test_bug733553.html] [test_bug767779.html] [test_bug865919.html] [test_bug89419-1.html] skip-if = (toolkit == 'android' && processor == 'x86') #x86 only [test_bug89419-2.html] skip-if = (toolkit == 'android' && processor == 'x86') #x86 only +[test_bug1180105.html] [test_animation_operators.html] [test_drawDiscardedImage.html] skip-if = toolkit == "gonk" #Bug 997034 - canvas.toDataURL() often causes lost connection to device. [test_error_events.html] [test_short_gif_header.html] [test_image_buffer_limit.html] #skip-if = toolkit != "gonk" #Image buffer limit is only set for Firefox OS currently. disabled = bug 1060869 diff --git a/image/test/mochitest/test_bug1180105.html b/image/test/mochitest/test_bug1180105.html new file mode 100644 index 0000000..1691b62 --- /dev/null +++ b/image/test/mochitest/test_bug1180105.html @@ -0,0 +1,46 @@ + + + + + Test for Bug 1180105 + + + + + +Mozilla Bug 1180105 +

+
+
+
+
> + +
+ +