tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 33eed4fe86589e1546697c114abff63260f56fce
parent 91b75d161ff7c2a7de6d2cc01cefdbc269e8fd01
Author: Markus Stange <mstange.moz@gmail.com>
Date:   Wed,  8 Oct 2025 23:07:54 +0000

Bug 1993321 - Ensure the parent endpoint for PNativeLayerRemote is bound before we send the child endpoint to the GPU process. r=bradwerth

Differential Revision: https://phabricator.services.mozilla.com/D268020

Diffstat:
Mwidget/cocoa/nsCocoaWindow.mm | 78+++++++++++++++++++++++++++++++++++-------------------------------------------
1 file changed, 35 insertions(+), 43 deletions(-)

diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm @@ -883,11 +883,6 @@ void nsCocoaWindow::CreateCompositor(int aWidth, int aHeight) { // Ensure we are on the parent process. MOZ_ASSERT(XRE_IsParentProcess()); - // We have some early exit cases. Create an exit scope so we call - // our superclass implemenation in all code paths. - auto completionScope = - MakeScopeExit([&] { nsBaseWidget::CreateCompositor(aWidth, aHeight); }); - // It's possible we might reach this before the GPU process has even // been started. That makes it hard to reason about the different // scenarios, which are: @@ -926,44 +921,41 @@ void nsCocoaWindow::CreateCompositor(int aWidth, int aHeight) { auto rv = PNativeLayerRemote::CreateEndpoints( mozilla::ipc::EndpointProcInfo::Current(), childProcessInfo, &parentEndpoint, &mChildEndpoint); - MOZ_ASSERT(parentEndpoint.IsValid()); - MOZ_ASSERT(mChildEndpoint.IsValid()); - - if (NS_SUCCEEDED(rv)) { - // Create our mNativeLayerRootRemoteMacParent. - mNativeLayerRootRemoteMacParent = - new NativeLayerRootRemoteMacParent(mNativeLayerRoot); - - // Prepare the paramters to call FinishCreateCompositor. - RefPtr<NativeLayerRootRemoteMacParent> nativeLayerRemoteParent( - mNativeLayerRootRemoteMacParent); - - // We want the rest to run on the compositor thread. - MOZ_ASSERT(CompositorThread()); - CompositorThread()->Dispatch(NewRunnableFunction( - "nsCocoaWindow::FinishCreateCompositor", - &nsCocoaWindow::FinishCreateCompositor, aWidth, aHeight, - std::move(parentEndpoint), nativeLayerRemoteParent)); - } -} - -/* static */ -void nsCocoaWindow::FinishCreateCompositor( - int aWidth, int aHeight, - mozilla::ipc::Endpoint<mozilla::layers::PNativeLayerRemoteParent>&& - aParentEndpoint, - RefPtr<NativeLayerRootRemoteMacParent> aNativeLayerRootRemoteMacParent) { - MOZ_ASSERT(aNativeLayerRootRemoteMacParent); - MOZ_ALWAYS_TRUE(aParentEndpoint.Bind(aNativeLayerRootRemoteMacParent)); - // If this Bind fails, there's not much we can do, except signal somehow - // that we want to retry with an in-process compositor. - - // If everything has gone well, the mChildEndpoint will be used in - // GetCompositorWidgetInitData, to send the endpoint to the compositor - // widget. Later, the render thread will bind a NativeLayerRemoteMacChild - // to the child side of the endpoint. Once that is done, the compositor - // widget child actor can send messages to our parent actor, and we can - // update the real mNativeLayerRoot with the GPU surfaces. + MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv)); + MOZ_RELEASE_ASSERT(parentEndpoint.IsValid()); + MOZ_RELEASE_ASSERT(mChildEndpoint.IsValid()); + + // Create our mNativeLayerRootRemoteMacParent. + mNativeLayerRootRemoteMacParent = + new NativeLayerRootRemoteMacParent(mNativeLayerRoot); + + // Bind the parent endpoint compositor thread. + MOZ_ASSERT(CompositorThread()); + RefPtr<NativeLayerRootRemoteMacParent> nativeLayerRemoteParent( + mNativeLayerRootRemoteMacParent); + Monitor monitor("nsCocoaWindow::CreateCompositor") MOZ_UNANNOTATED; + bool didBindParentEndpoint = false; + + CompositorThread()->Dispatch(NS_NewRunnableFunction( + "nsCocoaWindow::CreateCompositor bind endpoint", [&]() { + // Bind the endpoint. This has to happen before the child endpoint is + // sent to the GPU process. + MOZ_ALWAYS_TRUE(parentEndpoint.Bind(nativeLayerRemoteParent)); + MonitorAutoLock lock(monitor); + didBindParentEndpoint = true; + lock.Notify(); + })); + + // Block until the parent endpoint is bound, so that on the next call to + // GetCompositorWidgetInitData we are ready to forward the child endpoint + // to the GPU process. + MonitorAutoLock lock(monitor); + while (!didBindParentEndpoint) { + lock.Wait(); + } + + // Do the rest of the compositor setup. + nsBaseWidget::CreateCompositor(aWidth, aHeight); } void nsCocoaWindow::DestroyCompositor() {