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

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

Issue 17615003: ProcessSingleton now uses base::win::MessageWindow to create a message-only window. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: CR feedback. Created 7 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') | chrome/common/chrome_constants.h » ('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 <shellapi.h> 7 #include <shellapi.h>
8 8
9 #include "base/base_paths.h" 9 #include "base/base_paths.h"
10 #include "base/bind.h"
10 #include "base/command_line.h" 11 #include "base/command_line.h"
11 #include "base/files/file_path.h" 12 #include "base/files/file_path.h"
12 #include "base/path_service.h" 13 #include "base/path_service.h"
13 #include "base/process_info.h" 14 #include "base/process_info.h"
14 #include "base/process_util.h" 15 #include "base/process_util.h"
15 #include "base/strings/string_number_conversions.h" 16 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/stringprintf.h" 17 #include "base/strings/stringprintf.h"
17 #include "base/strings/utf_string_conversions.h" 18 #include "base/strings/utf_string_conversions.h"
18 #include "base/time.h" 19 #include "base/time.h"
19 #include "base/win/metro.h" 20 #include "base/win/metro.h"
20 #include "base/win/registry.h" 21 #include "base/win/registry.h"
21 #include "base/win/scoped_handle.h" 22 #include "base/win/scoped_handle.h"
22 #include "base/win/win_util.h" 23 #include "base/win/win_util.h"
23 #include "base/win/windows_version.h" 24 #include "base/win/windows_version.h"
24 #include "base/win/wrapped_window_proc.h"
25 #include "chrome/browser/browser_process.h" 25 #include "chrome/browser/browser_process.h"
26 #include "chrome/browser/browser_process_platform_part.h" 26 #include "chrome/browser/browser_process_platform_part.h"
27 #include "chrome/browser/chrome_process_finder_win.h" 27 #include "chrome/browser/chrome_process_finder_win.h"
28 #include "chrome/browser/metro_utils/metro_chrome_win.h" 28 #include "chrome/browser/metro_utils/metro_chrome_win.h"
29 #include "chrome/browser/shell_integration.h" 29 #include "chrome/browser/shell_integration.h"
30 #include "chrome/browser/ui/simple_message_box.h" 30 #include "chrome/browser/ui/simple_message_box.h"
31 #include "chrome/common/chrome_constants.h" 31 #include "chrome/common/chrome_constants.h"
32 #include "chrome/common/chrome_paths.h" 32 #include "chrome/common/chrome_paths.h"
33 #include "chrome/common/chrome_paths_internal.h" 33 #include "chrome/common/chrome_paths_internal.h"
34 #include "chrome/common/chrome_switches.h" 34 #include "chrome/common/chrome_switches.h"
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 86
87 // Checks the visibility of the enumerated window and signals once a visible 87 // Checks the visibility of the enumerated window and signals once a visible
88 // window has been found. 88 // window has been found.
89 BOOL CALLBACK BrowserWindowEnumeration(HWND window, LPARAM param) { 89 BOOL CALLBACK BrowserWindowEnumeration(HWND window, LPARAM param) {
90 bool* result = reinterpret_cast<bool*>(param); 90 bool* result = reinterpret_cast<bool*>(param);
91 *result = ::IsWindowVisible(window) != 0; 91 *result = ::IsWindowVisible(window) != 0;
92 // Stops enumeration if a visible window has been found. 92 // Stops enumeration if a visible window has been found.
93 return !*result; 93 return !*result;
94 } 94 }
95 95
96 // This function thunks to the object's version of the windowproc, taking in
97 // consideration that there are several messages being dispatched before
98 // WM_NCCREATE which we let windows handle.
99 LRESULT CALLBACK ThunkWndProc(HWND hwnd, UINT message,
100 WPARAM wparam, LPARAM lparam) {
101 ProcessSingleton* singleton =
102 reinterpret_cast<ProcessSingleton*>(ui::GetWindowUserData(hwnd));
103 if (message == WM_NCCREATE) {
104 CREATESTRUCT* cs = reinterpret_cast<CREATESTRUCT*>(lparam);
105 singleton = reinterpret_cast<ProcessSingleton*>(cs->lpCreateParams);
106 CHECK(singleton);
107 ui::SetWindowUserData(hwnd, singleton);
108 } else if (!singleton) {
109 return ::DefWindowProc(hwnd, message, wparam, lparam);
110 }
111 return singleton->WndProc(hwnd, message, wparam, lparam);
112 }
113
114 bool ParseCommandLine(const COPYDATASTRUCT* cds, 96 bool ParseCommandLine(const COPYDATASTRUCT* cds,
115 CommandLine* parsed_command_line, 97 CommandLine* parsed_command_line,
116 base::FilePath* current_directory) { 98 base::FilePath* current_directory) {
117 // We should have enough room for the shortest command (min_message_size) 99 // We should have enough room for the shortest command (min_message_size)
118 // and also be a multiple of wchar_t bytes. The shortest command 100 // and also be a multiple of wchar_t bytes. The shortest command
119 // possible is L"START\0\0" (empty current directory and command line). 101 // possible is L"START\0\0" (empty current directory and command line).
120 static const int min_message_size = 7; 102 static const int min_message_size = 7;
121 if (cds->cbData < min_message_size * sizeof(wchar_t) || 103 if (cds->cbData < min_message_size * sizeof(wchar_t) ||
122 cds->cbData % sizeof(wchar_t) != 0) { 104 cds->cbData % sizeof(wchar_t) != 0) {
123 LOG(WARNING) << "Invalid WM_COPYDATA, length = " << cds->cbData; 105 LOG(WARNING) << "Invalid WM_COPYDATA, length = " << cds->cbData;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 146
165 // Get command line. 147 // Get command line.
166 const std::wstring cmd_line = 148 const std::wstring cmd_line =
167 msg.substr(second_null + 1, third_null - second_null); 149 msg.substr(second_null + 1, third_null - second_null);
168 *parsed_command_line = CommandLine::FromString(cmd_line); 150 *parsed_command_line = CommandLine::FromString(cmd_line);
169 return true; 151 return true;
170 } 152 }
171 return false; 153 return false;
172 } 154 }
173 155
156 bool ProcessLaunchNotification(
157 const ProcessSingleton::NotificationCallback& notification_callback,
158 UINT message,
159 WPARAM wparam,
160 LPARAM lparam,
161 LRESULT* result) {
162 if (message != WM_COPYDATA)
163 return false;
164
165 // Handle the WM_COPYDATA message from another process.
166 HWND hwnd = reinterpret_cast<HWND>(wparam);
167 const COPYDATASTRUCT* cds = reinterpret_cast<COPYDATASTRUCT*>(lparam);
168
169 CommandLine parsed_command_line(CommandLine::NO_PROGRAM);
170 base::FilePath current_directory;
171 if (!ParseCommandLine(cds, &parsed_command_line, &current_directory)) {
172 *result = TRUE;
173 return true;
174 }
175
176 *result = notification_callback.Run(parsed_command_line, current_directory) ?
177 TRUE : FALSE;
178 return true;
179 }
180
174 // Returns true if Chrome needs to be relaunched into Windows 8 immersive mode. 181 // Returns true if Chrome needs to be relaunched into Windows 8 immersive mode.
175 // Following conditions apply:- 182 // Following conditions apply:-
176 // 1. Windows 8 or greater. 183 // 1. Windows 8 or greater.
177 // 2. Not in Windows 8 immersive mode. 184 // 2. Not in Windows 8 immersive mode.
178 // 3. Chrome is default browser. 185 // 3. Chrome is default browser.
179 // 4. Process integrity level is not high. 186 // 4. Process integrity level is not high.
180 // 5. The profile data directory is the default directory. 187 // 5. The profile data directory is the default directory.
181 // 6. Last used mode was immersive/machine is a tablet. 188 // 6. Last used mode was immersive/machine is a tablet.
182 // TODO(ananta) 189 // TODO(ananta)
183 // Move this function to a common place as the Windows 8 delegate_execute 190 // Move this function to a common place as the Windows 8 delegate_execute
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 ::Sleep(10); 260 ::Sleep(10);
254 } 261 }
255 return true; 262 return true;
256 } 263 }
257 return false; 264 return false;
258 } 265 }
259 266
260 ProcessSingleton::ProcessSingleton( 267 ProcessSingleton::ProcessSingleton(
261 const base::FilePath& user_data_dir, 268 const base::FilePath& user_data_dir,
262 const NotificationCallback& notification_callback) 269 const NotificationCallback& notification_callback)
263 : window_(NULL), notification_callback_(notification_callback), 270 : notification_callback_(notification_callback),
264 is_virtualized_(false), lock_file_(INVALID_HANDLE_VALUE), 271 is_virtualized_(false), lock_file_(INVALID_HANDLE_VALUE),
265 user_data_dir_(user_data_dir) { 272 user_data_dir_(user_data_dir) {
266 } 273 }
267 274
268 ProcessSingleton::~ProcessSingleton() { 275 ProcessSingleton::~ProcessSingleton() {
269 // We need to unregister the window as late as possible so that we can detect
270 // another instance of chrome running. Otherwise we may end up writing out
271 // data while a new chrome is starting up.
272 if (window_) {
273 ::DestroyWindow(window_);
274 ::UnregisterClass(chrome::kMessageWindowClass,
275 base::GetModuleFromAddress(&ThunkWndProc));
276 }
277 if (lock_file_ != INVALID_HANDLE_VALUE) 276 if (lock_file_ != INVALID_HANDLE_VALUE)
278 ::CloseHandle(lock_file_); 277 ::CloseHandle(lock_file_);
279 } 278 }
280 279
281 // Code roughly based on Mozilla. 280 // Code roughly based on Mozilla.
282 ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcess() { 281 ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcess() {
283 if (is_virtualized_) 282 if (is_virtualized_)
284 return PROCESS_NOTIFIED; // We already spawned the process in this case. 283 return PROCESS_NOTIFIED; // We already spawned the process in this case.
285 if (lock_file_ == INVALID_HANDLE_VALUE && !remote_window_) { 284 if (lock_file_ == INVALID_HANDLE_VALUE && !remote_window_) {
286 return LOCK_ERROR; 285 return LOCK_ERROR;
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
432 FILE_ATTRIBUTE_NORMAL | 431 FILE_ATTRIBUTE_NORMAL |
433 FILE_FLAG_DELETE_ON_CLOSE, 432 FILE_FLAG_DELETE_ON_CLOSE,
434 NULL); 433 NULL);
435 DWORD error = ::GetLastError(); 434 DWORD error = ::GetLastError();
436 LOG_IF(WARNING, lock_file_ != INVALID_HANDLE_VALUE && 435 LOG_IF(WARNING, lock_file_ != INVALID_HANDLE_VALUE &&
437 error == ERROR_ALREADY_EXISTS) << "Lock file exists but is writable."; 436 error == ERROR_ALREADY_EXISTS) << "Lock file exists but is writable.";
438 LOG_IF(ERROR, lock_file_ == INVALID_HANDLE_VALUE) 437 LOG_IF(ERROR, lock_file_ == INVALID_HANDLE_VALUE)
439 << "Lock file can not be created! Error code: " << error; 438 << "Lock file can not be created! Error code: " << error;
440 439
441 if (lock_file_ != INVALID_HANDLE_VALUE) { 440 if (lock_file_ != INVALID_HANDLE_VALUE) {
442 HINSTANCE hinst = base::GetModuleFromAddress(&ThunkWndProc);
443
444 WNDCLASSEX wc = {0};
445 wc.cbSize = sizeof(wc);
446 wc.lpfnWndProc = base::win::WrappedWindowProc<ThunkWndProc>;
447 wc.hInstance = hinst;
448 wc.lpszClassName = chrome::kMessageWindowClass;
449 ATOM clazz = ::RegisterClassEx(&wc);
450 DCHECK(clazz);
451
452 // Set the window's title to the path of our user data directory so 441 // Set the window's title to the path of our user data directory so
453 // other Chrome instances can decide if they should forward to us. 442 // other Chrome instances can decide if they should forward to us.
454 window_ = ::CreateWindow(MAKEINTATOM(clazz), 443 bool result = window_.CreateNamed(
455 user_data_dir_.value().c_str(), 444 base::Bind(&ProcessLaunchNotification, notification_callback_),
456 0, 0, 0, 0, 0, HWND_MESSAGE, 0, hinst, this); 445 user_data_dir_.value());
457 CHECK(window_); 446 CHECK(result && window_.hwnd());
458 } 447 }
459 448
460 if (base::win::GetVersion() >= base::win::VERSION_WIN8) { 449 if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
461 // Make sure no one is still waiting on Metro activation whether it 450 // Make sure no one is still waiting on Metro activation whether it
462 // succeeded (i.e., this is the Metro process) or failed. 451 // succeeded (i.e., this is the Metro process) or failed.
463 base::win::ScopedHandle metro_activation_event( 452 base::win::ScopedHandle metro_activation_event(
464 ::OpenEvent(EVENT_MODIFY_STATE, FALSE, kMetroActivationEventName)); 453 ::OpenEvent(EVENT_MODIFY_STATE, FALSE, kMetroActivationEventName));
465 if (metro_activation_event.IsValid()) 454 if (metro_activation_event.IsValid())
466 ::SetEvent(metro_activation_event); 455 ::SetEvent(metro_activation_event);
467 } 456 }
468 } 457 }
469 } 458 }
470 459
471 return window_ != NULL; 460 return window_.hwnd() != NULL;
472 } 461 }
473 462
474 void ProcessSingleton::Cleanup() { 463 void ProcessSingleton::Cleanup() {
475 } 464 }
476
477 LRESULT ProcessSingleton::OnCopyData(HWND hwnd, const COPYDATASTRUCT* cds) {
478 CommandLine parsed_command_line(CommandLine::NO_PROGRAM);
479 base::FilePath current_directory;
480 if (!ParseCommandLine(cds, &parsed_command_line, &current_directory))
481 return TRUE;
482 return notification_callback_.Run(parsed_command_line, current_directory) ?
483 TRUE : FALSE;
484 }
485
486 LRESULT ProcessSingleton::WndProc(HWND hwnd, UINT message,
487 WPARAM wparam, LPARAM lparam) {
488 switch (message) {
489 case WM_COPYDATA:
490 return OnCopyData(reinterpret_cast<HWND>(wparam),
491 reinterpret_cast<COPYDATASTRUCT*>(lparam));
492 default:
493 break;
494 }
495
496 return ::DefWindowProc(hwnd, message, wparam, lparam);
497 }
OLDNEW
« no previous file with comments | « chrome/browser/process_singleton.h ('k') | chrome/common/chrome_constants.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698