diff --git base/message_loop/message_pump_win.cc base/message_loop/message_pump_win.cc index 908f0cdf45682781160b9937f015aa9af628b451..fe5a8000171bd3eecf12aab1b290e0c26cc25777 100644 --- base/message_loop/message_pump_win.cc +++ base/message_loop/message_pump_win.cc @@ -25,6 +25,7 @@ #include "base/message_loop/message_pump_wakeup_counter.h" #include "base/numerics/safe_conversions.h" #include "base/strings/string_number_conversions.h" +#include "base/task/current_thread.h" #include "base/task/task_features.h" #include "base/trace_event/interned_args_helper.h" #include "base/trace_event/typed_macros.h" @@ -590,7 +591,19 @@ bool MessagePumpForUI::ProcessNextWindowsMessage() { if (native_event_observer_) { native_event_observer_->WillRunNativeEvent(next_peek_message_event_id_); } - has_msg = ::PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE) != FALSE; + + // We should not process all window messages if we are in the context of + // an OS modal loop, i.e. in the context of a windows API call like + // MessageBox. This is to ensure that these messages are peeked out by the + // OS modal loop. + if (CurrentThread::Get()->os_modal_loop()) { + // We only peek out WM_PAINT and WM_TIMER here for reasons mentioned + // above. + has_msg = PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE) || + PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_REMOVE); + } else { + has_msg = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != FALSE; + } if (native_event_observer_) { native_event_observer_->DidRunNativeEvent( next_peek_message_event_id_++); diff --git base/task/current_thread.cc base/task/current_thread.cc index dd959f737c8c66d6370d45a392a90e9abbbe5f0f..d257d16cb1ba1787662c119270715d6f7da7dc38 100644 --- base/task/current_thread.cc +++ base/task/current_thread.cc @@ -51,6 +51,8 @@ void CurrentThread::AddDestructionObserver( void CurrentThread::RemoveDestructionObserver( DestructionObserver* destruction_observer) { + if (!current_) + return; DCHECK(current_->IsBoundToCurrentThread()); current_->RemoveDestructionObserver(destruction_observer); } diff --git base/task/current_thread.h base/task/current_thread.h index 2bf2f919fe5cba57049cb7e80a92603c8d4980b8..72bde82f6b62e3981029d7c9ca876c853b563298 100644 --- base/task/current_thread.h +++ base/task/current_thread.h @@ -160,6 +160,12 @@ class BASE_EXPORT CurrentThread { RegisterOnNextIdleCallbackPasskey, OnceClosure on_next_idle_callback); +#if BUILDFLAG(IS_WIN) + void set_os_modal_loop(bool os_modal_loop) { os_modal_loop_ = os_modal_loop; } + + bool os_modal_loop() const { return os_modal_loop_; } +#endif // OS_WIN + // Enables nested task processing in scope of an upcoming native message loop. // Some unwanted message loops may occur when using common controls or printer // functions. Hence, nested task processing is disabled by default to avoid @@ -233,6 +239,13 @@ class BASE_EXPORT CurrentThread { friend class web::WebTaskEnvironment; raw_ptr current_; + +#if BUILDFLAG(IS_WIN) + private: + // Should be set to true before calling Windows APIs like TrackPopupMenu, etc. + // which enter a modal message loop. + bool os_modal_loop_ = false; +#endif }; // UI extension of CurrentThread.