| 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 "base/at_exit.h" | 8 #include "base/at_exit.h" |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 { 0x80, 0xc1, 0x52, 0x7f, 0xea, 0x23, 0xe3, 0xa7 } }; | 53 { 0x80, 0xc1, 0x52, 0x7f, 0xea, 0x23, 0xe3, 0xa7 } }; |
| 54 | 54 |
| 55 // The amount of time we wait around for a WM_ENDSESSION or a process exit. | 55 // The amount of time we wait around for a WM_ENDSESSION or a process exit. |
| 56 const int kDelayTimeSeconds = 30; | 56 const int kDelayTimeSeconds = 30; |
| 57 | 57 |
| 58 // Takes care of monitoring a browser. This class watches for a browser's exit | 58 // Takes care of monitoring a browser. This class watches for a browser's exit |
| 59 // code, as well as listening for WM_ENDSESSION messages. Events are recorded in | 59 // code, as well as listening for WM_ENDSESSION messages. Events are recorded in |
| 60 // an exit funnel, for reporting the next time Chrome runs. | 60 // an exit funnel, for reporting the next time Chrome runs. |
| 61 class BrowserMonitor { | 61 class BrowserMonitor { |
| 62 public: | 62 public: |
| 63 BrowserMonitor(base::RunLoop* run_loop, const base::char16* registry_path); | 63 BrowserMonitor(base::StringPiece16 registry_path, base::RunLoop* run_loop); |
| 64 ~BrowserMonitor(); | 64 ~BrowserMonitor(); |
| 65 | 65 |
| 66 // Initiates the asynchronous monitoring process, returns true on success. | 66 // Initiates the asynchronous monitoring process, returns true on success. |
| 67 // |on_initialized_event| will be signaled immediately before blocking on the | 67 // |on_initialized_event| will be signaled immediately before blocking on the |
| 68 // exit of |process|. | 68 // exit of |process|. |
| 69 bool StartWatching(const base::char16* registry_path, | 69 bool StartWatching(base::Process process, |
| 70 base::Process process, | |
| 71 base::win::ScopedHandle on_initialized_event); | 70 base::win::ScopedHandle on_initialized_event); |
| 72 | 71 |
| 73 private: | 72 private: |
| 74 // Called from EndSessionWatcherWindow on a end session messages. | 73 // Called from EndSessionWatcherWindow on a end session messages. |
| 75 void OnEndSessionMessage(UINT message, LPARAM lparam); | 74 void OnEndSessionMessage(UINT message, LPARAM lparam); |
| 76 | 75 |
| 77 // Blocking function that runs on |background_thread_|. Signals | 76 // Blocking function that runs on |background_thread_|. Signals |
| 78 // |on_initialized_event| before waiting for the browser process to exit. | 77 // |on_initialized_event| before waiting for the browser process to exit. |
| 79 void Watch(base::win::ScopedHandle on_initialized_event); | 78 void Watch(base::win::ScopedHandle on_initialized_event); |
| 80 | 79 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 91 // when WM_ENDSESSION occurs before browser exit. | 90 // when WM_ENDSESSION occurs before browser exit. |
| 92 base::WaitableEvent browser_exited_; | 91 base::WaitableEvent browser_exited_; |
| 93 | 92 |
| 94 // The run loop for the main thread and its task runner. | 93 // The run loop for the main thread and its task runner. |
| 95 base::RunLoop* run_loop_; | 94 base::RunLoop* run_loop_; |
| 96 scoped_refptr<base::SequencedTaskRunner> main_thread_; | 95 scoped_refptr<base::SequencedTaskRunner> main_thread_; |
| 97 | 96 |
| 98 DISALLOW_COPY_AND_ASSIGN(BrowserMonitor); | 97 DISALLOW_COPY_AND_ASSIGN(BrowserMonitor); |
| 99 }; | 98 }; |
| 100 | 99 |
| 101 BrowserMonitor::BrowserMonitor(base::RunLoop* run_loop, | 100 BrowserMonitor::BrowserMonitor(base::StringPiece16 registry_path, |
| 102 const base::char16* registry_path) | 101 base::RunLoop* run_loop) |
| 103 : exit_code_watcher_(registry_path), | 102 : exit_code_watcher_(registry_path), |
| 104 end_session_watcher_window_( | 103 end_session_watcher_window_( |
| 105 base::Bind(&BrowserMonitor::OnEndSessionMessage, | 104 base::Bind(&BrowserMonitor::OnEndSessionMessage, |
| 106 base::Unretained(this))), | 105 base::Unretained(this))), |
| 107 background_thread_("BrowserWatcherThread"), | 106 background_thread_("BrowserWatcherThread"), |
| 108 browser_exited_(true, false), // manual reset, initially non-signalled. | 107 browser_exited_(true, false), // manual reset, initially non-signalled. |
| 109 run_loop_(run_loop), | 108 run_loop_(run_loop), |
| 110 main_thread_(base::ThreadTaskRunnerHandle::Get()) { | 109 main_thread_(base::ThreadTaskRunnerHandle::Get()) { |
| 111 } | 110 } |
| 112 | 111 |
| 113 BrowserMonitor::~BrowserMonitor() { | 112 BrowserMonitor::~BrowserMonitor() { |
| 114 } | 113 } |
| 115 | 114 |
| 116 bool BrowserMonitor::StartWatching( | 115 bool BrowserMonitor::StartWatching( |
| 117 const base::char16* registry_path, | |
| 118 base::Process process, | 116 base::Process process, |
| 119 base::win::ScopedHandle on_initialized_event) { | 117 base::win::ScopedHandle on_initialized_event) { |
| 120 if (!exit_code_watcher_.Initialize(process.Pass())) | 118 if (!exit_code_watcher_.Initialize(process.Pass())) |
| 121 return false; | 119 return false; |
| 122 | 120 |
| 123 if (!background_thread_.StartWithOptions( | 121 if (!background_thread_.StartWithOptions( |
| 124 base::Thread::Options(base::MessageLoop::TYPE_IO, 0))) { | 122 base::Thread::Options(base::MessageLoop::TYPE_IO, 0))) { |
| 125 return false; | 123 return false; |
| 126 } | 124 } |
| 127 | 125 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 // The browser exited abnormally, wait around for a little bit to see | 177 // The browser exited abnormally, wait around for a little bit to see |
| 180 // whether this instance will get a logoff message. | 178 // whether this instance will get a logoff message. |
| 181 main_thread_->PostDelayedTask( | 179 main_thread_->PostDelayedTask( |
| 182 FROM_HERE, | 180 FROM_HERE, |
| 183 run_loop_->QuitClosure(), | 181 run_loop_->QuitClosure(), |
| 184 base::TimeDelta::FromSeconds(kDelayTimeSeconds)); | 182 base::TimeDelta::FromSeconds(kDelayTimeSeconds)); |
| 185 } | 183 } |
| 186 } | 184 } |
| 187 | 185 |
| 188 void OnWindowEvent( | 186 void OnWindowEvent( |
| 189 const base::string16& registry_path, | |
| 190 base::Process process, | 187 base::Process process, |
| 191 const base::Callback<void(const base::Process&)>& on_hung_callback, | 188 const base::Callback<void(const base::Process&)>& on_hung_callback, |
| 192 browser_watcher::WindowHangMonitor::WindowEvent window_event) { | 189 browser_watcher::WindowHangMonitor::WindowEvent window_event) { |
| 193 if (window_event == browser_watcher::WindowHangMonitor::WINDOW_HUNG && | 190 if (window_event == browser_watcher::WindowHangMonitor::WINDOW_HUNG && |
| 194 !on_hung_callback.is_null()) { | 191 !on_hung_callback.is_null()) { |
| 195 on_hung_callback.Run(process); | 192 on_hung_callback.Run(process); |
| 196 } | 193 } |
| 197 } | 194 } |
| 198 | 195 |
| 199 #if BUILDFLAG(ENABLE_KASKO) | 196 #if BUILDFLAG(ENABLE_KASKO) |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 378 base::Bind(&DumpHungBrowserProcess, main_thread_id, channel_name); | 375 base::Bind(&DumpHungBrowserProcess, main_thread_id, channel_name); |
| 379 } | 376 } |
| 380 #endif // BUILDFLAG(ENABLE_KASKO_HANG_REPORTS) | 377 #endif // BUILDFLAG(ENABLE_KASKO_HANG_REPORTS) |
| 381 #endif // BUILDFLAG(ENABLE_KASKO) | 378 #endif // BUILDFLAG(ENABLE_KASKO) |
| 382 | 379 |
| 383 // Run a UI message loop on the main thread. | 380 // Run a UI message loop on the main thread. |
| 384 base::MessageLoop msg_loop(base::MessageLoop::TYPE_UI); | 381 base::MessageLoop msg_loop(base::MessageLoop::TYPE_UI); |
| 385 msg_loop.set_thread_name("WatcherMainThread"); | 382 msg_loop.set_thread_name("WatcherMainThread"); |
| 386 | 383 |
| 387 base::RunLoop run_loop; | 384 base::RunLoop run_loop; |
| 388 BrowserMonitor monitor(&run_loop, registry_path); | 385 BrowserMonitor monitor(registry_path, &run_loop); |
| 389 if (!monitor.StartWatching(registry_path, process.Duplicate(), | 386 if (!monitor.StartWatching(process.Duplicate(), |
| 390 on_initialized_event.Pass())) { | 387 on_initialized_event.Pass())) { |
| 391 return 1; | 388 return 1; |
| 392 } | 389 } |
| 393 | 390 |
| 394 { | 391 { |
| 395 // Scoped to force |hang_monitor| destruction before Kasko is shut down. | 392 // Scoped to force |hang_monitor| destruction before Kasko is shut down. |
| 396 browser_watcher::WindowHangMonitor hang_monitor( | 393 browser_watcher::WindowHangMonitor hang_monitor( |
| 397 base::TimeDelta::FromSeconds(60), base::TimeDelta::FromSeconds(20), | 394 base::TimeDelta::FromSeconds(60), base::TimeDelta::FromSeconds(20), |
| 398 base::Bind(&OnWindowEvent, registry_path, | 395 base::Bind(&OnWindowEvent, base::Passed(process.Duplicate()), |
| 399 base::Passed(process.Duplicate()), on_hung_callback)); | 396 on_hung_callback)); |
| 400 hang_monitor.Initialize(process.Duplicate()); | 397 hang_monitor.Initialize(process.Duplicate()); |
| 401 | 398 |
| 402 run_loop.Run(); | 399 run_loop.Run(); |
| 403 } | 400 } |
| 404 | 401 |
| 405 #if BUILDFLAG(ENABLE_KASKO) | 402 #if BUILDFLAG(ENABLE_KASKO) |
| 406 if (launched_kasko) | 403 if (launched_kasko) |
| 407 kasko::api::ShutdownReporter(); | 404 kasko::api::ShutdownReporter(); |
| 408 #endif // BUILDFLAG(ENABLE_KASKO) | 405 #endif // BUILDFLAG(ENABLE_KASKO) |
| 409 | 406 |
| 410 // Wind logging down. | 407 // Wind logging down. |
| 411 logging::LogEventProvider::Uninitialize(); | 408 logging::LogEventProvider::Uninitialize(); |
| 412 | 409 |
| 413 return 0; | 410 return 0; |
| 414 } | 411 } |
| 415 | 412 |
| 416 static_assert( | 413 static_assert( |
| 417 base::is_same<decltype(&WatcherMain), ChromeWatcherMainFunction>::value, | 414 base::is_same<decltype(&WatcherMain), ChromeWatcherMainFunction>::value, |
| 418 "WatcherMain() has wrong type"); | 415 "WatcherMain() has wrong type"); |
| OLD | NEW |