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 #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/browser_process.h" | |
16 #include "chrome/browser/extensions/extensions_startup.h" | |
17 #include "chrome/browser/profiles/profile.h" | |
18 #include "chrome/browser/profiles/profile_manager.h" | |
19 #include "chrome/browser/simple_message_box.h" | 15 #include "chrome/browser/simple_message_box.h" |
20 #include "chrome/browser/ui/browser_init.h" | |
21 #include "chrome/common/chrome_constants.h" | 16 #include "chrome/common/chrome_constants.h" |
22 #include "chrome/common/chrome_paths.h" | |
23 #include "chrome/common/chrome_switches.h" | |
24 #include "chrome/installer/util/wmi.h" | 17 #include "chrome/installer/util/wmi.h" |
25 #include "content/public/common/result_codes.h" | 18 #include "content/public/common/result_codes.h" |
26 #include "grit/chromium_strings.h" | 19 #include "grit/chromium_strings.h" |
27 #include "grit/generated_resources.h" | 20 #include "grit/generated_resources.h" |
28 #include "ui/base/l10n/l10n_util.h" | 21 #include "ui/base/l10n/l10n_util.h" |
29 #include "ui/base/win/hwnd_util.h" | 22 #include "ui/base/win/hwnd_util.h" |
30 | 23 |
31 namespace { | 24 namespace { |
32 | 25 |
33 // Checks the visibility of the enumerated window and signals once a visible | 26 // Checks the visibility of the enumerated window and signals once a visible |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 HINSTANCE hinst = base::GetModuleFromAddress(&ThunkWndProc); | 179 HINSTANCE hinst = base::GetModuleFromAddress(&ThunkWndProc); |
187 | 180 |
188 WNDCLASSEX wc = {0}; | 181 WNDCLASSEX wc = {0}; |
189 wc.cbSize = sizeof(wc); | 182 wc.cbSize = sizeof(wc); |
190 wc.lpfnWndProc = base::win::WrappedWindowProc<ThunkWndProc>; | 183 wc.lpfnWndProc = base::win::WrappedWindowProc<ThunkWndProc>; |
191 wc.hInstance = hinst; | 184 wc.hInstance = hinst; |
192 wc.lpszClassName = chrome::kMessageWindowClass; | 185 wc.lpszClassName = chrome::kMessageWindowClass; |
193 ATOM clazz = ::RegisterClassEx(&wc); | 186 ATOM clazz = ::RegisterClassEx(&wc); |
194 DCHECK(clazz); | 187 DCHECK(clazz); |
195 | 188 |
196 FilePath user_data_dir; | |
197 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); | |
198 | |
199 // Set the window's title to the path of our user data directory so other | 189 // Set the window's title to the path of our user data directory so other |
200 // Chrome instances can decide if they should forward to us or not. | 190 // Chrome instances can decide if they should forward to us or not. |
201 window_ = ::CreateWindow(MAKEINTATOM(clazz), | 191 window_ = ::CreateWindow(MAKEINTATOM(clazz), |
202 user_data_dir.value().c_str(), | 192 user_data_dir.value().c_str(), |
203 0, 0, 0, 0, 0, HWND_MESSAGE, 0, hinst, this); | 193 0, 0, 0, 0, 0, HWND_MESSAGE, 0, hinst, this); |
204 CHECK(window_); | 194 CHECK(window_); |
205 } | 195 } |
206 BOOL success = ReleaseMutex(only_me); | 196 BOOL success = ReleaseMutex(only_me); |
207 DCHECK(success) << "GetLastError = " << GetLastError(); | 197 DCHECK(success) << "GetLastError = " << GetLastError(); |
208 } | 198 } |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 return PROCESS_NOTIFIED; | 272 return PROCESS_NOTIFIED; |
283 } | 273 } |
284 } | 274 } |
285 | 275 |
286 // Time to take action. Kill the browser process. | 276 // Time to take action. Kill the browser process. |
287 base::KillProcessById(process_id, content::RESULT_CODE_HUNG, true); | 277 base::KillProcessById(process_id, content::RESULT_CODE_HUNG, true); |
288 remote_window_ = NULL; | 278 remote_window_ = NULL; |
289 return PROCESS_NONE; | 279 return PROCESS_NONE; |
290 } | 280 } |
291 | 281 |
292 ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessOrCreate() { | 282 ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessOrCreate( |
| 283 const NotificationCallback& notification_callback) { |
293 NotifyResult result = NotifyOtherProcess(); | 284 NotifyResult result = NotifyOtherProcess(); |
294 if (result != PROCESS_NONE) | 285 if (result != PROCESS_NONE) |
295 return result; | 286 return result; |
296 return window_ ? PROCESS_NONE : PROFILE_IN_USE; | 287 return Create(notification_callback) ? PROCESS_NONE : PROFILE_IN_USE; |
297 } | 288 } |
298 | 289 |
299 // On Windows, there is no need to call Create() since the message | 290 // On Windows, there is no need to call Create() since the message |
300 // window is created in the constructor but to avoid having more | 291 // window is created in the constructor but to avoid having more |
301 // platform specific code in browser_main.cc we tolerate calls to | 292 // platform specific code in browser_main.cc we tolerate calls to |
302 // Create(), which will do nothing. | 293 // Create(). |
303 bool ProcessSingleton::Create() { | 294 bool ProcessSingleton::Create( |
| 295 const NotificationCallback& notification_callback) { |
304 DCHECK(!remote_window_); | 296 DCHECK(!remote_window_); |
| 297 DCHECK(notification_callback_.is_null()); |
| 298 |
| 299 if (window_ != NULL) |
| 300 notification_callback_ = notification_callback; |
| 301 |
305 return window_ != NULL; | 302 return window_ != NULL; |
306 } | 303 } |
307 | 304 |
308 void ProcessSingleton::Cleanup() { | 305 void ProcessSingleton::Cleanup() { |
309 // Window classes registered by DLLs are not cleaned up automatically on | 306 // Window classes registered by DLLs are not cleaned up automatically on |
310 // process exit, so we must unregister at the earliest chance possible. | 307 // process exit, so we must unregister at the earliest chance possible. |
311 // During the fast shutdown sequence, ProcessSingleton::Cleanup() is | 308 // During the fast shutdown sequence, ProcessSingleton::Cleanup() is |
312 // called if our process was the first to start. Therefore we try cleaning | 309 // called if our process was the first to start. Therefore we try cleaning |
313 // up here, and again in the destructor if needed to catch as many cases | 310 // up here, and again in the destructor if needed to catch as many cases |
314 // as possible. | 311 // as possible. |
(...skipping 21 matching lines...) Expand all Loading... |
336 CommandLine parsed_command_line(CommandLine::NO_PROGRAM); | 333 CommandLine parsed_command_line(CommandLine::NO_PROGRAM); |
337 FilePath current_directory; | 334 FilePath current_directory; |
338 if (ParseCommandLine(cds, &parsed_command_line, ¤t_directory)) | 335 if (ParseCommandLine(cds, &parsed_command_line, ¤t_directory)) |
339 saved_startup_messages_.push_back( | 336 saved_startup_messages_.push_back( |
340 std::make_pair(parsed_command_line.argv(), current_directory)); | 337 std::make_pair(parsed_command_line.argv(), current_directory)); |
341 } | 338 } |
342 #endif | 339 #endif |
343 return TRUE; | 340 return TRUE; |
344 } | 341 } |
345 | 342 |
346 // Ignore the request if the browser process is already in shutdown path. | |
347 if (!g_browser_process || g_browser_process->IsShuttingDown()) { | |
348 LOG(WARNING) << "Not handling WM_COPYDATA as browser is shutting down"; | |
349 return FALSE; | |
350 } | |
351 | |
352 CommandLine parsed_command_line(CommandLine::NO_PROGRAM); | 343 CommandLine parsed_command_line(CommandLine::NO_PROGRAM); |
353 FilePath current_directory; | 344 FilePath current_directory; |
354 if (!ParseCommandLine(cds, &parsed_command_line, ¤t_directory)) | 345 if (!ParseCommandLine(cds, &parsed_command_line, ¤t_directory)) |
355 return TRUE; | 346 return TRUE; |
356 ProcessCommandLine(parsed_command_line, current_directory); | 347 return notification_callback_.Run(parsed_command_line, current_directory) ? |
357 return TRUE; | 348 TRUE : FALSE; |
358 } | 349 } |
359 | 350 |
360 LRESULT ProcessSingleton::WndProc(HWND hwnd, UINT message, | 351 LRESULT ProcessSingleton::WndProc(HWND hwnd, UINT message, |
361 WPARAM wparam, LPARAM lparam) { | 352 WPARAM wparam, LPARAM lparam) { |
362 switch (message) { | 353 switch (message) { |
363 case WM_COPYDATA: | 354 case WM_COPYDATA: |
364 return OnCopyData(reinterpret_cast<HWND>(wparam), | 355 return OnCopyData(reinterpret_cast<HWND>(wparam), |
365 reinterpret_cast<COPYDATASTRUCT*>(lparam)); | 356 reinterpret_cast<COPYDATASTRUCT*>(lparam)); |
366 default: | 357 default: |
367 break; | 358 break; |
368 } | 359 } |
369 | 360 |
370 return ::DefWindowProc(hwnd, message, wparam, lparam); | 361 return ::DefWindowProc(hwnd, message, wparam, lparam); |
371 } | 362 } |
372 | |
373 void ProcessSingleton::ProcessCommandLine(const CommandLine& command_line, | |
374 const FilePath& current_directory) { | |
375 PrefService* prefs = g_browser_process->local_state(); | |
376 DCHECK(prefs); | |
377 | |
378 // Handle the --uninstall-extension startup action. This needs to done here | |
379 // in the process that is running with the target profile, otherwise the | |
380 // uninstall will fail to unload and remove all components. | |
381 if (command_line.HasSwitch(switches::kUninstallExtension)) { | |
382 // The uninstall extension switch can't be combined with the profile | |
383 // directory switch. | |
384 DCHECK(!command_line.HasSwitch(switches::kProfileDirectory)); | |
385 | |
386 Profile* profile = ProfileManager::GetLastUsedProfile(); | |
387 if (!profile) { | |
388 // We should only be able to get here if the profile already exists and | |
389 // has been created. | |
390 NOTREACHED(); | |
391 return; | |
392 } | |
393 | |
394 ExtensionsStartupUtil ext_startup_util; | |
395 ext_startup_util.UninstallExtension(command_line, profile); | |
396 return; | |
397 } | |
398 | |
399 // Run the browser startup sequence again, with the command line of the | |
400 // signalling process. | |
401 BrowserInit::ProcessCommandLineAlreadyRunning(command_line, | |
402 current_directory); | |
403 } | |
OLD | NEW |