Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(134)

Side by Side Diff: chrome/browser/process_singleton_win.cc

Issue 10702159: Implement lock file for windows profiles. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Refactored to production code. Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/process_singleton.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 #include "chrome/browser/process_singleton.h" 5 #include "chrome/browser/process_singleton.h"
6 6
7 #include "base/base_paths.h" 7 #include "base/base_paths.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/file_path.h" 9 #include "base/file_path.h"
10 #include "base/path_service.h" 10 #include "base/path_service.h"
11 #include "base/process_util.h" 11 #include "base/process_util.h"
12 #include "base/utf_string_conversions.h" 12 #include "base/utf_string_conversions.h"
13 #include "base/win/scoped_handle.h" 13 #include "base/win/scoped_handle.h"
14 #include "base/win/wrapped_window_proc.h" 14 #include "base/win/wrapped_window_proc.h"
15 #include "chrome/browser/ui/simple_message_box.h" 15 #include "chrome/browser/ui/simple_message_box.h"
16 #include "chrome/common/chrome_constants.h" 16 #include "chrome/common/chrome_constants.h"
17 #include "chrome/installer/util/wmi.h" 17 #include "chrome/installer/util/wmi.h"
18 #include "content/public/common/result_codes.h" 18 #include "content/public/common/result_codes.h"
19 #include "grit/chromium_strings.h" 19 #include "grit/chromium_strings.h"
20 #include "grit/generated_resources.h" 20 #include "grit/generated_resources.h"
21 #include "ui/base/l10n/l10n_util.h" 21 #include "ui/base/l10n/l10n_util.h"
22 #include "ui/base/win/hwnd_util.h" 22 #include "ui/base/win/hwnd_util.h"
23 23
24 namespace { 24 namespace {
25 25
26 const char kLockfile[] = "lockfile";
27
26 // Checks the visibility of the enumerated window and signals once a visible 28 // Checks the visibility of the enumerated window and signals once a visible
27 // window has been found. 29 // window has been found.
28 BOOL CALLBACK BrowserWindowEnumeration(HWND window, LPARAM param) { 30 BOOL CALLBACK BrowserWindowEnumeration(HWND window, LPARAM param) {
29 bool* result = reinterpret_cast<bool*>(param); 31 bool* result = reinterpret_cast<bool*>(param);
30 *result = IsWindowVisible(window) != 0; 32 *result = IsWindowVisible(window) != 0;
31 // Stops enumeration if a visible window has been found. 33 // Stops enumeration if a visible window has been found.
32 return !*result; 34 return !*result;
33 } 35 }
34 36
35 // This function thunks to the object's version of the windowproc, taking in 37 // This function thunks to the object's version of the windowproc, taking in
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 return true; 143 return true;
142 } 144 }
143 return false; 145 return false;
144 } 146 }
145 147
146 // Look for a Chrome instance that uses the same profile directory. 148 // Look for a Chrome instance that uses the same profile directory.
147 // If there isn't one, create a message window with its title set to 149 // If there isn't one, create a message window with its title set to
148 // the profile directory path. 150 // the profile directory path.
149 ProcessSingleton::ProcessSingleton(const FilePath& user_data_dir) 151 ProcessSingleton::ProcessSingleton(const FilePath& user_data_dir)
150 : window_(NULL), locked_(false), foreground_window_(NULL), 152 : window_(NULL), locked_(false), foreground_window_(NULL),
151 is_virtualized_(false) { 153 is_virtualized_(false), lock_file_(INVALID_HANDLE_VALUE) {
152 remote_window_ = FindWindowEx(HWND_MESSAGE, NULL, 154 remote_window_ = FindWindowEx(HWND_MESSAGE, NULL,
153 chrome::kMessageWindowClass, 155 chrome::kMessageWindowClass,
154 user_data_dir.value().c_str()); 156 user_data_dir.value().c_str());
155 if (!remote_window_ && !EscapeVirtualization(user_data_dir)) { 157 if (!remote_window_ && !EscapeVirtualization(user_data_dir)) {
156 // Make sure we will be the one and only process creating the window. 158 // Make sure we will be the one and only process creating the window.
157 // We use a named Mutex since we are protecting against multi-process 159 // We use a named Mutex since we are protecting against multi-process
158 // access. As documented, it's clearer to NOT request ownership on creation 160 // access. As documented, it's clearer to NOT request ownership on creation
159 // since it isn't guaranteed we will get it. It is better to create it 161 // since it isn't guaranteed we will get it. It is better to create it
160 // without ownership and explicitly get the ownership afterward. 162 // without ownership and explicitly get the ownership afterward.
161 std::wstring mutex_name(L"Local\\ChromeProcessSingletonStartup!"); 163 std::wstring mutex_name(L"Local\\ChromeProcessSingletonStartup!");
162 base::win::ScopedHandle only_me( 164 base::win::ScopedHandle only_me(
163 CreateMutex(NULL, FALSE, mutex_name.c_str())); 165 CreateMutex(NULL, FALSE, mutex_name.c_str()));
164 DCHECK(only_me.Get() != NULL) << "GetLastError = " << GetLastError(); 166 DCHECK(only_me.Get() != NULL) << "GetLastError = " << GetLastError();
165 167
166 // This is how we acquire the mutex (as opposed to the initial ownership). 168 // This is how we acquire the mutex (as opposed to the initial ownership).
167 DWORD result = WaitForSingleObject(only_me, INFINITE); 169 DWORD result = WaitForSingleObject(only_me, INFINITE);
168 DCHECK(result == WAIT_OBJECT_0) << "Result = " << result << 170 DCHECK(result == WAIT_OBJECT_0) << "Result = " << result <<
169 "GetLastError = " << GetLastError(); 171 "GetLastError = " << GetLastError();
170 172
171 // We now own the mutex so we are the only process that can create the 173 // We now own the mutex so we are the only process that can create the
172 // window at this time, but we must still check if someone created it 174 // window at this time, but we must still check if someone created it
173 // between the time where we looked for it above and the time the mutex 175 // between the time where we looked for it above and the time the mutex
174 // was given to us. 176 // was given to us.
175 remote_window_ = FindWindowEx(HWND_MESSAGE, NULL, 177 remote_window_ = FindWindowEx(HWND_MESSAGE, NULL,
176 chrome::kMessageWindowClass, 178 chrome::kMessageWindowClass,
177 user_data_dir.value().c_str()); 179 user_data_dir.value().c_str());
178 if (!remote_window_) { 180
181 // We have to make sure there is no Chrome instance running on another
182 // machine that uses the same profile.
183 FilePath lock_file_path = user_data_dir.AppendASCII(kLockfile);
184 lock_file_ = CreateFile(lock_file_path.value().c_str(),
185 GENERIC_WRITE,
186 FILE_SHARE_READ,
187 NULL,
188 CREATE_ALWAYS,
189 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE,
190 NULL);
191 DWORD error = GetLastError();
cpu_(ooo_6.6-7.5) 2012/07/16 20:36:31 this version I like better. Now for two local chro
pastarmovj 2012/07/16 21:17:53 For two local instances the first one will acquire
192 LOG_IF(WARNING, lock_file_ != INVALID_HANDLE_VALUE &&
193 error == ERROR_ALREADY_EXISTS) << "Lock file exists but is writable.";
194 LOG_IF(ERROR, lock_file_ == INVALID_HANDLE_VALUE)
195 << "Lock file can not be created! Error code: " << error;
196
197 if (!remote_window_ && lock_file_ != INVALID_HANDLE_VALUE) {
179 HINSTANCE hinst = base::GetModuleFromAddress(&ThunkWndProc); 198 HINSTANCE hinst = base::GetModuleFromAddress(&ThunkWndProc);
180 199
181 WNDCLASSEX wc = {0}; 200 WNDCLASSEX wc = {0};
182 wc.cbSize = sizeof(wc); 201 wc.cbSize = sizeof(wc);
183 wc.lpfnWndProc = base::win::WrappedWindowProc<ThunkWndProc>; 202 wc.lpfnWndProc = base::win::WrappedWindowProc<ThunkWndProc>;
184 wc.hInstance = hinst; 203 wc.hInstance = hinst;
185 wc.lpszClassName = chrome::kMessageWindowClass; 204 wc.lpszClassName = chrome::kMessageWindowClass;
186 ATOM clazz = ::RegisterClassEx(&wc); 205 ATOM clazz = ::RegisterClassEx(&wc);
187 DCHECK(clazz); 206 DCHECK(clazz);
188 207
(...skipping 11 matching lines...) Expand all
200 219
201 ProcessSingleton::~ProcessSingleton() { 220 ProcessSingleton::~ProcessSingleton() {
202 // We need to unregister the window as late as possible so that we can detect 221 // We need to unregister the window as late as possible so that we can detect
203 // another instance of chrome running. Otherwise we may end up writing out 222 // another instance of chrome running. Otherwise we may end up writing out
204 // data while a new chrome is starting up. 223 // data while a new chrome is starting up.
205 if (window_) { 224 if (window_) {
206 ::DestroyWindow(window_); 225 ::DestroyWindow(window_);
207 ::UnregisterClass(chrome::kMessageWindowClass, 226 ::UnregisterClass(chrome::kMessageWindowClass,
208 base::GetModuleFromAddress(&ThunkWndProc)); 227 base::GetModuleFromAddress(&ThunkWndProc));
209 } 228 }
229 if (lock_file_ != INVALID_HANDLE_VALUE)
230 CloseHandle(lock_file_);
210 } 231 }
211 232
212 ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcess() { 233 ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcess() {
213 if (is_virtualized_) 234 if (is_virtualized_)
214 return PROCESS_NOTIFIED; // We already spawned the process in this case. 235 return PROCESS_NOTIFIED; // We already spawned the process in this case.
236 if (lock_file_ == INVALID_HANDLE_VALUE && !remote_window_)
237 return LOCK_ERROR;
215 else if (!remote_window_) 238 else if (!remote_window_)
216 return PROCESS_NONE; 239 return PROCESS_NONE;
217 240
218 // Found another window, send our command line to it 241 // Found another window, send our command line to it
219 // format is "START\0<<<current directory>>>\0<<<commandline>>>". 242 // format is "START\0<<<current directory>>>\0<<<commandline>>>".
220 std::wstring to_send(L"START\0", 6); // want the NULL in the string. 243 std::wstring to_send(L"START\0", 6); // want the NULL in the string.
221 FilePath cur_dir; 244 FilePath cur_dir;
222 if (!PathService::Get(base::DIR_CURRENT, &cur_dir)) 245 if (!PathService::Get(base::DIR_CURRENT, &cur_dir))
223 return PROCESS_NONE; 246 return PROCESS_NONE;
224 to_send.append(cur_dir.value()); 247 to_send.append(cur_dir.value());
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 switch (message) { 370 switch (message) {
348 case WM_COPYDATA: 371 case WM_COPYDATA:
349 return OnCopyData(reinterpret_cast<HWND>(wparam), 372 return OnCopyData(reinterpret_cast<HWND>(wparam),
350 reinterpret_cast<COPYDATASTRUCT*>(lparam)); 373 reinterpret_cast<COPYDATASTRUCT*>(lparam));
351 default: 374 default:
352 break; 375 break;
353 } 376 }
354 377
355 return ::DefWindowProc(hwnd, message, wparam, lparam); 378 return ::DefWindowProc(hwnd, message, wparam, lparam);
356 } 379 }
OLDNEW
« no previous file with comments | « chrome/browser/process_singleton.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698