Title: [284786] trunk
Revision
284786
Author
[email protected]
Date
2021-10-25 08:37:16 -0700 (Mon, 25 Oct 2021)

Log Message

REGRESSION (r284079): Audio continues playing on hulu.com in private browsing mode after closing the tab
https://bugs.webkit.org/show_bug.cgi?id=232113
rdar://84399283

Reviewed by Chris Dumez.

Source/WebKit:

I inadvertently introduced a ref-counting cycle between RemoteRenderingBackend and RemoteDisplayListRecorder
after IPC stream refactoring in r284079, since RemoteDisplayListRecorder directly strongly refs the rendering
backend, and the rendering backend indirectly holds on to RemoteDisplayListRecorders through remote image
buffers in the resource cache. Since RemoteRenderingBackend also strongly refs  GPUConnectionToWebProcess as
well, this caused the entire GPUConnectionToWebProcess to leak after tearing down the connected web process, if
the web process ever installed a remote rendering backend for 2D canvas.

To avoid this cycle, turn RemoteDisplayListRecorder's `m_renderingBackend` into a RefPtr instead of a Ref, and
clear it out in `stopListeningForIPC()`. This also means that we no longer need a separate boolean flag to
ensure that `RemoteDisplayListRecorder::stopListeningForIPC()` is idempotent, so we also remove
`m_isListeningForIPC` altogether.

Test: GPUProcess.DoNotLeakConnectionAfterClosingWebPage

* GPUProcess/GPUConnectionToWebProcess.cpp:
(WebKit::GPUConnectionToWebProcess::GPUConnectionToWebProcess):
(WebKit::GPUConnectionToWebProcess::~GPUConnectionToWebProcess):
* GPUProcess/GPUConnectionToWebProcess.h:
(WebKit::GPUConnectionToWebProcess::objectCountForTesting):
* GPUProcess/GPUProcess.cpp:
(WebKit::GPUProcess::webProcessConnectionCountForTesting):

Add support for a testing-only SPI hook to ask for the live GPUConnectionToWebProcess count. This retrieves a
statically incremented/decremented count of the GPUConnectionToWebProcess instances that exist in the GPU
process; importantly, this is different from asking the GPUProcess for the number of connections in
`m_webProcessConnections`, since the latter will be 0 even when one or more GPUConnectionToWebProcesses are
still alive.

* GPUProcess/GPUProcess.h:
* GPUProcess/GPUProcess.messages.in:
* GPUProcess/graphics/RemoteDisplayListRecorder.cpp:
(WebKit::RemoteDisplayListRecorder::RemoteDisplayListRecorder):

Also fix a leak caused by RemoteDisplayListRecorder and RemoteImageBuffer strongly reffing each other. Since
RemoteImageBuffer owns RemoteDisplayListRecorder, the backpointer from RemoteDisplayListRecorder to the image
buffer should be weak, not strong.

(WebKit::RemoteDisplayListRecorder::startListeningForIPC):
(WebKit::RemoteDisplayListRecorder::stopListeningForIPC):
(WebKit::RemoteDisplayListRecorder::paintFrameForMedia):
* GPUProcess/graphics/RemoteDisplayListRecorder.h:
(): Deleted.
* GPUProcess/graphics/RemoteRenderingBackend.cpp:
(WebKit::RemoteRenderingBackend::stopListeningForIPC):

Adjust this logic to ensure that we finish pending work and destroy cached resources *right before* we stop
listening for all stream IPC messages. Since RemoteDisplayListRecorder now clears out its pointer to the
rendering backend in `stopListeningForIPC()`, we'll need to ensure that any pending IPC stream messages that
might cause RemoteDisplayListRecorder to call into the back end are processed before we sever the IPC stream
connection for good by removing all receivers.

* UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h:

Add the new testing SPI (see above for more details).

* UIProcess/API/Cocoa/WKWebViewTesting.mm:
(-[WKWebView _gpuToWebProcessConnectionCountForTesting:]):
* UIProcess/GPU/GPUProcessProxy.cpp:
(WebKit::GPUProcessProxy::webProcessConnectionCountForTesting):
* UIProcess/GPU/GPUProcessProxy.h:

