Title: [281980] trunk
Revision
281980
Author
s...@apple.com
Date
2021-09-03 01:25:03 -0700 (Fri, 03 Sep 2021)

Log Message

Add a layout test to detect memory leaks when drawing images to a detached canvas
https://bugs.webkit.org/show_bug.cgi?id=229790

Reviewed by Darin Adler.

Source/WebCore:

Add an internal API to return the number of remote images which are cached
by WebProcess and GPUProcess. It can be used after rendering update is
finished to verify that there are no images cached because they are
referenced in a DispalyList of a detached canvas.

Test: fast/canvas/canvas-drawImage-detached-leak.html

* page/ChromeClient.h:
(WebCore::ChromeClient::remoteImagesCountForTesting const):
* testing/Internals.cpp:
(WebCore::Internals::remoteImagesCountForTesting const):
* testing/Internals.h:
* testing/Internals.idl:

Source/WebKit:

* WebProcess/GPU/graphics/RemoteResourceCacheProxy.h:
(WebKit::RemoteResourceCacheProxy::imagesCount const):
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::remoteImagesCountForTesting const):
* WebProcess/WebCoreSupport/WebChromeClient.h:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::remoteImagesCountForTesting const):
* WebProcess/WebPage/WebPage.h:

LayoutTests:

Draw frames on an animated image to a detached canvas. Verify at the end
and after releasing all the image decoded frames that there are no remote
cached images.

* fast/canvas/canvas-drawImage-detached-leak-expected.txt: Added.
* fast/canvas/canvas-drawImage-detached-leak.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (281979 => 281980)


--- trunk/LayoutTests/ChangeLog	2021-09-03 07:25:34 UTC (rev 281979)
+++ trunk/LayoutTests/ChangeLog	2021-09-03 08:25:03 UTC (rev 281980)
@@ -1,3 +1,17 @@
+2021-09-03  Said Abou-Hallawa  <s...@apple.com>
+
+        Add a layout test to detect memory leaks when drawing images to a detached canvas
+        https://bugs.webkit.org/show_bug.cgi?id=229790
+
+        Reviewed by Darin Adler.
+
+        Draw frames on an animated image to a detached canvas. Verify at the end
+        and after releasing all the image decoded frames that there are no remote
+        cached images.
+
+        * fast/canvas/canvas-drawImage-detached-leak-expected.txt: Added.
+        * fast/canvas/canvas-drawImage-detached-leak.html: Added.
+
 2021-09-03  Frédéric Wang  <fw...@igalia.com>
 
         Use isRendererReplacedElement for SimplifiedBackwardsTextIterator

Added: trunk/LayoutTests/fast/canvas/canvas-drawImage-detached-leak-expected.txt (0 => 281980)


--- trunk/LayoutTests/fast/canvas/canvas-drawImage-detached-leak-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/canvas/canvas-drawImage-detached-leak-expected.txt	2021-09-03 08:25:03 UTC (rev 281980)
@@ -0,0 +1,10 @@
+Test drawImage() to a detached canvas won't leak the drawn images.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS internals.remoteImagesCountForTesting() is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/canvas/canvas-drawImage-detached-leak.html (0 => 281980)


--- trunk/LayoutTests/fast/canvas/canvas-drawImage-detached-leak.html	                        (rev 0)
+++ trunk/LayoutTests/fast/canvas/canvas-drawImage-detached-leak.html	2021-09-03 08:25:03 UTC (rev 281980)
@@ -0,0 +1,57 @@
+<head>
+    <script src=""
+</head>
+<body>
+    <script>
+        let canvas = document.createElement('canvas');
+
+        description("Test drawImage() to a detached canvas won't leak the drawn images.");
+        jsTestIsAsync = true;
+
+        if (window.internals) {
+            internals.clearMemoryCache();
+            internals.settings.setAnimatedImageDebugCanvasDrawingEnabled(true);
+        }
+
+        const drawFrame = (image) => {
+            return new Promise((resolve) => {
+                requestAnimationFrame(() => {
+                    var ctx = canvas.getContext("2d");
+                    ctx.drawImage(image, 0, 0);
+                    setTimeout(() => {
+                        resolve();
+                    }, 30);
+                });
+            });
+        }
+
+        const drawImage = (image, frameCount) => {
+            let promise = drawFrame(image);
+            for (let frame = 1; frame < frameCount; ++frame) {
+                promise = promise.then(() => {
+                    return drawFrame(image);
+                });
+            }
+            return promise;
+        }
+
+        const loadAndDrawImage = (src, frameCount) => {
+            return new Promise((resolve) => {
+                let image = new Image;
+                image._onload_ = (() => {
+                    drawImage(image, frameCount).then(resolve);
+                });
+                image.src = ""
+            });
+        }
+
+        loadAndDrawImage("../images/resources/animated-red-green-blue-repeat-1.gif", 3).then(() => {
+            if (window.internals) {
+                internals.destroyDecodedDataForAllImages();
+                shouldBeZero("internals.remoteImagesCountForTesting()");
+            }
+            finishJSTest();
+        });
+    </script>
+    <script src=""
+</body>

