diff options
author | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-25 23:41:45 +0000 |
---|---|---|
committer | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-25 23:41:45 +0000 |
commit | 8c47d69ca531d30e0ab82377420e5525424b86ce (patch) | |
tree | 6a6427b8605c353420342fa20e6b03a788c2f70b /chrome/browser | |
parent | c0e11ab531aae20470289475d69ac507d9715262 (diff) | |
download | chromium_src-8c47d69ca531d30e0ab82377420e5525424b86ce.zip chromium_src-8c47d69ca531d30e0ab82377420e5525424b86ce.tar.gz chromium_src-8c47d69ca531d30e0ab82377420e5525424b86ce.tar.bz2 |
Refactor new first run control flow.
Factor out the common code so that Mac and Linux may share the new flow with Windows (e.g., import is done before the first run dialog appears).
Windows *should* be unaffected by this change. Linux has some non-user-visible changes. The user visible changes (showing the default search engine in the ballot, for example) are TODO.
BUG=49705,47651
TEST=launching chromium with --first-run works as expected, i.e. it imports stuff from your default browser (such as history); if that browser is firefox and firefox is open, the failure is silent.
Review URL: http://codereview.chromium.org/3171029
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@57421 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/browser_main.cc | 2 | ||||
-rw-r--r-- | chrome/browser/first_run/first_run.cc | 79 | ||||
-rw-r--r-- | chrome/browser/first_run/first_run.h | 25 | ||||
-rw-r--r-- | chrome/browser/first_run/first_run_gtk.cc | 80 | ||||
-rw-r--r-- | chrome/browser/first_run/first_run_win.cc | 121 | ||||
-rw-r--r-- | chrome/browser/gtk/first_run_dialog.cc | 51 | ||||
-rw-r--r-- | chrome/browser/gtk/first_run_dialog.h | 19 | ||||
-rw-r--r-- | chrome/browser/importer/importer.cc | 3 |
8 files changed, 229 insertions, 151 deletions
diff --git a/chrome/browser/browser_main.cc b/chrome/browser/browser_main.cc index fcafef0..7bda668 100644 --- a/chrome/browser/browser_main.cc +++ b/chrome/browser/browser_main.cc @@ -1236,7 +1236,7 @@ int BrowserMain(const MainFunctionParams& parameters) { // touches reads preferences. if (is_first_run) { if (!first_run_ui_bypass) { -#if defined(OS_WIN) +#if defined(OS_WIN) || defined(OS_LINUX) FirstRun::AutoImport(profile, master_prefs.homepage_defined, master_prefs.do_import_items, diff --git a/chrome/browser/first_run/first_run.cc b/chrome/browser/first_run/first_run.cc index ba2011e..d86baa2 100644 --- a/chrome/browser/first_run/first_run.cc +++ b/chrome/browser/first_run/first_run.cc @@ -18,7 +18,9 @@ #include "base/path_service.h" #include "base/utf_string_conversions.h" #include "chrome/browser/importer/importer.h" +#include "chrome/browser/metrics/user_metrics.h" #include "chrome/browser/pref_service.h" +#include "chrome/browser/process_singleton.h" #include "chrome/browser/profile_manager.h" #include "chrome/browser/shell_integration.h" #include "chrome/common/chrome_paths.h" @@ -454,3 +456,80 @@ void FirstRunImportObserver::Finish() { MessageLoop::current()->Quit(); } +// TODO(avi): port the relevant pieces and enable this. +#if !defined(OS_MACOSX) +// static +void FirstRun::AutoImport( + Profile* profile, + bool homepage_defined, + int import_items, + int dont_import_items, + bool search_engine_experiment, + bool randomize_search_engine_experiment, + ProcessSingleton* process_singleton) { + // We need to avoid dispatching new tabs when we are importing because + // that will lead to data corruption or a crash. Because there is no UI for + // the import process, we pass NULL as the window to bring to the foreground + // when a CopyData message comes in; this causes the message to be silently + // discarded, which is the correct behavior during the import process. + process_singleton->Lock(NULL); + + PlatformSetup(); + + scoped_refptr<ImporterHost> importer_host; + importer_host = new ImporterHost(); + // Do import if there is an available profile for us to import. + if (importer_host->GetAvailableProfileCount() > 0) { + // Don't show the warning dialog if import fails. + importer_host->set_headless(); + int items = 0; + + // History is always imported unless turned off in master_preferences. + if (!(dont_import_items & importer::HISTORY)) + items = items | importer::HISTORY; + // Home page is imported in organic builds only unless turned off or + // defined in master_preferences. + if (IsOrganic()) { + if (!(dont_import_items & importer::HOME_PAGE) && !homepage_defined) + items = items | importer::HOME_PAGE; + } else { + if (import_items & importer::HOME_PAGE) + items = items | importer::HOME_PAGE; + } + // Search engines are imported in organic builds only unless overriden + // in master_preferences. + if (IsOrganic()) { + if (!(dont_import_items & importer::SEARCH_ENGINES)) + items = items | importer::SEARCH_ENGINES; + } else { + if (import_items & importer::SEARCH_ENGINES) + items = items | importer::SEARCH_ENGINES; + } + + // Bookmarks are never imported, unless turned on in master_preferences. + if (import_items & importer::FAVORITES) + items = items | importer::FAVORITES; + + ImportSettings(profile, importer_host, items); + } + + UserMetrics::RecordAction(UserMetricsAction("FirstRunDef_Accept")); + + // Launch the search engine dialog only if build is organic. + if (IsOrganic()) { + // The home page string may be set in the preferences, but the user should + // initially use Chrome with the NTP as home page in organic builds. + profile->GetPrefs()->SetBoolean(prefs::kHomePageIsNewTabPage, true); + + ShowFirstRunDialog(profile, randomize_search_engine_experiment); + } + + FirstRun::SetShowFirstRunBubblePref(true); + // Set the first run bubble to minimal. + FirstRun::SetMinimalFirstRunBubblePref(); + FirstRun::SetShowWelcomePagePref(); + + process_singleton->Unlock(); + FirstRun::CreateSentinel(); +} +#endif // !defined(OS_MACOSX) diff --git a/chrome/browser/first_run/first_run.h b/chrome/browser/first_run/first_run.h index 05fd070..d4dcf5e 100644 --- a/chrome/browser/first_run/first_run.h +++ b/chrome/browser/first_run/first_run.h @@ -67,7 +67,8 @@ class FirstRun { // Automatically import history and home page (and search engine, if // nonorganic). - static void AutoImport(Profile* profile, + static void AutoImport( + Profile* profile, bool homepage_defined, int import_items, int dont_import_items, @@ -75,6 +76,17 @@ class FirstRun { bool randomize_search_engine_experiment, ProcessSingleton* process_singleton); + // Does platform specific setup. Called at the start of AutoImport. + static void PlatformSetup(); + + // Returns whether the current install is "organic". + static bool IsOrganic(); + + // Shows the search engine choice dialog, and any other platform dialogs. + // Only called in "organic" installs. + static void ShowFirstRunDialog(Profile* profile, + bool randomize_search_engine_experiment); + // The master preferences is a JSON file with the same entries as the // 'Default\Preferences' file. This function locates this file from a standard // location and processes it so it becomes the default preferences in the @@ -98,11 +110,12 @@ class FirstRun { // Removes the sentinel file created in ConfigDone(). Returns false if the // sentinel file could not be removed. static bool RemoveSentinel(); - // Imports settings in a separate process. It spawns a second dedicated - // browser process that just does the import with the import progress UI. - static bool ImportSettings(Profile* profile, int browser_type, - int items_to_import, - gfx::NativeView parent_window); + // Imports settings. This may be done in a separate process depending on the + // platform, but it will always block until done. The return value indicates + // success. + static bool ImportSettings(Profile* profile, + scoped_refptr<ImporterHost> importer_host, + int items_to_import); // Sets the kShouldShowFirstRunBubble local state pref so that the browser // shows the bubble once the main message loop gets going (or refrains from diff --git a/chrome/browser/first_run/first_run_gtk.cc b/chrome/browser/first_run/first_run_gtk.cc index b4044ce7..d920f4e8 100644 --- a/chrome/browser/first_run/first_run_gtk.cc +++ b/chrome/browser/first_run/first_run_gtk.cc @@ -22,6 +22,44 @@ #include "chrome/installer/util/google_update_settings.h" #include "googleurl/src/gurl.h" +namespace { + +// This class acts as an observer for the ImporterHost::Observer::ImportEnded +// callback. When the import process is started, certain errors may cause +// ImportEnded() to be called synchronously, but the typical case is that +// ImportEnded() is called asynchronously. Thus we have to handle both cases. +class ImportEndedObserver : public ImporterHost::Observer { + public: + ImportEndedObserver() + : ended_(false), + quit_message_loop_(false) { + } + virtual ~ImportEndedObserver() {} + + virtual void ImportItemStarted(importer::ImportItem item) {} + virtual void ImportItemEnded(importer::ImportItem item) {} + virtual void ImportStarted() {} + virtual void ImportEnded() { + ended_ = true; + if (quit_message_loop_) + MessageLoop::current()->Quit(); + } + + void set_quit_message_loop() { + quit_message_loop_ = true; + } + + bool ended() { + return ended_; + } + + private: + bool ended_; + bool quit_message_loop_; +}; + +} // namespace + // TODO(estade): pay attention to the args between |profile| and // |process_singleton|. bool OpenFirstRunDialog(Profile* profile, @@ -36,6 +74,7 @@ bool OpenFirstRunDialog(Profile* profile, // TODO(port): This is just a piece of the silent import functionality from // ImportSettings for Windows. It would be nice to get the rest of it ported. +// TODO(estade): When do we use this? bool FirstRun::ImportBookmarks(const FilePath& import_bookmarks_path) { const CommandLine& cmdline = *CommandLine::ForCurrentProcess(); CommandLine import_cmd(cmdline.GetProgram()); @@ -94,3 +133,44 @@ double Upgrade::GetLastModifiedTimeOfExe() { return exe_file_info.last_modified.ToDoubleT(); } #endif // defined(OS_LINUX) && !defined(OS_CHROMEOS) + +// At least for now, we do profile import in-process on Linux. +// static +bool FirstRun::ImportSettings(Profile* profile, + scoped_refptr<ImporterHost> importer_host, + int items_to_import) { + // Import data. + const ProfileInfo& source_profile = importer_host->GetSourceProfileInfoAt(0); + scoped_ptr<ImportEndedObserver> observer(new ImportEndedObserver); + importer_host->SetObserver(observer.get()); + importer_host->StartImportSettings(source_profile, + profile, + items_to_import, + new ProfileWriter(profile), + true); + // If the import process has not errored out, block on it. + if (!observer->ended()) { + observer->set_quit_message_loop(); + MessageLoop::current()->Run(); + } + // Unfortunately there's no success/fail signal in ImporterHost. + return true; +} + +// static +void FirstRun::ShowFirstRunDialog(Profile* profile, + bool randomize_search_engine_experiment) { + FirstRunDialog::Show(profile, randomize_search_engine_experiment); +} + +// static +bool FirstRun::IsOrganic() { + // We treat all installs as organic. + return true; +} + +// static +void FirstRun::PlatformSetup() { + // Things that Windows does here (creating a desktop icon, for example) are + // handled at install time on Linux. +} diff --git a/chrome/browser/first_run/first_run_win.cc b/chrome/browser/first_run/first_run_win.cc index fd21d32..4538519 100644 --- a/chrome/browser/first_run/first_run_win.cc +++ b/chrome/browser/first_run/first_run_win.cc @@ -446,94 +446,38 @@ bool DecodeImportParams(const std::string& encoded, int* browser_type, } // namespace -void FirstRun::AutoImport(Profile* profile, - bool homepage_defined, - int import_items, - int dont_import_items, - bool search_engine_experiment, - bool randomize_search_engine_experiment, - ProcessSingleton* process_singleton) { +// static +void FirstRun::PlatformSetup() { FirstRun::CreateChromeDesktopShortcut(); // Windows 7 has deprecated the quick launch bar. if (win_util::GetWinVersion() < win_util::WINVERSION_WIN7) CreateChromeQuickLaunchShortcut(); +} - scoped_refptr<ImporterHost> importer_host; - importer_host = new ImporterHost(); - int items = 0; - - // History is always imported unless turned off in master_preferences. - if (!(dont_import_items & importer::HISTORY)) - items = items | importer::HISTORY; - // Home page is imported in organic builds only unless turned off or - // defined in master_preferences. +// static +bool FirstRun::IsOrganic() { std::wstring brand; GoogleUpdateSettings::GetBrand(&brand); - if (GoogleUpdateSettings::IsOrganic(brand)) { - if (!(dont_import_items & importer::HOME_PAGE) && !homepage_defined) { - items = items | importer::HOME_PAGE; - } - } else { - if (import_items & importer::HOME_PAGE) { - items = items | importer::HOME_PAGE; - } - } - // Search engines are imported in organic builds only, unless turned on - // in master_preferences. - if (GoogleUpdateSettings::IsOrganic(brand)) { - if (!(dont_import_items & importer::SEARCH_ENGINES)) { - items = items | importer::SEARCH_ENGINES; - } - } else { - if (import_items & importer::SEARCH_ENGINES) { - items = items | importer::SEARCH_ENGINES; - } - } - - // Bookmarks are never imported, unless turned on in master_preferences. - if (import_items & importer::FAVORITES) - items = items | importer::FAVORITES; - - // We need to avoid dispatching new tabs when we are importing because - // that will lead to data corruption or a crash. Because there is no UI for - // the import process, we pass NULL as the window to bring to the foreground - // when a CopyData message comes in; this causes the message to be silently - // discarded, which is the correct behavior during the import process. - process_singleton->Lock(NULL); - - // Index 0 is the default browser. - FirstRun::ImportSettings(profile, - importer_host->GetSourceProfileInfoAt(0).browser_type, items, NULL); - UserMetrics::RecordAction(UserMetricsAction("FirstRunDef_Accept")); - - // Launch the search engine dialog only if build is organic. - if (GoogleUpdateSettings::IsOrganic(brand)) { - // The home page string may be set in the preferences, but the user should - // initially use Chrome with the NTP as home page in organic builds. - profile->GetPrefs()->SetBoolean(prefs::kHomePageIsNewTabPage, true); - - views::Window* search_engine_dialog = views::Window::CreateChromeWindow( - NULL, - gfx::Rect(), - new FirstRunSearchEngineView(profile, - randomize_search_engine_experiment)); - DCHECK(search_engine_dialog); - - search_engine_dialog->Show(); - views::AcceleratorHandler accelerator_handler; - MessageLoopForUI::current()->Run(&accelerator_handler); - search_engine_dialog->Close(); - } - - FirstRun::SetShowFirstRunBubblePref(true); - // Set the first run bubble to minimal. - FirstRun::SetMinimalFirstRunBubblePref(); - FirstRun::SetShowWelcomePagePref(); + return GoogleUpdateSettings::IsOrganic(brand); +} - process_singleton->Unlock(); - FirstRun::CreateSentinel(); +// static +void FirstRun::ShowFirstRunDialog(Profile* profile, + bool randomize_search_engine_experiment) { + views::Window* search_engine_dialog = views::Window::CreateChromeWindow( + NULL, + gfx::Rect(), + new FirstRunSearchEngineView(profile, + randomize_search_engine_experiment)); + DCHECK(search_engine_dialog); + + search_engine_dialog->Show(); + views::AcceleratorHandler accelerator_handler; + MessageLoopForUI::current()->Run(&accelerator_handler); + search_engine_dialog->Close(); } +// static bool FirstRun::ImportSettings(Profile* profile, int browser_type, int items_to_import, const FilePath& import_bookmarks_path, @@ -558,7 +502,7 @@ bool FirstRun::ImportSettings(Profile* profile, int browser_type, if (items_to_import) { import_cmd.CommandLine::AppendSwitchASCII(switches::kImport, EncodeImportParams(browser_type, items_to_import, - skip_first_run_ui ? 1 : 0, parent_window)); + skip_first_run_ui ? 1 : 0, NULL)); } if (!import_bookmarks_path.empty()) { @@ -571,11 +515,6 @@ bool FirstRun::ImportSettings(Profile* profile, int browser_type, if (!base::LaunchApp(import_cmd, false, false, &import_process)) return false; - // Activate the importer monitor. It awakes periodically in another thread - // and checks that the importer UI is still pumping messages. - if (parent_window) - HungImporterMonitor hang_monitor(parent_window, import_process); - // We block inside the import_runner ctor, pumping messages until the // importer process ends. This can happen either by completing the import // or by hang_monitor killing it. @@ -589,11 +528,15 @@ bool FirstRun::ImportSettings(Profile* profile, int browser_type, return (import_runner.exit_code() == ResultCodes::NORMAL_EXIT); } -bool FirstRun::ImportSettings(Profile* profile, int browser_type, - int items_to_import, - HWND parent_window) { - return ImportSettings(profile, browser_type, items_to_import, - FilePath(), false, parent_window); +// static +bool FirstRun::ImportSettings(Profile* profile, + scoped_refptr<ImporterHost> importer_host, + int items_to_import) { + return ImportSettings( + profile, + importer_host->GetSourceProfileInfoAt(0).browser_type, + items_to_import, + FilePath(), false, NULL); } int FirstRun::ImportFromBrowser(Profile* profile, diff --git a/chrome/browser/gtk/first_run_dialog.cc b/chrome/browser/gtk/first_run_dialog.cc index 882786d..c756fb6 100644 --- a/chrome/browser/gtk/first_run_dialog.cc +++ b/chrome/browser/gtk/first_run_dialog.cc @@ -11,7 +11,6 @@ #include "chrome/browser/gtk/gtk_chrome_link_button.h" #include "chrome/browser/gtk/gtk_floating_container.h" #include "chrome/browser/gtk/gtk_util.h" -#include "chrome/browser/importer/importer_data_types.h" #include "chrome/browser/platform_util.h" #include "chrome/browser/process_singleton.h" #include "chrome/browser/profile.h" @@ -66,14 +65,10 @@ void SetWelcomePosition(GtkFloatingContainer* container, // static bool FirstRunDialog::Show(Profile* profile, - ProcessSingleton* process_singleton) { + bool randomize_search_engine_order) { int response = -1; // Object deletes itself. - new FirstRunDialog(profile, response); - - // Prevent further launches of Chrome until First Run UI is done. - // We don't actually use the parameter to Lock() on Posix. - process_singleton->Lock(NULL); + new FirstRunDialog(profile, randomize_search_engine_order, response); // TODO(port): it should be sufficient to just run the dialog: // int response = gtk_dialog_run(GTK_DIALOG(dialog)); @@ -82,25 +77,27 @@ bool FirstRunDialog::Show(Profile* profile, // Instead, run a loop and extract the response manually. MessageLoop::current()->Run(); - process_singleton->Unlock(); return (response == GTK_RESPONSE_ACCEPT); } -FirstRunDialog::FirstRunDialog(Profile* profile, int& response) +FirstRunDialog::FirstRunDialog(Profile* profile, + bool randomize_search_engine_order, + int& response) : search_engine_window_(NULL), dialog_(NULL), report_crashes_(NULL), make_default_(NULL), profile_(profile), chosen_search_engine_(NULL), - response_(response), - importer_host_(new ImporterHost()) { + response_(response) { search_engines_model_ = profile_->GetTemplateURLModel(); - DCHECK(!search_engines_model_->loaded()); - search_engines_model_->AddObserver(this); - search_engines_model_->Load(); - ShowSearchEngineWindow(); + + search_engines_model_->AddObserver(this); + if (search_engines_model_->loaded()) + OnTemplateURLModelChanged(); + else + search_engines_model_->Load(); } FirstRunDialog::~FirstRunDialog() { @@ -304,8 +301,6 @@ void FirstRunDialog::OnResponseDialog(GtkWidget* widget, int response) { gtk_widget_hide_all(dialog_); response_ = response; - bool do_import = false; - if (response == GTK_RESPONSE_ACCEPT) { // Mark that first run has ran. FirstRun::CreateSentinel(); @@ -327,30 +322,8 @@ void FirstRunDialog::OnResponseDialog(GtkWidget* widget, int response) { gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(make_default_))) { ShellIntegration::SetAsDefaultBrowser(); } - - do_import = importer_host_->GetAvailableProfileCount() > 0; - if (do_import) { - // Import data. - const ProfileInfo& source_profile = - importer_host_->GetSourceProfileInfoAt(0); - int items = importer::SEARCH_ENGINES + importer::HISTORY + - importer::HOME_PAGE + importer::PASSWORDS; - importer_host_->SetObserver(this); - // TODO(port): Should we do the actual import in a new process like - // Windows? - importer_host_->StartImportSettings(source_profile, - profile_, - items, - new ProfileWriter(profile_), - true); - } } - if (!do_import) - FirstRunDone(); -} - -void FirstRunDialog::ImportEnded() { FirstRunDone(); } diff --git a/chrome/browser/gtk/first_run_dialog.h b/chrome/browser/gtk/first_run_dialog.h index de24b46..5c3b6f4 100644 --- a/chrome/browser/gtk/first_run_dialog.h +++ b/chrome/browser/gtk/first_run_dialog.h @@ -11,25 +11,19 @@ typedef struct _GtkWidget GtkWidget; #include "app/gtk_signal.h" #include "chrome/browser/first_run/first_run.h" -#include "chrome/browser/importer/importer.h" #include "chrome/browser/search_engines/template_url_model.h" -class FirstRunDialog : public ImporterHost::Observer, - public TemplateURLModelObserver { +class FirstRunDialog : public TemplateURLModelObserver { public: // Displays the first run UI for reporting opt-in, import data etc. - static bool Show(Profile* profile, ProcessSingleton* process_singleton); - - // Overridden from ImporterHost::Observer ------------------------------------ - virtual void ImportEnded(); - virtual void ImportStarted() {} - virtual void ImportItemStarted(importer::ImportItem item) {} - virtual void ImportItemEnded(importer::ImportItem item) {} + static bool Show(Profile* profile, bool randomize_search_engine_order); virtual void OnTemplateURLModelChanged(); private: - FirstRunDialog(Profile* profile, int& response); + FirstRunDialog(Profile* profile, + bool randomize_search_engine_order, + int& response); virtual ~FirstRunDialog(); CHROMEGTK_CALLBACK_1(FirstRunDialog, void, OnResponseDialog, int); @@ -74,9 +68,6 @@ class FirstRunDialog : public ImporterHost::Observer, // User response (accept or cancel) is returned through this. int& response_; - // Utility class that does the actual import. - scoped_refptr<ImporterHost> importer_host_; - DISALLOW_COPY_AND_ASSIGN(FirstRunDialog); }; diff --git a/chrome/browser/importer/importer.cc b/chrome/browser/importer/importer.cc index 3c840f0..5280c13 100644 --- a/chrome/browser/importer/importer.cc +++ b/chrome/browser/importer/importer.cc @@ -277,8 +277,7 @@ void ImporterHost::CheckForFirefoxLock( // If fail to acquire the lock, we set the source unreadable and // show a warning dialog, unless running without UI. is_source_readable_ = false; - if (!this->headless_) - ShowWarningDialog(); + ShowWarningDialog(); } } } |