| 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 <windows.h> | 7 #include <windows.h> |
| 8 #include <shellapi.h> | 8 #include <shellapi.h> |
| 9 #include <stddef.h> | 9 #include <stddef.h> |
| 10 | 10 |
| 11 #include "base/base_paths.h" | 11 #include "base/base_paths.h" |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
| 14 #include "base/files/file_path.h" | 14 #include "base/files/file_path.h" |
| 15 #include "base/macros.h" | 15 #include "base/macros.h" |
| 16 #include "base/path_service.h" | 16 #include "base/path_service.h" |
| 17 #include "base/process/process.h" | 17 #include "base/process/process.h" |
| 18 #include "base/process/process_info.h" | 18 #include "base/process/process_info.h" |
| 19 #include "base/strings/string_number_conversions.h" | 19 #include "base/strings/string_number_conversions.h" |
| 20 #include "base/strings/stringprintf.h" | 20 #include "base/strings/stringprintf.h" |
| 21 #include "base/strings/utf_string_conversions.h" | 21 #include "base/strings/utf_string_conversions.h" |
| 22 #include "base/time/time.h" | 22 #include "base/time/time.h" |
| 23 #include "base/win/registry.h" | 23 #include "base/win/registry.h" |
| 24 #include "base/win/scoped_handle.h" | 24 #include "base/win/scoped_handle.h" |
| 25 #include "base/win/windows_version.h" | 25 #include "base/win/windows_version.h" |
| 26 #include "chrome/browser/browser_process.h" | 26 #include "chrome/browser/browser_process.h" |
| 27 #include "chrome/browser/browser_process_platform_part.h" | 27 #include "chrome/browser/browser_process_platform_part.h" |
| 28 #include "chrome/browser/chrome_process_finder_win.h" | |
| 29 #include "chrome/browser/shell_integration.h" | 28 #include "chrome/browser/shell_integration.h" |
| 30 #include "chrome/browser/ui/simple_message_box.h" | 29 #include "chrome/browser/ui/simple_message_box.h" |
| 30 #include "chrome/browser/win/chrome_process_finder.h" |
| 31 #include "chrome/common/channel_info.h" | 31 #include "chrome/common/channel_info.h" |
| 32 #include "chrome/common/chrome_constants.h" | 32 #include "chrome/common/chrome_constants.h" |
| 33 #include "chrome/common/chrome_paths.h" | 33 #include "chrome/common/chrome_paths.h" |
| 34 #include "chrome/common/chrome_paths_internal.h" | 34 #include "chrome/common/chrome_paths_internal.h" |
| 35 #include "chrome/common/chrome_switches.h" | 35 #include "chrome/common/chrome_switches.h" |
| 36 #include "chrome/grit/chromium_strings.h" | 36 #include "chrome/grit/chromium_strings.h" |
| 37 #include "chrome/installer/util/google_update_settings.h" | 37 #include "chrome/installer/util/google_update_settings.h" |
| 38 #include "chrome/installer/util/util_constants.h" | 38 #include "chrome/installer/util/util_constants.h" |
| 39 #include "chrome/installer/util/wmi.h" | 39 #include "chrome/installer/util/wmi.h" |
| 40 #include "components/version_info/version_info.h" | 40 #include "components/version_info/version_info.h" |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 266 if (!installer::WMIProcess::Launch(::GetCommandLineW(), &process_id)) | 266 if (!installer::WMIProcess::Launch(::GetCommandLineW(), &process_id)) |
| 267 return false; | 267 return false; |
| 268 is_virtualized_ = true; | 268 is_virtualized_ = true; |
| 269 // The new window was spawned from WMI, and won't be in the foreground. | 269 // The new window was spawned from WMI, and won't be in the foreground. |
| 270 // So, first we sleep while the new chrome.exe instance starts (because | 270 // So, first we sleep while the new chrome.exe instance starts (because |
| 271 // WaitForInputIdle doesn't work here). Then we poll for up to two more | 271 // WaitForInputIdle doesn't work here). Then we poll for up to two more |
| 272 // seconds and make the window foreground if we find it (or we give up). | 272 // seconds and make the window foreground if we find it (or we give up). |
| 273 HWND hwnd = 0; | 273 HWND hwnd = 0; |
| 274 ::Sleep(90); | 274 ::Sleep(90); |
| 275 for (int tries = 200; tries; --tries) { | 275 for (int tries = 200; tries; --tries) { |
| 276 hwnd = chrome::FindRunningChromeWindow(user_data_dir); | 276 hwnd = chrome::win::FindRunningChromeWindow(user_data_dir); |
| 277 if (hwnd) { | 277 if (hwnd) { |
| 278 ::SetForegroundWindow(hwnd); | 278 ::SetForegroundWindow(hwnd); |
| 279 break; | 279 break; |
| 280 } | 280 } |
| 281 ::Sleep(10); | 281 ::Sleep(10); |
| 282 } | 282 } |
| 283 return true; | 283 return true; |
| 284 } | 284 } |
| 285 return false; | 285 return false; |
| 286 } | 286 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 304 // Code roughly based on Mozilla. | 304 // Code roughly based on Mozilla. |
| 305 ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcess() { | 305 ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcess() { |
| 306 if (is_virtualized_) | 306 if (is_virtualized_) |
| 307 return PROCESS_NOTIFIED; // We already spawned the process in this case. | 307 return PROCESS_NOTIFIED; // We already spawned the process in this case. |
| 308 if (lock_file_ == INVALID_HANDLE_VALUE && !remote_window_) { | 308 if (lock_file_ == INVALID_HANDLE_VALUE && !remote_window_) { |
| 309 return LOCK_ERROR; | 309 return LOCK_ERROR; |
| 310 } else if (!remote_window_) { | 310 } else if (!remote_window_) { |
| 311 return PROCESS_NONE; | 311 return PROCESS_NONE; |
| 312 } | 312 } |
| 313 | 313 |
| 314 switch (chrome::AttemptToNotifyRunningChrome(remote_window_, false)) { | 314 switch (chrome::win::AttemptToNotifyRunningChrome(remote_window_, false)) { |
| 315 case chrome::NOTIFY_SUCCESS: | 315 case chrome::win::NOTIFY_SUCCESS: |
| 316 return PROCESS_NOTIFIED; | 316 return PROCESS_NOTIFIED; |
| 317 case chrome::NOTIFY_FAILED: | 317 case chrome::win::NOTIFY_FAILED: |
| 318 remote_window_ = NULL; | 318 remote_window_ = NULL; |
| 319 return PROCESS_NONE; | 319 return PROCESS_NONE; |
| 320 case chrome::NOTIFY_WINDOW_HUNG: | 320 case chrome::win::NOTIFY_WINDOW_HUNG: |
| 321 // Fall through and potentially terminate the hung browser. | 321 // Fall through and potentially terminate the hung browser. |
| 322 break; | 322 break; |
| 323 } | 323 } |
| 324 | 324 |
| 325 // The window is hung. | 325 // The window is hung. |
| 326 DWORD process_id = 0; | 326 DWORD process_id = 0; |
| 327 DWORD thread_id = ::GetWindowThreadProcessId(remote_window_, &process_id); | 327 DWORD thread_id = ::GetWindowThreadProcessId(remote_window_, &process_id); |
| 328 if (!thread_id || !process_id) { | 328 if (!thread_id || !process_id) { |
| 329 remote_window_ = NULL; | 329 remote_window_ = NULL; |
| 330 return PROCESS_NONE; | 330 return PROCESS_NONE; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 373 } | 373 } |
| 374 return result; | 374 return result; |
| 375 } | 375 } |
| 376 | 376 |
| 377 // Look for a Chrome instance that uses the same profile directory. If there | 377 // Look for a Chrome instance that uses the same profile directory. If there |
| 378 // isn't one, create a message window with its title set to the profile | 378 // isn't one, create a message window with its title set to the profile |
| 379 // directory path. | 379 // directory path. |
| 380 bool ProcessSingleton::Create() { | 380 bool ProcessSingleton::Create() { |
| 381 static const wchar_t kMutexName[] = L"Local\\ChromeProcessSingletonStartup!"; | 381 static const wchar_t kMutexName[] = L"Local\\ChromeProcessSingletonStartup!"; |
| 382 | 382 |
| 383 remote_window_ = chrome::FindRunningChromeWindow(user_data_dir_); | 383 remote_window_ = chrome::win::FindRunningChromeWindow(user_data_dir_); |
| 384 if (!remote_window_ && !EscapeVirtualization(user_data_dir_)) { | 384 if (!remote_window_ && !EscapeVirtualization(user_data_dir_)) { |
| 385 // Make sure we will be the one and only process creating the window. | 385 // Make sure we will be the one and only process creating the window. |
| 386 // We use a named Mutex since we are protecting against multi-process | 386 // We use a named Mutex since we are protecting against multi-process |
| 387 // access. As documented, it's clearer to NOT request ownership on creation | 387 // access. As documented, it's clearer to NOT request ownership on creation |
| 388 // since it isn't guaranteed we will get it. It is better to create it | 388 // since it isn't guaranteed we will get it. It is better to create it |
| 389 // without ownership and explicitly get the ownership afterward. | 389 // without ownership and explicitly get the ownership afterward. |
| 390 base::win::ScopedHandle only_me(::CreateMutex(NULL, FALSE, kMutexName)); | 390 base::win::ScopedHandle only_me(::CreateMutex(NULL, FALSE, kMutexName)); |
| 391 if (!only_me.IsValid()) { | 391 if (!only_me.IsValid()) { |
| 392 DPLOG(FATAL) << "CreateMutex failed"; | 392 DPLOG(FATAL) << "CreateMutex failed"; |
| 393 return false; | 393 return false; |
| 394 } | 394 } |
| 395 | 395 |
| 396 AutoLockMutex auto_lock_only_me(only_me.Get()); | 396 AutoLockMutex auto_lock_only_me(only_me.Get()); |
| 397 | 397 |
| 398 // We now own the mutex so we are the only process that can create the | 398 // We now own the mutex so we are the only process that can create the |
| 399 // window at this time, but we must still check if someone created it | 399 // window at this time, but we must still check if someone created it |
| 400 // between the time where we looked for it above and the time the mutex | 400 // between the time where we looked for it above and the time the mutex |
| 401 // was given to us. | 401 // was given to us. |
| 402 remote_window_ = chrome::FindRunningChromeWindow(user_data_dir_); | 402 remote_window_ = chrome::win::FindRunningChromeWindow(user_data_dir_); |
| 403 | 403 |
| 404 if (!remote_window_) { | 404 if (!remote_window_) { |
| 405 // We have to make sure there is no Chrome instance running on another | 405 // We have to make sure there is no Chrome instance running on another |
| 406 // machine that uses the same profile. | 406 // machine that uses the same profile. |
| 407 base::FilePath lock_file_path = user_data_dir_.AppendASCII(kLockfile); | 407 base::FilePath lock_file_path = user_data_dir_.AppendASCII(kLockfile); |
| 408 lock_file_ = ::CreateFile(lock_file_path.value().c_str(), | 408 lock_file_ = ::CreateFile(lock_file_path.value().c_str(), |
| 409 GENERIC_WRITE, | 409 GENERIC_WRITE, |
| 410 FILE_SHARE_READ, | 410 FILE_SHARE_READ, |
| 411 NULL, | 411 NULL, |
| 412 CREATE_ALWAYS, | 412 CREATE_ALWAYS, |
| (...skipping 20 matching lines...) Expand all Loading... |
| 433 return window_.hwnd() != NULL; | 433 return window_.hwnd() != NULL; |
| 434 } | 434 } |
| 435 | 435 |
| 436 void ProcessSingleton::Cleanup() { | 436 void ProcessSingleton::Cleanup() { |
| 437 } | 437 } |
| 438 | 438 |
| 439 void ProcessSingleton::OverrideShouldKillRemoteProcessCallbackForTesting( | 439 void ProcessSingleton::OverrideShouldKillRemoteProcessCallbackForTesting( |
| 440 const ShouldKillRemoteProcessCallback& display_dialog_callback) { | 440 const ShouldKillRemoteProcessCallback& display_dialog_callback) { |
| 441 should_kill_remote_process_callback_ = display_dialog_callback; | 441 should_kill_remote_process_callback_ = display_dialog_callback; |
| 442 } | 442 } |
| OLD | NEW |