Tools:

Add a new API test to verify that the GPU to web prcoess connection isn't leaked in the GPU process. See WebKit
ChangeLog for more details.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm:
* TestWebKitAPI/Tests/WebKitCocoa/canvas-image-data.html: Added.
* TestWebKitAPI/cocoa/TestWKWebView.h:
* TestWebKitAPI/cocoa/TestWKWebView.mm:
(-[WKWebView gpuToWebProcessConnectionCount]):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (284785 => 284786)


--- trunk/Source/WebKit/ChangeLog	2021-10-25 15:26:54 UTC (rev 284785)
+++ trunk/Source/WebKit/ChangeLog	2021-10-25 15:37:16 UTC (rev 284786)
@@ -1,3 +1,72 @@
+2021-10-25  Wenson Hsieh  <[email protected]>
+
+        REGRESSION (r284079): Audio continues playing on hulu.com in private browsing mode after closing the tab
+        https://bugs.webkit.org/show_bug.cgi?id=232113
+        rdar://84399283
+
+        Reviewed by Chris Dumez.
+
+        I inadvertently introduced a ref-counting cycle between RemoteRenderingBackend and RemoteDisplayListRecorder
+        after IPC stream refactoring in r284079, since RemoteDisplayListRecorder directly strongly refs the rendering
+        backend, and the rendering backend indirectly holds on to RemoteDisplayListRecorders through remote image
+        buffers in the resource cache. Since RemoteRenderingBackend also strongly refs  GPUConnectionToWebProcess as
+        well, this caused the entire GPUConnectionToWebProcess to leak after tearing down the connected web process, if
+        the web process ever installed a remote rendering backend for 2D canvas.
+
+        To avoid this cycle, turn RemoteDisplayListRecorder's `m_renderingBackend` into a RefPtr instead of a Ref, and
+        clear it out in `stopListeningForIPC()`. This also means that we no longer need a separate boolean flag to
+        ensure that `RemoteDisplayListRecorder::stopListeningForIPC()` is idempotent, so we also remove
+        `m_isListeningForIPC` altogether.
+
+        Test: GPUProcess.DoNotLeakConnectionAfterClosingWebPage
+
+        * GPUProcess/GPUConnectionToWebProcess.cpp:
+        (WebKit::GPUConnectionToWebProcess::GPUConnectionToWebProcess):
+        (WebKit::GPUConnectionToWebProcess::~GPUConnectionToWebProcess):
+        * GPUProcess/GPUConnectionToWebProcess.h:
+        (WebKit::GPUConnectionToWebProcess::objectCountForTesting):
+        * GPUProcess/GPUProcess.cpp:
+        (WebKit::GPUProcess::webProcessConnectionCountForTesting):
+
+        Add support for a testing-only SPI hook to ask for the live GPUConnectionToWebProcess count. This retrieves a
+        statically incremented/decremented count of the GPUConnectionToWebProcess instances that exist in the GPU
+        process; importantly, this is different from asking the GPUProcess for the number of connections in
+        `m_webProcessConnections`, since the latter will be 0 even when one or more GPUConnectionToWebProcesses are
+        still alive.
+
+        * GPUProcess/GPUProcess.h:
+        * GPUProcess/GPUProcess.messages.in:
+        * GPUProcess/graphics/RemoteDisplayListRecorder.cpp:
+        (WebKit::RemoteDisplayListRecorder::RemoteDisplayListRecorder):
+
+        Also fix a leak caused by RemoteDisplayListRecorder and RemoteImageBuffer strongly reffing each other. Since
+        RemoteImageBuffer owns RemoteDisplayListRecorder, the backpointer from RemoteDisplayListRecorder to the image
+        buffer should be weak, not strong.
+
+        (WebKit::RemoteDisplayListRecorder::startListeningForIPC):
+        (WebKit::RemoteDisplayListRecorder::stopListeningForIPC):
+        (WebKit::RemoteDisplayListRecorder::paintFrameForMedia):
+        * GPUProcess/graphics/RemoteDisplayListRecorder.h:
+        (): Deleted.
+        * GPUProcess/graphics/RemoteRenderingBackend.cpp:
+        (WebKit::RemoteRenderingBackend::stopListeningForIPC):
+
+        Adjust this logic to ensure that we finish pending work and destroy cached resources *right before* we stop
+        listening for all stream IPC messages. Since RemoteDisplayListRecorder now clears out its pointer to the
+        rendering backend in `stopListeningForIPC()`, we'll need to ensure that any pending IPC stream messages that
+        might cause RemoteDisplayListRecorder to call into the back end are processed before we sever the IPC stream
+        connection for good by removing all receivers.
+
+        * UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h:
+
+        Add the new testing SPI (see above for more details).
+
+        * UIProcess/API/Cocoa/WKWebViewTesting.mm:
+        (-[WKWebView _gpuToWebProcessConnectionCountForTesting:]):
+        * UIProcess/GPU/GPUProcessProxy.cpp:
+        (WebKit::GPUProcessProxy::webProcessConnectionCountForTesting):
+        * UIProcess/GPU/GPUProcessProxy.h:
+
 2021-10-25  Sam Sneddon  <[email protected]>
 
         [Python] rename assertEquals/assertNotEquals

