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

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

Issue 9121046: Cleanup in ProcessSingleton. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Merge to LKGR. Created 8 years, 10 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 | « base/process_util_win.cc ('k') | chrome_frame/buggy_bho_handling.cc » ('j') | 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"
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 break; 84 break;
85 } 85 }
86 ::Sleep(10); 86 ::Sleep(10);
87 } 87 }
88 return true; 88 return true;
89 } 89 }
90 return false; 90 return false;
91 } 91 }
92 92
93 // Look for a Chrome instance that uses the same profile directory. 93 // Look for a Chrome instance that uses the same profile directory.
94 // If there isn't one, create a message window with its title set to
95 // the profile directory path.
94 ProcessSingleton::ProcessSingleton(const FilePath& user_data_dir) 96 ProcessSingleton::ProcessSingleton(const FilePath& user_data_dir)
95 : window_(NULL), locked_(false), foreground_window_(NULL), 97 : window_(NULL), locked_(false), foreground_window_(NULL),
96 is_virtualized_(false) { 98 is_virtualized_(false) {
97 remote_window_ = FindWindowEx(HWND_MESSAGE, NULL, 99 remote_window_ = FindWindowEx(HWND_MESSAGE, NULL,
98 chrome::kMessageWindowClass, 100 chrome::kMessageWindowClass,
99 user_data_dir.value().c_str()); 101 user_data_dir.value().c_str());
100 if (!remote_window_ && !EscapeVirtualization(user_data_dir)) { 102 if (!remote_window_ && !EscapeVirtualization(user_data_dir)) {
101 // Make sure we will be the one and only process creating the window. 103 // Make sure we will be the one and only process creating the window.
102 // We use a named Mutex since we are protecting against multi-process 104 // We use a named Mutex since we are protecting against multi-process
103 // access. As documented, it's clearer to NOT request ownership on creation 105 // access. As documented, it's clearer to NOT request ownership on creation
104 // since it isn't guaranteed we will get it. It is better to create it 106 // since it isn't guaranteed we will get it. It is better to create it
105 // without ownership and explicitly get the ownership afterward. 107 // without ownership and explicitly get the ownership afterward.
106 std::wstring mutex_name(L"Local\\ChromeProcessSingletonStartup!"); 108 std::wstring mutex_name(L"Local\\ChromeProcessSingletonStartup!");
107 base::win::ScopedHandle only_me( 109 base::win::ScopedHandle only_me(
108 CreateMutex(NULL, FALSE, mutex_name.c_str())); 110 CreateMutex(NULL, FALSE, mutex_name.c_str()));
109 DCHECK(only_me.Get() != NULL) << "GetLastError = " << GetLastError(); 111 DCHECK(only_me.Get() != NULL) << "GetLastError = " << GetLastError();
110 112
111 // This is how we acquire the mutex (as opposed to the initial ownership). 113 // This is how we acquire the mutex (as opposed to the initial ownership).
112 DWORD result = WaitForSingleObject(only_me, INFINITE); 114 DWORD result = WaitForSingleObject(only_me, INFINITE);
113 DCHECK(result == WAIT_OBJECT_0) << "Result = " << result << 115 DCHECK(result == WAIT_OBJECT_0) << "Result = " << result <<
114 "GetLastError = " << GetLastError(); 116 "GetLastError = " << GetLastError();
115 117
116 // We now own the mutex so we are the only process that can create the 118 // We now own the mutex so we are the only process that can create the
117 // window at this time, but we must still check if someone created it 119 // window at this time, but we must still check if someone created it
118 // between the time where we looked for it above and the time the mutex 120 // between the time where we looked for it above and the time the mutex
119 // was given to us. 121 // was given to us.
120 remote_window_ = FindWindowEx(HWND_MESSAGE, NULL, 122 remote_window_ = FindWindowEx(HWND_MESSAGE, NULL,
121 chrome::kMessageWindowClass, 123 chrome::kMessageWindowClass,
122 user_data_dir.value().c_str()); 124 user_data_dir.value().c_str());
123 if (!remote_window_) 125 if (!remote_window_) {
124 Create(); 126 HINSTANCE hinst = base::GetModuleFromAddress(&ThunkWndProc);
127
128 WNDCLASSEX wc = {0};
129 wc.cbSize = sizeof(wc);
130 wc.lpfnWndProc = base::win::WrappedWindowProc<ThunkWndProc>;
131 wc.hInstance = hinst;
132 wc.lpszClassName = chrome::kMessageWindowClass;
133 ATOM clazz = ::RegisterClassEx(&wc);
134 DCHECK(clazz);
135
136 FilePath user_data_dir;
137 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
138
139 // Set the window's title to the path of our user data directory so other
140 // Chrome instances can decide if they should forward to us or not.
141 window_ = ::CreateWindow(MAKEINTATOM(clazz),
142 user_data_dir.value().c_str(),
143 0, 0, 0, 0, 0, HWND_MESSAGE, 0, hinst, this);
144 CHECK(window_);
145 }
125 BOOL success = ReleaseMutex(only_me); 146 BOOL success = ReleaseMutex(only_me);
126 DCHECK(success) << "GetLastError = " << GetLastError(); 147 DCHECK(success) << "GetLastError = " << GetLastError();
127 } 148 }
128 } 149 }
129 150
130 ProcessSingleton::~ProcessSingleton() { 151 ProcessSingleton::~ProcessSingleton() {
131 if (window_) { 152 Cleanup();
132 ::DestroyWindow(window_);
133 ::UnregisterClass(chrome::kMessageWindowClass, GetModuleHandle(NULL));
134 }
135 } 153 }
136 154
137 ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcess() { 155 ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcess() {
138 if (is_virtualized_) 156 if (is_virtualized_)
139 return PROCESS_NOTIFIED; // We already spawned the process in this case. 157 return PROCESS_NOTIFIED; // We already spawned the process in this case.
140 else if (!remote_window_) 158 else if (!remote_window_)
141 return PROCESS_NONE; 159 return PROCESS_NONE;
142 160
143 // Found another window, send our command line to it 161 // Found another window, send our command line to it
144 // format is "START\0<<<current directory>>>\0<<<commandline>>>". 162 // format is "START\0<<<current directory>>>\0<<<commandline>>>".
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 // Time to take action. Kill the browser process. 226 // Time to take action. Kill the browser process.
209 base::KillProcessById(process_id, content::RESULT_CODE_HUNG, true); 227 base::KillProcessById(process_id, content::RESULT_CODE_HUNG, true);
210 remote_window_ = NULL; 228 remote_window_ = NULL;
211 return PROCESS_NONE; 229 return PROCESS_NONE;
212 } 230 }
213 231
214 ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessOrCreate() { 232 ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessOrCreate() {
215 NotifyResult result = NotifyOtherProcess(); 233 NotifyResult result = NotifyOtherProcess();
216 if (result != PROCESS_NONE) 234 if (result != PROCESS_NONE)
217 return result; 235 return result;
218 return Create() ? PROCESS_NONE : PROFILE_IN_USE; 236 return window_ ? PROCESS_NONE : PROFILE_IN_USE;
219 } 237 }
220 238
221 // For windows, there is no need to call Create() since the call is made in 239 // On Windows, there is no need to call Create() since the message
222 // the constructor but to avoid having more platform specific code in 240 // window is created in the constructor but to avoid having more
223 // browser_main.cc we tolerate a second call which will do nothing. 241 // platform specific code in browser_main.cc we tolerate calls to
242 // Create(), which will do nothing.
224 bool ProcessSingleton::Create() { 243 bool ProcessSingleton::Create() {
225 DCHECK(!remote_window_); 244 DCHECK(!remote_window_);
226 if (window_) 245 return window_ != NULL;
227 return true;
228
229 HINSTANCE hinst = 0;
230 if (!::GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
231 reinterpret_cast<char*>(&ThunkWndProc),
232 &hinst)) {
233 NOTREACHED();
234 }
235
236 WNDCLASSEX wc = {0};
237 wc.cbSize = sizeof(wc);
238 wc.lpfnWndProc = base::win::WrappedWindowProc<ThunkWndProc>;
239 wc.hInstance = hinst;
240 wc.lpszClassName = chrome::kMessageWindowClass;
241 ATOM clazz = ::RegisterClassEx(&wc);
242 DCHECK(clazz);
243
244 FilePath user_data_dir;
245 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
246
247 // Set the window's title to the path of our user data directory so other
248 // Chrome instances can decide if they should forward to us or not.
249 window_ = ::CreateWindow(MAKEINTATOM(clazz),
250 user_data_dir.value().c_str(),
251 0, 0, 0, 0, 0, HWND_MESSAGE, 0, hinst, this);
252 CHECK(window_);
253 return true;
254 } 246 }
255 247
256 void ProcessSingleton::Cleanup() { 248 void ProcessSingleton::Cleanup() {
249 // Window classes registered by DLLs are not cleaned up automatically on
250 // process exit, so we must unregister at the earliest chance possible.
251 // During the fast shutdown sequence, ProcessSingleton::Cleanup() is
252 // called if our process was the first to start. Therefore we try cleaning
253 // up here, and again in the destructor if needed to catch as many cases
254 // as possible.
255 if (window_) {
256 ::DestroyWindow(window_);
257 ::UnregisterClass(chrome::kMessageWindowClass,
258 base::GetModuleFromAddress(&ThunkWndProc));
259 window_ = NULL;
260 }
257 } 261 }
258 262
259 LRESULT ProcessSingleton::OnCopyData(HWND hwnd, const COPYDATASTRUCT* cds) { 263 LRESULT ProcessSingleton::OnCopyData(HWND hwnd, const COPYDATASTRUCT* cds) {
260 // If locked, it means we are not ready to process this message because 264 // If locked, it means we are not ready to process this message because
261 // we are probably in a first run critical phase. 265 // we are probably in a first run critical phase.
262 if (locked_) { 266 if (locked_) {
263 #if defined(USE_AURA) 267 #if defined(USE_AURA)
264 NOTIMPLEMENTED(); 268 NOTIMPLEMENTED();
265 #else 269 #else
266 // Attempt to place ourselves in the foreground / flash the task bar. 270 // Attempt to place ourselves in the foreground / flash the task bar.
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
366 switch (message) { 370 switch (message) {
367 case WM_COPYDATA: 371 case WM_COPYDATA:
368 return OnCopyData(reinterpret_cast<HWND>(wparam), 372 return OnCopyData(reinterpret_cast<HWND>(wparam),
369 reinterpret_cast<COPYDATASTRUCT*>(lparam)); 373 reinterpret_cast<COPYDATASTRUCT*>(lparam));
370 default: 374 default:
371 break; 375 break;
372 } 376 }
373 377
374 return ::DefWindowProc(hwnd, message, wparam, lparam); 378 return ::DefWindowProc(hwnd, message, wparam, lparam);
375 } 379 }
OLDNEW
« no previous file with comments | « base/process_util_win.cc ('k') | chrome_frame/buggy_bho_handling.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698