Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / ui / views / win / windows_session_change_observer.cc
blobc9db4599fe7ffe9bd3066ccf9be96c7598cb1ec0
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"
7 #include <wtsapi32.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"
23 namespace views {
25 class WindowsSessionChangeObserver::WtsRegistrationNotificationManager {
26 public:
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);
48 private:
49 friend struct DefaultSingletonTraits<WtsRegistrationNotificationManager>;
51 void OnWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
52 switch (message) {
53 case WM_WTSSESSION_CHANGE:
54 FOR_EACH_OBSERVER(WindowsSessionChangeObserver,
55 observer_list_,
56 OnSessionChange(wparam));
57 break;
58 case WM_DESTROY:
59 RemoveSingletonHwndObserver();
60 break;
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);
78 if (task_runner) {
79 task_runner->PostTask(FROM_HERE, wts_register);
80 } else {
81 wts_register.Run();
85 void RemoveSingletonHwndObserver() {
86 if (!singleton_hwnd_observer_)
87 return;
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
95 // can be running.
96 WTSUnRegisterSessionNotification(gfx::SingletonHwnd::GetInstance()->hwnd());
97 FOR_EACH_OBSERVER(WindowsSessionChangeObserver,
98 observer_list_,
99 ClearCallback());
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() {
116 ClearCallback();
119 void WindowsSessionChangeObserver::OnSessionChange(WPARAM wparam) {
120 callback_.Run(wparam);
123 void WindowsSessionChangeObserver::ClearCallback() {
124 if (!callback_.is_null()) {
125 callback_.Reset();
126 WtsRegistrationNotificationManager::GetInstance()->RemoveObserver(this);
130 } // namespace views