OLD | NEW |
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <windows.h> | 5 #include <windows.h> |
6 #include <sddl.h> | 6 #include <sddl.h> |
7 | 7 |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/at_exit.h" | 10 #include "base/at_exit.h" |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
50 { 0x80, 0xc1, 0x52, 0x7f, 0xea, 0x23, 0xe3, 0xa7 } }; | 50 { 0x80, 0xc1, 0x52, 0x7f, 0xea, 0x23, 0xe3, 0xa7 } }; |
51 | 51 |
52 // The amount of time we wait around for a WM_ENDSESSION or a process exit. | 52 // The amount of time we wait around for a WM_ENDSESSION or a process exit. |
53 const int kDelayTimeSeconds = 30; | 53 const int kDelayTimeSeconds = 30; |
54 | 54 |
55 // Takes care of monitoring a browser. This class watches for a browser's exit | 55 // Takes care of monitoring a browser. This class watches for a browser's exit |
56 // code, as well as listening for WM_ENDSESSION messages. Events are recorded in | 56 // code, as well as listening for WM_ENDSESSION messages. Events are recorded in |
57 // an exit funnel, for reporting the next time Chrome runs. | 57 // an exit funnel, for reporting the next time Chrome runs. |
58 class BrowserMonitor { | 58 class BrowserMonitor { |
59 public: | 59 public: |
60 BrowserMonitor(base::RunLoop* run_loop, const base::char16* registry_path); | 60 BrowserMonitor(base::StringPiece16 registry_path, base::RunLoop* run_loop); |
61 ~BrowserMonitor(); | 61 ~BrowserMonitor(); |
62 | 62 |
63 // Initiates the asynchronous monitoring process, returns true on success. | 63 // Initiates the asynchronous monitoring process, returns true on success. |
64 // |on_initialized_event| will be signaled immediately before blocking on the | 64 // |on_initialized_event| will be signaled immediately before blocking on the |
65 // exit of |process|. | 65 // exit of |process|. |
66 bool StartWatching(const base::char16* registry_path, | 66 bool StartWatching(base::Process process, |
67 base::Process process, | |
68 base::win::ScopedHandle on_initialized_event); | 67 base::win::ScopedHandle on_initialized_event); |
69 | 68 |
70 private: | 69 private: |
71 // Called from EndSessionWatcherWindow on a end session messages. | 70 // Called from EndSessionWatcherWindow on a end session messages. |
72 void OnEndSessionMessage(UINT message, LPARAM lparam); | 71 void OnEndSessionMessage(UINT message, LPARAM lparam); |
73 | 72 |
74 // Blocking function that runs on |background_thread_|. Signals | 73 // Blocking function that runs on |background_thread_|. Signals |
75 // |on_initialized_event| before waiting for the browser process to exit. | 74 // |on_initialized_event| before waiting for the browser process to exit. |
76 void Watch(base::win::ScopedHandle on_initialized_event); | 75 void Watch(base::win::ScopedHandle on_initialized_event); |
77 | 76 |
(...skipping 10 matching lines...) Expand all Loading... |
88 // when WM_ENDSESSION occurs before browser exit. | 87 // when WM_ENDSESSION occurs before browser exit. |
89 base::WaitableEvent browser_exited_; | 88 base::WaitableEvent browser_exited_; |
90 | 89 |
91 // The run loop for the main thread and its task runner. | 90 // The run loop for the main thread and its task runner. |
92 base::RunLoop* run_loop_; | 91 base::RunLoop* run_loop_; |
93 scoped_refptr<base::SequencedTaskRunner> main_thread_; | 92 scoped_refptr<base::SequencedTaskRunner> main_thread_; |
94 | 93 |
95 DISALLOW_COPY_AND_ASSIGN(BrowserMonitor); | 94 DISALLOW_COPY_AND_ASSIGN(BrowserMonitor); |
96 }; | 95 }; |
97 | 96 |
98 BrowserMonitor::BrowserMonitor(base::RunLoop* run_loop, | 97 BrowserMonitor::BrowserMonitor(base::StringPiece16 registry_path, |
99 const base::char16* registry_path) | 98 base::RunLoop* run_loop) |
100 : exit_code_watcher_(registry_path), | 99 : exit_code_watcher_(registry_path), |
101 end_session_watcher_window_( | 100 end_session_watcher_window_( |
102 base::Bind(&BrowserMonitor::OnEndSessionMessage, | 101 base::Bind(&BrowserMonitor::OnEndSessionMessage, |
103 base::Unretained(this))), | 102 base::Unretained(this))), |
104 background_thread_("BrowserWatcherThread"), | 103 background_thread_("BrowserWatcherThread"), |
105 browser_exited_(true, false), // manual reset, initially non-signalled. | 104 browser_exited_(true, false), // manual reset, initially non-signalled. |
106 run_loop_(run_loop), | 105 run_loop_(run_loop), |
107 main_thread_(base::ThreadTaskRunnerHandle::Get()) { | 106 main_thread_(base::ThreadTaskRunnerHandle::Get()) {} |
108 } | |
109 | 107 |
110 BrowserMonitor::~BrowserMonitor() { | 108 BrowserMonitor::~BrowserMonitor() { |
111 } | 109 } |
112 | 110 |
113 bool BrowserMonitor::StartWatching( | 111 bool BrowserMonitor::StartWatching( |
114 const base::char16* registry_path, | |
115 base::Process process, | 112 base::Process process, |
116 base::win::ScopedHandle on_initialized_event) { | 113 base::win::ScopedHandle on_initialized_event) { |
117 if (!exit_code_watcher_.Initialize(std::move(process))) | 114 if (!exit_code_watcher_.Initialize(std::move(process))) |
118 return false; | 115 return false; |
119 | 116 |
120 if (!background_thread_.StartWithOptions( | 117 if (!background_thread_.StartWithOptions( |
121 base::Thread::Options(base::MessageLoop::TYPE_IO, 0))) { | 118 base::Thread::Options(base::MessageLoop::TYPE_IO, 0))) { |
122 return false; | 119 return false; |
123 } | 120 } |
124 | 121 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 // The browser exited abnormally, wait around for a little bit to see | 173 // The browser exited abnormally, wait around for a little bit to see |
177 // whether this instance will get a logoff message. | 174 // whether this instance will get a logoff message. |
178 main_thread_->PostDelayedTask( | 175 main_thread_->PostDelayedTask( |
179 FROM_HERE, | 176 FROM_HERE, |
180 run_loop_->QuitClosure(), | 177 run_loop_->QuitClosure(), |
181 base::TimeDelta::FromSeconds(kDelayTimeSeconds)); | 178 base::TimeDelta::FromSeconds(kDelayTimeSeconds)); |
182 } | 179 } |
183 } | 180 } |
184 | 181 |
185 void OnWindowEvent( | 182 void OnWindowEvent( |
186 const base::string16& registry_path, | |
187 base::Process process, | 183 base::Process process, |
188 const base::Callback<void(const base::Process&)>& on_hung_callback, | 184 const base::Callback<void(const base::Process&)>& on_hung_callback, |
189 browser_watcher::WindowHangMonitor::WindowEvent window_event) { | 185 browser_watcher::WindowHangMonitor::WindowEvent window_event) { |
190 if (window_event == browser_watcher::WindowHangMonitor::WINDOW_HUNG && | 186 if (window_event == browser_watcher::WindowHangMonitor::WINDOW_HUNG && |
191 !on_hung_callback.is_null()) { | 187 !on_hung_callback.is_null()) { |
192 on_hung_callback.Run(process); | 188 on_hung_callback.Run(process); |
193 } | 189 } |
194 } | 190 } |
195 | 191 |
196 } // namespace | 192 } // namespace |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
233 channel_name, L"hung-process"); | 229 channel_name, L"hung-process"); |
234 } | 230 } |
235 #endif // BUILDFLAG(ENABLE_KASKO_HANG_REPORTS) | 231 #endif // BUILDFLAG(ENABLE_KASKO_HANG_REPORTS) |
236 #endif // BUILDFLAG(ENABLE_KASKO) | 232 #endif // BUILDFLAG(ENABLE_KASKO) |
237 | 233 |
238 // Run a UI message loop on the main thread. | 234 // Run a UI message loop on the main thread. |
239 base::MessageLoop msg_loop(base::MessageLoop::TYPE_UI); | 235 base::MessageLoop msg_loop(base::MessageLoop::TYPE_UI); |
240 msg_loop.set_thread_name("WatcherMainThread"); | 236 msg_loop.set_thread_name("WatcherMainThread"); |
241 | 237 |
242 base::RunLoop run_loop; | 238 base::RunLoop run_loop; |
243 BrowserMonitor monitor(&run_loop, registry_path); | 239 BrowserMonitor monitor(registry_path, &run_loop); |
244 if (!monitor.StartWatching(registry_path, process.Duplicate(), | 240 if (!monitor.StartWatching(process.Duplicate(), |
245 std::move(on_initialized_event))) { | 241 std::move(on_initialized_event))) { |
246 return 1; | 242 return 1; |
247 } | 243 } |
248 | 244 |
249 { | 245 { |
250 // Scoped to force |hang_monitor| destruction before Kasko is shut down. | 246 // Scoped to force |hang_monitor| destruction before Kasko is shut down. |
251 browser_watcher::WindowHangMonitor hang_monitor( | 247 browser_watcher::WindowHangMonitor hang_monitor( |
252 base::TimeDelta::FromSeconds(60), base::TimeDelta::FromSeconds(20), | 248 base::TimeDelta::FromSeconds(60), base::TimeDelta::FromSeconds(20), |
253 base::Bind(&OnWindowEvent, registry_path, | 249 base::Bind(&OnWindowEvent, base::Passed(process.Duplicate()), |
254 base::Passed(process.Duplicate()), on_hung_callback)); | 250 on_hung_callback)); |
255 hang_monitor.Initialize(process.Duplicate()); | 251 hang_monitor.Initialize(process.Duplicate()); |
256 | 252 |
257 run_loop.Run(); | 253 run_loop.Run(); |
258 } | 254 } |
259 | 255 |
260 #if BUILDFLAG(ENABLE_KASKO) | 256 #if BUILDFLAG(ENABLE_KASKO) |
261 if (launched_kasko) | 257 if (launched_kasko) |
262 ShutdownKaskoReporter(); | 258 ShutdownKaskoReporter(); |
263 #endif // BUILDFLAG(ENABLE_KASKO) | 259 #endif // BUILDFLAG(ENABLE_KASKO) |
264 | 260 |
265 // Wind logging down. | 261 // Wind logging down. |
266 logging::LogEventProvider::Uninitialize(); | 262 logging::LogEventProvider::Uninitialize(); |
267 | 263 |
268 return 0; | 264 return 0; |
269 } | 265 } |
270 | 266 |
271 static_assert( | 267 static_assert( |
272 std::is_same<decltype(&WatcherMain), ChromeWatcherMainFunction>::value, | 268 std::is_same<decltype(&WatcherMain), ChromeWatcherMainFunction>::value, |
273 "WatcherMain() has wrong type"); | 269 "WatcherMain() has wrong type"); |
OLD | NEW |