// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/views/first_run_view.h" #include "app/l10n_util.h" #include "app/resource_bundle.h" #include "base/win_util.h" #include "chrome/browser/importer/importer.h" #include "chrome/browser/first_run.h" #include "chrome/browser/metrics/user_metrics.h" #include "chrome/browser/profile.h" #include "chrome/browser/search_engines/template_url.h" #include "chrome/browser/search_engines/template_url_model.h" #include "chrome/browser/views/first_run_customize_view.h" #include "chrome/browser/views/first_run_search_engine_view.h" #include "chrome/installer/util/browser_distribution.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" #include "grit/locale_settings.h" #include "grit/theme_resources.h" #include "views/controls/button/checkbox.h" #include "views/controls/image_view.h" #include "views/controls/label.h" #include "views/controls/throbber.h" #include "views/controls/separator.h" #include "views/standard_layout.h" #include "views/window/window.h" namespace { // Adds a bullet glyph to a string. std::wstring AddBullet(const std::wstring& text) { std::wstring btext(L" " + text); return btext.insert(0, 1, L'\u2022'); } } // namespace FirstRunView::FirstRunView(Profile* profile, bool homepage_defined, int import_items, int dont_import_items, bool search_engine_experiment) : FirstRunViewBase(profile, homepage_defined, import_items, dont_import_items, search_engine_experiment), welcome_label_(NULL), actions_label_(NULL), actions_import_(NULL), actions_shorcuts_(NULL), customize_link_(NULL), customize_selected_(false), accepted_(false) { importer_host_ = new ImporterHost(); SetupControls(); } FirstRunView::~FirstRunView() { } void FirstRunView::SetupControls() { using views::Label; using views::Link; if (default_browser_) default_browser_->SetChecked(true); welcome_label_ = new Label(l10n_util::GetString(IDS_FIRSTRUN_DLG_TEXT)); welcome_label_->SetColor(SK_ColorBLACK); welcome_label_->SetMultiLine(true); welcome_label_->SetHorizontalAlignment(Label::ALIGN_LEFT); welcome_label_->SizeToFit(0); AddChildView(welcome_label_); if (!search_engine_experiment_) { actions_label_ = new Label(l10n_util::GetString(IDS_FIRSTRUN_DLG_DETAIL)); } else { if (importer_host_->GetAvailableProfileCount() > 0) { actions_label_ = new Label(l10n_util::GetStringF( IDS_FIRSTRUN_DLG_ACTION1_ALT, l10n_util::GetString(IDS_PRODUCT_NAME), importer_host_->GetSourceProfileNameAt(0))); actions_label_->SetMultiLine(true); actions_label_->SetHorizontalAlignment(Label::ALIGN_LEFT); actions_label_->SizeToFit(0); } else { NOTREACHED(); } } actions_label_->SetHorizontalAlignment(Label::ALIGN_LEFT); AddChildView(actions_label_); if (!search_engine_experiment_) { // The first action label will tell what we are going to import from which // browser, which we obtain from the ImporterHost. We need that the first // browser profile be the default browser. std::wstring label1; if (importer_host_->GetAvailableProfileCount() > 0) { label1 = l10n_util::GetStringF(IDS_FIRSTRUN_DLG_ACTION1, importer_host_->GetSourceProfileNameAt(0)); } else { NOTREACHED(); } actions_import_ = new Label(AddBullet(label1)); actions_import_->SetMultiLine(true); actions_import_->SetHorizontalAlignment(Label::ALIGN_LEFT); AddChildView(actions_import_); std::wstring label2 = l10n_util::GetString(IDS_FIRSTRUN_DLG_ACTION2); actions_shorcuts_ = new Label(AddBullet(label2)); actions_shorcuts_->SetHorizontalAlignment(Label::ALIGN_LEFT); actions_shorcuts_->SetMultiLine(true); AddChildView(actions_shorcuts_); } customize_link_ = new Link(l10n_util::GetString(IDS_FIRSTRUN_DLG_OVERRIDE)); customize_link_->SetController(this); AddChildView(customize_link_); } gfx::Size FirstRunView::GetPreferredSize() { return gfx::Size(views::Window::GetLocalizedContentsSize( IDS_FIRSTRUN_DIALOG_WIDTH_CHARS, IDS_FIRSTRUN_DIALOG_HEIGHT_LINES)); } void FirstRunView::Layout() { FirstRunViewBase::Layout(); const int kVertSpacing = 8; ResourceBundle& rb = ResourceBundle::GetSharedInstance(); gfx::Size pref_size = welcome_label_->GetPreferredSize(); // Wrap the label text before we overlap the product icon. int label_width = background_image()->width() - rb.GetBitmapNamed(IDR_WIZARD_ICON)->width() - kPanelHorizMargin; welcome_label_->SetBounds(kPanelHorizMargin, kPanelVertMargin, label_width, pref_size.height()); AdjustDialogWidth(welcome_label_); int next_v_space = background_image()->y() + background_image()->height() + kPanelVertMargin; label_width = width() - (2 * kPanelHorizMargin); pref_size = actions_label_->GetPreferredSize(); actions_label_->SetBounds(kPanelHorizMargin, next_v_space, label_width, pref_size.height()); AdjustDialogWidth(actions_label_); next_v_space = actions_label_->y() + actions_label_->height() + kVertSpacing; if (!search_engine_experiment_) { int label_height = actions_import_->GetHeightForWidth(label_width); actions_import_->SetBounds(kPanelHorizMargin, next_v_space, label_width, label_height); next_v_space = actions_import_->y() + actions_import_->height() + kVertSpacing; AdjustDialogWidth(actions_import_); label_height = actions_shorcuts_->GetHeightForWidth(label_width); actions_shorcuts_->SetBounds(kPanelHorizMargin, next_v_space, label_width, label_height); AdjustDialogWidth(actions_shorcuts_); next_v_space = actions_shorcuts_->y() + actions_shorcuts_->height() + kUnrelatedControlVerticalSpacing; } pref_size = customize_link_->GetPreferredSize(); customize_link_->SetBounds(kPanelHorizMargin, next_v_space, pref_size.width(), pref_size.height()); } void FirstRunView::OpenCustomizeDialog() { // The customize dialog now owns the importer host object. views::Window::CreateChromeWindow( window()->GetNativeWindow(), gfx::Rect(), new FirstRunCustomizeView(profile_, importer_host_, this, default_browser_ && default_browser_->checked(), homepage_defined_, import_items_, dont_import_items_, search_engine_experiment_))->Show(); } void FirstRunView::OpenSearchEngineDialog() { views::Window::CreateChromeWindow( window()->GetNativeWindow(), gfx::Rect(), new FirstRunSearchEngineView(this, profile_))->Show(); } void FirstRunView::LinkActivated(views::Link* source, int event_flags) { OpenCustomizeDialog(); } std::wstring FirstRunView::GetWindowTitle() const { return l10n_util::GetString(IDS_FIRSTRUN_DLG_TITLE); } views::View* FirstRunView::GetContentsView() { return this; } bool FirstRunView::Accept() { if (!IsDialogButtonEnabled(MessageBoxFlags::DIALOGBUTTON_OK)) return false; DisableButtons(); customize_link_->SetEnabled(false); CreateDesktopShortcut(); // Windows 7 has deprecated the quick launch bar. if (win_util::GetWinVersion() < win_util::WINVERSION_WIN7) CreateQuickLaunchShortcut(); // Index 0 is the default browser. FirstRun::ImportSettings(profile_, importer_host_->GetSourceProfileInfoAt(0).browser_type, GetImportItems(), window()->GetNativeWindow()); UserMetrics::RecordAction(UserMetricsAction("FirstRunDef_Accept"), profile_); if (default_browser_ && default_browser_->checked()) SetDefaultBrowser(); // Launch the search engine dialog. if (search_engine_experiment_) { OpenSearchEngineDialog(); // Leave without shutting down; we'll observe the search engine dialog and // shut down after it closes. return false; } accepted_ = true; FirstRunComplete(); MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); return true; } bool FirstRunView::Cancel() { UserMetrics::RecordAction(UserMetricsAction("FirstRunDef_Cancel"), profile_); MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); return true; } // Notification from the customize dialog that the user accepted. Since all // the work is done there we have nothing else to do. void FirstRunView::CustomizeAccepted() { if (search_engine_experiment_) { OpenSearchEngineDialog(); // We'll shut down after search engine has been chosen. return; } accepted_ = true; FirstRunComplete(); window()->Close(); MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); } // Notification from the customize dialog that the user cancelled. void FirstRunView::CustomizeCanceled() { UserMetrics::RecordAction(UserMetricsAction("FirstRunCustom_Cancel"), profile_); } void FirstRunView::SearchEngineChosen(const TemplateURL* default_search) { // default_search may be NULL if the user closed the search view without // making a choice, or if a choice was made through the KeywordEditor. if (default_search) profile_->GetTemplateURLModel()->SetDefaultSearchProvider(default_search); accepted_ = true; FirstRunComplete(); window()->Close(); MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); }