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 |