| 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 // On Linux, when the user tries to launch a second copy of chrome, we check | 5 // On Linux, when the user tries to launch a second copy of chrome, we check |
| 6 // for a socket in the user's profile directory. If the socket file is open we | 6 // for a socket in the user's profile directory. If the socket file is open we |
| 7 // send a message to the first chrome browser process with the current | 7 // send a message to the first chrome browser process with the current |
| 8 // directory and second process command line flags. The second process then | 8 // directory and second process command line flags. The second process then |
| 9 // exits. | 9 // exits. |
| 10 // | 10 // |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 287 | 287 |
| 288 *hostname = real_path.substr(0, pos); | 288 *hostname = real_path.substr(0, pos); |
| 289 | 289 |
| 290 const std::string& pid_str = real_path.substr(pos + 1); | 290 const std::string& pid_str = real_path.substr(pos + 1); |
| 291 if (!base::StringToInt(pid_str, pid)) | 291 if (!base::StringToInt(pid_str, pid)) |
| 292 *pid = -1; | 292 *pid = -1; |
| 293 | 293 |
| 294 return true; | 294 return true; |
| 295 } | 295 } |
| 296 | 296 |
| 297 void DisplayProfileInUseError(const std::string& lock_path, | 297 // Returns true if the user opted to unlock the profile. |
| 298 bool DisplayProfileInUseError(const base::FilePath& lock_path, |
| 298 const std::string& hostname, | 299 const std::string& hostname, |
| 299 int pid) { | 300 int pid) { |
| 300 string16 error = l10n_util::GetStringFUTF16( | 301 string16 error = l10n_util::GetStringFUTF16( |
| 301 IDS_PROFILE_IN_USE_LINUX, | 302 IDS_PROFILE_IN_USE_LINUX, |
| 302 base::IntToString16(pid), | 303 base::IntToString16(pid), |
| 303 ASCIIToUTF16(hostname), | 304 ASCIIToUTF16(hostname), |
| 304 WideToUTF16(base::SysNativeMBToWide(lock_path)), | |
| 305 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); | 305 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); |
| 306 string16 relaunch_button_text = l10n_util::GetStringFUTF16( |
| 307 IDS_PROFILE_IN_USE_LINUX_RELAUNCH, |
| 308 string16()); |
| 306 LOG(ERROR) << base::SysWideToNativeMB(UTF16ToWide(error)).c_str(); | 309 LOG(ERROR) << base::SysWideToNativeMB(UTF16ToWide(error)).c_str(); |
| 307 if (!g_disable_prompt) { | 310 if (!g_disable_prompt) { |
| 308 #if defined(TOOLKIT_GTK) | 311 #if defined(TOOLKIT_GTK) |
| 309 ProcessSingletonDialog::ShowAndRun(UTF16ToUTF8(error)); | 312 return ProcessSingletonDialog::ShowAndRun( |
| 313 UTF16ToUTF8(error), UTF16ToUTF8(relaunch_button_text)); |
| 310 #else | 314 #else |
| 311 NOTIMPLEMENTED(); | 315 NOTIMPLEMENTED(); |
| 312 #endif | 316 #endif |
| 313 } | 317 } |
| 318 return false; |
| 314 } | 319 } |
| 315 | 320 |
| 316 bool IsChromeProcess(pid_t pid) { | 321 bool IsChromeProcess(pid_t pid) { |
| 317 base::FilePath other_chrome_path(base::GetProcessExecutablePath(pid)); | 322 base::FilePath other_chrome_path(base::GetProcessExecutablePath(pid)); |
| 318 return (!other_chrome_path.empty() && | 323 return (!other_chrome_path.empty() && |
| 319 other_chrome_path.BaseName() == | 324 other_chrome_path.BaseName() == |
| 320 base::FilePath(chrome::kBrowserProcessExecutableName)); | 325 base::FilePath(chrome::kBrowserProcessExecutableName)); |
| 321 } | 326 } |
| 322 | 327 |
| 323 // A helper class to hold onto a socket. | 328 // A helper class to hold onto a socket. |
| (...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 727 // No lockfile exists. | 732 // No lockfile exists. |
| 728 return PROCESS_NONE; | 733 return PROCESS_NONE; |
| 729 } | 734 } |
| 730 | 735 |
| 731 if (hostname.empty()) { | 736 if (hostname.empty()) { |
| 732 // Invalid lockfile. | 737 // Invalid lockfile. |
| 733 UnlinkPath(lock_path_); | 738 UnlinkPath(lock_path_); |
| 734 return PROCESS_NONE; | 739 return PROCESS_NONE; |
| 735 } | 740 } |
| 736 | 741 |
| 737 if (hostname != net::GetHostName()) { | 742 if (hostname != net::GetHostName() && !IsChromeProcess(pid)) { |
| 738 // Locked by process on another host. | 743 // Locked by process on another host. If the user selected to unlock |
| 739 DisplayProfileInUseError(lock_path_.value(), hostname, pid); | 744 // the profile, try to continue; otherwise quit. |
| 745 if (DisplayProfileInUseError(lock_path_, hostname, pid)) { |
| 746 UnlinkPath(lock_path_); |
| 747 return PROCESS_NONE; |
| 748 } |
| 740 return PROFILE_IN_USE; | 749 return PROFILE_IN_USE; |
| 741 } | 750 } |
| 742 | 751 |
| 743 if (!IsChromeProcess(pid)) { | 752 if (!IsChromeProcess(pid)) { |
| 744 // Orphaned lockfile (no process with pid, or non-chrome process.) | 753 // Orphaned lockfile (no process with pid, or non-chrome process.) |
| 745 UnlinkPath(lock_path_); | 754 UnlinkPath(lock_path_); |
| 746 return PROCESS_NONE; | 755 return PROCESS_NONE; |
| 747 } | 756 } |
| 748 | 757 |
| 749 if (IsSameChromeInstance(pid)) { | 758 if (IsSameChromeInstance(pid)) { |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 951 } | 960 } |
| 952 return true; | 961 return true; |
| 953 } | 962 } |
| 954 | 963 |
| 955 bool ProcessSingleton::KillProcessByLockPath() { | 964 bool ProcessSingleton::KillProcessByLockPath() { |
| 956 std::string hostname; | 965 std::string hostname; |
| 957 int pid; | 966 int pid; |
| 958 ParseLockPath(lock_path_, &hostname, &pid); | 967 ParseLockPath(lock_path_, &hostname, &pid); |
| 959 | 968 |
| 960 if (!hostname.empty() && hostname != net::GetHostName()) { | 969 if (!hostname.empty() && hostname != net::GetHostName()) { |
| 961 DisplayProfileInUseError(lock_path_.value(), hostname, pid); | 970 return DisplayProfileInUseError(lock_path_, hostname, pid); |
| 962 return false; | |
| 963 } | 971 } |
| 964 UnlinkPath(lock_path_); | 972 UnlinkPath(lock_path_); |
| 965 | 973 |
| 966 if (IsSameChromeInstance(pid)) | 974 if (IsSameChromeInstance(pid)) |
| 967 return true; | 975 return true; |
| 968 | 976 |
| 969 if (pid > 0) { | 977 if (pid > 0) { |
| 970 kill_callback_.Run(pid); | 978 kill_callback_.Run(pid); |
| 971 return true; | 979 return true; |
| 972 } | 980 } |
| 973 | 981 |
| 974 LOG(ERROR) << "Failed to extract pid from path: " << lock_path_.value(); | 982 LOG(ERROR) << "Failed to extract pid from path: " << lock_path_.value(); |
| 975 return true; | 983 return true; |
| 976 } | 984 } |
| 977 | 985 |
| 978 void ProcessSingleton::KillProcess(int pid) { | 986 void ProcessSingleton::KillProcess(int pid) { |
| 979 // TODO(james.su@gmail.com): Is SIGKILL ok? | 987 // TODO(james.su@gmail.com): Is SIGKILL ok? |
| 980 int rv = kill(static_cast<base::ProcessHandle>(pid), SIGKILL); | 988 int rv = kill(static_cast<base::ProcessHandle>(pid), SIGKILL); |
| 981 // ESRCH = No Such Process (can happen if the other process is already in | 989 // ESRCH = No Such Process (can happen if the other process is already in |
| 982 // progress of shutting down and finishes before we try to kill it). | 990 // progress of shutting down and finishes before we try to kill it). |
| 983 DCHECK(rv == 0 || errno == ESRCH) << "Error killing process: " | 991 DCHECK(rv == 0 || errno == ESRCH) << "Error killing process: " |
| 984 << safe_strerror(errno); | 992 << safe_strerror(errno); |
| 985 } | 993 } |
| OLD | NEW |