diff options
author | robertshield@google.com <robertshield@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-03 15:57:53 +0000 |
---|---|---|
committer | robertshield@google.com <robertshield@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-03 15:57:53 +0000 |
commit | 175a7a296b06339ee76d59fd8a98507b59aa2187 (patch) | |
tree | 66bc8cd9dd376252e266b6e7621f6a439f04128a /chrome/browser | |
parent | 537a1e191f7666d12c486a4054abd661b6c1d3a1 (diff) | |
download | chromium_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.cc | 6 | ||||
-rw-r--r-- | chrome/browser/first_run.cc | 30 | ||||
-rw-r--r-- | chrome/browser/first_run.h | 5 | ||||
-rw-r--r-- | chrome/browser/process_singleton.h | 12 | ||||
-rw-r--r-- | chrome/browser/process_singleton_win.cc | 20 |
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), |