process_singleton.h 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  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
  3. // found in the LICENSE file.
  4. #ifndef CHROME_BROWSER_PROCESS_SINGLETON_H_
  5. #define CHROME_BROWSER_PROCESS_SINGLETON_H_
  6. #if defined(OS_WIN)
  7. #include <windows.h>
  8. #endif // defined(OS_WIN)
  9. #include <set>
  10. #include <vector>
  11. #include "base/callback.h"
  12. #include "base/command_line.h"
  13. #include "base/files/file_path.h"
  14. #include "base/logging.h"
  15. #include "base/memory/ref_counted.h"
  16. #include "base/process/process.h"
  17. #include "base/sequence_checker.h"
  18. #include "ui/gfx/native_widget_types.h"
  19. #if defined(OS_POSIX) && !defined(OS_ANDROID)
  20. #include "base/files/scoped_temp_dir.h"
  21. #endif
  22. #if defined(OS_WIN)
  23. #include "base/win/message_window.h"
  24. #endif // defined(OS_WIN)
  25. namespace base {
  26. class CommandLine;
  27. }
  28. // ProcessSingleton ----------------------------------------------------------
  29. //
  30. // This class allows different browser processes to communicate with
  31. // each other. It is named according to the user data directory, so
  32. // we can be sure that no more than one copy of the application can be
  33. // running at once with a given data directory.
  34. //
  35. // Implementation notes:
  36. // - the Windows implementation uses an invisible global message window;
  37. // - the Linux implementation uses a Unix domain socket in the user data dir.
  38. class ProcessSingleton {
  39. public:
  40. enum NotifyResult {
  41. PROCESS_NONE,
  42. PROCESS_NOTIFIED,
  43. PROFILE_IN_USE,
  44. LOCK_ERROR,
  45. };
  46. // Implement this callback to handle notifications from other processes. The
  47. // callback will receive the command line and directory with which the other
  48. // Chrome process was launched. Return true if the command line will be
  49. // handled within the current browser instance or false if the remote process
  50. // should handle it (i.e., because the current process is shutting down).
  51. using NotificationCallback =
  52. base::Callback<bool(const base::CommandLine::StringVector& command_line,
  53. const base::FilePath& current_directory)>;
  54. ProcessSingleton(const base::FilePath& user_data_dir,
  55. const NotificationCallback& notification_callback);
  56. ~ProcessSingleton();
  57. // Notify another process, if available. Otherwise sets ourselves as the
  58. // singleton instance. Returns PROCESS_NONE if we became the singleton
  59. // instance. Callers are guaranteed to either have notified an existing
  60. // process or have grabbed the singleton (unless the profile is locked by an
  61. // unreachable process).
  62. // TODO(brettw): Make the implementation of this method non-platform-specific
  63. // by making Linux re-use the Windows implementation.
  64. NotifyResult NotifyOtherProcessOrCreate();
  65. void StartListeningOnSocket();
  66. void OnBrowserReady();
  67. // Sets ourself up as the singleton instance. Returns true on success. If
  68. // false is returned, we are not the singleton instance and the caller must
  69. // exit.
  70. // NOTE: Most callers should generally prefer NotifyOtherProcessOrCreate() to
  71. // this method, only callers for whom failure is preferred to notifying
  72. // another process should call this directly.
  73. bool Create();
  74. // Clear any lock state during shutdown.
  75. void Cleanup();
  76. #if defined(OS_POSIX) && !defined(OS_ANDROID)
  77. static void DisablePromptForTesting();
  78. #endif
  79. #if defined(OS_WIN)
  80. // Called to query whether to kill a hung browser process that has visible
  81. // windows. Return true to allow killing the hung process.
  82. using ShouldKillRemoteProcessCallback = base::Callback<bool()>;
  83. void OverrideShouldKillRemoteProcessCallbackForTesting(
  84. const ShouldKillRemoteProcessCallback& display_dialog_callback);
  85. #endif
  86. protected:
  87. // Notify another process, if available.
  88. // Returns true if another process was found and notified, false if we should
  89. // continue with the current process.
  90. // On Windows, Create() has to be called before this.
  91. NotifyResult NotifyOtherProcess();
  92. #if defined(OS_POSIX) && !defined(OS_ANDROID)
  93. // Exposed for testing. We use a timeout on Linux, and in tests we want
  94. // this timeout to be short.
  95. NotifyResult NotifyOtherProcessWithTimeout(
  96. const base::CommandLine& command_line,
  97. int retry_attempts,
  98. const base::TimeDelta& timeout,
  99. bool kill_unresponsive);
  100. NotifyResult NotifyOtherProcessWithTimeoutOrCreate(
  101. const base::CommandLine& command_line,
  102. int retry_attempts,
  103. const base::TimeDelta& timeout);
  104. void OverrideCurrentPidForTesting(base::ProcessId pid);
  105. void OverrideKillCallbackForTesting(
  106. const base::Callback<void(int)>& callback);
  107. #endif
  108. private:
  109. NotificationCallback notification_callback_; // Handler for notifications.
  110. #if defined(OS_WIN)
  111. HWND remote_window_; // The HWND_MESSAGE of another browser.
  112. base::win::MessageWindow window_; // The message-only window.
  113. bool is_virtualized_; // Stuck inside Microsoft Softricity VM environment.
  114. HANDLE lock_file_;
  115. base::FilePath user_data_dir_;
  116. ShouldKillRemoteProcessCallback should_kill_remote_process_callback_;
  117. #elif defined(OS_POSIX) && !defined(OS_ANDROID)
  118. // Start listening to the socket.
  119. void StartListening(int sock);
  120. // Return true if the given pid is one of our child processes.
  121. // Assumes that the current pid is the root of all pids of the current
  122. // instance.
  123. bool IsSameChromeInstance(pid_t pid);
  124. // Extract the process's pid from a symbol link path and if it is on
  125. // the same host, kill the process, unlink the lock file and return true.
  126. // If the process is part of the same chrome instance, unlink the lock file
  127. // and return true without killing it.
  128. // If the process is on a different host, return false.
  129. bool KillProcessByLockPath();
  130. // Default function to kill a process, overridable by tests.
  131. void KillProcess(int pid);
  132. // Allow overriding for tests.
  133. base::ProcessId current_pid_;
  134. // Function to call when the other process is hung and needs to be killed.
  135. // Allows overriding for tests.
  136. base::Callback<void(int)> kill_callback_;
  137. // Path in file system to the socket.
  138. base::FilePath socket_path_;
  139. // Path in file system to the lock.
  140. base::FilePath lock_path_;
  141. // Path in file system to the cookie file.
  142. base::FilePath cookie_path_;
  143. // Temporary directory to hold the socket.
  144. base::ScopedTempDir socket_dir_;
  145. // Helper class for linux specific messages. LinuxWatcher is ref counted
  146. // because it posts messages between threads.
  147. class LinuxWatcher;
  148. scoped_refptr<LinuxWatcher> watcher_;
  149. int sock_;
  150. bool listen_on_ready_ = false;
  151. #endif
  152. SEQUENCE_CHECKER(sequence_checker_);
  153. DISALLOW_COPY_AND_ASSIGN(ProcessSingleton);
  154. };
  155. #endif // CHROME_BROWSER_PROCESS_SINGLETON_H_