Fix attempt for the double-SessionRestoreImpl problem.
The problem is that BrowserInit::ProcessCommandLineAlreadyRunning gets called too
early, before launching the first profile during normal startup.
BUG=111238
TEST=NONE
Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=122065
Review URL: https://chromiumcodereview.appspot.com/9365049
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@123209 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/process_singleton_win.cc b/chrome/browser/process_singleton_win.cc
index 4d20415..fc55aac 100644
--- a/chrome/browser/process_singleton_win.cc
+++ b/chrome/browser/process_singleton_win.cc
@@ -57,6 +57,66 @@
return singleton->WndProc(hwnd, message, wparam, lparam);
}
+bool ParseCommandLine(const COPYDATASTRUCT* cds,
+ CommandLine* parsed_command_line,
+ FilePath* current_directory) {
+ // We should have enough room for the shortest command (min_message_size)
+ // and also be a multiple of wchar_t bytes. The shortest command
+ // possible is L"START\0\0" (empty current directory and command line).
+ static const int min_message_size = 7;
+ if (cds->cbData < min_message_size * sizeof(wchar_t) ||
+ cds->cbData % sizeof(wchar_t) != 0) {
+ LOG(WARNING) << "Invalid WM_COPYDATA, length = " << cds->cbData;
+ return false;
+ }
+
+ // We split the string into 4 parts on NULLs.
+ DCHECK(cds->lpData);
+ const std::wstring msg(static_cast<wchar_t*>(cds->lpData),
+ cds->cbData / sizeof(wchar_t));
+ const std::wstring::size_type first_null = msg.find_first_of(L'\0');
+ if (first_null == 0 || first_null == std::wstring::npos) {
+ // no NULL byte, don't know what to do
+ LOG(WARNING) << "Invalid WM_COPYDATA, length = " << msg.length() <<
+ ", first null = " << first_null;
+ return false;
+ }
+
+ // Decode the command, which is everything until the first NULL.
+ if (msg.substr(0, first_null) == L"START") {
+ // Another instance is starting parse the command line & do what it would
+ // have done.
+ VLOG(1) << "Handling STARTUP request from another process";
+ const std::wstring::size_type second_null =
+ msg.find_first_of(L'\0', first_null + 1);
+ if (second_null == std::wstring::npos ||
+ first_null == msg.length() - 1 || second_null == msg.length()) {
+ LOG(WARNING) << "Invalid format for start command, we need a string in 4 "
+ "parts separated by NULLs";
+ return false;
+ }
+
+ // Get current directory.
+ *current_directory = FilePath(msg.substr(first_null + 1,
+ second_null - first_null));
+
+ const std::wstring::size_type third_null =
+ msg.find_first_of(L'\0', second_null + 1);
+ if (third_null == std::wstring::npos ||
+ third_null == msg.length()) {
+ LOG(WARNING) << "Invalid format for start command, we need a string in 4 "
+ "parts separated by NULLs";
+ }
+
+ // Get command line.
+ const std::wstring cmd_line =
+ msg.substr(second_null + 1, third_null - second_null);
+ *parsed_command_line = CommandLine::FromString(cmd_line);
+ return true;
+ }
+ return false;
+}
+
} // namespace
// Microsoft's Softricity virtualization breaks the sandbox processes.
@@ -268,8 +328,17 @@
NOTIMPLEMENTED();
#else
// Attempt to place ourselves in the foreground / flash the task bar.
- if (IsWindow(foreground_window_))
+ if (foreground_window_ != NULL && IsWindow(foreground_window_)) {
SetForegroundWindow(foreground_window_);
+ } else {
+ // Read the command line and store it. It will be replayed when the
+ // ProcessSingleton becomes unlocked.
+ CommandLine parsed_command_line(CommandLine::NO_PROGRAM);
+ FilePath current_directory;
+ if (ParseCommandLine(cds, &parsed_command_line, ¤t_directory))
+ saved_startup_messages_.push_back(
+ std::make_pair(parsed_command_line.argv(), current_directory));
+ }
#endif
return TRUE;
}
@@ -280,88 +349,11 @@
return FALSE;
}
- // We should have enough room for the shortest command (min_message_size)
- // and also be a multiple of wchar_t bytes. The shortest command
- // possible is L"START\0\0" (empty current directory and command line).
- static const int min_message_size = 7;
- if (cds->cbData < min_message_size * sizeof(wchar_t) ||
- cds->cbData % sizeof(wchar_t) != 0) {
- LOG(WARNING) << "Invalid WM_COPYDATA, length = " << cds->cbData;
+ CommandLine parsed_command_line(CommandLine::NO_PROGRAM);
+ FilePath current_directory;
+ if (!ParseCommandLine(cds, &parsed_command_line, ¤t_directory))
return TRUE;
- }
-
- // We split the string into 4 parts on NULLs.
- DCHECK(cds->lpData);
- const std::wstring msg(static_cast<wchar_t*>(cds->lpData),
- cds->cbData / sizeof(wchar_t));
- const std::wstring::size_type first_null = msg.find_first_of(L'\0');
- if (first_null == 0 || first_null == std::wstring::npos) {
- // no NULL byte, don't know what to do
- LOG(WARNING) << "Invalid WM_COPYDATA, length = " << msg.length() <<
- ", first null = " << first_null;
- return TRUE;
- }
-
- // Decode the command, which is everything until the first NULL.
- if (msg.substr(0, first_null) == L"START") {
- // Another instance is starting parse the command line & do what it would
- // have done.
- VLOG(1) << "Handling STARTUP request from another process";
- const std::wstring::size_type second_null =
- msg.find_first_of(L'\0', first_null + 1);
- if (second_null == std::wstring::npos ||
- first_null == msg.length() - 1 || second_null == msg.length()) {
- LOG(WARNING) << "Invalid format for start command, we need a string in 4 "
- "parts separated by NULLs";
- return TRUE;
- }
-
- // Get current directory.
- const FilePath cur_dir(msg.substr(first_null + 1,
- second_null - first_null));
-
- const std::wstring::size_type third_null =
- msg.find_first_of(L'\0', second_null + 1);
- if (third_null == std::wstring::npos ||
- third_null == msg.length()) {
- LOG(WARNING) << "Invalid format for start command, we need a string in 4 "
- "parts separated by NULLs";
- }
-
- // Get command line.
- const std::wstring cmd_line =
- msg.substr(second_null + 1, third_null - second_null);
-
- CommandLine parsed_command_line = CommandLine::FromString(cmd_line);
- PrefService* prefs = g_browser_process->local_state();
- DCHECK(prefs);
-
- // Handle the --uninstall-extension startup action. This needs to done here
- // in the process that is running with the target profile, otherwise the
- // uninstall will fail to unload and remove all components.
- if (parsed_command_line.HasSwitch(switches::kUninstallExtension)) {
- // The uninstall extension switch can't be combined with the profile
- // directory switch.
- DCHECK(!parsed_command_line.HasSwitch(switches::kProfileDirectory));
-
- Profile* profile = ProfileManager::GetLastUsedProfile();
- if (!profile) {
- // We should only be able to get here if the profile already exists and
- // has been created.
- NOTREACHED();
- return TRUE;
- }
-
- ExtensionsStartupUtil ext_startup_util;
- ext_startup_util.UninstallExtension(parsed_command_line, profile);
- return TRUE;
- }
-
- // Run the browser startup sequence again, with the command line of the
- // signalling process.
- BrowserInit::ProcessCommandLineAlreadyRunning(parsed_command_line, cur_dir);
- return TRUE;
- }
+ ProcessCommandLine(parsed_command_line, current_directory);
return TRUE;
}
@@ -377,3 +369,35 @@
return ::DefWindowProc(hwnd, message, wparam, lparam);
}
+
+void ProcessSingleton::ProcessCommandLine(const CommandLine& command_line,
+ const FilePath& current_directory) {
+ PrefService* prefs = g_browser_process->local_state();
+ DCHECK(prefs);
+
+ // Handle the --uninstall-extension startup action. This needs to done here
+ // in the process that is running with the target profile, otherwise the
+ // uninstall will fail to unload and remove all components.
+ if (command_line.HasSwitch(switches::kUninstallExtension)) {
+ // The uninstall extension switch can't be combined with the profile
+ // directory switch.
+ DCHECK(!command_line.HasSwitch(switches::kProfileDirectory));
+
+ Profile* profile = ProfileManager::GetLastUsedProfile();
+ if (!profile) {
+ // We should only be able to get here if the profile already exists and
+ // has been created.
+ NOTREACHED();
+ return;
+ }
+
+ ExtensionsStartupUtil ext_startup_util;
+ ext_startup_util.UninstallExtension(command_line, profile);
+ return;
+ }
+
+ // Run the browser startup sequence again, with the command line of the
+ // signalling process.
+ BrowserInit::ProcessCommandLineAlreadyRunning(command_line,
+ current_directory);
+}