Modified: trunk/Source/WebKit/GPUProcess/GPUConnectionToWebProcess.cpp (284785 => 284786)


--- trunk/Source/WebKit/GPUProcess/GPUConnectionToWebProcess.cpp	2021-10-25 15:26:54 UTC (rev 284785)
+++ trunk/Source/WebKit/GPUProcess/GPUConnectionToWebProcess.cpp	2021-10-25 15:37:16 UTC (rev 284786)
@@ -248,6 +248,8 @@
     // reply from the GPU process, which would be unsafe.
     m_connection->setOnlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage(true);
     m_connection->open();
+
+    ++gObjectCountForTesting;
 }
 
 GPUConnectionToWebProcess::~GPUConnectionToWebProcess()
@@ -262,8 +264,12 @@
 #if PLATFORM(COCOA) && USE(LIBWEBRTC)
     m_libWebRTCCodecsProxy->close();
 #endif
+
+    --gObjectCountForTesting;
 }
 
+uint64_t GPUConnectionToWebProcess::gObjectCountForTesting = 0;
+
 void GPUConnectionToWebProcess::didClose(IPC::Connection& connection)
 {
 #if ENABLE(ROUTING_ARBITRATION) && HAVE(AVAUDIO_ROUTING_ARBITER)

Modified: trunk/Source/WebKit/GPUProcess/GPUConnectionToWebProcess.h (284785 => 284786)


--- trunk/Source/WebKit/GPUProcess/GPUConnectionToWebProcess.h	2021-10-25 15:26:54 UTC (rev 284785)
+++ trunk/Source/WebKit/GPUProcess/GPUConnectionToWebProcess.h	2021-10-25 15:37:16 UTC (rev 284786)
@@ -170,6 +170,8 @@
     void releaseGraphicsContextGLForTesting(GraphicsContextGLIdentifier);
 #endif
 
+    static uint64_t objectCountForTesting() { return gObjectCountForTesting; }
+
     using RemoteRenderingBackendMap = HashMap<RenderingBackendIdentifier, IPC::ScopedActiveMessageReceiveQueue<RemoteRenderingBackend>>;
     const RemoteRenderingBackendMap& remoteRenderingBackendMap() const { return m_remoteRenderingBackendMap; }
 
@@ -242,6 +244,8 @@
     void dispatchDisplayWasReconfigured();
 #endif
 
+    static uint64_t gObjectCountForTesting;
+
     RefPtr<Logger> m_logger;
 
     Ref<IPC::Connection> m_connection;

Modified: trunk/Source/WebKit/GPUProcess/GPUProcess.cpp (284785 => 284786)


--- trunk/Source/WebKit/GPUProcess/GPUProcess.cpp	2021-10-25 15:26:54 UTC (rev 284785)
+++ trunk/Source/WebKit/GPUProcess/GPUProcess.cpp	2021-10-25 15:37:16 UTC (rev 284786)
@@ -498,6 +498,11 @@
 }
 #endif
 
