1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/views/win/windows_session_change_observer.h"
8 #pragma comment(lib, "wtsapi32.lib")
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/callback.h"
13 #include "base/location.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/memory/singleton.h"
17 #include "base/observer_list.h"
18 #include "base/task_runner.h"
19 #include "ui/gfx/win/singleton_hwnd.h"
20 #include "ui/gfx/win/singleton_hwnd_observer.h"
21 #include "ui/views/views_delegate.h"
25 class WindowsSessionChangeObserver::WtsRegistrationNotificationManager
{
27 static WtsRegistrationNotificationManager
* GetInstance() {
28 return base::Singleton
<WtsRegistrationNotificationManager
>::get();
31 WtsRegistrationNotificationManager() {
32 AddSingletonHwndObserver();
35 ~WtsRegistrationNotificationManager() {
36 RemoveSingletonHwndObserver();
39 void AddObserver(WindowsSessionChangeObserver
* observer
) {
40 DCHECK(singleton_hwnd_observer_
);
41 observer_list_
.AddObserver(observer
);
44 void RemoveObserver(WindowsSessionChangeObserver
* observer
) {
45 observer_list_
.RemoveObserver(observer
);
49 friend struct base::DefaultSingletonTraits
<
50 WtsRegistrationNotificationManager
>;
52 void OnWndProc(HWND hwnd
, UINT message
, WPARAM wparam
, LPARAM lparam
) {
54 case WM_WTSSESSION_CHANGE
:
55 FOR_EACH_OBSERVER(WindowsSessionChangeObserver
,
57 OnSessionChange(wparam
));
60 RemoveSingletonHwndObserver();
65 void AddSingletonHwndObserver() {
66 DCHECK(!singleton_hwnd_observer_
);
67 singleton_hwnd_observer_
.reset(new gfx::SingletonHwndObserver(
68 base::Bind(&WtsRegistrationNotificationManager::OnWndProc
,
69 base::Unretained(this))));
70 scoped_refptr
<base::TaskRunner
> task_runner
;
71 if (ViewsDelegate::GetInstance()) {
72 task_runner
= ViewsDelegate::GetInstance()->GetBlockingPoolTaskRunner();
75 base::Closure wts_register
=
76 base::Bind(base::IgnoreResult(&WTSRegisterSessionNotification
),
77 gfx::SingletonHwnd::GetInstance()->hwnd(),
78 NOTIFY_FOR_THIS_SESSION
);
80 task_runner
->PostTask(FROM_HERE
, wts_register
);
86 void RemoveSingletonHwndObserver() {
87 if (!singleton_hwnd_observer_
)
90 singleton_hwnd_observer_
.reset(nullptr);
91 // There is no race condition between this code and the worker thread.
92 // RemoveSingletonHwndObserver is only called from two places:
93 // 1) Destruction due to Singleton Destruction.
94 // 2) WM_DESTROY fired by SingletonHwnd.
95 // Under both cases we are in shutdown, which means no other worker threads
97 WTSUnRegisterSessionNotification(gfx::SingletonHwnd::GetInstance()->hwnd());
98 FOR_EACH_OBSERVER(WindowsSessionChangeObserver
,
103 base::ObserverList
<WindowsSessionChangeObserver
, true> observer_list_
;
104 scoped_ptr
<gfx::SingletonHwndObserver
> singleton_hwnd_observer_
;
106 DISALLOW_COPY_AND_ASSIGN(WtsRegistrationNotificationManager
);
109 WindowsSessionChangeObserver::WindowsSessionChangeObserver(
110 const WtsCallback
& callback
)
111 : callback_(callback
) {
112 DCHECK(!callback_
.is_null());
113 WtsRegistrationNotificationManager::GetInstance()->AddObserver(this);
116 WindowsSessionChangeObserver::~WindowsSessionChangeObserver() {
120 void WindowsSessionChangeObserver::OnSessionChange(WPARAM wparam
) {
121 callback_
.Run(wparam
);
124 void WindowsSessionChangeObserver::ClearCallback() {
125 if (!callback_
.is_null()) {
127 WtsRegistrationNotificationManager::GetInstance()->RemoveObserver(this);