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 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 DefaultSingletonTraits
<WtsRegistrationNotificationManager
>;
51 void OnWndProc(HWND hwnd
, UINT message
, WPARAM wparam
, LPARAM lparam
) {
53 case WM_WTSSESSION_CHANGE
:
54 FOR_EACH_OBSERVER(WindowsSessionChangeObserver
,
56 OnSessionChange(wparam
));
59 RemoveSingletonHwndObserver();
64 void AddSingletonHwndObserver() {
65 DCHECK(!singleton_hwnd_observer_
);
66 singleton_hwnd_observer_
.reset(new gfx::SingletonHwndObserver(
67 base::Bind(&WtsRegistrationNotificationManager::OnWndProc
,
68 base::Unretained(this))));
69 scoped_refptr
<base::TaskRunner
> task_runner
;
70 if (ViewsDelegate::GetInstance()) {
71 task_runner
= ViewsDelegate::GetInstance()->GetBlockingPoolTaskRunner();
74 base::Closure wts_register
=
75 base::Bind(base::IgnoreResult(&WTSRegisterSessionNotification
),
76 gfx::SingletonHwnd::GetInstance()->hwnd(),
77 NOTIFY_FOR_THIS_SESSION
);
79 task_runner
->PostTask(FROM_HERE
, wts_register
);
85 void RemoveSingletonHwndObserver() {
86 if (!singleton_hwnd_observer_
)
89 singleton_hwnd_observer_
.reset(nullptr);
90 // There is no race condition between this code and the worker thread.
91 // RemoveSingletonHwndObserver is only called from two places:
92 // 1) Destruction due to Singleton Destruction.
93 // 2) WM_DESTROY fired by SingletonHwnd.
94 // Under both cases we are in shutdown, which means no other worker threads
96 WTSUnRegisterSessionNotification(gfx::SingletonHwnd::GetInstance()->hwnd());
97 FOR_EACH_OBSERVER(WindowsSessionChangeObserver
,
102 base::ObserverList
<WindowsSessionChangeObserver
, true> observer_list_
;
103 scoped_ptr
<gfx::SingletonHwndObserver
> singleton_hwnd_observer_
;
105 DISALLOW_COPY_AND_ASSIGN(WtsRegistrationNotificationManager
);
108 WindowsSessionChangeObserver::WindowsSessionChangeObserver(
109 const WtsCallback
& callback
)
110 : callback_(callback
) {
111 DCHECK(!callback_
.is_null());
112 WtsRegistrationNotificationManager::GetInstance()->AddObserver(this);
115 WindowsSessionChangeObserver::~WindowsSessionChangeObserver() {
119 void WindowsSessionChangeObserver::OnSessionChange(WPARAM wparam
) {
120 callback_
.Run(wparam
);
123 void WindowsSessionChangeObserver::ClearCallback() {
124 if (!callback_
.is_null()) {
126 WtsRegistrationNotificationManager::GetInstance()->RemoveObserver(this);