From b9fef1cb05c9a7bc0c3d1b8f3fbb351b65c2e6f5 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Fri, 3 Jul 2015 10:45:33 -0400 Subject: [PATCH] Bug 1180105 - Do not leak the SourceSurface returned from imgIContainer::GetFrame in BlockUntilDecodedAndFinishObserving; r=seth --- image/MultipartImage.cpp | 5 +- image/test/mochitest/bug1180105-waiter.sjs | 24 +++++++++ image/test/mochitest/bug1180105.sjs | 63 ++++++++++++++++++++++ image/test/mochitest/mochitest.ini | 3 ++ image/test/mochitest/test_bug1180105.html | 46 ++++++++++++++++ 5 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 image/test/mochitest/bug1180105-waiter.sjs create mode 100644 image/test/mochitest/bug1180105.sjs create mode 100644 image/test/mochitest/test_bug1180105.html diff --git a/image/MultipartImage.cpp b/image/MultipartImage.cpp index 5e94e599798f..387d5953f2d9 100644 --- a/image/MultipartImage.cpp +++ b/image/MultipartImage.cpp @@ -38,8 +38,9 @@ public: 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(); } diff --git a/image/test/mochitest/bug1180105-waiter.sjs b/image/test/mochitest/bug1180105-waiter.sjs new file mode 100644 index 000000000000..4e86ae28797c --- /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 000000000000..e138e548eec5 --- /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 611d543637ab..8944a8131652 100644 --- a/image/test/mochitest/mochitest.ini +++ b/image/test/mochitest/mochitest.ini @@ -30,6 +30,8 @@ support-files = bug89419.sjs bug900200.png bug900200-ref.png + bug1180105.sjs + bug1180105-waiter.sjs clear.gif clear.png clear2.gif @@ -86,6 +88,7 @@ skip-if = (toolkit == 'android' && processor == 'x86') #x86 only 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. diff --git a/image/test/mochitest/test_bug1180105.html b/image/test/mochitest/test_bug1180105.html new file mode 100644 index 000000000000..1691b621c2b2 --- /dev/null +++ b/image/test/mochitest/test_bug1180105.html @@ -0,0 +1,46 @@ + + + + + Test for Bug 1180105 + + + + + +Mozilla Bug 1180105 +

+
+
+
+
> + +
+ +