summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorrobertshield@google.com <robertshield@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-03 15:57:53 +0000
committerrobertshield@google.com <robertshield@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-03 15:57:53 +0000
commit175a7a296b06339ee76d59fd8a98507b59aa2187 (patch)
tree66bc8cd9dd376252e266b6e7621f6a439f04128a /chrome/browser
parent537a1e191f7666d12c486a4054abd661b6c1d3a1 (diff)
downloadchromium_src-175a7a296b06339ee76d59fd8a98507b59aa2187.zip
chromium_src-175a7a296b06339ee76d59fd8a98507b59aa2187.tar.gz
chromium_src-175a7a296b06339ee76d59fd8a98507b59aa2187.tar.bz2
Fix multiple instances of first run dialog appearing when Chrome is started again while a first run dialog is visible. Also cause the original first run dialog to come to foreground.
BUG=http://crbug.com/10765 Review URL: http://codereview.chromium.org/99281 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15170 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/browser_main.cc6
-rw-r--r--chrome/browser/first_run.cc30
-rw-r--r--chrome/browser/first_run.h5
-rw-r--r--chrome/browser/process_singleton.h12
-rw-r--r--chrome/browser/process_singleton_win.cc20
5 files changed, 50 insertions, 23 deletions
diff --git a/chrome/browser/browser_main.cc b/chrome/browser/browser_main.cc
index fd9ee3d..6b27a9d 100644
--- a/chrome/browser/browser_main.cc
+++ b/chrome/browser/browser_main.cc
@@ -448,11 +448,7 @@ int BrowserMain(const MainFunctionParams& parameters) {
// preferences are registered, since some of the code that the importer
// touches reads preferences.
if (is_first_run && !first_run_ui_bypass) {
- // We need to avoid dispatching new tabs when we are doing the import
- // because that will lead to data corruption or a crash. Lock() does that.
- process_singleton.Lock();
- OpenFirstRunDialog(profile);
- process_singleton.Unlock();
+ OpenFirstRunDialog(profile, &process_singleton);
}
// Sets things up so that if we crash from this point on, a dialog will
diff --git a/chrome/browser/first_run.cc b/chrome/browser/first_run.cc
index d14e0c1..8a93bd3 100644
--- a/chrome/browser/first_run.cc
+++ b/chrome/browser/first_run.cc
@@ -26,6 +26,7 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/hang_monitor/hung_window_detector.h"
#include "chrome/browser/importer/importer.h"
+#include "chrome/browser/process_singleton.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/profile_manager.h"
#include "chrome/browser/shell_integration.h"
@@ -177,8 +178,8 @@ bool FirstRun::CreateChromeDesktopShortcut() {
if (!dist)
return false;
return ShellUtil::CreateChromeDesktopShortcut(chrome_exe,
- dist->GetAppDescription(), ShellUtil::CURRENT_USER,
- false, true); // create if doesn't exist.
+ dist->GetAppDescription(), ShellUtil::CURRENT_USER,
+ false, true); // create if doesn't exist.
}
bool FirstRun::CreateChromeQuickLaunchShortcut() {
@@ -186,8 +187,8 @@ bool FirstRun::CreateChromeQuickLaunchShortcut() {
if (!PathService::Get(base::FILE_EXE, &chrome_exe))
return false;
return ShellUtil::CreateChromeQuickLaunchShortcut(chrome_exe,
- ShellUtil::CURRENT_USER, // create only for current user.
- true); // create if doesn't exist.
+ ShellUtil::CURRENT_USER, // create only for current user.
+ true); // create if doesn't exist.
}
bool FirstRun::RemoveSentinel() {
@@ -381,14 +382,29 @@ bool Upgrade::SwapNewChromeExeIfPresent() {
return false;
}
-void OpenFirstRunDialog(Profile* profile) {
- views::Window::CreateChromeWindow(NULL, gfx::Rect(),
- new FirstRunView(profile))->Show();
+void OpenFirstRunDialog(Profile* profile,
+ ProcessSingleton* process_singleton) {
+ DCHECK(profile);
+ DCHECK(process_singleton);
+
+ views::Window* first_run_ui = views::Window::CreateChromeWindow(
+ NULL, gfx::Rect(), new FirstRunView(profile));
+ DCHECK(first_run_ui);
+
+ // We need to avoid dispatching new tabs when we are doing the import
+ // because that will lead to data corruption or a crash. Lock() does that.
+ // If a CopyData message does come in while the First Run UI is visible,
+ // then we will attempt to set first_run_ui as the foreground window.
+ process_singleton->Lock(first_run_ui->GetNativeWindow());
+
+ first_run_ui->Show();
+
// We must now run a message loop (will be terminated when the First Run UI
// is closed) so that the window can receive messages and we block the
// browser window from showing up. We pass the accelerator handler here so
// that keyboard accelerators (Enter, Esc, etc) work in the dialog box.
MessageLoopForUI::current()->Run(g_browser_process->accelerator_handler());
+ process_singleton->Unlock();
}
namespace {
diff --git a/chrome/browser/first_run.h b/chrome/browser/first_run.h
index bc73622..d0d6177 100644
--- a/chrome/browser/first_run.h
+++ b/chrome/browser/first_run.h
@@ -12,6 +12,7 @@
class FilePath;
class Profile;
+class ProcessSingleton;
// This class contains the chrome first-run installation actions needed to
// fully test the custom installer. It also contains the opposite actions to
@@ -122,6 +123,8 @@ class FirstRunBrowserProcess : public BrowserProcessImpl {
// Show the First Run UI to the user, allowing them to create shortcuts for
// the app, import their bookmarks and other data from another browser into
// |profile| and perhaps some other tasks.
-void OpenFirstRunDialog(Profile* profile);
+// |process_singleton| is used to lock the handling of CopyData messages
+// while the First Run UI is visible.
+void OpenFirstRunDialog(Profile* profile, ProcessSingleton* process_singleton);
#endif // CHROME_BROWSER_FIRST_RUN_H_
diff --git a/chrome/browser/process_singleton.h b/chrome/browser/process_singleton.h
index b5f3631..0e39417 100644
--- a/chrome/browser/process_singleton.h
+++ b/chrome/browser/process_singleton.h
@@ -13,6 +13,7 @@
#include "base/basictypes.h"
#include "base/file_path.h"
+#include "base/gfx/native_widget_types.h"
// ProcessSingleton ----------------------------------------------------------
//
@@ -42,18 +43,23 @@ class ProcessSingleton {
// Set ourselves up as the singleton instance.
void Create();
- // Blocks the dispatch of CopyData messages.
- void Lock() {
+ // Blocks the dispatch of CopyData messages. foreground_window refers
+ // to the window that should be set to the foreground if a CopyData message
+ // is received while the ProcessSingleton is locked.
+ void Lock(gfx::NativeWindow foreground_window) {
locked_ = true;
+ foreground_window_ = foreground_window;
}
// Allows the dispatch of CopyData messages.
void Unlock() {
locked_ = false;
+ foreground_window_ = NULL;
}
private:
bool locked_;
+ gfx::NativeWindow foreground_window_;
#if defined(OS_WIN)
// This ugly behemoth handles startup commands sent from another process.
@@ -86,4 +92,4 @@ class ProcessSingleton {
DISALLOW_COPY_AND_ASSIGN(ProcessSingleton);
};
-#endif // #ifndef CHROME_BROWSER_PROCESS_SINGLETON_H_
+#endif // CHROME_BROWSER_PROCESS_SINGLETON_H_
diff --git a/chrome/browser/process_singleton_win.cc b/chrome/browser/process_singleton_win.cc
index c34a4d1..b3ce8f7 100644
--- a/chrome/browser/process_singleton_win.cc
+++ b/chrome/browser/process_singleton_win.cc
@@ -35,7 +35,7 @@ BOOL CALLBACK BrowserWindowEnumeration(HWND window, LPARAM param) {
// Look for a Chrome instance that uses the same profile directory.
ProcessSingleton::ProcessSingleton(const FilePath& user_data_dir)
- : window_(NULL), locked_(false) {
+ : window_(NULL), locked_(false), foreground_window_(NULL) {
// FindWindoEx and Create() should be one atomic operation in order to not
// have a race condition.
remote_window_ = FindWindowEx(HWND_MESSAGE, NULL, chrome::kMessageWindowClass,
@@ -160,17 +160,23 @@ void ProcessSingleton::Create() {
}
LRESULT ProcessSingleton::OnCopyData(HWND hwnd, const COPYDATASTRUCT* cds) {
+ // If locked, it means we are not ready to process this message because
+ // we are probably in a first run critical phase. We must do this before
+ // doing the IsShuttingDown() check since that returns true during first run
+ // (since g_browser_process hasn't been AddRefModule()d yet).
+ if (locked_) {
+ // Attempt to place ourselves in the foreground / flash the task bar.
+ if (IsWindow(foreground_window_))
+ SetForegroundWindow(foreground_window_);
+ return TRUE;
+ }
+
// Ignore the request if the browser process is already in shutdown path.
if (!g_browser_process || g_browser_process->IsShuttingDown()) {
LOG(WARNING) << "Not handling WM_COPYDATA as browser is shutting down";
return FALSE;
}
- // If locked, it means we are not ready to process this message because
- // we are probably in a first run critical phase.
- if (locked_)
- return TRUE;
-
// 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).
@@ -249,7 +255,7 @@ LRESULT ProcessSingleton::OnCopyData(HWND hwnd, const COPYDATASTRUCT* cds) {
}
LRESULT CALLBACK ProcessSingleton::WndProc(HWND hwnd, UINT message,
- WPARAM wparam, LPARAM lparam) {
+ WPARAM wparam, LPARAM lparam) {
switch (message) {
case WM_COPYDATA:
return OnCopyData(reinterpret_cast<HWND>(wparam),