+void GPUProcess::webProcessConnectionCountForTesting(CompletionHandler<void(uint64_t)>&& completionHandler)
+{
+    completionHandler(GPUConnectionToWebProcess::objectCountForTesting());
+}
+
 } // namespace WebKit
 
 #endif // ENABLE(GPU_PROCESS)

Modified: trunk/Source/WebKit/GPUProcess/GPUProcess.h (284785 => 284786)


--- trunk/Source/WebKit/GPUProcess/GPUProcess.h	2021-10-25 15:26:54 UTC (rev 284785)
+++ trunk/Source/WebKit/GPUProcess/GPUProcess.h	2021-10-25 15:37:16 UTC (rev 284786)
@@ -100,6 +100,8 @@
 
     const String& applicationVisibleName() const { return m_applicationVisibleName; }
 
+    void webProcessConnectionCountForTesting(CompletionHandler<void(uint64_t)>&&);
+
 private:
     void lowMemoryHandler(Critical, Synchronous);
 

Modified: trunk/Source/WebKit/GPUProcess/GPUProcess.messages.in (284785 => 284786)


--- trunk/Source/WebKit/GPUProcess/GPUProcess.messages.in	2021-10-25 15:26:54 UTC (rev 284785)
+++ trunk/Source/WebKit/GPUProcess/GPUProcess.messages.in	2021-10-25 15:37:16 UTC (rev 284786)
@@ -68,6 +68,8 @@
 #if ENABLE(CFPREFS_DIRECT_MODE)
     NotifyPreferencesChanged(String domain, String key, std::optional<String> encodedValue)
 #endif
+
+    WebProcessConnectionCountForTesting() -> (uint64_t count) Async
 }
 
 #endif // ENABLE(GPU_PROCESS)

Modified: trunk/Source/WebKit/GPUProcess/graphics/RemoteDisplayListRecorder.cpp (284785 => 284786)


--- trunk/Source/WebKit/GPUProcess/graphics/RemoteDisplayListRecorder.cpp	2021-10-25 15:26:54 UTC (rev 284785)
+++ trunk/Source/WebKit/GPUProcess/graphics/RemoteDisplayListRecorder.cpp	2021-10-25 15:37:16 UTC (rev 284786)
@@ -37,7 +37,7 @@
     : m_imageBuffer(imageBuffer)
     , m_imageBufferIdentifier(imageBufferIdentifier)
     , m_webProcessIdentifier(webProcessIdentifier)
-    , m_renderingBackend(renderingBackend)
+    , m_renderingBackend(&renderingBackend)
 {
 }
 
@@ -53,18 +53,13 @@
 
 void RemoteDisplayListRecorder::startListeningForIPC()
 {
-    ASSERT(!m_isListeningForIPC);
-    m_isListeningForIPC = true;
     m_renderingBackend->streamConnection().startReceivingMessages(*this, Messages::RemoteDisplayListRecorder::messageReceiverName(), m_imageBufferIdentifier.object().toUInt64());
 }
 
 void RemoteDisplayListRecorder::stopListeningForIPC()
 {
-    if (!m_isListeningForIPC)
-        return;
-
-    m_renderingBackend->streamConnection().stopReceivingMessages(Messages::RemoteDisplayListRecorder::messageReceiverName(), m_imageBufferIdentifier.object().toUInt64());
-    m_isListeningForIPC = false;
+    if (auto renderingBackend = std::exchange(m_renderingBackend, { }))
+        renderingBackend->streamConnection().stopReceivingMessages(Messages::RemoteDisplayListRecorder::messageReceiverName(), m_imageBufferIdentifier.object().toUInt64());
 }
 
 void RemoteDisplayListRecorder::save()
