1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifndef CHROME_BROWSER_PROCESS_SINGLETON_H_ 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define CHROME_BROWSER_PROCESS_SINGLETON_H_ 73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "build/build_config.h" 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN) 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <windows.h> 1321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#endif // defined(OS_WIN) 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/basictypes.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h" 17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/ref_counted.h" 183f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/non_thread_safe.h" 1972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/native_widget_types.h" 2021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 2121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#if defined(OS_POSIX) 2221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/file_path.h" 2321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#endif // defined(OS_POSIX) 2421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#if defined(USE_X11) 26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_temp_dir.h" 2721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#endif // defined(USE_X11) 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass CommandLine; 303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass FilePath; 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ProcessSingleton ---------------------------------------------------------- 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This class allows different browser processes to communicate with 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// each other. It is named according to the user data directory, so 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// we can be sure that no more than one copy of the application can be 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// running at once with a given data directory. 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Implementation notes: 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// - the Windows implementation uses an invisible global message window; 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// - the Linux implementation uses a Unix domain socket in the user data dir. 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 433f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenclass ProcessSingleton : public base::NonThreadSafe { 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch enum NotifyResult { 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PROCESS_NONE, 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PROCESS_NOTIFIED, 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PROFILE_IN_USE, 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOCK_ERROR, 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch explicit ProcessSingleton(const FilePath& user_data_dir); 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ~ProcessSingleton(); 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Notify another process, if available. 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Returns true if another process was found and notified, false if we 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // should continue with this process. 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Windows code roughly based on Mozilla. 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(brettw): this will not handle all cases. If two process start up too 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // close to each other, the Create() might not yet have happened for the 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // first one, so this function won't find it. 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotifyResult NotifyOtherProcess(); 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Notify another process, if available. Otherwise sets ourselves as the 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // singleton instance. Returns PROCESS_NONE if we became the singleton 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // instance. 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotifyResult NotifyOtherProcessOrCreate(); 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#if defined(OS_LINUX) 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Exposed for testing. We use a timeout on Linux, and in tests we want 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // this timeout to be short. 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotifyResult NotifyOtherProcessWithTimeout(const CommandLine& command_line, 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int timeout_seconds, 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool kill_unresponsive); 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotifyResult NotifyOtherProcessWithTimeoutOrCreate( 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const CommandLine& command_line, 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int timeout_seconds); 7921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#endif // defined(OS_LINUX) 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 81dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(OS_WIN) 82dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Used in specific cases to let us know that there is an existing instance 83dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // of Chrome running with this profile. In general, you should not use this 84dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // function. Instead consider using NotifyOtherProcessOrCreate(). 85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // For non profile-specific method, use 86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // browser_util::IsBrowserAlreadyRunning(). 87dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bool FoundOtherProcessWindow() const { 88dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return (NULL != remote_window_); 89dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 90dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif // defined(OS_WIN) 91dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Sets ourself up as the singleton instance. Returns true on success. If 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // false is returned, we are not the singleton instance and the caller must 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // exit. 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool Create(); 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Clear any lock state during shutdown. 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Cleanup(); 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Blocks the dispatch of CopyData messages. foreground_window refers 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to the window that should be set to the foreground if a CopyData message 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // is received while the ProcessSingleton is locked. 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Lock(gfx::NativeWindow foreground_window) { 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(CalledOnValidThread()); 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch locked_ = true; 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch foreground_window_ = foreground_window; 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Allows the dispatch of CopyData messages. 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Unlock() { 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(CalledOnValidThread()); 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch locked_ = false; 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch foreground_window_ = NULL; 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool locked() { 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(CalledOnValidThread()); 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return locked_; 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if !defined(OS_MACOSX) 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Timeout for the current browser process to respond. 20 seconds should be 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // enough. It's only used in Windows and Linux implementations. 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static const int kTimeoutInSeconds = 20; 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool locked_; 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch gfx::NativeWindow foreground_window_; 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN) 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This ugly behemoth handles startup commands sent from another process. 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LRESULT OnCopyData(HWND hwnd, const COPYDATASTRUCT* cds); 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LRESULT CALLBACK WndProc(HWND hwnd, 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UINT message, 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WPARAM wparam, 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LPARAM lparam); 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static LRESULT CALLBACK WndProcStatic(HWND hwnd, 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UINT message, 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WPARAM wparam, 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LPARAM lparam) { 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ProcessSingleton* msg_wnd = reinterpret_cast<ProcessSingleton*>( 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetWindowLongPtr(hwnd, GWLP_USERDATA)); 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return msg_wnd->WndProc(hwnd, message, wparam, lparam); 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HWND remote_window_; // The HWND_MESSAGE of another browser. 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HWND window_; // The HWND_MESSAGE window. 1513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#elif defined(USE_X11) 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Path in file system to the socket. 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath socket_path_; 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Path in file system to the lock. 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath lock_path_; 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Path in file system to the cookie file. 1593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick FilePath cookie_path_; 1603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Temporary directory to hold the socket. 1623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ScopedTempDir socket_dir_; 1633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Helper class for linux specific messages. LinuxWatcher is ref counted 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // because it posts messages between threads. 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch class LinuxWatcher; 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<LinuxWatcher> watcher_; 168731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#elif defined(OS_MACOSX) 169731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Path in file system to the lock. 170731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick FilePath lock_path_; 171731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 172731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // File descriptor associated with the lockfile, valid between 173731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // |Create()| and |Cleanup()|. Two instances cannot have a lock on 174731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // the same file at the same time. 175731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick int lock_fd_; 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(ProcessSingleton); 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif // CHROME_BROWSER_PROCESS_SINGLETON_H_ 182