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 0; |
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 |