@@ -426,7 +421,7 @@
 
 void RemoteDisplayListRecorder::paintFrameForMedia(MediaPlayerIdentifier identifier, const FloatRect& destination)
 {
-    m_renderingBackend->performWithMediaPlayerOnMainThread(identifier, [imageBuffer = m_imageBuffer.copyRef(), destination](MediaPlayer& player) {
+    m_renderingBackend->performWithMediaPlayerOnMainThread(identifier, [imageBuffer = RefPtr { m_imageBuffer.get() }, destination](MediaPlayer& player) {
         // It is currently not safe to call paintFrameForMedia() off the main thread.
         imageBuffer->context().paintFrameForMedia(player, destination);
     });

Modified: trunk/Source/WebKit/GPUProcess/graphics/RemoteDisplayListRecorder.h (284785 => 284786)


--- trunk/Source/WebKit/GPUProcess/graphics/RemoteDisplayListRecorder.h	2021-10-25 15:26:54 UTC (rev 284785)
+++ trunk/Source/WebKit/GPUProcess/graphics/RemoteDisplayListRecorder.h	2021-10-25 15:37:16 UTC (rev 284786)
@@ -149,12 +149,11 @@
     void startListeningForIPC();
     void didReceiveStreamMessage(IPC::StreamServerConnectionBase&, IPC::Decoder&) final;
 
-    Ref<WebCore::ImageBuffer> m_imageBuffer;
+    WeakPtr<WebCore::ImageBuffer> m_imageBuffer;
     QualifiedRenderingResourceIdentifier m_imageBufferIdentifier;
     WebCore::ProcessIdentifier m_webProcessIdentifier;
-    Ref<RemoteRenderingBackend> m_renderingBackend;
+    RefPtr<RemoteRenderingBackend> m_renderingBackend;
     RefPtr<WebCore::ImageBuffer> m_maskImageBuffer;
-    bool m_isListeningForIPC { false };
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.cpp (284785 => 284786)


--- trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.cpp	2021-10-25 15:26:54 UTC (rev 284785)
+++ trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.cpp	2021-10-25 15:37:16 UTC (rev 284786)
@@ -108,6 +108,11 @@
 void RemoteRenderingBackend::stopListeningForIPC()
 {
     ASSERT(RunLoop::isMain());
+    // Make sure we destroy the ResourceCache on the WorkQueue since it gets populated on the WorkQueue.
+    // Make sure rendering resource request is released after destroying the cache.
+    m_workQueue->dispatch([renderingResourcesRequest = WTFMove(m_renderingResourcesRequest), remoteResourceCache = WTFMove(m_remoteResourceCache)] { });
+    m_workQueue->stopAndWaitForCompletion();
+
     m_streamConnection->stopReceivingMessages(Messages::RemoteRenderingBackend::messageReceiverName(), m_renderingBackendIdentifier.toUInt64());
     m_streamConnection->stopReceivingMessages(Messages::RemoteDisplayListRecorder::messageReceiverName());
 
@@ -117,11 +122,6 @@
         for (auto& remoteContext : std::exchange(m_remoteDisplayLists, { }))
             remoteContext.value->stopListeningForIPC();
     }
-
-    // Make sure we destroy the ResourceCache on the WorkQueue since it gets populated on the WorkQueue.
-    // Make sure rendering resource request is released after destroying the cache.
-    m_workQueue->dispatch([renderingResourcesRequest = WTFMove(m_renderingResourcesRequest), remoteResourceCache = WTFMove(m_remoteResourceCache)] { });
-    m_workQueue->stopAndWaitForCompletion();
 }
 
 void RemoteRenderingBackend::dispatch(Function<void()>&& task)

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h (284785 => 284786)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h	2021-10-25 15:26:54 UTC (rev 284785)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h	2021-10-25 15:37:16 UTC (rev 284786)
@@ -114,6 +114,7 @@
 - (void)_clearAppPrivacyReportTestingData:(void(^)(void))completionHandler;
 
 - (void)_createMediaSessionCoordinatorForTesting:(id <_WKMediaSessionCoordinator>)privateCoordinator completionHandler:(void(^)(BOOL))completionHandler;
+- (void)_gpuToWebProcessConnectionCountForTesting:(void(^)(NSUInteger))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 
 @end
 

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewTesting.mm (284785 => 284786)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewTesting.mm	2021-10-25 15:26:54 UTC (rev 284785)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewTesting.mm	2021-10-25 15:37:16 UTC (rev 284786)
@@ -27,6 +27,7 @@
 #import "WKWebViewPrivateForTesting.h"
 
 #import "AudioSessionRoutingArbitratorProxy.h"
+#import "GPUProcessProxy.h"
 #import "MediaSessionCoordinatorProxyPrivate.h"
 #import "PlaybackSessionManagerProxy.h"
 #import "UserMediaProcessManager.h"
@@ -423,6 +424,19 @@
     });
 }
 
