Index: base/message_pump_win.cc |
diff --git a/base/message_pump_win.cc b/base/message_pump_win.cc |
index 9484b29e67c5cc00bd98e92e18a34e4f10e43c6b..72657dc51710ed605de7ece4452a9a9d763b6e27 100644 |
--- a/base/message_pump_win.cc |
+++ b/base/message_pump_win.cc |
@@ -8,11 +8,20 @@ |
#include "base/message_loop.h" |
#include "base/metrics/histogram.h" |
+#include "base/process_util.h" |
+#include "base/stringprintf.h" |
#include "base/win/wrapped_window_proc.h" |
+namespace { |
+ |
+// The ID of the timer used by the UI message pump. |
+const int kMessagePumpTimerId = 0; |
+ |
+} // namespace |
+ |
namespace base { |
-static const wchar_t kWndClass[] = L"Chrome_MessagePumpWindow"; |
+static const wchar_t kWndClassFormat[] = L"Chrome_MessagePumpWindow%p"; |
// Message sent to get an additional time slice for pumping (processing) another |
// task (a series of such messages creates a continuous task pump). |
@@ -82,13 +91,19 @@ int MessagePumpWin::GetCurrentDelay() const { |
//----------------------------------------------------------------------------- |
// MessagePumpForUI public: |
-MessagePumpForUI::MessagePumpForUI() { |
+MessagePumpForUI::MessagePumpForUI() |
+ : atom_(0), |
+ instance_(NULL), |
+ message_hwnd_(NULL) { |
InitMessageWnd(); |
} |
MessagePumpForUI::~MessagePumpForUI() { |
- DestroyWindow(message_hwnd_); |
- UnregisterClass(kWndClass, GetModuleHandle(NULL)); |
+ if (message_hwnd_ != NULL) |
+ DestroyWindow(message_hwnd_); |
+ |
+ if (atom_ != 0) |
+ UnregisterClass(reinterpret_cast<const char16*>(atom_), instance_); |
} |
void MessagePumpForUI::ScheduleWork() { |
@@ -96,7 +111,7 @@ void MessagePumpForUI::ScheduleWork() { |
return; // Someone else continued the pumping. |
// Make sure the MessagePump does some work for us. |
- PostMessage(message_hwnd_, kMsgHaveWork, reinterpret_cast<WPARAM>(this), 0); |
+ PostMessage(message_hwnd_, kMsgHaveWork, 0, 0); |
} |
void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { |
@@ -129,7 +144,7 @@ void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { |
// Create a WM_TIMER event that will wake us up to check for any pending |
// timers (in case we are running within a nested, external sub-pump). |
- SetTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this), delay_msec, NULL); |
+ SetTimer(message_hwnd_, kMessagePumpTimerId, delay_msec, NULL); |
} |
void MessagePumpForUI::PumpOutPendingPaintMessages() { |
@@ -162,13 +177,19 @@ void MessagePumpForUI::PumpOutPendingPaintMessages() { |
// static |
LRESULT CALLBACK MessagePumpForUI::WndProcThunk( |
HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { |
- switch (message) { |
- case kMsgHaveWork: |
- reinterpret_cast<MessagePumpForUI*>(wparam)->HandleWorkMessage(); |
- break; |
- case WM_TIMER: |
- reinterpret_cast<MessagePumpForUI*>(wparam)->HandleTimerMessage(); |
- break; |
+ // Retrieve |this| from the user data, associated with the window. |
+ MessagePumpForUI* self = reinterpret_cast<MessagePumpForUI*>( |
+ GetWindowLongPtr(hwnd, GWLP_USERDATA)); |
+ if (self != NULL) { |
jar (doing other things)
2012/05/15 21:39:42
Perchance we should not check the value of |self|,
alexeypa (please no reviews)
2012/05/15 22:10:27
|self| should never be NULL except for WM_CREATE m
|
+ switch (message) { |
+ case kMsgHaveWork: |
+ self->HandleWorkMessage(); |
+ break; |
+ case WM_TIMER: |
+ DCHECK(wparam == kMessagePumpTimerId); |
+ self->HandleTimerMessage(); |
+ break; |
+ } |
} |
return DefWindowProc(hwnd, message, wparam, lparam); |
} |
@@ -211,7 +232,7 @@ void MessagePumpForUI::DoRunLoop() { |
// don't want to disturb that timer if it is already in flight. However, |
// if we did do all remaining delayed work, then lets kill the WM_TIMER. |
if (more_work_is_plausible && delayed_work_time_.is_null()) |
- KillTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this)); |
+ KillTimer(message_hwnd_, kMessagePumpTimerId); |
if (state_->should_quit) |
break; |
@@ -230,18 +251,38 @@ void MessagePumpForUI::DoRunLoop() { |
} |
void MessagePumpForUI::InitMessageWnd() { |
- HINSTANCE hinst = GetModuleHandle(NULL); |
+ // Register a unique window class for each instance of UI pump. |
+ string16 class_name = base::StringPrintf(kWndClassFormat, this); |
+ WNDPROC window_procedure = &base::win::WrappedWindowProc<WndProcThunk>; |
- WNDCLASSEX wc = {0}; |
+ // RegisterClassEx uses a handle of the module containing the window procedure |
+ // to distinguish identically named classes registered in different modules. |
+ instance_ = GetModuleFromAddress(window_procedure); |
+ |
+ WNDCLASSEXW wc = {0}; |
wc.cbSize = sizeof(wc); |
- wc.lpfnWndProc = base::win::WrappedWindowProc<WndProcThunk>; |
- wc.hInstance = hinst; |
- wc.lpszClassName = kWndClass; |
- RegisterClassEx(&wc); |
+ wc.lpfnWndProc = window_procedure; |
+ wc.hInstance = instance_; |
+ wc.lpszClassName = class_name.c_str(); |
+ atom_ = RegisterClassEx(&wc); |
+ if (atom_ == 0) { |
+ DCHECK(atom_); |
alexeypa (please no reviews)
2012/05/15 22:10:27
We should also CHECK here.
|
+ return; |
+ } |
+ |
+ // Create the message-only window. |
+ message_hwnd_ = CreateWindow( |
+ reinterpret_cast<const char16*>(atom_), 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, |
+ instance_, 0); |
+ if (message_hwnd_ == NULL) { |
+ DCHECK(message_hwnd_); |
+ return; |
jar (doing other things)
2012/05/15 21:39:42
These return on error condition appear to mask a s
alexeypa (please no reviews)
2012/05/15 22:10:27
Those DCHECKs migrated from the previous version o
|
+ } |
- message_hwnd_ = |
- CreateWindow(kWndClass, 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, hinst, 0); |
- DCHECK(message_hwnd_); |
+ // Store |this| so that the window procedure could retrieve it later. |
+ SetWindowLongPtr(message_hwnd_, |
alexeypa (please no reviews)
2012/05/15 22:10:27
The return value of SetWindowLongPtr should be che
|
+ GWLP_USERDATA, |
+ reinterpret_cast<LONG_PTR>(this)); |
} |
void MessagePumpForUI::WaitForWork() { |
@@ -300,7 +341,7 @@ void MessagePumpForUI::HandleWorkMessage() { |
} |
void MessagePumpForUI::HandleTimerMessage() { |
- KillTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this)); |
+ KillTimer(message_hwnd_, kMessagePumpTimerId); |
// If we are being called outside of the context of Run, then don't do |
// anything. This could correspond to a MessageBox call or something of |