Modified: trunk/Source/WebCore/ChangeLog (281979 => 281980)


--- trunk/Source/WebCore/ChangeLog	2021-09-03 07:25:34 UTC (rev 281979)
+++ trunk/Source/WebCore/ChangeLog	2021-09-03 08:25:03 UTC (rev 281980)
@@ -1,3 +1,24 @@
+2021-09-03  Said Abou-Hallawa  <s...@apple.com>
+
+        Add a layout test to detect memory leaks when drawing images to a detached canvas
+        https://bugs.webkit.org/show_bug.cgi?id=229790
+
+        Reviewed by Darin Adler.
+
+        Add an internal API to return the number of remote images which are cached
+        by WebProcess and GPUProcess. It can be used after rendering update is
+        finished to verify that there are no images cached because they are
+        referenced in a DispalyList of a detached canvas.
+
+        Test: fast/canvas/canvas-drawImage-detached-leak.html
+
+        * page/ChromeClient.h:
+        (WebCore::ChromeClient::remoteImagesCountForTesting const):
+        * testing/Internals.cpp:
+        (WebCore::Internals::remoteImagesCountForTesting const):
+        * testing/Internals.h:
+        * testing/Internals.idl:
+
 2021-09-03  Frédéric Wang  <fw...@igalia.com>
 
         Use isRendererReplacedElement for SimplifiedBackwardsTextIterator

Modified: trunk/Source/WebCore/page/ChromeClient.h (281979 => 281980)


--- trunk/Source/WebCore/page/ChromeClient.h	2021-09-03 07:25:34 UTC (rev 281979)
+++ trunk/Source/WebCore/page/ChromeClient.h	2021-09-03 08:25:03 UTC (rev 281980)
@@ -368,6 +368,8 @@
     // Schedule a rendering update that coordinates with display refresh. Returns true if scheduled. (This is only used by SVGImageChromeClient.)
     virtual bool scheduleRenderingUpdate() { return false; }
 
+    virtual unsigned remoteImagesCountForTesting() const { return 0; }
+
     // Returns whether or not the client can render the composited layer,
     // regardless of the settings.
     virtual bool allowsAcceleratedCompositing() const { return true; }

Modified: trunk/Source/WebCore/testing/Internals.cpp (281979 => 281980)


--- trunk/Source/WebCore/testing/Internals.cpp	2021-09-03 07:25:34 UTC (rev 281979)
+++ trunk/Source/WebCore/testing/Internals.cpp	2021-09-03 08:25:03 UTC (rev 281980)
@@ -1007,6 +1007,15 @@
 #endif
 }
 
