• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1diff --git base/message_loop/message_pump_win.cc base/message_loop/message_pump_win.cc
2index d1140d7945a2d..a3b894aa4f6b0 100644
3--- base/message_loop/message_pump_win.cc
4+++ base/message_loop/message_pump_win.cc
5@@ -2,6 +2,7 @@
6 // Use of this source code is governed by a BSD-style license that can be
7 // found in the LICENSE file.
8
9+#include "base/task/current_thread.h"
10 #include "base/message_loop/message_pump_win.h"
11
12 #include <algorithm>
13@@ -497,7 +498,17 @@ bool MessagePumpForUI::ProcessNextWindowsMessage() {
14                 ctx.event()->set_chrome_message_pump();
15             msg_pump_data->set_sent_messages_in_queue(more_work_is_plausible);
16           });
17-      has_msg = ::PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE) != FALSE;
18+
19+      // We should not process all window messages if we are in the context of an
20+      // OS modal loop, i.e. in the context of a windows API call like MessageBox.
21+      // This is to ensure that these messages are peeked out by the OS modal loop.
22+      if (CurrentThread::Get()->os_modal_loop()) {
23+        // We only peek out WM_PAINT and WM_TIMER here for reasons mentioned above.
24+        has_msg = PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE) ||
25+                  PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_REMOVE);
26+      } else {
27+        has_msg = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != FALSE;
28+      }
29     }
30   }
31   if (has_msg)
32diff --git base/task/current_thread.cc base/task/current_thread.cc
33index b7e9d215c2039..57816ea1c8b81 100644
34--- base/task/current_thread.cc
35+++ base/task/current_thread.cc
36@@ -49,6 +49,8 @@ void CurrentThread::AddDestructionObserver(
37
38 void CurrentThread::RemoveDestructionObserver(
39     DestructionObserver* destruction_observer) {
40+  if (!current_)
41+    return;
42   DCHECK(current_->IsBoundToCurrentThread());
43   current_->RemoveDestructionObserver(destruction_observer);
44 }
45diff --git base/task/current_thread.h base/task/current_thread.h
46index f82025cca1d17..6feb6ac241895 100644
47--- base/task/current_thread.h
48+++ base/task/current_thread.h
49@@ -130,6 +130,12 @@ class BASE_EXPORT CurrentThread {
50   // to run. There can only be one OnNextIdleCallback at a time.
51   void RegisterOnNextIdleCallback(OnceClosure on_next_idle_callback);
52
53+#if BUILDFLAG(IS_WIN)
54+  void set_os_modal_loop(bool os_modal_loop) { os_modal_loop_ = os_modal_loop; }
55+
56+  bool os_modal_loop() const { return os_modal_loop_; }
57+#endif  // OS_WIN
58+
59   // Enables nested task processing in scope of an upcoming native message loop.
60   // Some unwanted message loops may occur when using common controls or printer
61   // functions. Hence, nested task processing is disabled by default to avoid
62@@ -195,6 +201,13 @@ class BASE_EXPORT CurrentThread {
63   friend class web::WebTaskEnvironment;
64
65   sequence_manager::internal::SequenceManagerImpl* current_;
66+
67+#if BUILDFLAG(IS_WIN)
68+ private:
69+  // Should be set to true before calling Windows APIs like TrackPopupMenu, etc.
70+  // which enter a modal message loop.
71+  bool os_modal_loop_ = false;
72+#endif
73 };
74
75 #if !BUILDFLAG(IS_NACL)
76