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