+- (void)_gpuToWebProcessConnectionCountForTesting:(void(^)(NSUInteger))completionHandler
+{
+    RefPtr gpuProcess = _page->process().processPool().gpuProcess();
+    if (!gpuProcess) {
+        completionHandler(0);
+        return;
+    }
+
+    gpuProcess->webProcessConnectionCountForTesting([completionHandler = makeBlockPtr(completionHandler)](uint64_t count) {
+        completionHandler(count);
+    });
+}
+
 - (void)_createMediaSessionCoordinatorForTesting:(id <_WKMediaSessionCoordinator>)privateCoordinator completionHandler:(void(^)(BOOL))completionHandler
 {
 #if ENABLE(MEDIA_SESSION_COORDINATOR)

Modified: trunk/Source/WebKit/UIProcess/GPU/GPUProcessProxy.cpp (284785 => 284786)


--- trunk/Source/WebKit/UIProcess/GPU/GPUProcessProxy.cpp	2021-10-25 15:26:54 UTC (rev 284785)
+++ trunk/Source/WebKit/UIProcess/GPU/GPUProcessProxy.cpp	2021-10-25 15:37:16 UTC (rev 284786)
@@ -399,6 +399,11 @@
     processIsReadyToExit();
 }
 
+void GPUProcessProxy::webProcessConnectionCountForTesting(CompletionHandler<void(uint64_t)>&& completionHandler)
+{
+    sendWithAsyncReply(Messages::GPUProcess::WebProcessConnectionCountForTesting(), WTFMove(completionHandler));
+}
+
 void GPUProcessProxy::didClose(IPC::Connection&)
 {
     RELEASE_LOG_ERROR(Process, "%p - GPUProcessProxy::didClose:", this);

Modified: trunk/Source/WebKit/UIProcess/GPU/GPUProcessProxy.h (284785 => 284786)


--- trunk/Source/WebKit/UIProcess/GPU/GPUProcessProxy.h	2021-10-25 15:26:54 UTC (rev 284785)
+++ trunk/Source/WebKit/UIProcess/GPU/GPUProcessProxy.h	2021-10-25 15:37:16 UTC (rev 284786)
@@ -94,6 +94,7 @@
     void updatePreferences();
 
     void terminateForTesting();
+    void webProcessConnectionCountForTesting(CompletionHandler<void(uint64_t)>&&);
 
 private:
     explicit GPUProcessProxy();

Modified: trunk/Tools/ChangeLog (284785 => 284786)


--- trunk/Tools/ChangeLog	2021-10-25 15:26:54 UTC (rev 284785)
+++ trunk/Tools/ChangeLog	2021-10-25 15:37:16 UTC (rev 284786)
@@ -1,3 +1,21 @@
+2021-10-25  Wenson Hsieh  <[email protected]>
+
+        REGRESSION (r284079): Audio continues playing on hulu.com in private browsing mode after closing the tab
+        https://bugs.webkit.org/show_bug.cgi?id=232113
+        rdar://84399283
+
+        Reviewed by Chris Dumez.
+
+        Add a new API test to verify that the GPU to web prcoess connection isn't leaked in the GPU process. See WebKit
+        ChangeLog for more details.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm:
+        * TestWebKitAPI/Tests/WebKitCocoa/canvas-image-data.html: Added.
+        * TestWebKitAPI/cocoa/TestWKWebView.h:
+        * TestWebKitAPI/cocoa/TestWKWebView.mm:
+        (-[WKWebView gpuToWebProcessConnectionCount]):
+
 2021-10-25  Simon Fraser  <[email protected]>
 
         webkitpy: have diff_image() return a ImageDiffResult

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (284785 => 284786)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2021-10-25 15:26:54 UTC (rev 284785)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2021-10-25 15:37:16 UTC (rev 284786)
@@ -1295,6 +1295,7 @@
 		F4E0A2B42122402B00AF7C7F /* image-and-file-upload.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4E0A2B321223F2D00AF7C7F /* image-and-file-upload.html */; };
 		F4E0A2B82122847400AF7C7F /* TestFilePromiseReceiver.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4E0A2B72122847400AF7C7F /* TestFilePromiseReceiver.mm */; };
 		F4E3D80820F70BB9007B58C5 /* significant-text-milestone-article.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4E3D80720F708E4007B58C5 /* significant-text-milestone-article.html */; };
