| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/browser/process_singleton.h" | 5 #include "chrome/browser/process_singleton.h" |
| 6 | 6 |
| 7 #include <shellapi.h> | 7 #include <shellapi.h> |
| 8 | 8 |
| 9 #include "base/base_paths.h" | 9 #include "base/base_paths.h" |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 #include "chrome/browser/chrome_process_finder_win.h" | 26 #include "chrome/browser/chrome_process_finder_win.h" |
| 27 #include "chrome/browser/metro_utils/metro_chrome_win.h" | 27 #include "chrome/browser/metro_utils/metro_chrome_win.h" |
| 28 #include "chrome/browser/shell_integration.h" | 28 #include "chrome/browser/shell_integration.h" |
| 29 #include "chrome/browser/ui/simple_message_box.h" | 29 #include "chrome/browser/ui/simple_message_box.h" |
| 30 #include "chrome/common/chrome_constants.h" | 30 #include "chrome/common/chrome_constants.h" |
| 31 #include "chrome/common/chrome_paths.h" | 31 #include "chrome/common/chrome_paths.h" |
| 32 #include "chrome/common/chrome_paths_internal.h" | 32 #include "chrome/common/chrome_paths_internal.h" |
| 33 #include "chrome/common/chrome_switches.h" | 33 #include "chrome/common/chrome_switches.h" |
| 34 #include "chrome/grit/chromium_strings.h" | 34 #include "chrome/grit/chromium_strings.h" |
| 35 #include "chrome/installer/util/wmi.h" | 35 #include "chrome/installer/util/wmi.h" |
| 36 #include "components/browser_watcher/exit_funnel_win.h" |
| 36 #include "content/public/common/result_codes.h" | 37 #include "content/public/common/result_codes.h" |
| 37 #include "net/base/escape.h" | 38 #include "net/base/escape.h" |
| 38 #include "ui/base/l10n/l10n_util.h" | 39 #include "ui/base/l10n/l10n_util.h" |
| 39 #include "ui/gfx/win/hwnd_util.h" | 40 #include "ui/gfx/win/hwnd_util.h" |
| 40 | 41 |
| 41 namespace { | 42 namespace { |
| 42 | 43 |
| 43 const char kLockfile[] = "lockfile"; | 44 const char kLockfile[] = "lockfile"; |
| 44 | 45 |
| 45 const int kMetroChromeActivationTimeoutMs = 3000; | 46 const int kMetroChromeActivationTimeoutMs = 3000; |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 return PROCESS_NONE; | 251 return PROCESS_NONE; |
| 251 } | 252 } |
| 252 | 253 |
| 253 switch (chrome::AttemptToNotifyRunningChrome(remote_window_, false)) { | 254 switch (chrome::AttemptToNotifyRunningChrome(remote_window_, false)) { |
| 254 case chrome::NOTIFY_SUCCESS: | 255 case chrome::NOTIFY_SUCCESS: |
| 255 return PROCESS_NOTIFIED; | 256 return PROCESS_NOTIFIED; |
| 256 case chrome::NOTIFY_FAILED: | 257 case chrome::NOTIFY_FAILED: |
| 257 remote_window_ = NULL; | 258 remote_window_ = NULL; |
| 258 return PROCESS_NONE; | 259 return PROCESS_NONE; |
| 259 case chrome::NOTIFY_WINDOW_HUNG: | 260 case chrome::NOTIFY_WINDOW_HUNG: |
| 260 remote_window_ = NULL; | 261 // Record a hung rendezvous event in this process' exit funnel. |
| 262 browser_watcher::ExitFunnel::RecordSingleEvent( |
| 263 chrome::kBrowserExitCodesRegistryPath, L"RendezvousToHungBrowser"); |
| 261 break; | 264 break; |
| 262 } | 265 } |
| 263 | 266 |
| 264 DWORD process_id = 0; | 267 DWORD process_id = 0; |
| 265 DWORD thread_id = ::GetWindowThreadProcessId(remote_window_, &process_id); | 268 DWORD thread_id = ::GetWindowThreadProcessId(remote_window_, &process_id); |
| 266 if (!thread_id || !process_id) { | 269 if (!thread_id || !process_id) { |
| 267 remote_window_ = NULL; | 270 remote_window_ = NULL; |
| 268 return PROCESS_NONE; | 271 return PROCESS_NONE; |
| 269 } | 272 } |
| 270 base::Process process = base::Process::Open(process_id); | 273 base::Process process = base::Process::Open(process_id); |
| 271 | 274 |
| 272 // The window is hung. Scan for every window to find a visible one. | 275 // The window is hung. Scan for every window to find a visible one. |
| 273 bool visible_window = false; | 276 bool visible_window = false; |
| 274 ::EnumThreadWindows(thread_id, | 277 ::EnumThreadWindows(thread_id, |
| 275 &BrowserWindowEnumeration, | 278 &BrowserWindowEnumeration, |
| 276 reinterpret_cast<LPARAM>(&visible_window)); | 279 reinterpret_cast<LPARAM>(&visible_window)); |
| 277 | 280 |
| 278 // If there is a visible browser window, ask the user before killing it. | 281 // If there is a visible browser window, ask the user before killing it. |
| 279 if (visible_window && | 282 if (visible_window && |
| 280 chrome::ShowMessageBox( | 283 chrome::ShowMessageBox( |
| 281 NULL, | 284 NULL, |
| 282 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME), | 285 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME), |
| 283 l10n_util::GetStringUTF16(IDS_BROWSER_HUNGBROWSER_MESSAGE), | 286 l10n_util::GetStringUTF16(IDS_BROWSER_HUNGBROWSER_MESSAGE), |
| 284 chrome::MESSAGE_BOX_TYPE_QUESTION) == chrome::MESSAGE_BOX_RESULT_NO) { | 287 chrome::MESSAGE_BOX_TYPE_QUESTION) == chrome::MESSAGE_BOX_RESULT_NO) { |
| 285 // The user denied. Quit silently. | 288 // The user denied. Quit silently. |
| 286 return PROCESS_NOTIFIED; | 289 return PROCESS_NOTIFIED; |
| 287 } | 290 } |
| 288 | 291 |
| 292 // Record the termination event in the hung process' exit funnel. |
| 293 browser_watcher::ExitFunnel funnel; |
| 294 if (funnel.Init(chrome::kBrowserExitCodesRegistryPath, process.Handle())) |
| 295 funnel.RecordEvent(L"HungBrowserTerminated"); |
| 296 |
| 289 // Time to take action. Kill the browser process. | 297 // Time to take action. Kill the browser process. |
| 290 base::KillProcess(process.Handle(), content::RESULT_CODE_HUNG, true); | 298 base::KillProcess(process.Handle(), content::RESULT_CODE_HUNG, true); |
| 291 remote_window_ = NULL; | 299 remote_window_ = NULL; |
| 292 return PROCESS_NONE; | 300 return PROCESS_NONE; |
| 293 } | 301 } |
| 294 | 302 |
| 295 ProcessSingleton::NotifyResult | 303 ProcessSingleton::NotifyResult |
| 296 ProcessSingleton::NotifyOtherProcessOrCreate() { | 304 ProcessSingleton::NotifyOtherProcessOrCreate() { |
| 297 ProcessSingleton::NotifyResult result = PROCESS_NONE; | 305 ProcessSingleton::NotifyResult result = PROCESS_NONE; |
| 298 if (!Create()) { | 306 if (!Create()) { |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 422 ::SetEvent(metro_activation_event.Get()); | 430 ::SetEvent(metro_activation_event.Get()); |
| 423 } | 431 } |
| 424 } | 432 } |
| 425 } | 433 } |
| 426 | 434 |
| 427 return window_.hwnd() != NULL; | 435 return window_.hwnd() != NULL; |
| 428 } | 436 } |
| 429 | 437 |
| 430 void ProcessSingleton::Cleanup() { | 438 void ProcessSingleton::Cleanup() { |
| 431 } | 439 } |
| OLD | NEW |