+unsigned Internals::remoteImagesCountForTesting() const
+{
+    Document* document = contextDocument();
+    if (!document || !document->page())
+        return 0;
+
+    return document->page()->chrome().client().remoteImagesCountForTesting();
+}
+
 void Internals::setLargeImageAsyncDecodingEnabledForTesting(HTMLImageElement& element, bool enabled)
 {
     if (auto* bitmapImage = bitmapImageFromImageElement(element))

Modified: trunk/Source/WebCore/testing/Internals.h (281979 => 281980)


--- trunk/Source/WebCore/testing/Internals.h	2021-09-03 07:25:34 UTC (rev 281979)
+++ trunk/Source/WebCore/testing/Internals.h	2021-09-03 08:25:03 UTC (rev 281980)
@@ -199,6 +199,7 @@
     void setClearDecoderAfterAsyncFrameRequestForTesting(HTMLImageElement&, bool enabled);
     unsigned imageDecodeCount(HTMLImageElement&);
     unsigned pdfDocumentCachingCount(HTMLImageElement&);
+    unsigned remoteImagesCountForTesting() const;
     void setLargeImageAsyncDecodingEnabledForTesting(HTMLImageElement&, bool enabled);
     void setForceUpdateImageDataEnabledForTesting(HTMLImageElement&, bool enabled);
 

Modified: trunk/Source/WebCore/testing/Internals.idl (281979 => 281980)


--- trunk/Source/WebCore/testing/Internals.idl	2021-09-03 07:25:34 UTC (rev 281979)
+++ trunk/Source/WebCore/testing/Internals.idl	2021-09-03 08:25:03 UTC (rev 281980)
@@ -497,6 +497,7 @@
     undefined setClearDecoderAfterAsyncFrameRequestForTesting(HTMLImageElement element, boolean enabled);
     unsigned long imageDecodeCount(HTMLImageElement element);
     unsigned long pdfDocumentCachingCount(HTMLImageElement element);
+    unsigned long remoteImagesCountForTesting();
     undefined setLargeImageAsyncDecodingEnabledForTesting(HTMLImageElement element, boolean enabled);
     undefined setForceUpdateImageDataEnabledForTesting(HTMLImageElement element, boolean enabled);
 

Modified: trunk/Source/WebKit/ChangeLog (281979 => 281980)


--- trunk/Source/WebKit/ChangeLog	2021-09-03 07:25:34 UTC (rev 281979)
+++ trunk/Source/WebKit/ChangeLog	2021-09-03 08:25:03 UTC (rev 281980)
@@ -1,3 +1,19 @@
+2021-09-03  Said Abou-Hallawa  <s...@apple.com>
+
+        Add a layout test to detect memory leaks when drawing images to a detached canvas
+        https://bugs.webkit.org/show_bug.cgi?id=229790
+
+        Reviewed by Darin Adler.
+
+        * WebProcess/GPU/graphics/RemoteResourceCacheProxy.h:
+        (WebKit::RemoteResourceCacheProxy::imagesCount const):
+        * WebProcess/WebCoreSupport/WebChromeClient.cpp:
+        (WebKit::WebChromeClient::remoteImagesCountForTesting const):
+        * WebProcess/WebCoreSupport/WebChromeClient.h:
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::remoteImagesCountForTesting const):
+        * WebProcess/WebPage/WebPage.h:
+
 2021-09-02  Wenson Hsieh  <wenson_hs...@apple.com>
 
         REGRESSION (r280767): Caret color is black after pasting rich text in Mail compose in dark mode

Modified: trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteResourceCacheProxy.h (281979 => 281980)


--- trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteResourceCacheProxy.h	2021-09-03 07:25:34 UTC (rev 281979)
+++ trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteResourceCacheProxy.h	2021-09-03 08:25:03 UTC (rev 281980)
@@ -59,6 +59,8 @@
     void remoteResourceCacheWasDestroyed();
     void releaseAllRemoteFonts();
     void releaseMemory();
+    
+    unsigned imagesCount() const { return m_nativeImages.size(); }
 
 private:
     struct ImageBufferState {

Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp (281979 => 281980)


--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp	2021-09-03 07:25:34 UTC (rev 281979)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp	2021-09-03 08:25:03 UTC (rev 281980)
@@ -988,6 +988,11 @@
         m_page.drawingArea()->triggerRenderingUpdate();
 }
 
+unsigned WebChromeClient::remoteImagesCountForTesting() const
+{
+    return m_page.remoteImagesCountForTesting();
+}
+
 void WebChromeClient::contentRuleListNotification(const URL& url, const ContentRuleListResults& results)
 {
 #if ENABLE(CONTENT_EXTENSIONS)

Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h (281979 => 281980)


--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h	2021-09-03 07:25:34 UTC (rev 281979)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h	2021-09-03 08:25:03 UTC (rev 281980)
@@ -229,6 +229,7 @@
     void setNeedsOneShotDrawingSynchronization() final;
     bool shouldTriggerRenderingUpdate(unsigned rescheduledRenderingUpdateCount) const final;
     void triggerRenderingUpdate() final;
+    unsigned remoteImagesCountForTesting() const final; 
 
     void contentRuleListNotification(const URL&, const WebCore::ContentRuleListResults&) final;
 

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (281979 => 281980)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2021-09-03 07:25:34 UTC (rev 281979)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2021-09-03 08:25:03 UTC (rev 281980)
@@ -4223,6 +4223,17 @@
 #endif
 }
 
+unsigned WebPage::remoteImagesCountForTesting() const
+{
+#if ENABLE(GPU_PROCESS)
+    if (!m_remoteRenderingBackendProxy)
+        return 0;
+    return m_remoteRenderingBackendProxy->remoteResourceCacheProxy().imagesCount();
+#else
+    return 0;
+#endif
+}
+
 WebInspector* WebPage::inspector(LazyCreationPolicy behavior)
 {
     if (m_isClosed)

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (281979 => 281980)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2021-09-03 07:25:34 UTC (rev 281979)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2021-09-03 08:25:03 UTC (rev 281980)
@@ -407,6 +407,8 @@
 
     void releaseMemory(WTF::Critical);
 
+    unsigned remoteImagesCountForTesting() const;
+
     enum class LazyCreationPolicy { UseExistingOnly, CreateIfNeeded };
 
     WebInspector* inspector(LazyCreationPolicy = LazyCreationPolicy::CreateIfNeeded);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to