+		F4E7A66327222CA900E74D36 /* canvas-image-data.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4E7A66227222BB100E74D36 /* canvas-image-data.html */; };
 		F4EB4E912328AC3000574DAB /* NSItemProviderAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4EB4E902328AC3000574DAB /* NSItemProviderAdditions.mm */; };
 		F4EC8094260D30540010311D /* simple-image-overlay.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4EC8093260D2E620010311D /* simple-image-overlay.html */; };
 		F4F137921D9B683E002BEC57 /* large-video-test-now-playing.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4F137911D9B6832002BEC57 /* large-video-test-now-playing.html */; };
@@ -1444,6 +1445,7 @@
 				2DE71B001D49C3ED00904094 /* blinking-div.html in Copy Resources */,
 				7C486BA11AA12567003F6F9B /* bundle-file.html in Copy Resources */,
 				26DF5A6315A2A27E003689C2 /* CancelLoadFromResourceLoadDelegate.html in Copy Resources */,
+				F4E7A66327222CA900E74D36 /* canvas-image-data.html in Copy Resources */,
 				2EFF06C51D8867760004BB30 /* change-video-source-on-click.html in Copy Resources */,
 				2EFF06C71D886A580004BB30 /* change-video-source-on-end.html in Copy Resources */,
 				9BD4239C1E04C01C00200395 /* chinese-character-with-image.html in Copy Resources */,
@@ -3187,6 +3189,7 @@
 		F4E0A2B62122847400AF7C7F /* TestFilePromiseReceiver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestFilePromiseReceiver.h; sourceTree = "<group>"; };
 		F4E0A2B72122847400AF7C7F /* TestFilePromiseReceiver.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = TestFilePromiseReceiver.mm; sourceTree = "<group>"; };
 		F4E3D80720F708E4007B58C5 /* significant-text-milestone-article.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "significant-text-milestone-article.html"; sourceTree = "<group>"; };
+		F4E7A66227222BB100E74D36 /* canvas-image-data.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "canvas-image-data.html"; sourceTree = "<group>"; };
 		F4EB4E8F2328AC3000574DAB /* NSItemProviderAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NSItemProviderAdditions.h; path = cocoa/NSItemProviderAdditions.h; sourceTree = SOURCE_ROOT; };
 		F4EB4E902328AC3000574DAB /* NSItemProviderAdditions.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = NSItemProviderAdditions.mm; path = cocoa/NSItemProviderAdditions.mm; sourceTree = SOURCE_ROOT; };
 		F4EC8093260D2E620010311D /* simple-image-overlay.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "simple-image-overlay.html"; sourceTree = "<group>"; };
@@ -4050,6 +4053,7 @@
 				F41AB9971EF4692C0083FA08 /* background-image-link-and-input.html */,
 				464C764C230DF83200AFB020 /* BadServiceWorkerRegistrations-4.sqlite3 */,
 				2DE71AFF1D49C2F000904094 /* blinking-div.html */,
+				F4E7A66227222BB100E74D36 /* canvas-image-data.html */,
 				2EFF06C41D8867700004BB30 /* change-video-source-on-click.html */,
 				2EFF06C61D886A560004BB30 /* change-video-source-on-end.html */,
 				839AA35E21A26ACD00980DD6 /* client-side-redirect.html */,

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm (284785 => 284786)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm	2021-10-25 15:26:54 UTC (rev 284785)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm	2021-10-25 15:37:16 UTC (rev 284786)
@@ -282,6 +282,21 @@
     EXPECT_EQ([configuration.get().processPool _gpuProcessIdentifier], 0);
 }
 
