From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Calvin Watford Date: Wed, 5 Mar 2025 15:26:28 -0700 Subject: fix: multiple ScopedPumpMessagesInPrivateModes instances Context: When swapping `Menu.popup` to use `ui::ShowContextMenu`, we found that its use of `ScopedPumpMessagesInPrivateModes` may potentially be used multiple times simultaneously. This class was designed to work with only one global instance. This patch adds a global reference count to keep track of `ScopedPumpMessagesInPrivateModes` instances and gate its enable/disable behavior on this reference count. diff --git a/base/message_loop/message_pump_apple.mm b/base/message_loop/message_pump_apple.mm index 52ed68ac3150bdeef3c5032f3f5f7df3d5aaac51..1658aece3e8fbcef89944a849e311f7949a68de9 100644 --- a/base/message_loop/message_pump_apple.mm +++ b/base/message_loop/message_pump_apple.mm @@ -760,20 +760,29 @@ explicit OptionalAutoreleasePool(MessagePumpCFRunLoopBase* pump) { #else +static int g_private_mode_ref_count = 0; + ScopedPumpMessagesInPrivateModes::ScopedPumpMessagesInPrivateModes() { DCHECK(g_app_pump); - DCHECK_EQ(kNSApplicationModalSafeModeMask, g_app_pump->GetModeMask()); // Pumping events in private runloop modes is known to interact badly with // app modal windows like NSAlert. if (NSApp.modalWindow) { return; } - g_app_pump->SetModeMask(kAllModesMask); + + g_private_mode_ref_count += 1; + if (g_private_mode_ref_count == 1) { + g_app_pump->SetModeMask(kAllModesMask); + } } ScopedPumpMessagesInPrivateModes::~ScopedPumpMessagesInPrivateModes() { DCHECK(g_app_pump); - g_app_pump->SetModeMask(kNSApplicationModalSafeModeMask); + DCHECK(g_private_mode_ref_count > 0); + g_private_mode_ref_count -= 1; + if (g_private_mode_ref_count == 0) { + g_app_pump->SetModeMask(kNSApplicationModalSafeModeMask); + } } int ScopedPumpMessagesInPrivateModes::GetModeMaskForTest() {