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