+TEST(GPUProcess, DoNotLeakConnectionAfterClosingWebPage)
+{
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    WKPreferencesSetBoolValueForKeyForTesting((__bridge WKPreferencesRef)[configuration preferences], true, WKStringCreateWithUTF8CString("UseGPUProcessForCanvasRenderingEnabled"));
+    WKPreferencesSetBoolValueForKeyForTesting((__bridge WKPreferencesRef)[configuration preferences], false, WKStringCreateWithUTF8CString("UseGPUProcessForDOMRenderingEnabled"));
+
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400) configuration:configuration.get()]);
+    [webView synchronouslyLoadTestPageNamed:@"canvas-image-data"];
+    EXPECT_EQ(1U, [webView gpuToWebProcessConnectionCount]);
+    [webView _close];
+
+    while ([webView gpuToWebProcessConnectionCount])
+        TestWebKitAPI::Util::sleep(0.1);
+}
+
 #if ENABLE(LEGACY_ENCRYPTED_MEDIA)
 TEST(GPUProcess, LegacyCDM)
 {

Added: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/canvas-image-data.html (0 => 284786)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/canvas-image-data.html	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/canvas-image-data.html	2021-10-25 15:37:16 UTC (rev 284786)
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+canvas {
+    width: 160px;
+    height: 160px;
+    display: block;
+}
+</style>
+</head>
+<body>
+<strong>Source</strong>
+<canvas id="source" width="320" height="320"></canvas>
+<strong>Destination</strong>
+<canvas id="destination" width="320" height="320"></canvas>
+<script>
+const sourceCanvas = document.getElementById("source");
+const sourceContext = sourceCanvas.getContext("2d");
+sourceContext.save();
+sourceContext.strokeStyle = "red";
+sourceContext.fillStyle = "rgba(200, 100, 100, 0.25)";
+sourceContext.lineWidth = 4;
+sourceContext.rect(40, 40, 240, 240);
+sourceContext.stroke();
+sourceContext.fill();
+sourceContext.restore();
+
+const imageData = sourceContext.getImageData(0, 0, 320, 320);
+const destinationCanvas = document.getElementById("destination");
+const destinationContext = destinationCanvas.getContext("2d");
+destinationContext.putImageData(imageData, 0, 0, 0, 0, 320, 320);
+</script>
+</body>
+</html>

Modified: trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h (284785 => 284786)


--- trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h	2021-10-25 15:26:54 UTC (rev 284785)
+++ trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h	2021-10-25 15:37:16 UTC (rev 284786)
@@ -53,6 +53,7 @@
 @property (nonatomic, readonly) UIView <UITextInputPrivate, UITextInputInternal, UITextInputMultiDocument, UIWKInteractionViewProtocol, UITextInputTokenizer> *textInputContentView;
 - (NSArray<_WKTextInputContext *> *)synchronouslyRequestTextInputContextsInRect:(CGRect)rect;
 #endif
+@property (nonatomic, readonly) NSUInteger gpuToWebProcessConnectionCount;
 @property (nonatomic, readonly) NSString *contentsAsString;
 @property (nonatomic, readonly) NSArray<NSString *> *tagsInBody;
 - (void)loadTestPageNamed:(NSString *)pageName;

Modified: trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm (284785 => 284786)


--- trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm	2021-10-25 15:26:54 UTC (rev 284785)
+++ trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm	2021-10-25 15:37:16 UTC (rev 284786)
@@ -154,6 +154,18 @@
 
 #endif // PLATFORM(IOS_FAMILY)
 
+- (NSUInteger)gpuToWebProcessConnectionCount
+{
+    __block bool done = false;
+    __block NSUInteger count = 0;
+    [self _gpuToWebProcessConnectionCountForTesting:^(NSUInteger result) {
+        done = true;
+        count = result;
+    }];
+    TestWebKitAPI::Util::run(&done);
+    return count;
+}
+
 - (NSString *)contentsAsString
 {
     __block bool done = false;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to